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