mirror of
https://github.com/isc-projects/bind9.git
synced 2026-05-22 10:10:14 -04:00
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.
This commit is contained in:
parent
f21d237374
commit
f4d88404e2
5 changed files with 725 additions and 488 deletions
|
|
@ -19,14 +19,10 @@
|
|||
#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>
|
||||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -13,6 +13,12 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/evp.h>
|
||||
|
||||
#include <isc/log.h>
|
||||
#include <isc/types.h>
|
||||
|
||||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,270 @@
|
|||
* 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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,332 @@
|
|||
* 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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
* information regarding copyright ownership.
|
||||
*/
|
||||
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/err.h>
|
||||
|
||||
#include <isc/ossl_wrap.h>
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Reference in a new issue