]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Implement support for OpenSSL 3 Provider API stored RSA keys
authorTimo Teräs <timo.teras@iki.fi>
Mon, 26 Dec 2022 17:42:32 +0000 (19:42 +0200)
committerOndřej Surý <ondrej@isc.org>
Mon, 9 Jan 2023 18:22:40 +0000 (19:22 +0100)
Allows using pkcs11-provider module for PKCS#11 keys

lib/dns/dst_openssl.h
lib/dns/openssl_link.c
lib/dns/opensslrsa_link.c

index 375c9351b64beb367e1781e333b5eebfe540a5c1..188e72cd160ffc4d67578d0e0c8c23a2a85b7f3d 100644 (file)
@@ -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
index 2e606b81edfc93f24b2e85c3894a4f66108d1294..f23f86443ec20a89f14cff526e2c27efd3062fa5 100644 (file)
 #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/core_names.h>
+#include <openssl/store.h>
+#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 */
index 715c0a564c5d81be523e755ccff72cc7093d7e85..efef7fe14a93d92ef92f3c871b45dcd2bd101905 100644 (file)
@@ -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;
        }