[前][次][番号順一覧][スレッド一覧]

ruby-changes:70375

From: Kazuki <ko1@a...>
Date: Tue, 21 Dec 2021 00:11:39 +0900 (JST)
Subject: [ruby-changes:70375] 8ebf597885 (master): [ruby/openssl] pkey: deprecate PKey#set_* methods

https://git.ruby-lang.org/ruby.git/commit/?id=8ebf597885

From 8ebf5978852e22358cbcdf74c0eb506f22e2c73f Mon Sep 17 00:00:00 2001
From: Kazuki Yamaguchi <k@r...>
Date: Tue, 21 Sep 2021 18:29:59 +0900
Subject: [ruby/openssl] pkey: deprecate PKey#set_* methods

OpenSSL 3.0 made EVP_PKEY immutable. This means we can only have a const
pointer of the low level struct and the following methods can no longer
be provided when linked against OpenSSL 3.0:

 - OpenSSL::PKey::RSA#set_key
 - OpenSSL::PKey::RSA#set_factors
 - OpenSSL::PKey::RSA#set_crt_params
 - OpenSSL::PKey::DSA#set_pqg
 - OpenSSL::PKey::DSA#set_key
 - OpenSSL::PKey::DH#set_pqg
 - OpenSSL::PKey::DH#set_key
 - OpenSSL::PKey::EC#group=
 - OpenSSL::PKey::EC#private_key=
 - OpenSSL::PKey::EC#public_key=

There is no direct replacement for this functionality at the moment.
I plan to introduce a wrapper around EVP_PKEY_fromdata(), which takes
all key components at once to construct an EVP_PKEY.

https://github.com/ruby/openssl/commit/6848d2d969
---
 ext/openssl/ossl_pkey.h       | 16 ++++++++
 ext/openssl/ossl_pkey_ec.c    | 12 ++++++
 test/openssl/test_pkey_dh.rb  | 38 +++++++++++++------
 test/openssl/test_pkey_dsa.rb |  8 +++-
 test/openssl/test_pkey_ec.rb  | 58 +++++++++++++++++------------
 test/openssl/test_pkey_rsa.rb | 85 +++++++++++++++++++++++++++----------------
 6 files changed, 149 insertions(+), 68 deletions(-)

diff --git a/ext/openssl/ossl_pkey.h b/ext/openssl/ossl_pkey.h
index ed18bc69276..38fb9fad108 100644
--- a/ext/openssl/ossl_pkey.h
+++ b/ext/openssl/ossl_pkey.h
@@ -116,6 +116,7 @@ static VALUE ossl_##_keytype##_get_##_name(VALUE self)			\ https://github.com/ruby/ruby/blob/trunk/ext/openssl/ossl_pkey.h#L116
 	OSSL_PKEY_BN_DEF_GETTER0(_keytype, _type, a2,			\
 		_type##_get0_##_group(obj, NULL, &bn))
 
+#if !OSSL_OPENSSL_PREREQ(3, 0, 0)
 #define OSSL_PKEY_BN_DEF_SETTER3(_keytype, _type, _group, a1, a2, a3)	\
 /*									\
  *  call-seq:								\
@@ -173,6 +174,21 @@ static VALUE ossl_##_keytype##_set_##_group(VALUE self, VALUE v1, VALUE v2) \ https://github.com/ruby/ruby/blob/trunk/ext/openssl/ossl_pkey.h#L174
 	}								\
 	return self;							\
 }
+#else
+#define OSSL_PKEY_BN_DEF_SETTER3(_keytype, _type, _group, a1, a2, a3)	\
+static VALUE ossl_##_keytype##_set_##_group(VALUE self, VALUE v1, VALUE v2, VALUE v3) \
+{									\
+        rb_raise(ePKeyError,						\
+                 #_keytype"#set_"#_group"= is incompatible with OpenSSL 3.0"); \
+}
+
+#define OSSL_PKEY_BN_DEF_SETTER2(_keytype, _type, _group, a1, a2)	\
+static VALUE ossl_##_keytype##_set_##_group(VALUE self, VALUE v1, VALUE v2) \
+{									\
+        rb_raise(ePKeyError,						\
+                 #_keytype"#set_"#_group"= is incompatible with OpenSSL 3.0"); \
+}
+#endif
 
 #define OSSL_PKEY_BN_DEF3(_keytype, _type, _group, a1, a2, a3)		\
 	OSSL_PKEY_BN_DEF_GETTER3(_keytype, _type, _group, a1, a2, a3)	\
diff --git a/ext/openssl/ossl_pkey_ec.c b/ext/openssl/ossl_pkey_ec.c
index ff3150dac03..dee215447da 100644
--- a/ext/openssl/ossl_pkey_ec.c
+++ b/ext/openssl/ossl_pkey_ec.c
@@ -248,6 +248,9 @@ ossl_ec_key_get_group(VALUE self) https://github.com/ruby/ruby/blob/trunk/ext/openssl/ossl_pkey_ec.c#L248
 static VALUE
 ossl_ec_key_set_group(VALUE self, VALUE group_v)
 {
+#if OSSL_OPENSSL_PREREQ(3, 0, 0)
+    rb_raise(ePKeyError, "pkeys are immutable on OpenSSL 3.0");
+#else
     EC_KEY *ec;
     EC_GROUP *group;
 
@@ -258,6 +261,7 @@ ossl_ec_key_set_group(VALUE self, VALUE group_v) https://github.com/ruby/ruby/blob/trunk/ext/openssl/ossl_pkey_ec.c#L261
         ossl_raise(eECError, "EC_KEY_set_group");
 
     return group_v;
+#endif
 }
 
 /*
@@ -286,6 +290,9 @@ static VALUE ossl_ec_key_get_private_key(VALUE self) https://github.com/ruby/ruby/blob/trunk/ext/openssl/ossl_pkey_ec.c#L290
  */
 static VALUE ossl_ec_key_set_private_key(VALUE self, VALUE private_key)
 {
+#if OSSL_OPENSSL_PREREQ(3, 0, 0)
+    rb_raise(ePKeyError, "pkeys are immutable on OpenSSL 3.0");
+#else
     EC_KEY *ec;
     BIGNUM *bn = NULL;
 
@@ -305,6 +312,7 @@ static VALUE ossl_ec_key_set_private_key(VALUE self, VALUE private_key) https://github.com/ruby/ruby/blob/trunk/ext/openssl/ossl_pkey_ec.c#L312
     }
 
     return private_key;
+#endif
 }
 
 /*
@@ -333,6 +341,9 @@ static VALUE ossl_ec_key_get_public_key(VALUE self) https://github.com/ruby/ruby/blob/trunk/ext/openssl/ossl_pkey_ec.c#L341
  */
 static VALUE ossl_ec_key_set_public_key(VALUE self, VALUE public_key)
 {
+#if OSSL_OPENSSL_PREREQ(3, 0, 0)
+    rb_raise(ePKeyError, "pkeys are immutable on OpenSSL 3.0");
+#else
     EC_KEY *ec;
     EC_POINT *point = NULL;
 
@@ -352,6 +363,7 @@ static VALUE ossl_ec_key_set_public_key(VALUE self, VALUE public_key) https://github.com/ruby/ruby/blob/trunk/ext/openssl/ossl_pkey_ec.c#L363
     }
 
     return public_key;
