]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
remove libcrypto version specific code in opensslrsa_link
authorAydın Mercan <aydin@isc.org>
Mon, 1 Dec 2025 13:23:37 +0000 (16:23 +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/opensslrsa_link.c
lib/isc/include/isc/ossl_wrap.h
lib/isc/ossl_wrap/ossl1_1.c
lib/isc/ossl_wrap/ossl3.c
lib/isc/ossl_wrap/ossl_common.c

index bc79ae010020f4a61ca390e55b1cbbceec37f49c..ec24bf202da729cec36c1e162b70be39de5f29ca 100644 (file)
 #include <openssl/bn.h>
 #include <openssl/err.h>
 #include <openssl/objects.h>
-#include <openssl/opensslv.h>
 #include <openssl/rsa.h>
-#if OPENSSL_VERSION_NUMBER >= 0x30000000L
-#include <openssl/core_names.h>
-#include <openssl/param_build.h>
-#endif
 
 #include <isc/mem.h>
+#include <isc/ossl_wrap.h>
 #include <isc/result.h>
 #include <isc/safe.h>
 #include <isc/string.h>
 /* TODO(aydin): remove this crap */
 extern EVP_MD *isc__crypto_md[];
 
-typedef struct rsa_components {
-       bool bnfree;
-       const BIGNUM *e, *n, *d, *p, *q, *dmp1, *dmq1, *iqmp;
-} rsa_components_t;
-
 /* length byte + 1.2.840.113549.1.1.11 BER encoded RFC 4055 */
 static unsigned char oid_rsasha256[] = { 0x0b, 0x06, 0x09, 0x2a, 0x86, 0x48,
                                         0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b };
@@ -55,103 +46,6 @@ static unsigned char oid_rsasha256[] = { 0x0b, 0x06, 0x09, 0x2a, 0x86, 0x48,
 static unsigned char oid_rsasha512[] = { 0x0b, 0x06, 0x09, 0x2a, 0x86, 0x48,
                                         0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0d };
 
-static isc_result_t
-opensslrsa_components_get(const dst_key_t *key, rsa_components_t *c,
-                         bool private) {
-       REQUIRE(c->e == NULL && c->n == NULL && c->d == NULL && c->p == NULL &&
-               c->q == NULL && c->dmp1 == NULL && c->dmq1 == NULL &&
-               c->iqmp == NULL);
-
-       EVP_PKEY *pub = key->keydata.pkeypair.pub;
-       EVP_PKEY *priv = key->keydata.pkeypair.priv;
-
-       if (private && priv == NULL) {
-               return DST_R_INVALIDPRIVATEKEY;
-       }
-       /*
-        * NOTE: Errors regarding private compoments are ignored.
-        *
-        * OpenSSL allows omitting the parameters for CRT based calculations
-        * (factors, exponents, coefficients). Only the 'd'  parameter is
-        * mandatory for software keys.
-        *
-        * However, for a label based keys, all private key component queries
-        * can fail if they key is e.g. on a hardware device.
-        */
-#if OPENSSL_VERSION_NUMBER >= 0x30000000L
-       if (EVP_PKEY_get_bn_param(pub, OSSL_PKEY_PARAM_RSA_E,
-                                 (BIGNUM **)&c->e) != 1)
-       {
-               return dst__openssl_toresult(DST_R_OPENSSLFAILURE);
-       }
-
-       c->bnfree = true;
-       if (EVP_PKEY_get_bn_param(pub, OSSL_PKEY_PARAM_RSA_N,
-                                 (BIGNUM **)&c->n) != 1)
-       {
-               return dst__openssl_toresult(DST_R_OPENSSLFAILURE);
-       }
-       if (!private) {
-               return ISC_R_SUCCESS;
-       }
-       (void)EVP_PKEY_get_bn_param(priv, OSSL_PKEY_PARAM_RSA_D,
-                                   (BIGNUM **)&c->d);
-       (void)EVP_PKEY_get_bn_param(priv, OSSL_PKEY_PARAM_RSA_FACTOR1,
-                                   (BIGNUM **)&c->p);
-       (void)EVP_PKEY_get_bn_param(priv, OSSL_PKEY_PARAM_RSA_FACTOR2,
-                                   (BIGNUM **)&c->q);
-       (void)EVP_PKEY_get_bn_param(priv, OSSL_PKEY_PARAM_RSA_EXPONENT1,
-                                   (BIGNUM **)&c->dmp1);
-       (void)EVP_PKEY_get_bn_param(priv, OSSL_PKEY_PARAM_RSA_EXPONENT2,
-                                   (BIGNUM **)&c->dmq1);
-       (void)EVP_PKEY_get_bn_param(priv, OSSL_PKEY_PARAM_RSA_COEFFICIENT1,
-                                   (BIGNUM **)&c->iqmp);
-       ERR_clear_error();
-       return ISC_R_SUCCESS;
-#else
-       const RSA *rsa = EVP_PKEY_get0_RSA(pub);
-       if (rsa == NULL) {
-               return dst__openssl_toresult(DST_R_OPENSSLFAILURE);
-       }
-       RSA_get0_key(rsa, &c->n, &c->e, &c->d);
-       if (c->e == NULL || c->n == NULL) {
-               return dst__openssl_toresult(DST_R_OPENSSLFAILURE);
-       }
-       if (!private) {
-               return ISC_R_SUCCESS;
-       }
-       rsa = EVP_PKEY_get0_RSA(priv);
-       if (rsa == NULL) {
-               return dst__openssl_toresult(DST_R_OPENSSLFAILURE);
-       }
-       RSA_get0_factors(rsa, &c->p, &c->q);
-       RSA_get0_crt_params(rsa, &c->dmp1, &c->dmq1, &c->iqmp);
-       return ISC_R_SUCCESS;
-#endif
-}
-
-static void
-opensslrsa_components_free(rsa_components_t *c) {
-       if (!c->bnfree) {
-               return;
-       }
-       /*
-        * NOTE: BN_free() frees the components of the BIGNUM, and if it was
-        * created by BN_new(), also the structure itself. BN_clear_free()
-        * additionally overwrites the data before the memory is returned to the
-        * system. If a is NULL, nothing is done.
-        */
-       BN_free((BIGNUM *)c->e);
-       BN_free((BIGNUM *)c->n);
-       BN_clear_free((BIGNUM *)c->d);
-       BN_clear_free((BIGNUM *)c->p);
-       BN_clear_free((BIGNUM *)c->q);
-       BN_clear_free((BIGNUM *)c->dmp1);
-       BN_clear_free((BIGNUM *)c->dmq1);
-       BN_clear_free((BIGNUM *)c->iqmp);
-       c->bnfree = false;
-}
-
 static bool
 opensslrsa_valid_key_alg(unsigned int key_alg) {
        switch (key_alg) {
@@ -325,29 +219,6 @@ opensslrsa_sign(dst_context_t *dctx, isc_buffer_t *sig) {
        return ISC_R_SUCCESS;
 }
 
-static bool
-opensslrsa_check_exponent_bits(EVP_PKEY *pkey, int maxbits) {
-       /* Always use the new API first with OpenSSL 3.x. */
-       int bits = INT_MAX;
-#if OPENSSL_VERSION_NUMBER >= 0x30000000L
-       BIGNUM *e = NULL;
-       if (EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_RSA_E, &e) == 1) {
-               bits = BN_num_bits(e);
-               BN_free(e);
-       }
-#else
-       const RSA *rsa = EVP_PKEY_get0_RSA(pkey);
-       if (rsa != NULL) {
-               const BIGNUM *ce = NULL;
-               RSA_get0_key(rsa, NULL, &ce, NULL);
-               if (ce != NULL) {
-                       bits = BN_num_bits(ce);
-               }
-       }
-#endif
-       return bits <= maxbits;
-}
-
 static isc_result_t
 opensslrsa_verify(dst_context_t *dctx, const isc_region_t *sig) {
        dst_key_t *key = NULL;
@@ -364,7 +235,7 @@ opensslrsa_verify(dst_context_t *dctx, const isc_region_t *sig) {
        evp_md_ctx = dctx->ctxdata.evp_md_ctx;
        pkey = key->keydata.pkeypair.pub;
 
-       if (!opensslrsa_check_exponent_bits(pkey, OPENSSLRSA_MAX_MODULUS_BITS))
+       if (!isc_ossl_wrap_rsa_key_bits_leq(pkey, OPENSSLRSA_MAX_MODULUS_BITS))
        {
                return DST_R_VERIFYFAILURE;
        }
@@ -405,344 +276,13 @@ opensslrsa_verify(dst_context_t *dctx, const isc_region_t *sig) {
        }
 }
 
-#if OPENSSL_VERSION_NUMBER < 0x30000000L
-static int
-progress_cb(int p, int n, BN_GENCB *cb) {
-       void (*fptr)(int);
-
-       UNUSED(n);
-
-       fptr = BN_GENCB_get_arg(cb);
-       if (fptr != NULL) {
-               fptr(p);
-       }
-       return 1;
-}
-
-static isc_result_t
-opensslrsa_generate_pkey(unsigned int key_size, const char *label, BIGNUM *e,
-                        void (*callback)(int), EVP_PKEY **retkey) {
-       RSA *rsa = NULL;
-       EVP_PKEY *pkey = NULL;
-       BN_GENCB *cb = NULL;
-       isc_result_t result;
-
-       UNUSED(label);
-
-       rsa = RSA_new();
-       pkey = EVP_PKEY_new();
-       if (rsa == NULL || pkey == NULL) {
-               CLEANUP(dst__openssl_toresult(DST_R_OPENSSLFAILURE));
-       }
-
-       if (EVP_PKEY_set1_RSA(pkey, rsa) != 1) {
-               CLEANUP(dst__openssl_toresult(DST_R_OPENSSLFAILURE));
-       }
-
-       if (callback != NULL) {
-               cb = BN_GENCB_new();
-               if (cb == NULL) {
-                       CLEANUP(dst__openssl_toresult(ISC_R_NOMEMORY));
-               }
-               BN_GENCB_set(cb, progress_cb, (void *)callback);
-       }
-
-       if (RSA_generate_key_ex(rsa, key_size, e, cb) != 1) {
-               CLEANUP(dst__openssl_toresult2("RSA_generate_key_ex",
-                                              DST_R_OPENSSLFAILURE));
-       }
-       *retkey = pkey;
-       pkey = NULL;
-       result = ISC_R_SUCCESS;
-
-cleanup:
-       EVP_PKEY_free(pkey);
-       RSA_free(rsa);
-       BN_GENCB_free(cb);
-       return result;
-}
-
-static isc_result_t
-opensslrsa_build_pkey(bool private, rsa_components_t *c, EVP_PKEY **retpkey) {
-       isc_result_t result;
-       EVP_PKEY *pkey = NULL;
-       RSA *rsa = RSA_new();
-       int status;
-
-       REQUIRE(c->bnfree);
-
-       if (c->n == NULL || c->e == NULL) {
-               if (private) {
-                       CLEANUP(DST_R_INVALIDPRIVATEKEY);
-               }
-               CLEANUP(DST_R_INVALIDPUBLICKEY);
-       }
-
-       if (rsa == NULL) {
-               CLEANUP(dst__openssl_toresult2("RSA_new",
-                                              DST_R_OPENSSLFAILURE));
-       }
-
-       if (RSA_set0_key(rsa, (BIGNUM *)c->n, (BIGNUM *)c->e, (BIGNUM *)c->d) !=
-           1)
-       {
-               CLEANUP(dst__openssl_toresult2("RSA_set0_key",
-                                              DST_R_OPENSSLFAILURE));
-       }
-       c->n = NULL;
-       c->e = NULL;
-       c->d = NULL;
-
-       if (c->p != NULL || c->q != NULL) {
-               if (RSA_set0_factors(rsa, (BIGNUM *)c->p, (BIGNUM *)c->q) != 1)
-               {
-                       CLEANUP(dst__openssl_toresult2("RSA_set0_factors",
-                                                      DST_R_OPENSSLFAILURE));
-               }
-               c->p = NULL;
-               c->q = NULL;
-       }
-
-       if (c->dmp1 != NULL || c->dmq1 != NULL || c->iqmp != NULL) {
-               if (RSA_set0_crt_params(rsa, (BIGNUM *)c->dmp1,
-                                       (BIGNUM *)c->dmq1,
-                                       (BIGNUM *)c->iqmp) == 0)
-               {
-                       CLEANUP(dst__openssl_toresult2("RSA_set0_crt_params",
-                                                      DST_R_OPENSSLFAILURE));
-               }
-               c->dmp1 = NULL;
-               c->dmq1 = NULL;
-               c->iqmp = NULL;
-       }
-
-       pkey = EVP_PKEY_new();
-       if (pkey == NULL) {
-               CLEANUP(dst__openssl_toresult2("EVP_PKEY_new",
-                                              DST_R_OPENSSLFAILURE));
-       }
-       status = EVP_PKEY_set1_RSA(pkey, rsa);
-       if (status != 1) {
-               CLEANUP(dst__openssl_toresult2("EVP_PKEY_set1_RSA",
-                                              DST_R_OPENSSLFAILURE));
-       }
-
-       *retpkey = pkey;
-       pkey = NULL;
-       result = ISC_R_SUCCESS;
-
-cleanup:
-       EVP_PKEY_free(pkey);
-       RSA_free(rsa);
-       opensslrsa_components_free(c);
-       return result;
-}
-#else
-static int
-progress_cb(EVP_PKEY_CTX *ctx) {
-       void (*fptr)(int);
-
-       fptr = EVP_PKEY_CTX_get_app_data(ctx);
-       if (fptr != NULL) {
-               int p = EVP_PKEY_CTX_get_keygen_info(ctx, 0);
-               fptr(p);
-       }
-       return 1;
-}
-
-static isc_result_t
-opensslrsa_generate_pkey_with_uri(size_t key_size, const char *label,
-                                 EVP_PKEY **retkey) {
-       EVP_PKEY_CTX *ctx = NULL;
-       OSSL_PARAM params[4];
-       char *uri = UNCONST(label);
-       isc_result_t result;
-       int status;
-
-       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_size_t("rsa_keygen_bits", &key_size);
-       params[3] = OSSL_PARAM_construct_end();
-
-       ctx = EVP_PKEY_CTX_new_from_name(NULL, "RSA", "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));
-       }
-
-       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
-opensslrsa_generate_pkey(unsigned int key_size, const char *label, BIGNUM *e,
-                        void (*callback)(int), EVP_PKEY **retkey) {
-       EVP_PKEY_CTX *ctx;
-       isc_result_t result;
-
-       if (label != NULL) {
-               return opensslrsa_generate_pkey_with_uri(key_size, label,
-                                                        retkey);
-       }
-
-       ctx = EVP_PKEY_CTX_new_from_name(NULL, "RSA", NULL);
-       if (ctx == NULL) {
-               CLEANUP(dst__openssl_toresult(DST_R_OPENSSLFAILURE));
-       }
-
-       if (EVP_PKEY_keygen_init(ctx) != 1) {
-               CLEANUP(dst__openssl_toresult(DST_R_OPENSSLFAILURE));
-       }
-
-       if (EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, (int)key_size) != 1) {
-               CLEANUP(dst__openssl_toresult(DST_R_OPENSSLFAILURE));
-       }
-
-       if (EVP_PKEY_CTX_set1_rsa_keygen_pubexp(ctx, e) != 1) {
-               CLEANUP(dst__openssl_toresult(DST_R_OPENSSLFAILURE));
-       }
-
-       if (callback != NULL) {
-               EVP_PKEY_CTX_set_app_data(ctx, (void *)callback);
-               EVP_PKEY_CTX_set_cb(ctx, progress_cb);
-       }
-
-       if (EVP_PKEY_keygen(ctx, retkey) != 1) {
-               CLEANUP(dst__openssl_toresult2("EVP_PKEY_keygen",
-                                              DST_R_OPENSSLFAILURE));
-       }
-       result = ISC_R_SUCCESS;
-cleanup:
-       EVP_PKEY_CTX_free(ctx);
-       return result;
-}
-
-static isc_result_t
-opensslrsa_build_pkey(bool private, rsa_components_t *c, EVP_PKEY **retpkey) {
-       isc_result_t result;
-       int status;
-       OSSL_PARAM_BLD *bld = NULL;
-       OSSL_PARAM *params = NULL;
-       EVP_PKEY_CTX *ctx = NULL;
-
-       bld = OSSL_PARAM_BLD_new();
-       if (bld == NULL) {
-               CLEANUP(dst__openssl_toresult2("OSSL_PARAM_BLD_new",
-                                              DST_R_OPENSSLFAILURE));
-       }
-       if (OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_RSA_N, c->n) != 1 ||
-           OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_RSA_E, c->e) != 1)
-       {
-               CLEANUP(dst__openssl_toresult2("OSSL_PARAM_BLD_push_BN",
-                                              DST_R_OPENSSLFAILURE));
-       }
-
-       if (c->d != NULL &&
-           OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_RSA_D, c->d) != 1)
-       {
-               CLEANUP(dst__openssl_toresult2("OSSL_PARAM_BLD_push_BN",
-                                              DST_R_OPENSSLFAILURE));
-       }
-       if (c->p != NULL &&
-           OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_RSA_FACTOR1, c->p) != 1)
-       {
-               CLEANUP(dst__openssl_toresult2("OSSL_PARAM_BLD_push_BN",
-                                              DST_R_OPENSSLFAILURE));
-       }
-       if (c->q != NULL &&
-           OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_RSA_FACTOR2, c->q) != 1)
-       {
-               CLEANUP(dst__openssl_toresult2("OSSL_PARAM_BLD_push_BN",
-                                              DST_R_OPENSSLFAILURE));
-       }
-       if (c->dmp1 != NULL &&
-           OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_RSA_EXPONENT1,
-                                  c->dmp1) != 1)
-       {
-               CLEANUP(dst__openssl_toresult2("OSSL_PARAM_BLD_push_BN",
-                                              DST_R_OPENSSLFAILURE));
-       }
-       if (c->dmq1 != NULL &&
-           OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_RSA_EXPONENT2,
-                                  c->dmq1) != 1)
-       {
-               CLEANUP(dst__openssl_toresult2("OSSL_PARAM_BLD_push_BN",
-                                              DST_R_OPENSSLFAILURE));
-       }
-       if (c->iqmp != NULL &&
-           OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_RSA_COEFFICIENT1,
-                                  c->iqmp) != 1)
-       {
-               CLEANUP(dst__openssl_toresult2("OSSL_PARAM_BLD_push_BN",
-                                              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, "RSA", 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) {
-               CLEANUP(dst__openssl_toresult2("EVP_PKEY_fromdata_init",
-                                              DST_R_OPENSSLFAILURE));
-       }
-
-       status = EVP_PKEY_fromdata(
-               ctx, retpkey, private ? EVP_PKEY_KEYPAIR : EVP_PKEY_PUBLIC_KEY,
-               params);
-       if (status != 1) {
-               CLEANUP(dst__openssl_toresult2("EVP_PKEY_fromdata",
-                                              DST_R_OPENSSLFAILURE));
-       }
-       result = ISC_R_SUCCESS;
-
-cleanup:
-       EVP_PKEY_CTX_free(ctx);
-       OSSL_PARAM_free(params);
-       OSSL_PARAM_BLD_free(bld);
-       return result;
-}
-#endif /* OPENSSL_VERSION_NUMBER < 0x30000000L */
-
 static isc_result_t
 opensslrsa_generate(dst_key_t *key, int unused, void (*callback)(int)) {
        isc_result_t result;
-       BIGNUM *e = BN_new();
        EVP_PKEY *pkey = NULL;
 
        UNUSED(unused);
 
-       if (e == NULL) {
-               CLEANUP(dst__openssl_toresult(DST_R_OPENSSLFAILURE));
-       }
-
        /*
         * Reject incorrect RSA key lengths.
         */
@@ -772,12 +312,13 @@ opensslrsa_generate(dst_key_t *key, int unused, void (*callback)(int)) {
                UNREACHABLE();
        }
 
-       /* e = 65537 (0x10001, F4) */
-       BN_set_bit(e, 0);
-       BN_set_bit(e, 16);
-
-       CHECK(opensslrsa_generate_pkey(key->key_size, key->label, e, callback,
-                                      &pkey));
+       if (key->label != NULL) {
+               CHECK(isc_ossl_wrap_generate_pkcs11_rsa_key(
+                       key->label, key->key_size, &pkey));
+       } else {
+               CHECK(isc_ossl_wrap_generate_rsa_key(callback, key->key_size,
+                                                    &pkey));
+       }
 
        key->keydata.pkeypair.pub = pkey;
        key->keydata.pkeypair.priv = pkey;
@@ -786,7 +327,6 @@ opensslrsa_generate(dst_key_t *key, int unused, void (*callback)(int)) {
 
 cleanup:
        EVP_PKEY_free(pkey);
-       BN_free(e);
        return result;
 }
 
@@ -796,7 +336,7 @@ opensslrsa_todns(const dst_key_t *key, isc_buffer_t *data) {
        unsigned int e_bytes;
        unsigned int mod_bytes;
        isc_result_t result;
-       rsa_components_t c = { 0 };
+       isc_ossl_wrap_rsa_components_t c = { 0 };
 
        REQUIRE(key->keydata.pkeypair.pub != NULL);
 
@@ -822,7 +362,8 @@ opensslrsa_todns(const dst_key_t *key, isc_buffer_t *data) {
                break;
        }
 
-       CHECK(opensslrsa_components_get(key, &c, false));
+       CHECK(isc_ossl_wrap_rsa_public_components(key->keydata.pkeypair.pub,
+                                                 &c));
 
        mod_bytes = BN_num_bytes(c.n);
        e_bytes = BN_num_bytes(c.e);
@@ -853,9 +394,8 @@ opensslrsa_todns(const dst_key_t *key, isc_buffer_t *data) {
 
        isc_buffer_add(data, e_bytes + mod_bytes);
 
-       result = ISC_R_SUCCESS;
 cleanup:
-       opensslrsa_components_free(&c);
+       isc_ossl_wrap_rsa_components_cleanup(&c);
        return result;
 }
 
@@ -865,7 +405,7 @@ opensslrsa_fromdns(dst_key_t *key, isc_buffer_t *data) {
        isc_region_t r;
        unsigned int e_bytes;
        unsigned int length;
-       rsa_components_t c = { .bnfree = true };
+       isc_ossl_wrap_rsa_components_t c = { .needs_cleanup = true };
 
        REQUIRE(opensslrsa_valid_key_alg(key->key_alg));
 
@@ -928,10 +468,11 @@ opensslrsa_fromdns(dst_key_t *key, isc_buffer_t *data) {
        isc_buffer_forward(data, length);
 
        key->key_size = BN_num_bits(c.n);
-       result = opensslrsa_build_pkey(false, &c, &key->keydata.pkeypair.pub);
+       result = isc_ossl_wrap_load_rsa_public_from_components(
+               &c, &key->keydata.pkeypair.pub);
 
 cleanup:
-       opensslrsa_components_free(&c);
+       isc_ossl_wrap_rsa_components_cleanup(&c);
        return result;
 }
 
@@ -941,13 +482,16 @@ opensslrsa_tofile(const dst_key_t *key, const char *directory) {
        dst_private_t priv = { 0 };
        unsigned char *bufs[8] = { NULL };
        unsigned short i = 0;
-       rsa_components_t c = { 0 };
+       isc_ossl_wrap_rsa_components_t c = { 0 };
 
        if (key->external) {
                return dst__privstruct_writefile(key, &priv, directory);
        }
 
-       CHECK(opensslrsa_components_get(key, &c, true));
+       CHECK(isc_ossl_wrap_rsa_public_components(key->keydata.pkeypair.pub,
+                                                 &c));
+       CHECK(isc_ossl_wrap_rsa_secret_components(key->keydata.pkeypair.priv,
+                                                 &c));
 
        priv.elements[i].tag = TAG_RSA_MODULUS;
        priv.elements[i].length = BN_num_bytes(c.n);
@@ -1041,7 +585,7 @@ cleanup:
                                    priv.elements[i].length);
                }
        }
-       opensslrsa_components_free(&c);
+       isc_ossl_wrap_rsa_components_cleanup(&c);
 
        return result;
 }
@@ -1057,7 +601,7 @@ opensslrsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
        isc_mem_t *mctx = NULL;
        const char *label = NULL;
        EVP_PKEY *pkey = NULL;
-       rsa_components_t c = { .bnfree = true };
+       isc_ossl_wrap_rsa_components_t c = { .needs_cleanup = true };
 
        REQUIRE(key != NULL);
        REQUIRE(opensslrsa_valid_key_alg(key->key_alg));
@@ -1160,7 +704,8 @@ opensslrsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
        }
 
        key->key_size = BN_num_bits(c.n);
