]> git.ipfire.org Git - thirdparty/openssl.git/blob - crypto/kdf/hkdf.c
hkdf zeroization fix
[thirdparty/openssl.git] / crypto / kdf / hkdf.c
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 #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 {
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
61 static 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
70 static 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
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 {
181 HKDF_PKEY_CTX *kctx = ctx->data;
182
183 if (kctx->md == NULL) {
184 KDFerr(KDF_F_PKEY_HKDF_DERIVE, KDF_R_MISSING_MESSAGE_DIGEST);
185 return 0;
186 }
187 if (kctx->key == NULL) {
188 KDFerr(KDF_F_PKEY_HKDF_DERIVE, KDF_R_MISSING_KEY);
189 return 0;
190 }
191
192 switch (kctx->mode) {
193 case EVP_PKEY_HKDEF_MODE_EXTRACT_AND_EXPAND:
194 return HKDF(kctx->md, kctx->salt, kctx->salt_len, kctx->key,
195 kctx->key_len, kctx->info, kctx->info_len, key,
196 *keylen) != NULL;
197
198 case EVP_PKEY_HKDEF_MODE_EXTRACT_ONLY:
199 if (key == NULL) {
200 *keylen = EVP_MD_size(kctx->md);
201 return 1;
202 }
203 return HKDF_Extract(kctx->md, kctx->salt, kctx->salt_len, kctx->key,
204 kctx->key_len, key, keylen) != NULL;
205
206 case EVP_PKEY_HKDEF_MODE_EXPAND_ONLY:
207 return HKDF_Expand(kctx->md, kctx->key, kctx->key_len, kctx->info,
208 kctx->info_len, key, *keylen) != NULL;
209
210 default:
211 return 0;
212 }
213 }
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 {
251 unsigned char prk[EVP_MAX_MD_SIZE];
252 unsigned char *ret;
253 size_t prk_len;
254
255 if (!HKDF_Extract(evp_md, salt, salt_len, key, key_len, prk, &prk_len))
256 return NULL;
257
258 ret = HKDF_Expand(evp_md, prk, prk_len, info, info_len, okm, okm_len);
259 OPENSSL_cleanse(prk, sizeof(prk));
260
261 return ret;
262 }
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 {
269 unsigned int tmp_len;
270
271 if (!HMAC(evp_md, salt, salt_len, key, key_len, prk, &tmp_len))
272 return NULL;
273
274 *prk_len = tmp_len;
275 return prk;
276 }
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 {
283 HMAC_CTX *hmac;
284 unsigned char *ret = NULL;
285
286 unsigned int i;
287
288 unsigned char prev[EVP_MAX_MD_SIZE];
289
290 size_t done_len = 0, dig_len = EVP_MD_size(evp_md);
291
292 size_t n = okm_len / dig_len;
293 if (okm_len % dig_len)
294 n++;
295
296 if (n > 255 || okm == NULL)
297 return NULL;
298
299 if ((hmac = HMAC_CTX_new()) == NULL)
300 return NULL;
301
302 if (!HMAC_Init_ex(hmac, prk, prk_len, evp_md, NULL))
303 goto err;
304
305 for (i = 1; i <= n; i++) {
306 size_t copy_len;
307 const unsigned char ctr = i;
308
309 if (i > 1) {
310 if (!HMAC_Init_ex(hmac, NULL, 0, NULL, NULL))
311 goto err;
312
313 if (!HMAC_Update(hmac, prev, dig_len))
314 goto err;
315 }
316
317 if (!HMAC_Update(hmac, info, info_len))
318 goto err;
319
320 if (!HMAC_Update(hmac, &ctr, 1))
321 goto err;
322
323 if (!HMAC_Final(hmac, prev, NULL))
324 goto err;
325
326 copy_len = (done_len + dig_len > okm_len) ?
327 okm_len - done_len :
328 dig_len;
329
330 memcpy(okm + done_len, prev, copy_len);
331
332 done_len += copy_len;
333 }
334 ret = okm;
335
336 err:
337 OPENSSL_cleanse(prev, sizeof(prev));
338 HMAC_CTX_free(hmac);
339 return ret;
340 }