Coverage Report

Created: 2023-06-08 06:40

/src/openssl111/crypto/kdf/hkdf.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved.
3
 *
4
 * Licensed under the OpenSSL license (the "License").  You may not use
5
 * this file except in compliance with the License.  You can obtain a copy
6
 * in the file LICENSE in the source distribution or at
7
 * https://www.openssl.org/source/license.html
8
 */
9
10
#include <stdlib.h>
11
#include <string.h>
12
#include <openssl/hmac.h>
13
#include <openssl/kdf.h>
14
#include <openssl/evp.h>
15
#include "internal/cryptlib.h"
16
#include "crypto/evp.h"
17
18
0
#define HKDF_MAXBUF 1024
19
20
static unsigned char *HKDF(const EVP_MD *evp_md,
21
                           const unsigned char *salt, size_t salt_len,
22
                           const unsigned char *key, size_t key_len,
23
                           const unsigned char *info, size_t info_len,
24
                           unsigned char *okm, size_t okm_len);
25
26
static unsigned char *HKDF_Extract(const EVP_MD *evp_md,
27
                                   const unsigned char *salt, size_t salt_len,
28
                                   const unsigned char *key, size_t key_len,
29
                                   unsigned char *prk, size_t *prk_len);
30
31
static unsigned char *HKDF_Expand(const EVP_MD *evp_md,
32
                                  const unsigned char *prk, size_t prk_len,
33
                                  const unsigned char *info, size_t info_len,
34
                                  unsigned char *okm, size_t okm_len);
35
36
typedef struct {
37
    int mode;
38
    const EVP_MD *md;
39
    unsigned char *salt;
40
    size_t salt_len;
41
    unsigned char *key;
42
    size_t key_len;
43
    unsigned char info[HKDF_MAXBUF];
44
    size_t info_len;
45
} HKDF_PKEY_CTX;
46
47
static int pkey_hkdf_init(EVP_PKEY_CTX *ctx)
48
0
{
49
0
    HKDF_PKEY_CTX *kctx;
50
51
0
    if ((kctx = OPENSSL_zalloc(sizeof(*kctx))) == NULL) {
52
0
        KDFerr(KDF_F_PKEY_HKDF_INIT, ERR_R_MALLOC_FAILURE);
53
0
        return 0;
54
0
    }
55
56
0
    ctx->data = kctx;
57
58
0
    return 1;
59
0
}
60
61
static void pkey_hkdf_cleanup(EVP_PKEY_CTX *ctx)
62
0
{
63
0
    HKDF_PKEY_CTX *kctx = ctx->data;
64
0
    OPENSSL_clear_free(kctx->salt, kctx->salt_len);
65
0
    OPENSSL_clear_free(kctx->key, kctx->key_len);
66
0
    OPENSSL_cleanse(kctx->info, kctx->info_len);
67
0
    OPENSSL_free(kctx);
68
0
}
69
70
static int pkey_hkdf_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
71
0
{
72
0
    HKDF_PKEY_CTX *kctx = ctx->data;
73
74
0
    switch (type) {
75
0
    case EVP_PKEY_CTRL_HKDF_MD:
76
0
        if (p2 == NULL)
77
0
            return 0;
78
79
0
        kctx->md = p2;
80
0
        return 1;
81
82
0
    case EVP_PKEY_CTRL_HKDF_MODE:
83
0
        kctx->mode = p1;
84
0
        return 1;
85
86
0
    case EVP_PKEY_CTRL_HKDF_SALT:
87
0
        if (p1 == 0 || p2 == NULL)
88
0
            return 1;
89
90
0
        if (p1 < 0)
91
0
            return 0;
92
93
0
        if (kctx->salt != NULL)
94
0
            OPENSSL_clear_free(kctx->salt, kctx->salt_len);
95
96
0
        kctx->salt = OPENSSL_memdup(p2, p1);
97
0
        if (kctx->salt == NULL)
98
0
            return 0;
99
100
0
        kctx->salt_len = p1;
101
0
        return 1;
102
103
0
    case EVP_PKEY_CTRL_HKDF_KEY:
104
0
        if (p1 < 0)
105
0
            return 0;
106
107
0
        if (kctx->key != NULL)
108
0
            OPENSSL_clear_free(kctx->key, kctx->key_len);
109
110
0
        kctx->key = OPENSSL_memdup(p2, p1);
111
0
        if (kctx->key == NULL)
112
0
            return 0;
113
114
0
        kctx->key_len  = p1;
115
0
        return 1;
116
117
0
    case EVP_PKEY_CTRL_HKDF_INFO:
118
0
        if (p1 == 0 || p2 == NULL)
119
0
            return 1;
120
121
0
        if (p1 < 0 || p1 > (int)(HKDF_MAXBUF - kctx->info_len))
122
0
            return 0;
123
124
0
        memcpy(kctx->info + kctx->info_len, p2, p1);
125
0
        kctx->info_len += p1;
126
0
        return 1;
127
128
0
    default:
129
0
        return -2;
130
131
0
    }
132
0
}
133
134
static int pkey_hkdf_ctrl_str(EVP_PKEY_CTX *ctx, const char *type,
135
                              const char *value)
