resolved: migrate ECDSA verification to OpenSSL 3 EVP API

OpenSSL 3.0 deprecated low-level Elliptic Curve (EC) key manipulation
functions (EC_KEY, EC_POINT, EC_GROUP) and direct signature verification
functions like ECDSA_do_verify().

This commit modernizes dnssec_ecdsa_verify_raw() by transitioning to the
provider-aware EVP API:
* Uses OSSL_PARAM arrays and EVP_PKEY_fromdata() to construct the EC
  public key directly from the raw octet string and curve name, avoiding
  deprecated EC_POINT parsing.
* Converts the raw R and S signature components into a DER-encoded ASN.1
  signature using i2d_ECDSA_SIG(), as required by the modern EVP API.
* Uses EVP_PKEY_verify() for the actual signature validation.

Additionally, this drops an outdated TODO comment waiting for raw ECDSA
support in the EVP API, as well as the deprecated warning suppression
macros and fallback code blocks. Unit tests for ECDSA are now run
unconditionally.
This commit is contained in:
Yu Watanabe
2026-07-03 03:02:56 +09:00
parent 13be553507
commit c18ee628a5
2 changed files with 37 additions and 37 deletions
+37 -33
View File
@@ -212,8 +212,6 @@ int dnssec_ecdsa_verify_raw(
const struct iovec *hash,
const struct iovec *key) {
#if !defined(OPENSSL_NO_DEPRECATED_3_0)
DISABLE_WARNING_DEPRECATED_DECLARATIONS;
int r;
assert(hash_algorithm);
@@ -222,33 +220,26 @@ int dnssec_ecdsa_verify_raw(
assert(iovec_is_set(hash));
assert(iovec_is_set(key));
_cleanup_(EC_GROUP_freep) EC_GROUP *ec_group = sym_EC_GROUP_new_by_curve_name(curve);
if (!ec_group)
const char *curve_name = sym_OBJ_nid2sn(curve);
if (!curve_name)
return log_openssl_errors(LOG_DEBUG, "Unknown curve NID");
OSSL_PARAM params[] = {
sym_OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, (char*) curve_name, 0),
sym_OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_PUB_KEY, key->iov_base, key->iov_len),
sym_OSSL_PARAM_construct_end(),
};
_cleanup_(EVP_PKEY_CTX_freep) EVP_PKEY_CTX *kctx = sym_EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL);
if (!kctx)
return -ENOMEM;
_cleanup_(EC_POINT_freep) EC_POINT *p = sym_EC_POINT_new(ec_group);
if (!p)
return -ENOMEM;
if (sym_EVP_PKEY_fromdata_init(kctx) <= 0)
return log_openssl_errors(LOG_DEBUG, "Failed to initialize EC key creation");
_cleanup_(BN_CTX_freep) BN_CTX *bctx = sym_BN_CTX_new();
if (!bctx)
return -ENOMEM;
if (sym_EC_POINT_oct2point(ec_group, p, key->iov_base, key->iov_len, bctx) <= 0)
return log_openssl_errors(LOG_DEBUG, "Failed to parse EC public key point");
_cleanup_(EC_KEY_freep) EC_KEY *eckey = sym_EC_KEY_new();
if (!eckey)
return -ENOMEM;
if (sym_EC_KEY_set_group(eckey, ec_group) <= 0)
return log_openssl_errors(LOG_DEBUG, "Failed to set EC group");
if (sym_EC_KEY_set_public_key(eckey, p) <= 0)
return log_openssl_errors(LOG_DEBUG, "EC_KEY_set_public_key failed");
if (sym_EC_KEY_check_key(eckey) <= 0)
return log_openssl_errors(LOG_DEBUG, "EC_KEY_check_key failed");
_cleanup_(EVP_PKEY_freep) EVP_PKEY *epubkey = NULL;
if (sym_EVP_PKEY_fromdata(kctx, &epubkey, EVP_PKEY_PUBLIC_KEY, params) <= 0)
return log_openssl_errors(LOG_DEBUG, "Failed to load EC public key from raw data");
_cleanup_(BN_freep) BIGNUM *bn_r = sym_BN_bin2bn(signature_r->iov_base, signature_r->iov_len, NULL);
if (!bn_r)
@@ -258,8 +249,6 @@ int dnssec_ecdsa_verify_raw(
if (!bn_s)
return log_openssl_errors(LOG_DEBUG, "Failed to convert ECDSA signature s to BIGNUM");
/* TODO: We should eventually use the EVP API once it supports ECDSA signature verification */
_cleanup_(ECDSA_SIG_freep) ECDSA_SIG *sig = sym_ECDSA_SIG_new();
if (!sig)
return -ENOMEM;
@@ -269,15 +258,30 @@ int dnssec_ecdsa_verify_raw(
TAKE_PTR(bn_r);
TAKE_PTR(bn_s);
r = sym_ECDSA_do_verify(hash->iov_base, hash->iov_len, sig, eckey);
_cleanup_(OPENSSL_freep) void *buf = NULL;
r = sym_i2d_ECDSA_SIG(sig, (unsigned char**) &buf);
if (r <= 0)
return log_openssl_errors(LOG_DEBUG, "Failed to DER encode ECDSA signature");
struct iovec der_sig = IOVEC_MAKE(buf, r);
_cleanup_(EVP_PKEY_CTX_freep) EVP_PKEY_CTX *vctx = sym_EVP_PKEY_CTX_new(epubkey, NULL);
if (!vctx)
return -ENOMEM;
if (sym_EVP_PKEY_public_check(vctx) <= 0)
return log_openssl_errors(LOG_DEBUG, "EC public key validation failed");
if (sym_EVP_PKEY_verify_init(vctx) <= 0)
return log_openssl_errors(LOG_DEBUG, "Failed to initialize ECDSA signature verification");
if (sym_EVP_PKEY_CTX_set_signature_md(vctx, hash_algorithm) <= 0)
return log_openssl_errors(LOG_DEBUG, "Failed to set ECDSA signature digest");
r = sym_EVP_PKEY_verify(vctx, der_sig.iov_base, der_sig.iov_len, hash->iov_base, hash->iov_len);
if (r < 0)
return log_openssl_errors(LOG_DEBUG, "Signature verification failed");
REENABLE_WARNING;
return r;
#else
return -EOPNOTSUPP;
#endif
}
static int dnssec_ecdsa_verify(
-4
View File
@@ -342,7 +342,6 @@ TEST(generate_ecdsa_test_vectors) {
-expected);
TEST(dnssec_ecdsa_verify_raw) {
#if !defined(OPENSSL_NO_DEPRECATED_3_0)
uint8_t *p;
/* Normal verification */
@@ -391,9 +390,6 @@ TEST(dnssec_ecdsa_verify_raw) {
p[bad_key.iov_len - 1] ^= 0x01;
bad_key.iov_len -= 1;
TEST_ECDSA_VERIFY(test_ecdsa_r, test_ecdsa_s, test_digest, bad_key, -ENOTRECOVERABLE);
#else
TEST_ECDSA_VERIFY(test_ecdsa_r, test_ecdsa_s, test_digest, test_ecdsa_key, -EOPNOTSUPP);
#endif
}
static int intro(void) {