2 * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
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
11 * DH low level APIs are deprecated for public use, but still ok for
14 #include "internal/deprecated.h"
17 #include <openssl/crypto.h>
18 #include <openssl/core_dispatch.h>
19 #include <openssl/core_names.h>
20 #include <openssl/dh.h>
21 #include <openssl/err.h>
22 #include <openssl/params.h>
23 #include "prov/providercommon.h"
24 #include "prov/implementations.h"
25 #include "prov/provider_ctx.h"
26 #include "prov/securitycheck.h"
27 #include "crypto/dh.h"
29 static OSSL_FUNC_keyexch_newctx_fn dh_newctx
;
30 static OSSL_FUNC_keyexch_init_fn dh_init
;
31 static OSSL_FUNC_keyexch_set_peer_fn dh_set_peer
;
32 static OSSL_FUNC_keyexch_derive_fn dh_derive
;
33 static OSSL_FUNC_keyexch_freectx_fn dh_freectx
;
34 static OSSL_FUNC_keyexch_dupctx_fn dh_dupctx
;
35 static OSSL_FUNC_keyexch_set_ctx_params_fn dh_set_ctx_params
;
36 static OSSL_FUNC_keyexch_settable_ctx_params_fn dh_settable_ctx_params
;
37 static OSSL_FUNC_keyexch_get_ctx_params_fn dh_get_ctx_params
;
38 static OSSL_FUNC_keyexch_gettable_ctx_params_fn dh_gettable_ctx_params
;
41 * This type is only really used to handle some legacy related functionality.
42 * If you need to use other KDF's (such as SSKDF) just use PROV_DH_KDF_NONE
43 * here and then create and run a KDF after the key is derived.
44 * Note that X942 has 2 variants of key derivation:
45 * (1) DH_KDF_X9_42_ASN1 - which contains an ANS1 encoded object that has
46 * the counter embedded in it.
47 * (2) DH_KDF_X941_CONCAT - which is the same as ECDH_X963_KDF (which can be
48 * done by creating a "X963KDF".
52 PROV_DH_KDF_X9_42_ASN1
56 * What's passed as an actual key is defined by the KEYMGMT interface.
57 * We happen to know that our KEYMGMT simply passes DH structures, so
58 * we use that here too.
68 /* KDF (if any) to use for DH */
69 enum kdf_type kdf_type
;
70 /* Message digest to use for key derivation */
72 /* User key material */
73 unsigned char *kdf_ukm
;
75 /* KDF output length */
80 static void *dh_newctx(void *provctx
)
84 if (!ossl_prov_is_running())
87 pdhctx
= OPENSSL_zalloc(sizeof(PROV_DH_CTX
));
90 pdhctx
->libctx
= PROV_LIBCTX_OF(provctx
);
91 pdhctx
->kdf_type
= PROV_DH_KDF_NONE
;
95 static int dh_init(void *vpdhctx
, void *vdh
)
97 PROV_DH_CTX
*pdhctx
= (PROV_DH_CTX
*)vpdhctx
;
99 if (!ossl_prov_is_running()
106 pdhctx
->kdf_type
= PROV_DH_KDF_NONE
;
107 return ossl_dh_check_key(vdh
);
110 static int dh_set_peer(void *vpdhctx
, void *vdh
)
112 PROV_DH_CTX
*pdhctx
= (PROV_DH_CTX
*)vpdhctx
;
114 if (!ossl_prov_is_running()
119 DH_free(pdhctx
->dhpeer
);
120 pdhctx
->dhpeer
= vdh
;
124 static int dh_plain_derive(void *vpdhctx
,
125 unsigned char *secret
, size_t *secretlen
,
128 PROV_DH_CTX
*pdhctx
= (PROV_DH_CTX
*)vpdhctx
;
131 const BIGNUM
*pub_key
= NULL
;
133 /* TODO(3.0): Add errors to stack */
134 if (pdhctx
->dh
== NULL
|| pdhctx
->dhpeer
== NULL
)
137 dhsize
= (size_t)DH_size(pdhctx
->dh
);
138 if (secret
== NULL
) {
145 DH_get0_key(pdhctx
->dhpeer
, &pub_key
, NULL
);
147 ret
= DH_compute_key_padded(secret
, pub_key
, pdhctx
->dh
);
149 ret
= DH_compute_key(secret
, pub_key
, pdhctx
->dh
);
157 static int dh_X9_42_kdf_derive(void *vpdhctx
, unsigned char *secret
,
158 size_t *secretlen
, size_t outlen
)
160 PROV_DH_CTX
*pdhctx
= (PROV_DH_CTX
*)vpdhctx
;
161 unsigned char *stmp
= NULL
;
165 if (secret
== NULL
) {
166 *secretlen
= pdhctx
->kdf_outlen
;
170 if (pdhctx
->kdf_outlen
> outlen
)
172 if (!dh_plain_derive(pdhctx
, NULL
, &stmplen
, 0))
174 if ((stmp
= OPENSSL_secure_malloc(stmplen
)) == NULL
) {
175 ERR_raise(ERR_LIB_PROV
, ERR_R_MALLOC_FAILURE
);
178 if (!dh_plain_derive(pdhctx
, stmp
, &stmplen
, stmplen
))
182 if (pdhctx
->kdf_type
== PROV_DH_KDF_X9_42_ASN1
) {
183 if (!dh_KDF_X9_42_asn1(secret
, pdhctx
->kdf_outlen
,
189 pdhctx
->libctx
, NULL
))
192 *secretlen
= pdhctx
->kdf_outlen
;
195 OPENSSL_secure_clear_free(stmp
, stmplen
);
199 static int dh_derive(void *vpdhctx
, unsigned char *secret
,
200 size_t *psecretlen
, size_t outlen
)
202 PROV_DH_CTX
*pdhctx
= (PROV_DH_CTX
*)vpdhctx
;
204 if (!ossl_prov_is_running())
207 switch (pdhctx
->kdf_type
) {
208 case PROV_DH_KDF_NONE
:
209 return dh_plain_derive(pdhctx
, secret
, psecretlen
, outlen
);
210 case PROV_DH_KDF_X9_42_ASN1
:
211 return dh_X9_42_kdf_derive(pdhctx
, secret
, psecretlen
, outlen
);
219 static void dh_freectx(void *vpdhctx
)
221 PROV_DH_CTX
*pdhctx
= (PROV_DH_CTX
*)vpdhctx
;
223 OPENSSL_free(pdhctx
->kdf_cekalg
);
225 DH_free(pdhctx
->dhpeer
);
226 EVP_MD_free(pdhctx
->kdf_md
);
227 OPENSSL_clear_free(pdhctx
->kdf_ukm
, pdhctx
->kdf_ukmlen
);
229 OPENSSL_free(pdhctx
);
232 static void *dh_dupctx(void *vpdhctx
)
234 PROV_DH_CTX
*srcctx
= (PROV_DH_CTX
*)vpdhctx
;
237 if (!ossl_prov_is_running())
240 dstctx
= OPENSSL_zalloc(sizeof(*srcctx
));
246 dstctx
->dhpeer
= NULL
;
247 dstctx
->kdf_md
= NULL
;
248 dstctx
->kdf_ukm
= NULL
;
249 dstctx
->kdf_cekalg
= NULL
;
251 if (dstctx
->dh
!= NULL
&& !DH_up_ref(srcctx
->dh
))
254 dstctx
->dh
= srcctx
->dh
;
256 if (dstctx
->dhpeer
!= NULL
&& !DH_up_ref(srcctx
->dhpeer
))
259 dstctx
->dhpeer
= srcctx
->dhpeer
;
261 if (srcctx
->kdf_md
!= NULL
&& !EVP_MD_up_ref(srcctx
->kdf_md
))
264 dstctx
->kdf_md
= srcctx
->kdf_md
;
266 /* Duplicate UKM data if present */
267 if (srcctx
->kdf_ukm
!= NULL
&& srcctx
->kdf_ukmlen
> 0) {
268 dstctx
->kdf_ukm
= OPENSSL_memdup(srcctx
->kdf_ukm
,
270 if (dstctx
->kdf_ukm
== NULL
)
273 dstctx
->kdf_cekalg
= OPENSSL_strdup(srcctx
->kdf_cekalg
);
281 static int dh_set_ctx_params(void *vpdhctx
, const OSSL_PARAM params
[])
283 PROV_DH_CTX
*pdhctx
= (PROV_DH_CTX
*)vpdhctx
;
286 char name
[80] = { '\0' }; /* should be big enough */
289 if (pdhctx
== NULL
|| params
== NULL
)
292 p
= OSSL_PARAM_locate_const(params
, OSSL_EXCHANGE_PARAM_KDF_TYPE
);
295 if (!OSSL_PARAM_get_utf8_string(p
, &str
, sizeof(name
)))
299 pdhctx
->kdf_type
= PROV_DH_KDF_NONE
;
300 else if (strcmp(name
, OSSL_KDF_NAME_X942KDF_ASN1
) == 0)
301 pdhctx
->kdf_type
= PROV_DH_KDF_X9_42_ASN1
;
305 p
= OSSL_PARAM_locate_const(params
, OSSL_EXCHANGE_PARAM_KDF_DIGEST
);
307 char mdprops
[80] = { '\0' }; /* should be big enough */
310 if (!OSSL_PARAM_get_utf8_string(p
, &str
, sizeof(name
)))
314 p
= OSSL_PARAM_locate_const(params
,
315 OSSL_EXCHANGE_PARAM_KDF_DIGEST_PROPS
);
318 if (!OSSL_PARAM_get_utf8_string(p
, &str
, sizeof(mdprops
)))
322 EVP_MD_free(pdhctx
->kdf_md
);
323 pdhctx
->kdf_md
= EVP_MD_fetch(pdhctx
->libctx
, name
, mdprops
);
324 if (!ossl_digest_is_allowed(pdhctx
->kdf_md
)) {
325 EVP_MD_free(pdhctx
->kdf_md
);
326 pdhctx
->kdf_md
= NULL
;
328 if (pdhctx
->kdf_md
== NULL
)
332 p
= OSSL_PARAM_locate_const(params
, OSSL_EXCHANGE_PARAM_KDF_OUTLEN
);
336 if (!OSSL_PARAM_get_size_t(p
, &outlen
))
338 pdhctx
->kdf_outlen
= outlen
;
341 p
= OSSL_PARAM_locate_const(params
, OSSL_EXCHANGE_PARAM_KDF_UKM
);
343 void *tmp_ukm
= NULL
;
346 OPENSSL_free(pdhctx
->kdf_ukm
);
347 pdhctx
->kdf_ukm
= NULL
;
348 pdhctx
->kdf_ukmlen
= 0;
349 /* ukm is an optional field so it can be NULL */
350 if (p
->data
!= NULL
&& p
->data_size
!= 0) {
351 if (!OSSL_PARAM_get_octet_string(p
, &tmp_ukm
, 0, &tmp_ukmlen
))
353 pdhctx
->kdf_ukm
= tmp_ukm
;
354 pdhctx
->kdf_ukmlen
= tmp_ukmlen
;
358 p
= OSSL_PARAM_locate_const(params
, OSSL_EXCHANGE_PARAM_PAD
);
360 if (!OSSL_PARAM_get_uint(p
, &pad
))
362 pdhctx
->pad
= pad
? 1 : 0;
365 p
= OSSL_PARAM_locate_const(params
, OSSL_KDF_PARAM_CEK_ALG
);
368 if (!OSSL_PARAM_get_utf8_string(p
, &str
, sizeof(name
)))
370 pdhctx
->kdf_cekalg
= OPENSSL_strdup(name
);
375 static const OSSL_PARAM known_settable_ctx_params
[] = {
376 OSSL_PARAM_int(OSSL_EXCHANGE_PARAM_PAD
, NULL
),
377 OSSL_PARAM_utf8_string(OSSL_EXCHANGE_PARAM_KDF_TYPE
, NULL
, 0),
378 OSSL_PARAM_utf8_string(OSSL_EXCHANGE_PARAM_KDF_DIGEST
, NULL
, 0),
379 OSSL_PARAM_utf8_string(OSSL_EXCHANGE_PARAM_KDF_DIGEST_PROPS
, NULL
, 0),
380 OSSL_PARAM_size_t(OSSL_EXCHANGE_PARAM_KDF_OUTLEN
, NULL
),
381 OSSL_PARAM_octet_string(OSSL_EXCHANGE_PARAM_KDF_UKM
, NULL
, 0),
382 OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_CEK_ALG
, NULL
, 0),
386 static const OSSL_PARAM
*dh_settable_ctx_params(ossl_unused
void *provctx
)
388 return known_settable_ctx_params
;
391 static const OSSL_PARAM known_gettable_ctx_params
[] = {
392 OSSL_PARAM_int(OSSL_EXCHANGE_PARAM_EC_ECDH_COFACTOR_MODE
, NULL
),
393 OSSL_PARAM_utf8_string(OSSL_EXCHANGE_PARAM_KDF_TYPE
, NULL
, 0),
394 OSSL_PARAM_utf8_string(OSSL_EXCHANGE_PARAM_KDF_DIGEST
, NULL
, 0),
395 OSSL_PARAM_size_t(OSSL_EXCHANGE_PARAM_KDF_OUTLEN
, NULL
),
396 OSSL_PARAM_DEFN(OSSL_EXCHANGE_PARAM_KDF_UKM
, OSSL_PARAM_OCTET_PTR
,
401 static const OSSL_PARAM
*dh_gettable_ctx_params(ossl_unused
void *provctx
)
403 return known_gettable_ctx_params
;
406 static int dh_get_ctx_params(void *vpdhctx
, OSSL_PARAM params
[])
408 PROV_DH_CTX
*pdhctx
= (PROV_DH_CTX
*)vpdhctx
;
411 if (pdhctx
== NULL
|| params
== NULL
)
414 p
= OSSL_PARAM_locate(params
, OSSL_EXCHANGE_PARAM_KDF_TYPE
);
416 const char *kdf_type
= NULL
;
418 switch (pdhctx
->kdf_type
) {
419 case PROV_DH_KDF_NONE
:
422 case PROV_DH_KDF_X9_42_ASN1
:
423 kdf_type
= OSSL_KDF_NAME_X942KDF_ASN1
;
429 if (!OSSL_PARAM_set_utf8_string(p
, kdf_type
))
433 p
= OSSL_PARAM_locate(params
, OSSL_EXCHANGE_PARAM_KDF_DIGEST
);
435 && !OSSL_PARAM_set_utf8_string(p
, pdhctx
->kdf_md
== NULL
437 : EVP_MD_name(pdhctx
->kdf_md
))){
441 p
= OSSL_PARAM_locate(params
, OSSL_EXCHANGE_PARAM_KDF_OUTLEN
);
442 if (p
!= NULL
&& !OSSL_PARAM_set_size_t(p
, pdhctx
->kdf_outlen
))
445 p
= OSSL_PARAM_locate(params
, OSSL_EXCHANGE_PARAM_KDF_UKM
);
447 && !OSSL_PARAM_set_octet_ptr(p
, pdhctx
->kdf_ukm
, pdhctx
->kdf_ukmlen
))
450 p
= OSSL_PARAM_locate(params
, OSSL_KDF_PARAM_CEK_ALG
);
452 && !OSSL_PARAM_set_utf8_string(p
, pdhctx
->kdf_cekalg
== NULL
453 ? "" : pdhctx
->kdf_cekalg
))
459 const OSSL_DISPATCH ossl_dh_keyexch_functions
[] = {
460 { OSSL_FUNC_KEYEXCH_NEWCTX
, (void (*)(void))dh_newctx
},
461 { OSSL_FUNC_KEYEXCH_INIT
, (void (*)(void))dh_init
},
462 { OSSL_FUNC_KEYEXCH_DERIVE
, (void (*)(void))dh_derive
},
463 { OSSL_FUNC_KEYEXCH_SET_PEER
, (void (*)(void))dh_set_peer
},
464 { OSSL_FUNC_KEYEXCH_FREECTX
, (void (*)(void))dh_freectx
},
465 { OSSL_FUNC_KEYEXCH_DUPCTX
, (void (*)(void))dh_dupctx
},
466 { OSSL_FUNC_KEYEXCH_SET_CTX_PARAMS
, (void (*)(void))dh_set_ctx_params
},
467 { OSSL_FUNC_KEYEXCH_SETTABLE_CTX_PARAMS
,
468 (void (*)(void))dh_settable_ctx_params
},
469 { OSSL_FUNC_KEYEXCH_GET_CTX_PARAMS
, (void (*)(void))dh_get_ctx_params
},
470 { OSSL_FUNC_KEYEXCH_GETTABLE_CTX_PARAMS
,
471 (void (*)(void))dh_gettable_ctx_params
},