Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions ext/openssl/ossl.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@
# include <openssl/provider.h>
#endif

#if OSSL_OPENSSL_PREREQ(3, 0, 0)
# define OSSL_HAVE_IMMUTABLE_PKEY
#endif

/*
* Common Module
*/
Expand Down
2 changes: 1 addition & 1 deletion ext/openssl/ossl_pkey.c
Original file line number Diff line number Diff line change
Expand Up @@ -508,7 +508,7 @@ ossl_pkey_s_generate_key(int argc, VALUE *argv, VALUE self)
void
ossl_pkey_check_public_key(const EVP_PKEY *pkey)
{
#if OSSL_OPENSSL_PREREQ(3, 0, 0)
#ifdef OSSL_HAVE_IMMUTABLE_PKEY
if (EVP_PKEY_missing_parameters(pkey))
ossl_raise(ePKeyError, "parameters missing");
#else
Expand Down
2 changes: 1 addition & 1 deletion ext/openssl/ossl_pkey.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ static VALUE ossl_##_keytype##_get_##_name(VALUE self) \
OSSL_PKEY_BN_DEF_GETTER0(_keytype, _type, a2, \
_type##_get0_##_group(obj, NULL, &bn))

#if !OSSL_OPENSSL_PREREQ(3, 0, 0)
#ifndef OSSL_HAVE_IMMUTABLE_PKEY
#define OSSL_PKEY_BN_DEF_SETTER3(_keytype, _type, _group, a1, a2, a3) \
/* \
* call-seq: \
Expand Down
11 changes: 9 additions & 2 deletions ext/openssl/ossl_pkey_dh.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ static VALUE eDHError;
* If called without arguments, an empty instance without any parameter or key
* components is created. Use #set_pqg to manually set the parameters afterwards
* (and optionally #set_key to set private and public key components).
* This form is not compatible with OpenSSL 3.0 or later.
*
* If a String is given, tries to parse it as a DER- or PEM- encoded parameters.
* See also OpenSSL::PKey.read which can parse keys of any kinds.
Expand All @@ -58,14 +59,15 @@ static VALUE eDHError;
*
* Examples:
* # Creating an instance from scratch
* # Note that this is deprecated and will not work on OpenSSL 3.0 or later.
* # Note that this is deprecated and will result in ArgumentError when
* # using OpenSSL 3.0 or later.
* dh = OpenSSL::PKey::DH.new
* dh.set_pqg(bn_p, nil, bn_g)
*
* # Generating a parameters and a key pair
* dh = OpenSSL::PKey::DH.new(2048) # An alias of OpenSSL::PKey::DH.generate(2048)
*
* # Reading DH parameters
* # Reading DH parameters from a PEM-encoded string
* dh_params = OpenSSL::PKey::DH.new(File.read('parameters.pem')) # loads parameters only
* dh = OpenSSL::PKey.generate_key(dh_params) # generates a key pair
*/
Expand All @@ -84,10 +86,15 @@ ossl_dh_initialize(int argc, VALUE *argv, VALUE self)

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

arg = ossl_to_der_if_possible(arg);
Expand Down
6 changes: 6 additions & 0 deletions ext/openssl/ossl_pkey_dsa.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ static VALUE eDSAError;
*
* If called without arguments, creates a new instance with no key components
* set. They can be set individually by #set_pqg and #set_key.
* This form is not compatible with OpenSSL 3.0 or later.
*
* If called with a String, tries to parse as DER or PEM encoding of a \DSA key.
* See also OpenSSL::PKey.read which can parse keys of any kinds.
Expand Down Expand Up @@ -96,10 +97,15 @@ ossl_dsa_initialize(int argc, VALUE *argv, VALUE self)
/* The DSA.new(size, generator) form is handled by lib/openssl/pkey.rb */
rb_scan_args(argc, argv, "02", &arg, &pass);
if (argc == 0) {
#ifdef OSSL_HAVE_IMMUTABLE_PKEY
rb_raise(rb_eArgError, "OpenSSL::PKey::DSA.new cannot be called " \
"without arguments; pkeys are immutable with OpenSSL 3.0");
#else
dsa = DSA_new();
if (!dsa)
ossl_raise(eDSAError, "DSA_new");
goto legacy;
#endif
}

pass = ossl_pem_passwd_value(pass);
Expand Down
15 changes: 10 additions & 5 deletions ext/openssl/ossl_pkey_ec.c
Original file line number Diff line number Diff line change
Expand Up @@ -147,9 +147,14 @@ static VALUE ossl_ec_key_initialize(int argc, VALUE *argv, VALUE self)

rb_scan_args(argc, argv, "02", &arg, &pass);
if (NIL_P(arg)) {
#ifdef OSSL_HAVE_IMMUTABLE_PKEY
rb_raise(rb_eArgError, "OpenSSL::PKey::EC.new cannot be called " \
"without arguments; pkeys are immutable with OpenSSL 3.0");
#else
if (!(ec = EC_KEY_new()))
ossl_raise(eECError, "EC_KEY_new");
goto legacy;
#endif
}
else if (rb_obj_is_kind_of(arg, cEC_GROUP)) {
ec = ec_key_new_from_group(arg);
Expand Down Expand Up @@ -246,7 +251,7 @@ ossl_ec_key_get_group(VALUE self)
static VALUE
ossl_ec_key_set_group(VALUE self, VALUE group_v)
{
#if OSSL_OPENSSL_PREREQ(3, 0, 0)
#ifdef OSSL_HAVE_IMMUTABLE_PKEY
rb_raise(ePKeyError, "pkeys are immutable on OpenSSL 3.0");
#else
EC_KEY *ec;
Expand Down Expand Up @@ -288,7 +293,7 @@ static VALUE ossl_ec_key_get_private_key(VALUE self)
*/
static VALUE ossl_ec_key_set_private_key(VALUE self, VALUE private_key)
{
#if OSSL_OPENSSL_PREREQ(3, 0, 0)
#ifdef OSSL_HAVE_IMMUTABLE_PKEY
rb_raise(ePKeyError, "pkeys are immutable on OpenSSL 3.0");
#else
EC_KEY *ec;
Expand Down Expand Up @@ -339,7 +344,7 @@ static VALUE ossl_ec_key_get_public_key(VALUE self)
*/
static VALUE ossl_ec_key_set_public_key(VALUE self, VALUE public_key)
{
#if OSSL_OPENSSL_PREREQ(3, 0, 0)
#ifdef OSSL_HAVE_IMMUTABLE_PKEY
rb_raise(ePKeyError, "pkeys are immutable on OpenSSL 3.0");
#else
EC_KEY *ec;
Expand Down Expand Up @@ -511,7 +516,7 @@ ossl_ec_key_to_der(VALUE self)
*/
static VALUE ossl_ec_key_generate_key(VALUE self)
{
#if OSSL_OPENSSL_PREREQ(3, 0, 0)
#ifdef OSSL_HAVE_IMMUTABLE_PKEY
rb_raise(ePKeyError, "pkeys are immutable on OpenSSL 3.0");
#else
EC_KEY *ec;
Expand Down Expand Up @@ -1368,7 +1373,7 @@ static VALUE ossl_ec_point_make_affine(VALUE self)
GetECPointGroup(self, group);

rb_warn("OpenSSL::PKey::EC::Point#make_affine! is deprecated");
#if !OSSL_OPENSSL_PREREQ(3, 0, 0) && !defined(OPENSSL_IS_AWSLC)
#if !defined(OSSL_HAVE_IMMUTABLE_PKEY) && !defined(OPENSSL_IS_AWSLC)
if (EC_POINT_make_affine(group, point, ossl_bn_ctx) != 1)
ossl_raise(eEC_POINT, "EC_POINT_make_affine");
#endif
Expand Down
6 changes: 6 additions & 0 deletions ext/openssl/ossl_pkey_rsa.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ static VALUE eRSAError;
* If called without arguments, creates a new instance with no key components
* set. They can be set individually by #set_key, #set_factors, and
* #set_crt_params.
* This form is not compatible with OpenSSL 3.0 or later.
*
* If called with a String, tries to parse as DER or PEM encoding of an \RSA key.
* Note that if _password_ is not specified, but the key is encrypted with a
Expand Down Expand Up @@ -89,10 +90,15 @@ ossl_rsa_initialize(int argc, VALUE *argv, VALUE self)
/* The RSA.new(size, generator) form is handled by lib/openssl/pkey.rb */
rb_scan_args(argc, argv, "02", &arg, &pass);
if (argc == 0) {
#ifdef OSSL_HAVE_IMMUTABLE_PKEY
rb_raise(rb_eArgError, "OpenSSL::PKey::RSA.new cannot be called " \
"without arguments; pkeys are immutable with OpenSSL 3.0");
#else
rsa = RSA_new();
if (!rsa)
ossl_raise(eRSAError, "RSA_new");
goto legacy;
#endif
}

pass = ossl_pem_passwd_value(pass);
Expand Down
4 changes: 2 additions & 2 deletions gems/bundled_gems
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,15 @@ minitest 5.25.5 https://github.com/minitest/minitest
power_assert 2.0.5 https://github.com/ruby/power_assert f88e406e7c9e0810cc149869582afbae1fb84c4a
rake 13.3.0 https://github.com/ruby/rake
test-unit 3.7.0 https://github.com/test-unit/test-unit
rexml 3.4.2 https://github.com/ruby/rexml
rexml 3.4.4 https://github.com/ruby/rexml
rss 0.3.1 https://github.com/ruby/rss
net-ftp 0.3.8 https://github.com/ruby/net-ftp
net-imap 0.5.10 https://github.com/ruby/net-imap 71c0288b9a8f78a7125a4ce2980ab421acdf5836
net-pop 0.1.2 https://github.com/ruby/net-pop
net-smtp 0.5.1 https://github.com/ruby/net-smtp
matrix 0.4.3 https://github.com/ruby/matrix
prime 0.1.4 https://github.com/ruby/prime
rbs 3.9.4 https://github.com/ruby/rbs aa22d7ea0c992de7557c3e346c9100b8aa36d945
rbs 3.9.5 https://github.com/ruby/rbs
typeprof 0.30.1 https://github.com/ruby/typeprof
debug 1.11.0 https://github.com/ruby/debug
racc 1.8.1 https://github.com/ruby/racc
Expand Down
79 changes: 48 additions & 31 deletions test/openssl/test_pkey_dh.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,31 +4,42 @@
if defined?(OpenSSL) && defined?(OpenSSL::PKey::DH)

class OpenSSL::TestPKeyDH < OpenSSL::PKeyTestCase
NEW_KEYLEN = 2048

def test_new_empty
dh = OpenSSL::PKey::DH.new
assert_equal nil, dh.p
assert_equal nil, dh.priv_key
# pkeys are immutable with OpenSSL >= 3.0
if openssl?(3, 0, 0)
assert_raise(ArgumentError) { OpenSSL::PKey::DH.new }
else
dh = OpenSSL::PKey::DH.new
assert_nil(dh.p)
assert_nil(dh.priv_key)
end
end

def test_new_generate
# This test is slow
dh = OpenSSL::PKey::DH.new(NEW_KEYLEN)
assert_key(dh)
begin
dh1 = OpenSSL::PKey::DH.new(512)
rescue OpenSSL::PKey::PKeyError
omit "generating 512-bit DH parameters failed; " \
"likely not supported by this OpenSSL build"
end
assert_equal(512, dh1.p.num_bits)
assert_key(dh1)

dh2 = OpenSSL::PKey::DH.generate(512)
assert_equal(512, dh2.p.num_bits)
assert_key(dh2)
assert_not_equal(dh1.p, dh2.p)
end if ENV["OSSL_TEST_ALL"] == "1"

def test_new_break
unless openssl? && OpenSSL.fips_mode
assert_nil(OpenSSL::PKey::DH.new(NEW_KEYLEN) { break })
assert_raise(RuntimeError) do
OpenSSL::PKey::DH.new(NEW_KEYLEN) { raise }
OpenSSL::PKey::DH.new(2048) { raise }
end
else
# The block argument is not executed in FIPS case.
# See https://github.com/ruby/openssl/issues/692 for details.
assert(OpenSSL::PKey::DH.new(NEW_KEYLEN) { break })
assert(OpenSSL::PKey::DH.new(NEW_KEYLEN) { raise })
assert_kind_of(OpenSSL::PKey::DH, OpenSSL::PKey::DH.new(2048) { raise })
end
end

Expand All @@ -51,15 +62,15 @@ def test_derive_key
end

def test_DHparams
dh = Fixtures.pkey("dh2048_ffdhe2048")
dh_params = dh.public_key
dh_params = Fixtures.pkey("dh2048_ffdhe2048")

asn1 = OpenSSL::ASN1::Sequence([
OpenSSL::ASN1::Integer(dh.p),
OpenSSL::ASN1::Integer(dh.g)
OpenSSL::ASN1::Integer(dh_params.p),
OpenSSL::ASN1::Integer(dh_params.g)
])
assert_equal(asn1.to_der, dh_params.to_der)
key = OpenSSL::PKey::DH.new(asn1.to_der)
assert_same_dh dh_params, key
assert_same_dh_params(dh_params, key)

pem = <<~EOF
-----BEGIN DH PARAMETERS-----
Expand All @@ -71,14 +82,20 @@ def test_DHparams
ssbzSibBsu/6iGtCOGEoXJf//////////wIBAg==
-----END DH PARAMETERS-----
EOF
assert_equal(pem, dh_params.export)

key = OpenSSL::PKey::DH.new(pem)
assert_same_dh dh_params, key
assert_same_dh_params(dh_params, key)
assert_no_key(key)
key = OpenSSL::PKey.read(pem)
assert_same_dh dh_params, key

assert_equal asn1.to_der, dh.to_der
assert_equal pem, dh.export
assert_same_dh_params(dh_params, key)
assert_no_key(key)

key = OpenSSL::PKey.generate_key(dh_params)
assert_same_dh_params(dh_params, key)
assert_key(key)
assert_equal(dh_params.to_der, key.to_der)
assert_equal(dh_params.to_pem, key.to_pem)
end

def test_public_key
Expand All @@ -91,14 +108,14 @@ def test_public_key

def test_generate_key
# Deprecated in v3.0.0; incompatible with OpenSSL 3.0
# Creates a copy with params only
dh = Fixtures.pkey("dh2048_ffdhe2048").public_key
dh = Fixtures.pkey("dh2048_ffdhe2048")
assert_no_key(dh)
dh.generate_key!
assert_key(dh)

dh2 = dh.public_key
dh2 = OpenSSL::PKey::DH.new(dh.to_der)
dh2.generate_key!
assert_not_equal(dh.pub_key, dh2.pub_key)
assert_equal(dh.compute_key(dh2.pub_key), dh2.compute_key(dh.pub_key))
end if !openssl?(3, 0, 0)

Expand Down Expand Up @@ -204,14 +221,14 @@ def assert_no_key(dh)
end

def assert_key(dh)
assert(dh.public?)
assert(dh.private?)
assert(dh.pub_key)
assert(dh.priv_key)
assert_true(dh.public?)
assert_true(dh.private?)
assert_kind_of(OpenSSL::BN, dh.pub_key)
assert_kind_of(OpenSSL::BN, dh.priv_key)
end

def assert_same_dh(expected, key)
check_component(expected, key, [:p, :q, :g, :pub_key, :priv_key])
def assert_same_dh_params(expected, key)
check_component(expected, key, [:p, :q, :g])
end
end

Expand Down
11 changes: 8 additions & 3 deletions test/openssl/test_pkey_dsa.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,14 @@ def test_new_break
end

def test_new_empty
key = OpenSSL::PKey::DSA.new
assert_nil(key.p)
assert_raise(OpenSSL::PKey::PKeyError) { key.to_der }
# pkeys are immutable with OpenSSL >= 3.0
if openssl?(3, 0, 0)
assert_raise(ArgumentError) { OpenSSL::PKey::DSA.new }
else
key = OpenSSL::PKey::DSA.new
assert_nil(key.p)
assert_raise(OpenSSL::PKey::PKeyError) { key.to_der }
end
end

def test_generate
Expand Down
Loading