diff options
author | Richard Levitte <levitte@openssl.org> | 2021-03-18 10:41:53 +0100 |
---|---|---|
committer | Richard Levitte <levitte@openssl.org> | 2021-03-19 16:46:39 +0100 |
commit | cf333799979755dd46193b49c15db0afd262c6a0 (patch) | |
tree | 77e5ab82979b1b8a9a64fcb2e0500af5361a57d0 /crypto/dsa/dsa_backend.c | |
parent | e0be34beee9ef8ebab49c51581f796e013600b77 (diff) |
PROV: Add type specific PKCS#8 decoding to the DER->key decoders
This required refactoring a number of functions from the diverse
EVP_PKEY_ASN1_METHOD implementations to become shared backend
functions. It also meant modifying a few of them to return pointers
to our internal RSA / DSA/ DH / EC_KEY, ... structures instead of
manipulating an EVP_PKEY pointer directly, letting the caller do the
latter.
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/14314)
Diffstat (limited to 'crypto/dsa/dsa_backend.c')
-rw-r--r-- | crypto/dsa/dsa_backend.c | 73 |
1 files changed, 73 insertions, 0 deletions
diff --git a/crypto/dsa/dsa_backend.c b/crypto/dsa/dsa_backend.c index e6f8f3645e..f3e54aeb13 100644 --- a/crypto/dsa/dsa_backend.c +++ b/crypto/dsa/dsa_backend.c @@ -14,6 +14,7 @@ #include "internal/deprecated.h" #include <openssl/core_names.h> +#include <openssl/err.h> #include "crypto/dsa.h" /* @@ -54,3 +55,75 @@ int ossl_dsa_key_fromdata(DSA *dsa, const OSSL_PARAM params[]) BN_free(pub_key); return 0; } + +#ifndef FIPS_MODULE +DSA *ossl_dsa_key_from_pkcs8(const PKCS8_PRIV_KEY_INFO *p8inf, + OSSL_LIB_CTX *libctx, const char *propq) +{ + const unsigned char *p, *pm; + int pklen, pmlen; + int ptype; + const void *pval; + const ASN1_STRING *pstr; + const X509_ALGOR *palg; + ASN1_INTEGER *privkey = NULL; + const BIGNUM *dsa_p, *dsa_g; + BIGNUM *dsa_pubkey = NULL, *dsa_privkey = NULL; + BN_CTX *ctx = NULL; + + DSA *dsa = NULL; + + if (!PKCS8_pkey_get0(NULL, &p, &pklen, &palg, p8inf)) + return 0; + X509_ALGOR_get0(NULL, &ptype, &pval, palg); + + if ((privkey = d2i_ASN1_INTEGER(NULL, &p, pklen)) == NULL) + goto decerr; + if (privkey->type == V_ASN1_NEG_INTEGER || ptype != V_ASN1_SEQUENCE) + goto decerr; + + pstr = pval; + pm = pstr->data; + pmlen = pstr->length; + if ((dsa = d2i_DSAparams(NULL, &pm, pmlen)) == NULL) + goto decerr; + /* We have parameters now set private key */ + if ((dsa_privkey = BN_secure_new()) == NULL + || !ASN1_INTEGER_to_BN(privkey, dsa_privkey)) { + ERR_raise(ERR_LIB_DSA, DSA_R_BN_ERROR); + goto dsaerr; + } + /* Calculate public key */ + if ((dsa_pubkey = BN_new()) == NULL) { + ERR_raise(ERR_LIB_DSA, ERR_R_MALLOC_FAILURE); + goto dsaerr; + } + if ((ctx = BN_CTX_new()) == NULL) { + ERR_raise(ERR_LIB_DSA, ERR_R_MALLOC_FAILURE); + goto dsaerr; + } + + dsa_p = DSA_get0_p(dsa); + dsa_g = DSA_get0_g(dsa); + BN_set_flags(dsa_privkey, BN_FLG_CONSTTIME); + if (!BN_mod_exp(dsa_pubkey, dsa_g, dsa_privkey, dsa_p, ctx)) { + ERR_raise(ERR_LIB_DSA, DSA_R_BN_ERROR); + goto dsaerr; + } + DSA_set0_key(dsa, dsa_pubkey, dsa_privkey); + + goto done; + + decerr: + ERR_raise(ERR_LIB_DSA, DSA_R_DECODE_ERROR); + dsaerr: + BN_free(dsa_privkey); + BN_free(dsa_pubkey); + DSA_free(dsa); + dsa = NULL; + done: + BN_CTX_free(ctx); + ASN1_STRING_clear_free(privkey); + return dsa; +} +#endif |