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#define HKDF_MAXBUF 1024
19
20static 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
26static 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
31static 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
36typedef 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
47static int pkey_hkdf_init(EVP_PKEY_CTX *ctx)
48{
49    HKDF_PKEY_CTX *kctx;
50
51    if ((kctx = OPENSSL_zalloc(sizeof(*kctx))) == NULL) {
52        KDFerr(KDF_F_PKEY_HKDF_INIT, ERR_R_MALLOC_FAILURE);
53        return 0;
54    }
55
56    ctx->data = kctx;
57
58    return 1;
59}
60
61static void pkey_hkdf_cleanup(EVP_PKEY_CTX *ctx)
62{
63    HKDF_PKEY_CTX *kctx = ctx->data;
64    OPENSSL_clear_free(kctx->salt, kctx->salt_len);
65    OPENSSL_clear_free(kctx->key, kctx->key_len);
66    OPENSSL_cleanse(kctx->info, kctx->info_len);
67    OPENSSL_free(kctx);
68}
69
70static int pkey_hkdf_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
71{
72    HKDF_PKEY_CTX *kctx = ctx->data;
73
74    switch (type) {
75    case EVP_PKEY_CTRL_HKDF_MD:
76        if (p2 == NULL)
77            return 0;
78
79        kctx->md = p2;
80        return 1;
81
82    case EVP_PKEY_CTRL_HKDF_MODE:
83        kctx->mode = p1;
84        return 1;
85
86    case EVP_PKEY_CTRL_HKDF_SALT:
87        if (p1 == 0 || p2 == NULL)
88            return 1;
89
90        if (p1 < 0)
91            return 0;
92
93        if (kctx->salt != NULL)
94            OPENSSL_clear_free(kctx->salt, kctx->salt_len);
95
96        kctx->salt = OPENSSL_memdup(p2, p1);
97        if (kctx->salt == NULL)
98            return 0;
99
100        kctx->salt_len = p1;
101        return 1;
102
103    case EVP_PKEY_CTRL_HKDF_KEY:
104        if (p1 < 0)
105            return 0;
106
107        if (kctx->key != NULL)
108            OPENSSL_clear_free(kctx->key, kctx->key_len);
109
110        kctx->key = OPENSSL_memdup(p2, p1);
111        if (kctx->key == NULL)
112            return 0;
113
114        kctx->key_len  = p1;
115        return 1;
116
117    case EVP_PKEY_CTRL_HKDF_INFO:
118        if (p1 == 0 || p2 == NULL)
119            return 1;
120
121        if (p1 < 0 || p1 > (int)(HKDF_MAXBUF - kctx->info_len))
122            return 0;
123
124        memcpy(kctx->info + kctx->info_len, p2, p1);
125        kctx->info_len += p1;
126        return 1;
127
128    default:
129        return -2;
130
131    }
132}
133
134static 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
178static int pkey_hkdf_derive_init(EVP_PKEY_CTX *ctx)
179{
180    HKDF_PKEY_CTX *kctx = ctx->data;
181
182    OPENSSL_clear_free(kctx->key, kctx->key_len);
183    OPENSSL_clear_free(kctx->salt, kctx->salt_len);
184    OPENSSL_cleanse(kctx->info, kctx->info_len);
185    memset(kctx, 0, sizeof(*kctx));
186
187    return 1;
188}
189
190static int pkey_hkdf_derive(EVP_PKEY_CTX *ctx, unsigned char *key,
191                            size_t *keylen)
192{
193    HKDF_PKEY_CTX *kctx = ctx->data;
194
195    if (kctx->md == NULL) {
196        KDFerr(KDF_F_PKEY_HKDF_DERIVE, KDF_R_MISSING_MESSAGE_DIGEST);
197        return 0;
198    }
199    if (kctx->key == NULL) {
200        KDFerr(KDF_F_PKEY_HKDF_DERIVE, KDF_R_MISSING_KEY);
201        return 0;
202    }
203
204    switch (kctx->mode) {
205    case EVP_PKEY_HKDEF_MODE_EXTRACT_AND_EXPAND:
206        return HKDF(kctx->md, kctx->salt, kctx->salt_len, kctx->key,
207                    kctx->key_len, kctx->info, kctx->info_len, key,
208                    *keylen) != NULL;
209
210    case EVP_PKEY_HKDEF_MODE_EXTRACT_ONLY:
211        if (key == NULL) {
212            *keylen = EVP_MD_size(kctx->md);
213            return 1;
214        }
215        return HKDF_Extract(kctx->md, kctx->salt, kctx->salt_len, kctx->key,
216                            kctx->key_len, key, keylen) != NULL;
217
218    case EVP_PKEY_HKDEF_MODE_EXPAND_ONLY:
219        return HKDF_Expand(kctx->md, kctx->key, kctx->key_len, kctx->info,
220                           kctx->info_len, key, *keylen) != NULL;
221
222    default:
223        return 0;
224    }
225}
226
227const 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
257static 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{
263    unsigned char prk[EVP_MAX_MD_SIZE];
264    unsigned char *ret;
265    size_t prk_len;
266
267    if (!HKDF_Extract(evp_md, salt, salt_len, key, key_len, prk, &prk_len))
268        return NULL;
269
270    ret = HKDF_Expand(evp_md, prk, prk_len, info, info_len, okm, okm_len);
271    OPENSSL_cleanse(prk, sizeof(prk));
272
273    return ret;
274}
275
276static 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{
281    unsigned int tmp_len;
282
283    if (!HMAC(evp_md, salt, salt_len, key, key_len, prk, &tmp_len))
284        return NULL;
285
286    *prk_len = tmp_len;
287    return prk;
288}
289
290static 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{
295    HMAC_CTX *hmac;
296    unsigned char *ret = NULL;
297
298    unsigned int i;
299
300    unsigned char prev[EVP_MAX_MD_SIZE];
301
302    size_t done_len = 0, dig_len = EVP_MD_size(evp_md);
303
304    size_t n = okm_len / dig_len;
305    if (okm_len % dig_len)
306        n++;
307
308    if (n > 255 || okm == NULL)
309        return NULL;
310
311    if ((hmac = HMAC_CTX_new()) == NULL)
312        return NULL;
313
314    if (!HMAC_Init_ex(hmac, prk, prk_len, evp_md, NULL))
315        goto err;
316
317    for (i = 1; i <= n; i++) {
318        size_t copy_len;
319        const unsigned char ctr = i;
320
321        if (i > 1) {
322            if (!HMAC_Init_ex(hmac, NULL, 0, NULL, NULL))
323                goto err;
324
325            if (!HMAC_Update(hmac, prev, dig_len))
326                goto err;
327        }
328
329        if (!HMAC_Update(hmac, info, info_len))
330            goto err;
331
332        if (!HMAC_Update(hmac, &ctr, 1))
333            goto err;
334
335        if (!HMAC_Final(hmac, prev, NULL))
336            goto err;
337
338        copy_len = (done_len + dig_len > okm_len) ?
339                       okm_len - done_len :
340                       dig_len;
341
342        memcpy(okm + done_len, prev, copy_len);
343
344        done_len += copy_len;
345    }
346    ret = okm;
347
348 err:
349    OPENSSL_cleanse(prev, sizeof(prev));
350    HMAC_CTX_free(hmac);
351    return ret;
352}
353