Skip to content

Commit c89f4e6

Browse files
authored
Merge pull request #848 from rhenium/ky/pkey-disallow-empty-init
pkey: disallow {DH,DSA,EC,RSA}.new without arguments on OpenSSL 3.0
2 parents 4b923b4 + affd569 commit c89f4e6

File tree

11 files changed

+82
-27
lines changed

11 files changed

+82
-27
lines changed

ext/openssl/ossl.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,10 @@
7474
# include <openssl/provider.h>
7575
#endif
7676

77+
#if OSSL_OPENSSL_PREREQ(3, 0, 0)
78+
# define OSSL_HAVE_IMMUTABLE_PKEY
79+
#endif
80+
7781
/*
7882
* Common Module
7983
*/

ext/openssl/ossl_pkey.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -508,7 +508,7 @@ ossl_pkey_s_generate_key(int argc, VALUE *argv, VALUE self)
508508
void
509509
ossl_pkey_check_public_key(const EVP_PKEY *pkey)
510510
{
511-
#if OSSL_OPENSSL_PREREQ(3, 0, 0)
511+
#ifdef OSSL_HAVE_IMMUTABLE_PKEY
512512
if (EVP_PKEY_missing_parameters(pkey))
513513
ossl_raise(ePKeyError, "parameters missing");
514514
#else

ext/openssl/ossl_pkey.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ static VALUE ossl_##_keytype##_get_##_name(VALUE self) \
105105
OSSL_PKEY_BN_DEF_GETTER0(_keytype, _type, a2, \
106106
_type##_get0_##_group(obj, NULL, &bn))
107107

108-
#if !OSSL_OPENSSL_PREREQ(3, 0, 0)
108+
#ifndef OSSL_HAVE_IMMUTABLE_PKEY
109109
#define OSSL_PKEY_BN_DEF_SETTER3(_keytype, _type, _group, a1, a2, a3) \
110110
/* \
111111
* call-seq: \

ext/openssl/ossl_pkey_dh.c

Lines changed: 9 additions & 2 deletions
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 not compatible with 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.
@@ -58,14 +59,15 @@ static VALUE eDHError;
5859
*
5960
* Examples:
6061
* # Creating an instance from scratch
61-
* # Note that this is deprecated and will not work on OpenSSL 3.0 or later.
62+
* # Note that this is deprecated and will result in ArgumentError when
63+
* # using OpenSSL 3.0 or later.
6264
* dh = OpenSSL::PKey::DH.new
6365
* dh.set_pqg(bn_p, nil, bn_g)
6466
*
6567
* # Generating a parameters and a key pair
6668
* dh = OpenSSL::PKey::DH.new(2048) # An alias of OpenSSL::PKey::DH.generate(2048)
6769
*
68-
* # Reading DH parameters
70+
* # Reading DH parameters from a PEM-encoded string
6971
* dh_params = OpenSSL::PKey::DH.new(File.read('parameters.pem')) # loads parameters only
7072
* dh = OpenSSL::PKey.generate_key(dh_params) # generates a key pair
7173
*/
@@ -84,10 +86,15 @@ ossl_dh_initialize(int argc, VALUE *argv, VALUE self)
8486

8587
/* The DH.new(size, generator) form is handled by lib/openssl/pkey.rb */
8688
if (rb_scan_args(argc, argv, "01", &arg) == 0) {
89+
#ifdef OSSL_HAVE_IMMUTABLE_PKEY
90+
rb_raise(rb_eArgError, "OpenSSL::PKey::DH.new cannot be called " \
91+
"without arguments; pkeys are immutable with OpenSSL 3.0");
92+
#else
8793
dh = DH_new();
8894
if (!dh)
8995
ossl_raise(eDHError, "DH_new");
9096
goto legacy;
97+
#endif
9198
}
9299

93100
arg = ossl_to_der_if_possible(arg);

ext/openssl/ossl_pkey_dsa.c

Lines changed: 6 additions & 0 deletions
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 not compatible with 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 cannot be called " \
102+
"without arguments; pkeys are immutable with OpenSSL 3.0");
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

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -147,9 +147,14 @@ static VALUE ossl_ec_key_initialize(int argc, VALUE *argv, VALUE self)
147147

148148
rb_scan_args(argc, argv, "02", &arg, &pass);
149149
if (NIL_P(arg)) {
150+
#ifdef OSSL_HAVE_IMMUTABLE_PKEY
151+
rb_raise(rb_eArgError, "OpenSSL::PKey::EC.new cannot be called " \
152+
"without arguments; pkeys are immutable with OpenSSL 3.0");
153+
#else
150154
if (!(ec = EC_KEY_new()))
151155
ossl_raise(eECError, "EC_KEY_new");
152156
goto legacy;
157+
#endif
153158
}
154159
else if (rb_obj_is_kind_of(arg, cEC_GROUP)) {
155160
ec = ec_key_new_from_group(arg);
@@ -246,7 +251,7 @@ ossl_ec_key_get_group(VALUE self)
246251
static VALUE
247252
ossl_ec_key_set_group(VALUE self, VALUE group_v)
248253
{
249-
#if OSSL_OPENSSL_PREREQ(3, 0, 0)
254+
#ifdef OSSL_HAVE_IMMUTABLE_PKEY
250255
rb_raise(ePKeyError, "pkeys are immutable on OpenSSL 3.0");
251256
#else
252257
EC_KEY *ec;
@@ -288,7 +293,7 @@ static VALUE ossl_ec_key_get_private_key(VALUE self)
288293
*/
289294
static VALUE ossl_ec_key_set_private_key(VALUE self, VALUE private_key)
290295
{
291-
#if OSSL_OPENSSL_PREREQ(3, 0, 0)
296+
#ifdef OSSL_HAVE_IMMUTABLE_PKEY
292297
rb_raise(ePKeyError, "pkeys are immutable on OpenSSL 3.0");
293298
#else
294299
EC_KEY *ec;
@@ -339,7 +344,7 @@ static VALUE ossl_ec_key_get_public_key(VALUE self)
339344
*/
340345
static VALUE ossl_ec_key_set_public_key(VALUE self, VALUE public_key)
341346
{
342-
#if OSSL_OPENSSL_PREREQ(3, 0, 0)
347+
#ifdef OSSL_HAVE_IMMUTABLE_PKEY
343348
rb_raise(ePKeyError, "pkeys are immutable on OpenSSL 3.0");
344349
#else
345350
EC_KEY *ec;
@@ -511,7 +516,7 @@ ossl_ec_key_to_der(VALUE self)
511516
*/
512517
static VALUE ossl_ec_key_generate_key(VALUE self)
513518
{
514-
#if OSSL_OPENSSL_PREREQ(3, 0, 0)
519+
#ifdef OSSL_HAVE_IMMUTABLE_PKEY
515520
rb_raise(ePKeyError, "pkeys are immutable on OpenSSL 3.0");
516521
#else
517522
EC_KEY *ec;
@@ -1368,7 +1373,7 @@ static VALUE ossl_ec_point_make_affine(VALUE self)
13681373
GetECPointGroup(self, group);
13691374

13701375
rb_warn("OpenSSL::PKey::EC::Point#make_affine! is deprecated");
1371-
#if !OSSL_OPENSSL_PREREQ(3, 0, 0) && !defined(OPENSSL_IS_AWSLC)
1376+
#if !defined(OSSL_HAVE_IMMUTABLE_PKEY) && !defined(OPENSSL_IS_AWSLC)
13721377
if (EC_POINT_make_affine(group, point, ossl_bn_ctx) != 1)
13731378
ossl_raise(eEC_POINT, "EC_POINT_make_affine");
13741379
#endif

ext/openssl/ossl_pkey_rsa.c

Lines changed: 6 additions & 0 deletions
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 not compatible with 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 cannot be called " \
95+
"without arguments; pkeys are immutable with OpenSSL 3.0");
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

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,14 @@ class OpenSSL::TestPKeyDH < OpenSSL::PKeyTestCase
77
NEW_KEYLEN = 2048
88

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

1520
def test_new_generate

test/openssl/test_pkey_dsa.rb

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,14 @@ def test_new_break
3434
end
3535

3636
def test_new_empty
37-
key = OpenSSL::PKey::DSA.new
38-
assert_nil(key.p)
39-
assert_raise(OpenSSL::PKey::PKeyError) { key.to_der }
37+
# pkeys are immutable with OpenSSL >= 3.0
38+
if openssl?(3, 0, 0)
39+
assert_raise(ArgumentError) { OpenSSL::PKey::DSA.new }
40+
else
41+
key = OpenSSL::PKey::DSA.new
42+
assert_nil(key.p)
43+
assert_raise(OpenSSL::PKey::PKeyError) { key.to_der }
44+
end
4045
end
4146

4247
def test_generate

test/openssl/test_pkey_ec.rb

Lines changed: 18 additions & 11 deletions
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,23 @@ def test_ec_key
3525
end
3626
end
3727

28+
def test_ec_key_new_empty
29+
# pkeys are immutable with 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+
else
34+
key = OpenSSL::PKey::EC.new
35+
assert_nil(key.group)
36+
37+
p256 = Fixtures.pkey("p256")
38+
key.group = p256.group
39+
key.private_key = p256.private_key
40+
key.public_key = p256.public_key
41+
assert_equal(p256.to_der, key.to_der)
42+
end
43+
end
44+
3845
def test_builtin_curves
3946
builtin_curves = OpenSSL::PKey::EC.builtin_curves
4047
assert_not_empty builtin_curves

0 commit comments

Comments
 (0)