1e1051a39Sopenharmony_ci/* 2e1051a39Sopenharmony_ci * Copyright 2020-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 <openssl/err.h> 17e1051a39Sopenharmony_ci#include <openssl/core_names.h> 18e1051a39Sopenharmony_ci#ifndef FIPS_MODULE 19e1051a39Sopenharmony_ci# include <openssl/x509.h> 20e1051a39Sopenharmony_ci#endif 21e1051a39Sopenharmony_ci#include "internal/param_build_set.h" 22e1051a39Sopenharmony_ci#include "crypto/dh.h" 23e1051a39Sopenharmony_ci#include "dh_local.h" 24e1051a39Sopenharmony_ci 25e1051a39Sopenharmony_ci/* 26e1051a39Sopenharmony_ci * The intention with the "backend" source file is to offer backend functions 27e1051a39Sopenharmony_ci * for legacy backends (EVP_PKEY_ASN1_METHOD and EVP_PKEY_METHOD) and provider 28e1051a39Sopenharmony_ci * implementations alike. 29e1051a39Sopenharmony_ci */ 30e1051a39Sopenharmony_ci 31e1051a39Sopenharmony_cistatic int dh_ffc_params_fromdata(DH *dh, const OSSL_PARAM params[]) 32e1051a39Sopenharmony_ci{ 33e1051a39Sopenharmony_ci int ret; 34e1051a39Sopenharmony_ci FFC_PARAMS *ffc; 35e1051a39Sopenharmony_ci 36e1051a39Sopenharmony_ci if (dh == NULL) 37e1051a39Sopenharmony_ci return 0; 38e1051a39Sopenharmony_ci ffc = ossl_dh_get0_params(dh); 39e1051a39Sopenharmony_ci if (ffc == NULL) 40e1051a39Sopenharmony_ci return 0; 41e1051a39Sopenharmony_ci 42e1051a39Sopenharmony_ci ret = ossl_ffc_params_fromdata(ffc, params); 43e1051a39Sopenharmony_ci if (ret) 44e1051a39Sopenharmony_ci ossl_dh_cache_named_group(dh); /* This increments dh->dirty_cnt */ 45e1051a39Sopenharmony_ci return ret; 46e1051a39Sopenharmony_ci} 47e1051a39Sopenharmony_ci 48e1051a39Sopenharmony_ciint ossl_dh_params_fromdata(DH *dh, const OSSL_PARAM params[]) 49e1051a39Sopenharmony_ci{ 50e1051a39Sopenharmony_ci const OSSL_PARAM *param_priv_len; 51e1051a39Sopenharmony_ci long priv_len; 52e1051a39Sopenharmony_ci 53e1051a39Sopenharmony_ci if (!dh_ffc_params_fromdata(dh, params)) 54e1051a39Sopenharmony_ci return 0; 55e1051a39Sopenharmony_ci 56e1051a39Sopenharmony_ci param_priv_len = 57e1051a39Sopenharmony_ci OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_DH_PRIV_LEN); 58e1051a39Sopenharmony_ci if (param_priv_len != NULL 59e1051a39Sopenharmony_ci && (!OSSL_PARAM_get_long(param_priv_len, &priv_len) 60e1051a39Sopenharmony_ci || !DH_set_length(dh, priv_len))) 61e1051a39Sopenharmony_ci return 0; 62e1051a39Sopenharmony_ci 63e1051a39Sopenharmony_ci return 1; 64e1051a39Sopenharmony_ci} 65e1051a39Sopenharmony_ci 66e1051a39Sopenharmony_ciint ossl_dh_key_fromdata(DH *dh, const OSSL_PARAM params[], int include_private) 67e1051a39Sopenharmony_ci{ 68e1051a39Sopenharmony_ci const OSSL_PARAM *param_priv_key, *param_pub_key; 69e1051a39Sopenharmony_ci BIGNUM *priv_key = NULL, *pub_key = NULL; 70e1051a39Sopenharmony_ci 71e1051a39Sopenharmony_ci if (dh == NULL) 72e1051a39Sopenharmony_ci return 0; 73e1051a39Sopenharmony_ci 74e1051a39Sopenharmony_ci param_priv_key = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PRIV_KEY); 75e1051a39Sopenharmony_ci param_pub_key = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PUB_KEY); 76e1051a39Sopenharmony_ci 77e1051a39Sopenharmony_ci if (include_private 78e1051a39Sopenharmony_ci && param_priv_key != NULL 79e1051a39Sopenharmony_ci && !OSSL_PARAM_get_BN(param_priv_key, &priv_key)) 80e1051a39Sopenharmony_ci goto err; 81e1051a39Sopenharmony_ci 82e1051a39Sopenharmony_ci if (param_pub_key != NULL 83e1051a39Sopenharmony_ci && !OSSL_PARAM_get_BN(param_pub_key, &pub_key)) 84e1051a39Sopenharmony_ci goto err; 85e1051a39Sopenharmony_ci 86e1051a39Sopenharmony_ci if (!DH_set0_key(dh, pub_key, priv_key)) 87e1051a39Sopenharmony_ci goto err; 88e1051a39Sopenharmony_ci 89e1051a39Sopenharmony_ci return 1; 90e1051a39Sopenharmony_ci 91e1051a39Sopenharmony_ci err: 92e1051a39Sopenharmony_ci BN_clear_free(priv_key); 93e1051a39Sopenharmony_ci BN_free(pub_key); 94e1051a39Sopenharmony_ci return 0; 95e1051a39Sopenharmony_ci} 96e1051a39Sopenharmony_ci 97e1051a39Sopenharmony_ciint ossl_dh_params_todata(DH *dh, OSSL_PARAM_BLD *bld, OSSL_PARAM params[]) 98e1051a39Sopenharmony_ci{ 99e1051a39Sopenharmony_ci long l = DH_get_length(dh); 100e1051a39Sopenharmony_ci 101e1051a39Sopenharmony_ci if (!ossl_ffc_params_todata(ossl_dh_get0_params(dh), bld, params)) 102e1051a39Sopenharmony_ci return 0; 103e1051a39Sopenharmony_ci if (l > 0 104e1051a39Sopenharmony_ci && !ossl_param_build_set_long(bld, params, OSSL_PKEY_PARAM_DH_PRIV_LEN, l)) 105e1051a39Sopenharmony_ci return 0; 106e1051a39Sopenharmony_ci return 1; 107e1051a39Sopenharmony_ci} 108e1051a39Sopenharmony_ci 109e1051a39Sopenharmony_ciint ossl_dh_key_todata(DH *dh, OSSL_PARAM_BLD *bld, OSSL_PARAM params[], 110e1051a39Sopenharmony_ci int include_private) 111e1051a39Sopenharmony_ci{ 112e1051a39Sopenharmony_ci const BIGNUM *priv = NULL, *pub = NULL; 113e1051a39Sopenharmony_ci 114e1051a39Sopenharmony_ci if (dh == NULL) 115e1051a39Sopenharmony_ci return 0; 116e1051a39Sopenharmony_ci 117e1051a39Sopenharmony_ci DH_get0_key(dh, &pub, &priv); 118e1051a39Sopenharmony_ci if (priv != NULL 119e1051a39Sopenharmony_ci && include_private 120e1051a39Sopenharmony_ci && !ossl_param_build_set_bn(bld, params, OSSL_PKEY_PARAM_PRIV_KEY, priv)) 121e1051a39Sopenharmony_ci return 0; 122e1051a39Sopenharmony_ci if (pub != NULL 123e1051a39Sopenharmony_ci && !ossl_param_build_set_bn(bld, params, OSSL_PKEY_PARAM_PUB_KEY, pub)) 124e1051a39Sopenharmony_ci return 0; 125e1051a39Sopenharmony_ci 126e1051a39Sopenharmony_ci return 1; 127e1051a39Sopenharmony_ci} 128e1051a39Sopenharmony_ci 129e1051a39Sopenharmony_ciint ossl_dh_is_foreign(const DH *dh) 130e1051a39Sopenharmony_ci{ 131e1051a39Sopenharmony_ci#ifndef FIPS_MODULE 132e1051a39Sopenharmony_ci if (dh->engine != NULL || ossl_dh_get_method(dh) != DH_OpenSSL()) 133e1051a39Sopenharmony_ci return 1; 134e1051a39Sopenharmony_ci#endif 135e1051a39Sopenharmony_ci return 0; 136e1051a39Sopenharmony_ci} 137e1051a39Sopenharmony_ci 138e1051a39Sopenharmony_cistatic ossl_inline int dh_bn_dup_check(BIGNUM **out, const BIGNUM *f) 139e1051a39Sopenharmony_ci{ 140e1051a39Sopenharmony_ci if (f != NULL && (*out = BN_dup(f)) == NULL) 141e1051a39Sopenharmony_ci return 0; 142e1051a39Sopenharmony_ci return 1; 143e1051a39Sopenharmony_ci} 144e1051a39Sopenharmony_ci 145e1051a39Sopenharmony_ciDH *ossl_dh_dup(const DH *dh, int selection) 146e1051a39Sopenharmony_ci{ 147e1051a39Sopenharmony_ci DH *dupkey = NULL; 148e1051a39Sopenharmony_ci 149e1051a39Sopenharmony_ci /* Do not try to duplicate foreign DH keys */ 150e1051a39Sopenharmony_ci if (ossl_dh_is_foreign(dh)) 151e1051a39Sopenharmony_ci return NULL; 152e1051a39Sopenharmony_ci 153e1051a39Sopenharmony_ci if ((dupkey = ossl_dh_new_ex(dh->libctx)) == NULL) 154e1051a39Sopenharmony_ci return NULL; 155e1051a39Sopenharmony_ci 156e1051a39Sopenharmony_ci dupkey->length = DH_get_length(dh); 157e1051a39Sopenharmony_ci if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0 158e1051a39Sopenharmony_ci && !ossl_ffc_params_copy(&dupkey->params, &dh->params)) 159e1051a39Sopenharmony_ci goto err; 160e1051a39Sopenharmony_ci 161e1051a39Sopenharmony_ci dupkey->flags = dh->flags; 162e1051a39Sopenharmony_ci 163e1051a39Sopenharmony_ci if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0 164e1051a39Sopenharmony_ci && ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) == 0 165e1051a39Sopenharmony_ci || !dh_bn_dup_check(&dupkey->pub_key, dh->pub_key))) 166e1051a39Sopenharmony_ci goto err; 167e1051a39Sopenharmony_ci 168e1051a39Sopenharmony_ci if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0 169e1051a39Sopenharmony_ci && ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) == 0 170e1051a39Sopenharmony_ci || !dh_bn_dup_check(&dupkey->priv_key, dh->priv_key))) 171e1051a39Sopenharmony_ci goto err; 172e1051a39Sopenharmony_ci 173e1051a39Sopenharmony_ci#ifndef FIPS_MODULE 174e1051a39Sopenharmony_ci if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_DH, 175e1051a39Sopenharmony_ci &dupkey->ex_data, &dh->ex_data)) 176e1051a39Sopenharmony_ci goto err; 177e1051a39Sopenharmony_ci#endif 178e1051a39Sopenharmony_ci 179e1051a39Sopenharmony_ci return dupkey; 180e1051a39Sopenharmony_ci 181e1051a39Sopenharmony_ci err: 182e1051a39Sopenharmony_ci DH_free(dupkey); 183e1051a39Sopenharmony_ci return NULL; 184e1051a39Sopenharmony_ci} 185e1051a39Sopenharmony_ci 186e1051a39Sopenharmony_ci#ifndef FIPS_MODULE 187e1051a39Sopenharmony_ciDH *ossl_dh_key_from_pkcs8(const PKCS8_PRIV_KEY_INFO *p8inf, 188e1051a39Sopenharmony_ci OSSL_LIB_CTX *libctx, const char *propq) 189e1051a39Sopenharmony_ci{ 190e1051a39Sopenharmony_ci const unsigned char *p, *pm; 191e1051a39Sopenharmony_ci int pklen, pmlen; 192e1051a39Sopenharmony_ci int ptype; 193e1051a39Sopenharmony_ci const void *pval; 194e1051a39Sopenharmony_ci const ASN1_STRING *pstr; 195e1051a39Sopenharmony_ci const X509_ALGOR *palg; 196e1051a39Sopenharmony_ci BIGNUM *privkey_bn = NULL; 197e1051a39Sopenharmony_ci ASN1_INTEGER *privkey = NULL; 198e1051a39Sopenharmony_ci DH *dh = NULL; 199e1051a39Sopenharmony_ci 200e1051a39Sopenharmony_ci if (!PKCS8_pkey_get0(NULL, &p, &pklen, &palg, p8inf)) 201e1051a39Sopenharmony_ci return 0; 202e1051a39Sopenharmony_ci 203e1051a39Sopenharmony_ci X509_ALGOR_get0(NULL, &ptype, &pval, palg); 204e1051a39Sopenharmony_ci 205e1051a39Sopenharmony_ci if (ptype != V_ASN1_SEQUENCE) 206e1051a39Sopenharmony_ci goto decerr; 207e1051a39Sopenharmony_ci if ((privkey = d2i_ASN1_INTEGER(NULL, &p, pklen)) == NULL) 208e1051a39Sopenharmony_ci goto decerr; 209e1051a39Sopenharmony_ci 210e1051a39Sopenharmony_ci pstr = pval; 211e1051a39Sopenharmony_ci pm = pstr->data; 212e1051a39Sopenharmony_ci pmlen = pstr->length; 213e1051a39Sopenharmony_ci switch (OBJ_obj2nid(palg->algorithm)) { 214e1051a39Sopenharmony_ci case NID_dhKeyAgreement: 215e1051a39Sopenharmony_ci dh = d2i_DHparams(NULL, &pm, pmlen); 216e1051a39Sopenharmony_ci break; 217e1051a39Sopenharmony_ci case NID_dhpublicnumber: 218e1051a39Sopenharmony_ci dh = d2i_DHxparams(NULL, &pm, pmlen); 219e1051a39Sopenharmony_ci break; 220e1051a39Sopenharmony_ci default: 221e1051a39Sopenharmony_ci goto decerr; 222e1051a39Sopenharmony_ci } 223e1051a39Sopenharmony_ci if (dh == NULL) 224e1051a39Sopenharmony_ci goto decerr; 225e1051a39Sopenharmony_ci 226e1051a39Sopenharmony_ci /* We have parameters now set private key */ 227e1051a39Sopenharmony_ci if ((privkey_bn = BN_secure_new()) == NULL 228e1051a39Sopenharmony_ci || !ASN1_INTEGER_to_BN(privkey, privkey_bn)) { 229e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_DH, DH_R_BN_ERROR); 230e1051a39Sopenharmony_ci BN_clear_free(privkey_bn); 231e1051a39Sopenharmony_ci goto dherr; 232e1051a39Sopenharmony_ci } 233e1051a39Sopenharmony_ci if (!DH_set0_key(dh, NULL, privkey_bn)) 234e1051a39Sopenharmony_ci goto dherr; 235e1051a39Sopenharmony_ci /* Calculate public key, increments dirty_cnt */ 236e1051a39Sopenharmony_ci if (!DH_generate_key(dh)) 237e1051a39Sopenharmony_ci goto dherr; 238e1051a39Sopenharmony_ci 239e1051a39Sopenharmony_ci goto done; 240e1051a39Sopenharmony_ci 241e1051a39Sopenharmony_ci decerr: 242e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_DH, EVP_R_DECODE_ERROR); 243e1051a39Sopenharmony_ci dherr: 244e1051a39Sopenharmony_ci DH_free(dh); 245e1051a39Sopenharmony_ci dh = NULL; 246e1051a39Sopenharmony_ci done: 247e1051a39Sopenharmony_ci ASN1_STRING_clear_free(privkey); 248e1051a39Sopenharmony_ci return dh; 249e1051a39Sopenharmony_ci} 250e1051a39Sopenharmony_ci#endif 251