]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Generate Ed25519/Ed448 keys via PKCS#11 when a label is set 11591/head
authorMichal Nowak <mnowak@isc.org>
Thu, 14 May 2026 14:50:58 +0000 (14:50 +0000)
committerMichal Nowak <mnowak@isc.org>
Tue, 26 May 2026 11:18:56 +0000 (11:18 +0000)
When a dst_key_t carries a PKCS#11 URI in key->label (as named
does for dnssec-policy zones backed by a key-store "hsm"), key
generation must happen inside the HSM, not in software.
opensslecdsa_generate already branches on key->label and calls
the matching pkcs11 wrapper; the EDDSA generator silently ignored
the label and produced a software key, which named then wrote to
the .private file with both a Label: line and the raw PrivateKey:
bytes -- a corrupt hybrid record that prevented zone signing.

Add the missing wrapper:

  - lib/isc/ossl_wrap/ossl3.c gains generate_pkcs11_eddsa_key()
    and the public isc_ossl_wrap_generate_pkcs11_ed25519_key() /
    isc_ossl_wrap_generate_pkcs11_ed448_key() entry points.  They
    use EVP_PKEY_CTX_new_from_name(NULL, "ED25519" or "ED448",
    "provider=pkcs11") with the pkcs11_uri and pkcs11_key_usage
    parameters, mirroring the existing EC wrapper.
  - lib/isc/ossl_wrap/ossl1_1.c provides stubs returning
    ISC_R_NOTIMPLEMENTED for the new EDDSA wrappers; the
    pkcs11-provider stack requires OpenSSL 3.  The pre-existing
    isc_ossl_wrap_generate_pkcs11_rsa_key() stub used to silently
    delegate to software keygen -- that hid the same "HSM label
    on a software key" hazard for RSA on OpenSSL 1.1 builds, so
    align it with the EDDSA stubs and return ISC_R_NOTIMPLEMENTED
    too.
  - lib/isc/include/isc/ossl_wrap.h declares the new wrappers.
  - lib/dns/openssleddsa_link.c routes openssleddsa_generate()
    through the new wrappers when key->label is non-NULL, leaving
    the existing EVP_PKEY_keygen() path untouched for software
    keys.  The Ed448 case is guarded by HAVE_OPENSSL_ED448 to
    match the surrounding code.

Assisted-by: Claude:claude-opus-4-7
lib/dns/openssleddsa_link.c
lib/isc/include/isc/ossl_wrap.h
lib/isc/ossl_wrap/ossl1_1.c
lib/isc/ossl_wrap/ossl3.c

index 26cc36072793b65d727a54587c036d80c2a9f616..0d30defcc4be7db17df3f01cdd3fdec77800b02e 100644 (file)
@@ -22,6 +22,7 @@
 
 #include <isc/crypto.h>
 #include <isc/mem.h>
+#include <isc/ossl_wrap.h>
 #include <isc/result.h>
 #include <isc/safe.h>
 #include <isc/string.h>
