diff --git a/lib/dns/dst_openssl.h b/lib/dns/dst_openssl.h index 375c9351b6..188e72cd16 100644 --- a/lib/dns/dst_openssl.h +++ b/lib/dns/dst_openssl.h @@ -42,7 +42,7 @@ dst__openssl_getengine(const char *engine); #endif /* if !defined(OPENSSL_NO_ENGINE) && OPENSSL_API_LEVEL < 30000 */ isc_result_t -dst__openssl_fromlabel(const char *engine, const char *label, const char *pin, - EVP_PKEY **ppub, EVP_PKEY **ppriv); +dst__openssl_fromlabel(int key_base_id, const char *engine, const char *label, + const char *pin, EVP_PKEY **ppub, EVP_PKEY **ppriv); ISC_LANG_ENDDECLS diff --git a/lib/dns/openssl_link.c b/lib/dns/openssl_link.c index 2e606b81ed..f23f86443e 100644 --- a/lib/dns/openssl_link.c +++ b/lib/dns/openssl_link.c @@ -44,6 +44,10 @@ #if !defined(OPENSSL_NO_ENGINE) && OPENSSL_API_LEVEL < 30000 #include #endif /* if !defined(OPENSSL_NO_ENGINE) && OPENSSL_API_LEVEL < 30000 */ +#if OPENSSL_VERSION_NUMBER >= 0x30000000L +#include +#include +#endif #include "openssl_shim.h" @@ -225,9 +229,10 @@ dst__openssl_getengine(const char *engine) { } #endif /* if !defined(OPENSSL_NO_ENGINE) && OPENSSL_API_LEVEL < 30000 */ -isc_result_t -dst__openssl_fromlabel(const char *engine, const char *label, const char *pin, - EVP_PKEY **ppub, EVP_PKEY **ppriv) { +static isc_result_t +dst__openssl_fromlabel_engine(int key_base_id, const char *engine, + const char *label, const char *pin, + EVP_PKEY **ppub, EVP_PKEY **ppriv) { #if !defined(OPENSSL_NO_ENGINE) && OPENSSL_API_LEVEL < 30000 isc_result_t ret = ISC_R_SUCCESS; ENGINE *e = NULL; @@ -247,15 +252,22 @@ dst__openssl_fromlabel(const char *engine, const char *label, const char *pin, DST_RET(dst__openssl_toresult2("ENGINE_load_public_key", DST_R_OPENSSLFAILURE)); } + if (EVP_PKEY_base_id(*ppub) != key_base_id) { + DST_RET(DST_R_BADKEYTYPE); + } *ppriv = ENGINE_load_private_key(e, label, NULL, NULL); if (*ppriv == NULL) { DST_RET(dst__openssl_toresult2("ENGINE_load_private_key", DST_R_OPENSSLFAILURE)); } + if (EVP_PKEY_base_id(*ppriv) != key_base_id) { + DST_RET(DST_R_BADKEYTYPE); + } err: return (ret); #else /* if !defined(OPENSSL_NO_ENGINE) && OPENSSL_API_LEVEL < 30000 */ + UNUSED(key_base_id); UNUSED(engine); UNUSED(label); UNUSED(pin); @@ -265,4 +277,80 @@ err: #endif /* if !defined(OPENSSL_NO_ENGINE) && OPENSSL_API_LEVEL < 30000 */ } +static isc_result_t +dst__openssl_fromlabel_provider(int key_base_id, const char *engine, + const char *label, const char *pin, + EVP_PKEY **ppub, EVP_PKEY **ppriv) { +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + isc_result_t ret = DST_R_OPENSSLFAILURE; + OSSL_STORE_CTX *ctx = NULL; + + UNUSED(pin); + UNUSED(engine); + + ctx = OSSL_STORE_open(label, NULL, NULL, NULL, NULL); + if (!ctx) { + DST_RET(dst__openssl_toresult2("OSSL_STORE_open_ex", + DST_R_OPENSSLFAILURE)); + } + + while (!OSSL_STORE_eof(ctx)) { + OSSL_STORE_INFO *info = OSSL_STORE_load(ctx); + if (info == NULL) { + continue; + } + switch (OSSL_STORE_INFO_get_type(info)) { + case OSSL_STORE_INFO_PKEY: + if (*ppriv != NULL) { + DST_RET(DST_R_INVALIDPRIVATEKEY); + } + *ppriv = OSSL_STORE_INFO_get1_PKEY(info); + if (EVP_PKEY_get_base_id(*ppriv) != key_base_id) { + DST_RET(DST_R_BADKEYTYPE); + } + break; + case OSSL_STORE_INFO_PUBKEY: + if (*ppub != NULL) { + DST_RET(DST_R_INVALIDPUBLICKEY); + } + *ppub = OSSL_STORE_INFO_get1_PUBKEY(info); + if (EVP_PKEY_get_base_id(*ppub) != key_base_id) { + DST_RET(DST_R_BADKEYTYPE); + } + break; + } + OSSL_STORE_INFO_free(info); + } + if (*ppriv != NULL && *ppub != NULL) { + ret = ISC_R_SUCCESS; + } +err: + OSSL_STORE_close(ctx); + return (ret); +#else + UNUSED(key_base_id); + UNUSED(engine); + UNUSED(label); + UNUSED(pin); + UNUSED(ppub); + UNUSED(ppriv); + return (DST_R_OPENSSLFAILURE); +#endif +} + +isc_result_t +dst__openssl_fromlabel(int key_base_id, const char *engine, const char *label, + const char *pin, EVP_PKEY **ppub, EVP_PKEY **ppriv) { + isc_result_t result; + + result = dst__openssl_fromlabel_provider(key_base_id, engine, label, + pin, ppub, ppriv); + if (result != DST_R_OPENSSLFAILURE) { + return (result); + } + + return (dst__openssl_fromlabel_engine(key_base_id, engine, label, pin, + ppub, ppriv)); +} + /*! \file */ diff --git a/lib/dns/opensslrsa_link.c b/lib/dns/opensslrsa_link.c index 715c0a564c..efef7fe14a 100644 --- a/lib/dns/opensslrsa_link.c +++ b/lib/dns/opensslrsa_link.c @@ -1106,7 +1106,8 @@ opensslrsa_fromlabel(dst_key_t *key, const char *engine, const char *label, EVP_PKEY *privpkey = NULL, *pubpkey = NULL; isc_result_t ret; - ret = dst__openssl_fromlabel(engine, label, pin, &pubpkey, &privpkey); + ret = dst__openssl_fromlabel(EVP_PKEY_RSA, engine, label, pin, &pubpkey, + &privpkey); if (ret != ISC_R_SUCCESS) { goto err; }