136
0
{
137
0
    if (strcmp(type, "mode") == 0) {
138
0
        int mode;
139
140
0
        if (strcmp(value, "EXTRACT_AND_EXPAND") == 0)
141
0
            mode = EVP_PKEY_HKDEF_MODE_EXTRACT_AND_EXPAND;
142
0
        else if (strcmp(value, "EXTRACT_ONLY") == 0)
143
0
            mode = EVP_PKEY_HKDEF_MODE_EXTRACT_ONLY;
144
0
        else if (strcmp(value, "EXPAND_ONLY") == 0)
145
0
            mode = EVP_PKEY_HKDEF_MODE_EXPAND_ONLY;
146
0
        else
147
0
            return 0;
148
149
0
        return EVP_PKEY_CTX_hkdf_mode(ctx, mode);
150
0
    }
151
152
0
    if (strcmp(type, "md") == 0)
153
0
        return EVP_PKEY_CTX_md(ctx, EVP_PKEY_OP_DERIVE,
154
0
                               EVP_PKEY_CTRL_HKDF_MD, value);
155
156
0
    if (strcmp(type, "salt") == 0)
157
0
        return EVP_PKEY_CTX_str2ctrl(ctx, EVP_PKEY_CTRL_HKDF_SALT, value);
158
159
0
    if (strcmp(type, "hexsalt") == 0)
160
0
        return EVP_PKEY_CTX_hex2ctrl(ctx, EVP_PKEY_CTRL_HKDF_SALT, value);
161
162
0
    if (strcmp(type, "key") == 0)
163
0
        return EVP_PKEY_CTX_str2ctrl(ctx, EVP_PKEY_CTRL_HKDF_KEY, value);
164
165
0
    if (strcmp(type, "hexkey") == 0)
166
0
        return EVP_PKEY_CTX_hex2ctrl(ctx, EVP_PKEY_CTRL_HKDF_KEY, value);
167
168
0
    if (strcmp(type, "info") == 0)
169
0
        return EVP_PKEY_CTX_str2ctrl(ctx, EVP_PKEY_CTRL_HKDF_INFO, value);
170
171
0
    if (strcmp(type, "hexinfo") == 0)
172
0
        return EVP_PKEY_CTX_hex2ctrl(ctx, EVP_PKEY_CTRL_HKDF_INFO, value);
173
174
0
    KDFerr(KDF_F_PKEY_HKDF_CTRL_STR, KDF_R_UNKNOWN_PARAMETER_TYPE);
175
0
    return -2;
176
0
}
177
178
static int pkey_hkdf_derive_init(EVP_PKEY_CTX *ctx)
179
0
{
180
0
    HKDF_PKEY_CTX *kctx = ctx->data;
181
182
0
    OPENSSL_clear_free(kctx->key, kctx->key_len);
183
0
    OPENSSL_clear_free(kctx->salt, kctx->salt_len);
184
0
    OPENSSL_cleanse(kctx->info, kctx->info_len);
185
0
    memset(kctx, 0, sizeof(*kctx));
186
187
0
    return 1;
188
0
}
189
190
static int pkey_hkdf_derive(EVP_PKEY_CTX *ctx, unsigned char *key,
191
                            size_t *keylen)
