]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
remove libcrypto version specific code in opensslecdsa_link
authorAydın Mercan <aydin@isc.org>
Mon, 1 Dec 2025 14:07:54 +0000 (17:07 +0300)
committerAydın Mercan <aydin@isc.org>
Mon, 2 Feb 2026 08:50:14 +0000 (11:50 +0300)
Using `EVP_SIGNATURE` explicit algoritms for signatures have been added
in OpenSSL 3.4 and so is skipped for the initial OpenSSL version
specific code splitting.

lib/dns/opensslecdsa_link.c
lib/isc/include/isc/ossl_wrap.h
lib/isc/ossl_wrap/ossl1_1.c
lib/isc/ossl_wrap/ossl3.c

index 9203cdba045377c1e9b8253a2f51bbdbe19fd3a6..7b89b3f25ad1bf141ff9d22dfa2512ab78181f60 100644 (file)
 
 #include <openssl/bn.h>
 #include <openssl/ecdsa.h>
-#include <openssl/err.h>
 #include <openssl/evp.h>
 #include <openssl/objects.h>
-#include <openssl/opensslv.h>
-#if OPENSSL_VERSION_NUMBER >= 0x30000000L
-#include <openssl/core_names.h>
-#include <openssl/param_build.h>
-#endif
 
 #include <isc/crypto.h>
 #include <isc/md.h>
@@ -55,37 +49,6 @@ extern EVP_MD *isc__crypto_md[];
 
 #define MAX_PRIVKEY_SIZE (MAX_PUBKEY_SIZE / 2)
 
