Skip to content

Commit e38a63a

Browse files
bannablerhenium
authored andcommitted
pkey/ec: check private key validity with OpenSSL 3
The behavior of EVP_PKEY_public_check changed between OpenSSL 1.1.1 and 3.0 so that it no longer validates the private key. Instead, private keys can be validated through EVP_PKEY_private_check and EVP_PKEY_pairwise_check. [ky: simplified condition to use either EVP_PKEY_check() or EVP_PKEY_public_check().]
1 parent e5bbd01 commit e38a63a

File tree

4 files changed

+35
-5
lines changed

4 files changed

+35
-5
lines changed

ext/openssl/ossl_pkey_ec.c

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -483,16 +483,28 @@ static VALUE ossl_ec_key_check_key(VALUE self)
483483
#ifdef HAVE_EVP_PKEY_CHECK
484484
EVP_PKEY *pkey;
485485
EVP_PKEY_CTX *pctx;
486-
int ret;
486+
EC_KEY *ec;
487487

488488
GetPKey(self, pkey);
489+
GetEC(self, ec);
489490
pctx = EVP_PKEY_CTX_new(pkey, /* engine */NULL);
490491
if (!pctx)
491-
ossl_raise(eDHError, "EVP_PKEY_CTX_new");
492-
ret = EVP_PKEY_public_check(pctx);
492+
ossl_raise(eECError, "EVP_PKEY_CTX_new");
493+
494+
if (EC_KEY_get0_private_key(ec) != NULL) {
495+
if (EVP_PKEY_check(pctx) != 1) {
496+
EVP_PKEY_CTX_free(pctx);
497+
ossl_raise(eECError, "EVP_PKEY_check");
498+
}
499+
}
500+
else {
501+
if (EVP_PKEY_public_check(pctx) != 1) {
502+
EVP_PKEY_CTX_free(pctx);
503+
ossl_raise(eECError, "EVP_PKEY_public_check");
504+
}
505+
}
506+
493507
EVP_PKEY_CTX_free(pctx);
494-
if (ret != 1)
495-
ossl_raise(eECError, "EVP_PKEY_public_check");
496508
#else
497509
EC_KEY *ec;
498510

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
-----BEGIN EC PRIVATE KEY-----
2+
MHcCAQEEIP+TT0V8Fndsnacji9tyf6hmhHywcOWTee9XkiBeJoVloAoGCCqGSM49
3+
AwEHoUQDQgAEBkhhJIU/2/YdPSlY2I1k25xjK4trr5OXSgXvBC21PtY0HQ7lor7A
4+
jzT0giJITqmcd81fwGw5+96zLcdxTF1hVQ==
5+
-----END EC PRIVATE KEY-----
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
-----BEGIN EC PRIVATE KEY-----
2+
MIGkAgEBBDDA1Tm0m7YhkfeVpFuarAJYVlHp2tQj+1fOBiLa10t9E8TiQO/hVfxB
3+
vGaVEQwOheWgBwYFK4EEACKhZANiAASyGqmryZGqdpsq5gEDIfNvgC3AwSJxiBCL
4+
XKHBTFRp+tCezLDOK/6V8KK/vVGBJlGFW6/I7ahyXprxS7xs7hPA9iz5YiuqXlu+
5+
lbrIpZOz7b73hyQQCkvbBO/Avg+hPAk=
6+
-----END EC PRIVATE KEY-----

test/openssl/test_pkey_ec.rb

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,13 @@ def test_check_key
9090
assert_equal(true, key2.public?)
9191
assert_equal(true, key2.check_key)
9292

93+
# Behavior of EVP_PKEY_public_check changes between OpenSSL 1.1.1 and 3.0
94+
key4 = Fixtures.pkey("p256_too_large")
95+
assert_raise(OpenSSL::PKey::ECError) { key4.check_key }
96+
97+
key5 = Fixtures.pkey("p384_invalid")
98+
assert_raise(OpenSSL::PKey::ECError) { key5.check_key }
99+
93100
# EC#private_key= is deprecated in 3.0 and won't work on OpenSSL 3.0
94101
if !openssl?(3, 0, 0)
95102
key2.private_key += 1

0 commit comments

Comments
 (0)