]> git.ipfire.org Git - thirdparty/openssl.git/blame - crypto/kdf/hkdf.c
Update copyright year
[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
178static int pkey_hkdf_derive(EVP_PKEY_CTX *ctx, unsigned char *key,
179 size_t *keylen)
180{
181 HKDF_PKEY_CTX *kctx = ctx->data;
182
f55129c7
JB
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);
aacfb134 189 return 0;
e65f6509 190 }
aacfb134 191
d2139cf8
MC
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:
aacfb134
AG
211 return 0;
212 }
aacfb134
AG
213}
214
215const 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
245static 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];
d2139cf8 252 unsigned char *ret;
aacfb134
AG
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
d2139cf8
MC
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;
aacfb134
AG
262}
263
264static 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
278static 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
285 unsigned int i;
286
287 unsigned char prev[EVP_MAX_MD_SIZE];
288
289 size_t done_len = 0, dig_len = EVP_MD_size(evp_md);
290
291 size_t n = okm_len / dig_len;
292 if (okm_len % dig_len)
293 n++;
294
d2139cf8 295 if (n > 255 || okm == NULL)
aacfb134
AG
296 return NULL;
297
298 if ((hmac = HMAC_CTX_new()) == NULL)
299 return NULL;
300
301 if (!HMAC_Init_ex(hmac, prk, prk_len, evp_md, NULL))
302 goto err;
303
304 for (i = 1; i <= n; i++) {
305 size_t copy_len;
306 const unsigned char ctr = i;
307
308 if (i > 1) {
309 if (!HMAC_Init_ex(hmac, NULL, 0, NULL, NULL))
310 goto err;
311
312 if (!HMAC_Update(hmac, prev, dig_len))
313 goto err;
314 }
315
316 if (!HMAC_Update(hmac, info, info_len))
317 goto err;
318
319 if (!HMAC_Update(hmac, &ctr, 1))
320 goto err;
321
322 if (!HMAC_Final(hmac, prev, NULL))
323 goto err;
324
325 copy_len = (done_len + dig_len > okm_len) ?
326 okm_len - done_len :
327 dig_len;
328
329 memcpy(okm + done_len, prev, copy_len);
330
331 done_len += copy_len;
332 }
333
334 HMAC_CTX_free(hmac);
335 return okm;
336
337 err:
338 HMAC_CTX_free(hmac);
339 return NULL;
340}