xref: /freebsd/crypto/openssl/providers/implementations/kdfs/hkdf.c (revision e7be843b4a162e68651d3911f0357ed464915629)
1b077aed3SPierre Pronchery /*
2*e7be843bSPierre Pronchery  * Copyright 2016-2025 The OpenSSL Project Authors. All Rights Reserved.
3b077aed3SPierre Pronchery  *
4b077aed3SPierre Pronchery  * Licensed under the Apache License 2.0 (the "License").  You may not use
5b077aed3SPierre Pronchery  * this file except in compliance with the License.  You can obtain a copy
6b077aed3SPierre Pronchery  * in the file LICENSE in the source distribution or at
7b077aed3SPierre Pronchery  * https://www.openssl.org/source/license.html
8b077aed3SPierre Pronchery  */
9b077aed3SPierre Pronchery 
10b077aed3SPierre Pronchery /*
11b077aed3SPierre Pronchery  * HMAC low level APIs are deprecated for public use, but still ok for internal
12b077aed3SPierre Pronchery  * use.
13b077aed3SPierre Pronchery  */
14b077aed3SPierre Pronchery #include "internal/deprecated.h"
15b077aed3SPierre Pronchery 
16b077aed3SPierre Pronchery #include <stdlib.h>
17b077aed3SPierre Pronchery #include <stdarg.h>
18b077aed3SPierre Pronchery #include <string.h>
19b077aed3SPierre Pronchery #include <openssl/hmac.h>
20b077aed3SPierre Pronchery #include <openssl/evp.h>
21b077aed3SPierre Pronchery #include <openssl/kdf.h>
22b077aed3SPierre Pronchery #include <openssl/core_names.h>
23b077aed3SPierre Pronchery #include <openssl/proverr.h>
24b077aed3SPierre Pronchery #include "internal/cryptlib.h"
25b077aed3SPierre Pronchery #include "internal/numbers.h"
26b077aed3SPierre Pronchery #include "internal/packet.h"
27b077aed3SPierre Pronchery #include "crypto/evp.h"
28b077aed3SPierre Pronchery #include "prov/provider_ctx.h"
29b077aed3SPierre Pronchery #include "prov/providercommon.h"
30b077aed3SPierre Pronchery #include "prov/implementations.h"
31b077aed3SPierre Pronchery #include "prov/provider_util.h"
32*e7be843bSPierre Pronchery #include "prov/securitycheck.h"
33*e7be843bSPierre Pronchery #include "internal/e_os.h"
34*e7be843bSPierre Pronchery #include "internal/params.h"
35b077aed3SPierre Pronchery 
36b077aed3SPierre Pronchery #define HKDF_MAXBUF 2048
37b077aed3SPierre Pronchery #define HKDF_MAXINFO (32*1024)
38b077aed3SPierre Pronchery 
39b077aed3SPierre Pronchery static OSSL_FUNC_kdf_newctx_fn kdf_hkdf_new;
40*e7be843bSPierre Pronchery static OSSL_FUNC_kdf_dupctx_fn kdf_hkdf_dup;
41b077aed3SPierre Pronchery static OSSL_FUNC_kdf_freectx_fn kdf_hkdf_free;
42b077aed3SPierre Pronchery static OSSL_FUNC_kdf_reset_fn kdf_hkdf_reset;
43b077aed3SPierre Pronchery static OSSL_FUNC_kdf_derive_fn kdf_hkdf_derive;
44b077aed3SPierre Pronchery static OSSL_FUNC_kdf_settable_ctx_params_fn kdf_hkdf_settable_ctx_params;
45b077aed3SPierre Pronchery static OSSL_FUNC_kdf_set_ctx_params_fn kdf_hkdf_set_ctx_params;
46b077aed3SPierre Pronchery static OSSL_FUNC_kdf_gettable_ctx_params_fn kdf_hkdf_gettable_ctx_params;
47b077aed3SPierre Pronchery static OSSL_FUNC_kdf_get_ctx_params_fn kdf_hkdf_get_ctx_params;
48b077aed3SPierre Pronchery static OSSL_FUNC_kdf_derive_fn kdf_tls1_3_derive;
49b077aed3SPierre Pronchery static OSSL_FUNC_kdf_settable_ctx_params_fn kdf_tls1_3_settable_ctx_params;
50b077aed3SPierre Pronchery static OSSL_FUNC_kdf_set_ctx_params_fn kdf_tls1_3_set_ctx_params;
51*e7be843bSPierre Pronchery static OSSL_FUNC_kdf_gettable_ctx_params_fn kdf_tls1_3_gettable_ctx_params;
52*e7be843bSPierre Pronchery static OSSL_FUNC_kdf_get_ctx_params_fn kdf_tls1_3_get_ctx_params;
53b077aed3SPierre Pronchery 
54b077aed3SPierre Pronchery static int HKDF(OSSL_LIB_CTX *libctx, const EVP_MD *evp_md,
55b077aed3SPierre Pronchery                 const unsigned char *salt, size_t salt_len,
56b077aed3SPierre Pronchery                 const unsigned char *key, size_t key_len,
57b077aed3SPierre Pronchery                 const unsigned char *info, size_t info_len,
58b077aed3SPierre Pronchery                 unsigned char *okm, size_t okm_len);
59b077aed3SPierre Pronchery static int HKDF_Extract(OSSL_LIB_CTX *libctx, const EVP_MD *evp_md,
60b077aed3SPierre Pronchery                         const unsigned char *salt, size_t salt_len,
61b077aed3SPierre Pronchery                         const unsigned char *ikm, size_t ikm_len,
62b077aed3SPierre Pronchery                         unsigned char *prk, size_t prk_len);
63b077aed3SPierre Pronchery static int HKDF_Expand(const EVP_MD *evp_md,
64b077aed3SPierre Pronchery                        const unsigned char *prk, size_t prk_len,
65b077aed3SPierre Pronchery                        const unsigned char *info, size_t info_len,
66b077aed3SPierre Pronchery                        unsigned char *okm, size_t okm_len);
67b077aed3SPierre Pronchery 
68b077aed3SPierre Pronchery /* Settable context parameters that are common across HKDF and the TLS KDF */
69b077aed3SPierre Pronchery #define HKDF_COMMON_SETTABLES                                       \
70b077aed3SPierre Pronchery     OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_MODE, NULL, 0),           \
71b077aed3SPierre Pronchery     OSSL_PARAM_int(OSSL_KDF_PARAM_MODE, NULL),                      \
72b077aed3SPierre Pronchery     OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_PROPERTIES, NULL, 0),     \
73b077aed3SPierre Pronchery     OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_DIGEST, NULL, 0),         \
74b077aed3SPierre Pronchery     OSSL_PARAM_octet_string(OSSL_KDF_PARAM_KEY, NULL, 0),           \
75b077aed3SPierre Pronchery     OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SALT, NULL, 0)
76b077aed3SPierre Pronchery 
77*e7be843bSPierre Pronchery /* Gettable context parameters that are common across HKDF and the TLS KDF */
78*e7be843bSPierre Pronchery #define HKDF_COMMON_GETTABLES                                       \
79*e7be843bSPierre Pronchery     OSSL_PARAM_size_t(OSSL_KDF_PARAM_SIZE, NULL),                   \
80*e7be843bSPierre Pronchery     OSSL_PARAM_octet_string(OSSL_KDF_PARAM_INFO, NULL, 0)
81*e7be843bSPierre Pronchery 
82b077aed3SPierre Pronchery typedef struct {
83b077aed3SPierre Pronchery     void *provctx;
84b077aed3SPierre Pronchery     int mode;
85b077aed3SPierre Pronchery     PROV_DIGEST digest;
86b077aed3SPierre Pronchery     unsigned char *salt;
87b077aed3SPierre Pronchery     size_t salt_len;
88b077aed3SPierre Pronchery     unsigned char *key;
89b077aed3SPierre Pronchery     size_t key_len;
90b077aed3SPierre Pronchery     unsigned char *prefix;
91b077aed3SPierre Pronchery     size_t prefix_len;
92b077aed3SPierre Pronchery     unsigned char *label;
93b077aed3SPierre Pronchery     size_t label_len;
94b077aed3SPierre Pronchery     unsigned char *data;
95b077aed3SPierre Pronchery     size_t data_len;
96b077aed3SPierre Pronchery     unsigned char *info;
97b077aed3SPierre Pronchery     size_t info_len;
98*e7be843bSPierre Pronchery     OSSL_FIPS_IND_DECLARE
99b077aed3SPierre Pronchery } KDF_HKDF;
100b077aed3SPierre Pronchery 
kdf_hkdf_new(void * provctx)101b077aed3SPierre Pronchery static void *kdf_hkdf_new(void *provctx)
102b077aed3SPierre Pronchery {
103b077aed3SPierre Pronchery     KDF_HKDF *ctx;
104b077aed3SPierre Pronchery 
105b077aed3SPierre Pronchery     if (!ossl_prov_is_running())
106b077aed3SPierre Pronchery         return NULL;
107b077aed3SPierre Pronchery 
108*e7be843bSPierre Pronchery     if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) != NULL) {
109b077aed3SPierre Pronchery         ctx->provctx = provctx;
110*e7be843bSPierre Pronchery         OSSL_FIPS_IND_INIT(ctx)
111*e7be843bSPierre Pronchery     }
112b077aed3SPierre Pronchery     return ctx;
113b077aed3SPierre Pronchery }
114b077aed3SPierre Pronchery 
kdf_hkdf_free(void * vctx)115b077aed3SPierre Pronchery static void kdf_hkdf_free(void *vctx)
116b077aed3SPierre Pronchery {
117b077aed3SPierre Pronchery     KDF_HKDF *ctx = (KDF_HKDF *)vctx;
118b077aed3SPierre Pronchery 
119b077aed3SPierre Pronchery     if (ctx != NULL) {
120b077aed3SPierre Pronchery         kdf_hkdf_reset(ctx);
121b077aed3SPierre Pronchery         OPENSSL_free(ctx);
122b077aed3SPierre Pronchery     }
123b077aed3SPierre Pronchery }
124b077aed3SPierre Pronchery 
kdf_hkdf_reset(void * vctx)125b077aed3SPierre Pronchery static void kdf_hkdf_reset(void *vctx)
126b077aed3SPierre Pronchery {
127b077aed3SPierre Pronchery     KDF_HKDF *ctx = (KDF_HKDF *)vctx;
128b077aed3SPierre Pronchery     void *provctx = ctx->provctx;
129b077aed3SPierre Pronchery 
130b077aed3SPierre Pronchery     ossl_prov_digest_reset(&ctx->digest);
131*e7be843bSPierre Pronchery #ifdef OPENSSL_PEDANTIC_ZEROIZATION
132*e7be843bSPierre Pronchery     OPENSSL_clear_free(ctx->salt, ctx->salt_len);
133*e7be843bSPierre Pronchery #else
134b077aed3SPierre Pronchery     OPENSSL_free(ctx->salt);
135*e7be843bSPierre Pronchery #endif
136b077aed3SPierre Pronchery     OPENSSL_free(ctx->prefix);
137b077aed3SPierre Pronchery     OPENSSL_free(ctx->label);
138b077aed3SPierre Pronchery     OPENSSL_clear_free(ctx->data, ctx->data_len);
139b077aed3SPierre Pronchery     OPENSSL_clear_free(ctx->key, ctx->key_len);
140b077aed3SPierre Pronchery     OPENSSL_clear_free(ctx->info, ctx->info_len);
141b077aed3SPierre Pronchery     memset(ctx, 0, sizeof(*ctx));
142b077aed3SPierre Pronchery     ctx->provctx = provctx;
143b077aed3SPierre Pronchery }
144b077aed3SPierre Pronchery 
kdf_hkdf_dup(void * vctx)145*e7be843bSPierre Pronchery static void *kdf_hkdf_dup(void *vctx)
146*e7be843bSPierre Pronchery {
147*e7be843bSPierre Pronchery     const KDF_HKDF *src = (const KDF_HKDF *)vctx;
148*e7be843bSPierre Pronchery     KDF_HKDF *dest;
149*e7be843bSPierre Pronchery 
150*e7be843bSPierre Pronchery     dest = kdf_hkdf_new(src->provctx);
151*e7be843bSPierre Pronchery     if (dest != NULL) {
152*e7be843bSPierre Pronchery         if (!ossl_prov_memdup(src->salt, src->salt_len, &dest->salt,
153*e7be843bSPierre Pronchery                               &dest->salt_len)
154*e7be843bSPierre Pronchery                 || !ossl_prov_memdup(src->key, src->key_len,
155*e7be843bSPierre Pronchery                                      &dest->key , &dest->key_len)
156*e7be843bSPierre Pronchery                 || !ossl_prov_memdup(src->prefix, src->prefix_len,
157*e7be843bSPierre Pronchery                                      &dest->prefix, &dest->prefix_len)
158*e7be843bSPierre Pronchery                 || !ossl_prov_memdup(src->label, src->label_len,
159*e7be843bSPierre Pronchery                                      &dest->label, &dest->label_len)
160*e7be843bSPierre Pronchery                 || !ossl_prov_memdup(src->data, src->data_len,
161*e7be843bSPierre Pronchery                                      &dest->data, &dest->data_len)
162*e7be843bSPierre Pronchery                 || !ossl_prov_memdup(src->info, src->info_len,
163*e7be843bSPierre Pronchery                                      &dest->info, &dest->info_len)
164*e7be843bSPierre Pronchery                 || !ossl_prov_digest_copy(&dest->digest, &src->digest))
165*e7be843bSPierre Pronchery             goto err;
166*e7be843bSPierre Pronchery         dest->mode = src->mode;
167*e7be843bSPierre Pronchery         OSSL_FIPS_IND_COPY(dest, src)
168*e7be843bSPierre Pronchery     }
169*e7be843bSPierre Pronchery     return dest;
170*e7be843bSPierre Pronchery 
171*e7be843bSPierre Pronchery  err:
172*e7be843bSPierre Pronchery     kdf_hkdf_free(dest);
173*e7be843bSPierre Pronchery     return NULL;
174*e7be843bSPierre Pronchery }
175*e7be843bSPierre Pronchery 
kdf_hkdf_size(KDF_HKDF * ctx)176b077aed3SPierre Pronchery static size_t kdf_hkdf_size(KDF_HKDF *ctx)
177b077aed3SPierre Pronchery {
178b077aed3SPierre Pronchery     int sz;
179b077aed3SPierre Pronchery     const EVP_MD *md = ossl_prov_digest_md(&ctx->digest);
180b077aed3SPierre Pronchery 
181b077aed3SPierre Pronchery     if (ctx->mode != EVP_KDF_HKDF_MODE_EXTRACT_ONLY)
182b077aed3SPierre Pronchery         return SIZE_MAX;
183b077aed3SPierre Pronchery 
184b077aed3SPierre Pronchery     if (md == NULL) {
185b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_MESSAGE_DIGEST);
186b077aed3SPierre Pronchery         return 0;
187b077aed3SPierre Pronchery     }
188b077aed3SPierre Pronchery     sz = EVP_MD_get_size(md);
189*e7be843bSPierre Pronchery     if (sz <= 0)
190b077aed3SPierre Pronchery         return 0;
191b077aed3SPierre Pronchery 
192b077aed3SPierre Pronchery     return sz;
193b077aed3SPierre Pronchery }
194b077aed3SPierre Pronchery 
195*e7be843bSPierre Pronchery #ifdef FIPS_MODULE
fips_hkdf_key_check_passed(KDF_HKDF * ctx)196*e7be843bSPierre Pronchery static int fips_hkdf_key_check_passed(KDF_HKDF *ctx)
197*e7be843bSPierre Pronchery {
198*e7be843bSPierre Pronchery     OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(ctx->provctx);
199*e7be843bSPierre Pronchery     int key_approved = ossl_kdf_check_key_size(ctx->key_len);
200*e7be843bSPierre Pronchery 
201*e7be843bSPierre Pronchery     if (!key_approved) {
202*e7be843bSPierre Pronchery         if (!OSSL_FIPS_IND_ON_UNAPPROVED(ctx, OSSL_FIPS_IND_SETTABLE0,
203*e7be843bSPierre Pronchery                                          libctx, "HKDF", "Key size",
204*e7be843bSPierre Pronchery                                          ossl_fips_config_hkdf_key_check)) {
205*e7be843bSPierre Pronchery             ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
206*e7be843bSPierre Pronchery             return 0;
207*e7be843bSPierre Pronchery         }
208*e7be843bSPierre Pronchery     }
209*e7be843bSPierre Pronchery     return 1;
210*e7be843bSPierre Pronchery }
211*e7be843bSPierre Pronchery #endif
212*e7be843bSPierre Pronchery 
kdf_hkdf_derive(void * vctx,unsigned char * key,size_t keylen,const OSSL_PARAM params[])213b077aed3SPierre Pronchery static int kdf_hkdf_derive(void *vctx, unsigned char *key, size_t keylen,
214b077aed3SPierre Pronchery                            const OSSL_PARAM params[])
215b077aed3SPierre Pronchery {
216b077aed3SPierre Pronchery     KDF_HKDF *ctx = (KDF_HKDF *)vctx;
217b077aed3SPierre Pronchery     OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(ctx->provctx);
218b077aed3SPierre Pronchery     const EVP_MD *md;
219b077aed3SPierre Pronchery 
220b077aed3SPierre Pronchery     if (!ossl_prov_is_running() || !kdf_hkdf_set_ctx_params(ctx, params))
221b077aed3SPierre Pronchery         return 0;
222b077aed3SPierre Pronchery 
223b077aed3SPierre Pronchery     md = ossl_prov_digest_md(&ctx->digest);
224b077aed3SPierre Pronchery     if (md == NULL) {
225b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_MESSAGE_DIGEST);
226b077aed3SPierre Pronchery         return 0;
227b077aed3SPierre Pronchery     }
228b077aed3SPierre Pronchery     if (ctx->key == NULL) {
229b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_KEY);
230b077aed3SPierre Pronchery         return 0;
231b077aed3SPierre Pronchery     }
232b077aed3SPierre Pronchery     if (keylen == 0) {
233b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
234b077aed3SPierre Pronchery         return 0;
235b077aed3SPierre Pronchery     }
236b077aed3SPierre Pronchery 
237b077aed3SPierre Pronchery     switch (ctx->mode) {
238b077aed3SPierre Pronchery     case EVP_KDF_HKDF_MODE_EXTRACT_AND_EXPAND:
239b077aed3SPierre Pronchery     default:
240b077aed3SPierre Pronchery         return HKDF(libctx, md, ctx->salt, ctx->salt_len,
241b077aed3SPierre Pronchery                     ctx->key, ctx->key_len, ctx->info, ctx->info_len, key, keylen);
242b077aed3SPierre Pronchery 
243b077aed3SPierre Pronchery     case EVP_KDF_HKDF_MODE_EXTRACT_ONLY:
244b077aed3SPierre Pronchery         return HKDF_Extract(libctx, md, ctx->salt, ctx->salt_len,
245b077aed3SPierre Pronchery                             ctx->key, ctx->key_len, key, keylen);
246b077aed3SPierre Pronchery 
247b077aed3SPierre Pronchery     case EVP_KDF_HKDF_MODE_EXPAND_ONLY:
248b077aed3SPierre Pronchery         return HKDF_Expand(md, ctx->key, ctx->key_len, ctx->info,
249b077aed3SPierre Pronchery                            ctx->info_len, key, keylen);
250b077aed3SPierre Pronchery     }
251b077aed3SPierre Pronchery }
252b077aed3SPierre Pronchery 
hkdf_common_set_ctx_params(KDF_HKDF * ctx,const OSSL_PARAM params[])253b077aed3SPierre Pronchery static int hkdf_common_set_ctx_params(KDF_HKDF *ctx, const OSSL_PARAM params[])
254b077aed3SPierre Pronchery {
255b077aed3SPierre Pronchery     OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(ctx->provctx);
256b077aed3SPierre Pronchery     const OSSL_PARAM *p;
257b077aed3SPierre Pronchery     int n;
258b077aed3SPierre Pronchery 
259*e7be843bSPierre Pronchery     if (ossl_param_is_empty(params))
260b077aed3SPierre Pronchery         return 1;
261b077aed3SPierre Pronchery 
262*e7be843bSPierre Pronchery     if (OSSL_PARAM_locate_const(params, OSSL_ALG_PARAM_DIGEST) != NULL) {
263*e7be843bSPierre Pronchery         const EVP_MD *md = NULL;
264*e7be843bSPierre Pronchery 
265b077aed3SPierre Pronchery         if (!ossl_prov_digest_load_from_params(&ctx->digest, params, libctx))
266b077aed3SPierre Pronchery             return 0;
267b077aed3SPierre Pronchery 
268*e7be843bSPierre Pronchery         md = ossl_prov_digest_md(&ctx->digest);
269*e7be843bSPierre Pronchery         if (EVP_MD_xof(md)) {
270*e7be843bSPierre Pronchery             ERR_raise(ERR_LIB_PROV, PROV_R_XOF_DIGESTS_NOT_ALLOWED);
271*e7be843bSPierre Pronchery             return 0;
272*e7be843bSPierre Pronchery         }
273*e7be843bSPierre Pronchery     }
274*e7be843bSPierre Pronchery 
275b077aed3SPierre Pronchery     if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_MODE)) != NULL) {
276b077aed3SPierre Pronchery         if (p->data_type == OSSL_PARAM_UTF8_STRING) {
277b077aed3SPierre Pronchery             if (OPENSSL_strcasecmp(p->data, "EXTRACT_AND_EXPAND") == 0) {
278b077aed3SPierre Pronchery                 ctx->mode = EVP_KDF_HKDF_MODE_EXTRACT_AND_EXPAND;
279b077aed3SPierre Pronchery             } else if (OPENSSL_strcasecmp(p->data, "EXTRACT_ONLY") == 0) {
280b077aed3SPierre Pronchery                 ctx->mode = EVP_KDF_HKDF_MODE_EXTRACT_ONLY;
281b077aed3SPierre Pronchery             } else if (OPENSSL_strcasecmp(p->data, "EXPAND_ONLY") == 0) {
282b077aed3SPierre Pronchery                 ctx->mode = EVP_KDF_HKDF_MODE_EXPAND_ONLY;
283b077aed3SPierre Pronchery             } else {
284b077aed3SPierre Pronchery                 ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_MODE);
285b077aed3SPierre Pronchery                 return 0;
286b077aed3SPierre Pronchery             }
287b077aed3SPierre Pronchery         } else if (OSSL_PARAM_get_int(p, &n)) {
288b077aed3SPierre Pronchery             if (n != EVP_KDF_HKDF_MODE_EXTRACT_AND_EXPAND
289b077aed3SPierre Pronchery                 && n != EVP_KDF_HKDF_MODE_EXTRACT_ONLY
290b077aed3SPierre Pronchery                 && n != EVP_KDF_HKDF_MODE_EXPAND_ONLY) {
291b077aed3SPierre Pronchery                 ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_MODE);
292b077aed3SPierre Pronchery                 return 0;
293b077aed3SPierre Pronchery             }
294b077aed3SPierre Pronchery             ctx->mode = n;
295b077aed3SPierre Pronchery         } else {
296b077aed3SPierre Pronchery             ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_MODE);
297b077aed3SPierre Pronchery             return 0;
298b077aed3SPierre Pronchery         }
299b077aed3SPierre Pronchery     }
300b077aed3SPierre Pronchery 
301b077aed3SPierre Pronchery     if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_KEY)) != NULL) {
302b077aed3SPierre Pronchery         OPENSSL_clear_free(ctx->key, ctx->key_len);
303b077aed3SPierre Pronchery         ctx->key = NULL;
304b077aed3SPierre Pronchery         if (!OSSL_PARAM_get_octet_string(p, (void **)&ctx->key, 0,
305b077aed3SPierre Pronchery                                          &ctx->key_len))
306b077aed3SPierre Pronchery             return 0;
307b077aed3SPierre Pronchery     }
308b077aed3SPierre Pronchery 
309b077aed3SPierre Pronchery     if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SALT)) != NULL) {
310b077aed3SPierre Pronchery         OPENSSL_free(ctx->salt);
311b077aed3SPierre Pronchery         ctx->salt = NULL;
312b077aed3SPierre Pronchery         if (!OSSL_PARAM_get_octet_string(p, (void **)&ctx->salt, 0,
313b077aed3SPierre Pronchery                                          &ctx->salt_len))
314b077aed3SPierre Pronchery             return 0;
315b077aed3SPierre Pronchery     }
316b077aed3SPierre Pronchery 
317b077aed3SPierre Pronchery     return 1;
318b077aed3SPierre Pronchery }
319b077aed3SPierre Pronchery 
kdf_hkdf_set_ctx_params(void * vctx,const OSSL_PARAM params[])320b077aed3SPierre Pronchery static int kdf_hkdf_set_ctx_params(void *vctx, const OSSL_PARAM params[])
321b077aed3SPierre Pronchery {
322b077aed3SPierre Pronchery     KDF_HKDF *ctx = vctx;
323b077aed3SPierre Pronchery 
324*e7be843bSPierre Pronchery     if (ossl_param_is_empty(params))
325b077aed3SPierre Pronchery         return 1;
326b077aed3SPierre Pronchery 
327*e7be843bSPierre Pronchery     if (!OSSL_FIPS_IND_SET_CTX_PARAM(ctx, OSSL_FIPS_IND_SETTABLE0, params,
328*e7be843bSPierre Pronchery                                      OSSL_KDF_PARAM_FIPS_KEY_CHECK))
329*e7be843bSPierre Pronchery         return 0;
330*e7be843bSPierre Pronchery 
331b077aed3SPierre Pronchery     if (!hkdf_common_set_ctx_params(ctx, params))
332b077aed3SPierre Pronchery         return 0;
333b077aed3SPierre Pronchery 
334*e7be843bSPierre Pronchery     if (ossl_param_get1_concat_octet_string(params, OSSL_KDF_PARAM_INFO,
335*e7be843bSPierre Pronchery                                             &ctx->info, &ctx->info_len,
336*e7be843bSPierre Pronchery                                             HKDF_MAXINFO) == 0)
337b077aed3SPierre Pronchery         return 0;
338b077aed3SPierre Pronchery 
339*e7be843bSPierre Pronchery #ifdef FIPS_MODULE
340*e7be843bSPierre Pronchery     if (OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_KEY) != NULL)
341*e7be843bSPierre Pronchery         if (!fips_hkdf_key_check_passed(ctx))
342b077aed3SPierre Pronchery             return 0;
343*e7be843bSPierre Pronchery #endif
344*e7be843bSPierre Pronchery 
345b077aed3SPierre Pronchery     return 1;
346b077aed3SPierre Pronchery }
347b077aed3SPierre Pronchery 
kdf_hkdf_settable_ctx_params(ossl_unused void * ctx,ossl_unused void * provctx)348b077aed3SPierre Pronchery static const OSSL_PARAM *kdf_hkdf_settable_ctx_params(ossl_unused void *ctx,
349b077aed3SPierre Pronchery                                                       ossl_unused void *provctx)
350b077aed3SPierre Pronchery {
351b077aed3SPierre Pronchery     static const OSSL_PARAM known_settable_ctx_params[] = {
352b077aed3SPierre Pronchery         HKDF_COMMON_SETTABLES,
353b077aed3SPierre Pronchery         OSSL_PARAM_octet_string(OSSL_KDF_PARAM_INFO, NULL, 0),
354*e7be843bSPierre Pronchery         OSSL_FIPS_IND_SETTABLE_CTX_PARAM(OSSL_KDF_PARAM_FIPS_KEY_CHECK)
355b077aed3SPierre Pronchery         OSSL_PARAM_END
356b077aed3SPierre Pronchery     };
357b077aed3SPierre Pronchery     return known_settable_ctx_params;
358b077aed3SPierre Pronchery }
359b077aed3SPierre Pronchery 
hkdf_common_get_ctx_params(KDF_HKDF * ctx,OSSL_PARAM params[])360*e7be843bSPierre Pronchery static int hkdf_common_get_ctx_params(KDF_HKDF *ctx, OSSL_PARAM params[])
361b077aed3SPierre Pronchery {
362b077aed3SPierre Pronchery     OSSL_PARAM *p;
363b077aed3SPierre Pronchery 
364*e7be843bSPierre Pronchery     if (ossl_param_is_empty(params))
365*e7be843bSPierre Pronchery         return 1;
366*e7be843bSPierre Pronchery 
367b077aed3SPierre Pronchery     if ((p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_SIZE)) != NULL) {
368b077aed3SPierre Pronchery         size_t sz = kdf_hkdf_size(ctx);
369b077aed3SPierre Pronchery 
370b077aed3SPierre Pronchery         if (sz == 0)
371b077aed3SPierre Pronchery             return 0;
372*e7be843bSPierre Pronchery         if (!OSSL_PARAM_set_size_t(p, sz))
373*e7be843bSPierre Pronchery             return 0;
374b077aed3SPierre Pronchery     }
375*e7be843bSPierre Pronchery 
37644096ebdSEnji Cooper     if ((p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_INFO)) != NULL) {
377*e7be843bSPierre Pronchery         if (ctx->info == NULL || ctx->info_len == 0)
37844096ebdSEnji Cooper             p->return_size = 0;
379*e7be843bSPierre Pronchery         else if (!OSSL_PARAM_set_octet_string(p, ctx->info, ctx->info_len))
380*e7be843bSPierre Pronchery             return 0;
381*e7be843bSPierre Pronchery     }
382*e7be843bSPierre Pronchery 
38344096ebdSEnji Cooper     return 1;
38444096ebdSEnji Cooper }
385*e7be843bSPierre Pronchery 
kdf_hkdf_get_ctx_params(void * vctx,OSSL_PARAM params[])386*e7be843bSPierre Pronchery static int kdf_hkdf_get_ctx_params(void *vctx, OSSL_PARAM params[])
387*e7be843bSPierre Pronchery {
388*e7be843bSPierre Pronchery     KDF_HKDF *ctx = (KDF_HKDF *)vctx;
389*e7be843bSPierre Pronchery 
390*e7be843bSPierre Pronchery     if (ossl_param_is_empty(params))
391*e7be843bSPierre Pronchery         return 1;
392*e7be843bSPierre Pronchery 
393*e7be843bSPierre Pronchery     if (!hkdf_common_get_ctx_params(ctx, params))
394*e7be843bSPierre Pronchery         return 0;
395*e7be843bSPierre Pronchery 
396*e7be843bSPierre Pronchery     if (!OSSL_FIPS_IND_GET_CTX_PARAM(ctx, params))
397*e7be843bSPierre Pronchery         return 0;
398*e7be843bSPierre Pronchery 
399*e7be843bSPierre Pronchery     return 1;
400b077aed3SPierre Pronchery }
401b077aed3SPierre Pronchery 
kdf_hkdf_gettable_ctx_params(ossl_unused void * ctx,ossl_unused void * provctx)402b077aed3SPierre Pronchery static const OSSL_PARAM *kdf_hkdf_gettable_ctx_params(ossl_unused void *ctx,
403b077aed3SPierre Pronchery                                                       ossl_unused void *provctx)
404b077aed3SPierre Pronchery {
405b077aed3SPierre Pronchery     static const OSSL_PARAM known_gettable_ctx_params[] = {
406*e7be843bSPierre Pronchery         HKDF_COMMON_GETTABLES,
407*e7be843bSPierre Pronchery         OSSL_FIPS_IND_GETTABLE_CTX_PARAM()
408b077aed3SPierre Pronchery         OSSL_PARAM_END
409b077aed3SPierre Pronchery     };
410b077aed3SPierre Pronchery     return known_gettable_ctx_params;
411b077aed3SPierre Pronchery }
412b077aed3SPierre Pronchery 
413b077aed3SPierre Pronchery const OSSL_DISPATCH ossl_kdf_hkdf_functions[] = {
414b077aed3SPierre Pronchery     { OSSL_FUNC_KDF_NEWCTX, (void(*)(void))kdf_hkdf_new },
415*e7be843bSPierre Pronchery     { OSSL_FUNC_KDF_DUPCTX, (void(*)(void))kdf_hkdf_dup },
416b077aed3SPierre Pronchery     { OSSL_FUNC_KDF_FREECTX, (void(*)(void))kdf_hkdf_free },
417b077aed3SPierre Pronchery     { OSSL_FUNC_KDF_RESET, (void(*)(void))kdf_hkdf_reset },
418b077aed3SPierre Pronchery     { OSSL_FUNC_KDF_DERIVE, (void(*)(void))kdf_hkdf_derive },
419b077aed3SPierre Pronchery     { OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS,
420b077aed3SPierre Pronchery       (void(*)(void))kdf_hkdf_settable_ctx_params },
421b077aed3SPierre Pronchery     { OSSL_FUNC_KDF_SET_CTX_PARAMS, (void(*)(void))kdf_hkdf_set_ctx_params },
422b077aed3SPierre Pronchery     { OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS,
423b077aed3SPierre Pronchery       (void(*)(void))kdf_hkdf_gettable_ctx_params },
424b077aed3SPierre Pronchery     { OSSL_FUNC_KDF_GET_CTX_PARAMS, (void(*)(void))kdf_hkdf_get_ctx_params },
425*e7be843bSPierre Pronchery     OSSL_DISPATCH_END
426b077aed3SPierre Pronchery };
427b077aed3SPierre Pronchery 
428b077aed3SPierre Pronchery /*
429b077aed3SPierre Pronchery  * Refer to "HMAC-based Extract-and-Expand Key Derivation Function (HKDF)"
430b077aed3SPierre Pronchery  * Section 2 (https://tools.ietf.org/html/rfc5869#section-2) and
431b077aed3SPierre Pronchery  * "Cryptographic Extraction and Key Derivation: The HKDF Scheme"
432b077aed3SPierre Pronchery  * Section 4.2 (https://eprint.iacr.org/2010/264.pdf).
433b077aed3SPierre Pronchery  *
434b077aed3SPierre Pronchery  * From the paper:
435b077aed3SPierre Pronchery  *   The scheme HKDF is specified as:
436b077aed3SPierre Pronchery  *     HKDF(XTS, SKM, CTXinfo, L) = K(1) | K(2) | ... | K(t)
437b077aed3SPierre Pronchery  *
438b077aed3SPierre Pronchery  *     where:
439b077aed3SPierre Pronchery  *       SKM is source key material
440b077aed3SPierre Pronchery  *       XTS is extractor salt (which may be null or constant)
441b077aed3SPierre Pronchery  *       CTXinfo is context information (may be null)
442b077aed3SPierre Pronchery  *       L is the number of key bits to be produced by KDF
443b077aed3SPierre Pronchery  *       k is the output length in bits of the hash function used with HMAC
444b077aed3SPierre Pronchery  *       t = ceil(L/k)
445b077aed3SPierre Pronchery  *       the value K(t) is truncated to its first d = L mod k bits.
446b077aed3SPierre Pronchery  *
447b077aed3SPierre Pronchery  * From RFC 5869:
448b077aed3SPierre Pronchery  *   2.2.  Step 1: Extract
449b077aed3SPierre Pronchery  *     HKDF-Extract(salt, IKM) -> PRK
450b077aed3SPierre Pronchery  *   2.3.  Step 2: Expand
451b077aed3SPierre Pronchery  *     HKDF-Expand(PRK, info, L) -> OKM
452b077aed3SPierre Pronchery  */
HKDF(OSSL_LIB_CTX * libctx,const EVP_MD * evp_md,const unsigned char * salt,size_t salt_len,const unsigned char * ikm,size_t ikm_len,const unsigned char * info,size_t info_len,unsigned char * okm,size_t okm_len)453b077aed3SPierre Pronchery static int HKDF(OSSL_LIB_CTX *libctx, const EVP_MD *evp_md,
454b077aed3SPierre Pronchery                 const unsigned char *salt, size_t salt_len,
455b077aed3SPierre Pronchery                 const unsigned char *ikm, size_t ikm_len,
456b077aed3SPierre Pronchery                 const unsigned char *info, size_t info_len,
457b077aed3SPierre Pronchery                 unsigned char *okm, size_t okm_len)
458b077aed3SPierre Pronchery {
459b077aed3SPierre Pronchery     unsigned char prk[EVP_MAX_MD_SIZE];
460b077aed3SPierre Pronchery     int ret, sz;
461b077aed3SPierre Pronchery     size_t prk_len;
462b077aed3SPierre Pronchery 
463b077aed3SPierre Pronchery     sz = EVP_MD_get_size(evp_md);
464*e7be843bSPierre Pronchery     if (sz <= 0)
465b077aed3SPierre Pronchery         return 0;
466b077aed3SPierre Pronchery     prk_len = (size_t)sz;
467b077aed3SPierre Pronchery 
468b077aed3SPierre Pronchery     /* Step 1: HKDF-Extract(salt, IKM) -> PRK */
469b077aed3SPierre Pronchery     if (!HKDF_Extract(libctx, evp_md,
470b077aed3SPierre Pronchery                       salt, salt_len, ikm, ikm_len, prk, prk_len))
471b077aed3SPierre Pronchery         return 0;
472b077aed3SPierre Pronchery 
473b077aed3SPierre Pronchery     /* Step 2: HKDF-Expand(PRK, info, L) -> OKM */
474b077aed3SPierre Pronchery     ret = HKDF_Expand(evp_md, prk, prk_len, info, info_len, okm, okm_len);
475b077aed3SPierre Pronchery     OPENSSL_cleanse(prk, sizeof(prk));
476b077aed3SPierre Pronchery 
477b077aed3SPierre Pronchery     return ret;
478b077aed3SPierre Pronchery }
479b077aed3SPierre Pronchery 
480b077aed3SPierre Pronchery /*
481b077aed3SPierre Pronchery  * Refer to "HMAC-based Extract-and-Expand Key Derivation Function (HKDF)"
482b077aed3SPierre Pronchery  * Section 2.2 (https://tools.ietf.org/html/rfc5869#section-2.2).
483b077aed3SPierre Pronchery  *
484b077aed3SPierre Pronchery  * 2.2.  Step 1: Extract
485b077aed3SPierre Pronchery  *
486b077aed3SPierre Pronchery  *   HKDF-Extract(salt, IKM) -> PRK
487b077aed3SPierre Pronchery  *
488b077aed3SPierre Pronchery  *   Options:
489b077aed3SPierre Pronchery  *      Hash     a hash function; HashLen denotes the length of the
490b077aed3SPierre Pronchery  *               hash function output in octets
491b077aed3SPierre Pronchery  *
492b077aed3SPierre Pronchery  *   Inputs:
493b077aed3SPierre Pronchery  *      salt     optional salt value (a non-secret random value);
494b077aed3SPierre Pronchery  *               if not provided, it is set to a string of HashLen zeros.
495b077aed3SPierre Pronchery  *      IKM      input keying material
496b077aed3SPierre Pronchery  *
497b077aed3SPierre Pronchery  *   Output:
498b077aed3SPierre Pronchery  *      PRK      a pseudorandom key (of HashLen octets)
499b077aed3SPierre Pronchery  *
500b077aed3SPierre Pronchery  *   The output PRK is calculated as follows:
501b077aed3SPierre Pronchery  *
502b077aed3SPierre Pronchery  *   PRK = HMAC-Hash(salt, IKM)
503b077aed3SPierre Pronchery  */
HKDF_Extract(OSSL_LIB_CTX * libctx,const EVP_MD * evp_md,const unsigned char * salt,size_t salt_len,const unsigned char * ikm,size_t ikm_len,unsigned char * prk,size_t prk_len)504b077aed3SPierre Pronchery static int HKDF_Extract(OSSL_LIB_CTX *libctx, const EVP_MD *evp_md,
505b077aed3SPierre Pronchery                         const unsigned char *salt, size_t salt_len,
506b077aed3SPierre Pronchery                         const unsigned char *ikm, size_t ikm_len,
507b077aed3SPierre Pronchery                         unsigned char *prk, size_t prk_len)
508b077aed3SPierre Pronchery {
509b077aed3SPierre Pronchery     int sz = EVP_MD_get_size(evp_md);
510b077aed3SPierre Pronchery 
511*e7be843bSPierre Pronchery     if (sz <= 0)
512b077aed3SPierre Pronchery         return 0;
513b077aed3SPierre Pronchery     if (prk_len != (size_t)sz) {
514b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_PROV, PROV_R_WRONG_OUTPUT_BUFFER_SIZE);
515b077aed3SPierre Pronchery         return 0;
516b077aed3SPierre Pronchery     }
517b077aed3SPierre Pronchery     /* calc: PRK = HMAC-Hash(salt, IKM) */
518b077aed3SPierre Pronchery     return
519b077aed3SPierre Pronchery         EVP_Q_mac(libctx, "HMAC", NULL, EVP_MD_get0_name(evp_md), NULL, salt,
520b077aed3SPierre Pronchery                   salt_len, ikm, ikm_len, prk, EVP_MD_get_size(evp_md), NULL)
521b077aed3SPierre Pronchery         != NULL;
522b077aed3SPierre Pronchery }
523b077aed3SPierre Pronchery 
524b077aed3SPierre Pronchery /*
525b077aed3SPierre Pronchery  * Refer to "HMAC-based Extract-and-Expand Key Derivation Function (HKDF)"
526b077aed3SPierre Pronchery  * Section 2.3 (https://tools.ietf.org/html/rfc5869#section-2.3).
527b077aed3SPierre Pronchery  *
528b077aed3SPierre Pronchery  * 2.3.  Step 2: Expand
529b077aed3SPierre Pronchery  *
530b077aed3SPierre Pronchery  *   HKDF-Expand(PRK, info, L) -> OKM
531b077aed3SPierre Pronchery  *
532b077aed3SPierre Pronchery  *   Options:
533b077aed3SPierre Pronchery  *      Hash     a hash function; HashLen denotes the length of the
534b077aed3SPierre Pronchery  *               hash function output in octets
535b077aed3SPierre Pronchery  *
536b077aed3SPierre Pronchery  *   Inputs:
537b077aed3SPierre Pronchery  *      PRK      a pseudorandom key of at least HashLen octets
538b077aed3SPierre Pronchery  *               (usually, the output from the extract step)
539b077aed3SPierre Pronchery  *      info     optional context and application specific information
540b077aed3SPierre Pronchery  *               (can be a zero-length string)
541b077aed3SPierre Pronchery  *      L        length of output keying material in octets
542b077aed3SPierre Pronchery  *               (<= 255*HashLen)
543b077aed3SPierre Pronchery  *
544b077aed3SPierre Pronchery  *   Output:
545b077aed3SPierre Pronchery  *      OKM      output keying material (of L octets)
546b077aed3SPierre Pronchery  *
547b077aed3SPierre Pronchery  *   The output OKM is calculated as follows:
548b077aed3SPierre Pronchery  *
549b077aed3SPierre Pronchery  *   N = ceil(L/HashLen)
550b077aed3SPierre Pronchery  *   T = T(1) | T(2) | T(3) | ... | T(N)
551b077aed3SPierre Pronchery  *   OKM = first L octets of T
552b077aed3SPierre Pronchery  *
553b077aed3SPierre Pronchery  *   where:
554b077aed3SPierre Pronchery  *   T(0) = empty string (zero length)
555b077aed3SPierre Pronchery  *   T(1) = HMAC-Hash(PRK, T(0) | info | 0x01)
556b077aed3SPierre Pronchery  *   T(2) = HMAC-Hash(PRK, T(1) | info | 0x02)
557b077aed3SPierre Pronchery  *   T(3) = HMAC-Hash(PRK, T(2) | info | 0x03)
558b077aed3SPierre Pronchery  *   ...
559b077aed3SPierre Pronchery  *
560b077aed3SPierre Pronchery  *   (where the constant concatenated to the end of each T(n) is a
561b077aed3SPierre Pronchery  *   single octet.)
562b077aed3SPierre Pronchery  */
HKDF_Expand(const EVP_MD * evp_md,const unsigned char * prk,size_t prk_len,const unsigned char * info,size_t info_len,unsigned char * okm,size_t okm_len)563b077aed3SPierre Pronchery static int HKDF_Expand(const EVP_MD *evp_md,
564b077aed3SPierre Pronchery                        const unsigned char *prk, size_t prk_len,
565b077aed3SPierre Pronchery                        const unsigned char *info, size_t info_len,
566b077aed3SPierre Pronchery                        unsigned char *okm, size_t okm_len)
567b077aed3SPierre Pronchery {
568b077aed3SPierre Pronchery     HMAC_CTX *hmac;
569b077aed3SPierre Pronchery     int ret = 0, sz;
570b077aed3SPierre Pronchery     unsigned int i;
571b077aed3SPierre Pronchery     unsigned char prev[EVP_MAX_MD_SIZE];
572b077aed3SPierre Pronchery     size_t done_len = 0, dig_len, n;
573b077aed3SPierre Pronchery 
574b077aed3SPierre Pronchery     sz = EVP_MD_get_size(evp_md);
575b077aed3SPierre Pronchery     if (sz <= 0)
576b077aed3SPierre Pronchery         return 0;
577b077aed3SPierre Pronchery     dig_len = (size_t)sz;
578b077aed3SPierre Pronchery 
579b077aed3SPierre Pronchery     /* calc: N = ceil(L/HashLen) */
580b077aed3SPierre Pronchery     n = okm_len / dig_len;
581b077aed3SPierre Pronchery     if (okm_len % dig_len)
582b077aed3SPierre Pronchery         n++;
583b077aed3SPierre Pronchery 
584b077aed3SPierre Pronchery     if (n > 255 || okm == NULL)
585b077aed3SPierre Pronchery         return 0;
586b077aed3SPierre Pronchery 
587b077aed3SPierre Pronchery     if ((hmac = HMAC_CTX_new()) == NULL)
588b077aed3SPierre Pronchery         return 0;
589b077aed3SPierre Pronchery 
590b077aed3SPierre Pronchery     if (!HMAC_Init_ex(hmac, prk, prk_len, evp_md, NULL))
591b077aed3SPierre Pronchery         goto err;
592b077aed3SPierre Pronchery 
593b077aed3SPierre Pronchery     for (i = 1; i <= n; i++) {
594b077aed3SPierre Pronchery         size_t copy_len;
595b077aed3SPierre Pronchery         const unsigned char ctr = i;
596b077aed3SPierre Pronchery 
597b077aed3SPierre Pronchery         /* calc: T(i) = HMAC-Hash(PRK, T(i - 1) | info | i) */
598b077aed3SPierre Pronchery         if (i > 1) {
599b077aed3SPierre Pronchery             if (!HMAC_Init_ex(hmac, NULL, 0, NULL, NULL))
600b077aed3SPierre Pronchery                 goto err;
601b077aed3SPierre Pronchery 
602b077aed3SPierre Pronchery             if (!HMAC_Update(hmac, prev, dig_len))
603b077aed3SPierre Pronchery                 goto err;
604b077aed3SPierre Pronchery         }
605b077aed3SPierre Pronchery 
606b077aed3SPierre Pronchery         if (!HMAC_Update(hmac, info, info_len))
607b077aed3SPierre Pronchery             goto err;
608b077aed3SPierre Pronchery 
609b077aed3SPierre Pronchery         if (!HMAC_Update(hmac, &ctr, 1))
610b077aed3SPierre Pronchery             goto err;
611b077aed3SPierre Pronchery 
612b077aed3SPierre Pronchery         if (!HMAC_Final(hmac, prev, NULL))
613b077aed3SPierre Pronchery             goto err;
614b077aed3SPierre Pronchery 
615b077aed3SPierre Pronchery         copy_len = (dig_len > okm_len - done_len) ?
616b077aed3SPierre Pronchery                        okm_len - done_len :
617b077aed3SPierre Pronchery                        dig_len;
618b077aed3SPierre Pronchery 
619b077aed3SPierre Pronchery         memcpy(okm + done_len, prev, copy_len);
620b077aed3SPierre Pronchery 
621b077aed3SPierre Pronchery         done_len += copy_len;
622b077aed3SPierre Pronchery     }
623b077aed3SPierre Pronchery     ret = 1;
624b077aed3SPierre Pronchery 
625b077aed3SPierre Pronchery  err:
626b077aed3SPierre Pronchery     OPENSSL_cleanse(prev, sizeof(prev));
627b077aed3SPierre Pronchery     HMAC_CTX_free(hmac);
628b077aed3SPierre Pronchery     return ret;
629b077aed3SPierre Pronchery }
630b077aed3SPierre Pronchery 
631b077aed3SPierre Pronchery /*
632b077aed3SPierre Pronchery  * TLS uses slight variations of the above and for FIPS validation purposes,
633b077aed3SPierre Pronchery  * they need to be present here.
634b077aed3SPierre Pronchery  * Refer to RFC 8446 section 7 for specific details.
635b077aed3SPierre Pronchery  */
636b077aed3SPierre Pronchery 
637b077aed3SPierre Pronchery /*
638b077aed3SPierre Pronchery  * Given a |secret|; a |label| of length |labellen|; and |data| of length
639b077aed3SPierre Pronchery  * |datalen| (e.g. typically a hash of the handshake messages), derive a new
640b077aed3SPierre Pronchery  * secret |outlen| bytes long and store it in the location pointed to be |out|.
641b077aed3SPierre Pronchery  * The |data| value may be zero length. Returns 1 on success and 0 on failure.
642b077aed3SPierre Pronchery  */
prov_tls13_hkdf_expand(const EVP_MD * md,const unsigned char * key,size_t keylen,const unsigned char * prefix,size_t prefixlen,const unsigned char * label,size_t labellen,const unsigned char * data,size_t datalen,unsigned char * out,size_t outlen)643b077aed3SPierre Pronchery static int prov_tls13_hkdf_expand(const EVP_MD *md,
644b077aed3SPierre Pronchery                                   const unsigned char *key, size_t keylen,
645b077aed3SPierre Pronchery                                   const unsigned char *prefix, size_t prefixlen,
646b077aed3SPierre Pronchery                                   const unsigned char *label, size_t labellen,
647b077aed3SPierre Pronchery                                   const unsigned char *data, size_t datalen,
648b077aed3SPierre Pronchery                                   unsigned char *out, size_t outlen)
649b077aed3SPierre Pronchery {
650b077aed3SPierre Pronchery     size_t hkdflabellen;
651b077aed3SPierre Pronchery     unsigned char hkdflabel[HKDF_MAXBUF];
652b077aed3SPierre Pronchery     WPACKET pkt;
653b077aed3SPierre Pronchery 
654b077aed3SPierre Pronchery     /*
655b077aed3SPierre Pronchery      * 2 bytes for length of derived secret + 1 byte for length of combined
656b077aed3SPierre Pronchery      * prefix and label + bytes for the label itself + 1 byte length of hash
657b077aed3SPierre Pronchery      * + bytes for the hash itself.  We've got the maximum the KDF can handle
658b077aed3SPierre Pronchery      * which should always be sufficient.
659b077aed3SPierre Pronchery      */
660b077aed3SPierre Pronchery     if (!WPACKET_init_static_len(&pkt, hkdflabel, sizeof(hkdflabel), 0)
661b077aed3SPierre Pronchery             || !WPACKET_put_bytes_u16(&pkt, outlen)
662b077aed3SPierre Pronchery             || !WPACKET_start_sub_packet_u8(&pkt)
663b077aed3SPierre Pronchery             || !WPACKET_memcpy(&pkt, prefix, prefixlen)
664b077aed3SPierre Pronchery             || !WPACKET_memcpy(&pkt, label, labellen)
665b077aed3SPierre Pronchery             || !WPACKET_close(&pkt)
666b077aed3SPierre Pronchery             || !WPACKET_sub_memcpy_u8(&pkt, data, (data == NULL) ? 0 : datalen)
667b077aed3SPierre Pronchery             || !WPACKET_get_total_written(&pkt, &hkdflabellen)
668b077aed3SPierre Pronchery             || !WPACKET_finish(&pkt)) {
669b077aed3SPierre Pronchery         WPACKET_cleanup(&pkt);
670b077aed3SPierre Pronchery         return 0;
671b077aed3SPierre Pronchery     }
672b077aed3SPierre Pronchery 
673b077aed3SPierre Pronchery     return HKDF_Expand(md, key, keylen, hkdflabel, hkdflabellen,
674b077aed3SPierre Pronchery                        out, outlen);
675b077aed3SPierre Pronchery }
676b077aed3SPierre Pronchery 
prov_tls13_hkdf_generate_secret(OSSL_LIB_CTX * libctx,const EVP_MD * md,const unsigned char * prevsecret,size_t prevsecretlen,const unsigned char * insecret,size_t insecretlen,const unsigned char * prefix,size_t prefixlen,const unsigned char * label,size_t labellen,unsigned char * out,size_t outlen)677b077aed3SPierre Pronchery static int prov_tls13_hkdf_generate_secret(OSSL_LIB_CTX *libctx,
678b077aed3SPierre Pronchery                                            const EVP_MD *md,
679b077aed3SPierre Pronchery                                            const unsigned char *prevsecret,
680b077aed3SPierre Pronchery                                            size_t prevsecretlen,
681b077aed3SPierre Pronchery                                            const unsigned char *insecret,
682b077aed3SPierre Pronchery                                            size_t insecretlen,
683b077aed3SPierre Pronchery                                            const unsigned char *prefix,
684b077aed3SPierre Pronchery                                            size_t prefixlen,
685b077aed3SPierre Pronchery                                            const unsigned char *label,
686b077aed3SPierre Pronchery                                            size_t labellen,
687b077aed3SPierre Pronchery                                            unsigned char *out, size_t outlen)
688b077aed3SPierre Pronchery {
689b077aed3SPierre Pronchery     size_t mdlen;
690b077aed3SPierre Pronchery     int ret;
691b077aed3SPierre Pronchery     unsigned char preextractsec[EVP_MAX_MD_SIZE];
692b077aed3SPierre Pronchery     /* Always filled with zeros */
693b077aed3SPierre Pronchery     static const unsigned char default_zeros[EVP_MAX_MD_SIZE];
694b077aed3SPierre Pronchery 
695b077aed3SPierre Pronchery     ret = EVP_MD_get_size(md);
696b077aed3SPierre Pronchery     /* Ensure cast to size_t is safe */
697b077aed3SPierre Pronchery     if (ret <= 0)
698b077aed3SPierre Pronchery         return 0;
699b077aed3SPierre Pronchery     mdlen = (size_t)ret;
700b077aed3SPierre Pronchery 
701b077aed3SPierre Pronchery     if (insecret == NULL) {
702b077aed3SPierre Pronchery         insecret = default_zeros;
703b077aed3SPierre Pronchery         insecretlen = mdlen;
704b077aed3SPierre Pronchery     }
705b077aed3SPierre Pronchery     if (prevsecret == NULL) {
706b077aed3SPierre Pronchery         prevsecret = default_zeros;
707*e7be843bSPierre Pronchery         prevsecretlen = mdlen;
708b077aed3SPierre Pronchery     } else {
709b077aed3SPierre Pronchery         EVP_MD_CTX *mctx = EVP_MD_CTX_new();
710b077aed3SPierre Pronchery         unsigned char hash[EVP_MAX_MD_SIZE];
711b077aed3SPierre Pronchery 
712b077aed3SPierre Pronchery         /* The pre-extract derive step uses a hash of no messages */
713b077aed3SPierre Pronchery         if (mctx == NULL
714b077aed3SPierre Pronchery                 || EVP_DigestInit_ex(mctx, md, NULL) <= 0
715b077aed3SPierre Pronchery                 || EVP_DigestFinal_ex(mctx, hash, NULL) <= 0) {
716b077aed3SPierre Pronchery             EVP_MD_CTX_free(mctx);
717b077aed3SPierre Pronchery             return 0;
718b077aed3SPierre Pronchery         }
719b077aed3SPierre Pronchery         EVP_MD_CTX_free(mctx);
720b077aed3SPierre Pronchery 
721b077aed3SPierre Pronchery         /* Generate the pre-extract secret */
7220d0c8621SEnji Cooper         if (!prov_tls13_hkdf_expand(md, prevsecret, prevsecretlen,
723b077aed3SPierre Pronchery                                     prefix, prefixlen, label, labellen,
724b077aed3SPierre Pronchery                                     hash, mdlen, preextractsec, mdlen))
725b077aed3SPierre Pronchery             return 0;
726b077aed3SPierre Pronchery         prevsecret = preextractsec;
727b077aed3SPierre Pronchery         prevsecretlen = mdlen;
728b077aed3SPierre Pronchery     }
729b077aed3SPierre Pronchery 
730b077aed3SPierre Pronchery     ret = HKDF_Extract(libctx, md, prevsecret, prevsecretlen,
731b077aed3SPierre Pronchery                        insecret, insecretlen, out, outlen);
732b077aed3SPierre Pronchery 
733b077aed3SPierre Pronchery     if (prevsecret == preextractsec)
734b077aed3SPierre Pronchery         OPENSSL_cleanse(preextractsec, mdlen);
735b077aed3SPierre Pronchery     return ret;
736b077aed3SPierre Pronchery }
737b077aed3SPierre Pronchery 
738*e7be843bSPierre Pronchery #ifdef FIPS_MODULE
fips_tls1_3_digest_check_passed(KDF_HKDF * ctx,const EVP_MD * md)739*e7be843bSPierre Pronchery static int fips_tls1_3_digest_check_passed(KDF_HKDF *ctx, const EVP_MD *md)
740*e7be843bSPierre Pronchery {
741*e7be843bSPierre Pronchery     OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(ctx->provctx);
742*e7be843bSPierre Pronchery     /*
743*e7be843bSPierre Pronchery      * Perform digest check
744*e7be843bSPierre Pronchery      *
745*e7be843bSPierre Pronchery      * According to RFC 8446 appendix B.4, the valid hash functions are
746*e7be843bSPierre Pronchery      * specified in FIPS 180-4. However, it only lists SHA2-256 and SHA2-384 in
747*e7be843bSPierre Pronchery      * the table. ACVP also only lists the same set of hash functions.
748*e7be843bSPierre Pronchery      */
749*e7be843bSPierre Pronchery     int digest_unapproved = !EVP_MD_is_a(md, SN_sha256)
750*e7be843bSPierre Pronchery         && !EVP_MD_is_a(md, SN_sha384);
751*e7be843bSPierre Pronchery 
752*e7be843bSPierre Pronchery     if (digest_unapproved) {
753*e7be843bSPierre Pronchery         if (!OSSL_FIPS_IND_ON_UNAPPROVED(ctx, OSSL_FIPS_IND_SETTABLE0,
754*e7be843bSPierre Pronchery                                          libctx, "TLS13 KDF", "Digest",
755*e7be843bSPierre Pronchery                                          ossl_fips_config_tls13_kdf_digest_check)) {
756*e7be843bSPierre Pronchery             ERR_raise(ERR_LIB_PROV, PROV_R_DIGEST_NOT_ALLOWED);
757*e7be843bSPierre Pronchery             return 0;
758*e7be843bSPierre Pronchery         }
759*e7be843bSPierre Pronchery     }
760*e7be843bSPierre Pronchery     return 1;
761*e7be843bSPierre Pronchery }
762*e7be843bSPierre Pronchery 
763*e7be843bSPierre Pronchery /*
764*e7be843bSPierre Pronchery  * Calculate the correct length of the secret key.
765*e7be843bSPierre Pronchery  *
766*e7be843bSPierre Pronchery  * RFC 8446:
767*e7be843bSPierre Pronchery  *   If a given secret is not available, then the 0-value consisting of a
768*e7be843bSPierre Pronchery  *   string of Hash.length bytes set to zeros is used.
769*e7be843bSPierre Pronchery  */
fips_tls1_3_key_size(KDF_HKDF * ctx)770*e7be843bSPierre Pronchery static size_t fips_tls1_3_key_size(KDF_HKDF *ctx)
771*e7be843bSPierre Pronchery {
772*e7be843bSPierre Pronchery     const EVP_MD *md = ossl_prov_digest_md(&ctx->digest);
773*e7be843bSPierre Pronchery     size_t key_size = 0;
774*e7be843bSPierre Pronchery 
775*e7be843bSPierre Pronchery     if (ctx->key != NULL)
776*e7be843bSPierre Pronchery         key_size = ctx->key_len;
777*e7be843bSPierre Pronchery     else if (md != NULL)
778*e7be843bSPierre Pronchery         key_size = EVP_MD_size(md);
779*e7be843bSPierre Pronchery 
780*e7be843bSPierre Pronchery     return key_size;
781*e7be843bSPierre Pronchery }
782*e7be843bSPierre Pronchery 
fips_tls1_3_key_check_passed(KDF_HKDF * ctx)783*e7be843bSPierre Pronchery static int fips_tls1_3_key_check_passed(KDF_HKDF *ctx)
784*e7be843bSPierre Pronchery {
785*e7be843bSPierre Pronchery     OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(ctx->provctx);
786*e7be843bSPierre Pronchery     int key_approved = ossl_kdf_check_key_size(fips_tls1_3_key_size(ctx));
787*e7be843bSPierre Pronchery 
788*e7be843bSPierre Pronchery     if (!key_approved) {
789*e7be843bSPierre Pronchery         if (!OSSL_FIPS_IND_ON_UNAPPROVED(ctx, OSSL_FIPS_IND_SETTABLE1,
790*e7be843bSPierre Pronchery                                          libctx, "TLS13 KDF", "Key size",
791*e7be843bSPierre Pronchery                                          ossl_fips_config_tls13_kdf_key_check)) {
792*e7be843bSPierre Pronchery             ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
793*e7be843bSPierre Pronchery             return 0;
794*e7be843bSPierre Pronchery         }
795*e7be843bSPierre Pronchery     }
796*e7be843bSPierre Pronchery     return 1;
797*e7be843bSPierre Pronchery }
798*e7be843bSPierre Pronchery #endif
799*e7be843bSPierre Pronchery 
kdf_tls1_3_derive(void * vctx,unsigned char * key,size_t keylen,const OSSL_PARAM params[])800b077aed3SPierre Pronchery static int kdf_tls1_3_derive(void *vctx, unsigned char *key, size_t keylen,
801b077aed3SPierre Pronchery                              const OSSL_PARAM params[])
802b077aed3SPierre Pronchery {
803b077aed3SPierre Pronchery     KDF_HKDF *ctx = (KDF_HKDF *)vctx;
804b077aed3SPierre Pronchery     const EVP_MD *md;
805b077aed3SPierre Pronchery 
806b077aed3SPierre Pronchery     if (!ossl_prov_is_running() || !kdf_tls1_3_set_ctx_params(ctx, params))
807b077aed3SPierre Pronchery         return 0;
808b077aed3SPierre Pronchery 
809b077aed3SPierre Pronchery     md = ossl_prov_digest_md(&ctx->digest);
810b077aed3SPierre Pronchery     if (md == NULL) {
811b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_MESSAGE_DIGEST);
812b077aed3SPierre Pronchery         return 0;
813b077aed3SPierre Pronchery     }
814b077aed3SPierre Pronchery 
815b077aed3SPierre Pronchery     switch (ctx->mode) {
816b077aed3SPierre Pronchery     default:
817b077aed3SPierre Pronchery         return 0;
818b077aed3SPierre Pronchery 
819b077aed3SPierre Pronchery     case EVP_KDF_HKDF_MODE_EXTRACT_ONLY:
820b077aed3SPierre Pronchery         return prov_tls13_hkdf_generate_secret(PROV_LIBCTX_OF(ctx->provctx),
821b077aed3SPierre Pronchery                                                md,
822b077aed3SPierre Pronchery                                                ctx->salt, ctx->salt_len,
823b077aed3SPierre Pronchery                                                ctx->key, ctx->key_len,
824b077aed3SPierre Pronchery                                                ctx->prefix, ctx->prefix_len,
825b077aed3SPierre Pronchery                                                ctx->label, ctx->label_len,
826b077aed3SPierre Pronchery                                                key, keylen);
827b077aed3SPierre Pronchery 
828b077aed3SPierre Pronchery     case EVP_KDF_HKDF_MODE_EXPAND_ONLY:
829b077aed3SPierre Pronchery         return prov_tls13_hkdf_expand(md, ctx->key, ctx->key_len,
830b077aed3SPierre Pronchery                                       ctx->prefix, ctx->prefix_len,
831b077aed3SPierre Pronchery                                       ctx->label, ctx->label_len,
832b077aed3SPierre Pronchery                                       ctx->data, ctx->data_len,
833b077aed3SPierre Pronchery                                       key, keylen);
834b077aed3SPierre Pronchery     }
835b077aed3SPierre Pronchery }
836b077aed3SPierre Pronchery 
kdf_tls1_3_set_ctx_params(void * vctx,const OSSL_PARAM params[])837b077aed3SPierre Pronchery static int kdf_tls1_3_set_ctx_params(void *vctx, const OSSL_PARAM params[])
838b077aed3SPierre Pronchery {
839b077aed3SPierre Pronchery     const OSSL_PARAM *p;
840b077aed3SPierre Pronchery     KDF_HKDF *ctx = vctx;
841b077aed3SPierre Pronchery 
842*e7be843bSPierre Pronchery     if (ossl_param_is_empty(params))
843b077aed3SPierre Pronchery         return 1;
844b077aed3SPierre Pronchery 
845*e7be843bSPierre Pronchery     if (!OSSL_FIPS_IND_SET_CTX_PARAM(ctx, OSSL_FIPS_IND_SETTABLE0, params,
846*e7be843bSPierre Pronchery                                      OSSL_KDF_PARAM_FIPS_DIGEST_CHECK))
847*e7be843bSPierre Pronchery         return 0;
848*e7be843bSPierre Pronchery     if (!OSSL_FIPS_IND_SET_CTX_PARAM(ctx, OSSL_FIPS_IND_SETTABLE1, params,
849*e7be843bSPierre Pronchery                                      OSSL_KDF_PARAM_FIPS_KEY_CHECK))
850*e7be843bSPierre Pronchery         return 0;
851*e7be843bSPierre Pronchery 
852b077aed3SPierre Pronchery     if (!hkdf_common_set_ctx_params(ctx, params))
853b077aed3SPierre Pronchery         return 0;
854b077aed3SPierre Pronchery 
855b077aed3SPierre Pronchery     if (ctx->mode == EVP_KDF_HKDF_MODE_EXTRACT_AND_EXPAND) {
856b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_MODE);
857b077aed3SPierre Pronchery         return 0;
858b077aed3SPierre Pronchery     }
859b077aed3SPierre Pronchery 
860b077aed3SPierre Pronchery     if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_PREFIX)) != NULL) {
861b077aed3SPierre Pronchery         OPENSSL_free(ctx->prefix);
862b077aed3SPierre Pronchery         ctx->prefix = NULL;
863b077aed3SPierre Pronchery         if (!OSSL_PARAM_get_octet_string(p, (void **)&ctx->prefix, 0,
864b077aed3SPierre Pronchery                                          &ctx->prefix_len))
865b077aed3SPierre Pronchery             return 0;
866b077aed3SPierre Pronchery     }
867b077aed3SPierre Pronchery 
868b077aed3SPierre Pronchery     if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_LABEL)) != NULL) {
869b077aed3SPierre Pronchery         OPENSSL_free(ctx->label);
870b077aed3SPierre Pronchery         ctx->label = NULL;
871b077aed3SPierre Pronchery         if (!OSSL_PARAM_get_octet_string(p, (void **)&ctx->label, 0,
872b077aed3SPierre Pronchery                                          &ctx->label_len))
873b077aed3SPierre Pronchery             return 0;
874b077aed3SPierre Pronchery     }
875b077aed3SPierre Pronchery 
876b077aed3SPierre Pronchery     OPENSSL_clear_free(ctx->data, ctx->data_len);
877b077aed3SPierre Pronchery     ctx->data = NULL;
878b077aed3SPierre Pronchery     if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_DATA)) != NULL
879b077aed3SPierre Pronchery             && !OSSL_PARAM_get_octet_string(p, (void **)&ctx->data, 0,
880b077aed3SPierre Pronchery                                             &ctx->data_len))
881b077aed3SPierre Pronchery         return 0;
882*e7be843bSPierre Pronchery 
883*e7be843bSPierre Pronchery #ifdef FIPS_MODULE
884*e7be843bSPierre Pronchery     if (OSSL_PARAM_locate_const(params, OSSL_ALG_PARAM_DIGEST) != NULL) {
885*e7be843bSPierre Pronchery         const EVP_MD *md = ossl_prov_digest_md(&ctx->digest);
886*e7be843bSPierre Pronchery 
887*e7be843bSPierre Pronchery         if (!fips_tls1_3_digest_check_passed(ctx, md))
888*e7be843bSPierre Pronchery             return 0;
889*e7be843bSPierre Pronchery     }
890*e7be843bSPierre Pronchery 
891*e7be843bSPierre Pronchery     if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_KEY)) != NULL)
892*e7be843bSPierre Pronchery         if (!fips_tls1_3_key_check_passed(ctx))
893*e7be843bSPierre Pronchery             return 0;
894*e7be843bSPierre Pronchery #endif
895*e7be843bSPierre Pronchery 
896b077aed3SPierre Pronchery     return 1;
897b077aed3SPierre Pronchery }
898b077aed3SPierre Pronchery 
kdf_tls1_3_settable_ctx_params(ossl_unused void * ctx,ossl_unused void * provctx)899b077aed3SPierre Pronchery static const OSSL_PARAM *kdf_tls1_3_settable_ctx_params(ossl_unused void *ctx,
900b077aed3SPierre Pronchery                                                         ossl_unused void *provctx)
901b077aed3SPierre Pronchery {
902b077aed3SPierre Pronchery     static const OSSL_PARAM known_settable_ctx_params[] = {
903b077aed3SPierre Pronchery         HKDF_COMMON_SETTABLES,
904b077aed3SPierre Pronchery         OSSL_PARAM_octet_string(OSSL_KDF_PARAM_PREFIX, NULL, 0),
905b077aed3SPierre Pronchery         OSSL_PARAM_octet_string(OSSL_KDF_PARAM_LABEL, NULL, 0),
906b077aed3SPierre Pronchery         OSSL_PARAM_octet_string(OSSL_KDF_PARAM_DATA, NULL, 0),
907*e7be843bSPierre Pronchery         OSSL_FIPS_IND_SETTABLE_CTX_PARAM(OSSL_KDF_PARAM_FIPS_DIGEST_CHECK)
908*e7be843bSPierre Pronchery         OSSL_FIPS_IND_SETTABLE_CTX_PARAM(OSSL_KDF_PARAM_FIPS_KEY_CHECK)
909b077aed3SPierre Pronchery         OSSL_PARAM_END
910b077aed3SPierre Pronchery     };
911b077aed3SPierre Pronchery     return known_settable_ctx_params;
912b077aed3SPierre Pronchery }
913b077aed3SPierre Pronchery 
kdf_tls1_3_get_ctx_params(void * vctx,OSSL_PARAM params[])914*e7be843bSPierre Pronchery static int kdf_tls1_3_get_ctx_params(void *vctx, OSSL_PARAM params[])
915*e7be843bSPierre Pronchery {
916*e7be843bSPierre Pronchery     KDF_HKDF *ctx = (KDF_HKDF *)vctx;
917*e7be843bSPierre Pronchery 
918*e7be843bSPierre Pronchery     if (ossl_param_is_empty(params))
919*e7be843bSPierre Pronchery         return 1;
920*e7be843bSPierre Pronchery 
921*e7be843bSPierre Pronchery     if (!hkdf_common_get_ctx_params(ctx, params))
922*e7be843bSPierre Pronchery         return 0;
923*e7be843bSPierre Pronchery 
924*e7be843bSPierre Pronchery     if (!OSSL_FIPS_IND_GET_CTX_PARAM(ctx, params))
925*e7be843bSPierre Pronchery         return 0;
926*e7be843bSPierre Pronchery 
927*e7be843bSPierre Pronchery     return 1;
928*e7be843bSPierre Pronchery }
929*e7be843bSPierre Pronchery 
kdf_tls1_3_gettable_ctx_params(ossl_unused void * ctx,ossl_unused void * provctx)930*e7be843bSPierre Pronchery static const OSSL_PARAM *kdf_tls1_3_gettable_ctx_params(ossl_unused void *ctx,
931*e7be843bSPierre Pronchery                                                         ossl_unused void *provctx)
932*e7be843bSPierre Pronchery {
933*e7be843bSPierre Pronchery     static const OSSL_PARAM known_gettable_ctx_params[] = {
934*e7be843bSPierre Pronchery         HKDF_COMMON_GETTABLES,
935*e7be843bSPierre Pronchery         OSSL_FIPS_IND_GETTABLE_CTX_PARAM()
936*e7be843bSPierre Pronchery         OSSL_PARAM_END
937*e7be843bSPierre Pronchery     };
938*e7be843bSPierre Pronchery     return known_gettable_ctx_params;
939*e7be843bSPierre Pronchery }
940*e7be843bSPierre Pronchery 
941b077aed3SPierre Pronchery const OSSL_DISPATCH ossl_kdf_tls1_3_kdf_functions[] = {
942b077aed3SPierre Pronchery     { OSSL_FUNC_KDF_NEWCTX, (void(*)(void))kdf_hkdf_new },
943*e7be843bSPierre Pronchery     { OSSL_FUNC_KDF_DUPCTX, (void(*)(void))kdf_hkdf_dup },
944b077aed3SPierre Pronchery     { OSSL_FUNC_KDF_FREECTX, (void(*)(void))kdf_hkdf_free },
945b077aed3SPierre Pronchery     { OSSL_FUNC_KDF_RESET, (void(*)(void))kdf_hkdf_reset },
946b077aed3SPierre Pronchery     { OSSL_FUNC_KDF_DERIVE, (void(*)(void))kdf_tls1_3_derive },
947b077aed3SPierre Pronchery     { OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS,
948b077aed3SPierre Pronchery       (void(*)(void))kdf_tls1_3_settable_ctx_params },
949b077aed3SPierre Pronchery     { OSSL_FUNC_KDF_SET_CTX_PARAMS, (void(*)(void))kdf_tls1_3_set_ctx_params },
950b077aed3SPierre Pronchery     { OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS,
951*e7be843bSPierre Pronchery       (void(*)(void))kdf_tls1_3_gettable_ctx_params },
952*e7be843bSPierre Pronchery     { OSSL_FUNC_KDF_GET_CTX_PARAMS, (void(*)(void))kdf_tls1_3_get_ctx_params },
953*e7be843bSPierre Pronchery     OSSL_DISPATCH_END
954b077aed3SPierre Pronchery };
955