]> git.ipfire.org Git - thirdparty/openssl.git/blob - crypto/kdf/hkdf.c
Reset the HKDF state between operations
[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_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
190 static 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
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 {
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
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 {
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
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 {
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 }