@@ -270,6 +271,27 @@ openssleddsa_generate(dst_key_t *key, int unused, void (*callback)(int)) {
        UNUSED(unused);
        UNUSED(callback);
 
+       if (key->label != NULL) {
+               switch (key->key_alg) {
+               case DST_ALG_ED25519:
+                       RETERR(isc_ossl_wrap_generate_pkcs11_ed25519_key(
+                               key->label, &pkey));
+                       break;
+#if HAVE_OPENSSL_ED448
+               case DST_ALG_ED448:
+                       RETERR(isc_ossl_wrap_generate_pkcs11_ed448_key(
+                               key->label, &pkey));
+                       break;
+#endif /* HAVE_OPENSSL_ED448 */
+               default:
+                       UNREACHABLE();
+               }
+               key->key_size = alginfo->key_size * 8;
+               key->keydata.pkeypair.priv = pkey;
+               key->keydata.pkeypair.pub = pkey;
+               return ISC_R_SUCCESS;
+       }
+
        ctx = EVP_PKEY_CTX_new_id(alginfo->nid, NULL);
        if (ctx == NULL) {
                return dst__openssl_toresult2("EVP_PKEY_CTX_new_id",
index 4831fab405c78333b335127a492b70622a8160e0..cfb1cf2faf4129a261a32add6cfbb18f1c954821 100644 (file)
@@ -131,6 +131,28 @@ isc_ossl_wrap_generate_pkcs11_p384_key(char *uri, EVP_PKEY **pkeyp);
  * \li `uri != NULL` and is a NUL-terminated string
  */
 
+isc_result_t
+isc_ossl_wrap_generate_pkcs11_ed25519_key(char *uri, EVP_PKEY **pkeyp);
+/*%
+ * Generates an Ed25519 key using the PKCS#11 label specified at `uri`.
+ *
+ * Requires:
+ * \li pkeyp != NULL
+ * \li *pkeyp == NULL
+ * \li `uri != NULL` and is a NUL-terminated string
+ */
+
+isc_result_t
+isc_ossl_wrap_generate_pkcs11_ed448_key(char *uri, EVP_PKEY **pkeyp);
+/*%
+ * Generates an Ed448 key using the PKCS#11 label specified at `uri`.
+ *
+ * Requires:
+ * \li pkeyp != NULL
+ * \li *pkeyp == NULL
+ * \li `uri != NULL` and is a NUL-terminated string
+ */
+
 isc_result_t
 isc_ossl_wrap_load_p384_public_from_region(isc_region_t region,
                                           EVP_PKEY   **pkeyp);
index de325c47c4b6aaf856373bfd9bd37703a06824d4..6a5740a3b8e9961db04758eb90f287c2ee4d9472 100644 (file)
@@ -410,9 +410,33 @@ cleanup:
 isc_result_t
 isc_ossl_wrap_generate_pkcs11_rsa_key(char *uri, size_t bit_size,
                                      EVP_PKEY **pkeyp) {
+       REQUIRE(uri != NULL);
+       REQUIRE(pkeyp != NULL && *pkeyp == NULL);
+
+       UNUSED(uri);
+       UNUSED(bit_size);
+       UNUSED(pkeyp);
+       return ISC_R_NOTIMPLEMENTED;
+}
+
+isc_result_t
+isc_ossl_wrap_generate_pkcs11_ed25519_key(char *uri, EVP_PKEY **pkeyp) {
+       REQUIRE(uri != NULL);
+       REQUIRE(pkeyp != NULL && *pkeyp == NULL);
+
        UNUSED(uri);
+       UNUSED(pkeyp);
+       return ISC_R_NOTIMPLEMENTED;
+}
+
+isc_result_t
+isc_ossl_wrap_generate_pkcs11_ed448_key(char *uri, EVP_PKEY **pkeyp) {
+       REQUIRE(uri != NULL);
+       REQUIRE(pkeyp != NULL && *pkeyp == NULL);
 
-       return isc_ossl_wrap_generate_rsa_key(NULL, bit_size, pkeyp);
+       UNUSED(uri);
+       UNUSED(pkeyp);
+       return ISC_R_NOTIMPLEMENTED;
 }
 
 bool
index 92334b2d1cb9a0ca96e200a0e8fa762d5b16cd24..7021ff5f5d9a878cd00f68e25b6fe162efb73eb0 100644 (file)
@@ -239,6 +239,60 @@ cleanup:
        return result;
 }
 
+static isc_result_t
+generate_pkcs11_eddsa_key(char *uri, EVP_PKEY **pkeyp, const char *keytype) {
+       isc_result_t result;
+       EVP_PKEY_CTX *pctx = NULL;
+       size_t len;
+
+       INSIST(uri != NULL);
+       len = strlen(uri);
+
+       const OSSL_PARAM params[] = {
+               OSSL_PARAM_utf8_string("pkcs11_uri", uri, len),
+               OSSL_PARAM_utf8_string("pkcs11_key_usage", pkcs11_key_usage,
+                                      sizeof(pkcs11_key_usage) - 1),
+               OSSL_PARAM_END,
+       };
+
+       pctx = EVP_PKEY_CTX_new_from_name(NULL, keytype, "provider=pkcs11");
+       if (pctx == NULL) {
+               CLEANUP(OSSL_WRAP_ERROR("EVP_PKEY_CTX_new_from_name"));
+       }
+
+       if (EVP_PKEY_keygen_init(pctx) != 1) {
+               CLEANUP(OSSL_WRAP_ERROR("EVP_PKEY_keygen_init"));
+       }
+
+       if (EVP_PKEY_CTX_set_params(pctx, params) != 1) {
+               CLEANUP(OSSL_WRAP_ERROR("EVP_PKEY_CTX_set_params"));
+       }
+
+       if (EVP_PKEY_generate(pctx, pkeyp) != 1) {
+               CLEANUP(OSSL_WRAP_ERROR("EVP_PKEY_generate"));
+       }
+
+       result = ISC_R_SUCCESS;
+
+cleanup:
+       EVP_PKEY_CTX_free(pctx);
+       return result;
+}
+
+isc_result_t
+isc_ossl_wrap_generate_pkcs11_ed25519_key(char *uri, EVP_PKEY **pkeyp) {
+       REQUIRE(pkeyp != NULL && *pkeyp == NULL);
+       REQUIRE(uri != NULL);
+       return generate_pkcs11_eddsa_key(uri, pkeyp, "ED25519");
+}
+
+isc_result_t
+isc_ossl_wrap_generate_pkcs11_ed448_key(char *uri, EVP_PKEY **pkeyp) {
+       REQUIRE(pkeyp != NULL && *pkeyp == NULL);
+       REQUIRE(uri != NULL);
+       return generate_pkcs11_eddsa_key(uri, pkeyp, "ED448");
+}
+
 static isc_result_t
 validate_ec_pkey(EVP_PKEY *pkey, const OSSL_PARAM *const curve_params) {
        isc_result_t result;
@@ -523,6 +577,9 @@ isc_ossl_wrap_generate_pkcs11_rsa_key(char *uri, size_t bit_size,
        int status;
        size_t len;
 
+       REQUIRE(uri != NULL);
+       REQUIRE(pkeyp != NULL && *pkeyp == NULL);
+
        len = strlen(uri);
        INSIST(len != 0);