xref: /freebsd/crypto/openssl/providers/implementations/exchange/kdf_exch.c (revision 44096ebd22ddd0081a357011714eff8963614b65)
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 
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 
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 
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 
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 
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 
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 
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 
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 
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         { 0, NULL } \
253     };
254 
255 KDF_KEYEXCH_FUNCTIONS(tls1_prf)
256 KDF_KEYEXCH_FUNCTIONS(hkdf)
257 KDF_KEYEXCH_FUNCTIONS(scrypt)
258