1e1051a39Sopenharmony_ci/* 2e1051a39Sopenharmony_ci * Copyright 2020-2023 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 * DSA 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/core_names.h> 17e1051a39Sopenharmony_ci#include <openssl/err.h> 18e1051a39Sopenharmony_ci#ifndef FIPS_MODULE 19e1051a39Sopenharmony_ci# include <openssl/x509.h> 20e1051a39Sopenharmony_ci#endif 21e1051a39Sopenharmony_ci#include "crypto/dsa.h" 22e1051a39Sopenharmony_ci#include "dsa_local.h" 23e1051a39Sopenharmony_ci 24e1051a39Sopenharmony_ci/* 25e1051a39Sopenharmony_ci * The intention with the "backend" source file is to offer backend support 26e1051a39Sopenharmony_ci * for legacy backends (EVP_PKEY_ASN1_METHOD and EVP_PKEY_METHOD) and provider 27e1051a39Sopenharmony_ci * implementations alike. 28e1051a39Sopenharmony_ci */ 29e1051a39Sopenharmony_ci 30e1051a39Sopenharmony_ciint ossl_dsa_key_fromdata(DSA *dsa, const OSSL_PARAM params[], 31e1051a39Sopenharmony_ci int include_private) 32e1051a39Sopenharmony_ci{ 33e1051a39Sopenharmony_ci const OSSL_PARAM *param_priv_key = NULL, *param_pub_key; 34e1051a39Sopenharmony_ci BIGNUM *priv_key = NULL, *pub_key = NULL; 35e1051a39Sopenharmony_ci 36e1051a39Sopenharmony_ci if (dsa == NULL) 37e1051a39Sopenharmony_ci return 0; 38e1051a39Sopenharmony_ci 39e1051a39Sopenharmony_ci if (include_private) { 40e1051a39Sopenharmony_ci param_priv_key = 41e1051a39Sopenharmony_ci OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PRIV_KEY); 42e1051a39Sopenharmony_ci } 43e1051a39Sopenharmony_ci param_pub_key = 44e1051a39Sopenharmony_ci OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PUB_KEY); 45e1051a39Sopenharmony_ci 46e1051a39Sopenharmony_ci /* It's ok if neither half is present */ 47e1051a39Sopenharmony_ci if (param_priv_key == NULL && param_pub_key == NULL) 48e1051a39Sopenharmony_ci return 1; 49e1051a39Sopenharmony_ci 50e1051a39Sopenharmony_ci if (param_pub_key != NULL && !OSSL_PARAM_get_BN(param_pub_key, &pub_key)) 51e1051a39Sopenharmony_ci goto err; 52e1051a39Sopenharmony_ci if (param_priv_key != NULL && !OSSL_PARAM_get_BN(param_priv_key, &priv_key)) 53e1051a39Sopenharmony_ci goto err; 54e1051a39Sopenharmony_ci 55e1051a39Sopenharmony_ci if (!DSA_set0_key(dsa, pub_key, priv_key)) 56e1051a39Sopenharmony_ci goto err; 57e1051a39Sopenharmony_ci 58e1051a39Sopenharmony_ci return 1; 59e1051a39Sopenharmony_ci 60e1051a39Sopenharmony_ci err: 61e1051a39Sopenharmony_ci BN_clear_free(priv_key); 62e1051a39Sopenharmony_ci BN_free(pub_key); 63e1051a39Sopenharmony_ci return 0; 64e1051a39Sopenharmony_ci} 65e1051a39Sopenharmony_ci 66e1051a39Sopenharmony_ciint ossl_dsa_is_foreign(const DSA *dsa) 67e1051a39Sopenharmony_ci{ 68e1051a39Sopenharmony_ci#ifndef FIPS_MODULE 69e1051a39Sopenharmony_ci if (dsa->engine != NULL || DSA_get_method((DSA *)dsa) != DSA_OpenSSL()) 70e1051a39Sopenharmony_ci return 1; 71e1051a39Sopenharmony_ci#endif 72e1051a39Sopenharmony_ci return 0; 73e1051a39Sopenharmony_ci} 74e1051a39Sopenharmony_ci 75e1051a39Sopenharmony_cistatic ossl_inline int dsa_bn_dup_check(BIGNUM **out, const BIGNUM *f) 76e1051a39Sopenharmony_ci{ 77e1051a39Sopenharmony_ci if (f != NULL && (*out = BN_dup(f)) == NULL) 78e1051a39Sopenharmony_ci return 0; 79e1051a39Sopenharmony_ci return 1; 80e1051a39Sopenharmony_ci} 81e1051a39Sopenharmony_ci 82e1051a39Sopenharmony_ciDSA *ossl_dsa_dup(const DSA *dsa, int selection) 83e1051a39Sopenharmony_ci{ 84e1051a39Sopenharmony_ci DSA *dupkey = NULL; 85e1051a39Sopenharmony_ci 86e1051a39Sopenharmony_ci /* Do not try to duplicate foreign DSA keys */ 87e1051a39Sopenharmony_ci if (ossl_dsa_is_foreign(dsa)) 88e1051a39Sopenharmony_ci return NULL; 89e1051a39Sopenharmony_ci 90e1051a39Sopenharmony_ci if ((dupkey = ossl_dsa_new(dsa->libctx)) == NULL) 91e1051a39Sopenharmony_ci return NULL; 92e1051a39Sopenharmony_ci 93e1051a39Sopenharmony_ci if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0 94e1051a39Sopenharmony_ci && !ossl_ffc_params_copy(&dupkey->params, &dsa->params)) 95e1051a39Sopenharmony_ci goto err; 96e1051a39Sopenharmony_ci 97e1051a39Sopenharmony_ci dupkey->flags = dsa->flags; 98e1051a39Sopenharmony_ci 99e1051a39Sopenharmony_ci if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0 100e1051a39Sopenharmony_ci && ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) == 0 101e1051a39Sopenharmony_ci || !dsa_bn_dup_check(&dupkey->pub_key, dsa->pub_key))) 102e1051a39Sopenharmony_ci goto err; 103e1051a39Sopenharmony_ci 104e1051a39Sopenharmony_ci if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0 105e1051a39Sopenharmony_ci && ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) == 0 106e1051a39Sopenharmony_ci || !dsa_bn_dup_check(&dupkey->priv_key, dsa->priv_key))) 107e1051a39Sopenharmony_ci goto err; 108e1051a39Sopenharmony_ci 109e1051a39Sopenharmony_ci#ifndef FIPS_MODULE 110e1051a39Sopenharmony_ci if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_DSA, 111e1051a39Sopenharmony_ci &dupkey->ex_data, &dsa->ex_data)) 112e1051a39Sopenharmony_ci goto err; 113e1051a39Sopenharmony_ci#endif 114e1051a39Sopenharmony_ci 115e1051a39Sopenharmony_ci return dupkey; 116e1051a39Sopenharmony_ci 117e1051a39Sopenharmony_ci err: 118e1051a39Sopenharmony_ci DSA_free(dupkey); 119e1051a39Sopenharmony_ci return NULL; 120e1051a39Sopenharmony_ci} 121e1051a39Sopenharmony_ci 122e1051a39Sopenharmony_ci#ifndef FIPS_MODULE 123e1051a39Sopenharmony_ciDSA *ossl_dsa_key_from_pkcs8(const PKCS8_PRIV_KEY_INFO *p8inf, 124e1051a39Sopenharmony_ci OSSL_LIB_CTX *libctx, const char *propq) 125e1051a39Sopenharmony_ci{ 126e1051a39Sopenharmony_ci const unsigned char *p, *pm; 127e1051a39Sopenharmony_ci int pklen, pmlen; 128e1051a39Sopenharmony_ci int ptype; 129e1051a39Sopenharmony_ci const void *pval; 130e1051a39Sopenharmony_ci const ASN1_STRING *pstr; 131e1051a39Sopenharmony_ci const X509_ALGOR *palg; 132e1051a39Sopenharmony_ci ASN1_INTEGER *privkey = NULL; 133e1051a39Sopenharmony_ci const BIGNUM *dsa_p, *dsa_g; 134e1051a39Sopenharmony_ci BIGNUM *dsa_pubkey = NULL, *dsa_privkey = NULL; 135e1051a39Sopenharmony_ci BN_CTX *ctx = NULL; 136e1051a39Sopenharmony_ci 137e1051a39Sopenharmony_ci DSA *dsa = NULL; 138e1051a39Sopenharmony_ci 139e1051a39Sopenharmony_ci if (!PKCS8_pkey_get0(NULL, &p, &pklen, &palg, p8inf)) 140e1051a39Sopenharmony_ci return 0; 141e1051a39Sopenharmony_ci X509_ALGOR_get0(NULL, &ptype, &pval, palg); 142e1051a39Sopenharmony_ci 143e1051a39Sopenharmony_ci if ((privkey = d2i_ASN1_INTEGER(NULL, &p, pklen)) == NULL) 144e1051a39Sopenharmony_ci goto decerr; 145e1051a39Sopenharmony_ci if (privkey->type == V_ASN1_NEG_INTEGER || ptype != V_ASN1_SEQUENCE) 146e1051a39Sopenharmony_ci goto decerr; 147e1051a39Sopenharmony_ci 148e1051a39Sopenharmony_ci pstr = pval; 149e1051a39Sopenharmony_ci pm = pstr->data; 150e1051a39Sopenharmony_ci pmlen = pstr->length; 151e1051a39Sopenharmony_ci if ((dsa = d2i_DSAparams(NULL, &pm, pmlen)) == NULL) 152e1051a39Sopenharmony_ci goto decerr; 153e1051a39Sopenharmony_ci /* We have parameters now set private key */ 154e1051a39Sopenharmony_ci if ((dsa_privkey = BN_secure_new()) == NULL 155e1051a39Sopenharmony_ci || !ASN1_INTEGER_to_BN(privkey, dsa_privkey)) { 156e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_DSA, DSA_R_BN_ERROR); 157e1051a39Sopenharmony_ci goto dsaerr; 158e1051a39Sopenharmony_ci } 159e1051a39Sopenharmony_ci /* Calculate public key */ 160e1051a39Sopenharmony_ci if ((dsa_pubkey = BN_new()) == NULL) { 161e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_DSA, ERR_R_MALLOC_FAILURE); 162e1051a39Sopenharmony_ci goto dsaerr; 163e1051a39Sopenharmony_ci } 164e1051a39Sopenharmony_ci if ((ctx = BN_CTX_new()) == NULL) { 165e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_DSA, ERR_R_MALLOC_FAILURE); 166e1051a39Sopenharmony_ci goto dsaerr; 167e1051a39Sopenharmony_ci } 168e1051a39Sopenharmony_ci 169e1051a39Sopenharmony_ci dsa_p = DSA_get0_p(dsa); 170e1051a39Sopenharmony_ci dsa_g = DSA_get0_g(dsa); 171e1051a39Sopenharmony_ci BN_set_flags(dsa_privkey, BN_FLG_CONSTTIME); 172e1051a39Sopenharmony_ci if (!BN_mod_exp(dsa_pubkey, dsa_g, dsa_privkey, dsa_p, ctx)) { 173e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_DSA, DSA_R_BN_ERROR); 174e1051a39Sopenharmony_ci goto dsaerr; 175e1051a39Sopenharmony_ci } 176e1051a39Sopenharmony_ci if (!DSA_set0_key(dsa, dsa_pubkey, dsa_privkey)) { 177e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_DSA, ERR_R_INTERNAL_ERROR); 178e1051a39Sopenharmony_ci goto dsaerr; 179e1051a39Sopenharmony_ci } 180e1051a39Sopenharmony_ci 181e1051a39Sopenharmony_ci goto done; 182e1051a39Sopenharmony_ci 183e1051a39Sopenharmony_ci decerr: 184e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_DSA, DSA_R_DECODE_ERROR); 185e1051a39Sopenharmony_ci dsaerr: 186e1051a39Sopenharmony_ci BN_free(dsa_privkey); 187e1051a39Sopenharmony_ci BN_free(dsa_pubkey); 188e1051a39Sopenharmony_ci DSA_free(dsa); 189e1051a39Sopenharmony_ci dsa = NULL; 190e1051a39Sopenharmony_ci done: 191e1051a39Sopenharmony_ci BN_CTX_free(ctx); 192e1051a39Sopenharmony_ci ASN1_STRING_clear_free(privkey); 193e1051a39Sopenharmony_ci return dsa; 194e1051a39Sopenharmony_ci} 195e1051a39Sopenharmony_ci#endif 196