+#endif
 }
 
 /*
diff --git a/test/openssl/test_pkey_dh.rb b/test/openssl/test_pkey_dh.rb
index ac11af382a7..161af1897bd 100644
--- a/test/openssl/test_pkey_dh.rb
+++ b/test/openssl/test_pkey_dh.rb
@@ -107,13 +107,32 @@ class OpenSSL::TestPKeyDH < OpenSSL::PKeyTestCase https://github.com/ruby/ruby/blob/trunk/test/openssl/test_pkey_dh.rb#L107
   end
 
   def test_dup
-    dh = Fixtures.pkey("dh1024")
-    dh2 = dh.dup
-    assert_equal dh.to_der, dh2.to_der # params
-    assert_equal_params dh, dh2 # keys
-    dh2.set_pqg(dh2.p + 1, nil, dh2.g)
-    assert_not_equal dh2.p, dh.p
-    assert_equal dh2.g, dh.g
+    # Parameters only
+    dh1 = Fixtures.pkey("dh1024")
+    dh2 = dh1.dup
+    assert_equal dh1.to_der, dh2.to_der
+    assert_not_equal nil, dh1.p
+    assert_not_equal nil, dh1.g
+    assert_equal [dh1.p, dh1.g], [dh2.p, dh2.g]
+    assert_equal nil, dh1.pub_key
+    assert_equal nil, dh1.priv_key
+    assert_equal [dh1.pub_key, dh1.priv_key], [dh2.pub_key, dh2.priv_key]
+
+    # PKey is immutable in OpenSSL >= 3.0
+    if !openssl?(3, 0, 0)
+      dh2.set_pqg(dh2.p + 1, nil, dh2.g)
+      assert_not_equal dh2.p, dh1.p
+    end
+
+    # With a key pair
+    dh3 = OpenSSL::PKey.generate_key(Fixtures.pkey("dh1024"))
+    dh4 = dh3.dup
+    assert_equal dh3.to_der, dh4.to_der
+    assert_equal dh1.to_der, dh4.to_der # encodes parameters only
+    assert_equal [dh1.p, dh1.g], [dh4.p, dh4.g]
+    assert_not_equal nil, dh3.pub_key
+    assert_not_equal nil, dh3.priv_key
+    assert_equal [dh3.pub_key, dh3.priv_key], [dh4.pub_key, dh4.priv_key]
   end
 
   def test_marshal
@@ -125,11 +144,6 @@ class OpenSSL::TestPKeyDH < OpenSSL::PKeyTestCase https://github.com/ruby/ruby/blob/trunk/test/openssl/test_pkey_dh.rb#L144
 
   private
 
-  def assert_equal_params(dh1, dh2)
-    assert_equal(dh1.g, dh2.g)
-    assert_equal(dh1.p, dh2.p)
-  end
-
   def assert_no_key(dh)
     assert_equal(false, dh.public?)
     assert_equal(false, dh.private?)
diff --git a/test/openssl/test_pkey_dsa.rb b/test/openssl/test_pkey_dsa.rb
index 0994607f21a..726b7dbf7e6 100644
--- a/test/openssl/test_pkey_dsa.rb
+++ b/test/openssl/test_pkey_dsa.rb
@@ -208,8 +208,12 @@ fWLOqqkzFeRrYMDzUpl36XktY6Yq8EJYlW9pCMmBVNy/dQ== https://github.com/ruby/ruby/blob/trunk/test/openssl/test_pkey_dsa.rb#L208
     key = Fixtures.pkey("dsa1024")
     key2 = key.dup
     assert_equal key.params, key2.params
-    key2.set_pqg(key2.p + 1, key2.q, key2.g)
-    assert_not_equal key.params, key2.params
+
+    # PKey is immutable in OpenSSL >= 3.0
+    if !openssl?(3, 0, 0)
+      key2.set_pqg(key2.p + 1, key2.q, key2.g)
+      assert_not_equal key.params, key2.params
+    end
   end
 
   def test_marshal
diff --git a/test/openssl/test_pkey_ec.rb b/test/openssl/test_pkey_ec.rb
index 33f78a4c778..ffe5a94e5b1 100644
--- a/test/openssl/test_pkey_ec.rb
+++ b/test/openssl/test_pkey_ec.rb
@@ -21,11 +21,15 @@ class OpenSSL::TestEC < OpenSSL::PKeyTestCase https://github.com/ruby/ruby/blob/trunk/test/openssl/test_pkey_ec.rb#L21
 
     key1 = OpenSSL::PKey::EC.generate("prime256v1")
 
-    key2 = OpenSSL::PKey::EC.new
-    key2.group = key1.group
-    key2.private_key = key1.private_key
-    key2.public_key = key1.public_key
-    assert_equal key1.to_der, key2.to_der
+    # PKey is immutable in OpenSSL >= 3.0; constructing an empty EC object is
+    # deprecated
+    if !openssl?(3, 0, 0)
+      key2 = OpenSSL::PKey::EC.new
+      key2.group = key1.group
+      key2.private_key = key1.private_key
+      key2.public_key = key1.public_key
+      assert_equal key1.to_der, key2.to_der
+    end
 
     key3 = OpenSSL::PKey::EC.new(key1)
     assert_equal key1.to_der, key3.to_der
@@ -35,10 +39,14 @@ class OpenSSL::TestEC < OpenSSL::PKeyTestCase https://github.com/ruby/ruby/blob/trunk/test/openssl/test_pkey_ec.rb#L39
 
     key5 = key1.dup
     assert_equal key1.to_der, key5.to_der
-    key_tmp = OpenSSL::PKey::EC.new("prime256v1").generate_key!
-    key5.private_key = key_tmp.private_key
-    key5.public_key = key_tmp.public_key
-    assert_not_equal key1.to_der, key5.to_der
+
+    # PKey is immutable in OpenSSL >= 3.0; EC object should not be modified
+    if !openssl?(3, 0, 0)
+      key_tmp = OpenSSL::PKey::EC.generate("prime256v1")
+      key5.private_key = key_tmp.private_key
+      key5.public_key = key_tmp.public_key
+      assert_not_equal key1.to_der, key5.to_der
+    end
   end
 
   def test_generate
@@ -65,22 +73,26 @@ class OpenSSL::TestEC < OpenSSL::PKeyTestCase https://github.com/ruby/ruby/blob/trunk/test/openssl/test_pkey_ec.rb#L73
   end
 
   def test_check_key
-    key = OpenSSL::PKey::EC.new("prime256v1").generate_key!
-    assert_equal(true, key.check_key)
-    assert_equal(true, key.private?)
-    assert_equal(true, key.public?)
-    key2 = OpenSSL::PKey::EC.new(key.group)
-    assert_equal(false, key2.private?)
-    assert_equal(false, key2.public?)
-    key2.public_key = key.public_key
-    assert_equal(false, key2.private?)
-    assert_equal(true, key2.public?)
-    key2.private_key = key.private_key
+    key0 = Fixtures.pkey("p256")
+    assert_equal(true, key0.check_key)
+    assert_equal(true, key0.private?)
+    assert_equal(true, key0.public?)
+
+    key1 = OpenSSL::PKey.read(key0.public_to_der)
+    assert_equ (... truncated)

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]