-       CHECK(opensslrsa_build_pkey(true, &c, &pkey));
+
+       CHECK(isc_ossl_wrap_load_rsa_secret_from_components(&c, &pkey));
 
        /* Check that the public component matches if given */
        if (pub != NULL && EVP_PKEY_eq(pkey, pub->keydata.pkeypair.pub) != 1) {
@@ -1172,7 +717,7 @@ opensslrsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
        pkey = NULL;
 
 cleanup:
-       opensslrsa_components_free(&c);
+       isc_ossl_wrap_rsa_components_cleanup(&c);
        EVP_PKEY_free(pkey);
        if (result != ISC_R_SUCCESS) {
                key->keydata.generic = NULL;
@@ -1192,7 +737,7 @@ opensslrsa_fromlabel(dst_key_t *key, const char *label, const char *pin) {
        CHECK(dst__openssl_fromlabel(EVP_PKEY_RSA, label, pin, &pubpkey,
                                     &privpkey));
 
-       if (!opensslrsa_check_exponent_bits(pubpkey, RSA_MAX_PUBEXP_BITS)) {
+       if (!isc_ossl_wrap_rsa_key_bits_leq(pubpkey, RSA_MAX_PUBEXP_BITS)) {
                CLEANUP(ISC_R_RANGE);
        }
 
@@ -1304,7 +849,7 @@ static const unsigned char sha512_sig[] =
 
 static isc_result_t
 check_algorithm(unsigned short algorithm) {
-       rsa_components_t c = { .bnfree = true };
+       isc_ossl_wrap_rsa_components_t c = { .needs_cleanup = true };
        EVP_MD_CTX *evp_md_ctx = EVP_MD_CTX_create();
        EVP_PKEY *pkey = NULL;
        const EVP_MD *type = NULL;
@@ -1341,7 +886,7 @@ check_algorithm(unsigned short algorithm) {
        c.e = BN_bin2bn(e_bytes, sizeof(e_bytes) - 1, NULL);
        c.n = BN_bin2bn(n_bytes, sizeof(n_bytes) - 1, NULL);
 
-       result = opensslrsa_build_pkey(false, &c, &pkey);
+       result = isc_ossl_wrap_load_rsa_public_from_components(&c, &pkey);
        INSIST(result == ISC_R_SUCCESS);
 
        /*
@@ -1355,7 +900,7 @@ check_algorithm(unsigned short algorithm) {
        }
 
 cleanup:
-       opensslrsa_components_free(&c);
+       isc_ossl_wrap_rsa_components_cleanup(&c);
        EVP_PKEY_free(pkey);
        EVP_MD_CTX_destroy(evp_md_ctx);
        ERR_clear_error();
index 4b9b330f04c15bc6f76f279388281403f43ce152..cef831793889bbc2557b5d2e376088cf8093a91e 100644 (file)
 
 #pragma once
 
+#include <stdbool.h>
+#include <stddef.h>
+
+#include <openssl/bn.h>
+#include <openssl/evp.h>
+
 #include <isc/log.h>
 #include <isc/types.h>
 
        isc__ossl_wrap_logged_toresult(category, module, funcname, fallback, \
                                       __FILE__, __LINE__)
 
+typedef struct isc_ossl_wrap_rsa_components {
+       bool    needs_cleanup;
+       BIGNUM *e, *n, *d, *p, *q, *dmp1, *dmq1, *iqmp;
+} isc_ossl_wrap_rsa_components_t;
+
+isc_result_t
+isc_ossl_wrap_generate_rsa_key(void (*callback)(int), size_t bit_size,
+                              EVP_PKEY **pkeyp);
+/*%
+ * Creates a RSA key with the specified bit-size
+ *
+ * Requires:
+ * \li `pkeyp != NULL`
+ * \li `*pkeyp == NULL`
+ */
+
+isc_result_t
+isc_ossl_wrap_generate_pkcs11_rsa_key(char *uri, size_t bit_size,
+                                     EVP_PKEY **pkeyp);
+/*%
+ * Creates a RSA key with the specified bit-size using the PKCS11 label
+ * specified at `uri`.
+ *
+ * Requires:
+ * \li `pkeyp != NULL`
+ * \li `*pkeyp == NULL`
+ * \li `uri != NULL` and is a NUL-terminated string
+ */
+
+bool
+isc_ossl_wrap_rsa_key_bits_leq(EVP_PKEY *pkey, size_t limit);
+
+isc_result_t
+isc_ossl_wrap_rsa_public_components(EVP_PKEY                      *pkey,
+                                   isc_ossl_wrap_rsa_components_t *c);
+
+isc_result_t
+isc_ossl_wrap_rsa_secret_components(EVP_PKEY                      *pkey,
+                                   isc_ossl_wrap_rsa_components_t *c);
+
+isc_result_t
+isc_ossl_wrap_load_rsa_public_from_components(isc_ossl_wrap_rsa_components_t *c,
+                                             EVP_PKEY **pkeyp);
+/*%
+ * Create a verifying `EVP_PKEY` using the public RSA components at `c`
+ *
+ * Requires:
+ * \li `pkeyp != NULL`
+ * \li `*pkeyp == NULL`
+ * \li `c != NULL`
+ * \li `c.n != NULL`
+ * \li `c.e != NULL`
+ */
+
+isc_result_t
+isc_ossl_wrap_load_rsa_secret_from_components(isc_ossl_wrap_rsa_components_t *c,
+                                             EVP_PKEY **pkeyp);
+/*%
+ * Create a signing `EVP_PKEY` using the public and secret RSA components at `c`
+ *
+ * Requires:
+ * \li `pkeyp != NULL`
+ * \li `*pkeyp == NULL`
+ * \li `c != NULL`
+ * \li `c.n != NULL`
+ * \li `c.e != NULL`
+ */
+
+void
+isc_ossl_wrap_rsa_components_cleanup(isc_ossl_wrap_rsa_components_t *comp);
+
 isc_result_t
 isc_ossl_wrap_toresult(isc_result_t fallback);
 
index 844583345b14a26f15c19d070d4d688d179d09ee..32fac0d1d610bcc3faa3e6a81f6068caf4165347 100644 (file)
  * information regarding copyright ownership.
  */
 
+#include <openssl/bn.h>
+#include <openssl/evp.h>
+#include <openssl/rsa.h>
+
 #include <isc/ossl_wrap.h>
 #include <isc/util.h>
 
-EMPTY_TRANSLATION_UNIT;
+#define OSSL_WRAP_ERROR(fn)                                        \
+       isc__ossl_wrap_logged_toresult(                            \
+               ISC_LOGCATEGORY_GENERAL, ISC_LOGMODULE_CRYPTO, fn, \
+               ISC_R_CRYPTOFAILURE, __FILE__, __LINE__)
+
+static int
+rsa_keygen_progress_cb(int p, int n, BN_GENCB *cb) {
+       void (*fptr)(int);
+
+       UNUSED(n);
+
+       fptr = BN_GENCB_get_arg(cb);
+       if (fptr != NULL) {
+               fptr(p);
+       }
+       return 1;
+}
+
+isc_result_t
+isc_ossl_wrap_generate_rsa_key(void (*callback)(int), size_t bit_size,
+                              EVP_PKEY **pkeyp) {
+       RSA *rsa = NULL;
+       EVP_PKEY *pkey = NULL;
+       BN_GENCB *cb = NULL;
+       isc_result_t result;
+       BIGNUM *e;
+
+       e = BN_new();
+
+       /* e = 65537 (0x10001, F4) */
+       BN_set_bit(e, 0);
+       BN_set_bit(e, 16);
+
+       rsa = RSA_new();
+       if (rsa == NULL) {
+               CLEANUP(OSSL_WRAP_ERROR("RSA_new"));
+       }
+
+       pkey = EVP_PKEY_new();
+       if (pkey == NULL) {
+               CLEANUP(OSSL_WRAP_ERROR("EVP_PKEY_new"));
+       }
+
+       if (EVP_PKEY_set1_RSA(pkey, rsa) != 1) {
+               CLEANUP(OSSL_WRAP_ERROR("EVP_PKEY_set1_RSA"));
+       }
+
+       if (callback != NULL) {
+               cb = BN_GENCB_new();
+               if (cb == NULL) {
+                       CLEANUP(OSSL_WRAP_ERROR("BN_GENCB_new"));
+               }
+
+               BN_GENCB_set(cb, rsa_keygen_progress_cb, (void *)callback);
+       }
+
+       if (RSA_generate_key_ex(rsa, bit_size, e, cb) != 1) {
+               CLEANUP(OSSL_WRAP_ERROR("RSA_generate_key_ex"));
+       }
+       *pkeyp = pkey;
+       pkey = NULL;
+       result = ISC_R_SUCCESS;
+
+cleanup:
+       EVP_PKEY_free(pkey);
+       RSA_free(rsa);
+       BN_GENCB_free(cb);
+       BN_free(e);
+       return result;
+}
+
+isc_result_t
+isc_ossl_wrap_generate_pkcs11_rsa_key(char *uri, size_t bit_size,
+                                     EVP_PKEY **pkeyp) {
+       UNUSED(uri);
+
+       return isc_ossl_wrap_generate_rsa_key(NULL, bit_size, pkeyp);
+}
+
+bool
+isc_ossl_wrap_rsa_key_bits_leq(EVP_PKEY *pkey, size_t limit) {
+       const RSA *rsa;
+       const BIGNUM *ce;
+       size_t bits = SIZE_MAX;
+
+       REQUIRE(pkey != NULL);
+
+       rsa = EVP_PKEY_get0_RSA(pkey);
+       if (rsa != NULL) {
+               ce = NULL;
+               RSA_get0_key(rsa, NULL, &ce, NULL);
+               if (ce != NULL) {
+                       bits = BN_num_bits(ce);
+               }
+       }
+
+       return bits <= limit;
+}
+
+isc_result_t
+isc_ossl_wrap_rsa_public_components(EVP_PKEY *pkey,
+                                   isc_ossl_wrap_rsa_components_t *c) {
+       isc_result_t result;
+       const RSA *rsa;
+
+       REQUIRE(pkey != NULL);
+       REQUIRE(c != NULL && c->e == NULL && c->n == NULL);
+
+       rsa = EVP_PKEY_get0_RSA(pkey);
+       if (rsa == NULL) {
+               CLEANUP(OSSL_WRAP_ERROR("EVP_PKEY_get0_RSA"));
+       }
+
+       RSA_get0_key(rsa, (const BIGNUM **)&c->n, (const BIGNUM **)&c->e, NULL);
+
+       result = ISC_R_SUCCESS;
+
+cleanup:
+       return result;
+}
+
+isc_result_t
+isc_ossl_wrap_rsa_secret_components(EVP_PKEY *pkey,
+                                   isc_ossl_wrap_rsa_components_t *c) {
+       isc_result_t result;
+       const RSA *rsa;
+
+       REQUIRE(pkey != NULL);
+       REQUIRE(c != NULL && c->d == NULL && c->p == NULL && c->q == NULL &&
+               c->dmp1 == NULL && c->dmq1 == NULL && c->iqmp == NULL);
+
+       rsa = EVP_PKEY_get0_RSA(pkey);
+       if (rsa == NULL) {
+               CLEANUP(OSSL_WRAP_ERROR("EVP_PKEY_get0_RSA"));
+       }
+
+       /*
+        * We don't support PKCS11 with OpenSSL <=1.1.1a
+        * d *must* succeed.
+        */
+       RSA_get0_key(rsa, NULL, NULL, (const BIGNUM **)&c->d);
+       if (c->d == NULL) {
+               CLEANUP(OSSL_WRAP_ERROR("RSA_get0_key"));
+       }
+
+       RSA_get0_factors(rsa, (const BIGNUM **)&c->p, (const BIGNUM **)&c->q);
+       RSA_get0_crt_params(rsa, (const BIGNUM **)&c->dmp1,
+                           (const BIGNUM **)&c->dmq1,
+                           (const BIGNUM **)&c->iqmp);
+
+       result = ISC_R_SUCCESS;
+
+cleanup:
+       return result;
+}
+
+isc_result_t
+isc_ossl_wrap_load_rsa_public_from_components(isc_ossl_wrap_rsa_components_t *c,
+                                             EVP_PKEY **pkeyp) {
+       isc_result_t result;
+       EVP_PKEY *pkey = NULL;
+       RSA *rsa = NULL;
+
+       REQUIRE(pkeyp != NULL && *pkeyp == NULL);
+       REQUIRE(c != NULL && c->e != NULL && c->n != NULL);
+       REQUIRE(c->needs_cleanup);
+
+       rsa = RSA_new();
+       if (rsa == NULL) {
+               CLEANUP(OSSL_WRAP_ERROR("RSA_new"));
+       }
+
+       if (RSA_set0_key(rsa, c->n, c->e, NULL) != 1) {
+               CLEANUP(OSSL_WRAP_ERROR("RSA_set0_key"));
+       }
+
+       c->n = NULL;
+       c->e = NULL;
+
+       pkey = EVP_PKEY_new();
+       if (pkey == NULL) {
+               CLEANUP(OSSL_WRAP_ERROR("EVP_PKEY_new"));
+       }
+
+       if (EVP_PKEY_set1_RSA(pkey, rsa) != 1) {
+               CLEANUP(OSSL_WRAP_ERROR("EVP_PKEY_set1_RSA"));
+       }
+
+       *pkeyp = pkey;
+       pkey = NULL;
+       result = ISC_R_SUCCESS;
+
+cleanup:
+       EVP_PKEY_free(pkey);
+       RSA_free(rsa);
+       return result;
+}
+
+isc_result_t
+isc_ossl_wrap_load_rsa_secret_from_components(isc_ossl_wrap_rsa_components_t *c,
+                                             EVP_PKEY **pkeyp) {
+       isc_result_t result;
+       EVP_PKEY *pkey = NULL;
+       RSA *rsa = NULL;
+
+       REQUIRE(pkeyp != NULL && *pkeyp == NULL);
+       REQUIRE(c != NULL);
+
+       result = ISC_R_SUCCESS;
+
+       rsa = RSA_new();
+       if (rsa == NULL) {
+               CLEANUP(OSSL_WRAP_ERROR("RSA_new"));
+       }
+
+       if (RSA_set0_key(rsa, c->n, c->e, c->d) != 1) {
+               CLEANUP(OSSL_WRAP_ERROR("RSA_set0_key"));
+       }
+
+       c->n = NULL;
+       c->e = NULL;
+       c->d = NULL;
+
+       if (c->p != NULL || c->q != NULL) {
+               if (RSA_set0_factors(rsa, c->p, c->q) != 1) {
+                       CLEANUP(OSSL_WRAP_ERROR("RSA_set0_factors"));
+               }
+
+               c->p = NULL;
+               c->q = NULL;
+       }
+
+       if (c->dmp1 != NULL || c->dmq1 != NULL || c->iqmp != NULL) {
+               if (RSA_set0_crt_params(rsa, c->dmp1, c->dmq1, c->iqmp) != 1) {
+                       CLEANUP(OSSL_WRAP_ERROR("RSA_set0_crt_params"));
+               }
+               c->dmp1 = NULL;
+               c->dmq1 = NULL;
+               c->iqmp = NULL;
+       }
+
+       pkey = EVP_PKEY_new();
+       if (pkey == NULL) {
+               CLEANUP(OSSL_WRAP_ERROR("EVP_PKEY_new"));
+       }
+
+       if (EVP_PKEY_set1_RSA(pkey, rsa) != 1) {
+               CLEANUP(OSSL_WRAP_ERROR("EVP_PKEY_set1_RSA"));
+       }
+
+       *pkeyp = pkey;
+       pkey = NULL;
+       result = ISC_R_SUCCESS;
+
+cleanup:
+       EVP_PKEY_free(pkey);
+       RSA_free(rsa);
+       isc_ossl_wrap_rsa_components_cleanup(c);
+       return result;
+}
index 844583345b14a26f15c19d070d4d688d179d09ee..d18beb3e19863afac245ceb0c6ee93b5bd3f6b2f 100644 (file)
  * information regarding copyright ownership.
  */
 
+#include <stdbool.h>
+
+#include <openssl/bn.h>
+#include <openssl/core_names.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/util.h>
 
-EMPTY_TRANSLATION_UNIT;
+#define OSSL_WRAP_ERROR(fn)                                        \
+       isc__ossl_wrap_logged_toresult(                            \
+               ISC_LOGCATEGORY_GENERAL, ISC_LOGMODULE_CRYPTO, fn, \
+               ISC_R_CRYPTOFAILURE, __FILE__, __LINE__)
+
+static int
+rsa_keygen_progress_cb(EVP_PKEY_CTX *ctx) {
+       void (*fptr)(int);
+
+       fptr = EVP_PKEY_CTX_get_app_data(ctx);
+       if (fptr != NULL) {
+               int p = EVP_PKEY_CTX_get_keygen_info(ctx, 0);
+               fptr(p);
+       }
+       return 1;
+}
+
+isc_result_t
+isc_ossl_wrap_generate_rsa_key(void (*callback)(int), size_t bit_size,
+                              EVP_PKEY **pkeyp) {
+       isc_result_t result;
+       EVP_PKEY_CTX *ctx;
+       BIGNUM *e;
+
+       REQUIRE(pkeyp != NULL && *pkeyp == NULL);
+
+       e = BN_new();
+
+       /* e = 65537 (0x10001, F4) */
+       BN_set_bit(e, 0);
+       BN_set_bit(e, 16);
+
+       ctx = EVP_PKEY_CTX_new_from_name(NULL, "RSA", NULL);
+       if (ctx == NULL) {
+               CLEANUP(OSSL_WRAP_ERROR("EVP_PKEY_CTX_new_from_name"));
+       }
+
+       if (EVP_PKEY_keygen_init(ctx) != 1) {
+               CLEANUP(OSSL_WRAP_ERROR("EVP_PKEY_keygen_init"));
+       }
+
+       if (EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, bit_size) != 1) {
+               CLEANUP(OSSL_WRAP_ERROR("EVP_PKEY_CTX_set_rsa_keygen_bits"));
+       }
+
+       if (EVP_PKEY_CTX_set1_rsa_keygen_pubexp(ctx, e) != 1) {
+               CLEANUP(OSSL_WRAP_ERROR("EVP_PKEY_CTX_set1_rsa_keygen_pubexp"));
+       }
+
+       if (callback != NULL) {
+               EVP_PKEY_CTX_set_app_data(ctx, (void *)callback);
+               EVP_PKEY_CTX_set_cb(ctx, rsa_keygen_progress_cb);
+       }
+
+       if (EVP_PKEY_keygen(ctx, pkeyp) != 1) {
+               CLEANUP(OSSL_WRAP_ERROR("EVP_PKEY_keygen"));
+       }
+
+       result = ISC_R_SUCCESS;
+
+cleanup:
+       EVP_PKEY_CTX_free(ctx);
+       BN_free(e);
+       return result;
+}
+
+isc_result_t
+isc_ossl_wrap_generate_pkcs11_rsa_key(char *uri, size_t bit_size,
+                                     EVP_PKEY **pkeyp) {
+       EVP_PKEY_CTX *ctx = NULL;
+       OSSL_PARAM params[4];
+       isc_result_t result;
+       int status;
+
+       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_size_t("rsa_keygen_bits", &bit_size);
+       params[3] = OSSL_PARAM_construct_end();
+
+       ctx = EVP_PKEY_CTX_new_from_name(NULL, "RSA", "provider=pkcs11");
+       if (ctx == NULL) {
+               CLEANUP(OSSL_WRAP_ERROR("EVP_PKEY_CTX_new_from_name"));
+       }
+
+       status = EVP_PKEY_keygen_init(ctx);
+       if (status != 1) {
+               CLEANUP(OSSL_WRAP_ERROR("EVP_PKEY_keygen_init"));
+       }
+
+       status = EVP_PKEY_CTX_set_params(ctx, params);
+       if (status != 1) {
+               CLEANUP(OSSL_WRAP_ERROR("EVP_PKEY_CTX_set_params"));
+       }
+
+       status = EVP_PKEY_generate(ctx, pkeyp);
+       if (status != 1) {
+               CLEANUP(OSSL_WRAP_ERROR("EVP_PKEY_generate"));
+       }
+
+       result = ISC_R_SUCCESS;
+
+cleanup:
+       EVP_PKEY_CTX_free(ctx);
+       return result;
+}
+
+bool
+isc_ossl_wrap_rsa_key_bits_leq(EVP_PKEY *pkey, size_t limit) {
+       size_t bits = SIZE_MAX;
+       BIGNUM *e = NULL;
+       if (EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_RSA_E, &e) == 1) {
+               bits = BN_num_bits(e);
+               BN_free(e);
+       }
+       return bits <= limit;
+}
+
+isc_result_t
+isc_ossl_wrap_rsa_public_components(EVP_PKEY *pkey,
+                                   isc_ossl_wrap_rsa_components_t *c) {
+       isc_result_t result;
+
+       REQUIRE(pkey != NULL);
+       REQUIRE(c != NULL && c->e == NULL && c->n == NULL);
+
+       c->needs_cleanup = true;
+
+       if (EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_RSA_E, &c->e) != 1) {
+               CLEANUP(OSSL_WRAP_ERROR("EVP_PKEY_get_bn_param"));
+       }
+
+       if (EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_RSA_N, &c->n) != 1) {
+               CLEANUP(OSSL_WRAP_ERROR("EVP_PKEY_get_bn_param"));
+       }
+
+       result = ISC_R_SUCCESS;
+
+cleanup:
+       return result;
+}
+
+isc_result_t
+isc_ossl_wrap_rsa_secret_components(EVP_PKEY *pkey,
+                                   isc_ossl_wrap_rsa_components_t *c) {
+       REQUIRE(pkey != NULL);
+       REQUIRE(c != NULL && c->d == NULL && c->p == NULL && c->q == NULL &&
+               c->dmp1 == NULL && c->dmq1 == NULL && c->iqmp == NULL);
+
+       c->needs_cleanup = true;
+
+       /*
+        * NOTE: Errors regarding private compoments are ignored.
+        *
+        * OpenSSL allows omitting the parameters for CRT based calculations
+        * (factors, exponents, coefficients). Only the 'd'  parameter is
+        * mandatory for software keys.
+        *
+        * However, for a label based keys, all private key component queries
+        * can fail if they key is e.g. on a hardware device.
+        */
+       (void)EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_RSA_D, &c->d);
+       (void)EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_RSA_FACTOR1, &c->p);
+       (void)EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_RSA_FACTOR2, &c->q);
+       (void)EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_RSA_EXPONENT1,
+                                   &c->dmp1);
+       (void)EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_RSA_EXPONENT2,
+                                   &c->dmq1);
+       (void)EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_RSA_COEFFICIENT1,
+                                   &c->iqmp);
+
+       ERR_clear_error();
+
+       return ISC_R_SUCCESS;
+}
+
+isc_result_t
+isc_ossl_wrap_load_rsa_public_from_components(isc_ossl_wrap_rsa_components_t *c,
+                                             EVP_PKEY **pkeyp) {
+       OSSL_PARAM_BLD *bld = NULL;
+       EVP_PKEY_CTX *pctx = NULL;
+       OSSL_PARAM *params = NULL;
+       isc_result_t result;
+
+       result = ISC_R_SUCCESS;
+
+       REQUIRE(pkeyp != NULL && *pkeyp == NULL);
+       REQUIRE(c != NULL && c->n != NULL && c->e != NULL);
+
+       bld = OSSL_PARAM_BLD_new();
+       if (bld == NULL) {
+               CLEANUP(OSSL_WRAP_ERROR("OSSL_PARAM_BLD_new"));
+       }
+
+       if (OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_RSA_N, c->n) != 1) {
+               CLEANUP(OSSL_WRAP_ERROR("OSSL_PARAM_BLD_push_BN"));
+       }
+
+       if (OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_RSA_E, c->e) != 1) {
+               CLEANUP(OSSL_WRAP_ERROR("OSSL_PARAM_BLD_push_BN"));
+       }
+
+       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, "RSA", 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:
+       EVP_PKEY_CTX_free(pctx);
+       OSSL_PARAM_free(params);
+       OSSL_PARAM_BLD_free(bld);
+       return result;
+}
+
+isc_result_t
+isc_ossl_wrap_load_rsa_secret_from_components(isc_ossl_wrap_rsa_components_t *c,
+                                             EVP_PKEY **pkeyp) {
+       isc_result_t result;
+       OSSL_PARAM_BLD *bld = NULL;
+       EVP_PKEY_CTX *pctx = NULL;
+       OSSL_PARAM *params = NULL;
+
+       REQUIRE(pkeyp != NULL && *pkeyp == NULL);
+
+       bld = OSSL_PARAM_BLD_new();
+       if (bld == NULL) {
+               CLEANUP(OSSL_WRAP_ERROR("OSSL_PARAM_BLD_new"));
+       }
+
+       if (OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_RSA_N, c->n) != 1) {
+               CLEANUP(OSSL_WRAP_ERROR("OSSL_PARAM_BLD_push_BN"));
+       }
+
+       if (OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_RSA_E, c->e) != 1) {
+               CLEANUP(OSSL_WRAP_ERROR("OSSL_PARAM_BLD_push_BN"));
+       }
+
+       if (c->d != NULL &&
+           OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_RSA_D, c->d) != 1)
+       {
+               CLEANUP(OSSL_WRAP_ERROR("OSSL_PARAM_BLD_push_BN"));
+       }
+
+       if (c->p != NULL &&
+           OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_RSA_FACTOR1, c->p) != 1)
+       {
+               CLEANUP(OSSL_WRAP_ERROR("OSSL_PARAM_BLD_push_BN"));
+       }
+
+       if (c->q != NULL &&
+           OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_RSA_FACTOR2, c->q) != 1)
+       {
+               CLEANUP(OSSL_WRAP_ERROR("OSSL_PARAM_BLD_push_BN"));
+       }
+
+       if (c->dmp1 != NULL &&
+           OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_RSA_EXPONENT1,
+                                  c->dmp1) != 1)
+       {
+               CLEANUP(OSSL_WRAP_ERROR("OSSL_PARAM_BLD_push_BN"));
+       }
+
+       if (c->dmq1 != NULL &&
+           OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_RSA_EXPONENT2,
+                                  c->dmq1) != 1)
+       {
+               CLEANUP(OSSL_WRAP_ERROR("OSSL_PARAM_BLD_push_BN"));
+       }
+
+       if (c->iqmp != NULL &&
+           OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_RSA_COEFFICIENT1,
+                                  c->iqmp) != 1)
+       {
+               CLEANUP(OSSL_WRAP_ERROR("OSSL_PARAM_BLD_push_BN"));
+       }
+
+       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, "RSA", 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:
+       EVP_PKEY_CTX_free(pctx);
+       OSSL_PARAM_free(params);
+       OSSL_PARAM_BLD_free(bld);
+       return result;
+}
index cf09d93a1827367b9e046ddb15eb72bfd7857736..0828a37ff0e134028787ebb4361a7bfd0814846c 100644 (file)
@@ -11,6 +11,7 @@
  * information regarding copyright ownership.
  */
 
+#include <openssl/bn.h>
 #include <openssl/err.h>
 
 #include <isc/ossl_wrap.h>
 
 #include "../openssl_shim.h"
 
+void
+isc_ossl_wrap_rsa_components_cleanup(isc_ossl_wrap_rsa_components_t *c) {
+       REQUIRE(c != NULL);
+
+       if (!c->needs_cleanup) {
+               return;
+       }
+
+       /*
+        * NOTE: BN_free() frees the components of the BIGNUM, and if it was
+        * created by BN_new(), also the structure itself. BN_clear_free()
+        * additionally overwrites the data before the memory is returned to the
+        * system. If a is NULL, nothing is done.
+        */
+       BN_free(c->e);
+       BN_free(c->n);
+       BN_clear_free(c->d);
+       BN_clear_free(c->p);
+       BN_clear_free(c->q);
+       BN_clear_free(c->dmp1);
+       BN_clear_free(c->dmq1);
+       BN_clear_free(c->iqmp);
+
+       c->needs_cleanup = false;
+}
+
 isc_result_t
 isc_ossl_wrap_toresult(isc_result_t fallback) {
        isc_result_t result = fallback;