Should allow PKCS11 provider used from dnssec-keyfromlabel and then from signing tools or named daemon. Use final Fedora version of backport. Fix also rsabigexponent test. Resolves: RHEL-33729
905 lines
25 KiB
Diff
905 lines
25 KiB
Diff
From ec38a39feabea02eb75f257e8b81cf16aac9d184 Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Petr=20Men=C5=A1=C3=ADk?= <pemensik@redhat.com>
|
|
Date: Thu, 13 Feb 2025 13:20:28 +0100
|
|
Subject: [PATCH] Backport OpenSSL 3 provider support
|
|
|
|
Use gist of 451edf324281d30fbbe5669223dcea331670847c and
|
|
5fd6cfc625aa84005618236f4cd699c07367a3dc upstream commits, but do not do
|
|
significant rebase together. Move engine loading of EVP_PKEY from label to
|
|
openssl_link and copy provider variant from newer.
|
|
|
|
Remove legacy RSA calls from _fromlabel to separate engine handling
|
|
code. Make rsa_check accepting EVP_PKEY pair only and use conditional
|
|
compilation to verify them. Move checking of max exponent bits to
|
|
rsa_check too, because it is done from all usages anyway.
|
|
|
|
Use rsa_check_legacy in places where bit checking is not necessary.
|
|
|
|
Fix keyfromlabel to not use engine parameter for provider keys
|
|
|
|
- Rework key checks to not require 'engine' tag, private key
|
|
is valid with 'label' tag alone
|
|
|
|
- Fix _fromlabel() functions to work with engine == NULL
|
|
|
|
- Update dst__openssl_fromlabel_engine() to do provider lookup
|
|
only when engine is not set
|
|
|
|
(cherry picked from commit de486d0ec5d5642ddb1820a1269f5406a2bb1c64)
|
|
|
|
Use dst_key_t label to signal isprivate property as a downstream
|
|
alternative to upstream commit 74361b0b6e5a6b17ebeea6afe1ca990395d7a6dd.
|
|
That would require additional heavier changes.
|
|
|
|
Downstream change:
|
|
Move RSA bits check to legacy, let it use rsa_check for newer
|
|
|
|
rsabigexponent tests got broken by this change.
|
|
---
|
|
lib/dns/dst_openssl.h | 4 +
|
|
lib/dns/dst_parse.c | 21 ++--
|
|
lib/dns/openssl_link.c | 161 ++++++++++++++++++++++++++----
|
|
lib/dns/openssldh_link.c | 5 +
|
|
lib/dns/opensslecdsa_link.c | 110 ++++++++++-----------
|
|
lib/dns/openssleddsa_link.c | 40 +++-----
|
|
lib/dns/opensslrsa_link.c | 189 +++++++++++++++---------------------
|
|
7 files changed, 303 insertions(+), 227 deletions(-)
|
|
|
|
diff --git a/lib/dns/dst_openssl.h b/lib/dns/dst_openssl.h
|
|
index 819af0f..cd386c0 100644
|
|
--- a/lib/dns/dst_openssl.h
|
|
+++ b/lib/dns/dst_openssl.h
|
|
@@ -64,4 +64,8 @@ ENGINE *
|
|
dst__openssl_getengine(const char *engine);
|
|
#endif /* if !defined(OPENSSL_NO_ENGINE) && OPENSSL_API_LEVEL < 30000 */
|
|
|
|
+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_LANG_ENDDECLS
|
|
diff --git a/lib/dns/dst_parse.c b/lib/dns/dst_parse.c
|
|
index d5ea0e4..addb65e 100644
|
|
--- a/lib/dns/dst_parse.c
|
|
+++ b/lib/dns/dst_parse.c
|
|
@@ -195,10 +195,9 @@ check_rsa(const dst_private_t *priv, bool external) {
|
|
|
|
mask = (1ULL << TAG_SHIFT) - 1;
|
|
|
|
- if (have[TAG_RSA_ENGINE & mask]) {
|
|
+ if (have[TAG_RSA_LABEL & mask]) {
|
|
ok = have[TAG_RSA_MODULUS & mask] &&
|
|
- have[TAG_RSA_PUBLICEXPONENT & mask] &&
|
|
- have[TAG_RSA_LABEL & mask];
|
|
+ have[TAG_RSA_PUBLICEXPONENT & mask];
|
|
} else {
|
|
ok = have[TAG_RSA_MODULUS & mask] &&
|
|
have[TAG_RSA_PUBLICEXPONENT & mask] &&
|
|
@@ -259,11 +258,9 @@ check_ecdsa(const dst_private_t *priv, bool external) {
|
|
|
|
mask = (1ULL << TAG_SHIFT) - 1;
|
|
|
|
- if (have[TAG_ECDSA_ENGINE & mask]) {
|
|
- ok = have[TAG_ECDSA_LABEL & mask];
|
|
- } else {
|
|
- ok = have[TAG_ECDSA_PRIVATEKEY & mask];
|
|
- }
|
|
+ ok = have[TAG_ECDSA_LABEL & mask] ||
|
|
+ have[TAG_ECDSA_PRIVATEKEY & mask];
|
|
+
|
|
return ok ? 0 : -1;
|
|
}
|
|
|
|
@@ -295,11 +292,9 @@ check_eddsa(const dst_private_t *priv, bool external) {
|
|
|
|
mask = (1ULL << TAG_SHIFT) - 1;
|
|
|
|
- if (have[TAG_EDDSA_ENGINE & mask]) {
|
|
- ok = have[TAG_EDDSA_LABEL & mask];
|
|
- } else {
|
|
- ok = have[TAG_EDDSA_PRIVATEKEY & mask];
|
|
- }
|
|
+ ok = have[TAG_EDDSA_LABEL & mask] ||
|
|
+ have[TAG_EDDSA_PRIVATEKEY & mask];
|
|
+
|
|
return ok ? 0 : -1;
|
|
}
|
|
|
|
diff --git a/lib/dns/openssl_link.c b/lib/dns/openssl_link.c
|
|
index e3a89f4..62077b6 100644
|
|
--- a/lib/dns/openssl_link.c
|
|
+++ b/lib/dns/openssl_link.c
|
|
@@ -44,6 +44,9 @@
|
|
#if !defined(OPENSSL_NO_ENGINE) && OPENSSL_API_LEVEL < 30000
|
|
#include <openssl/engine.h>
|
|
#endif /* if !defined(OPENSSL_NO_ENGINE) && OPENSSL_API_LEVEL < 30000 */
|
|
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
|
+#include <openssl/store.h>
|
|
+#endif
|
|
|
|
#include "openssl_shim.h"
|
|
|
|
@@ -51,6 +54,12 @@
|
|
static ENGINE *e = NULL;
|
|
#endif /* if !defined(OPENSSL_NO_ENGINE) && OPENSSL_API_LEVEL < 30000 */
|
|
|
|
+#define DST_RET(a) \
|
|
+ { \
|
|
+ ret = a; \
|
|
+ goto err; \
|
|
+ }
|
|
+
|
|
static void
|
|
enable_fips_mode(void) {
|
|
#ifdef HAVE_FIPS_MODE
|
|
@@ -70,32 +79,28 @@ enable_fips_mode(void) {
|
|
|
|
isc_result_t
|
|
dst__openssl_init(const char *engine) {
|
|
- isc_result_t result = ISC_R_SUCCESS;
|
|
-
|
|
enable_fips_mode();
|
|
|
|
-#if !defined(OPENSSL_NO_ENGINE) && OPENSSL_API_LEVEL < 30000
|
|
if (engine != NULL && *engine == '\0') {
|
|
engine = NULL;
|
|
}
|
|
|
|
- if (engine != NULL) {
|
|
- e = ENGINE_by_id(engine);
|
|
- if (e == NULL) {
|
|
- result = DST_R_NOENGINE;
|
|
- goto cleanup_rm;
|
|
- }
|
|
- if (!ENGINE_init(e)) {
|
|
- result = DST_R_NOENGINE;
|
|
- goto cleanup_rm;
|
|
- }
|
|
- /* This will init the engine. */
|
|
- if (!ENGINE_set_default(e, ENGINE_METHOD_ALL)) {
|
|
- result = DST_R_NOENGINE;
|
|
- goto cleanup_init;
|
|
- }
|
|
+ if (engine == NULL) {
|
|
+ return (ISC_R_SUCCESS);
|
|
}
|
|
|
|
+#if !defined(OPENSSL_NO_ENGINE) && OPENSSL_API_LEVEL < 30000
|
|
+ e = ENGINE_by_id(engine);
|
|
+ if (e == NULL) {
|
|
+ goto cleanup_rm;
|
|
+ }
|
|
+ if (!ENGINE_init(e)) {
|
|
+ goto cleanup_rm;
|
|
+ }
|
|
+ /* This will init the engine. */
|
|
+ if (!ENGINE_set_default(e, ENGINE_METHOD_ALL)) {
|
|
+ goto cleanup_init;
|
|
+ }
|
|
return ISC_R_SUCCESS;
|
|
cleanup_init:
|
|
ENGINE_finish(e);
|
|
@@ -105,10 +110,8 @@ cleanup_rm:
|
|
}
|
|
e = NULL;
|
|
ERR_clear_error();
|
|
-#else
|
|
- UNUSED(engine);
|
|
#endif /* if !defined(OPENSSL_NO_ENGINE) && OPENSSL_API_LEVEL < 30000 */
|
|
- return result;
|
|
+ return (DST_R_NOENGINE);
|
|
}
|
|
|
|
void
|
|
@@ -220,4 +223,120 @@ dst__openssl_getengine(const char *engine) {
|
|
}
|
|
#endif /* if !defined(OPENSSL_NO_ENGINE) && OPENSSL_API_LEVEL < 30000 */
|
|
|
|
+static isc_result_t
|
|
+dst__openssl_fromlabel_engine(int key_base_id, const char *engine,
|
|
+ const char *label,
|
|
+ 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;
|
|
+ EVP_PKEY *pkey = NULL, *pubpkey = NULL;
|
|
+
|
|
+ UNUSED(key_base_id);
|
|
+
|
|
+ e = dst__openssl_getengine(engine);
|
|
+ if (e == NULL) {
|
|
+ DST_RET(dst__openssl_toresult(DST_R_NOENGINE));
|
|
+ }
|
|
+
|
|
+ pubpkey = ENGINE_load_public_key(e, label, NULL, NULL);
|
|
+ if (pubpkey == NULL) {
|
|
+ DST_RET(dst__openssl_toresult2("ENGINE_load_public_key",
|
|
+ DST_R_OPENSSLFAILURE));
|
|
+ }
|
|
+ if (EVP_PKEY_get_base_id(pubpkey) != key_base_id) {
|
|
+ DST_RET(DST_R_BADKEYTYPE);
|
|
+ }
|
|
+ pkey = ENGINE_load_private_key(e, label, NULL, NULL);
|
|
+ if (pkey == NULL) {
|
|
+ DST_RET(dst__openssl_toresult2("ENGINE_load_private_key",
|
|
+ DST_R_OPENSSLFAILURE));
|
|
+ }
|
|
+ if (EVP_PKEY_base_id(pkey) != key_base_id) {
|
|
+ DST_RET(DST_R_INVALIDPRIVATEKEY);
|
|
+ }
|
|
+ *ppub = pubpkey;
|
|
+ *ppriv = pkey;
|
|
+err:
|
|
+ return ret;
|
|
+#else
|
|
+ UNUSED(key_base_id);
|
|
+ UNUSED(engine);
|
|
+ UNUSED(label);
|
|
+ UNUSED(ppub);
|
|
+ UNUSED(ppriv);
|
|
+ return DST_R_NOENGINE;
|
|
+#endif
|
|
+}
|
|
+
|
|
+
|
|
+static isc_result_t
|
|
+dst__openssl_fromlabel_provider(int key_base_id, const char *label, const char *pin,
|
|
+ EVP_PKEY **ppub, EVP_PKEY **ppriv) {
|
|
+ UNUSED(pin);
|
|
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
|
+ isc_result_t ret = DST_R_OPENSSLFAILURE;
|
|
+ OSSL_STORE_CTX *ctx = NULL;
|
|
+
|
|
+
|
|
+ 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(label);
|
|
+ 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) {
|
|
+ if (engine == NULL) {
|
|
+ return (dst__openssl_fromlabel_provider(key_base_id, label,
|
|
+ pin, ppub, ppriv));
|
|
+ }
|
|
+
|
|
+ return (dst__openssl_fromlabel_engine(key_base_id, engine, label,
|
|
+ ppub, ppriv));
|
|
+}
|
|
+
|
|
/*! \file */
|
|
diff --git a/lib/dns/openssldh_link.c b/lib/dns/openssldh_link.c
|
|
index a4ba0f7..38345e6 100644
|
|
--- a/lib/dns/openssldh_link.c
|
|
+++ b/lib/dns/openssldh_link.c
|
|
@@ -610,6 +610,11 @@ err:
|
|
|
|
static bool
|
|
openssldh_isprivate(const dst_key_t *key) {
|
|
+ if (key->label != NULL) {
|
|
+ /* assume that _fromlabel will not pass without loading private key,
|
|
+ * but for non-exportable key cannot get d value on the object. */
|
|
+ return true;
|
|
+ }
|
|
#if OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000
|
|
DH *dh = key->keydata.dh;
|
|
const BIGNUM *priv_key = NULL;
|
|
diff --git a/lib/dns/opensslecdsa_link.c b/lib/dns/opensslecdsa_link.c
|
|
index ca12bb5..5d07014 100644
|
|
--- a/lib/dns/opensslecdsa_link.c
|
|
+++ b/lib/dns/opensslecdsa_link.c
|
|
@@ -617,6 +617,12 @@ opensslecdsa_isprivate(const dst_key_t *key) {
|
|
return false;
|
|
}
|
|
|
|
+ if (key->label != NULL) {
|
|
+ /* assume that _fromlabel will not pass without loading private key,
|
|
+ * but for non-exportable key cannot get d value on the object. */
|
|
+ return true;
|
|
+ }
|
|
+
|
|
#if OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000
|
|
eckey = EVP_PKEY_get1_EC_KEY(pkey);
|
|
|
|
@@ -916,7 +922,7 @@ err:
|
|
|
|
#if OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000
|
|
static isc_result_t
|
|
-ecdsa_check(EC_KEY *eckey, EC_KEY *pubeckey) {
|
|
+ecdsa_check_legacy(EC_KEY *eckey, EC_KEY *pubeckey) {
|
|
const EC_POINT *pubkey;
|
|
|
|
pubkey = EC_KEY_get0_public_key(eckey);
|
|
@@ -937,9 +943,42 @@ ecdsa_check(EC_KEY *eckey, EC_KEY *pubeckey) {
|
|
|
|
return ISC_R_FAILURE;
|
|
}
|
|
+
|
|
+static isc_result_t
|
|
+ecdsa_check(EVP_PKEY **pkey, EVP_PKEY *pubpkey, int group_nid) {
|
|
+ isc_result_t ret = ISC_R_FAILURE;
|
|
+ EC_KEY *eckey;
|
|
+ EC_KEY *pubeckey;
|
|
+
|
|
+ eckey = EVP_PKEY_get1_EC_KEY(*pkey);
|
|
+ if (eckey == NULL) {
|
|
+ DST_RET(dst__openssl_toresult(DST_R_OPENSSLFAILURE));
|
|
+ }
|
|
+ if (EC_GROUP_get_curve_name(EC_KEY_get0_group(eckey)) != group_nid) {
|
|
+ DST_RET(DST_R_INVALIDPRIVATEKEY);
|
|
+ }
|
|
+
|
|
+ pubeckey = EVP_PKEY_get1_EC_KEY(pubpkey);
|
|
+ if (pubeckey == NULL) {
|
|
+ DST_RET(dst__openssl_toresult(DST_R_OPENSSLFAILURE));
|
|
+ }
|
|
+ if (EC_GROUP_get_curve_name(EC_KEY_get0_group(pubeckey)) != group_nid) {
|
|
+ DST_RET(DST_R_INVALIDPUBLICKEY);
|
|
+ }
|
|
+
|
|
+ ret = ecdsa_check_legacy(eckey, pubeckey);
|
|
+err:
|
|
+ if (pubeckey != NULL) {
|
|
+ EC_KEY_free(pubeckey);
|
|
+ }
|
|
+ if (eckey != NULL) {
|
|
+ EC_KEY_free(eckey);
|
|
+ }
|
|
+ return ret;
|
|
+}
|
|
#else
|
|
static isc_result_t
|
|
-ecdsa_check(EVP_PKEY **pkey, EVP_PKEY *pubpkey) {
|
|
+ecdsa_check(EVP_PKEY **pkey, EVP_PKEY *pubpkey, int group_nid) {
|
|
isc_result_t ret = ISC_R_FAILURE;
|
|
int status;
|
|
size_t pkey_len = 0;
|
|
@@ -954,6 +993,8 @@ ecdsa_check(EVP_PKEY **pkey, EVP_PKEY *pubpkey) {
|
|
EVP_PKEY_CTX *ctx = NULL;
|
|
EVP_PKEY *pkey_new = NULL;
|
|
|
|
+ UNUSED(group_nid);
|
|
+
|
|
/* Check if `pkey` has a public key. */
|
|
status = EVP_PKEY_get_octet_string_param(*pkey, OSSL_PKEY_PARAM_PUB_KEY,
|
|
NULL, 0, &pkey_len);
|
|
@@ -1279,7 +1320,7 @@ opensslecdsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
|
|
pubeckey = EVP_PKEY_get1_EC_KEY(pub->keydata.pkey);
|
|
}
|
|
|
|
- if (ecdsa_check(eckey, pubeckey) != ISC_R_SUCCESS) {
|
|
+ if (ecdsa_check_legacy(eckey, pubeckey) != ISC_R_SUCCESS) {
|
|
DST_RET(dst__openssl_toresult(DST_R_INVALIDPRIVATEKEY));
|
|
}
|
|
|
|
@@ -1288,7 +1329,7 @@ opensslecdsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
|
|
}
|
|
#else
|
|
if (ecdsa_check(&key->keydata.pkey,
|
|
- pub == NULL ? NULL : pub->keydata.pkey) !=
|
|
+ pub == NULL ? NULL : pub->keydata.pkey, NID_undef) !=
|
|
ISC_R_SUCCESS)
|
|
{
|
|
DST_RET(dst__openssl_toresult(DST_R_INVALIDPRIVATEKEY));
|
|
@@ -1321,11 +1362,7 @@ err:
|
|
static isc_result_t
|
|
opensslecdsa_fromlabel(dst_key_t *key, const char *engine, const char *label,
|
|
const char *pin) {
|
|
-#if !defined(OPENSSL_NO_ENGINE) && OPENSSL_API_LEVEL < 30000
|
|
isc_result_t ret = ISC_R_SUCCESS;
|
|
- ENGINE *e;
|
|
- EC_KEY *eckey = NULL;
|
|
- EC_KEY *pubeckey = NULL;
|
|
int group_nid;
|
|
EVP_PKEY *pkey = NULL;
|
|
EVP_PKEY *pubpkey = NULL;
|
|
@@ -1335,13 +1372,9 @@ opensslecdsa_fromlabel(dst_key_t *key, const char *engine, const char *label,
|
|
|
|
UNUSED(pin);
|
|
|
|
- if (engine == NULL || label == NULL) {
|
|
+ if (label == NULL) {
|
|
return DST_R_NOENGINE;
|
|
}
|
|
- e = dst__openssl_getengine(engine);
|
|
- if (e == NULL) {
|
|
- DST_RET(DST_R_NOENGINE);
|
|
- }
|
|
|
|
if (key->key_alg == DST_ALG_ECDSA256) {
|
|
group_nid = NID_X9_62_prime256v1;
|
|
@@ -1349,48 +1382,30 @@ opensslecdsa_fromlabel(dst_key_t *key, const char *engine, const char *label,
|
|
group_nid = NID_secp384r1;
|
|
}
|
|
|
|
- /* Load private key. */
|
|
- pkey = ENGINE_load_private_key(e, label, NULL, NULL);
|
|
- if (pkey == NULL) {
|
|
- DST_RET(dst__openssl_toresult2("ENGINE_load_private_key",
|
|
- DST_R_OPENSSLFAILURE));
|
|
+ ret = dst__openssl_fromlabel(EVP_PKEY_EC, engine, label, pin,
|
|
+ &pubpkey, &pkey);
|
|
+ if (ret != ISC_R_SUCCESS) {
|
|
+ goto err;
|
|
}
|
|
+
|
|
/* Check base id, group nid */
|
|
if (EVP_PKEY_base_id(pkey) != EVP_PKEY_EC) {
|
|
DST_RET(DST_R_INVALIDPRIVATEKEY);
|
|
}
|
|
- eckey = EVP_PKEY_get1_EC_KEY(pkey);
|
|
- if (eckey == NULL) {
|
|
- DST_RET(dst__openssl_toresult(DST_R_OPENSSLFAILURE));
|
|
- }
|
|
- if (EC_GROUP_get_curve_name(EC_KEY_get0_group(eckey)) != group_nid) {
|
|
- DST_RET(DST_R_INVALIDPRIVATEKEY);
|
|
- }
|
|
-
|
|
- /* Load public key. */
|
|
- pubpkey = ENGINE_load_public_key(e, label, NULL, NULL);
|
|
- if (pubpkey == NULL) {
|
|
- DST_RET(dst__openssl_toresult2("ENGINE_load_public_key",
|
|
- DST_R_OPENSSLFAILURE));
|
|
- }
|
|
/* Check base id, group nid */
|
|
if (EVP_PKEY_base_id(pubpkey) != EVP_PKEY_EC) {
|
|
DST_RET(DST_R_INVALIDPUBLICKEY);
|
|
}
|
|
- pubeckey = EVP_PKEY_get1_EC_KEY(pubpkey);
|
|
- if (pubeckey == NULL) {
|
|
- DST_RET(dst__openssl_toresult(DST_R_OPENSSLFAILURE));
|
|
- }
|
|
- if (EC_GROUP_get_curve_name(EC_KEY_get0_group(pubeckey)) != group_nid) {
|
|
- DST_RET(DST_R_INVALIDPUBLICKEY);
|
|
- }
|
|
|
|
- if (ecdsa_check(eckey, pubeckey) != ISC_R_SUCCESS) {
|
|
+ if (ecdsa_check(&pkey, pubpkey, group_nid) != ISC_R_SUCCESS) {
|
|
DST_RET(dst__openssl_toresult(DST_R_INVALIDPRIVATEKEY));
|
|
}
|
|
|
|
+ if (engine != NULL)
|
|
+ key->engine = isc_mem_strdup(key->mctx, engine);
|
|
+ else
|
|
+ key->engine = NULL;
|
|
key->label = isc_mem_strdup(key->mctx, label);
|
|
- key->engine = isc_mem_strdup(key->mctx, engine);
|
|
key->key_size = EVP_PKEY_bits(pkey);
|
|
key->keydata.pkey = pkey;
|
|
pkey = NULL;
|
|
@@ -1402,21 +1417,8 @@ err:
|
|
if (pkey != NULL) {
|
|
EVP_PKEY_free(pkey);
|
|
}
|
|
- if (pubeckey != NULL) {
|
|
- EC_KEY_free(pubeckey);
|
|
- }
|
|
- if (eckey != NULL) {
|
|
- EC_KEY_free(eckey);
|
|
- }
|
|
|
|
return ret;
|
|
-#else
|
|
- UNUSED(key);
|
|
- UNUSED(engine);
|
|
- UNUSED(label);
|
|
- UNUSED(pin);
|
|
- return DST_R_NOENGINE;
|
|
-#endif /* !defined(OPENSSL_NO_ENGINE) && OPENSSL_API_LEVEL < 30000 */
|
|
}
|
|
|
|
static dst_func_t opensslecdsa_functions = {
|
|
diff --git a/lib/dns/openssleddsa_link.c b/lib/dns/openssleddsa_link.c
|
|
index 74dac17..04457fb 100644
|
|
--- a/lib/dns/openssleddsa_link.c
|
|
+++ b/lib/dns/openssleddsa_link.c
|
|
@@ -361,6 +361,12 @@ openssleddsa_isprivate(const dst_key_t *key) {
|
|
return false;
|
|
}
|
|
|
|
+ if (key->label != NULL) {
|
|
+ /* assume that _fromlabel will not pass without loading private key,
|
|
+ * but for non-exportable key cannot get d value on the object. */
|
|
+ return true;
|
|
+ }
|
|
+
|
|
/* Must have a buffer to actually check if there is a private key. */
|
|
if (EVP_PKEY_get_raw_private_key(pkey, buf, &len) == 1) {
|
|
return true;
|
|
@@ -603,9 +609,7 @@ err:
|
|
static isc_result_t
|
|
openssleddsa_fromlabel(dst_key_t *key, const char *engine, const char *label,
|
|
const char *pin) {
|
|
-#if !defined(OPENSSL_NO_ENGINE) && OPENSSL_API_LEVEL < 30000
|
|
isc_result_t ret;
|
|
- ENGINE *e;
|
|
EVP_PKEY *pkey = NULL, *pubpkey = NULL;
|
|
int baseid = EVP_PKEY_NONE;
|
|
|
|
@@ -628,28 +632,17 @@ openssleddsa_fromlabel(dst_key_t *key, const char *engine, const char *label,
|
|
return ISC_R_NOTIMPLEMENTED;
|
|
}
|
|
|
|
- if (engine == NULL) {
|
|
- return DST_R_NOENGINE;
|
|
- }
|
|
- e = dst__openssl_getengine(engine);
|
|
- if (e == NULL) {
|
|
- return DST_R_NOENGINE;
|
|
- }
|
|
- pkey = ENGINE_load_private_key(e, label, NULL, NULL);
|
|
- if (pkey == NULL) {
|
|
- return dst__openssl_toresult2("ENGINE_load_private_key",
|
|
- ISC_R_NOTFOUND);
|
|
- }
|
|
- if (EVP_PKEY_base_id(pkey) != baseid) {
|
|
- DST_RET(DST_R_INVALIDPRIVATEKEY);
|
|
- }
|
|
+ DST_RET(dst__openssl_fromlabel(baseid, engine, label, pin,
|
|
+ &pubpkey, &pkey));
|
|
|
|
- pubpkey = ENGINE_load_public_key(e, label, NULL, NULL);
|
|
- if (eddsa_check(pkey, pubpkey) != ISC_R_SUCCESS) {
|
|
+ if (EVP_PKEY_base_id(pkey) != baseid) {
|
|
DST_RET(DST_R_INVALIDPRIVATEKEY);
|
|
}
|
|
|
|
- key->engine = isc_mem_strdup(key->mctx, engine);
|
|
+ if (engine != NULL)
|
|
+ key->engine = isc_mem_strdup(key->mctx, engine);
|
|
+ else
|
|
+ key->engine = NULL;
|
|
key->label = isc_mem_strdup(key->mctx, label);
|
|
key->key_size = EVP_PKEY_bits(pkey);
|
|
key->keydata.pkey = pkey;
|
|
@@ -664,13 +657,6 @@ err:
|
|
EVP_PKEY_free(pkey);
|
|
}
|
|
return ret;
|
|
-#else /* if !defined(OPENSSL_NO_ENGINE) && OPENSSL_API_LEVEL < 30000 */
|
|
- UNUSED(key);
|
|
- UNUSED(engine);
|
|
- UNUSED(label);
|
|
- UNUSED(pin);
|
|
- return DST_R_NOENGINE;
|
|
-#endif /* if !defined(OPENSSL_NO_ENGINE) && OPENSSL_API_LEVEL < 30000 */
|
|
}
|
|
|
|
static dst_func_t openssleddsa_functions = {
|
|
diff --git a/lib/dns/opensslrsa_link.c b/lib/dns/opensslrsa_link.c
|
|
index 37e8a63..d4fbe97 100644
|
|
--- a/lib/dns/opensslrsa_link.c
|
|
+++ b/lib/dns/opensslrsa_link.c
|
|
@@ -545,6 +545,12 @@ opensslrsa_isprivate(const dst_key_t *key) {
|
|
return false;
|
|
}
|
|
|
|
+ if (key->label != NULL) {
|
|
+ /* assume that _fromlabel will not pass without loading private key,
|
|
+ * but for non-exportable key cannot get d value on the object. */
|
|
+ return true;
|
|
+ }
|
|
+
|
|
#if OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000
|
|
rsa = EVP_PKEY_get1_RSA(pkey);
|
|
INSIST(rsa != NULL);
|
|
@@ -995,7 +1001,7 @@ err:
|
|
|
|
#if OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000
|
|
static isc_result_t
|
|
-rsa_check(RSA *rsa, RSA *pub) {
|
|
+rsa_check_legacy(RSA *rsa, RSA *pub) {
|
|
const BIGNUM *n1 = NULL, *n2 = NULL;
|
|
const BIGNUM *e1 = NULL, *e2 = NULL;
|
|
BIGNUM *n = NULL, *e = NULL;
|
|
@@ -1050,6 +1056,46 @@ rsa_check(RSA *rsa, RSA *pub) {
|
|
|
|
return ISC_R_SUCCESS;
|
|
}
|
|
+
|
|
+static isc_result_t
|
|
+rsa_check(EVP_PKEY *pkey, EVP_PKEY *pubpkey) {
|
|
+ isc_result_t ret = ISC_R_FAILURE;
|
|
+ RSA *rsa = NULL, *pubrsa = NULL;
|
|
+ const BIGNUM *ex = NULL;
|
|
+
|
|
+ pubrsa = EVP_PKEY_get1_RSA(pubpkey);
|
|
+ if (pubrsa == NULL) {
|
|
+ DST_RET(dst__openssl_toresult(DST_R_OPENSSLFAILURE));
|
|
+ }
|
|
+
|
|
+ rsa = EVP_PKEY_get1_RSA(pkey);
|
|
+ if (rsa == NULL) {
|
|
+ DST_RET(dst__openssl_toresult(DST_R_OPENSSLFAILURE));
|
|
+ }
|
|
+
|
|
+ ret = rsa_check_legacy(rsa, pubrsa);
|
|
+ if (ret != ISC_R_SUCCESS) {
|
|
+ DST_RET(ret);
|
|
+ }
|
|
+
|
|
+ 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);
|
|
+ }
|
|
+
|
|
+err:
|
|
+ if (rsa != NULL) {
|
|
+ RSA_free(rsa);
|
|
+ }
|
|
+ if (pubrsa != NULL) {
|
|
+ RSA_free(pubrsa);
|
|
+ }
|
|
+ return ret;
|
|
+}
|
|
#else
|
|
static isc_result_t
|
|
rsa_check(EVP_PKEY *pkey, EVP_PKEY *pubpkey) {
|
|
@@ -1097,6 +1143,10 @@ rsa_check(EVP_PKEY *pkey, EVP_PKEY *pubpkey) {
|
|
}
|
|
}
|
|
|
|
+ if (BN_num_bits(e1) > RSA_MAX_PUBEXP_BITS) {
|
|
+ DST_RET(ISC_R_RANGE);
|
|
+ }
|
|
+
|
|
if (EVP_PKEY_eq(pkey, pubpkey) == 1) {
|
|
DST_RET(ISC_R_SUCCESS);
|
|
}
|
|
@@ -1119,6 +1169,10 @@ err:
|
|
}
|
|
#endif /* OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000 */
|
|
|
|
+static isc_result_t
|
|
+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) {
|
|
dst_private_t priv;
|
|
@@ -1131,12 +1185,8 @@ opensslrsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
|
|
OSSL_PARAM *params = NULL;
|
|
EVP_PKEY_CTX *ctx = NULL;
|
|
#endif /* OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000 */
|
|
-#if !defined(OPENSSL_NO_ENGINE) && OPENSSL_API_LEVEL < 30000
|
|
- const BIGNUM *ex = NULL;
|
|
- ENGINE *ep = NULL;
|
|
- const char *engine = NULL;
|
|
-#endif /* if !defined(OPENSSL_NO_ENGINE) && OPENSSL_API_LEVEL < 30000 */
|
|
isc_mem_t *mctx = NULL;
|
|
+ const char *engine = NULL;
|
|
const char *label = NULL;
|
|
EVP_PKEY *pkey = NULL;
|
|
BIGNUM *n = NULL, *e = NULL, *d = NULL;
|
|
@@ -1193,46 +1243,7 @@ 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);
|
|
- }
|
|
- ep = dst__openssl_getengine(engine);
|
|
- if (ep == NULL) {
|
|
- DST_RET(dst__openssl_toresult(DST_R_NOENGINE));
|
|
- }
|
|
- 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 */
|
|
- DST_RET(DST_R_NOENGINE);
|
|
-#endif /* if !defined(OPENSSL_NO_ENGINE) && OPENSSL_API_LEVEL < 30000 */
|
|
+ DST_RET(opensslrsa_fromlabel(key, engine, label, NULL));
|
|
}
|
|
|
|
for (i = 0; i < priv.nelements; i++) {
|
|
@@ -1321,9 +1332,14 @@ 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) {
|
|
+ if (rsa_check_legacy(rsa, pubrsa) != ISC_R_SUCCESS) {
|
|
DST_RET(dst__openssl_toresult(DST_R_INVALIDPRIVATEKEY));
|
|
}
|
|
+
|
|
+ if (BN_num_bits(e) > RSA_MAX_PUBEXP_BITS) {
|
|
+ DST_RET(ISC_R_RANGE);
|
|
+ }
|
|
+
|
|
#else
|
|
bld = OSSL_PARAM_BLD_new();
|
|
if (bld == NULL) {
|
|
@@ -1390,17 +1406,12 @@ 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));
|
|
+ ret = rsa_check(pkey, pub != NULL ? pub->keydata.pkey : NULL);
|
|
+ if (ret != ISC_R_SUCCESS) {
|
|
+ DST_RET(ret);
|
|
}
|
|
#endif /* OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000 */
|
|
|
|
- if (BN_num_bits(e) > RSA_MAX_PUBEXP_BITS) {
|
|
- DST_RET(ISC_R_RANGE);
|
|
- }
|
|
-
|
|
key->key_size = BN_num_bits(n);
|
|
key->keydata.pkey = pkey;
|
|
pkey = NULL;
|
|
@@ -1464,69 +1475,30 @@ err:
|
|
static isc_result_t
|
|
opensslrsa_fromlabel(dst_key_t *key, const char *engine, const char *label,
|
|
const char *pin) {
|
|
-#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;
|
|
|
|
UNUSED(pin);
|
|
|
|
- if (engine == NULL) {
|
|
- DST_RET(DST_R_NOENGINE);
|
|
- }
|
|
- e = dst__openssl_getengine(engine);
|
|
- if (e == NULL) {
|
|
- DST_RET(dst__openssl_toresult(DST_R_NOENGINE));
|
|
- }
|
|
-
|
|
- pubpkey = ENGINE_load_public_key(e, label, NULL, NULL);
|
|
- if (pubpkey == NULL) {
|
|
- 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));
|
|
- }
|
|
+ ret = dst__openssl_fromlabel(EVP_PKEY_RSA, engine, label, pin,
|
|
+ &pubpkey, &pkey);
|
|
+ if (ret != ISC_R_SUCCESS)
|
|
+ DST_RET(ret);
|
|
|
|
- pkey = ENGINE_load_private_key(e, label, NULL, NULL);
|
|
- if (pkey == NULL) {
|
|
- DST_RET(dst__openssl_toresult2("ENGINE_load_private_key",
|
|
- DST_R_OPENSSLFAILURE));
|
|
- }
|
|
+ ret = rsa_check(pkey, pubpkey);
|
|
+ if (ret != ISC_R_SUCCESS)
|
|
+ DST_RET(ret);
|
|
|
|
- key->engine = isc_mem_strdup(key->mctx, engine);
|
|
+ if (engine != NULL)
|
|
+ key->engine = isc_mem_strdup(key->mctx, engine);
|
|
+ else
|
|
+ key->engine = NULL;
|
|
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;
|
|
|
|
err:
|
|
- if (rsa != NULL) {
|
|
- RSA_free(rsa);
|
|
- }
|
|
- if (pubrsa != NULL) {
|
|
- RSA_free(pubrsa);
|
|
- }
|
|
if (pkey != NULL) {
|
|
EVP_PKEY_free(pkey);
|
|
}
|
|
@@ -1534,13 +1506,6 @@ err:
|
|
EVP_PKEY_free(pubpkey);
|
|
}
|
|
return ret;
|
|
-#else /* if !defined(OPENSSL_NO_ENGINE) && OPENSSL_API_LEVEL < 30000 */
|
|
- UNUSED(key);
|
|
- UNUSED(engine);
|
|
- UNUSED(label);
|
|
- UNUSED(pin);
|
|
- return DST_R_NOENGINE;
|
|
-#endif /* if !defined(OPENSSL_NO_ENGINE) && OPENSSL_API_LEVEL < 30000 */
|
|
}
|
|
|
|
static dst_func_t opensslrsa_functions = {
|
|
--
|
|
2.50.1
|
|
|