192
0
{
193
0
    HKDF_PKEY_CTX *kctx = ctx->data;
194
195
0
    if (kctx->md == NULL) {
196
0
        KDFerr(KDF_F_PKEY_HKDF_DERIVE, KDF_R_MISSING_MESSAGE_DIGEST);
197
0
        return 0;
198
0
    }
199
0
    if (kctx->key == NULL) {
200
0
        KDFerr(KDF_F_PKEY_HKDF_DERIVE, KDF_R_MISSING_KEY);
201
0
        return 0;
202
0
    }
203
204
0
    switch (kctx->mode) {
205
0
    case EVP_PKEY_HKDEF_MODE_EXTRACT_AND_EXPAND:
206
0
        return HKDF(kctx->md, kctx->salt, kctx->salt_len, kctx->key,
207
0
                    kctx->key_len, kctx->info, kctx->info_len, key,
208
0
                    *keylen) != NULL;
209
210
0
    case EVP_PKEY_HKDEF_MODE_EXTRACT_ONLY:
211
0
        if (key == NULL) {
212
0
            *keylen = EVP_MD_size(kctx->md);
213
0
            return 1;
214
0
        }
215
0
        return HKDF_Extract(kctx->md, kctx->salt, kctx->salt_len, kctx->key,
216
0
                            kctx->key_len, key, keylen) != NULL;
217
218
0
    case EVP_PKEY_HKDEF_MODE_EXPAND_ONLY:
219
0
        return HKDF_Expand(kctx->md, kctx->key, kctx->key_len, kctx->info,
220
0
                           kctx->info_len, key, *keylen) != NULL;
221
222
0
    default:
223
0
        return 0;
224
0
    }
225
0
}
226
227
const EVP_PKEY_METHOD hkdf_pkey_meth = {
228
    EVP_PKEY_HKDF,
229
    0,
230
    pkey_hkdf_init,
231
    0,
232
    pkey_hkdf_cleanup,
233
234
    0, 0,
235
    0, 0,
236
237
    0,
238
    0,
239
240
    0,
241
    0,
242
243
    0, 0,
244
245
    0, 0, 0, 0,
246
247
    0, 0,
248
249
    0, 0,
250
251
    pkey_hkdf_derive_init,
252
    pkey_hkdf_derive,
253
    pkey_hkdf_ctrl,
254
    pkey_hkdf_ctrl_str
255
};
256
257
static unsigned char *HKDF(const EVP_MD *evp_md,
258
                           const unsigned char *salt, size_t salt_len,
259
                           const unsigned char *key, size_t key_len,
260
                           const unsigned char *info, size_t info_len,
261
                           unsigned char *okm, size_t okm_len)
262
0
{
263
0
    unsigned char prk[EVP_MAX_MD_SIZE];
264
0
    unsigned char *ret;
265
0
    size_t prk_len;
266
267
0
    if (!HKDF_Extract(evp_md, salt, salt_len, key, key_len, prk, &prk_len))
268
0
        return NULL;
269
270
0
    ret = HKDF_Expand(evp_md, prk, prk_len, info, info_len, okm, okm_len);
271
0
    OPENSSL_cleanse(prk, sizeof(prk));
272
273
0
    return ret;
274
0
}
275
276
static unsigned char *HKDF_Extract(const EVP_MD *evp_md,
277
                                   const unsigned char *salt, size_t salt_len,
278
                                   const unsigned char *key, size_t key_len,
279
                                   unsigned char *prk, size_t *prk_len)
280
0
{
281
0
    unsigned int tmp_len;
282
283
0
    if (!HMAC(evp_md, salt, salt_len, key, key_len, prk, &tmp_len))
284
0
        return NULL;
285
286
0
    *prk_len = tmp_len;
287
0
    return prk;
288
0
}
289
290
static unsigned char *HKDF_Expand(const EVP_MD *evp_md,
291
                                  const unsigned char *prk, size_t prk_len,
292
                                  const unsigned char *info, size_t info_len,
293
                                  unsigned char *okm, size_t okm_len)
294
0
{
295
0
    HMAC_CTX *hmac;
296
0
    unsigned char *ret = NULL;
297
298
0
    unsigned int i;
299
300
0
    unsigned char prev[EVP_MAX_MD_SIZE];
301
302
0
    size_t done_len = 0, dig_len = EVP_MD_size(evp_md);
303
304
0
    size_t n = okm_len / dig_len;
305
0
    if (okm_len % dig_len)
306
0
        n++;
307
308
0
    if (n > 255 || okm == NULL)
309
0
        return NULL;
310
311
0
    if ((hmac = HMAC_CTX_new()) == NULL)
312
0
        return NULL;
313
314
0
    if (!HMAC_Init_ex(hmac, prk, prk_len, evp_md, NULL))
315
0
        goto err;
316
317
0
    for (i = 1; i <= n; i++) {
318
0
        size_t copy_len;
319
0
        const unsigned char ctr = i;
320
321
0
        if (i > 1) {
322
0
            if (!HMAC_Init_ex(hmac, NULL, 0, NULL, NULL))
323
0
                goto err;
324
325
0
            if (!HMAC_Update(hmac, prev, dig_len))
326
0
                goto err;
327
0
        }
328
329
0
        if (!HMAC_Update(hmac, info, info_len))
330
0
            goto err;
331
332
0
        if (!HMAC_Update(hmac, &ctr, 1))
333
0
            goto err;
334
335
0
        if (!HMAC_Final(hmac, prev, NULL))
336
0
            goto err;
337
338
0
        copy_len = (done_len + dig_len > okm_len) ?
339
0
                       okm_len - done_len :
340
0
                       dig_len;
341
342
0
        memcpy(okm + done_len, prev, copy_len);
343
344
0
        done_len += copy_len;
345
0
    }
346
0
    ret = okm;
347
348
0
 err:
349
0
    OPENSSL_cleanse(prev, sizeof(prev));
350
0
    HMAC_CTX_free(hmac);
351
0
    return ret;
352
0
}