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