-#if OPENSSL_VERSION_NUMBER >= 0x30200000L
-static isc_result_t
-opensslecdsa_set_deterministic(EVP_PKEY_CTX *pctx, unsigned int key_alg) {
-       unsigned int rfc6979 = 1;
-       const char *md = NULL;
-       OSSL_PARAM params[3];
-
-       switch (key_alg) {
-       case DST_ALG_ECDSA256:
-               md = "SHA256";
-               break;
-       case DST_ALG_ECDSA384:
-               md = "SHA384";
-               break;
-       default:
-               UNREACHABLE();
-       }
-
-       params[0] = OSSL_PARAM_construct_utf8_string("digest", UNCONST(md), 0);
-       params[1] = OSSL_PARAM_construct_uint("nonce-type", &rfc6979);
-       params[2] = OSSL_PARAM_construct_end();
-
-       if (EVP_PKEY_CTX_set_params(pctx, params) != 1) {
-               return dst__openssl_toresult2("EVP_PKEY_CTX_set_params",
-                                             DST_R_OPENSSLFAILURE);
-       }
-
-       return ISC_R_SUCCESS;
-}
-#endif /* OPENSSL_VERSION_NUMBER >= 0x30200000L */
-
 static bool
 opensslecdsa_valid_key_alg(unsigned int key_alg) {
        switch (key_alg) {
@@ -97,18 +60,6 @@ opensslecdsa_valid_key_alg(unsigned int key_alg) {
        }
 }
 
-static int
-opensslecdsa_key_alg_to_group_nid(unsigned int key_alg) {
-       switch (key_alg) {
-       case DST_ALG_ECDSA256:
-               return NID_X9_62_prime256v1;
-       case DST_ALG_ECDSA384:
-               return NID_secp384r1;
-       default:
-               UNREACHABLE();
-       }
-}
-
 static size_t
 opensslecdsa_key_alg_to_publickey_size(unsigned int key_alg) {
        switch (key_alg) {
@@ -121,23 +72,6 @@ opensslecdsa_key_alg_to_publickey_size(unsigned int key_alg) {
        }
 }
 
-/*
- * OpenSSL requires us to set the public key portion, but since our private key
- * file format does not contain it directly, we generate it as needed.
- */
-static EC_POINT *
-opensslecdsa_generate_public_key(const EC_GROUP *group, const BIGNUM *privkey) {
-       EC_POINT *pubkey = EC_POINT_new(group);
-       if (pubkey == NULL) {
-               return NULL;
-       }
-       if (EC_POINT_mul(group, pubkey, privkey, NULL, NULL, NULL) != 1) {
-               EC_POINT_free(pubkey);
-               return NULL;
-       }
-       return pubkey;
-}
-
 static int
 BN_bn2bin_fixed(const BIGNUM *bn, unsigned char *buf, int size) {
        int bytes = size - BN_num_bytes(bn);
@@ -151,534 +85,13 @@ BN_bn2bin_fixed(const BIGNUM *bn, unsigned char *buf, int size) {
        return size;
 }
 
-#if OPENSSL_VERSION_NUMBER >= 0x30000000L
-
-static const char *
-opensslecdsa_key_alg_to_group_name(unsigned int key_alg) {
-       switch (key_alg) {
-       case DST_ALG_ECDSA256:
-               return "prime256v1";
-       case DST_ALG_ECDSA384:
-               return "secp384r1";
-       default:
-               UNREACHABLE();
-       }
-}
-
-static isc_result_t
-opensslecdsa_create_pkey_params(unsigned int key_alg, bool private,
-                               const unsigned char *key, size_t key_len,
-                               EVP_PKEY **pkey) {
-       isc_result_t result;
-       int status;
-       int group_nid = opensslecdsa_key_alg_to_group_nid(key_alg);
-       const char *groupname = opensslecdsa_key_alg_to_group_name(key_alg);
-       OSSL_PARAM_BLD *bld = NULL;
-       OSSL_PARAM *params = NULL;
-       EVP_PKEY_CTX *ctx = NULL;
-       EC_POINT *pubkey = NULL;
-       EC_GROUP *group = NULL;
-       BIGNUM *priv = NULL;
-       unsigned char buf[MAX_PUBKEY_SIZE + 1];
-
-       bld = OSSL_PARAM_BLD_new();
-       if (bld == NULL) {
-               CLEANUP(dst__openssl_toresult2("OSSL_PARAM_BLD_new",
-                                              DST_R_OPENSSLFAILURE));
-       }
-       status = OSSL_PARAM_BLD_push_utf8_string(
-               bld, OSSL_PKEY_PARAM_GROUP_NAME, groupname, 0);
-       if (status != 1) {
-               CLEANUP(dst__openssl_toresult2("OSSL_PARAM_BLD_push_"
-                                              "utf8_string",
-                                              DST_R_OPENSSLFAILURE));
-       }
-
-       if (private) {
-               group = EC_GROUP_new_by_curve_name(group_nid);
-               if (group == NULL) {
-                       CLEANUP(dst__openssl_toresult2("EC_GROUP_new_by_"
-                                                      "curve_name",
-                                                      DST_R_OPENSSLFAILURE));
-               }
-
-               priv = BN_bin2bn(key, key_len, NULL);
-               if (priv == NULL) {
-                       CLEANUP(dst__openssl_toresult2("BN_bin2bn",
-                                                      DST_R_OPENSSLFAILURE));
-               }
-
-               status = OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_PRIV_KEY,
-                                               priv);
-               if (status != 1) {
-                       CLEANUP(dst__openssl_toresult2("OSSL_PARAM_BLD_push_BN",
-                                                      DST_R_OPENSSLFAILURE));
-               }
-
-               pubkey = opensslecdsa_generate_public_key(group, priv);
-               if (pubkey == NULL) {
-                       CLEANUP(dst__openssl_toresult(DST_R_OPENSSLFAILURE));
-               }
-
-               key = buf;
-               key_len = EC_POINT_point2oct(group, pubkey,
-                                            POINT_CONVERSION_UNCOMPRESSED, buf,
-                                            sizeof(buf), NULL);
-               if (key_len == 0) {
-                       CLEANUP(dst__openssl_toresult2("EC_POINT_point2oct",
-                                                      DST_R_OPENSSLFAILURE));
-               }
-       } else {
-               INSIST(key_len + 1 <= sizeof(buf));
-               buf[0] = POINT_CONVERSION_UNCOMPRESSED;
-               memmove(buf + 1, key, key_len);
-               key = buf;
-               key_len = key_len + 1;
-       }
-
-       status = OSSL_PARAM_BLD_push_octet_string(bld, OSSL_PKEY_PARAM_PUB_KEY,
-                                                 key, key_len);
-       if (status != 1) {
-               CLEANUP(dst__openssl_toresult2("OSSL_PARAM_BLD_push_"
-                                              "octet_string",
-                                              DST_R_OPENSSLFAILURE));
-       }
-
-       params = OSSL_PARAM_BLD_to_param(bld);
-       if (params == NULL) {
-               CLEANUP(dst__openssl_toresult2("OSSL_PARAM_BLD_to_param",
-                                              DST_R_OPENSSLFAILURE));
-       }
-       ctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL);
-       if (ctx == NULL) {
-               CLEANUP(dst__openssl_toresult2("EVP_PKEY_CTX_new_from_name",
-                                              DST_R_OPENSSLFAILURE));
-       }
-       status = EVP_PKEY_fromdata_init(ctx);
-       if (status != 1) {
-               /* This will fail if the default provider is an engine.
-                * Return ISC_R_FAILURE to retry using the legacy API. */
-               CLEANUP(dst__openssl_toresult(ISC_R_FAILURE));
-       }
-       status = EVP_PKEY_fromdata(
-               ctx, pkey, private ? EVP_PKEY_KEYPAIR : EVP_PKEY_PUBLIC_KEY,
-               params);
-       if (status != 1 || *pkey == NULL) {
-               CLEANUP(dst__openssl_toresult2("EVP_PKEY_fromdata",
-                                              DST_R_OPENSSLFAILURE));
-       }
-
-       result = ISC_R_SUCCESS;
-
-cleanup:
-       OSSL_PARAM_free(params);
-       OSSL_PARAM_BLD_free(bld);
-       EVP_PKEY_CTX_free(ctx);
-       BN_clear_free(priv);
-       EC_POINT_free(pubkey);
-       EC_GROUP_free(group);
-
-       return result;
-}
-
-static bool
-opensslecdsa_extract_public_key_params(const dst_key_t *key, unsigned char *dst,
-                                      size_t dstlen) {
-       EVP_PKEY *pkey = key->keydata.pkeypair.pub;
-       BIGNUM *x = NULL;
-       BIGNUM *y = NULL;
-       bool ret = false;
-
-       if (EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_EC_PUB_X, &x) == 1 &&
-           EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_EC_PUB_Y, &y) == 1)
-       {
-               BN_bn2bin_fixed(x, &dst[0], dstlen / 2);
-               BN_bn2bin_fixed(y, &dst[dstlen / 2], dstlen / 2);
-               ret = true;
-       }
-       BN_clear_free(x);
-       BN_clear_free(y);
-       return ret;
-}
-
-#endif
-
-#if OPENSSL_VERSION_NUMBER < 0x30000000L
-
-static isc_result_t
-opensslecdsa_create_pkey_legacy(unsigned int key_alg, bool private,
-                               const unsigned char *key, size_t key_len,
-                               EVP_PKEY **retkey) {
-       isc_result_t result = ISC_R_SUCCESS;
-       EC_KEY *eckey = NULL;
-       EVP_PKEY *pkey = NULL;
-       BIGNUM *privkey = NULL;
-       EC_POINT *pubkey = NULL;
-       unsigned char buf[MAX_PUBKEY_SIZE + 1];
-       int group_nid = opensslecdsa_key_alg_to_group_nid(key_alg);
-
-       eckey = EC_KEY_new_by_curve_name(group_nid);
-       if (eckey == NULL) {
-               CLEANUP(dst__openssl_toresult(DST_R_OPENSSLFAILURE));
-       }
-
-       if (private) {
-               const EC_GROUP *group = EC_KEY_get0_group(eckey);
-
-               privkey = BN_bin2bn(key, key_len, NULL);
-               if (privkey == NULL) {
-                       CLEANUP(dst__openssl_toresult(DST_R_OPENSSLFAILURE));
-               }
-               if (!EC_KEY_set_private_key(eckey, privkey)) {
-                       CLEANUP(dst__openssl_toresult(DST_R_INVALIDPRIVATEKEY));
-               }
-
-               pubkey = opensslecdsa_generate_public_key(group, privkey);
-               if (pubkey == NULL) {
-                       CLEANUP(dst__openssl_toresult(DST_R_OPENSSLFAILURE));
-               }
-               if (EC_KEY_set_public_key(eckey, pubkey) != 1) {
-                       CLEANUP(dst__openssl_toresult(DST_R_OPENSSLFAILURE));
-               }
-       } else {
-               const unsigned char *cp = buf;
-               INSIST(key_len + 1 <= sizeof(buf));
-               buf[0] = POINT_CONVERSION_UNCOMPRESSED;
-               memmove(buf + 1, key, key_len);
-               if (o2i_ECPublicKey(&eckey, &cp, key_len + 1) == NULL) {
-                       CLEANUP(dst__openssl_toresult(DST_R_INVALIDPUBLICKEY));
-               }
-               if (EC_KEY_check_key(eckey) != 1) {
-                       CLEANUP(dst__openssl_toresult(DST_R_INVALIDPUBLICKEY));
-               }
-       }
-
-       pkey = EVP_PKEY_new();
-       if (pkey == NULL) {
-               CLEANUP(dst__openssl_toresult(ISC_R_NOMEMORY));
-       }
-       if (!EVP_PKEY_set1_EC_KEY(pkey, eckey)) {
-               CLEANUP(dst__openssl_toresult(ISC_R_FAILURE));
-       }
-
-       *retkey = pkey;
-       pkey = NULL;
-
-cleanup:
-       BN_clear_free(privkey);
-       EC_POINT_free(pubkey);
-       EC_KEY_free(eckey);
-       EVP_PKEY_free(pkey);
-       return result;
-}
-
-static bool
-opensslecdsa_extract_public_key_legacy(const dst_key_t *key, unsigned char *dst,
-                                      size_t dstlen) {
-       EVP_PKEY *pkey = key->keydata.pkeypair.pub;
-       const EC_KEY *eckey = EVP_PKEY_get0_EC_KEY(pkey);
-       const EC_GROUP *group = (eckey == NULL) ? NULL
-                                               : EC_KEY_get0_group(eckey);
-       const EC_POINT *pub = (eckey == NULL) ? NULL
-                                             : EC_KEY_get0_public_key(eckey);
-       unsigned char buf[MAX_PUBKEY_SIZE + 1];
-       size_t len;
-
-       if (group == NULL || pub == NULL) {
-               return false;
-       }
-
-       len = EC_POINT_point2oct(group, pub, POINT_CONVERSION_UNCOMPRESSED, buf,
-                                sizeof(buf), NULL);
-       if (len == dstlen + 1) {
-               memmove(dst, buf + 1, dstlen);
-               return true;
-       }
-       return false;
-}
-
-#endif
-
-static bool
-opensslecdsa_extract_public_key(const dst_key_t *key, unsigned char *dst,
-                               size_t dstlen) {
-#if OPENSSL_VERSION_NUMBER >= 0x30000000L
-       if (opensslecdsa_extract_public_key_params(key, dst, dstlen)) {
-               return true;
-       }
-#else
-       if (opensslecdsa_extract_public_key_legacy(key, dst, dstlen)) {
-               return true;
-       }
-#endif
-       return false;
-}
-
-static isc_result_t
-opensslecdsa_create_pkey(unsigned int key_alg, bool private,
-                        const unsigned char *key, size_t key_len,
-                        EVP_PKEY **retkey) {
-       isc_result_t result;
-#if OPENSSL_VERSION_NUMBER >= 0x30000000L
-       result = opensslecdsa_create_pkey_params(key_alg, private, key, key_len,
-                                                retkey);
-       if (result != ISC_R_FAILURE) {
-               return result;
-       }
-#else
-       result = opensslecdsa_create_pkey_legacy(key_alg, private, key, key_len,
-                                                retkey);
-       if (result == ISC_R_SUCCESS) {
-               return result;
-       }
-#endif
-       return DST_R_OPENSSLFAILURE;
-}
-
-#if OPENSSL_VERSION_NUMBER >= 0x30000000L
-
-static isc_result_t
-opensslecdsa_generate_pkey_with_uri(int group_nid, const char *label,
-                                   EVP_PKEY **retkey) {
-       int status;
-       isc_result_t result;
-       char *uri = UNCONST(label);
-       EVP_PKEY_CTX *ctx = NULL;
-       OSSL_PARAM params[3];
-
-       /* Generate the key's parameters. */
-       params[0] = OSSL_PARAM_construct_utf8_string("pkcs11_uri", uri, 0);
-       params[1] = OSSL_PARAM_construct_utf8_string(
-               "pkcs11_key_usage", (char *)"digitalSignature", 0);
-       params[2] = OSSL_PARAM_construct_end();
-
-       ctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", "provider=pkcs11");
-       if (ctx == NULL) {
-               CLEANUP(dst__openssl_toresult2("EVP_PKEY_CTX_new_from_name",
-                                              DST_R_OPENSSLFAILURE));
-       }
-
-       status = EVP_PKEY_keygen_init(ctx);
-       if (status != 1) {
-               CLEANUP(dst__openssl_toresult2("EVP_PKEY_keygen_init",
-                                              DST_R_OPENSSLFAILURE));
-       }
-
-       status = EVP_PKEY_CTX_set_params(ctx, params);
-       if (status != 1) {
-               CLEANUP(dst__openssl_toresult2("EVP_PKEY_CTX_set_params",
-                                              DST_R_OPENSSLFAILURE));
-       }
-       /*
-        * Setting the P-384 curve doesn't work correctly when using:
-        * OSSL_PARAM_construct_utf8_string("ec_paramgen_curve", "P-384", 0);
-        *
-        * Instead use the OpenSSL function to set the curve nid param.
-        */
-       status = EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, group_nid);
-       if (status != 1) {
-               CLEANUP(dst__openssl_toresult2("EVP_PKEY_CTX_set_ec_paramgen_"
-                                              "curve_nid",
-                                              DST_R_OPENSSLFAILURE));
-       }
-
-       /* Generate the key. */
-       status = EVP_PKEY_generate(ctx, retkey);
-       if (status != 1) {
-               CLEANUP(dst__openssl_toresult2("EVP_PKEY_generate",
-                                              DST_R_OPENSSLFAILURE));
-       }
-
-       result = ISC_R_SUCCESS;
-
-cleanup:
-       EVP_PKEY_CTX_free(ctx);
-       return result;
-}
-
-static isc_result_t
-opensslecdsa_generate_pkey(unsigned int key_alg, const char *label,
-                          EVP_PKEY **retkey) {
-       isc_result_t result;
-       EVP_PKEY_CTX *ctx = NULL;
-       EVP_PKEY *params_pkey = NULL;
-       int group_nid = opensslecdsa_key_alg_to_group_nid(key_alg);
-       int status;
-
-       if (label != NULL) {
-               return opensslecdsa_generate_pkey_with_uri(group_nid, label,
-                                                          retkey);
-       }
-
-       /* Generate the key's parameters. */
-       ctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL);
-       if (ctx == NULL) {
-               CLEANUP(dst__openssl_toresult2("EVP_PKEY_CTX_new_from_name",
-                                              DST_R_OPENSSLFAILURE));
-       }
-       status = EVP_PKEY_paramgen_init(ctx);
-       if (status != 1) {
-               CLEANUP(dst__openssl_toresult2("EVP_PKEY_paramgen_init",
-                                              DST_R_OPENSSLFAILURE));
-       }
-       status = EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, group_nid);
-       if (status != 1) {
-               CLEANUP(dst__openssl_toresult2("EVP_PKEY_CTX_set_ec_paramgen_"
-                                              "curve_nid",
-                                              DST_R_OPENSSLFAILURE));
-       }
-       status = EVP_PKEY_paramgen(ctx, &params_pkey);
-       if (status != 1 || params_pkey == NULL) {
-               CLEANUP(dst__openssl_toresult2("EVP_PKEY_paramgen",
-                                              DST_R_OPENSSLFAILURE));
-       }
-       EVP_PKEY_CTX_free(ctx);
-
-       /* Generate the key. */
-       ctx = EVP_PKEY_CTX_new(params_pkey, NULL);
-       if (ctx == NULL) {
-               CLEANUP(dst__openssl_toresult2("EVP_PKEY_CTX_new",
-                                              DST_R_OPENSSLFAILURE));
-       }
-
-       status = EVP_PKEY_keygen_init(ctx);
-       if (status != 1) {
-               CLEANUP(dst__openssl_toresult2("EVP_PKEY_keygen_init",
-                                              DST_R_OPENSSLFAILURE));
-       }
-       status = EVP_PKEY_keygen(ctx, retkey);
-       if (status != 1) {
-               CLEANUP(dst__openssl_toresult2("EVP_PKEY_keygen",
-                                              DST_R_OPENSSLFAILURE));
-       }
-       result = ISC_R_SUCCESS;
-
-cleanup:
-       EVP_PKEY_free(params_pkey);
-       EVP_PKEY_CTX_free(ctx);
-       return result;
-}
-
-static isc_result_t
-opensslecdsa_validate_pkey_group(unsigned int key_alg, EVP_PKEY *pkey) {
-       const char *groupname = opensslecdsa_key_alg_to_group_name(key_alg);
-       char gname[64];
-
-       if (EVP_PKEY_get_group_name(pkey, gname, sizeof(gname), NULL) != 1) {
-               return DST_R_INVALIDPRIVATEKEY;
-       }
-       if (strcmp(gname, groupname) != 0) {
-               return DST_R_INVALIDPRIVATEKEY;
-       }
-       return ISC_R_SUCCESS;
-}
-
-static bool
-opensslecdsa_extract_private_key(const dst_key_t *key, unsigned char *buf,
-                                size_t buflen) {
-       EVP_PKEY *pkey = key->keydata.pkeypair.priv;
-       BIGNUM *priv = NULL;
-
-       if (EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_PRIV_KEY, &priv) != 1) {
-               return false;
-       }
-
-       BN_bn2bin_fixed(priv, buf, buflen);
-       BN_clear_free(priv);
-       return true;
-}
-
-#else
-
-static isc_result_t
-opensslecdsa_generate_pkey(unsigned int key_alg, const char *label,
-                          EVP_PKEY **retkey) {
-       isc_result_t result;
-       EC_KEY *eckey = NULL;
-       EVP_PKEY *pkey = NULL;
-       int group_nid;
-
-       UNUSED(label);
-
-       group_nid = opensslecdsa_key_alg_to_group_nid(key_alg);
-
-       eckey = EC_KEY_new_by_curve_name(group_nid);
-       if (eckey == NULL) {
-               CLEANUP(dst__openssl_toresult2("EC_KEY_new_by_curve_name",
-                                              DST_R_OPENSSLFAILURE));
-       }
-
-       if (EC_KEY_generate_key(eckey) != 1) {
-               CLEANUP(dst__openssl_toresult2("EC_KEY_generate_key",
-                                              DST_R_OPENSSLFAILURE));
-       }
-
-       pkey = EVP_PKEY_new();
-       if (pkey == NULL) {
-               CLEANUP(dst__openssl_toresult(ISC_R_NOMEMORY));
-       }
-       if (EVP_PKEY_set1_EC_KEY(pkey, eckey) != 1) {
-               CLEANUP(dst__openssl_toresult2("EVP_PKEY_set1_EC_KEY",
-                                              DST_R_OPENSSLFAILURE));
-       }
-       *retkey = pkey;
-       pkey = NULL;
-       result = ISC_R_SUCCESS;
-
-cleanup:
-       EC_KEY_free(eckey);
-       EVP_PKEY_free(pkey);
-       return result;
-}
-
-static isc_result_t
-opensslecdsa_validate_pkey_group(unsigned int key_alg, EVP_PKEY *pkey) {
-       const EC_KEY *eckey = EVP_PKEY_get0_EC_KEY(pkey);
-       int group_nid;
-
-       if (eckey == NULL) {
-               return dst__openssl_toresult(DST_R_INVALIDPRIVATEKEY);
-       }
-
-       group_nid = opensslecdsa_key_alg_to_group_nid(key_alg);
-
-       if (EC_GROUP_get_curve_name(EC_KEY_get0_group(eckey)) != group_nid) {
-               return DST_R_INVALIDPRIVATEKEY;
-       }
-
-       return ISC_R_SUCCESS;
-}
-
-static bool
-opensslecdsa_extract_private_key(const dst_key_t *key, unsigned char *buf,
-                                size_t buflen) {
-       const EC_KEY *eckey = NULL;
-       const BIGNUM *privkey = NULL;
-
-       eckey = EVP_PKEY_get0_EC_KEY(key->keydata.pkeypair.priv);
-       if (eckey == NULL) {
-               ERR_clear_error();
-               return false;
-       }
-
-       privkey = EC_KEY_get0_private_key(eckey);
-       if (privkey == NULL) {
-               ERR_clear_error();
-               return false;
-       }
-
-       BN_bn2bin_fixed(privkey, buf, buflen);
-       return true;
-}
-
-#endif /* OPENSSL_VERSION_NUMBER >= 0x30000000L */
-
 static isc_result_t
 opensslecdsa_createctx(dst_key_t *key, dst_context_t *dctx) {
        isc_result_t result = ISC_R_SUCCESS;
        EVP_MD_CTX *evp_md_ctx;
        EVP_PKEY_CTX *pctx = NULL;
        const EVP_MD *type = NULL;
+       const char *md = NULL;
 
        UNUSED(key);
        REQUIRE(opensslecdsa_valid_key_alg(dctx->key->key_alg));
@@ -690,8 +103,10 @@ opensslecdsa_createctx(dst_key_t *key, dst_context_t *dctx) {
        }
        if (dctx->key->key_alg == DST_ALG_ECDSA256) {
                type = isc__crypto_md[ISC_MD_SHA256];
+               md = "SHA256";
        } else {
                type = isc__crypto_md[ISC_MD_SHA384];
+               md = "SHA384";
        }
 
        if (dctx->use == DO_SIGN) {
@@ -704,12 +119,15 @@ opensslecdsa_createctx(dst_key_t *key, dst_context_t *dctx) {
                                                       ISC_R_FAILURE));
                }
 
