]> git.ipfire.org Git - thirdparty/openssl.git/blame - crypto/kdf/hkdf.c
Following the license change, modify the boilerplates in crypto/idea/
[thirdparty/openssl.git] / crypto / kdf / hkdf.c
CommitLineData
d2e9e320 1/*
28428130 2 * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved.
aacfb134 3 *
d2e9e320
RS
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
aacfb134
AG
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
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 {
d2139cf8 37 int mode;
aacfb134
AG
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
cdb10bae
RS
51 if ((kctx = OPENSSL_zalloc(sizeof(*kctx))) == NULL) {
52 KDFerr(KDF_F_PKEY_HKDF_INIT, ERR_R_MALLOC_FAILURE);
aacfb134 53 return 0;
cdb10bae 54 }
aacfb134
AG
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
d2139cf8
MC
82 case EVP_PKEY_CTRL_HKDF_MODE:
83 kctx->mode = p1;
84 return 1;
85
aacfb134
AG
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{
ddd2c389
MC
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
f55129c7
JB
152 if (strcmp(type, "md") == 0)
153 return EVP_PKEY_CTX_md(ctx, EVP_PKEY_OP_DERIVE,
3f4af53c 154 EVP_PKEY_CTRL_HKDF_MD, value);
aacfb134
AG
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
a24a5b8c 174 KDFerr(KDF_F_PKEY_HKDF_CTRL_STR, KDF_R_UNKNOWN_PARAMETER_TYPE);
aacfb134
AG
175 return -2;
176}
177
ca55d70b
MC
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
aacfb134
AG
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
f55129c7
JB
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);
aacfb134 201 return 0;
e65f6509 202 }
aacfb134 203
d2139cf8
MC
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:
aacfb134
AG
223 return 0;
224 }
aacfb134
AG
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
ca55d70b 251 pkey_hkdf_derive_init,
aacfb134
AG
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];
d2139cf8 264 unsigned char *ret;
aacfb134
AG
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
d2139cf8
MC
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;
aacfb134
AG
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;
64ed55ab 296 unsigned char *ret = NULL;
aacfb134
AG
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
d2139cf8 308 if (n > 255 || okm == NULL)
aacfb134
AG
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 }
64ed55ab 346 ret = okm;
aacfb134
AG
347
348 err:
64ed55ab 349 OPENSSL_cleanse(prev, sizeof(prev));
aacfb134 350 HMAC_CTX_free(hmac);
64ed55ab 351 return ret;
aacfb134 352}