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