-#if OPENSSL_VERSION_NUMBER >= 0x30200000L
                if (!isc_crypto_fips_mode()) {
-                       CHECK(opensslecdsa_set_deterministic(
-                               pctx, dctx->key->key_alg));
+                       result = isc_ossl_wrap_ecdsa_set_deterministic(pctx,
+                                                                      md);
+                       if (result != ISC_R_SUCCESS &&
+                           result != ISC_R_NOTIMPLEMENTED)
+                       {
+                               CLEANUP(result);
+                       }
                }
-#endif /* OPENSSL_VERSION_NUMBER >= 0x30200000L */
 
        } else {
                if (EVP_DigestVerifyInit(evp_md_ctx, NULL, type, NULL,
@@ -723,6 +141,7 @@ opensslecdsa_createctx(dst_key_t *key, dst_context_t *dctx) {
        }
 
        dctx->ctxdata.evp_md_ctx = evp_md_ctx;
+       result = ISC_R_SUCCESS;
 
 cleanup:
        return result;
@@ -921,7 +340,31 @@ opensslecdsa_generate(dst_key_t *key, int unused, void (*callback)(int)) {
        UNUSED(unused);
        UNUSED(callback);
 
-       RETERR(opensslecdsa_generate_pkey(key->key_alg, key->label, &pkey));
+       if (key->label != NULL) {
+               switch (key->key_alg) {
+               case DST_ALG_ECDSA256:
+                       RETERR(isc_ossl_wrap_generate_pkcs11_p256_key(
+                               key->label, &pkey));
+                       break;
+               case DST_ALG_ECDSA384:
+                       RETERR(isc_ossl_wrap_generate_pkcs11_p384_key(
+                               key->label, &pkey));
+                       break;
+               default:
+                       UNREACHABLE();
+               }
+       } else {
+               switch (key->key_alg) {
+               case DST_ALG_ECDSA256:
+                       RETERR(isc_ossl_wrap_generate_p256_key(&pkey));
+                       break;
+               case DST_ALG_ECDSA384:
+                       RETERR(isc_ossl_wrap_generate_p384_key(&pkey));
+                       break;
+               default:
+                       UNREACHABLE();
+               }
+       }
 
        key->key_size = EVP_PKEY_bits(pkey);
        key->keydata.pkeypair.priv = pkey;
@@ -933,6 +376,7 @@ static isc_result_t
 opensslecdsa_todns(const dst_key_t *key, isc_buffer_t *data) {
        isc_result_t result;
        isc_region_t r;
+       EVP_PKEY *pkey;
        size_t keysize;
 
        REQUIRE(opensslecdsa_valid_key_alg(key->key_alg));
@@ -943,8 +387,23 @@ opensslecdsa_todns(const dst_key_t *key, isc_buffer_t *data) {
        if (r.length < keysize) {
                CLEANUP(ISC_R_NOSPACE);
        }
-       if (!opensslecdsa_extract_public_key(key, r.base, keysize)) {
-               CLEANUP(dst__openssl_toresult(DST_R_OPENSSLFAILURE));
+
+       pkey = key->keydata.pkeypair.pub;
+       switch (key->key_alg) {
+       case DST_ALG_ECDSA256:
+               if (isc_ossl_wrap_p256_public_region(pkey, r) != ISC_R_SUCCESS)
+               {
+                       CLEANUP(dst__openssl_toresult(DST_R_OPENSSLFAILURE));
+               }
+               break;
+       case DST_ALG_ECDSA384:
+               if (isc_ossl_wrap_p384_public_region(pkey, r) != ISC_R_SUCCESS)
+               {
+                       CLEANUP(dst__openssl_toresult(DST_R_OPENSSLFAILURE));
+               }
+               break;
+       default:
+               UNREACHABLE();
        }
 
        isc_buffer_add(data, keysize);
@@ -972,8 +431,16 @@ opensslecdsa_fromdns(dst_key_t *key, isc_buffer_t *data) {
                CLEANUP(DST_R_INVALIDPUBLICKEY);
        }
 
-       CHECK(opensslecdsa_create_pkey(key->key_alg, false, r.base, len,
-                                      &pkey));
+       switch (key->key_alg) {
+       case DST_ALG_ECDSA256:
+               CHECK(isc_ossl_wrap_load_p256_public_from_region(r, &pkey));
+               break;
+       case DST_ALG_ECDSA384:
+               CHECK(isc_ossl_wrap_load_p384_public_from_region(r, &pkey));
+               break;
+       default:
+               UNREACHABLE();
+       }
 
        isc_buffer_forward(data, len);
        key->key_size = EVP_PKEY_bits(pkey);
@@ -991,6 +458,7 @@ opensslecdsa_tofile(const dst_key_t *key, const char *directory) {
        unsigned char buf[MAX_PRIVKEY_SIZE];
        size_t keylen = 0;
        unsigned short i;
+       EVP_PKEY *pkey;
 
        if (key->keydata.pkeypair.pub == NULL) {
                CLEANUP(DST_R_NULLKEY);
@@ -1008,8 +476,23 @@ opensslecdsa_tofile(const dst_key_t *key, const char *directory) {
        keylen = opensslecdsa_key_alg_to_publickey_size(key->key_alg) / 2;
        INSIST(keylen <= sizeof(buf));
 
+       pkey = key->keydata.pkeypair.priv;
+
        i = 0;
-       if (opensslecdsa_extract_private_key(key, buf, keylen)) {
+       switch (key->key_alg) {
+       case DST_ALG_ECDSA256:
+               result = isc_ossl_wrap_p256_secret_region(
+                       pkey, (isc_region_t){ buf, keylen });
+               break;
+       case DST_ALG_ECDSA384:
+               result = isc_ossl_wrap_p384_secret_region(
+                       pkey, (isc_region_t){ buf, keylen });
+               break;
+       default:
+               UNREACHABLE();
+       }
+
+       if (result == ISC_R_SUCCESS) {
                priv.elements[i].tag = TAG_ECDSA_PRIVATEKEY;
                priv.elements[i].length = keylen;
                priv.elements[i].data = buf;
@@ -1039,6 +522,7 @@ static isc_result_t
 opensslecdsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
        dst_private_t priv;
        isc_result_t result;
+       isc_region_t r;
        EVP_PKEY *pkey = NULL;
        const char *label = NULL;
        int i, privkey_index = -1;
@@ -1091,9 +575,21 @@ opensslecdsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
                CLEANUP(dst__openssl_toresult(DST_R_INVALIDPRIVATEKEY));
        }
 
-       CHECK(opensslecdsa_create_pkey(
-               key->key_alg, true, priv.elements[privkey_index].data,
-               priv.elements[privkey_index].length, &pkey));
+       r = (isc_region_t){
+               .base = priv.elements[privkey_index].data,
+               .length = priv.elements[privkey_index].length,
+       };
+
+       switch (key->key_alg) {
+       case DST_ALG_ECDSA256:
+               CHECK(isc_ossl_wrap_load_p256_secret_from_region(r, &pkey));
+               break;
+       case DST_ALG_ECDSA384:
+               CHECK(isc_ossl_wrap_load_p384_secret_from_region(r, &pkey));
+               break;
+       default:
+               UNREACHABLE();
+       }
 
        /* Check that the public component matches if given */
        if (pub != NULL && EVP_PKEY_eq(pkey, pub->keydata.pkeypair.pub) != 1) {
@@ -1127,8 +623,18 @@ opensslecdsa_fromlabel(dst_key_t *key, const char *label, const char *pin) {
        CHECK(dst__openssl_fromlabel(EVP_PKEY_EC, label, pin, &pubpkey,
                                     &privpkey));
 
-       CHECK(opensslecdsa_validate_pkey_group(key->key_alg, privpkey));
-       CHECK(opensslecdsa_validate_pkey_group(key->key_alg, pubpkey));
+       switch (key->key_alg) {
+       case DST_ALG_ECDSA256:
+               CHECK(isc_ossl_wrap_validate_p256_pkey(privpkey));
+               CHECK(isc_ossl_wrap_validate_p256_pkey(pubpkey));
+               break;
+       case DST_ALG_ECDSA384:
+               CHECK(isc_ossl_wrap_validate_p384_pkey(privpkey));
+               CHECK(isc_ossl_wrap_validate_p384_pkey(pubpkey));
+               break;
+       default:
+               UNREACHABLE();
+       }
 
        key->label = isc_mem_strdup(key->mctx, label);
        key->key_size = EVP_PKEY_bits(privpkey);
index cef831793889bbc2557b5d2e376088cf8093a91e..96f282a13b0bfb7ce2bccedaedaad9e1af074e7d 100644 (file)
@@ -31,6 +31,179 @@ typedef struct isc_ossl_wrap_rsa_components {
        BIGNUM *e, *n, *d, *p, *q, *dmp1, *dmq1, *iqmp;
 } isc_ossl_wrap_rsa_components_t;
 
+isc_result_t
+isc_ossl_wrap_generate_p256_key(EVP_PKEY **pkeyp);
+/*%
+ * Generates an uncompressed, named P-256 secret key.
+ *
+ * Requires:
+ * \li pkeyp != NULL
+ * \li *pkeyp == NULL
+ */
+
+isc_result_t
+isc_ossl_wrap_generate_pkcs11_p256_key(char *uri, EVP_PKEY **pkeyp);
+/*%
+ * Generates a P-256 secret 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_validate_p256_pkey(EVP_PKEY *pkey);
+/*%
+ * Validatest that a EVP_PKEY is a P-256 EC key.
+ *
+ * Requires:
+ * \li `pkey != NULL`
+ * \li pkey is a valid EVP_PKEY
+ */
+
+isc_result_t
+isc_ossl_wrap_load_p256_public_from_region(isc_region_t region,
+                                          EVP_PKEY   **pkeyp);
+/*%
+ * Create a verifying `EVP_PKEY` using the P-256 public key pointed by
+ * `region`.
+ *
+ * Requires:
+ * \li `pkeyp != NULL`
+ * \li `*pkeyp == NULL`
+ * \li `region.base != NULL`
+ * \li `region.length == 64`
+ */
+
+isc_result_t
+isc_ossl_wrap_load_p256_secret_from_region(isc_region_t region,
+                                          EVP_PKEY   **pkeyp);
+/*%
+ * Create a signing `EVP_PKEY` using the P-256 secret key pointed by
+ * `region`.
+ *
+ * Requires:
+ * \li `pkeyp != NULL`
+ * \li `*pkeyp == NULL`
+ * \li `region.base != NULL`
+ * \li `region.length == 32`
+ */
+
+isc_result_t
+isc_ossl_wrap_p256_public_region(EVP_PKEY *pkey, isc_region_t pub);
+/*%
+ * Export the P-256 public key to the region pointed by `pub`
+ *
+ * Requires:
+ * \li `pkey` is a non-NULL, valid, P-256 public key.
+ * \li `pub` has to a non-NULL pointer with enough space to fit the public key.
+ */
+
+isc_result_t
+isc_ossl_wrap_p256_secret_region(EVP_PKEY *pkey, isc_region_t sec);
+/*%
+ * Export the P-256 curve secret key to the region pointed by `sec`
+ *
+ * Requires:
+ * \li `pkey` is a non-NULL, valid P-256 secret key.
+ * \li `sec` has to a non-NULL pointer with enough space to fit the secret key.
+ */
+
+isc_result_t
+isc_ossl_wrap_generate_p384_key(EVP_PKEY **pkeyp);
+/*%
+ * Generates an uncompressed, named P-256 secret key.
+ *
+ * Requires:
+ * \li pkeyp != NULL
+ * \li *pkeyp == NULL
+ */
+
+isc_result_t
+isc_ossl_wrap_generate_pkcs11_p384_key(char *uri, EVP_PKEY **pkeyp);
+/*%
+ * Generates a P-384 secret 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);
+/*%
+ * Create a verifying `EVP_PKEY` using the P-384 public key pointed by
+ * `region`.
+ *
+ * Requires:
+ * \li `pkeyp != NULL`
+ * \li `*pkeyp == NULL`
+ * \li `region.base != NULL`
+ * \li `region.length == 64`
+ */
+
+isc_result_t
+isc_ossl_wrap_load_p384_secret_from_region(isc_region_t region,
+                                          EVP_PKEY   **pkeyp);
+/*%
+ * Create a signing `EVP_PKEY` using the P-384 secret key pointed by
+ * `region`.
+ *
+ * Requires:
+ * \li `pkeyp != NULL`
+ * \li `*pkeyp == NULL`
+ * \li `region.base != NULL`
+ * \li `region.length == 32`
+ */
+
+isc_result_t
+isc_ossl_wrap_validate_p384_pkey(EVP_PKEY *pkey);
+
+isc_result_t
+isc_ossl_wrap_p384_public_region(EVP_PKEY *pkey, isc_region_t pub);
+/*%
+ * Export the P-384 public key to the region pointed by `pub`
+ *
+ * Requires:
+ * \li `pkey` is a non-NULL, valid, P-384 public key.
+ * \li `pub` has to a non-NULL pointer with enough space to fit the public key.
+ */
+
+isc_result_t
+isc_ossl_wrap_p384_secret_region(EVP_PKEY *pkey, isc_region_t sec);
+/*%
+ * Export the P-384 curve secret key to the region pointed by `sec`
+ *
+ * Requires:
+ * \li `pkey` is a non-NULL, valid P-384 secret key.
+ * \li `sec` has to a non-NULL pointer with enough space to fit the secret key.
+ */
+
+isc_result_t
+isc_ossl_wrap_ecdsa_set_deterministic(EVP_PKEY_CTX *pctx, const char *hash);
+/*
+ * Use deterministic ECDSA to generate signatures.
+ *
+ * Returns:
+ * \li #ISC_R_SUCCESS          -- signature set to use RFC6979
+ * \li #ISC_R_IGNORE           -- FIPS mode is active
+ * \li #ISC_R_NOTIMPLEMENTED   -- libcrypto doesn't support
+ */
+
+isc_result_t
+isc_ossl_wrap_ecdsa_set_deterministic(EVP_PKEY_CTX *pctx, const char *hash);
+/*
+ * Use deterministic ECDSA to generate signatures.
+ *
+ * Returns:
+ * \li #ISC_R_SUCCESS          -- signature set to use RFC6979
+ * \li #ISC_R_IGNORE           -- FIPS mode is active
+ * \li #ISC_R_NOTIMPLEMENTED   -- libcrypto doesn't support RFC6979
+ */
+
 isc_result_t
 isc_ossl_wrap_generate_rsa_key(void (*callback)(int), size_t bit_size,
                               EVP_PKEY **pkeyp);
index 32fac0d1d610bcc3faa3e6a81f6068caf4165347..e5d63e2706e0456d9211d75119b1769e14b1594d 100644 (file)
  */
 
 #include <openssl/bn.h>
+#include <openssl/ec.h>
 #include <openssl/evp.h>
 #include <openssl/rsa.h>
 
 #include <isc/ossl_wrap.h>
+#include <isc/region.h>
 #include <isc/util.h>
 
+#define MAX_PUBLIC_KEY_SIZE 96
+#define MAX_SECRET_KEY_SIZE 48
+
 #define OSSL_WRAP_ERROR(fn)                                        \
        isc__ossl_wrap_logged_toresult(                            \
                ISC_LOGCATEGORY_GENERAL, ISC_LOGMODULE_CRYPTO, fn, \
                ISC_R_CRYPTOFAILURE, __FILE__, __LINE__)
 
+#define P_CURVE_IMPL(curve, nid)                                               \
+       isc_result_t isc_ossl_wrap_generate_##curve##_key(EVP_PKEY **pkeyp) {  \
+               REQUIRE(pkeyp != NULL && *pkeyp == NULL);                      \
+               return generate_ec_key(pkeyp, nid);                            \
+       }                                                                      \
+       isc_result_t isc_ossl_wrap_generate_pkcs11_##curve##_key(              \
+               char *uri, EVP_PKEY **pkeyp) {                                 \
+               UNUSED(uri);                                                   \
+               return isc_ossl_wrap_generate_##curve##_key(pkeyp);            \
+       }                                                                      \
+       isc_result_t isc_ossl_wrap_validate_##curve##_pkey(EVP_PKEY *pkey) {   \
+               REQUIRE(pkey != NULL);                                         \
+               return validate_ec_pkey(pkey, nid);                            \
+       }                                                                      \
+       isc_result_t isc_ossl_wrap_load_##curve##_public_from_region(          \
+               isc_region_t region, EVP_PKEY **pkeyp) {                       \
+               REQUIRE(pkeyp != NULL && *pkeyp == NULL);                      \
+               REQUIRE(region.base != NULL &&                                 \
+                       region.length >= curve##_public_key_size);             \
+               region.length = curve##_public_key_size;                       \
+               return load_ec_public_from_region(region, pkeyp, nid);         \
+       }                                                                      \
+       isc_result_t isc_ossl_wrap_load_##curve##_secret_from_region(          \
+               isc_region_t region, EVP_PKEY **pkeyp) {                       \
+               REQUIRE(pkeyp != NULL && *pkeyp == NULL);                      \
+               REQUIRE(region.base != NULL &&                                 \
+                       region.length >= curve##_secret_key_size);             \
+               region.length = curve##_secret_key_size;                       \
+               return load_ec_secret_from_region(region, pkeyp, nid);         \
+       }                                                                      \
+       isc_result_t isc_ossl_wrap_##curve##_public_region(EVP_PKEY *pkey,     \
+                                                          isc_region_t pub) { \
+               REQUIRE(pkey != NULL);                                         \
+               REQUIRE(pub.base != NULL &&                                    \
+                       pub.length >= curve##_public_key_size);                \
+               pub.length = curve##_public_key_size;                          \
+               return ec_public_region(pkey, pub);                            \
+       }                                                                      \
+       isc_result_t isc_ossl_wrap_##curve##_secret_region(EVP_PKEY *pkey,     \
+                                                          isc_region_t sec) { \
+               REQUIRE(pkey != NULL);                                         \
+               REQUIRE(sec.base != NULL &&                                    \
+                       sec.length >= curve##_secret_key_size);                \
+               sec.length = curve##_secret_key_size;                          \
+               return ec_secret_region(pkey, sec);                            \
+       }
+
+constexpr size_t p256_public_key_size = 64;
+constexpr size_t p384_public_key_size = 96;
+
+constexpr size_t p256_secret_key_size = 32;
+constexpr size_t p384_secret_key_size = 48;
+
+static int
+BN_bn2bin_fixed(const BIGNUM *bn, unsigned char *buf, int size) {
+       int bytes = size - BN_num_bytes(bn);
+
+       INSIST(bytes >= 0);
+
+       while (bytes-- > 0) {
+               *buf++ = 0;
+       }
+       BN_bn2bin(bn, buf);
+       return size;
+}
+
 static int
 rsa_keygen_progress_cb(int p, int n, BN_GENCB *cb) {
        void (*fptr)(int);
@@ -36,6 +107,251 @@ rsa_keygen_progress_cb(int p, int n, BN_GENCB *cb) {
        return 1;
 }
 
+static isc_result_t
+generate_ec_key(EVP_PKEY **pkeyp, const int nid) {
+       isc_result_t result;
+       EC_KEY *eckey = NULL;
+       EVP_PKEY *pkey = NULL;
+
+       eckey = EC_KEY_new_by_curve_name(nid);
+       if (eckey == NULL) {
+               CLEANUP(OSSL_WRAP_ERROR("EC_KEY_new_by_curve_name"));
+       }
+
+       if (EC_KEY_generate_key(eckey) != 1) {
+               CLEANUP(OSSL_WRAP_ERROR("EC_KEY_generate_key"));
+       }
+
+       pkey = EVP_PKEY_new();
+       if (pkey == NULL) {
+               CLEANUP(OSSL_WRAP_ERROR("EVP_PKEY_new"));
+       }
+
+       if (EVP_PKEY_set1_EC_KEY(pkey, eckey) != 1) {
+               CLEANUP(OSSL_WRAP_ERROR("EVP_PKEY_set1_EC_KEY"));
+       }
+
+       *pkeyp = pkey;
+       pkey = NULL;
+       result = ISC_R_SUCCESS;
+
+cleanup:
+       EC_KEY_free(eckey);
+       EVP_PKEY_free(pkey);
+       return result;
+}
+
+static isc_result_t
+validate_ec_pkey(EVP_PKEY *pkey, const int nid) {
+       const EC_GROUP *group;
+       const EC_KEY *eckey;
+       isc_result_t result;
+
+       eckey = EVP_PKEY_get0_EC_KEY(pkey);
+       if (eckey == NULL) {
+               CLEANUP(OSSL_WRAP_ERROR("EVP_PKEY_get0_EC_KEY"));
+       }
+
+       group = EC_KEY_get0_group(eckey);
+       if (group == NULL) {
+               CLEANUP(OSSL_WRAP_ERROR("EC_KEY_get0_group"));
+       }
+
+       if (EC_GROUP_get_curve_name(group) != nid) {
+               return DST_R_INVALIDPRIVATEKEY;
+       }
+
+       result = ISC_R_SUCCESS;
+cleanup:
+       return result;
+}
+
+static isc_result_t
+load_ec_public_from_region(isc_region_t region, EVP_PKEY **pkeyp,
+                          const int nid) {
+       isc_result_t result;
+       const unsigned char *buf_launder;
+       uint8_t buffer[MAX_PUBLIC_KEY_SIZE + 1];
+       EC_KEY *eckey = NULL;
+       EVP_PKEY *pkey = NULL;
+
+       eckey = EC_KEY_new_by_curve_name(nid);
+       if (eckey == NULL) {
+               CLEANUP(OSSL_WRAP_ERROR("EC_KEY_new_curve_by_name"));
+       }
+
+       buffer[0] = POINT_CONVERSION_UNCOMPRESSED;
+       memmove(buffer + 1, region.base, region.length);
+
+       buf_launder = buffer;
+       if (o2i_ECPublicKey(&eckey, &buf_launder, region.length + 1) == NULL) {
+               CLEANUP(OSSL_WRAP_ERROR("o2i_ECPublicKey"));
+       }
+
+       if (EC_KEY_check_key(eckey) != 1) {
+               CLEANUP(OSSL_WRAP_ERROR("EC_KEY_check_key"));
+       }
+
+       pkey = EVP_PKEY_new();
+       if (pkey == NULL) {
+               CLEANUP(OSSL_WRAP_ERROR("EVP_PKEY_new"));
+       }
+
+       if (EVP_PKEY_set1_EC_KEY(pkey, eckey) != 1) {
+               CLEANUP(OSSL_WRAP_ERROR("EVP_PKEY_set1_EC_KEY"));
+       }
+
+       *pkeyp = pkey;
+       pkey = NULL;
+       result = ISC_R_SUCCESS;
+
+cleanup:
+       EVP_PKEY_free(pkey);
+       EC_KEY_free(eckey);
+       return result;
+}
+
+static isc_result_t
+load_ec_secret_from_region(isc_region_t region, EVP_PKEY **pkeyp,
+                          const int nid) {
+       isc_result_t result;
+       const EC_GROUP *group = NULL;
+       EC_POINT *public = NULL;
+       EVP_PKEY *pkey = NULL;
+       BIGNUM *private = NULL;
+       EC_KEY *eckey = NULL;
+
+       eckey = EC_KEY_new_by_curve_name(nid);
+       if (eckey == NULL) {
+               CLEANUP(OSSL_WRAP_ERROR("EC_KEY_new_curve_by_name"));
+       }
+
+       group = EC_KEY_get0_group(eckey);
+       if (group == NULL) {
+               CLEANUP(OSSL_WRAP_ERROR("EC_KEY_get0_group"));
+       }
+
+       private = BN_bin2bn(region.base, region.length, NULL);
+       if (private == NULL) {
+               CLEANUP(OSSL_WRAP_ERROR("BN_bin2bn"));
+       }
+
+       if (EC_KEY_set_private_key(eckey, private) != 1) {
+               CLEANUP(OSSL_WRAP_ERROR("EC_KEY_set_private_key"));
+       }
+
+       /*
+        * OpenSSL requires us to set the public key portion, but since our
+        * private key file format does not contain it directly, we generate it
+        * as needed.
+        */
+       public = EC_POINT_new(group);
+       if (public == NULL) {
+               CLEANUP(OSSL_WRAP_ERROR("EC_POINT_new"));
+       }
+
+       if (EC_POINT_mul(group, public, private, NULL, NULL, NULL) != 1) {
+               CLEANUP(OSSL_WRAP_ERROR("EC_POINT_mul"));
+       }
+
+       if (EC_KEY_set_public_key(eckey, public) != 1) {
+               CLEANUP(OSSL_WRAP_ERROR("EC_KEY_set_public_key"));
+       }
+
+       pkey = EVP_PKEY_new();
+       if (pkey == NULL) {
+               CLEANUP(OSSL_WRAP_ERROR("EVP_PKEY_new"));
+       }
+
+       if (EVP_PKEY_set1_EC_KEY(pkey, eckey) != 1) {
+               CLEANUP(OSSL_WRAP_ERROR("EVP_PKEY_set1_EC_KEY"));
+       }
+
+       *pkeyp = pkey;
+       pkey = NULL;
+       result = ISC_R_SUCCESS;
+
+cleanup:
+       EVP_PKEY_free(pkey);
+       EC_POINT_free(public);
+       BN_clear_free(private);
+       EC_KEY_free(eckey);
+       return result;
+}
+
+static isc_result_t
+ec_public_region(EVP_PKEY *pkey, isc_region_t pub) {
+       isc_result_t result;
+       uint8_t buffer[MAX_PUBLIC_KEY_SIZE + 1];
+       const EC_POINT *public;
+       const EC_GROUP *group;
+       const EC_KEY *eckey;
+       size_t len;
+
+       eckey = EVP_PKEY_get0_EC_KEY(pkey);
+       if (eckey == NULL) {
+               CLEANUP(OSSL_WRAP_ERROR("EVP_PKEY_get0_EC_KEY"));
+       }
+
+       group = EC_KEY_get0_group(eckey);
+       if (group == NULL) {
+               CLEANUP(OSSL_WRAP_ERROR("EC_KEY_get0_group"));
+       }
+
+       public = EC_KEY_get0_public_key(eckey);
+       if (public == NULL) {
+               CLEANUP(OSSL_WRAP_ERROR("EC_KEY_get0_public_key"));
+       }
+
+       len = EC_POINT_point2oct(group, public, POINT_CONVERSION_UNCOMPRESSED,
+                                buffer, sizeof(buffer), NULL);
+       if (len != pub.length + 1) {
+               CLEANUP(OSSL_WRAP_ERROR("EC_POINT_point2oct"));
+       }
+
+       memmove(pub.base, buffer + 1, pub.length);
+
+       result = ISC_R_SUCCESS;
+
+cleanup:
+       return result;
+}
+
+static isc_result_t
+ec_secret_region(EVP_PKEY *pkey, isc_region_t pub) {
+       const BIGNUM *private;
+       isc_result_t result;
+       const EC_KEY *eckey;
+
+       eckey = EVP_PKEY_get0_EC_KEY(pkey);
+       if (eckey == NULL) {
+               CLEANUP(OSSL_WRAP_ERROR("EVP_PKEY_get0_EC_KEY"));
+       }
+
+       private = EC_KEY_get0_private_key(eckey);
+       if (private == NULL) {
+               CLEANUP(OSSL_WRAP_ERROR("EC_KEY_get0_private_key"));
+       }
+
+       BN_bn2bin_fixed(private, pub.base, pub.length);
+
+       result = ISC_R_SUCCESS;
+
+cleanup:
+       return result;
+}
+
+P_CURVE_IMPL(p256, NID_X9_62_prime256v1);
+P_CURVE_IMPL(p384, NID_secp384r1);
+
+isc_result_t
+isc_ossl_wrap_ecdsa_set_deterministic(EVP_PKEY_CTX *pctx, const char *hash) {
+       UNUSED(pctx);
+       UNUSED(hash);
+
+       return ISC_R_NOTIMPLEMENTED;
+}
+
 isc_result_t
 isc_ossl_wrap_generate_rsa_key(void (*callback)(int), size_t bit_size,
                               EVP_PKEY **pkeyp) {
index d18beb3e19863afac245ceb0c6ee93b5bd3f6b2f..0bd116f38161280f9e7594aa58563ad70f22654c 100644 (file)
 
 #include <openssl/bn.h>
 #include <openssl/core_names.h>
+#include <openssl/ec.h>
 #include <openssl/err.h>
 #include <openssl/evp.h>
 #include <openssl/param_build.h>
 #include <openssl/rsa.h>
 
 #include <isc/ossl_wrap.h>
+#include <isc/region.h>
 #include <isc/util.h>
 
+#define MAX_PUBLIC_KEY_SIZE 96
+#define MAX_SECRET_KEY_SIZE 48
+
 #define OSSL_WRAP_ERROR(fn)                                        \
        isc__ossl_wrap_logged_toresult(                            \
                ISC_LOGCATEGORY_GENERAL, ISC_LOGMODULE_CRYPTO, fn, \
                ISC_R_CRYPTOFAILURE, __FILE__, __LINE__)
 
+#define P_CURVE_IMPL(curve, nid)                                               \
+       isc_result_t isc_ossl_wrap_generate_##curve##_key(EVP_PKEY **pkeyp) {  \
+               REQUIRE(pkeyp != NULL && *pkeyp == NULL);                      \
+               return generate_ec_key(pkeyp, nid);                            \
+       }                                                                      \
+       isc_result_t isc_ossl_wrap_generate_pkcs11_##curve##_key(              \
+               char *uri, EVP_PKEY **pkeyp) {                                 \
+               REQUIRE(pkeyp != NULL && *pkeyp == NULL);                      \
+               REQUIRE(uri != NULL);                                          \
+               return generate_pkcs11_ec_key(uri, pkeyp, nid);                \
+       }                                                                      \
+       isc_result_t isc_ossl_wrap_validate_##curve##_pkey(EVP_PKEY *pkey) {   \
+               REQUIRE(pkey != NULL);                                         \
+               return validate_ec_pkey(pkey, curve##_group_name);             \
+       }                                                                      \
+       isc_result_t isc_ossl_wrap_load_##curve##_public_from_region(          \
+               isc_region_t region, EVP_PKEY **pkeyp) {                       \
+               REQUIRE(region.base != NULL &&                                 \
+                       region.length <= MAX_PUBLIC_KEY_SIZE);                 \
+               REQUIRE(pkeyp != NULL && *pkeyp == NULL);                      \
+               region.length = curve##_public_key_size;                       \
+               return load_ec_public_from_region(region, pkeyp,               \
+                                                 curve##_group_name);         \
+       }                                                                      \
+       isc_result_t isc_ossl_wrap_load_##curve##_secret_from_region(          \
+               isc_region_t region, EVP_PKEY **pkeyp) {                       \
+               REQUIRE(pkeyp != NULL && *pkeyp == NULL);                      \
+               REQUIRE(region.base != NULL &&                                 \
+                       region.length >= curve##_secret_key_size);             \
+               region.length = curve##_secret_key_size;                       \
+               return load_ec_secret_from_region(region, pkeyp,               \
+                                                 curve##_group_name, nid);    \
+       }                                                                      \
+       isc_result_t isc_ossl_wrap_##curve##_public_region(EVP_PKEY *pkey,     \
+                                                          isc_region_t pub) { \
+               REQUIRE(pkey != NULL);                                         \
+               REQUIRE(pub.base != NULL &&                                    \
+                       pub.length >= curve##_public_key_size);                \
+               pub.length = curve##_public_key_size;                          \
+               return ec_public_region(pkey, pub);                            \
+       }                                                                      \
+       isc_result_t isc_ossl_wrap_##curve##_secret_region(EVP_PKEY *pkey,     \
+                                                          isc_region_t sec) { \
+               REQUIRE(pkey != NULL);                                         \
+               REQUIRE(sec.base != NULL &&                                    \
+                       sec.length >= curve##_secret_key_size);                \
+               sec.length = curve##_secret_key_size;                          \
+               return ec_secret_region(pkey, sec);                            \
+       }
+
+static char pkcs11_key_usage[] = "digitalSignature";
+
+constexpr char *p256_group_name = "prime256v1";
+constexpr char *p384_group_name = "secp384r1";
+
+constexpr size_t p256_public_key_size = 64;
+constexpr size_t p384_public_key_size = 96;
+
+constexpr size_t p256_secret_key_size = 32;
+constexpr size_t p384_secret_key_size = 48;
+
+static void
+BN_bn2bin_fixed(const BIGNUM *bn, unsigned char *buf, int size) {
+       int bytes = size - BN_num_bytes(bn);
+
+       INSIST(bytes >= 0);
+
+       while (bytes-- > 0) {
+               *buf++ = 0;
+       }
+       BN_bn2bin(bn, buf);
+}
+
 static int
 rsa_keygen_progress_cb(EVP_PKEY_CTX *ctx) {
        void (*fptr)(int);
@@ -40,6 +118,346 @@ rsa_keygen_progress_cb(EVP_PKEY_CTX *ctx) {
        return 1;
 }
 
+static isc_result_t
+generate_ec_key(EVP_PKEY **pkeyp, const int nid) {
+       isc_result_t result;
+       EVP_PKEY_CTX *pctx = NULL;
+       EVP_PKEY *params_pkey = NULL;
+
+       /* Generate the key's parameters. */
+       pctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL);
+       if (pctx == NULL) {
+               CLEANUP(OSSL_WRAP_ERROR("EVP_PKEY_CTX_new_from_name"));
+       }
+
+       if (EVP_PKEY_paramgen_init(pctx) != 1) {
+               CLEANUP(OSSL_WRAP_ERROR("EVP_PKEY_paramgen_init"));
+       }
+
+       if (EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, nid) != 1) {
+               CLEANUP(OSSL_WRAP_ERROR("EVP_PKEY_CTX_set_ec_paramgen_curve_"
+                                     "nid"));
+       }
+
+       if (EVP_PKEY_paramgen(pctx, &params_pkey) != 1) {
+               CLEANUP(OSSL_WRAP_ERROR("EVP_PKEY_paramgen"));
+       }
+
+       if (params_pkey == NULL) {
+               CLEANUP(OSSL_WRAP_ERROR("EVP_PKEY_paramgen"));
+       }
+
+       EVP_PKEY_CTX_free(pctx);
+
+       /* Generate the key. */
+       pctx = EVP_PKEY_CTX_new(params_pkey, NULL);
+       if (pctx == NULL) {
+               CLEANUP(OSSL_WRAP_ERROR("EVP_PKEY_CTX_new"));
+       }
+
+       if (EVP_PKEY_keygen_init(pctx) != 1) {
+               CLEANUP(OSSL_WRAP_ERROR("EVP_PKEY_keygen_init"));
+       }
+
+       if (EVP_PKEY_keygen(pctx, pkeyp) != 1) {
+               CLEANUP(OSSL_WRAP_ERROR("EVP_PKEY_keygen"));
+       }
+
+       result = ISC_R_SUCCESS;
+
+cleanup:
+       EVP_PKEY_CTX_free(pctx);
+       EVP_PKEY_free(params_pkey);
+       return result;
+}
+
+static isc_result_t
+generate_pkcs11_ec_key(char *uri, EVP_PKEY **pkeyp, int nid) {
+       isc_result_t result;
+       EVP_PKEY_CTX *pctx;
+       OSSL_PARAM params[3];
+
+       params[0] = OSSL_PARAM_construct_utf8_string("pkcs11_uri", uri, 0);
+       params[1] = OSSL_PARAM_construct_utf8_string(
+               "pkcs11_key_usage", pkcs11_key_usage,
+               sizeof(pkcs11_key_usage) - 1);
+       params[2] = OSSL_PARAM_construct_end();
+
+       pctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", "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"));
+       }
+
+       /*
+        * Setting the P-384 curve doesn't work correctly when using:
+        * OSSL_PARAM_construct_utf8_string("ec_paramgen_curve", "P-384", 0);
+        *
+        * Instead use the OpenSSL function to set the curve nid param.
+        */
+       if (EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, nid) != 1) {
+               CLEANUP(OSSL_WRAP_ERROR("EVP_PKEY_CTX_set_ec_paramgen_curve_"
+                                       "nid"));
+       }
+
+       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;
+}
+
+static isc_result_t
+validate_ec_pkey(EVP_PKEY *pkey, const char *expected) {
+       isc_result_t result;
+       char actual[64];
+
+       if (EVP_PKEY_get_group_name(pkey, actual, sizeof(actual), NULL) != 1) {
+               CLEANUP(OSSL_WRAP_ERROR("EVP_PKEY_get_group_name"));
+       }
+
+       if (strcmp(expected, actual) != 0) {
+               return ISC_R_FAILURE;
+       }
+
+       result = ISC_R_SUCCESS;
+
+cleanup:
+       return result;
+}
+
+static isc_result_t
+load_ec_public_from_region(isc_region_t region, EVP_PKEY **pkeyp,
+                          const char *group_name) {
+       isc_result_t result;
+       OSSL_PARAM_BLD *bld = NULL;
+       OSSL_PARAM *params = NULL;
+       EVP_PKEY_CTX *pctx = NULL;
+       uint8_t buffer[MAX_PUBLIC_KEY_SIZE + 1];
+
+       buffer[0] = POINT_CONVERSION_UNCOMPRESSED;
+       memmove(buffer + 1, region.base, region.length);
+
+       bld = OSSL_PARAM_BLD_new();
+       if (bld == NULL) {
+               CLEANUP(OSSL_WRAP_ERROR("OSSL_PARAM_BLD_new"));
+       }
+
+       if (OSSL_PARAM_BLD_push_utf8_string(bld, OSSL_PKEY_PARAM_GROUP_NAME,
+                                           group_name, 0) != 1)
+       {
+               CLEANUP(OSSL_WRAP_ERROR("OSSL_PARAM_BLD_push_utf8_string"));
+       }
+
+       if (OSSL_PARAM_BLD_push_octet_string(bld, OSSL_PKEY_PARAM_PUB_KEY,
+                                            buffer, region.length + 1) != 1)
+       {
+               CLEANUP(OSSL_WRAP_ERROR("OSSL_PARAM_BLD_push_octet_string"));
+       }
+
+       params = OSSL_PARAM_BLD_to_param(bld);
+       if (params == NULL) {
+               CLEANUP(OSSL_WRAP_ERROR("OSSL_PARAM_BLD_to_param"));
+       }
+
+       pctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL);
+       if (pctx == NULL) {
+               CLEANUP(OSSL_WRAP_ERROR("EVP_PKEY_CTX_new_from_name"));
+       }
+
+       if (EVP_PKEY_fromdata_init(pctx) != 1) {
+               CLEANUP(OSSL_WRAP_ERROR("EVP_PKEY_fromdata_init"));
+       }
+
+       if (EVP_PKEY_fromdata(pctx, pkeyp, EVP_PKEY_PUBLIC_KEY, params) != 1) {
+               CLEANUP(OSSL_WRAP_ERROR("EVP_PKEY_fromdata"));
+       }
+
+       result = ISC_R_SUCCESS;
+
+cleanup:
+       OSSL_PARAM_free(params);
+       OSSL_PARAM_BLD_free(bld);
+       EVP_PKEY_CTX_free(pctx);
+       return result;
+}
+
+static isc_result_t
+load_ec_secret_from_region(isc_region_t region, EVP_PKEY **pkeyp,
+                          const char *group_name, const int nid) {
+       uint8_t public[MAX_PUBLIC_KEY_SIZE + 1];
+       EVP_PKEY_CTX *pctx = NULL;
+       OSSL_PARAM_BLD *bld = NULL;
+       OSSL_PARAM *params = NULL;
+       EC_POINT *pub_point = NULL;
+       EC_GROUP *group = NULL;
+       BIGNUM *private = NULL;
+       isc_result_t result;
+       size_t public_len;
+
+       /*
+        * OpenSSL requires us to set the public key portion, but since our
+        * private key file format does not contain it directly, we generate it
+        * as needed.
+        */
+       group = EC_GROUP_new_by_curve_name(nid);
+       if (group == NULL) {
+               CLEANUP(OSSL_WRAP_ERROR("EC_GROUP_new_by_curve_name"));
+       }
+
+       private = BN_bin2bn(region.base, region.length, NULL);
+       if (private == NULL) {
+               CLEANUP(OSSL_WRAP_ERROR("BN_bin2bn"));
+       }
+
+       pub_point = EC_POINT_new(group);
+       if (pub_point == NULL) {
+               CLEANUP(OSSL_WRAP_ERROR("EC_POINT_new"));
+       }
+
+       if (EC_POINT_mul(group, pub_point, private, NULL, NULL, NULL) != 1) {
+               CLEANUP(OSSL_WRAP_ERROR("EC_POINT_mul"));
+       }
+
+       public_len = EC_POINT_point2oct(group, pub_point,
+                                       POINT_CONVERSION_UNCOMPRESSED, public,
+                                       sizeof(public), NULL);
+       if (public_len == 0) {
+               CLEANUP(OSSL_WRAP_ERROR("EC_POINT_point2oct"));
+       }
+
+       bld = OSSL_PARAM_BLD_new();
+       if (bld == NULL) {
+               CLEANUP(OSSL_WRAP_ERROR("OSSL_PARAM_BLD_new"));
+       }
+
+       if (OSSL_PARAM_BLD_push_utf8_string(bld, OSSL_PKEY_PARAM_GROUP_NAME,
+                                           group_name, 0) != 1)
+       {
+               CLEANUP(OSSL_WRAP_ERROR("OSSL_PARAM_BLD_push_utf8_string"));
+       }
+
+       if (OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_PRIV_KEY, private) != 1)
+       {
+               CLEANUP(OSSL_WRAP_ERROR("OSSL_PARAM_BLD_push_BN"));
+       }
+
+       if (OSSL_PARAM_BLD_push_octet_string(bld, OSSL_PKEY_PARAM_PUB_KEY,
+                                            public, public_len) != 1)
+       {
+               CLEANUP(OSSL_WRAP_ERROR("OSSL_PARAM_BLD_push_octet_string"));
+       }
+
+       params = OSSL_PARAM_BLD_to_param(bld);
+       if (params == NULL) {
+               CLEANUP(OSSL_WRAP_ERROR("OSSL_PARAM_BLD_to_param"));
+       }
+
+       pctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL);
+       if (pctx == NULL) {
+               CLEANUP(OSSL_WRAP_ERROR("EVP_PKEY_CTX_new_from_name"));
+       }
+
+       if (EVP_PKEY_fromdata_init(pctx) != 1) {
+               CLEANUP(OSSL_WRAP_ERROR("EVP_PKEY_fromdata_init"));
+       }
+
+       if (EVP_PKEY_fromdata(pctx, pkeyp, EVP_PKEY_KEYPAIR, params) != 1) {
+               CLEANUP(OSSL_WRAP_ERROR("EVP_PKEY_fromdata"));
+       }
+
+       result = ISC_R_SUCCESS;
+
+cleanup:
+       OSSL_PARAM_free(params);
+       OSSL_PARAM_BLD_free(bld);
+       EC_POINT_free(pub_point);
+       BN_clear_free(private);
+       EC_GROUP_free(group);
+       EVP_PKEY_CTX_free(pctx);
+       return result;
+}
+
+static isc_result_t
+ec_public_region(EVP_PKEY *pkey, isc_region_t pub) {
+       isc_result_t result;
+       BIGNUM *x = NULL;
+       BIGNUM *y = NULL;
+
+       if (EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_EC_PUB_X, &x) != 1) {
+               CLEANUP(OSSL_WRAP_ERROR("EVP_PKEY_get_bn_param"));
+       }
+
+       if (EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_EC_PUB_Y, &y) != 1) {
+               CLEANUP(OSSL_WRAP_ERROR("EVP_PKEY_get_bn_param"));
+       }
+
+       BN_bn2bin_fixed(x, &pub.base[0], pub.length / 2);
+       BN_bn2bin_fixed(y, &pub.base[pub.length / 2], pub.length / 2);
+
+       result = ISC_R_SUCCESS;
+
+cleanup:
+       BN_clear_free(x);
+       BN_clear_free(y);
+       return result;
+}
+
+static isc_result_t
+ec_secret_region(EVP_PKEY *pkey, isc_region_t sec) {
+       isc_result_t result;
+       BIGNUM *priv = NULL;
+
+       if (EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_PRIV_KEY, &priv) != 1) {
+               CLEANUP(OSSL_WRAP_ERROR("EVP_PKEY_get_bn_param"));
+       }
+
+       BN_bn2bin_fixed(priv, sec.base, sec.length);
+
+       result = ISC_R_SUCCESS;
+
+cleanup:
+       BN_clear_free(priv);
+       return result;
+}
+
+P_CURVE_IMPL(p256, NID_X9_62_prime256v1);
+P_CURVE_IMPL(p384, NID_secp384r1);
+
+isc_result_t
+isc_ossl_wrap_ecdsa_set_deterministic(EVP_PKEY_CTX *pctx, const char *hash) {
+       unsigned int rfc6979 = 1;
+       isc_result_t result;
+       OSSL_PARAM params[3];
+
+       REQUIRE(pctx != NULL && hash != NULL);
+
+       params[0] = OSSL_PARAM_construct_utf8_string("digest", UNCONST(hash),
+                                                    0);
+       params[1] = OSSL_PARAM_construct_uint("nonce-type", &rfc6979);
+       params[2] = OSSL_PARAM_construct_end();
+
+       if (EVP_PKEY_CTX_set_params(pctx, params) != 1) {
+               CLEANUP(OSSL_WRAP_ERROR("EVP_PKEY_CTX_set_params"));
+       }
+
+       result = ISC_R_SUCCESS;
+
+cleanup:
+       return result;
+}
+
 isc_result_t
 isc_ossl_wrap_generate_rsa_key(void (*callback)(int), size_t bit_size,
                               EVP_PKEY **pkeyp) {