Skip to content

Commit 43aa5ca

Browse files
committed
pkey: disallow {DH,DSA,EC,RSA}.new without arguments on OpenSSL 3.0
When OpenSSL::PKey::{DH,DSA,EC,RSA}.new is called without any arguments, it sets up an empty corresponding low-level struct and wraps it in an EVP_PKEY. This form has been supported so that users can fill the fields later using low-level setter methods such as OpenSSL::PKey::RSA#set_key. Such setter methods are not compatible with OpenSSL 3.0 or later, where pkeys are immutable once created. This means that the ability to create an empty instance is useless. Let's remove it and raise ArgumentError if attempted.
1 parent 09edb69 commit 43aa5ca

File tree

8 files changed

+68
-13
lines changed

8 files changed

+68
-13
lines changed

ext/openssl/ossl_pkey_dh.c

+6
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ static VALUE eDHError;
4343
* If called without arguments, an empty instance without any parameter or key
4444
* components is created. Use #set_pqg to manually set the parameters afterwards
4545
* (and optionally #set_key to set private and public key components).
46+
* This form is deprecated and will not work on OpenSSL 3.0 or later.
4647
*
4748
* If a String is given, tries to parse it as a DER- or PEM- encoded parameters.
4849
* See also OpenSSL::PKey.read which can parse keys of any kinds.
@@ -84,10 +85,15 @@ ossl_dh_initialize(int argc, VALUE *argv, VALUE self)
8485

8586
/* The DH.new(size, generator) form is handled by lib/openssl/pkey.rb */
8687
if (rb_scan_args(argc, argv, "01", &arg) == 0) {
88+
#ifdef OSSL_HAVE_IMMUTABLE_PKEY
89+
rb_raise(rb_eArgError, "OpenSSL::PKey::DH.new without arguments is " \
90+
"not supported in this version of OpenSSL");
91+
#else
8792
dh = DH_new();
8893
if (!dh)
8994
ossl_raise(eDHError, "DH_new");
9095
goto legacy;
96+
#endif
9197
}
9298

9399
arg = ossl_to_der_if_possible(arg);

ext/openssl/ossl_pkey_dsa.c

+6
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ static VALUE eDSAError;
5656
*
5757
* If called without arguments, creates a new instance with no key components
5858
* set. They can be set individually by #set_pqg and #set_key.
59+
* This form is deprecated and will not work on OpenSSL 3.0 or later.
5960
*
6061
* If called with a String, tries to parse as DER or PEM encoding of a \DSA key.
6162
* See also OpenSSL::PKey.read which can parse keys of any kinds.
@@ -96,10 +97,15 @@ ossl_dsa_initialize(int argc, VALUE *argv, VALUE self)
9697
/* The DSA.new(size, generator) form is handled by lib/openssl/pkey.rb */
9798
rb_scan_args(argc, argv, "02", &arg, &pass);
9899
if (argc == 0) {
100+
#ifdef OSSL_HAVE_IMMUTABLE_PKEY
101+
rb_raise(rb_eArgError, "OpenSSL::PKey::DSA.new without arguments is " \
102+
"not supported in this version of OpenSSL");
103+
#else
99104
dsa = DSA_new();
100105
if (!dsa)
101106
ossl_raise(eDSAError, "DSA_new");
102107
goto legacy;
108+
#endif
103109
}
104110

105111
pass = ossl_pem_passwd_value(pass);

ext/openssl/ossl_pkey_ec.c

+5
Original file line numberDiff line numberDiff line change
@@ -150,9 +150,14 @@ static VALUE ossl_ec_key_initialize(int argc, VALUE *argv, VALUE self)
150150

151151
rb_scan_args(argc, argv, "02", &arg, &pass);
152152
if (NIL_P(arg)) {
153+
#ifdef OSSL_HAVE_IMMUTABLE_PKEY
154+
rb_raise(rb_eArgError, "OpenSSL::PKey::EC.new without arguments is " \
155+
"not supported in this version of OpenSSL");
156+
#else
153157
if (!(ec = EC_KEY_new()))
154158
ossl_raise(eECError, "EC_KEY_new");
155159
goto legacy;
160+
#endif
156161
}
157162
else if (rb_obj_is_kind_of(arg, cEC_GROUP)) {
158163
ec = ec_key_new_from_group(arg);

ext/openssl/ossl_pkey_rsa.c

+6
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ static VALUE eRSAError;
5959
* If called without arguments, creates a new instance with no key components
6060
* set. They can be set individually by #set_key, #set_factors, and
6161
* #set_crt_params.
62+
* This form is deprecated and will not work on OpenSSL 3.0 or later.
6263
*
6364
* If called with a String, tries to parse as DER or PEM encoding of an \RSA key.
6465
* Note that if _password_ is not specified, but the key is encrypted with a
@@ -89,10 +90,15 @@ ossl_rsa_initialize(int argc, VALUE *argv, VALUE self)
8990
/* The RSA.new(size, generator) form is handled by lib/openssl/pkey.rb */
9091
rb_scan_args(argc, argv, "02", &arg, &pass);
9192
if (argc == 0) {
93+
#ifdef OSSL_HAVE_IMMUTABLE_PKEY
94+
rb_raise(rb_eArgError, "OpenSSL::PKey::RSA.new without arguments is " \
95+
"not supported in this version of OpenSSL");
96+
#else
9297
rsa = RSA_new();
9398
if (!rsa)
9499
ossl_raise(eRSAError, "RSA_new");
95100
goto legacy;
101+
#endif
96102
}
97103

98104
pass = ossl_pem_passwd_value(pass);

test/openssl/test_pkey_dh.rb

+8-2
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,15 @@ class OpenSSL::TestPKeyDH < OpenSSL::PKeyTestCase
77
NEW_KEYLEN = 2048
88

99
def test_new_empty
10+
# pkeys are immutable in OpenSSL >= 3.0
11+
if openssl?(3, 0, 0)
12+
assert_raise(ArgumentError) { OpenSSL::PKey::DH.new }
13+
return
14+
end
15+
1016
dh = OpenSSL::PKey::DH.new
11-
assert_equal nil, dh.p
12-
assert_equal nil, dh.priv_key
17+
assert_nil(dh.p)
18+
assert_nil(dh.priv_key)
1319
end
1420

1521
def test_new_generate

test/openssl/test_pkey_dsa.rb

+5
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,11 @@ def test_new_break
3434
end
3535

3636
def test_new_empty
37+
# pkeys are immutable in OpenSSL >= 3.0
38+
if openssl?(3, 0, 0)
39+
assert_raise(ArgumentError) { OpenSSL::PKey::DSA.new }
40+
return
41+
end
3742
key = OpenSSL::PKey::DSA.new
3843
assert_nil(key.p)
3944
assert_raise(OpenSSL::PKey::PKeyError) { key.to_der }

test/openssl/test_pkey_ec.rb

+19-11
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,9 @@
44
if defined?(OpenSSL)
55

66
class OpenSSL::TestEC < OpenSSL::PKeyTestCase
7-
def test_ec_key
7+
def test_ec_key_new
88
key1 = OpenSSL::PKey::EC.generate("prime256v1")
99

10-
# PKey is immutable in OpenSSL >= 3.0; constructing an empty EC object is
11-
# deprecated
12-
if !openssl?(3, 0, 0)
13-
key2 = OpenSSL::PKey::EC.new
14-
key2.group = key1.group
15-
key2.private_key = key1.private_key
16-
key2.public_key = key1.public_key
17-
assert_equal key1.to_der, key2.to_der
18-
end
19-
2010
key3 = OpenSSL::PKey::EC.new(key1)
2111
assert_equal key1.to_der, key3.to_der
2212

@@ -35,6 +25,24 @@ def test_ec_key
3525
end
3626
end
3727

28+
def test_ec_key_new_empty
29+
# pkeys are immutable in OpenSSL >= 3.0; constructing an empty EC object is
30+
# disallowed
31+
if openssl?(3, 0, 0)
32+
assert_raise(ArgumentError) { OpenSSL::PKey::EC.new }
33+
return
34+
end
35+
36+
key = OpenSSL::PKey::EC.new
37+
assert_nil(key.group)
38+
39+
p256 = Fixtures.pkey("p256")
40+
key.group = p256.group
41+
key.private_key = p256.private_key
42+
key.public_key = p256.public_key
43+
assert_equal(p256.to_der, key.to_der)
44+
end
45+
3846
def test_builtin_curves
3947
builtin_curves = OpenSSL::PKey::EC.builtin_curves
4048
assert_not_empty builtin_curves

test/openssl/test_pkey_rsa.rb

+13
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,17 @@ def test_new_public_exponent
6161
assert_equal 3, key.e
6262
end
6363

64+
def test_new_empty
65+
# pkeys are immutable in OpenSSL >= 3.0
66+
if openssl?(3, 0, 0)
67+
assert_raise(ArgumentError) { OpenSSL::PKey::RSA.new }
68+
return
69+
end
70+
71+
key = OpenSSL::PKey::RSA.new
72+
assert_nil(key.n)
73+
end
74+
6475
def test_s_generate
6576
key1 = OpenSSL::PKey::RSA.generate(2048)
6677
assert_equal 2048, key1.n.num_bits
@@ -177,6 +188,8 @@ def test_sign_verify_raw_legacy
177188

178189

179190
def test_verify_empty_rsa
191+
# pkeys are immutable in OpenSSL >= 3.0; empty RSA instance is disallowed
192+
return if openssl?(3, 0, 0)
180193
rsa = OpenSSL::PKey::RSA.new
181194
assert_raise(OpenSSL::PKey::PKeyError, "[Bug #12783]") {
182195
rsa.verify("SHA1", "a", "b")

0 commit comments

Comments
 (0)