]>
Commit | Line | Data |
---|---|---|
d2e9e320 | 1 | /* |
da1c088f | 2 | * Copyright 2016-2023 The OpenSSL Project Authors. All Rights Reserved. |
aacfb134 | 3 | * |
7bb803e8 | 4 | * Licensed under the Apache License 2.0 (the "License"). You may not use |
d2e9e320 RS |
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 | ||
dbde4726 P |
10 | /* |
11 | * HMAC low level APIs are deprecated for public use, but still ok for internal | |
12 | * use. | |
13 | */ | |
14 | #include "internal/deprecated.h" | |
15 | ||
aacfb134 | 16 | #include <stdlib.h> |
5a285add | 17 | #include <stdarg.h> |
aacfb134 AG |
18 | #include <string.h> |
19 | #include <openssl/hmac.h> | |
aacfb134 | 20 | #include <openssl/evp.h> |
5a285add | 21 | #include <openssl/kdf.h> |
e3405a4a | 22 | #include <openssl/core_names.h> |
2741128e | 23 | #include <openssl/proverr.h> |
aacfb134 | 24 | #include "internal/cryptlib.h" |
cee719c2 | 25 | #include "internal/numbers.h" |
f7d998a2 | 26 | #include "internal/packet.h" |
25f2138b | 27 | #include "crypto/evp.h" |
ddd21319 | 28 | #include "prov/provider_ctx.h" |
2b9e4e95 | 29 | #include "prov/providercommon.h" |
af3e7e1b | 30 | #include "prov/implementations.h" |
ddd21319 | 31 | #include "prov/provider_util.h" |
d5f9166b | 32 | #include "internal/e_os.h" |
345b42be | 33 | #include "internal/params.h" |
aacfb134 | 34 | |
20c2876f | 35 | #define HKDF_MAXBUF 2048 |
e8115bd1 | 36 | #define HKDF_MAXINFO (32*1024) |
aacfb134 | 37 | |
363b1e5d | 38 | static OSSL_FUNC_kdf_newctx_fn kdf_hkdf_new; |
95bd5ff6 | 39 | static OSSL_FUNC_kdf_dupctx_fn kdf_hkdf_dup; |
363b1e5d DMSP |
40 | static OSSL_FUNC_kdf_freectx_fn kdf_hkdf_free; |
41 | static OSSL_FUNC_kdf_reset_fn kdf_hkdf_reset; | |
42 | static OSSL_FUNC_kdf_derive_fn kdf_hkdf_derive; | |
43 | static OSSL_FUNC_kdf_settable_ctx_params_fn kdf_hkdf_settable_ctx_params; | |
44 | static OSSL_FUNC_kdf_set_ctx_params_fn kdf_hkdf_set_ctx_params; | |
45 | static OSSL_FUNC_kdf_gettable_ctx_params_fn kdf_hkdf_gettable_ctx_params; | |
46 | static OSSL_FUNC_kdf_get_ctx_params_fn kdf_hkdf_get_ctx_params; | |
f7d998a2 P |
47 | static OSSL_FUNC_kdf_derive_fn kdf_tls1_3_derive; |
48 | static OSSL_FUNC_kdf_settable_ctx_params_fn kdf_tls1_3_settable_ctx_params; | |
49 | static OSSL_FUNC_kdf_set_ctx_params_fn kdf_tls1_3_set_ctx_params; | |
e3405a4a | 50 | |
0a8a6afd | 51 | static int HKDF(OSSL_LIB_CTX *libctx, const EVP_MD *evp_md, |
5a285add DM |
52 | const unsigned char *salt, size_t salt_len, |
53 | const unsigned char *key, size_t key_len, | |
54 | const unsigned char *info, size_t info_len, | |
55 | unsigned char *okm, size_t okm_len); | |
0a8a6afd | 56 | static int HKDF_Extract(OSSL_LIB_CTX *libctx, const EVP_MD *evp_md, |
5a285add | 57 | const unsigned char *salt, size_t salt_len, |
e7018588 | 58 | const unsigned char *ikm, size_t ikm_len, |
5a285add DM |
59 | unsigned char *prk, size_t prk_len); |
60 | static int HKDF_Expand(const EVP_MD *evp_md, | |
61 | const unsigned char *prk, size_t prk_len, | |
62 | const unsigned char *info, size_t info_len, | |
63 | unsigned char *okm, size_t okm_len); | |
64 | ||
f7d998a2 P |
65 | /* Settable context parameters that are common across HKDF and the TLS KDF */ |
66 | #define HKDF_COMMON_SETTABLES \ | |
67 | OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_MODE, NULL, 0), \ | |
68 | OSSL_PARAM_int(OSSL_KDF_PARAM_MODE, NULL), \ | |
69 | OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_PROPERTIES, NULL, 0), \ | |
70 | OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_DIGEST, NULL, 0), \ | |
71 | OSSL_PARAM_octet_string(OSSL_KDF_PARAM_KEY, NULL, 0), \ | |
72 | OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SALT, NULL, 0) | |
73 | ||
e3405a4a P |
74 | typedef struct { |
75 | void *provctx; | |
d2139cf8 | 76 | int mode; |
86f17ed6 | 77 | PROV_DIGEST digest; |
aacfb134 AG |
78 | unsigned char *salt; |
79 | size_t salt_len; | |
80 | unsigned char *key; | |
81 | size_t key_len; | |
f7d998a2 P |
82 | unsigned char *prefix; |
83 | size_t prefix_len; | |
84 | unsigned char *label; | |
85 | size_t label_len; | |
86 | unsigned char *data; | |
87 | size_t data_len; | |
e8115bd1 | 88 | unsigned char *info; |
aacfb134 | 89 | size_t info_len; |
e3405a4a | 90 | } KDF_HKDF; |
aacfb134 | 91 | |
e3405a4a | 92 | static void *kdf_hkdf_new(void *provctx) |
aacfb134 | 93 | { |
e3405a4a | 94 | KDF_HKDF *ctx; |
aacfb134 | 95 | |
2b9e4e95 P |
96 | if (!ossl_prov_is_running()) |
97 | return NULL; | |
98 | ||
e077455e | 99 | if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) != NULL) |
e3405a4a P |
100 | ctx->provctx = provctx; |
101 | return ctx; | |
5a285add | 102 | } |
aacfb134 | 103 | |
e3405a4a | 104 | static void kdf_hkdf_free(void *vctx) |
5a285add | 105 | { |
e3405a4a | 106 | KDF_HKDF *ctx = (KDF_HKDF *)vctx; |
aacfb134 | 107 | |
3c659415 P |
108 | if (ctx != NULL) { |
109 | kdf_hkdf_reset(ctx); | |
110 | OPENSSL_free(ctx); | |
111 | } | |
aacfb134 AG |
112 | } |
113 | ||
e3405a4a | 114 | static void kdf_hkdf_reset(void *vctx) |
aacfb134 | 115 | { |
e3405a4a | 116 | KDF_HKDF *ctx = (KDF_HKDF *)vctx; |
0577959c | 117 | void *provctx = ctx->provctx; |
aacfb134 | 118 | |
86f17ed6 | 119 | ossl_prov_digest_reset(&ctx->digest); |
fa338aa7 DJL |
120 | #ifdef FIPS_MODULE |
121 | OPENSSL_clear_free(ctx->salt, ctx->salt_len); | |
122 | #else | |
e3405a4a | 123 | OPENSSL_free(ctx->salt); |
fa338aa7 | 124 | #endif |
f7d998a2 P |
125 | OPENSSL_free(ctx->prefix); |
126 | OPENSSL_free(ctx->label); | |
127 | OPENSSL_clear_free(ctx->data, ctx->data_len); | |
e3405a4a | 128 | OPENSSL_clear_free(ctx->key, ctx->key_len); |
e8115bd1 | 129 | OPENSSL_clear_free(ctx->info, ctx->info_len); |
e3405a4a | 130 | memset(ctx, 0, sizeof(*ctx)); |
0577959c | 131 | ctx->provctx = provctx; |
aacfb134 AG |
132 | } |
133 | ||
95bd5ff6 P |
134 | static void *kdf_hkdf_dup(void *vctx) |
135 | { | |
136 | const KDF_HKDF *src = (const KDF_HKDF *)vctx; | |
137 | KDF_HKDF *dest; | |
138 | ||
139 | dest = kdf_hkdf_new(src->provctx); | |
140 | if (dest != NULL) { | |
141 | if (!ossl_prov_memdup(src->salt, src->salt_len, &dest->salt, | |
142 | &dest->salt_len) | |
143 | || !ossl_prov_memdup(src->key, src->key_len, | |
144 | &dest->key , &dest->key_len) | |
145 | || !ossl_prov_memdup(src->prefix, src->prefix_len, | |
146 | &dest->prefix, &dest->prefix_len) | |
147 | || !ossl_prov_memdup(src->label, src->label_len, | |
148 | &dest->label, &dest->label_len) | |
149 | || !ossl_prov_memdup(src->data, src->data_len, | |
150 | &dest->data, &dest->data_len) | |
e8115bd1 | 151 | || !ossl_prov_memdup(src->info, src->info_len, |
152 | &dest->info, &dest->info_len) | |
95bd5ff6 P |
153 | || !ossl_prov_digest_copy(&dest->digest, &src->digest)) |
154 | goto err; | |
95bd5ff6 P |
155 | dest->mode = src->mode; |
156 | } | |
157 | return dest; | |
158 | ||
159 | err: | |
160 | kdf_hkdf_free(dest); | |
161 | return NULL; | |
162 | } | |
163 | ||
e3405a4a | 164 | static size_t kdf_hkdf_size(KDF_HKDF *ctx) |
ca55d70b | 165 | { |
97cc9c9b | 166 | int sz; |
86f17ed6 | 167 | const EVP_MD *md = ossl_prov_digest_md(&ctx->digest); |
97cc9c9b | 168 | |
e3405a4a | 169 | if (ctx->mode != EVP_KDF_HKDF_MODE_EXTRACT_ONLY) |
5a285add | 170 | return SIZE_MAX; |
ca55d70b | 171 | |
86f17ed6 | 172 | if (md == NULL) { |
e3405a4a | 173 | ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_MESSAGE_DIGEST); |
5a285add DM |
174 | return 0; |
175 | } | |
ed576acd | 176 | sz = EVP_MD_get_size(md); |
97cc9c9b SL |
177 | if (sz < 0) |
178 | return 0; | |
179 | ||
180 | return sz; | |
ca55d70b MC |
181 | } |
182 | ||
3469b388 P |
183 | static int kdf_hkdf_derive(void *vctx, unsigned char *key, size_t keylen, |
184 | const OSSL_PARAM params[]) | |
aacfb134 | 185 | { |
e3405a4a | 186 | KDF_HKDF *ctx = (KDF_HKDF *)vctx; |
0a8a6afd | 187 | OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(ctx->provctx); |
2b9e4e95 P |
188 | const EVP_MD *md; |
189 | ||
3469b388 | 190 | if (!ossl_prov_is_running() || !kdf_hkdf_set_ctx_params(ctx, params)) |
2b9e4e95 | 191 | return 0; |
e3405a4a | 192 | |
2b9e4e95 | 193 | md = ossl_prov_digest_md(&ctx->digest); |
86f17ed6 | 194 | if (md == NULL) { |
e3405a4a | 195 | ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_MESSAGE_DIGEST); |
f55129c7 JB |
196 | return 0; |
197 | } | |
e3405a4a P |
198 | if (ctx->key == NULL) { |
199 | ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_KEY); | |
aacfb134 | 200 | return 0; |
e65f6509 | 201 | } |
1cae59d1 JS |
202 | if (keylen == 0) { |
203 | ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH); | |
204 | return 0; | |
205 | } | |
aacfb134 | 206 | |
e3405a4a | 207 | switch (ctx->mode) { |
5a285add | 208 | case EVP_KDF_HKDF_MODE_EXTRACT_AND_EXPAND: |
9d300aa2 | 209 | default: |
0a8a6afd DDO |
210 | return HKDF(libctx, md, ctx->salt, ctx->salt_len, |
211 | ctx->key, ctx->key_len, ctx->info, ctx->info_len, key, keylen); | |
d2139cf8 | 212 | |
5a285add | 213 | case EVP_KDF_HKDF_MODE_EXTRACT_ONLY: |
0a8a6afd DDO |
214 | return HKDF_Extract(libctx, md, ctx->salt, ctx->salt_len, |
215 | ctx->key, ctx->key_len, key, keylen); | |
d2139cf8 | 216 | |
5a285add | 217 | case EVP_KDF_HKDF_MODE_EXPAND_ONLY: |
86f17ed6 | 218 | return HKDF_Expand(md, ctx->key, ctx->key_len, ctx->info, |
e3405a4a | 219 | ctx->info_len, key, keylen); |
aacfb134 | 220 | } |
aacfb134 AG |
221 | } |
222 | ||
f7d998a2 | 223 | static int hkdf_common_set_ctx_params(KDF_HKDF *ctx, const OSSL_PARAM params[]) |
e3405a4a | 224 | { |
0a8a6afd | 225 | OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(ctx->provctx); |
f7d998a2 | 226 | const OSSL_PARAM *p; |
e3405a4a | 227 | int n; |
86f17ed6 | 228 | |
c983a0e5 P |
229 | if (params == NULL) |
230 | return 1; | |
231 | ||
0a8a6afd | 232 | if (!ossl_prov_digest_load_from_params(&ctx->digest, params, libctx)) |
86f17ed6 | 233 | return 0; |
e3405a4a P |
234 | |
235 | if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_MODE)) != NULL) { | |
236 | if (p->data_type == OSSL_PARAM_UTF8_STRING) { | |
fba140c7 | 237 | if (OPENSSL_strcasecmp(p->data, "EXTRACT_AND_EXPAND") == 0) { |
e3405a4a | 238 | ctx->mode = EVP_KDF_HKDF_MODE_EXTRACT_AND_EXPAND; |
fba140c7 | 239 | } else if (OPENSSL_strcasecmp(p->data, "EXTRACT_ONLY") == 0) { |
e3405a4a | 240 | ctx->mode = EVP_KDF_HKDF_MODE_EXTRACT_ONLY; |
fba140c7 | 241 | } else if (OPENSSL_strcasecmp(p->data, "EXPAND_ONLY") == 0) { |
e3405a4a P |
242 | ctx->mode = EVP_KDF_HKDF_MODE_EXPAND_ONLY; |
243 | } else { | |
244 | ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_MODE); | |
245 | return 0; | |
246 | } | |
247 | } else if (OSSL_PARAM_get_int(p, &n)) { | |
248 | if (n != EVP_KDF_HKDF_MODE_EXTRACT_AND_EXPAND | |
249 | && n != EVP_KDF_HKDF_MODE_EXTRACT_ONLY | |
250 | && n != EVP_KDF_HKDF_MODE_EXPAND_ONLY) { | |
251 | ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_MODE); | |
252 | return 0; | |
253 | } | |
254 | ctx->mode = n; | |
255 | } else { | |
256 | ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_MODE); | |
257 | return 0; | |
258 | } | |
259 | } | |
260 | ||
261 | if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_KEY)) != NULL) { | |
262 | OPENSSL_clear_free(ctx->key, ctx->key_len); | |
263 | ctx->key = NULL; | |
264 | if (!OSSL_PARAM_get_octet_string(p, (void **)&ctx->key, 0, | |
265 | &ctx->key_len)) | |
266 | return 0; | |
267 | } | |
268 | ||
269 | if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SALT)) != NULL) { | |
270 | if (p->data_size != 0 && p->data != NULL) { | |
271 | OPENSSL_free(ctx->salt); | |
272 | ctx->salt = NULL; | |
273 | if (!OSSL_PARAM_get_octet_string(p, (void **)&ctx->salt, 0, | |
274 | &ctx->salt_len)) | |
275 | return 0; | |
276 | } | |
277 | } | |
f7d998a2 P |
278 | |
279 | return 1; | |
280 | } | |
281 | ||
282 | static int kdf_hkdf_set_ctx_params(void *vctx, const OSSL_PARAM params[]) | |
283 | { | |
f7d998a2 P |
284 | KDF_HKDF *ctx = vctx; |
285 | ||
286 | if (params == NULL) | |
287 | return 1; | |
288 | ||
289 | if (!hkdf_common_set_ctx_params(ctx, params)) | |
290 | return 0; | |
291 | ||
345b42be P |
292 | if (ossl_param_get1_concat_octet_string(params, OSSL_KDF_PARAM_INFO, |
293 | &ctx->info, &ctx->info_len, | |
294 | HKDF_MAXINFO) == 0) | |
295 | return 0; | |
e8115bd1 | 296 | |
e3405a4a P |
297 | return 1; |
298 | } | |
299 | ||
1e8e5c60 P |
300 | static const OSSL_PARAM *kdf_hkdf_settable_ctx_params(ossl_unused void *ctx, |
301 | ossl_unused void *provctx) | |
e3405a4a P |
302 | { |
303 | static const OSSL_PARAM known_settable_ctx_params[] = { | |
f7d998a2 | 304 | HKDF_COMMON_SETTABLES, |
e3405a4a P |
305 | OSSL_PARAM_octet_string(OSSL_KDF_PARAM_INFO, NULL, 0), |
306 | OSSL_PARAM_END | |
307 | }; | |
308 | return known_settable_ctx_params; | |
309 | } | |
310 | ||
311 | static int kdf_hkdf_get_ctx_params(void *vctx, OSSL_PARAM params[]) | |
312 | { | |
313 | KDF_HKDF *ctx = (KDF_HKDF *)vctx; | |
314 | OSSL_PARAM *p; | |
315 | ||
9d300aa2 SL |
316 | if ((p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_SIZE)) != NULL) { |
317 | size_t sz = kdf_hkdf_size(ctx); | |
318 | ||
319 | if (sz == 0) | |
320 | return 0; | |
321 | return OSSL_PARAM_set_size_t(p, sz); | |
322 | } | |
6b566687 TS |
323 | if ((p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_INFO)) != NULL) { |
324 | if (ctx->info == NULL || ctx->info_len == 0) { | |
325 | p->return_size = 0; | |
326 | return 1; | |
327 | } | |
328 | return OSSL_PARAM_set_octet_string(p, ctx->info, ctx->info_len); | |
329 | } | |
e3405a4a P |
330 | return -2; |
331 | } | |
332 | ||
1e8e5c60 P |
333 | static const OSSL_PARAM *kdf_hkdf_gettable_ctx_params(ossl_unused void *ctx, |
334 | ossl_unused void *provctx) | |
e3405a4a P |
335 | { |
336 | static const OSSL_PARAM known_gettable_ctx_params[] = { | |
337 | OSSL_PARAM_size_t(OSSL_KDF_PARAM_SIZE, NULL), | |
6b566687 | 338 | OSSL_PARAM_octet_string(OSSL_KDF_PARAM_INFO, NULL, 0), |
e3405a4a P |
339 | OSSL_PARAM_END |
340 | }; | |
341 | return known_gettable_ctx_params; | |
342 | } | |
343 | ||
1be63951 | 344 | const OSSL_DISPATCH ossl_kdf_hkdf_functions[] = { |
e3405a4a | 345 | { OSSL_FUNC_KDF_NEWCTX, (void(*)(void))kdf_hkdf_new }, |
95bd5ff6 | 346 | { OSSL_FUNC_KDF_DUPCTX, (void(*)(void))kdf_hkdf_dup }, |
e3405a4a P |
347 | { OSSL_FUNC_KDF_FREECTX, (void(*)(void))kdf_hkdf_free }, |
348 | { OSSL_FUNC_KDF_RESET, (void(*)(void))kdf_hkdf_reset }, | |
349 | { OSSL_FUNC_KDF_DERIVE, (void(*)(void))kdf_hkdf_derive }, | |
350 | { OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS, | |
351 | (void(*)(void))kdf_hkdf_settable_ctx_params }, | |
352 | { OSSL_FUNC_KDF_SET_CTX_PARAMS, (void(*)(void))kdf_hkdf_set_ctx_params }, | |
353 | { OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS, | |
354 | (void(*)(void))kdf_hkdf_gettable_ctx_params }, | |
355 | { OSSL_FUNC_KDF_GET_CTX_PARAMS, (void(*)(void))kdf_hkdf_get_ctx_params }, | |
1e6bd31e | 356 | OSSL_DISPATCH_END |
aacfb134 AG |
357 | }; |
358 | ||
e7018588 DM |
359 | /* |
360 | * Refer to "HMAC-based Extract-and-Expand Key Derivation Function (HKDF)" | |
361 | * Section 2 (https://tools.ietf.org/html/rfc5869#section-2) and | |
362 | * "Cryptographic Extraction and Key Derivation: The HKDF Scheme" | |
363 | * Section 4.2 (https://eprint.iacr.org/2010/264.pdf). | |
364 | * | |
365 | * From the paper: | |
366 | * The scheme HKDF is specified as: | |
367 | * HKDF(XTS, SKM, CTXinfo, L) = K(1) | K(2) | ... | K(t) | |
368 | * | |
369 | * where: | |
370 | * SKM is source key material | |
371 | * XTS is extractor salt (which may be null or constant) | |
372 | * CTXinfo is context information (may be null) | |
373 | * L is the number of key bits to be produced by KDF | |
374 | * k is the output length in bits of the hash function used with HMAC | |
375 | * t = ceil(L/k) | |
376 | * the value K(t) is truncated to its first d = L mod k bits. | |
377 | * | |
378 | * From RFC 5869: | |
379 | * 2.2. Step 1: Extract | |
380 | * HKDF-Extract(salt, IKM) -> PRK | |
381 | * 2.3. Step 2: Expand | |
382 | * HKDF-Expand(PRK, info, L) -> OKM | |
383 | */ | |
0a8a6afd | 384 | static int HKDF(OSSL_LIB_CTX *libctx, const EVP_MD *evp_md, |
5a285add | 385 | const unsigned char *salt, size_t salt_len, |
e7018588 | 386 | const unsigned char *ikm, size_t ikm_len, |
5a285add DM |
387 | const unsigned char *info, size_t info_len, |
388 | unsigned char *okm, size_t okm_len) | |
aacfb134 AG |
389 | { |
390 | unsigned char prk[EVP_MAX_MD_SIZE]; | |
97cc9c9b SL |
391 | int ret, sz; |
392 | size_t prk_len; | |
393 | ||
ed576acd | 394 | sz = EVP_MD_get_size(evp_md); |
97cc9c9b SL |
395 | if (sz < 0) |
396 | return 0; | |
397 | prk_len = (size_t)sz; | |
aacfb134 | 398 | |
e7018588 | 399 | /* Step 1: HKDF-Extract(salt, IKM) -> PRK */ |
0a8a6afd DDO |
400 | if (!HKDF_Extract(libctx, evp_md, |
401 | salt, salt_len, ikm, ikm_len, prk, prk_len)) | |
5a285add | 402 | return 0; |
aacfb134 | 403 | |
e7018588 | 404 | /* Step 2: HKDF-Expand(PRK, info, L) -> OKM */ |
d2139cf8 MC |
405 | ret = HKDF_Expand(evp_md, prk, prk_len, info, info_len, okm, okm_len); |
406 | OPENSSL_cleanse(prk, sizeof(prk)); | |
407 | ||
408 | return ret; | |
aacfb134 AG |
409 | } |
410 | ||
e7018588 DM |
411 | /* |
412 | * Refer to "HMAC-based Extract-and-Expand Key Derivation Function (HKDF)" | |
413 | * Section 2.2 (https://tools.ietf.org/html/rfc5869#section-2.2). | |
414 | * | |
415 | * 2.2. Step 1: Extract | |
416 | * | |
417 | * HKDF-Extract(salt, IKM) -> PRK | |
418 | * | |
419 | * Options: | |
420 | * Hash a hash function; HashLen denotes the length of the | |
421 | * hash function output in octets | |
422 | * | |
423 | * Inputs: | |
424 | * salt optional salt value (a non-secret random value); | |
425 | * if not provided, it is set to a string of HashLen zeros. | |
426 | * IKM input keying material | |
427 | * | |
428 | * Output: | |
429 | * PRK a pseudorandom key (of HashLen octets) | |
430 | * | |
431 | * The output PRK is calculated as follows: | |
432 | * | |
433 | * PRK = HMAC-Hash(salt, IKM) | |
434 | */ | |
0a8a6afd | 435 | static int HKDF_Extract(OSSL_LIB_CTX *libctx, const EVP_MD *evp_md, |
5a285add | 436 | const unsigned char *salt, size_t salt_len, |
e7018588 | 437 | const unsigned char *ikm, size_t ikm_len, |
5a285add | 438 | unsigned char *prk, size_t prk_len) |
aacfb134 | 439 | { |
ed576acd | 440 | int sz = EVP_MD_get_size(evp_md); |
97cc9c9b SL |
441 | |
442 | if (sz < 0) | |
443 | return 0; | |
444 | if (prk_len != (size_t)sz) { | |
e3405a4a | 445 | ERR_raise(ERR_LIB_PROV, PROV_R_WRONG_OUTPUT_BUFFER_SIZE); |
5a285add DM |
446 | return 0; |
447 | } | |
e7018588 | 448 | /* calc: PRK = HMAC-Hash(salt, IKM) */ |
0a8a6afd | 449 | return |
ed576acd TM |
450 | EVP_Q_mac(libctx, "HMAC", NULL, EVP_MD_get0_name(evp_md), NULL, salt, |
451 | salt_len, ikm, ikm_len, prk, EVP_MD_get_size(evp_md), NULL) | |
0a8a6afd | 452 | != NULL; |
aacfb134 AG |
453 | } |
454 | ||
e7018588 DM |
455 | /* |
456 | * Refer to "HMAC-based Extract-and-Expand Key Derivation Function (HKDF)" | |
457 | * Section 2.3 (https://tools.ietf.org/html/rfc5869#section-2.3). | |
458 | * | |
459 | * 2.3. Step 2: Expand | |
460 | * | |
461 | * HKDF-Expand(PRK, info, L) -> OKM | |
462 | * | |
463 | * Options: | |
464 | * Hash a hash function; HashLen denotes the length of the | |
465 | * hash function output in octets | |
466 | * | |
467 | * Inputs: | |
468 | * PRK a pseudorandom key of at least HashLen octets | |
469 | * (usually, the output from the extract step) | |
470 | * info optional context and application specific information | |
471 | * (can be a zero-length string) | |
472 | * L length of output keying material in octets | |
473 | * (<= 255*HashLen) | |
474 | * | |
475 | * Output: | |
476 | * OKM output keying material (of L octets) | |
477 | * | |
478 | * The output OKM is calculated as follows: | |
479 | * | |
480 | * N = ceil(L/HashLen) | |
481 | * T = T(1) | T(2) | T(3) | ... | T(N) | |
482 | * OKM = first L octets of T | |
483 | * | |
484 | * where: | |
485 | * T(0) = empty string (zero length) | |
486 | * T(1) = HMAC-Hash(PRK, T(0) | info | 0x01) | |
487 | * T(2) = HMAC-Hash(PRK, T(1) | info | 0x02) | |
488 | * T(3) = HMAC-Hash(PRK, T(2) | info | 0x03) | |
489 | * ... | |
490 | * | |
491 | * (where the constant concatenated to the end of each T(n) is a | |
492 | * single octet.) | |
493 | */ | |
5a285add DM |
494 | static int HKDF_Expand(const EVP_MD *evp_md, |
495 | const unsigned char *prk, size_t prk_len, | |
496 | const unsigned char *info, size_t info_len, | |
497 | unsigned char *okm, size_t okm_len) | |
aacfb134 AG |
498 | { |
499 | HMAC_CTX *hmac; | |
97cc9c9b | 500 | int ret = 0, sz; |
aacfb134 | 501 | unsigned int i; |
aacfb134 | 502 | unsigned char prev[EVP_MAX_MD_SIZE]; |
97cc9c9b SL |
503 | size_t done_len = 0, dig_len, n; |
504 | ||
ed576acd | 505 | sz = EVP_MD_get_size(evp_md); |
97cc9c9b SL |
506 | if (sz <= 0) |
507 | return 0; | |
508 | dig_len = (size_t)sz; | |
5a285add | 509 | |
e7018588 DM |
510 | /* calc: N = ceil(L/HashLen) */ |
511 | n = okm_len / dig_len; | |
aacfb134 AG |
512 | if (okm_len % dig_len) |
513 | n++; | |
514 | ||
d2139cf8 | 515 | if (n > 255 || okm == NULL) |
5a285add | 516 | return 0; |
aacfb134 AG |
517 | |
518 | if ((hmac = HMAC_CTX_new()) == NULL) | |
5a285add | 519 | return 0; |
aacfb134 AG |
520 | |
521 | if (!HMAC_Init_ex(hmac, prk, prk_len, evp_md, NULL)) | |
522 | goto err; | |
523 | ||
524 | for (i = 1; i <= n; i++) { | |
525 | size_t copy_len; | |
526 | const unsigned char ctr = i; | |
527 | ||
e7018588 | 528 | /* calc: T(i) = HMAC-Hash(PRK, T(i - 1) | info | i) */ |
aacfb134 AG |
529 | if (i > 1) { |
530 | if (!HMAC_Init_ex(hmac, NULL, 0, NULL, NULL)) | |
531 | goto err; | |
532 | ||
533 | if (!HMAC_Update(hmac, prev, dig_len)) | |
534 | goto err; | |
535 | } | |
536 | ||
537 | if (!HMAC_Update(hmac, info, info_len)) | |
538 | goto err; | |
539 | ||
540 | if (!HMAC_Update(hmac, &ctr, 1)) | |
541 | goto err; | |
542 | ||
543 | if (!HMAC_Final(hmac, prev, NULL)) | |
544 | goto err; | |
545 | ||
56a51b5a | 546 | copy_len = (dig_len > okm_len - done_len) ? |
aacfb134 AG |
547 | okm_len - done_len : |
548 | dig_len; | |
549 | ||
550 | memcpy(okm + done_len, prev, copy_len); | |
551 | ||
552 | done_len += copy_len; | |
553 | } | |
5a285add | 554 | ret = 1; |
aacfb134 AG |
555 | |
556 | err: | |
64ed55ab | 557 | OPENSSL_cleanse(prev, sizeof(prev)); |
aacfb134 | 558 | HMAC_CTX_free(hmac); |
64ed55ab | 559 | return ret; |
aacfb134 | 560 | } |
f7d998a2 P |
561 | |
562 | /* | |
563 | * TLS uses slight variations of the above and for FIPS validation purposes, | |
564 | * they need to be present here. | |
565 | * Refer to RFC 8446 section 7 for specific details. | |
566 | */ | |
567 | ||
568 | /* | |
569 | * Given a |secret|; a |label| of length |labellen|; and |data| of length | |
570 | * |datalen| (e.g. typically a hash of the handshake messages), derive a new | |
571 | * secret |outlen| bytes long and store it in the location pointed to be |out|. | |
572 | * The |data| value may be zero length. Returns 1 on success and 0 on failure. | |
573 | */ | |
574 | static int prov_tls13_hkdf_expand(const EVP_MD *md, | |
575 | const unsigned char *key, size_t keylen, | |
576 | const unsigned char *prefix, size_t prefixlen, | |
577 | const unsigned char *label, size_t labellen, | |
578 | const unsigned char *data, size_t datalen, | |
579 | unsigned char *out, size_t outlen) | |
580 | { | |
581 | size_t hkdflabellen; | |
582 | unsigned char hkdflabel[HKDF_MAXBUF]; | |
583 | WPACKET pkt; | |
584 | ||
585 | /* | |
586 | * 2 bytes for length of derived secret + 1 byte for length of combined | |
587 | * prefix and label + bytes for the label itself + 1 byte length of hash | |
588 | * + bytes for the hash itself. We've got the maximum the KDF can handle | |
589 | * which should always be sufficient. | |
590 | */ | |
591 | if (!WPACKET_init_static_len(&pkt, hkdflabel, sizeof(hkdflabel), 0) | |
592 | || !WPACKET_put_bytes_u16(&pkt, outlen) | |
593 | || !WPACKET_start_sub_packet_u8(&pkt) | |
594 | || !WPACKET_memcpy(&pkt, prefix, prefixlen) | |
595 | || !WPACKET_memcpy(&pkt, label, labellen) | |
596 | || !WPACKET_close(&pkt) | |
597 | || !WPACKET_sub_memcpy_u8(&pkt, data, (data == NULL) ? 0 : datalen) | |
598 | || !WPACKET_get_total_written(&pkt, &hkdflabellen) | |
599 | || !WPACKET_finish(&pkt)) { | |
600 | WPACKET_cleanup(&pkt); | |
601 | return 0; | |
602 | } | |
603 | ||
604 | return HKDF_Expand(md, key, keylen, hkdflabel, hkdflabellen, | |
605 | out, outlen); | |
606 | } | |
607 | ||
608 | static int prov_tls13_hkdf_generate_secret(OSSL_LIB_CTX *libctx, | |
609 | const EVP_MD *md, | |
610 | const unsigned char *prevsecret, | |
611 | size_t prevsecretlen, | |
612 | const unsigned char *insecret, | |
613 | size_t insecretlen, | |
614 | const unsigned char *prefix, | |
615 | size_t prefixlen, | |
616 | const unsigned char *label, | |
617 | size_t labellen, | |
618 | unsigned char *out, size_t outlen) | |
619 | { | |
620 | size_t mdlen; | |
621 | int ret; | |
622 | unsigned char preextractsec[EVP_MAX_MD_SIZE]; | |
623 | /* Always filled with zeros */ | |
624 | static const unsigned char default_zeros[EVP_MAX_MD_SIZE]; | |
625 | ||
626 | ret = EVP_MD_get_size(md); | |
627 | /* Ensure cast to size_t is safe */ | |
628 | if (ret <= 0) | |
629 | return 0; | |
630 | mdlen = (size_t)ret; | |
631 | ||
632 | if (insecret == NULL) { | |
633 | insecret = default_zeros; | |
634 | insecretlen = mdlen; | |
635 | } | |
636 | if (prevsecret == NULL) { | |
637 | prevsecret = default_zeros; | |
15d6114d | 638 | prevsecretlen = mdlen; |
f7d998a2 P |
639 | } else { |
640 | EVP_MD_CTX *mctx = EVP_MD_CTX_new(); | |
641 | unsigned char hash[EVP_MAX_MD_SIZE]; | |
642 | ||
643 | /* The pre-extract derive step uses a hash of no messages */ | |
644 | if (mctx == NULL | |
645 | || EVP_DigestInit_ex(mctx, md, NULL) <= 0 | |
646 | || EVP_DigestFinal_ex(mctx, hash, NULL) <= 0) { | |
647 | EVP_MD_CTX_free(mctx); | |
648 | return 0; | |
649 | } | |
650 | EVP_MD_CTX_free(mctx); | |
651 | ||
652 | /* Generate the pre-extract secret */ | |
653 | if (!prov_tls13_hkdf_expand(md, prevsecret, mdlen, | |
654 | prefix, prefixlen, label, labellen, | |
655 | hash, mdlen, preextractsec, mdlen)) | |
656 | return 0; | |
657 | prevsecret = preextractsec; | |
658 | prevsecretlen = mdlen; | |
659 | } | |
660 | ||
661 | ret = HKDF_Extract(libctx, md, prevsecret, prevsecretlen, | |
662 | insecret, insecretlen, out, outlen); | |
663 | ||
664 | if (prevsecret == preextractsec) | |
665 | OPENSSL_cleanse(preextractsec, mdlen); | |
666 | return ret; | |
667 | } | |
668 | ||
669 | static int kdf_tls1_3_derive(void *vctx, unsigned char *key, size_t keylen, | |
670 | const OSSL_PARAM params[]) | |
671 | { | |
672 | KDF_HKDF *ctx = (KDF_HKDF *)vctx; | |
673 | const EVP_MD *md; | |
674 | ||
675 | if (!ossl_prov_is_running() || !kdf_tls1_3_set_ctx_params(ctx, params)) | |
676 | return 0; | |
677 | ||
678 | md = ossl_prov_digest_md(&ctx->digest); | |
679 | if (md == NULL) { | |
680 | ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_MESSAGE_DIGEST); | |
681 | return 0; | |
682 | } | |
683 | ||
684 | switch (ctx->mode) { | |
685 | default: | |
686 | return 0; | |
687 | ||
688 | case EVP_KDF_HKDF_MODE_EXTRACT_ONLY: | |
689 | return prov_tls13_hkdf_generate_secret(PROV_LIBCTX_OF(ctx->provctx), | |
690 | md, | |
691 | ctx->salt, ctx->salt_len, | |
692 | ctx->key, ctx->key_len, | |
693 | ctx->prefix, ctx->prefix_len, | |
694 | ctx->label, ctx->label_len, | |
695 | key, keylen); | |
696 | ||
697 | case EVP_KDF_HKDF_MODE_EXPAND_ONLY: | |
698 | return prov_tls13_hkdf_expand(md, ctx->key, ctx->key_len, | |
699 | ctx->prefix, ctx->prefix_len, | |
700 | ctx->label, ctx->label_len, | |
701 | ctx->data, ctx->data_len, | |
702 | key, keylen); | |
703 | } | |
704 | } | |
705 | ||
706 | static int kdf_tls1_3_set_ctx_params(void *vctx, const OSSL_PARAM params[]) | |
707 | { | |
708 | const OSSL_PARAM *p; | |
709 | KDF_HKDF *ctx = vctx; | |
710 | ||
711 | if (params == NULL) | |
712 | return 1; | |
713 | ||
714 | if (!hkdf_common_set_ctx_params(ctx, params)) | |
715 | return 0; | |
716 | ||
717 | if (ctx->mode == EVP_KDF_HKDF_MODE_EXTRACT_AND_EXPAND) { | |
718 | ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_MODE); | |
719 | return 0; | |
720 | } | |
721 | ||
722 | if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_PREFIX)) != NULL) { | |
723 | OPENSSL_free(ctx->prefix); | |
724 | ctx->prefix = NULL; | |
725 | if (!OSSL_PARAM_get_octet_string(p, (void **)&ctx->prefix, 0, | |
726 | &ctx->prefix_len)) | |
727 | return 0; | |
728 | } | |
729 | ||
730 | if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_LABEL)) != NULL) { | |
731 | OPENSSL_free(ctx->label); | |
732 | ctx->label = NULL; | |
733 | if (!OSSL_PARAM_get_octet_string(p, (void **)&ctx->label, 0, | |
734 | &ctx->label_len)) | |
735 | return 0; | |
736 | } | |
737 | ||
738 | OPENSSL_clear_free(ctx->data, ctx->data_len); | |
739 | ctx->data = NULL; | |
740 | if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_DATA)) != NULL | |
741 | && !OSSL_PARAM_get_octet_string(p, (void **)&ctx->data, 0, | |
742 | &ctx->data_len)) | |
743 | return 0; | |
744 | return 1; | |
745 | } | |
746 | ||
747 | static const OSSL_PARAM *kdf_tls1_3_settable_ctx_params(ossl_unused void *ctx, | |
748 | ossl_unused void *provctx) | |
749 | { | |
750 | static const OSSL_PARAM known_settable_ctx_params[] = { | |
751 | HKDF_COMMON_SETTABLES, | |
752 | OSSL_PARAM_octet_string(OSSL_KDF_PARAM_PREFIX, NULL, 0), | |
753 | OSSL_PARAM_octet_string(OSSL_KDF_PARAM_LABEL, NULL, 0), | |
754 | OSSL_PARAM_octet_string(OSSL_KDF_PARAM_DATA, NULL, 0), | |
755 | OSSL_PARAM_END | |
756 | }; | |
757 | return known_settable_ctx_params; | |
758 | } | |
759 | ||
760 | const OSSL_DISPATCH ossl_kdf_tls1_3_kdf_functions[] = { | |
761 | { OSSL_FUNC_KDF_NEWCTX, (void(*)(void))kdf_hkdf_new }, | |
95bd5ff6 | 762 | { OSSL_FUNC_KDF_DUPCTX, (void(*)(void))kdf_hkdf_dup }, |
f7d998a2 P |
763 | { OSSL_FUNC_KDF_FREECTX, (void(*)(void))kdf_hkdf_free }, |
764 | { OSSL_FUNC_KDF_RESET, (void(*)(void))kdf_hkdf_reset }, | |
765 | { OSSL_FUNC_KDF_DERIVE, (void(*)(void))kdf_tls1_3_derive }, | |
766 | { OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS, | |
767 | (void(*)(void))kdf_tls1_3_settable_ctx_params }, | |
768 | { OSSL_FUNC_KDF_SET_CTX_PARAMS, (void(*)(void))kdf_tls1_3_set_ctx_params }, | |
769 | { OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS, | |
770 | (void(*)(void))kdf_hkdf_gettable_ctx_params }, | |
771 | { OSSL_FUNC_KDF_GET_CTX_PARAMS, (void(*)(void))kdf_hkdf_get_ctx_params }, | |
1e6bd31e | 772 | OSSL_DISPATCH_END |
f7d998a2 | 773 | }; |