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