From 74361b0b6e5a6b17ebeea6afe1ca990395d7a6dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20Ter=C3=A4s?= Date: Mon, 26 Dec 2022 16:29:56 +0200 Subject: [PATCH] Refactor OpenSSL RSA private key handling Instead of trying to enforce one pkey to contain both a private and a public key pair, refactor the code to have separate public and private pkeys. This is a prerequisite for proper openssl 3.0 providers support and greatly simplifies the code. --- lib/dns/dst_internal.h | 6 +- lib/dns/opensslrsa_link.c | 432 ++++++-------------------------------- 2 files changed, 75 insertions(+), 363 deletions(-) diff --git a/lib/dns/dst_internal.h b/lib/dns/dst_internal.h index 9f5e8ee3b6..13dd6dc75a 100644 --- a/lib/dns/dst_internal.h +++ b/lib/dns/dst_internal.h @@ -98,8 +98,12 @@ struct dst_key { void *generic; dns_gss_ctx_id_t gssctx; DH *dh; - EVP_PKEY *pkey; dst_hmac_key_t *hmac_key; + EVP_PKEY *pkey; + struct { + EVP_PKEY *pub; + EVP_PKEY *priv; + } pkeypair; } keydata; /*%< pointer to key in crypto pkg fmt */ isc_stdtime_t times[DST_MAX_TIMES + 1]; /*%< timing metadata */ diff --git a/lib/dns/opensslrsa_link.c b/lib/dns/opensslrsa_link.c index 94f4f45731..619ce345f4 100644 --- a/lib/dns/opensslrsa_link.c +++ b/lib/dns/opensslrsa_link.c @@ -155,7 +155,7 @@ opensslrsa_sign(dst_context_t *dctx, isc_buffer_t *sig) { isc_region_t r; unsigned int siglen = 0; EVP_MD_CTX *evp_md_ctx = dctx->ctxdata.evp_md_ctx; - EVP_PKEY *pkey = key->keydata.pkey; + EVP_PKEY *pkey = key->keydata.pkeypair.priv; REQUIRE(opensslrsa_valid_key_alg(dctx->key->key_alg)); @@ -205,7 +205,7 @@ opensslrsa_verify2(dst_context_t *dctx, int maxbits, const isc_region_t *sig) { dst_key_t *key = dctx->key; int status = 0; EVP_MD_CTX *evp_md_ctx = dctx->ctxdata.evp_md_ctx; - EVP_PKEY *pkey = key->keydata.pkey; + EVP_PKEY *pkey = key->keydata.pkeypair.pub; REQUIRE(opensslrsa_valid_key_alg(dctx->key->key_alg)); @@ -233,21 +233,8 @@ opensslrsa_verify(dst_context_t *dctx, const isc_region_t *sig) { static bool opensslrsa_compare(const dst_key_t *key1, const dst_key_t *key2) { - bool ret; - int status; - EVP_PKEY *pkey1 = key1->keydata.pkey; - EVP_PKEY *pkey2 = key2->keydata.pkey; -#if OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000 - RSA *rsa1 = NULL; - RSA *rsa2 = NULL; - const BIGNUM *d1 = NULL, *d2 = NULL; - const BIGNUM *p1 = NULL, *p2 = NULL; - const BIGNUM *q1 = NULL, *q2 = NULL; -#else - BIGNUM *d1 = NULL, *d2 = NULL; - BIGNUM *p1 = NULL, *p2 = NULL; - BIGNUM *q1 = NULL, *q2 = NULL; -#endif /* OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000 */ + EVP_PKEY *pkey1 = key1->keydata.pkeypair.pub; + EVP_PKEY *pkey2 = key2->keydata.pkeypair.pub; if (pkey1 == NULL && pkey2 == NULL) { return (true); @@ -255,81 +242,17 @@ opensslrsa_compare(const dst_key_t *key1, const dst_key_t *key2) { return (false); } - /* `EVP_PKEY_eq` checks only the public key components and paramters. */ - status = EVP_PKEY_eq(pkey1, pkey2); - if (status != 1) { - DST_RET(false); + /* `EVP_PKEY_eq` checks only the public components and parameters. */ + if (EVP_PKEY_eq(pkey1, pkey2) != 1) { + return (false); } - -#if OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000 - rsa1 = EVP_PKEY_get1_RSA(pkey1); - rsa2 = EVP_PKEY_get1_RSA(pkey2); - if (rsa1 == NULL && rsa2 == NULL) { - DST_RET(true); - } else if (rsa1 == NULL || rsa2 == NULL) { - DST_RET(false); + /* The private key presence must be same for keys to match. */ + if ((key1->keydata.pkeypair.priv != NULL) != + (key2->keydata.pkeypair.priv != NULL)) + { + return (false); } - RSA_get0_key(rsa1, NULL, NULL, &d1); - RSA_get0_key(rsa2, NULL, NULL, &d2); -#else - EVP_PKEY_get_bn_param(pkey1, OSSL_PKEY_PARAM_RSA_D, &d1); - EVP_PKEY_get_bn_param(pkey2, OSSL_PKEY_PARAM_RSA_D, &d2); -#endif /* OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000 */ - - if (d1 != NULL || d2 != NULL) { - if (d1 == NULL || d2 == NULL) { - DST_RET(false); - } - -#if OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000 - RSA_get0_factors(rsa1, &p1, &q1); - RSA_get0_factors(rsa2, &p2, &q2); -#else - EVP_PKEY_get_bn_param(pkey1, OSSL_PKEY_PARAM_RSA_FACTOR1, &p1); - EVP_PKEY_get_bn_param(pkey1, OSSL_PKEY_PARAM_RSA_FACTOR2, &q1); - EVP_PKEY_get_bn_param(pkey2, OSSL_PKEY_PARAM_RSA_FACTOR1, &p2); - EVP_PKEY_get_bn_param(pkey2, OSSL_PKEY_PARAM_RSA_FACTOR2, &q2); -#endif /* OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000 */ - - if (BN_cmp(d1, d2) != 0 || BN_cmp(p1, p2) != 0 || - BN_cmp(q1, q2) != 0) - { - DST_RET(false); - } - } - - ret = true; - -err: -#if OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000 - if (rsa1 != NULL) { - RSA_free(rsa1); - } - if (rsa2 != NULL) { - RSA_free(rsa2); - } -#else - if (d1 != NULL) { - BN_clear_free(d1); - } - if (d2 != NULL) { - BN_clear_free(d2); - } - if (p1 != NULL) { - BN_clear_free(p1); - } - if (p2 != NULL) { - BN_clear_free(p2); - } - if (q1 != NULL) { - BN_clear_free(q1); - } - if (q2 != NULL) { - BN_clear_free(q2); - } -#endif /* OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000 */ - - return (ret); + return (true); } #if OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000 @@ -478,7 +401,8 @@ opensslrsa_generate(dst_key_t *key, int exp, void (*callback)(int)) { } #endif /* OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000 */ - key->keydata.pkey = pkey; + key->keydata.pkeypair.pub = pkey; + key->keydata.pkeypair.priv = pkey; pkey = NULL; ret = ISC_R_SUCCESS; @@ -506,52 +430,19 @@ err: static bool opensslrsa_isprivate(const dst_key_t *key) { - bool ret; - EVP_PKEY *pkey; -#if OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000 - RSA *rsa; - const BIGNUM *d = NULL; -#else - BIGNUM *d = NULL; -#endif /* OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000 */ - REQUIRE(opensslrsa_valid_key_alg(key->key_alg)); - pkey = key->keydata.pkey; - if (pkey == NULL) { - return (false); - } - -#if OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000 - rsa = EVP_PKEY_get1_RSA(pkey); - INSIST(rsa != NULL); - - if (RSA_test_flags(rsa, RSA_FLAG_EXT_PKEY) != 0) { - ret = true; - } else { - RSA_get0_key(rsa, NULL, NULL, &d); - ret = (d != NULL); - } - RSA_free(rsa); -#else - ret = (EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_RSA_D, &d) == 1 && - d != NULL); - if (d != NULL) { - BN_clear_free(d); - } -#endif /* OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000 */ - - return (ret); + return (key->keydata.pkeypair.priv != NULL); } static void opensslrsa_destroy(dst_key_t *key) { - EVP_PKEY *pkey = key->keydata.pkey; - - if (pkey != NULL) { - EVP_PKEY_free(pkey); - key->keydata.pkey = NULL; + if (key->keydata.pkeypair.pub != key->keydata.pkeypair.priv) { + EVP_PKEY_free(key->keydata.pkeypair.priv); } + EVP_PKEY_free(key->keydata.pkeypair.pub); + key->keydata.pkeypair.pub = NULL; + key->keydata.pkeypair.priv = NULL; } static isc_result_t @@ -568,9 +459,9 @@ opensslrsa_todns(const dst_key_t *key, isc_buffer_t *data) { BIGNUM *e = NULL, *n = NULL; #endif /* OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000 */ - REQUIRE(key->keydata.pkey != NULL); + REQUIRE(key->keydata.pkeypair.pub != NULL); - pkey = key->keydata.pkey; + pkey = key->keydata.pkeypair.pub; isc_buffer_availableregion(data, &r); #if OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000 @@ -748,7 +639,7 @@ opensslrsa_fromdns(dst_key_t *key, isc_buffer_t *data) { } #endif /* OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000 */ - key->keydata.pkey = pkey; + key->keydata.pkeypair.pub = pkey; pkey = NULL; ret = ISC_R_SUCCESS; @@ -800,7 +691,11 @@ opensslrsa_tofile(const dst_key_t *key, const char *directory) { BIGNUM *dmp1 = NULL, *dmq1 = NULL, *iqmp = NULL; #endif /* OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000 */ - if (key->keydata.pkey == NULL) { + if (key->keydata.pkeypair.priv != NULL) { + pkey = key->keydata.pkeypair.priv; + } else if (key->keydata.pkeypair.pub != NULL) { + pkey = key->keydata.pkeypair.pub; + } else { DST_RET(DST_R_NULLKEY); } @@ -808,7 +703,6 @@ opensslrsa_tofile(const dst_key_t *key, const char *directory) { return (dst__privstruct_writefile(key, &priv, directory)); } - pkey = key->keydata.pkey; #if OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000 rsa = EVP_PKEY_get1_RSA(pkey); if (rsa == NULL) { @@ -964,131 +858,9 @@ err: return (ret); } -#if OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000 static isc_result_t -rsa_check(RSA *rsa, RSA *pub) { - const BIGNUM *n1 = NULL, *n2 = NULL; - const BIGNUM *e1 = NULL, *e2 = NULL; - BIGNUM *n = NULL, *e = NULL; - - /* - * Public parameters should be the same but if they are not set - * copy them from the public key. - */ - if (pub != NULL) { - RSA_get0_key(rsa, &n1, &e1, NULL); - RSA_get0_key(pub, &n2, &e2, NULL); - if (n1 != NULL) { - if (BN_cmp(n1, n2) != 0) { - return (DST_R_INVALIDPRIVATEKEY); - } - } else { - n = BN_dup(n2); - if (n == NULL) { - return (ISC_R_NOMEMORY); - } - } - if (e1 != NULL) { - if (BN_cmp(e1, e2) != 0) { - if (n != NULL) { - BN_free(n); - } - return (DST_R_INVALIDPRIVATEKEY); - } - } else { - e = BN_dup(e2); - if (e == NULL) { - if (n != NULL) { - BN_free(n); - } - return (ISC_R_NOMEMORY); - } - } - if (RSA_set0_key(rsa, n, e, NULL) == 0) { - if (n != NULL) { - BN_free(n); - } - if (e != NULL) { - BN_free(e); - } - } - } - - RSA_get0_key(rsa, &n1, &e1, NULL); - if (n1 == NULL || e1 == NULL) { - return (DST_R_INVALIDPRIVATEKEY); - } - - return (ISC_R_SUCCESS); -} -#else -static isc_result_t -rsa_check(EVP_PKEY *pkey, EVP_PKEY *pubpkey) { - isc_result_t ret = ISC_R_FAILURE; - int status; - BIGNUM *n1 = NULL, *n2 = NULL; - BIGNUM *e1 = NULL, *e2 = NULL; - - /* Try to get the public key from pkey. */ - EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_RSA_N, &n1); - EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_RSA_E, &e1); - - /* Check if `pubpkey` exists and that we can extract its public key. */ - if (pubpkey == NULL || - EVP_PKEY_get_bn_param(pubpkey, OSSL_PKEY_PARAM_RSA_N, &n2) != 1 || - n2 == NULL || - EVP_PKEY_get_bn_param(pubpkey, OSSL_PKEY_PARAM_RSA_E, &e2) != 1 || - e2 == NULL) - { - if (n1 == NULL || e1 == NULL) { - /* No public key both in `pkey` and in `pubpkey`. */ - DST_RET(DST_R_INVALIDPRIVATEKEY); - } else { - /* - * `pkey` has a public key, but there is no public key - * in `pubpkey` to check against. - */ - DST_RET(ISC_R_SUCCESS); - } - } - - /* - * If `pkey` doesn't have a public key then we will copy it from - * `pubpkey`. - */ - if (n1 == NULL || e1 == NULL) { - status = EVP_PKEY_set_bn_param(pkey, OSSL_PKEY_PARAM_RSA_N, n2); - if (status != 1) { - DST_RET(ISC_R_FAILURE); - } - - status = EVP_PKEY_set_bn_param(pkey, OSSL_PKEY_PARAM_RSA_E, e2); - if (status != 1) { - DST_RET(ISC_R_FAILURE); - } - } - - if (EVP_PKEY_eq(pkey, pubpkey) == 1) { - DST_RET(ISC_R_SUCCESS); - } - -err: - if (n1 != NULL) { - BN_free(n1); - } - if (n2 != NULL) { - BN_free(n2); - } - if (e1 != NULL) { - BN_free(e1); - } - if (e2 != NULL) { - BN_free(e2); - } - - return (ret); -} -#endif /* OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000 */ +opensslrsa_fromlabel(dst_key_t *key, const char *engine, const char *label, + const char *pin); static isc_result_t opensslrsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) { @@ -1096,17 +868,13 @@ opensslrsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) { isc_result_t ret; int i; #if OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000 - RSA *rsa = NULL, *pubrsa = NULL; - const BIGNUM *ex = NULL; + RSA *rsa = NULL; #else OSSL_PARAM_BLD *bld = NULL; OSSL_PARAM *params = NULL; EVP_PKEY_CTX *ctx = NULL; BIGNUM *ex = NULL; #endif /* OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000 */ -#if !defined(OPENSSL_NO_ENGINE) && OPENSSL_API_LEVEL < 30000 - ENGINE *ep = NULL; -#endif /* if !defined(OPENSSL_NO_ENGINE) && OPENSSL_API_LEVEL < 30000 */ isc_mem_t *mctx = key->mctx; const char *engine = NULL, *label = NULL; EVP_PKEY *pkey = NULL; @@ -1126,18 +894,14 @@ opensslrsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) { if (priv.nelements != 0 || pub == NULL) { DST_RET(DST_R_INVALIDPRIVATEKEY); } - key->keydata.pkey = pub->keydata.pkey; - pub->keydata.pkey = NULL; + key->keydata.pkeypair.pub = pub->keydata.pkeypair.pub; + key->keydata.pkeypair.priv = pub->keydata.pkeypair.priv; + pub->keydata.pkeypair.pub = NULL; + pub->keydata.pkeypair.priv = NULL; key->key_size = pub->key_size; DST_RET(ISC_R_SUCCESS); } -#if OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000 - if (pub != NULL && pub->keydata.pkey != NULL) { - pubrsa = EVP_PKEY_get1_RSA(pub->keydata.pkey); - } -#endif /* OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000 */ - for (i = 0; i < priv.nelements; i++) { switch (priv.elements[i].tag) { case TAG_RSA_ENGINE: @@ -1156,48 +920,17 @@ opensslrsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) { * See if we can fetch it. */ if (label != NULL) { -#if !defined(OPENSSL_NO_ENGINE) && OPENSSL_API_LEVEL < 30000 - if (engine == NULL) { - DST_RET(DST_R_NOENGINE); + ret = opensslrsa_fromlabel(key, engine, label, NULL); + if (ret != ISC_R_SUCCESS) { + DST_RET(ret); } - ep = dst__openssl_getengine(engine); - if (ep == NULL) { - DST_RET(dst__openssl_toresult(DST_R_NOENGINE)); + /* Check that the public component matches if given */ + if (pub != NULL && EVP_PKEY_eq(key->keydata.pkeypair.pub, + pub->keydata.pkeypair.pub) != 1) + { + DST_RET(DST_R_INVALIDPRIVATEKEY); } - pkey = ENGINE_load_private_key(ep, label, NULL, NULL); - if (pkey == NULL) { - DST_RET(dst__openssl_toresult2("ENGINE_load_private_" - "key", - ISC_R_NOTFOUND)); - } - key->engine = isc_mem_strdup(key->mctx, engine); - key->label = isc_mem_strdup(key->mctx, label); - - rsa = EVP_PKEY_get1_RSA(pkey); - if (rsa == NULL) { - DST_RET(dst__openssl_toresult(DST_R_OPENSSLFAILURE)); - } - if (rsa_check(rsa, pubrsa) != ISC_R_SUCCESS) { - DST_RET(dst__openssl_toresult(DST_R_INVALIDPRIVATEKEY)); - } - RSA_get0_key(rsa, NULL, &ex, NULL); - - if (ex == NULL) { - DST_RET(dst__openssl_toresult(DST_R_INVALIDPRIVATEKEY)); - } - if (BN_num_bits(ex) > RSA_MAX_PUBEXP_BITS) { - DST_RET(ISC_R_RANGE); - } - - key->key_size = EVP_PKEY_bits(pkey); - key->keydata.pkey = pkey; - pkey = NULL; DST_RET(ISC_R_SUCCESS); -#else /* if !defined(OPENSSL_NO_ENGINE) && OPENSSL_API_LEVEL < 30000 */ - UNUSED(engine); - UNUSED(ex); - DST_RET(DST_R_NOENGINE); -#endif /* if !defined(OPENSSL_NO_ENGINE) && OPENSSL_API_LEVEL < 30000 */ } for (i = 0; i < priv.nelements; i++) { @@ -1244,6 +977,14 @@ opensslrsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) { } } + /* Basic sanity check for public key portion */ + if (n == NULL || e == NULL) { + DST_RET(DST_R_INVALIDPRIVATEKEY); + } + if (BN_num_bits(e) > RSA_MAX_PUBEXP_BITS) { + DST_RET(ISC_R_RANGE); + } + #if OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000 rsa = RSA_new(); if (rsa == NULL) { @@ -1266,6 +1007,7 @@ opensslrsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) { if (d != NULL) { BN_clear_free(d); } + DST_RET(DST_R_INVALIDPRIVATEKEY); } if (RSA_set0_factors(rsa, p, q) == 0) { if (p != NULL) { @@ -1286,9 +1028,6 @@ opensslrsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) { BN_clear_free(iqmp); } } - if (rsa_check(rsa, pubrsa) != ISC_R_SUCCESS) { - DST_RET(dst__openssl_toresult(DST_R_INVALIDPRIVATEKEY)); - } #else bld = OSSL_PARAM_BLD_new(); if (bld == NULL) { @@ -1354,20 +1093,16 @@ opensslrsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) { { DST_RET(dst__openssl_toresult(DST_R_OPENSSLFAILURE)); } - - if (rsa_check(pkey, pub != NULL ? pub->keydata.pkey : NULL) != - ISC_R_SUCCESS) - { - DST_RET(dst__openssl_toresult(DST_R_INVALIDPRIVATEKEY)); - } #endif /* OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000 */ - if (BN_num_bits(e) > RSA_MAX_PUBEXP_BITS) { - DST_RET(ISC_R_RANGE); + /* Check that the public component matches if given */ + if (pub != NULL && EVP_PKEY_eq(pkey, pub->keydata.pkeypair.pub) != 1) { + DST_RET(DST_R_INVALIDPRIVATEKEY); } key->key_size = BN_num_bits(n); - key->keydata.pkey = pkey; + key->keydata.pkeypair.pub = pkey; + key->keydata.pkeypair.priv = pkey; pkey = NULL; err: @@ -1378,9 +1113,6 @@ err: if (rsa != NULL) { RSA_free(rsa); } - if (pubrsa != NULL) { - RSA_free(pubrsa); - } #else if (ctx != NULL) { EVP_PKEY_CTX_free(ctx); @@ -1435,9 +1167,7 @@ opensslrsa_fromlabel(dst_key_t *key, const char *engine, const char *label, #if !defined(OPENSSL_NO_ENGINE) && OPENSSL_API_LEVEL < 30000 ENGINE *e = NULL; isc_result_t ret = ISC_R_SUCCESS; - EVP_PKEY *pkey = NULL, *pubpkey = NULL; - RSA *rsa = NULL, *pubrsa = NULL; - const BIGNUM *ex = NULL; + EVP_PKEY *privpkey = NULL, *pubpkey = NULL; UNUSED(pin); @@ -1454,49 +1184,27 @@ opensslrsa_fromlabel(dst_key_t *key, const char *engine, const char *label, DST_RET(dst__openssl_toresult2("ENGINE_load_public_key", DST_R_OPENSSLFAILURE)); } - pubrsa = EVP_PKEY_get1_RSA(pubpkey); - if (pubrsa == NULL) { - DST_RET(dst__openssl_toresult(DST_R_OPENSSLFAILURE)); + if (!opensslrsa_check_exponent_bits(pubpkey, RSA_MAX_PUBEXP_BITS)) { + DST_RET(ISC_R_RANGE); } - pkey = ENGINE_load_private_key(e, label, NULL, NULL); - if (pkey == NULL) { + privpkey = ENGINE_load_private_key(e, label, NULL, NULL); + if (privpkey == NULL) { DST_RET(dst__openssl_toresult2("ENGINE_load_private_key", DST_R_OPENSSLFAILURE)); } key->engine = isc_mem_strdup(key->mctx, engine); key->label = isc_mem_strdup(key->mctx, label); - - rsa = EVP_PKEY_get1_RSA(pkey); - if (rsa == NULL) { - DST_RET(dst__openssl_toresult(DST_R_OPENSSLFAILURE)); - } - if (rsa_check(rsa, pubrsa) != ISC_R_SUCCESS) { - DST_RET(dst__openssl_toresult(DST_R_INVALIDPRIVATEKEY)); - } - RSA_get0_key(rsa, NULL, &ex, NULL); - - if (ex == NULL) { - DST_RET(dst__openssl_toresult(DST_R_INVALIDPRIVATEKEY)); - } - if (BN_num_bits(ex) > RSA_MAX_PUBEXP_BITS) { - DST_RET(ISC_R_RANGE); - } - - key->key_size = EVP_PKEY_bits(pkey); - key->keydata.pkey = pkey; - pkey = NULL; + key->key_size = EVP_PKEY_bits(privpkey); + key->keydata.pkeypair.priv = privpkey; + key->keydata.pkeypair.pub = pubpkey; + privpkey = NULL; + pubpkey = NULL; err: - if (rsa != NULL) { - RSA_free(rsa); - } - if (pubrsa != NULL) { - RSA_free(pubrsa); - } - if (pkey != NULL) { - EVP_PKEY_free(pkey); + if (privpkey != NULL) { + EVP_PKEY_free(privpkey); } if (pubpkey != NULL) { EVP_PKEY_free(pubpkey);