Coverage Report

Created: 2018-08-29 13:53

/src/openssl/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 "internal/evp_int.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
0
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
0
56
0
    ctx->data = kctx;
57
0
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
0
74
0
    switch (type) {
75
0
    case EVP_PKEY_CTRL_HKDF_MD:
76
0
        if (p2 == NULL)
77
0
            return 0;
78
0
79
0
        kctx->md = p2;
80
0
        return 1;
81
0
82
0
    case EVP_PKEY_CTRL_HKDF_MODE:
83
0
        kctx->mode = p1;
84
0
        return 1;
85
0
86
0
    case EVP_PKEY_CTRL_HKDF_SALT:
87
0
        if (p1 == 0 || p2 == NULL)
88
0
            return 1;
89
0
90
0
        if (p1 < 0)
91
0
            return 0;
92
0
93
0
        if (kctx->salt != NULL)
94
0
            OPENSSL_clear_free(kctx->salt, kctx->salt_len);
95
0
96
0
        kctx->salt = OPENSSL_memdup(p2, p1);
97
0
        if (kctx->salt == NULL)
98
0
            return 0;
99
0
100
0
        kctx->salt_len = p1;
101
0
        return 1;
102
0
103
0
    case EVP_PKEY_CTRL_HKDF_KEY:
104
0
        if (p1 < 0)
105
0
            return 0;
106
0
107
0
        if (kctx->key != NULL)
108
0
            OPENSSL_clear_free(kctx->key, kctx->key_len);
109
0
110
0
        kctx->key = OPENSSL_memdup(p2, p1);
111
0
        if (kctx->key == NULL)
112
0
            return 0;
113
0
114
0
        kctx->key_len  = p1;
115
0
        return 1;
116
0
117
0
    case EVP_PKEY_CTRL_HKDF_INFO:
118
0
        if (p1 == 0 || p2 == NULL)
119
0
            return 1;
120
0
121
0
        if (p1 < 0 || p1 > (int)(HKDF_MAXBUF - kctx->info_len))
122
0
            return 0;
123
0
124
0
        memcpy(kctx->info + kctx->info_len, p2, p1);
125
0
        kctx->info_len += p1;
126
0
        return 1;
127
0
128
0
    default:
129
0
        return -2;
130
0
131
0
    }
132
0
}
133
134
static int pkey_hkdf_ctrl_str(EVP_PKEY_CTX *ctx, const char *type,
135
                              const char *value)
136
{
137
    if (strcmp(type, "mode") == 0) {
138
        int mode;
139
140
        if (strcmp(value, "EXTRACT_AND_EXPAND") == 0)
141
            mode = EVP_PKEY_HKDEF_MODE_EXTRACT_AND_EXPAND;
142
        else if (strcmp(value, "EXTRACT_ONLY") == 0)
143
            mode = EVP_PKEY_HKDEF_MODE_EXTRACT_ONLY;
144
        else if (strcmp(value, "EXPAND_ONLY") == 0)
145
            mode = EVP_PKEY_HKDEF_MODE_EXPAND_ONLY;
146
        else
147
            return 0;
148
149
        return EVP_PKEY_CTX_hkdf_mode(ctx, mode);
150
    }
151
152
    if (strcmp(type, "md") == 0)
153
        return EVP_PKEY_CTX_md(ctx, EVP_PKEY_OP_DERIVE,
154
                               EVP_PKEY_CTRL_HKDF_MD, value);
155
156
    if (strcmp(type, "salt") == 0)
157
        return EVP_PKEY_CTX_str2ctrl(ctx, EVP_PKEY_CTRL_HKDF_SALT, value);
158
159
    if (strcmp(type, "hexsalt") == 0)
160
        return EVP_PKEY_CTX_hex2ctrl(ctx, EVP_PKEY_CTRL_HKDF_SALT, value);
161
162
    if (strcmp(type, "key") == 0)
163
        return EVP_PKEY_CTX_str2ctrl(ctx, EVP_PKEY_CTRL_HKDF_KEY, value);
164
165
    if (strcmp(type, "hexkey") == 0)
166
        return EVP_PKEY_CTX_hex2ctrl(ctx, EVP_PKEY_CTRL_HKDF_KEY, value);
167
168
    if (strcmp(type, "info") == 0)
169
        return EVP_PKEY_CTX_str2ctrl(ctx, EVP_PKEY_CTRL_HKDF_INFO, value);
170
171
    if (strcmp(type, "hexinfo") == 0)
172
        return EVP_PKEY_CTX_hex2ctrl(ctx, EVP_PKEY_CTRL_HKDF_INFO, value);
173
174
    KDFerr(KDF_F_PKEY_HKDF_CTRL_STR, KDF_R_UNKNOWN_PARAMETER_TYPE);
175
    return -2;
176
}
177
178
static int pkey_hkdf_derive(EVP_PKEY_CTX *ctx, unsigned char *key,
179
                            size_t *keylen)
