mirror of
https://github.com/isc-projects/bind9.git
synced 2026-02-23 09:51:03 -05:00
Rework opensslecdsa_link to handle legacy key objects w/ openssl3
Due to bug in openssl3, the pkcs11-engine is made the default provider if enabled. This causes key generation and load to return legacy objects. Openssl3 has limited glue and does not support the full set of new style parameter to be inqueried from legacy key objects Rewrite required functions to use first the new API (if available), but fallback to the old API (if available). For the methods that have proper OpenSSL compatiblity glue, ship only one version.
This commit is contained in:
parent
edd9925e44
commit
628dd278d3
1 changed files with 206 additions and 162 deletions
|
|
@ -119,7 +119,7 @@ BN_bn2bin_fixed(const BIGNUM *bn, unsigned char *buf, int size) {
|
|||
return (size);
|
||||
}
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x30000000L && OPENSSL_API_LEVEL >= 30000
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||
|
||||
static const char *
|
||||
opensslecdsa_key_alg_to_group_name(unsigned int key_alg) {
|
||||
|
|
@ -134,66 +134,9 @@ opensslecdsa_key_alg_to_group_name(unsigned int key_alg) {
|
|||
}
|
||||
|
||||
static isc_result_t
|
||||
opensslecdsa_generate_pkey(unsigned int key_alg, EVP_PKEY **retkey) {
|
||||
isc_result_t ret;
|
||||
EVP_PKEY_CTX *ctx = NULL;
|
||||
EVP_PKEY *params_pkey = NULL;
|
||||
int group_nid = opensslecdsa_key_alg_to_group_nid(key_alg);
|
||||
int status;
|
||||
|
||||
/* Generate the key's parameters. */
|
||||
ctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL);
|
||||
if (ctx == NULL) {
|
||||
DST_RET(dst__openssl_toresult2("EVP_PKEY_CTX_new_from_name",
|
||||
DST_R_OPENSSLFAILURE));
|
||||
}
|
||||
status = EVP_PKEY_paramgen_init(ctx);
|
||||
if (status != 1) {
|
||||
DST_RET(dst__openssl_toresult2("EVP_PKEY_paramgen_init",
|
||||
DST_R_OPENSSLFAILURE));
|
||||
}
|
||||
status = EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, group_nid);
|
||||
if (status != 1) {
|
||||
DST_RET(dst__openssl_toresult2("EVP_PKEY_CTX_set_ec_paramgen_"
|
||||
"curve_nid",
|
||||
DST_R_OPENSSLFAILURE));
|
||||
}
|
||||
status = EVP_PKEY_paramgen(ctx, ¶ms_pkey);
|
||||
if (status != 1 || params_pkey == NULL) {
|
||||
DST_RET(dst__openssl_toresult2("EVP_PKEY_paramgen",
|
||||
DST_R_OPENSSLFAILURE));
|
||||
}
|
||||
EVP_PKEY_CTX_free(ctx);
|
||||
|
||||
/* Generate the key. */
|
||||
ctx = EVP_PKEY_CTX_new(params_pkey, NULL);
|
||||
if (ctx == NULL) {
|
||||
DST_RET(dst__openssl_toresult2("EVP_PKEY_CTX_new",
|
||||
DST_R_OPENSSLFAILURE));
|
||||
}
|
||||
status = EVP_PKEY_keygen_init(ctx);
|
||||
if (status != 1) {
|
||||
DST_RET(dst__openssl_toresult2("EVP_PKEY_keygen_init",
|
||||
DST_R_OPENSSLFAILURE));
|
||||
}
|
||||
|
||||
status = EVP_PKEY_keygen(ctx, retkey);
|
||||
if (status != 1) {
|
||||
DST_RET(dst__openssl_toresult2("EVP_PKEY_keygen",
|
||||
DST_R_OPENSSLFAILURE));
|
||||
}
|
||||
ret = ISC_R_SUCCESS;
|
||||
|
||||
err:
|
||||
EVP_PKEY_free(params_pkey);
|
||||
EVP_PKEY_CTX_free(ctx);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
opensslecdsa_create_pkey(unsigned int key_alg, bool private,
|
||||
const unsigned char *key, size_t key_len,
|
||||
EVP_PKEY **pkey) {
|
||||
opensslecdsa_create_pkey_params(unsigned int key_alg, bool private,
|
||||
const unsigned char *key, size_t key_len,
|
||||
EVP_PKEY **pkey) {
|
||||
isc_result_t ret;
|
||||
int status;
|
||||
int group_nid = opensslecdsa_key_alg_to_group_nid(key_alg);
|
||||
|
|
@ -281,8 +224,9 @@ opensslecdsa_create_pkey(unsigned int key_alg, bool private,
|
|||
}
|
||||
status = EVP_PKEY_fromdata_init(ctx);
|
||||
if (status != 1) {
|
||||
DST_RET(dst__openssl_toresult2("EVP_PKEY_fromdata_init",
|
||||
DST_R_OPENSSLFAILURE));
|
||||
/* This will fail if the default provider is an engine.
|
||||
* Return ISC_R_FAILURE to retry using the legacy API. */
|
||||
DST_RET(dst__openssl_toresult(ISC_R_FAILURE));
|
||||
}
|
||||
status = EVP_PKEY_fromdata(
|
||||
ctx, pkey, private ? EVP_PKEY_KEYPAIR : EVP_PKEY_PUBLIC_KEY,
|
||||
|
|
@ -305,100 +249,34 @@ err:
|
|||
return (ret);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
opensslecdsa_validate_pkey_group(unsigned int key_alg, EVP_PKEY *pkey) {
|
||||
const char *groupname = opensslecdsa_key_alg_to_group_name(key_alg);
|
||||
char gname[64];
|
||||
|
||||
if (EVP_PKEY_get_group_name(pkey, gname, sizeof(gname), NULL) != 1) {
|
||||
return (DST_R_INVALIDPRIVATEKEY);
|
||||
}
|
||||
if (strcmp(gname, groupname) != 0) {
|
||||
return (DST_R_INVALIDPRIVATEKEY);
|
||||
}
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
static bool
|
||||
opensslecdsa_extract_public_key(const dst_key_t *key, unsigned char *buf,
|
||||
size_t buflen) {
|
||||
opensslecdsa_extract_public_key_params(const dst_key_t *key, unsigned char *dst,
|
||||
size_t dstlen) {
|
||||
EVP_PKEY *pkey = key->keydata.pkeypair.pub;
|
||||
BIGNUM *x = NULL;
|
||||
BIGNUM *y = NULL;
|
||||
bool ret = false;
|
||||
|
||||
if (EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_EC_PUB_X, &x) != 1) {
|
||||
goto err;
|
||||
if (EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_EC_PUB_X, &x) == 1 &&
|
||||
EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_EC_PUB_Y, &y) == 1)
|
||||
{
|
||||
BN_bn2bin_fixed(x, &dst[0], dstlen / 2);
|
||||
BN_bn2bin_fixed(y, &dst[dstlen / 2], dstlen / 2);
|
||||
ret = true;
|
||||
}
|
||||
if (EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_EC_PUB_Y, &y) != 1) {
|
||||
goto err;
|
||||
}
|
||||
BN_bn2bin_fixed(x, &buf[0], buflen / 2);
|
||||
BN_bn2bin_fixed(y, &buf[buflen / 2], buflen / 2);
|
||||
ret = true;
|
||||
err:
|
||||
BN_clear_free(x);
|
||||
BN_clear_free(y);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static bool
|
||||
opensslecdsa_extract_private_key(const dst_key_t *key, unsigned char *buf,
|
||||
size_t buflen) {
|
||||
EVP_PKEY *pkey = key->keydata.pkeypair.priv;
|
||||
BIGNUM *priv = NULL;
|
||||
#endif
|
||||
|
||||
if (EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_PRIV_KEY, &priv) != 1) {
|
||||
return (false);
|
||||
}
|
||||
|
||||
BN_bn2bin_fixed(priv, buf, buflen);
|
||||
BN_clear_free(priv);
|
||||
return (true);
|
||||
}
|
||||
|
||||
#else
|
||||
#if OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000
|
||||
|
||||
static isc_result_t
|
||||
opensslecdsa_generate_pkey(unsigned int key_alg, EVP_PKEY **retkey) {
|
||||
isc_result_t ret;
|
||||
EC_KEY *eckey = NULL;
|
||||
EVP_PKEY *pkey = NULL;
|
||||
int group_nid = opensslecdsa_key_alg_to_group_nid(key_alg);
|
||||
|
||||
eckey = EC_KEY_new_by_curve_name(group_nid);
|
||||
if (eckey == NULL) {
|
||||
DST_RET(dst__openssl_toresult2("EC_KEY_new_by_curve_name",
|
||||
DST_R_OPENSSLFAILURE));
|
||||
}
|
||||
|
||||
if (EC_KEY_generate_key(eckey) != 1) {
|
||||
DST_RET(dst__openssl_toresult2("EC_KEY_generate_key",
|
||||
DST_R_OPENSSLFAILURE));
|
||||
}
|
||||
|
||||
pkey = EVP_PKEY_new();
|
||||
if (pkey == NULL) {
|
||||
DST_RET(ISC_R_NOMEMORY);
|
||||
}
|
||||
if (EVP_PKEY_set1_EC_KEY(pkey, eckey) != 1) {
|
||||
DST_RET(dst__openssl_toresult2("EVP_PKEY_set1_EC_KEY",
|
||||
DST_R_OPENSSLFAILURE));
|
||||
}
|
||||
*retkey = pkey;
|
||||
pkey = NULL;
|
||||
ret = ISC_R_SUCCESS;
|
||||
|
||||
err:
|
||||
EC_KEY_free(eckey);
|
||||
EVP_PKEY_free(pkey);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
opensslecdsa_create_pkey(unsigned int key_alg, bool private,
|
||||
const unsigned char *key, size_t key_len,
|
||||
EVP_PKEY **retkey) {
|
||||
opensslecdsa_create_pkey_legacy(unsigned int key_alg, bool private,
|
||||
const unsigned char *key, size_t key_len,
|
||||
EVP_PKEY **retkey) {
|
||||
isc_result_t ret = ISC_R_SUCCESS;
|
||||
EC_KEY *eckey = NULL;
|
||||
EVP_PKEY *pkey = NULL;
|
||||
|
|
@ -462,6 +340,191 @@ err:
|
|||
return (ret);
|
||||
}
|
||||
|
||||
static bool
|
||||
opensslecdsa_extract_public_key_legacy(const dst_key_t *key, unsigned char *dst,
|
||||
size_t dstlen) {
|
||||
EVP_PKEY *pkey = key->keydata.pkeypair.pub;
|
||||
const EC_KEY *eckey = EVP_PKEY_get0_EC_KEY(pkey);
|
||||
const EC_GROUP *group = EC_KEY_get0_group(eckey);
|
||||
const EC_POINT *pub = EC_KEY_get0_public_key(eckey);
|
||||
unsigned char buf[MAX_PUBKEY_SIZE + 1];
|
||||
size_t len;
|
||||
|
||||
len = EC_POINT_point2oct(group, pub, POINT_CONVERSION_UNCOMPRESSED, buf,
|
||||
sizeof(buf), NULL);
|
||||
if (len == dstlen + 1) {
|
||||
memmove(dst, buf + 1, dstlen);
|
||||
return (true);
|
||||
}
|
||||
return (false);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static bool
|
||||
opensslecdsa_extract_public_key(const dst_key_t *key, unsigned char *dst,
|
||||
size_t dstlen) {
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||
if (opensslecdsa_extract_public_key_params(key, dst, dstlen)) {
|
||||
return (true);
|
||||
}
|
||||
#endif
|
||||
#if OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000
|
||||
if (opensslecdsa_extract_public_key_legacy(key, dst, dstlen)) {
|
||||
return (true);
|
||||
}
|
||||
#endif
|
||||
return (false);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
opensslecdsa_create_pkey(unsigned int key_alg, bool private,
|
||||
const unsigned char *key, size_t key_len,
|
||||
EVP_PKEY **retkey) {
|
||||
isc_result_t ret;
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||
ret = opensslecdsa_create_pkey_params(key_alg, private, key, key_len,
|
||||
retkey);
|
||||
if (ret != ISC_R_FAILURE) {
|
||||
return (ret);
|
||||
}
|
||||
#endif
|
||||
#if OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000
|
||||
ret = opensslecdsa_create_pkey_legacy(key_alg, private, key, key_len,
|
||||
retkey);
|
||||
if (ret == ISC_R_SUCCESS) {
|
||||
return (ret);
|
||||
}
|
||||
#endif
|
||||
return (DST_R_OPENSSLFAILURE);
|
||||
}
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||
|
||||
static isc_result_t
|
||||
opensslecdsa_generate_pkey(unsigned int key_alg, EVP_PKEY **retkey) {
|
||||
isc_result_t ret;
|
||||
EVP_PKEY_CTX *ctx = NULL;
|
||||
EVP_PKEY *params_pkey = NULL;
|
||||
int group_nid = opensslecdsa_key_alg_to_group_nid(key_alg);
|
||||
int status;
|
||||
|
||||
/* Generate the key's parameters. */
|
||||
ctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL);
|
||||
if (ctx == NULL) {
|
||||
DST_RET(dst__openssl_toresult2("EVP_PKEY_CTX_new_from_name",
|
||||
DST_R_OPENSSLFAILURE));
|
||||
}
|
||||
status = EVP_PKEY_paramgen_init(ctx);
|
||||
if (status != 1) {
|
||||
DST_RET(dst__openssl_toresult2("EVP_PKEY_paramgen_init",
|
||||
DST_R_OPENSSLFAILURE));
|
||||
}
|
||||
status = EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, group_nid);
|
||||
if (status != 1) {
|
||||
DST_RET(dst__openssl_toresult2("EVP_PKEY_CTX_set_ec_paramgen_"
|
||||
"curve_nid",
|
||||
DST_R_OPENSSLFAILURE));
|
||||
}
|
||||
status = EVP_PKEY_paramgen(ctx, ¶ms_pkey);
|
||||
if (status != 1 || params_pkey == NULL) {
|
||||
DST_RET(dst__openssl_toresult2("EVP_PKEY_paramgen",
|
||||
DST_R_OPENSSLFAILURE));
|
||||
}
|
||||
EVP_PKEY_CTX_free(ctx);
|
||||
|
||||
/* Generate the key. */
|
||||
ctx = EVP_PKEY_CTX_new(params_pkey, NULL);
|
||||
if (ctx == NULL) {
|
||||
DST_RET(dst__openssl_toresult2("EVP_PKEY_CTX_new",
|
||||
DST_R_OPENSSLFAILURE));
|
||||
}
|
||||
status = EVP_PKEY_keygen_init(ctx);
|
||||
if (status != 1) {
|
||||
DST_RET(dst__openssl_toresult2("EVP_PKEY_keygen_init",
|
||||
DST_R_OPENSSLFAILURE));
|
||||
}
|
||||
|
||||
status = EVP_PKEY_keygen(ctx, retkey);
|
||||
if (status != 1) {
|
||||
DST_RET(dst__openssl_toresult2("EVP_PKEY_keygen",
|
||||
DST_R_OPENSSLFAILURE));
|
||||
}
|
||||
ret = ISC_R_SUCCESS;
|
||||
|
||||
err:
|
||||
EVP_PKEY_free(params_pkey);
|
||||
EVP_PKEY_CTX_free(ctx);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
opensslecdsa_validate_pkey_group(unsigned int key_alg, EVP_PKEY *pkey) {
|
||||
const char *groupname = opensslecdsa_key_alg_to_group_name(key_alg);
|
||||
char gname[64];
|
||||
|
||||
if (EVP_PKEY_get_group_name(pkey, gname, sizeof(gname), NULL) != 1) {
|
||||
return (DST_R_INVALIDPRIVATEKEY);
|
||||
}
|
||||
if (strcmp(gname, groupname) != 0) {
|
||||
return (DST_R_INVALIDPRIVATEKEY);
|
||||
}
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
static bool
|
||||
opensslecdsa_extract_private_key(const dst_key_t *key, unsigned char *buf,
|
||||
size_t buflen) {
|
||||
EVP_PKEY *pkey = key->keydata.pkeypair.priv;
|
||||
BIGNUM *priv = NULL;
|
||||
|
||||
if (EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_PRIV_KEY, &priv) != 1) {
|
||||
return (false);
|
||||
}
|
||||
|
||||
BN_bn2bin_fixed(priv, buf, buflen);
|
||||
BN_clear_free(priv);
|
||||
return (true);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static isc_result_t
|
||||
opensslecdsa_generate_pkey(unsigned int key_alg, EVP_PKEY **retkey) {
|
||||
isc_result_t ret;
|
||||
EC_KEY *eckey = NULL;
|
||||
EVP_PKEY *pkey = NULL;
|
||||
int group_nid = opensslecdsa_key_alg_to_group_nid(key_alg);
|
||||
|
||||
eckey = EC_KEY_new_by_curve_name(group_nid);
|
||||
if (eckey == NULL) {
|
||||
DST_RET(dst__openssl_toresult2("EC_KEY_new_by_curve_name",
|
||||
DST_R_OPENSSLFAILURE));
|
||||
}
|
||||
|
||||
if (EC_KEY_generate_key(eckey) != 1) {
|
||||
DST_RET(dst__openssl_toresult2("EC_KEY_generate_key",
|
||||
DST_R_OPENSSLFAILURE));
|
||||
}
|
||||
|
||||
pkey = EVP_PKEY_new();
|
||||
if (pkey == NULL) {
|
||||
DST_RET(ISC_R_NOMEMORY);
|
||||
}
|
||||
if (EVP_PKEY_set1_EC_KEY(pkey, eckey) != 1) {
|
||||
DST_RET(dst__openssl_toresult2("EVP_PKEY_set1_EC_KEY",
|
||||
DST_R_OPENSSLFAILURE));
|
||||
}
|
||||
*retkey = pkey;
|
||||
pkey = NULL;
|
||||
ret = ISC_R_SUCCESS;
|
||||
|
||||
err:
|
||||
EC_KEY_free(eckey);
|
||||
EVP_PKEY_free(pkey);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
opensslecdsa_validate_pkey_group(unsigned int key_alg, EVP_PKEY *pkey) {
|
||||
const EC_KEY *eckey = EVP_PKEY_get0_EC_KEY(pkey);
|
||||
|
|
@ -474,24 +537,6 @@ opensslecdsa_validate_pkey_group(unsigned int key_alg, EVP_PKEY *pkey) {
|
|||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
static bool
|
||||
opensslecdsa_extract_public_key(const dst_key_t *key, unsigned char *dst,
|
||||
size_t dstlen) {
|
||||
const EC_KEY *eckey = EVP_PKEY_get0_EC_KEY(key->keydata.pkeypair.pub);
|
||||
const EC_GROUP *group = EC_KEY_get0_group(eckey);
|
||||
const EC_POINT *pub = EC_KEY_get0_public_key(eckey);
|
||||
unsigned char buf[MAX_PUBKEY_SIZE + 1];
|
||||
size_t len;
|
||||
|
||||
len = EC_POINT_point2oct(group, pub, POINT_CONVERSION_UNCOMPRESSED, buf,
|
||||
sizeof(buf), NULL);
|
||||
if (len != dstlen + 1) {
|
||||
return (false);
|
||||
}
|
||||
memmove(dst, buf + 1, dstlen);
|
||||
return (true);
|
||||
}
|
||||
|
||||
static bool
|
||||
opensslecdsa_extract_private_key(const dst_key_t *key, unsigned char *buf,
|
||||
size_t buflen) {
|
||||
|
|
@ -512,8 +557,7 @@ opensslecdsa_extract_private_key(const dst_key_t *key, unsigned char *buf,
|
|||
return (true);
|
||||
}
|
||||
|
||||
#endif /* OPENSSL_VERSION_NUMBER >= 0x30000000L && OPENSSL_API_LEVEL >= 30000 \
|
||||
*/
|
||||
#endif /* OPENSSL_VERSION_NUMBER >= 0x30000000L */
|
||||
|
||||
static isc_result_t
|
||||
opensslecdsa_createctx(dst_key_t *key, dst_context_t *dctx) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue