xref: /netbsd-src/crypto/external/bsd/openssl/dist/providers/implementations/exchange/dh_exch.c (revision b0d1725196a7921d003d2c66a14f186abda4176b)
1*b0d17251Schristos /*
2*b0d17251Schristos  * Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
3*b0d17251Schristos  *
4*b0d17251Schristos  * Licensed under the Apache License 2.0 (the "License").  You may not use
5*b0d17251Schristos  * this file except in compliance with the License.  You can obtain a copy
6*b0d17251Schristos  * in the file LICENSE in the source distribution or at
7*b0d17251Schristos  * https://www.openssl.org/source/license.html
8*b0d17251Schristos  */
9*b0d17251Schristos 
10*b0d17251Schristos /*
11*b0d17251Schristos  * DH low level APIs are deprecated for public use, but still ok for
12*b0d17251Schristos  * internal use.
13*b0d17251Schristos  */
14*b0d17251Schristos #include "internal/deprecated.h"
15*b0d17251Schristos 
16*b0d17251Schristos #include <string.h>
17*b0d17251Schristos #include <openssl/crypto.h>
18*b0d17251Schristos #include <openssl/core_dispatch.h>
19*b0d17251Schristos #include <openssl/core_names.h>
20*b0d17251Schristos #include <openssl/dh.h>
21*b0d17251Schristos #include <openssl/err.h>
22*b0d17251Schristos #include <openssl/proverr.h>
23*b0d17251Schristos #include <openssl/params.h>
24*b0d17251Schristos #include "prov/providercommon.h"
25*b0d17251Schristos #include "prov/implementations.h"
26*b0d17251Schristos #include "prov/provider_ctx.h"
27*b0d17251Schristos #include "prov/securitycheck.h"
28*b0d17251Schristos #include "crypto/dh.h"
29*b0d17251Schristos 
30*b0d17251Schristos static OSSL_FUNC_keyexch_newctx_fn dh_newctx;
31*b0d17251Schristos static OSSL_FUNC_keyexch_init_fn dh_init;
32*b0d17251Schristos static OSSL_FUNC_keyexch_set_peer_fn dh_set_peer;
33*b0d17251Schristos static OSSL_FUNC_keyexch_derive_fn dh_derive;
34*b0d17251Schristos static OSSL_FUNC_keyexch_freectx_fn dh_freectx;
35*b0d17251Schristos static OSSL_FUNC_keyexch_dupctx_fn dh_dupctx;
36*b0d17251Schristos static OSSL_FUNC_keyexch_set_ctx_params_fn dh_set_ctx_params;
37*b0d17251Schristos static OSSL_FUNC_keyexch_settable_ctx_params_fn dh_settable_ctx_params;
38*b0d17251Schristos static OSSL_FUNC_keyexch_get_ctx_params_fn dh_get_ctx_params;
39*b0d17251Schristos static OSSL_FUNC_keyexch_gettable_ctx_params_fn dh_gettable_ctx_params;
40*b0d17251Schristos 
41*b0d17251Schristos /*
42*b0d17251Schristos  * This type is only really used to handle some legacy related functionality.
43*b0d17251Schristos  * If you need to use other KDF's (such as SSKDF) just use PROV_DH_KDF_NONE
44*b0d17251Schristos  * here and then create and run a KDF after the key is derived.
45*b0d17251Schristos  * Note that X942 has 2 variants of key derivation:
46*b0d17251Schristos  *   (1) DH_KDF_X9_42_ASN1 - which contains an ANS1 encoded object that has
47*b0d17251Schristos  *   the counter embedded in it.
48*b0d17251Schristos  *   (2) DH_KDF_X941_CONCAT - which is the same as ECDH_X963_KDF (which can be
49*b0d17251Schristos  *       done by creating a "X963KDF".
50*b0d17251Schristos  */
51*b0d17251Schristos enum kdf_type {
52*b0d17251Schristos     PROV_DH_KDF_NONE = 0,
53*b0d17251Schristos     PROV_DH_KDF_X9_42_ASN1
54*b0d17251Schristos };
55*b0d17251Schristos 
56*b0d17251Schristos /*
57*b0d17251Schristos  * What's passed as an actual key is defined by the KEYMGMT interface.
58*b0d17251Schristos  * We happen to know that our KEYMGMT simply passes DH structures, so
59*b0d17251Schristos  * we use that here too.
60*b0d17251Schristos  */
61*b0d17251Schristos 
62*b0d17251Schristos typedef struct {
63*b0d17251Schristos     OSSL_LIB_CTX *libctx;
64*b0d17251Schristos     DH *dh;
65*b0d17251Schristos     DH *dhpeer;
66*b0d17251Schristos     unsigned int pad : 1;
67*b0d17251Schristos 
68*b0d17251Schristos     /* DH KDF */
69*b0d17251Schristos     /* KDF (if any) to use for DH */
70*b0d17251Schristos     enum kdf_type kdf_type;
71*b0d17251Schristos     /* Message digest to use for key derivation */
72*b0d17251Schristos     EVP_MD *kdf_md;
73*b0d17251Schristos     /* User key material */
74*b0d17251Schristos     unsigned char *kdf_ukm;
75*b0d17251Schristos     size_t kdf_ukmlen;
76*b0d17251Schristos     /* KDF output length */
77*b0d17251Schristos     size_t kdf_outlen;
78*b0d17251Schristos     char *kdf_cekalg;
79*b0d17251Schristos } PROV_DH_CTX;
80*b0d17251Schristos 
dh_newctx(void * provctx)81*b0d17251Schristos static void *dh_newctx(void *provctx)
82*b0d17251Schristos {
83*b0d17251Schristos     PROV_DH_CTX *pdhctx;
84*b0d17251Schristos 
85*b0d17251Schristos     if (!ossl_prov_is_running())
86*b0d17251Schristos         return NULL;
87*b0d17251Schristos 
88*b0d17251Schristos     pdhctx = OPENSSL_zalloc(sizeof(PROV_DH_CTX));
89*b0d17251Schristos     if (pdhctx == NULL)
90*b0d17251Schristos         return NULL;
91*b0d17251Schristos     pdhctx->libctx = PROV_LIBCTX_OF(provctx);
92*b0d17251Schristos     pdhctx->kdf_type = PROV_DH_KDF_NONE;
93*b0d17251Schristos     return pdhctx;
94*b0d17251Schristos }
95*b0d17251Schristos 
dh_init(void * vpdhctx,void * vdh,const OSSL_PARAM params[])96*b0d17251Schristos static int dh_init(void *vpdhctx, void *vdh, const OSSL_PARAM params[])
97*b0d17251Schristos {
98*b0d17251Schristos     PROV_DH_CTX *pdhctx = (PROV_DH_CTX *)vpdhctx;
99*b0d17251Schristos 
100*b0d17251Schristos     if (!ossl_prov_is_running()
101*b0d17251Schristos             || pdhctx == NULL
102*b0d17251Schristos             || vdh == NULL
103*b0d17251Schristos             || !DH_up_ref(vdh))
104*b0d17251Schristos         return 0;
105*b0d17251Schristos     DH_free(pdhctx->dh);
106*b0d17251Schristos     pdhctx->dh = vdh;
107*b0d17251Schristos     pdhctx->kdf_type = PROV_DH_KDF_NONE;
108*b0d17251Schristos     return dh_set_ctx_params(pdhctx, params)
109*b0d17251Schristos            && ossl_dh_check_key(pdhctx->libctx, vdh);
110*b0d17251Schristos }
111*b0d17251Schristos 
112*b0d17251Schristos /* The 2 parties must share the same domain parameters */
dh_match_params(DH * priv,DH * peer)113*b0d17251Schristos static int dh_match_params(DH *priv, DH *peer)
114*b0d17251Schristos {
115*b0d17251Schristos     int ret;
116*b0d17251Schristos     FFC_PARAMS *dhparams_priv = ossl_dh_get0_params(priv);
117*b0d17251Schristos     FFC_PARAMS *dhparams_peer = ossl_dh_get0_params(peer);
118*b0d17251Schristos 
119*b0d17251Schristos     ret = dhparams_priv != NULL
120*b0d17251Schristos           && dhparams_peer != NULL
121*b0d17251Schristos           && ossl_ffc_params_cmp(dhparams_priv, dhparams_peer, 1);
122*b0d17251Schristos     if (!ret)
123*b0d17251Schristos         ERR_raise(ERR_LIB_PROV, PROV_R_MISMATCHING_DOMAIN_PARAMETERS);
124*b0d17251Schristos     return ret;
125*b0d17251Schristos }
126*b0d17251Schristos 
dh_set_peer(void * vpdhctx,void * vdh)127*b0d17251Schristos static int dh_set_peer(void *vpdhctx, void *vdh)
128*b0d17251Schristos {
129*b0d17251Schristos     PROV_DH_CTX *pdhctx = (PROV_DH_CTX *)vpdhctx;
130*b0d17251Schristos 
131*b0d17251Schristos     if (!ossl_prov_is_running()
132*b0d17251Schristos             || pdhctx == NULL
133*b0d17251Schristos             || vdh == NULL
134*b0d17251Schristos             || !dh_match_params(vdh, pdhctx->dh)
135*b0d17251Schristos             || !DH_up_ref(vdh))
136*b0d17251Schristos         return 0;
137*b0d17251Schristos     DH_free(pdhctx->dhpeer);
138*b0d17251Schristos     pdhctx->dhpeer = vdh;
139*b0d17251Schristos     return 1;
140*b0d17251Schristos }
141*b0d17251Schristos 
dh_plain_derive(void * vpdhctx,unsigned char * secret,size_t * secretlen,size_t outlen,unsigned int pad)142*b0d17251Schristos static int dh_plain_derive(void *vpdhctx,
143*b0d17251Schristos                            unsigned char *secret, size_t *secretlen,
144*b0d17251Schristos                            size_t outlen, unsigned int pad)
145*b0d17251Schristos {
146*b0d17251Schristos     PROV_DH_CTX *pdhctx = (PROV_DH_CTX *)vpdhctx;
147*b0d17251Schristos     int ret;
148*b0d17251Schristos     size_t dhsize;
149*b0d17251Schristos     const BIGNUM *pub_key = NULL;
150*b0d17251Schristos 
151*b0d17251Schristos     if (pdhctx->dh == NULL || pdhctx->dhpeer == NULL) {
152*b0d17251Schristos         ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_KEY);
153*b0d17251Schristos         return 0;
154*b0d17251Schristos     }
155*b0d17251Schristos 
156*b0d17251Schristos     dhsize = (size_t)DH_size(pdhctx->dh);
157*b0d17251Schristos     if (secret == NULL) {
158*b0d17251Schristos         *secretlen = dhsize;
159*b0d17251Schristos         return 1;
160*b0d17251Schristos     }
161*b0d17251Schristos     if (outlen < dhsize) {
162*b0d17251Schristos         ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
163*b0d17251Schristos         return 0;
164*b0d17251Schristos     }
165*b0d17251Schristos 
166*b0d17251Schristos     DH_get0_key(pdhctx->dhpeer, &pub_key, NULL);
167*b0d17251Schristos     if (pad)
168*b0d17251Schristos         ret = DH_compute_key_padded(secret, pub_key, pdhctx->dh);
169*b0d17251Schristos     else
170*b0d17251Schristos         ret = DH_compute_key(secret, pub_key, pdhctx->dh);
171*b0d17251Schristos     if (ret <= 0)
172*b0d17251Schristos         return 0;
173*b0d17251Schristos 
174*b0d17251Schristos     *secretlen = ret;
175*b0d17251Schristos     return 1;
176*b0d17251Schristos }
177*b0d17251Schristos 
dh_X9_42_kdf_derive(void * vpdhctx,unsigned char * secret,size_t * secretlen,size_t outlen)178*b0d17251Schristos static int dh_X9_42_kdf_derive(void *vpdhctx, unsigned char *secret,
179*b0d17251Schristos                                size_t *secretlen, size_t outlen)
180*b0d17251Schristos {
181*b0d17251Schristos     PROV_DH_CTX *pdhctx = (PROV_DH_CTX *)vpdhctx;
182*b0d17251Schristos     unsigned char *stmp = NULL;
183*b0d17251Schristos     size_t stmplen;
184*b0d17251Schristos     int ret = 0;
185*b0d17251Schristos 
186*b0d17251Schristos     if (secret == NULL) {
187*b0d17251Schristos         *secretlen = pdhctx->kdf_outlen;
188*b0d17251Schristos         return 1;
189*b0d17251Schristos     }
190*b0d17251Schristos 
191*b0d17251Schristos     if (pdhctx->kdf_outlen > outlen) {
192*b0d17251Schristos         ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
193*b0d17251Schristos         return 0;
194*b0d17251Schristos     }
195*b0d17251Schristos     if (!dh_plain_derive(pdhctx, NULL, &stmplen, 0, 1))
196*b0d17251Schristos         return 0;
197*b0d17251Schristos     if ((stmp = OPENSSL_secure_malloc(stmplen)) == NULL) {
198*b0d17251Schristos         ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
199*b0d17251Schristos         return 0;
200*b0d17251Schristos     }
201*b0d17251Schristos     if (!dh_plain_derive(pdhctx, stmp, &stmplen, stmplen, 1))
202*b0d17251Schristos         goto err;
203*b0d17251Schristos 
204*b0d17251Schristos     /* Do KDF stuff */
205*b0d17251Schristos     if (pdhctx->kdf_type == PROV_DH_KDF_X9_42_ASN1) {
206*b0d17251Schristos         if (!ossl_dh_kdf_X9_42_asn1(secret, pdhctx->kdf_outlen,
207*b0d17251Schristos                                     stmp, stmplen,
208*b0d17251Schristos                                     pdhctx->kdf_cekalg,
209*b0d17251Schristos                                     pdhctx->kdf_ukm,
210*b0d17251Schristos                                     pdhctx->kdf_ukmlen,
211*b0d17251Schristos                                     pdhctx->kdf_md,
212*b0d17251Schristos                                     pdhctx->libctx, NULL))
213*b0d17251Schristos             goto err;
214*b0d17251Schristos     }
215*b0d17251Schristos     *secretlen = pdhctx->kdf_outlen;
216*b0d17251Schristos     ret = 1;
217*b0d17251Schristos err:
218*b0d17251Schristos     OPENSSL_secure_clear_free(stmp, stmplen);
219*b0d17251Schristos     return ret;
220*b0d17251Schristos }
221*b0d17251Schristos 
dh_derive(void * vpdhctx,unsigned char * secret,size_t * psecretlen,size_t outlen)222*b0d17251Schristos static int dh_derive(void *vpdhctx, unsigned char *secret,
223*b0d17251Schristos                      size_t *psecretlen, size_t outlen)
224*b0d17251Schristos {
225*b0d17251Schristos     PROV_DH_CTX *pdhctx = (PROV_DH_CTX *)vpdhctx;
226*b0d17251Schristos 
227*b0d17251Schristos     if (!ossl_prov_is_running())
228*b0d17251Schristos         return 0;
229*b0d17251Schristos 
230*b0d17251Schristos     switch (pdhctx->kdf_type) {
231*b0d17251Schristos         case PROV_DH_KDF_NONE:
232*b0d17251Schristos             return dh_plain_derive(pdhctx, secret, psecretlen, outlen,
233*b0d17251Schristos                                    pdhctx->pad);
234*b0d17251Schristos         case PROV_DH_KDF_X9_42_ASN1:
235*b0d17251Schristos             return dh_X9_42_kdf_derive(pdhctx, secret, psecretlen, outlen);
236*b0d17251Schristos         default:
237*b0d17251Schristos             break;
238*b0d17251Schristos     }
239*b0d17251Schristos     return 0;
240*b0d17251Schristos }
241*b0d17251Schristos 
dh_freectx(void * vpdhctx)242*b0d17251Schristos static void dh_freectx(void *vpdhctx)
243*b0d17251Schristos {
244*b0d17251Schristos     PROV_DH_CTX *pdhctx = (PROV_DH_CTX *)vpdhctx;
245*b0d17251Schristos 
246*b0d17251Schristos     OPENSSL_free(pdhctx->kdf_cekalg);
247*b0d17251Schristos     DH_free(pdhctx->dh);
248*b0d17251Schristos     DH_free(pdhctx->dhpeer);
249*b0d17251Schristos     EVP_MD_free(pdhctx->kdf_md);
250*b0d17251Schristos     OPENSSL_clear_free(pdhctx->kdf_ukm, pdhctx->kdf_ukmlen);
251*b0d17251Schristos 
252*b0d17251Schristos     OPENSSL_free(pdhctx);
253*b0d17251Schristos }
254*b0d17251Schristos 
dh_dupctx(void * vpdhctx)255*b0d17251Schristos static void *dh_dupctx(void *vpdhctx)
256*b0d17251Schristos {
257*b0d17251Schristos     PROV_DH_CTX *srcctx = (PROV_DH_CTX *)vpdhctx;
258*b0d17251Schristos     PROV_DH_CTX *dstctx;
259*b0d17251Schristos 
260*b0d17251Schristos     if (!ossl_prov_is_running())
261*b0d17251Schristos         return NULL;
262*b0d17251Schristos 
263*b0d17251Schristos     dstctx = OPENSSL_zalloc(sizeof(*srcctx));
264*b0d17251Schristos     if (dstctx == NULL)
265*b0d17251Schristos         return NULL;
266*b0d17251Schristos 
267*b0d17251Schristos     *dstctx = *srcctx;
268*b0d17251Schristos     dstctx->dh = NULL;
269*b0d17251Schristos     dstctx->dhpeer = NULL;
270*b0d17251Schristos     dstctx->kdf_md = NULL;
271*b0d17251Schristos     dstctx->kdf_ukm = NULL;
272*b0d17251Schristos     dstctx->kdf_cekalg = NULL;
273*b0d17251Schristos 
274*b0d17251Schristos     if (srcctx->dh != NULL && !DH_up_ref(srcctx->dh))
275*b0d17251Schristos         goto err;
276*b0d17251Schristos     else
277*b0d17251Schristos         dstctx->dh = srcctx->dh;
278*b0d17251Schristos 
279*b0d17251Schristos     if (srcctx->dhpeer != NULL && !DH_up_ref(srcctx->dhpeer))
280*b0d17251Schristos         goto err;
281*b0d17251Schristos     else
282*b0d17251Schristos         dstctx->dhpeer = srcctx->dhpeer;
283*b0d17251Schristos 
284*b0d17251Schristos     if (srcctx->kdf_md != NULL && !EVP_MD_up_ref(srcctx->kdf_md))
285*b0d17251Schristos         goto err;
286*b0d17251Schristos     else
287*b0d17251Schristos         dstctx->kdf_md = srcctx->kdf_md;
288*b0d17251Schristos 
289*b0d17251Schristos     /* Duplicate UKM data if present */
290*b0d17251Schristos     if (srcctx->kdf_ukm != NULL && srcctx->kdf_ukmlen > 0) {
291*b0d17251Schristos         dstctx->kdf_ukm = OPENSSL_memdup(srcctx->kdf_ukm,
292*b0d17251Schristos                                          srcctx->kdf_ukmlen);
293*b0d17251Schristos         if (dstctx->kdf_ukm == NULL)
294*b0d17251Schristos             goto err;
295*b0d17251Schristos     }
296*b0d17251Schristos 
297*b0d17251Schristos     if (srcctx->kdf_cekalg != NULL) {
298*b0d17251Schristos         dstctx->kdf_cekalg = OPENSSL_strdup(srcctx->kdf_cekalg);
299*b0d17251Schristos         if (dstctx->kdf_cekalg == NULL)
300*b0d17251Schristos             goto err;
301*b0d17251Schristos     }
302*b0d17251Schristos 
303*b0d17251Schristos     return dstctx;
304*b0d17251Schristos err:
305*b0d17251Schristos     dh_freectx(dstctx);
306*b0d17251Schristos     return NULL;
307*b0d17251Schristos }
308*b0d17251Schristos 
dh_set_ctx_params(void * vpdhctx,const OSSL_PARAM params[])309*b0d17251Schristos static int dh_set_ctx_params(void *vpdhctx, const OSSL_PARAM params[])
310*b0d17251Schristos {
311*b0d17251Schristos     PROV_DH_CTX *pdhctx = (PROV_DH_CTX *)vpdhctx;
312*b0d17251Schristos     const OSSL_PARAM *p;
313*b0d17251Schristos     unsigned int pad;
314*b0d17251Schristos     char name[80] = { '\0' }; /* should be big enough */
315*b0d17251Schristos     char *str = NULL;
316*b0d17251Schristos 
317*b0d17251Schristos     if (pdhctx == NULL)
318*b0d17251Schristos         return 0;
319*b0d17251Schristos     if (params == NULL)
320*b0d17251Schristos         return 1;
321*b0d17251Schristos 
322*b0d17251Schristos     p = OSSL_PARAM_locate_const(params, OSSL_EXCHANGE_PARAM_KDF_TYPE);
323*b0d17251Schristos     if (p != NULL) {
324*b0d17251Schristos         str = name;
325*b0d17251Schristos         if (!OSSL_PARAM_get_utf8_string(p, &str, sizeof(name)))
326*b0d17251Schristos             return 0;
327*b0d17251Schristos 
328*b0d17251Schristos         if (name[0] == '\0')
329*b0d17251Schristos             pdhctx->kdf_type = PROV_DH_KDF_NONE;
330*b0d17251Schristos         else if (strcmp(name, OSSL_KDF_NAME_X942KDF_ASN1) == 0)
331*b0d17251Schristos             pdhctx->kdf_type = PROV_DH_KDF_X9_42_ASN1;
332*b0d17251Schristos         else
333*b0d17251Schristos             return 0;
334*b0d17251Schristos     }
335*b0d17251Schristos     p = OSSL_PARAM_locate_const(params, OSSL_EXCHANGE_PARAM_KDF_DIGEST);
336*b0d17251Schristos     if (p != NULL) {
337*b0d17251Schristos         char mdprops[80] = { '\0' }; /* should be big enough */
338*b0d17251Schristos 
339*b0d17251Schristos         str = name;
340*b0d17251Schristos         if (!OSSL_PARAM_get_utf8_string(p, &str, sizeof(name)))
341*b0d17251Schristos             return 0;
342*b0d17251Schristos 
343*b0d17251Schristos         str = mdprops;
344*b0d17251Schristos         p = OSSL_PARAM_locate_const(params,
345*b0d17251Schristos                                     OSSL_EXCHANGE_PARAM_KDF_DIGEST_PROPS);
346*b0d17251Schristos 
347*b0d17251Schristos         if (p != NULL) {
348*b0d17251Schristos             if (!OSSL_PARAM_get_utf8_string(p, &str, sizeof(mdprops)))
349*b0d17251Schristos                 return 0;
350*b0d17251Schristos         }
351*b0d17251Schristos 
352*b0d17251Schristos         EVP_MD_free(pdhctx->kdf_md);
353*b0d17251Schristos         pdhctx->kdf_md = EVP_MD_fetch(pdhctx->libctx, name, mdprops);
354*b0d17251Schristos         if (!ossl_digest_is_allowed(pdhctx->libctx, pdhctx->kdf_md)) {
355*b0d17251Schristos             EVP_MD_free(pdhctx->kdf_md);
356*b0d17251Schristos             pdhctx->kdf_md = NULL;
357*b0d17251Schristos         }
358*b0d17251Schristos         if (pdhctx->kdf_md == NULL)
359*b0d17251Schristos             return 0;
360*b0d17251Schristos     }
361*b0d17251Schristos 
362*b0d17251Schristos     p = OSSL_PARAM_locate_const(params, OSSL_EXCHANGE_PARAM_KDF_OUTLEN);
363*b0d17251Schristos     if (p != NULL) {
364*b0d17251Schristos         size_t outlen;
365*b0d17251Schristos 
366*b0d17251Schristos         if (!OSSL_PARAM_get_size_t(p, &outlen))
367*b0d17251Schristos             return 0;
368*b0d17251Schristos         pdhctx->kdf_outlen = outlen;
369*b0d17251Schristos     }
370*b0d17251Schristos 
371*b0d17251Schristos     p = OSSL_PARAM_locate_const(params, OSSL_EXCHANGE_PARAM_KDF_UKM);
372*b0d17251Schristos     if (p != NULL) {
373*b0d17251Schristos         void *tmp_ukm = NULL;
374*b0d17251Schristos         size_t tmp_ukmlen;
375*b0d17251Schristos 
376*b0d17251Schristos         OPENSSL_free(pdhctx->kdf_ukm);
377*b0d17251Schristos         pdhctx->kdf_ukm = NULL;
378*b0d17251Schristos         pdhctx->kdf_ukmlen = 0;
379*b0d17251Schristos         /* ukm is an optional field so it can be NULL */
380*b0d17251Schristos         if (p->data != NULL && p->data_size != 0) {
381*b0d17251Schristos             if (!OSSL_PARAM_get_octet_string(p, &tmp_ukm, 0, &tmp_ukmlen))
382*b0d17251Schristos                 return 0;
383*b0d17251Schristos             pdhctx->kdf_ukm = tmp_ukm;
384*b0d17251Schristos             pdhctx->kdf_ukmlen = tmp_ukmlen;
385*b0d17251Schristos         }
386*b0d17251Schristos     }
387*b0d17251Schristos 
388*b0d17251Schristos     p = OSSL_PARAM_locate_const(params, OSSL_EXCHANGE_PARAM_PAD);
389*b0d17251Schristos     if (p != NULL) {
390*b0d17251Schristos         if (!OSSL_PARAM_get_uint(p, &pad))
391*b0d17251Schristos             return 0;
392*b0d17251Schristos         pdhctx->pad = pad ? 1 : 0;
393*b0d17251Schristos     }
394*b0d17251Schristos 
395*b0d17251Schristos     p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_CEK_ALG);
396*b0d17251Schristos     if (p != NULL) {
397*b0d17251Schristos         str = name;
398*b0d17251Schristos 
399*b0d17251Schristos         OPENSSL_free(pdhctx->kdf_cekalg);
400*b0d17251Schristos         pdhctx->kdf_cekalg = NULL;
401*b0d17251Schristos         if (p->data != NULL && p->data_size != 0) {
402*b0d17251Schristos             if (!OSSL_PARAM_get_utf8_string(p, &str, sizeof(name)))
403*b0d17251Schristos                 return 0;
404*b0d17251Schristos             pdhctx->kdf_cekalg = OPENSSL_strdup(name);
405*b0d17251Schristos             if (pdhctx->kdf_cekalg == NULL)
406*b0d17251Schristos                 return 0;
407*b0d17251Schristos         }
408*b0d17251Schristos     }
409*b0d17251Schristos     return 1;
410*b0d17251Schristos }
411*b0d17251Schristos 
412*b0d17251Schristos static const OSSL_PARAM known_settable_ctx_params[] = {
413*b0d17251Schristos     OSSL_PARAM_int(OSSL_EXCHANGE_PARAM_PAD, NULL),
414*b0d17251Schristos     OSSL_PARAM_utf8_string(OSSL_EXCHANGE_PARAM_KDF_TYPE, NULL, 0),
415*b0d17251Schristos     OSSL_PARAM_utf8_string(OSSL_EXCHANGE_PARAM_KDF_DIGEST, NULL, 0),
416*b0d17251Schristos     OSSL_PARAM_utf8_string(OSSL_EXCHANGE_PARAM_KDF_DIGEST_PROPS, NULL, 0),
417*b0d17251Schristos     OSSL_PARAM_size_t(OSSL_EXCHANGE_PARAM_KDF_OUTLEN, NULL),
418*b0d17251Schristos     OSSL_PARAM_octet_string(OSSL_EXCHANGE_PARAM_KDF_UKM, NULL, 0),
419*b0d17251Schristos     OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_CEK_ALG, NULL, 0),
420*b0d17251Schristos     OSSL_PARAM_END
421*b0d17251Schristos };
422*b0d17251Schristos 
dh_settable_ctx_params(ossl_unused void * vpdhctx,ossl_unused void * provctx)423*b0d17251Schristos static const OSSL_PARAM *dh_settable_ctx_params(ossl_unused void *vpdhctx,
424*b0d17251Schristos                                                 ossl_unused void *provctx)
425*b0d17251Schristos {
426*b0d17251Schristos     return known_settable_ctx_params;
427*b0d17251Schristos }
428*b0d17251Schristos 
429*b0d17251Schristos static const OSSL_PARAM known_gettable_ctx_params[] = {
430*b0d17251Schristos     OSSL_PARAM_utf8_string(OSSL_EXCHANGE_PARAM_KDF_TYPE, NULL, 0),
431*b0d17251Schristos     OSSL_PARAM_utf8_string(OSSL_EXCHANGE_PARAM_KDF_DIGEST, NULL, 0),
432*b0d17251Schristos     OSSL_PARAM_size_t(OSSL_EXCHANGE_PARAM_KDF_OUTLEN, NULL),
433*b0d17251Schristos     OSSL_PARAM_DEFN(OSSL_EXCHANGE_PARAM_KDF_UKM, OSSL_PARAM_OCTET_PTR,
434*b0d17251Schristos                     NULL, 0),
435*b0d17251Schristos     OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_CEK_ALG, NULL, 0),
436*b0d17251Schristos     OSSL_PARAM_END
437*b0d17251Schristos };
438*b0d17251Schristos 
dh_gettable_ctx_params(ossl_unused void * vpdhctx,ossl_unused void * provctx)439*b0d17251Schristos static const OSSL_PARAM *dh_gettable_ctx_params(ossl_unused void *vpdhctx,
440*b0d17251Schristos                                                 ossl_unused void *provctx)
441*b0d17251Schristos {
442*b0d17251Schristos     return known_gettable_ctx_params;
443*b0d17251Schristos }
444*b0d17251Schristos 
dh_get_ctx_params(void * vpdhctx,OSSL_PARAM params[])445*b0d17251Schristos static int dh_get_ctx_params(void *vpdhctx, OSSL_PARAM params[])
446*b0d17251Schristos {
447*b0d17251Schristos     PROV_DH_CTX *pdhctx = (PROV_DH_CTX *)vpdhctx;
448*b0d17251Schristos     OSSL_PARAM *p;
449*b0d17251Schristos 
450*b0d17251Schristos     if (pdhctx == NULL)
451*b0d17251Schristos         return 0;
452*b0d17251Schristos 
453*b0d17251Schristos     p = OSSL_PARAM_locate(params, OSSL_EXCHANGE_PARAM_KDF_TYPE);
454*b0d17251Schristos     if (p != NULL) {
455*b0d17251Schristos         const char *kdf_type = NULL;
456*b0d17251Schristos 
457*b0d17251Schristos         switch (pdhctx->kdf_type) {
458*b0d17251Schristos             case PROV_DH_KDF_NONE:
459*b0d17251Schristos                 kdf_type = "";
460*b0d17251Schristos                 break;
461*b0d17251Schristos             case PROV_DH_KDF_X9_42_ASN1:
462*b0d17251Schristos                 kdf_type = OSSL_KDF_NAME_X942KDF_ASN1;
463*b0d17251Schristos                 break;
464*b0d17251Schristos             default:
465*b0d17251Schristos                 return 0;
466*b0d17251Schristos         }
467*b0d17251Schristos 
468*b0d17251Schristos         if (!OSSL_PARAM_set_utf8_string(p, kdf_type))
469*b0d17251Schristos             return 0;
470*b0d17251Schristos     }
471*b0d17251Schristos 
472*b0d17251Schristos     p = OSSL_PARAM_locate(params, OSSL_EXCHANGE_PARAM_KDF_DIGEST);
473*b0d17251Schristos     if (p != NULL
474*b0d17251Schristos             && !OSSL_PARAM_set_utf8_string(p, pdhctx->kdf_md == NULL
475*b0d17251Schristos                                            ? ""
476*b0d17251Schristos                                            : EVP_MD_get0_name(pdhctx->kdf_md))){
477*b0d17251Schristos         return 0;
478*b0d17251Schristos     }
479*b0d17251Schristos 
480*b0d17251Schristos     p = OSSL_PARAM_locate(params, OSSL_EXCHANGE_PARAM_KDF_OUTLEN);
481*b0d17251Schristos     if (p != NULL && !OSSL_PARAM_set_size_t(p, pdhctx->kdf_outlen))
482*b0d17251Schristos         return 0;
483*b0d17251Schristos 
484*b0d17251Schristos     p = OSSL_PARAM_locate(params, OSSL_EXCHANGE_PARAM_KDF_UKM);
485*b0d17251Schristos     if (p != NULL
486*b0d17251Schristos         && !OSSL_PARAM_set_octet_ptr(p, pdhctx->kdf_ukm, pdhctx->kdf_ukmlen))
487*b0d17251Schristos         return 0;
488*b0d17251Schristos 
489*b0d17251Schristos     p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_CEK_ALG);
490*b0d17251Schristos     if (p != NULL
491*b0d17251Schristos             && !OSSL_PARAM_set_utf8_string(p, pdhctx->kdf_cekalg == NULL
492*b0d17251Schristos                                            ? "" :  pdhctx->kdf_cekalg))
493*b0d17251Schristos         return 0;
494*b0d17251Schristos 
495*b0d17251Schristos     return 1;
496*b0d17251Schristos }
497*b0d17251Schristos 
498*b0d17251Schristos const OSSL_DISPATCH ossl_dh_keyexch_functions[] = {
499*b0d17251Schristos     { OSSL_FUNC_KEYEXCH_NEWCTX, (void (*)(void))dh_newctx },
500*b0d17251Schristos     { OSSL_FUNC_KEYEXCH_INIT, (void (*)(void))dh_init },
501*b0d17251Schristos     { OSSL_FUNC_KEYEXCH_DERIVE, (void (*)(void))dh_derive },
502*b0d17251Schristos     { OSSL_FUNC_KEYEXCH_SET_PEER, (void (*)(void))dh_set_peer },
503*b0d17251Schristos     { OSSL_FUNC_KEYEXCH_FREECTX, (void (*)(void))dh_freectx },
504*b0d17251Schristos     { OSSL_FUNC_KEYEXCH_DUPCTX, (void (*)(void))dh_dupctx },
505*b0d17251Schristos     { OSSL_FUNC_KEYEXCH_SET_CTX_PARAMS, (void (*)(void))dh_set_ctx_params },
506*b0d17251Schristos     { OSSL_FUNC_KEYEXCH_SETTABLE_CTX_PARAMS,
507*b0d17251Schristos       (void (*)(void))dh_settable_ctx_params },
508*b0d17251Schristos     { OSSL_FUNC_KEYEXCH_GET_CTX_PARAMS, (void (*)(void))dh_get_ctx_params },
509*b0d17251Schristos     { OSSL_FUNC_KEYEXCH_GETTABLE_CTX_PARAMS,
510*b0d17251Schristos       (void (*)(void))dh_gettable_ctx_params },
511*b0d17251Schristos     { 0, NULL }
512*b0d17251Schristos };
513