180
0
{
181
0
    HKDF_PKEY_CTX *kctx = ctx->data;
182
0
183
0
    if (kctx->md == NULL) {
184
0
        KDFerr(KDF_F_PKEY_HKDF_DERIVE, KDF_R_MISSING_MESSAGE_DIGEST);
185
0
        return 0;
186
0
    }
187
0
    if (kctx->key == NULL) {
188
0
        KDFerr(KDF_F_PKEY_HKDF_DERIVE, KDF_R_MISSING_KEY);
189
0
        return 0;
190
0
    }
191
0
192
0
    switch (kctx->mode) {
193
0
    case EVP_PKEY_HKDEF_MODE_EXTRACT_AND_EXPAND:
194
0
        return HKDF(kctx->md, kctx->salt, kctx->salt_len, kctx->key,
195
0
                    kctx->key_len, kctx->info, kctx->info_len, key,
196
0
                    *keylen) != NULL;
197
0
198
0
    case EVP_PKEY_HKDEF_MODE_EXTRACT_ONLY:
199
0
        if (key == NULL) {
200
0
            *keylen = EVP_MD_size(kctx->md);
201
0
            return 1;
202
0
        }
203
0
        return HKDF_Extract(kctx->md, kctx->salt, kctx->salt_len, kctx->key,
204
0
                            kctx->key_len, key, keylen) != NULL;
205
0
206
0
    case EVP_PKEY_HKDEF_MODE_EXPAND_ONLY:
207
0
        return HKDF_Expand(kctx->md, kctx->key, kctx->key_len, kctx->info,
208
0
                           kctx->info_len, key, *keylen) != NULL;
209
0
210
0
    default:
211
0
        return 0;
212
0
    }
213
0
}
214
215
const EVP_PKEY_METHOD hkdf_pkey_meth = {
216
    EVP_PKEY_HKDF,
217
    0,
218
    pkey_hkdf_init,
219
    0,
220
    pkey_hkdf_cleanup,
221
222
    0, 0,
223
    0, 0,
224
225
    0,
226
    0,
227
228
    0,
229
    0,
230
231
    0, 0,
232
233
    0, 0, 0, 0,
234
235
    0, 0,
236
237
    0, 0,
238
239
    0,
240
    pkey_hkdf_derive,
241
    pkey_hkdf_ctrl,
242
    pkey_hkdf_ctrl_str
243
};
244
245
static unsigned char *HKDF(const EVP_MD *evp_md,
246
                           const unsigned char *salt, size_t salt_len,
247
                           const unsigned char *key, size_t key_len,
248
                           const unsigned char *info, size_t info_len,
249
                           unsigned char *okm, size_t okm_len)
250
0
{
251
0
    unsigned char prk[EVP_MAX_MD_SIZE];
252
0
    unsigned char *ret;
253
0
    size_t prk_len;
254
0
255
0
    if (!HKDF_Extract(evp_md, salt, salt_len, key, key_len, prk, &prk_len))
256
0
        return NULL;
257
0
258
0
    ret = HKDF_Expand(evp_md, prk, prk_len, info, info_len, okm, okm_len);
259
0
    OPENSSL_cleanse(prk, sizeof(prk));
260
0
261
0
    return ret;
262
0
}
263
264
static unsigned char *HKDF_Extract(const EVP_MD *evp_md,
265
                                   const unsigned char *salt, size_t salt_len,
266
                                   const unsigned char *key, size_t key_len,
267
                                   unsigned char *prk, size_t *prk_len)
268
0
{
269
0
    unsigned int tmp_len;
270
0
271
0
    if (!HMAC(evp_md, salt, salt_len, key, key_len, prk, &tmp_len))
272
0
        return NULL;
273
0
274
0
    *prk_len = tmp_len;
275
0
    return prk;
276
0
}
277
278
static unsigned char *HKDF_Expand(const EVP_MD *evp_md,
279
                                  const unsigned char *prk, size_t prk_len,
280
                                  const unsigned char *info, size_t info_len,
281
                                  unsigned char *okm, size_t okm_len)
282
0
{
283
0
    HMAC_CTX *hmac;
284
0
285
0
    unsigned int i;
286
0
287
0
    unsigned char prev[EVP_MAX_MD_SIZE];
288
0
289
0
    size_t done_len = 0, dig_len = EVP_MD_size(evp_md);
290
0
291
0
    size_t n = okm_len / dig_len;
292
0
    if (okm_len % dig_len)
293
0
        n++;
294
0
295
0
    if (n > 255 || okm == NULL)
296
0
        return NULL;
297
0
298
0
    if ((hmac = HMAC_CTX_new()) == NULL)
299
0
        return NULL;
300
0
301
0
    if (!HMAC_Init_ex(hmac, prk, prk_len, evp_md, NULL))
302
0
        goto err;
303
0
304
0
    for (i = 1; i <= n; i++) {
305
0
        size_t copy_len;
306
0
        const unsigned char ctr = i;
307
0
308
0
        if (i > 1) {
309
0
            if (!HMAC_Init_ex(hmac, NULL, 0, NULL, NULL))
310
0
                goto err;
311
0
312
0
            if (!HMAC_Update(hmac, prev, dig_len))
313
0
                goto err;
314
0
        }
315
0
316
0
        if (!HMAC_Update(hmac, info, info_len))
317
0
            goto err;
318
0
319
0
        if (!HMAC_Update(hmac, &ctr, 1))
320
0
            goto err;
321
0
322
0
        if (!HMAC_Final(hmac, prev, NULL))
323
0
            goto err;
324
0
325
0
        copy_len = (done_len + dig_len > okm_len) ?
326
0
                       okm_len - done_len :
327
0
                       dig_len;
328
0
329
0
        memcpy(okm + done_len, prev, copy_len);
330
0
331
0
        done_len += copy_len;
332
0
    }
333
0
334
0
    HMAC_CTX_free(hmac);
335
0
    return okm;
336
0
337
0
 err:
338
0
    HMAC_CTX_free(hmac);
339
0
    return NULL;
340
0
}