1b077aed3SPierre Pronchery /*
2*44096ebdSEnji Cooper * Copyright 2020-2024 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 #include <openssl/crypto.h>
11b077aed3SPierre Pronchery #include <openssl/kdf.h>
12b077aed3SPierre Pronchery #include <openssl/core_dispatch.h>
13b077aed3SPierre Pronchery #include <openssl/core_names.h>
14b077aed3SPierre Pronchery #include <openssl/err.h>
15b077aed3SPierre Pronchery #include <openssl/proverr.h>
16b077aed3SPierre Pronchery #include <openssl/params.h>
17b077aed3SPierre Pronchery #include "internal/numbers.h"
18b077aed3SPierre Pronchery #include "prov/implementations.h"
19b077aed3SPierre Pronchery #include "prov/provider_ctx.h"
20b077aed3SPierre Pronchery #include "prov/kdfexchange.h"
21b077aed3SPierre Pronchery #include "prov/providercommon.h"
22b077aed3SPierre Pronchery
23b077aed3SPierre Pronchery static OSSL_FUNC_keyexch_newctx_fn kdf_tls1_prf_newctx;
24b077aed3SPierre Pronchery static OSSL_FUNC_keyexch_newctx_fn kdf_hkdf_newctx;
25b077aed3SPierre Pronchery static OSSL_FUNC_keyexch_newctx_fn kdf_scrypt_newctx;
26b077aed3SPierre Pronchery static OSSL_FUNC_keyexch_init_fn kdf_init;
27b077aed3SPierre Pronchery static OSSL_FUNC_keyexch_derive_fn kdf_derive;
28b077aed3SPierre Pronchery static OSSL_FUNC_keyexch_freectx_fn kdf_freectx;
29b077aed3SPierre Pronchery static OSSL_FUNC_keyexch_dupctx_fn kdf_dupctx;
30b077aed3SPierre Pronchery static OSSL_FUNC_keyexch_set_ctx_params_fn kdf_set_ctx_params;
31*44096ebdSEnji Cooper static OSSL_FUNC_keyexch_get_ctx_params_fn kdf_get_ctx_params;
32b077aed3SPierre Pronchery static OSSL_FUNC_keyexch_settable_ctx_params_fn kdf_tls1_prf_settable_ctx_params;
33b077aed3SPierre Pronchery static OSSL_FUNC_keyexch_settable_ctx_params_fn kdf_hkdf_settable_ctx_params;
34b077aed3SPierre Pronchery static OSSL_FUNC_keyexch_settable_ctx_params_fn kdf_scrypt_settable_ctx_params;
35*44096ebdSEnji Cooper static OSSL_FUNC_keyexch_gettable_ctx_params_fn kdf_tls1_prf_gettable_ctx_params;
36*44096ebdSEnji Cooper static OSSL_FUNC_keyexch_gettable_ctx_params_fn kdf_hkdf_gettable_ctx_params;
37*44096ebdSEnji Cooper static OSSL_FUNC_keyexch_gettable_ctx_params_fn kdf_scrypt_gettable_ctx_params;
38b077aed3SPierre Pronchery
39b077aed3SPierre Pronchery typedef struct {
40b077aed3SPierre Pronchery void *provctx;
41b077aed3SPierre Pronchery EVP_KDF_CTX *kdfctx;
42b077aed3SPierre Pronchery KDF_DATA *kdfdata;
43b077aed3SPierre Pronchery } PROV_KDF_CTX;
44b077aed3SPierre Pronchery
kdf_newctx(const char * kdfname,void * provctx)45b077aed3SPierre Pronchery static void *kdf_newctx(const char *kdfname, void *provctx)
46b077aed3SPierre Pronchery {
47b077aed3SPierre Pronchery PROV_KDF_CTX *kdfctx;
48b077aed3SPierre Pronchery EVP_KDF *kdf = NULL;
49b077aed3SPierre Pronchery
50b077aed3SPierre Pronchery if (!ossl_prov_is_running())
51b077aed3SPierre Pronchery return NULL;
52b077aed3SPierre Pronchery
53b077aed3SPierre Pronchery kdfctx = OPENSSL_zalloc(sizeof(PROV_KDF_CTX));
54b077aed3SPierre Pronchery if (kdfctx == NULL)
55b077aed3SPierre Pronchery return NULL;
56b077aed3SPierre Pronchery
57b077aed3SPierre Pronchery kdfctx->provctx = provctx;
58b077aed3SPierre Pronchery
59b077aed3SPierre Pronchery kdf = EVP_KDF_fetch(PROV_LIBCTX_OF(provctx), kdfname, NULL);
60b077aed3SPierre Pronchery if (kdf == NULL)
61b077aed3SPierre Pronchery goto err;
62b077aed3SPierre Pronchery kdfctx->kdfctx = EVP_KDF_CTX_new(kdf);
63b077aed3SPierre Pronchery EVP_KDF_free(kdf);
64b077aed3SPierre Pronchery
65b077aed3SPierre Pronchery if (kdfctx->kdfctx == NULL)
66b077aed3SPierre Pronchery goto err;
67b077aed3SPierre Pronchery
68b077aed3SPierre Pronchery return kdfctx;
69b077aed3SPierre Pronchery err:
70b077aed3SPierre Pronchery OPENSSL_free(kdfctx);
71b077aed3SPierre Pronchery return NULL;
72b077aed3SPierre Pronchery }
73b077aed3SPierre Pronchery
74b077aed3SPierre Pronchery #define KDF_NEWCTX(funcname, kdfname) \
75b077aed3SPierre Pronchery static void *kdf_##funcname##_newctx(void *provctx) \
76b077aed3SPierre Pronchery { \
77b077aed3SPierre Pronchery return kdf_newctx(kdfname, provctx); \
78b077aed3SPierre Pronchery }
79b077aed3SPierre Pronchery
80b077aed3SPierre Pronchery KDF_NEWCTX(tls1_prf, "TLS1-PRF")
81b077aed3SPierre Pronchery KDF_NEWCTX(hkdf, "HKDF")
82b077aed3SPierre Pronchery KDF_NEWCTX(scrypt, "SCRYPT")
83b077aed3SPierre Pronchery
kdf_init(void * vpkdfctx,void * vkdf,const OSSL_PARAM params[])84b077aed3SPierre Pronchery static int kdf_init(void *vpkdfctx, void *vkdf, const OSSL_PARAM params[])
85b077aed3SPierre Pronchery {
86b077aed3SPierre Pronchery PROV_KDF_CTX *pkdfctx = (PROV_KDF_CTX *)vpkdfctx;
87b077aed3SPierre Pronchery
88b077aed3SPierre Pronchery if (!ossl_prov_is_running()
89b077aed3SPierre Pronchery || pkdfctx == NULL
90b077aed3SPierre Pronchery || vkdf == NULL
91b077aed3SPierre Pronchery || !ossl_kdf_data_up_ref(vkdf))
92b077aed3SPierre Pronchery return 0;
93b077aed3SPierre Pronchery pkdfctx->kdfdata = vkdf;
94b077aed3SPierre Pronchery
95b077aed3SPierre Pronchery return kdf_set_ctx_params(pkdfctx, params);
96b077aed3SPierre Pronchery }
97b077aed3SPierre Pronchery
kdf_derive(void * vpkdfctx,unsigned char * secret,size_t * secretlen,size_t outlen)98b077aed3SPierre Pronchery static int kdf_derive(void *vpkdfctx, unsigned char *secret, size_t *secretlen,
99b077aed3SPierre Pronchery size_t outlen)
100b077aed3SPierre Pronchery {
101b077aed3SPierre Pronchery PROV_KDF_CTX *pkdfctx = (PROV_KDF_CTX *)vpkdfctx;
102b077aed3SPierre Pronchery size_t kdfsize;
103b077aed3SPierre Pronchery int ret;
104b077aed3SPierre Pronchery
105b077aed3SPierre Pronchery if (!ossl_prov_is_running())
106b077aed3SPierre Pronchery return 0;
107b077aed3SPierre Pronchery
108b077aed3SPierre Pronchery kdfsize = EVP_KDF_CTX_get_kdf_size(pkdfctx->kdfctx);
109b077aed3SPierre Pronchery
110b077aed3SPierre Pronchery if (secret == NULL) {
111b077aed3SPierre Pronchery *secretlen = kdfsize;
112b077aed3SPierre Pronchery return 1;
113b077aed3SPierre Pronchery }
114b077aed3SPierre Pronchery
115b077aed3SPierre Pronchery if (kdfsize != SIZE_MAX) {
116b077aed3SPierre Pronchery if (outlen < kdfsize) {
117b077aed3SPierre Pronchery ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
118b077aed3SPierre Pronchery return 0;
119b077aed3SPierre Pronchery }
120b077aed3SPierre Pronchery outlen = kdfsize;
121b077aed3SPierre Pronchery }
122b077aed3SPierre Pronchery
123b077aed3SPierre Pronchery ret = EVP_KDF_derive(pkdfctx->kdfctx, secret, outlen, NULL);
124b077aed3SPierre Pronchery if (ret <= 0)
125b077aed3SPierre Pronchery return 0;
126b077aed3SPierre Pronchery
127b077aed3SPierre Pronchery *secretlen = outlen;
128b077aed3SPierre Pronchery return 1;
129b077aed3SPierre Pronchery }
130b077aed3SPierre Pronchery
kdf_freectx(void * vpkdfctx)131b077aed3SPierre Pronchery static void kdf_freectx(void *vpkdfctx)
132b077aed3SPierre Pronchery {
133b077aed3SPierre Pronchery PROV_KDF_CTX *pkdfctx = (PROV_KDF_CTX *)vpkdfctx;
134b077aed3SPierre Pronchery
135b077aed3SPierre Pronchery EVP_KDF_CTX_free(pkdfctx->kdfctx);
136b077aed3SPierre Pronchery ossl_kdf_data_free(pkdfctx->kdfdata);
137b077aed3SPierre Pronchery
138b077aed3SPierre Pronchery OPENSSL_free(pkdfctx);
139b077aed3SPierre Pronchery }
140b077aed3SPierre Pronchery
kdf_dupctx(void * vpkdfctx)141b077aed3SPierre Pronchery static void *kdf_dupctx(void *vpkdfctx)
142b077aed3SPierre Pronchery {
143b077aed3SPierre Pronchery PROV_KDF_CTX *srcctx = (PROV_KDF_CTX *)vpkdfctx;
144b077aed3SPierre Pronchery PROV_KDF_CTX *dstctx;
145b077aed3SPierre Pronchery
146b077aed3SPierre Pronchery if (!ossl_prov_is_running())
147b077aed3SPierre Pronchery return NULL;
148b077aed3SPierre Pronchery
149b077aed3SPierre Pronchery dstctx = OPENSSL_zalloc(sizeof(*srcctx));
150b077aed3SPierre Pronchery if (dstctx == NULL)
151b077aed3SPierre Pronchery return NULL;
152b077aed3SPierre Pronchery
153b077aed3SPierre Pronchery *dstctx = *srcctx;
154b077aed3SPierre Pronchery
155b077aed3SPierre Pronchery dstctx->kdfctx = EVP_KDF_CTX_dup(srcctx->kdfctx);
156b077aed3SPierre Pronchery if (dstctx->kdfctx == NULL) {
157b077aed3SPierre Pronchery OPENSSL_free(dstctx);
158b077aed3SPierre Pronchery return NULL;
159b077aed3SPierre Pronchery }
160b077aed3SPierre Pronchery if (!ossl_kdf_data_up_ref(dstctx->kdfdata)) {
161b077aed3SPierre Pronchery EVP_KDF_CTX_free(dstctx->kdfctx);
162b077aed3SPierre Pronchery OPENSSL_free(dstctx);
163b077aed3SPierre Pronchery return NULL;
164b077aed3SPierre Pronchery }
165b077aed3SPierre Pronchery
166b077aed3SPierre Pronchery return dstctx;
167b077aed3SPierre Pronchery }
168b077aed3SPierre Pronchery
kdf_set_ctx_params(void * vpkdfctx,const OSSL_PARAM params[])169b077aed3SPierre Pronchery static int kdf_set_ctx_params(void *vpkdfctx, const OSSL_PARAM params[])
170b077aed3SPierre Pronchery {
171b077aed3SPierre Pronchery PROV_KDF_CTX *pkdfctx = (PROV_KDF_CTX *)vpkdfctx;
172b077aed3SPierre Pronchery
173b077aed3SPierre Pronchery return EVP_KDF_CTX_set_params(pkdfctx->kdfctx, params);
174b077aed3SPierre Pronchery }
175b077aed3SPierre Pronchery
kdf_get_ctx_params(void * vpkdfctx,OSSL_PARAM params[])176*44096ebdSEnji Cooper static int kdf_get_ctx_params(void *vpkdfctx, OSSL_PARAM params[])
177*44096ebdSEnji Cooper {
178*44096ebdSEnji Cooper PROV_KDF_CTX *pkdfctx = (PROV_KDF_CTX *)vpkdfctx;
179*44096ebdSEnji Cooper
180*44096ebdSEnji Cooper return EVP_KDF_CTX_get_params(pkdfctx->kdfctx, params);
181*44096ebdSEnji Cooper }
182*44096ebdSEnji Cooper
kdf_settable_ctx_params(ossl_unused void * vpkdfctx,void * provctx,const char * kdfname)183b077aed3SPierre Pronchery static const OSSL_PARAM *kdf_settable_ctx_params(ossl_unused void *vpkdfctx,
184b077aed3SPierre Pronchery void *provctx,
185b077aed3SPierre Pronchery const char *kdfname)
186b077aed3SPierre Pronchery {
187b077aed3SPierre Pronchery EVP_KDF *kdf = EVP_KDF_fetch(PROV_LIBCTX_OF(provctx), kdfname,
188b077aed3SPierre Pronchery NULL);
189b077aed3SPierre Pronchery const OSSL_PARAM *params;
190b077aed3SPierre Pronchery
191b077aed3SPierre Pronchery if (kdf == NULL)
192b077aed3SPierre Pronchery return NULL;
193b077aed3SPierre Pronchery
194b077aed3SPierre Pronchery params = EVP_KDF_settable_ctx_params(kdf);
195b077aed3SPierre Pronchery EVP_KDF_free(kdf);
196b077aed3SPierre Pronchery
197b077aed3SPierre Pronchery return params;
198b077aed3SPierre Pronchery }
199b077aed3SPierre Pronchery
200b077aed3SPierre Pronchery #define KDF_SETTABLE_CTX_PARAMS(funcname, kdfname) \
201b077aed3SPierre Pronchery static const OSSL_PARAM *kdf_##funcname##_settable_ctx_params(void *vpkdfctx, \
202b077aed3SPierre Pronchery void *provctx) \
203b077aed3SPierre Pronchery { \
204b077aed3SPierre Pronchery return kdf_settable_ctx_params(vpkdfctx, provctx, kdfname); \
205b077aed3SPierre Pronchery }
206b077aed3SPierre Pronchery
207b077aed3SPierre Pronchery KDF_SETTABLE_CTX_PARAMS(tls1_prf, "TLS1-PRF")
208b077aed3SPierre Pronchery KDF_SETTABLE_CTX_PARAMS(hkdf, "HKDF")
209b077aed3SPierre Pronchery KDF_SETTABLE_CTX_PARAMS(scrypt, "SCRYPT")
210b077aed3SPierre Pronchery
kdf_gettable_ctx_params(ossl_unused void * vpkdfctx,void * provctx,const char * kdfname)211*44096ebdSEnji Cooper static const OSSL_PARAM *kdf_gettable_ctx_params(ossl_unused void *vpkdfctx,
212*44096ebdSEnji Cooper void *provctx,
213*44096ebdSEnji Cooper const char *kdfname)
214*44096ebdSEnji Cooper {
215*44096ebdSEnji Cooper EVP_KDF *kdf = EVP_KDF_fetch(PROV_LIBCTX_OF(provctx), kdfname,
216*44096ebdSEnji Cooper NULL);
217*44096ebdSEnji Cooper const OSSL_PARAM *params;
218*44096ebdSEnji Cooper
219*44096ebdSEnji Cooper if (kdf == NULL)
220*44096ebdSEnji Cooper return NULL;
221*44096ebdSEnji Cooper
222*44096ebdSEnji Cooper params = EVP_KDF_gettable_ctx_params(kdf);
223*44096ebdSEnji Cooper EVP_KDF_free(kdf);
224*44096ebdSEnji Cooper
225*44096ebdSEnji Cooper return params;
226*44096ebdSEnji Cooper }
227*44096ebdSEnji Cooper
228*44096ebdSEnji Cooper #define KDF_GETTABLE_CTX_PARAMS(funcname, kdfname) \
229*44096ebdSEnji Cooper static const OSSL_PARAM *kdf_##funcname##_gettable_ctx_params(void *vpkdfctx, \
230*44096ebdSEnji Cooper void *provctx) \
231*44096ebdSEnji Cooper { \
232*44096ebdSEnji Cooper return kdf_gettable_ctx_params(vpkdfctx, provctx, kdfname); \
233*44096ebdSEnji Cooper }
234*44096ebdSEnji Cooper
235*44096ebdSEnji Cooper KDF_GETTABLE_CTX_PARAMS(tls1_prf, "TLS1-PRF")
236*44096ebdSEnji Cooper KDF_GETTABLE_CTX_PARAMS(hkdf, "HKDF")
237*44096ebdSEnji Cooper KDF_GETTABLE_CTX_PARAMS(scrypt, "SCRYPT")
238*44096ebdSEnji Cooper
239b077aed3SPierre Pronchery #define KDF_KEYEXCH_FUNCTIONS(funcname) \
240b077aed3SPierre Pronchery const OSSL_DISPATCH ossl_kdf_##funcname##_keyexch_functions[] = { \
241b077aed3SPierre Pronchery { OSSL_FUNC_KEYEXCH_NEWCTX, (void (*)(void))kdf_##funcname##_newctx }, \
242b077aed3SPierre Pronchery { OSSL_FUNC_KEYEXCH_INIT, (void (*)(void))kdf_init }, \
243b077aed3SPierre Pronchery { OSSL_FUNC_KEYEXCH_DERIVE, (void (*)(void))kdf_derive }, \
244b077aed3SPierre Pronchery { OSSL_FUNC_KEYEXCH_FREECTX, (void (*)(void))kdf_freectx }, \
245b077aed3SPierre Pronchery { OSSL_FUNC_KEYEXCH_DUPCTX, (void (*)(void))kdf_dupctx }, \
246b077aed3SPierre Pronchery { OSSL_FUNC_KEYEXCH_SET_CTX_PARAMS, (void (*)(void))kdf_set_ctx_params }, \
247*44096ebdSEnji Cooper { OSSL_FUNC_KEYEXCH_GET_CTX_PARAMS, (void (*)(void))kdf_get_ctx_params }, \
248b077aed3SPierre Pronchery { OSSL_FUNC_KEYEXCH_SETTABLE_CTX_PARAMS, \
249b077aed3SPierre Pronchery (void (*)(void))kdf_##funcname##_settable_ctx_params }, \
250*44096ebdSEnji Cooper { OSSL_FUNC_KEYEXCH_GETTABLE_CTX_PARAMS, \
251*44096ebdSEnji Cooper (void (*)(void))kdf_##funcname##_gettable_ctx_params }, \
252b077aed3SPierre Pronchery { 0, NULL } \
253b077aed3SPierre Pronchery };
254b077aed3SPierre Pronchery
255b077aed3SPierre Pronchery KDF_KEYEXCH_FUNCTIONS(tls1_prf)
256b077aed3SPierre Pronchery KDF_KEYEXCH_FUNCTIONS(hkdf)
257b077aed3SPierre Pronchery KDF_KEYEXCH_FUNCTIONS(scrypt)
258