From: Aydın Mercan Date: Mon, 1 Dec 2025 13:23:37 +0000 (+0300) Subject: remove libcrypto version specific code in opensslrsa_link X-Git-Tag: v9.21.18~2^2~9 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f4d88404e2fb7175ea1d302836adc515f7980211;p=thirdparty%2Fbind9.git remove libcrypto version specific code in opensslrsa_link 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. --- diff --git a/lib/dns/opensslrsa_link.c b/lib/dns/opensslrsa_link.c index bc79ae01002..ec24bf202da 100644 --- a/lib/dns/opensslrsa_link.c +++ b/lib/dns/opensslrsa_link.c @@ -19,14 +19,10 @@ #include #include #include -#include #include -#if OPENSSL_VERSION_NUMBER >= 0x30000000L -#include -#include -#endif #include +#include #include #include #include @@ -42,11 +38,6 @@ /* 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(); diff --git a/lib/isc/include/isc/ossl_wrap.h b/lib/isc/include/isc/ossl_wrap.h index 4b9b330f04c..cef83179388 100644 --- a/lib/isc/include/isc/ossl_wrap.h +++ b/lib/isc/include/isc/ossl_wrap.h @@ -13,6 +13,12 @@ #pragma once +#include +#include + +#include +#include + #include #include @@ -20,6 +26,77 @@ 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); diff --git a/lib/isc/ossl_wrap/ossl1_1.c b/lib/isc/ossl_wrap/ossl1_1.c index 844583345b1..32fac0d1d61 100644 --- a/lib/isc/ossl_wrap/ossl1_1.c +++ b/lib/isc/ossl_wrap/ossl1_1.c @@ -11,7 +11,270 @@ * information regarding copyright ownership. */ +#include +#include +#include + #include #include -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; +} diff --git a/lib/isc/ossl_wrap/ossl3.c b/lib/isc/ossl_wrap/ossl3.c index 844583345b1..d18beb3e198 100644 --- a/lib/isc/ossl_wrap/ossl3.c +++ b/lib/isc/ossl_wrap/ossl3.c @@ -11,7 +11,332 @@ * information regarding copyright ownership. */ +#include + +#include +#include +#include +#include +#include +#include + #include #include -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; +} diff --git a/lib/isc/ossl_wrap/ossl_common.c b/lib/isc/ossl_wrap/ossl_common.c index cf09d93a182..0828a37ff0e 100644 --- a/lib/isc/ossl_wrap/ossl_common.c +++ b/lib/isc/ossl_wrap/ossl_common.c @@ -11,6 +11,7 @@ * information regarding copyright ownership. */ +#include #include #include @@ -18,6 +19,32 @@ #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;