cd5466
From e8504c6248c4b0e5e961f57f004e1133c20c88a5 Mon Sep 17 00:00:00 2001
cd5466
From: Kazuki Yamaguchi <k@rhe.jp>
cd5466
Date: Mon, 5 Apr 2021 00:30:01 +0900
cd5466
Subject: [PATCH 1/5] pkey: fix interrupt handling in
cd5466
 OpenSSL::PKey.generate_key
cd5466
cd5466
rb_thread_call_without_gvl() can be interrupted, but it may be able to
cd5466
resume the operation. Call rb_thread_check_ints() to see if it raises
cd5466
an exception or not.
cd5466
---
cd5466
 ext/openssl/ossl_pkey.c | 18 +++++++++++++-----
cd5466
 1 file changed, 13 insertions(+), 5 deletions(-)
cd5466
cd5466
diff --git a/ext/openssl/ossl_pkey.c b/ext/openssl/ossl_pkey.c
cd5466
index 22e9f19982..d76f0600d1 100644
cd5466
--- a/ext/openssl/ossl_pkey.c
cd5466
+++ b/ext/openssl/ossl_pkey.c
cd5466
@@ -239,7 +239,7 @@ struct pkey_blocking_generate_arg {
cd5466
     int state;
cd5466
     int yield: 1;
cd5466
     int genparam: 1;
cd5466
-    int stop: 1;
cd5466
+    int interrupted: 1;
cd5466
 };
cd5466
 
cd5466
 static VALUE
cd5466
@@ -261,23 +261,31 @@ static int
cd5466
 pkey_gen_cb(EVP_PKEY_CTX *ctx)
cd5466
 {
cd5466
     struct pkey_blocking_generate_arg *arg = EVP_PKEY_CTX_get_app_data(ctx);
cd5466
+    int state;
cd5466
 
cd5466
     if (arg->yield) {
cd5466
-        int state;
cd5466
         rb_protect(pkey_gen_cb_yield, (VALUE)ctx, &state);
cd5466
         if (state) {
cd5466
-            arg->stop = 1;
cd5466
             arg->state = state;
cd5466
+            return 0;
cd5466
+        }
cd5466
+    }
cd5466
+    if (arg->interrupted) {
cd5466
+        arg->interrupted = 0;
cd5466
+        state = (int)(VALUE)rb_thread_call_with_gvl(call_check_ints, NULL);
cd5466
+        if (state) {
cd5466
+            arg->state = state;
cd5466
+            return 0;
cd5466
         }
cd5466
     }
cd5466
-    return !arg->stop;
cd5466
+    return 1;
cd5466
 }
cd5466
 
cd5466
 static void
cd5466
 pkey_blocking_gen_stop(void *ptr)
cd5466
 {
cd5466
     struct pkey_blocking_generate_arg *arg = ptr;
cd5466
-    arg->stop = 1;
cd5466
+    arg->interrupted = 1;
cd5466
 }
cd5466
 
cd5466
 static void *
cd5466
-- 
cd5466
2.32.0
cd5466
cd5466
cd5466
From f433d1b680e7ac5ef13fc15b0844267222438cf3 Mon Sep 17 00:00:00 2001
cd5466
From: Kazuki Yamaguchi <k@rhe.jp>
cd5466
Date: Sun, 17 May 2020 20:48:23 +0900
cd5466
Subject: [PATCH 2/5] pkey/dh: use high level EVP interface to generate
cd5466
 parameters and keys
cd5466
cd5466
Implement PKey::DH.new(size, gen), PKey::DH.generate(size, gen), and
cd5466
PKey::DH#generate_key! using PKey.generate_parameters and .generate_key
cd5466
instead of the low level DH functions.
cd5466
cd5466
Note that the EVP interface can enforce additional restrictions - for
cd5466
example, DH key shorter than 2048 bits is no longer accepted by default
cd5466
in OpenSSL 3.0. The test code is updated accordingly.
cd5466
---
cd5466
 ext/openssl/lib/openssl/pkey.rb |  57 ++++++++++
cd5466
 ext/openssl/ossl_pkey_dh.c      | 186 ++++++--------------------------
cd5466
 test/openssl/test_pkey_dh.rb    |  15 ++-
cd5466
 3 files changed, 101 insertions(+), 157 deletions(-)
cd5466
cd5466
diff --git a/ext/openssl/lib/openssl/pkey.rb b/ext/openssl/lib/openssl/pkey.rb
cd5466
index be60ac2beb..5a3d0ed1ef 100644
cd5466
--- a/ext/openssl/lib/openssl/pkey.rb
cd5466
+++ b/ext/openssl/lib/openssl/pkey.rb
cd5466
@@ -27,6 +27,63 @@ def compute_key(pub_bn)
cd5466
       peer.set_key(pub_bn, nil)
cd5466
       derive(peer)
cd5466
     end
cd5466
+
cd5466
+    # :call-seq:
cd5466
+    #    dh.generate_key! -> self
cd5466
+    #
cd5466
+    # Generates a private and public key unless a private key already exists.
cd5466
+    # If this DH instance was generated from public \DH parameters (e.g. by
cd5466
+    # encoding the result of DH#public_key), then this method needs to be
cd5466
+    # called first in order to generate the per-session keys before performing
cd5466
+    # the actual key exchange.
cd5466
+    #
cd5466
+    # See also OpenSSL::PKey.generate_key.
cd5466
+    #
cd5466
+    # Example:
cd5466
+    #   dh = OpenSSL::PKey::DH.new(2048)
cd5466
+    #   public_key = dh.public_key #contains no private/public key yet
cd5466
+    #   public_key.generate_key!
cd5466
+    #   puts public_key.private? # => true
cd5466
+    def generate_key!
cd5466
+      unless priv_key
cd5466
+        tmp = OpenSSL::PKey.generate_key(self)
cd5466
+        set_key(tmp.pub_key, tmp.priv_key)
cd5466
+      end
cd5466
+      self
cd5466
+    end
cd5466
+
cd5466
+    class << self
cd5466
+      # :call-seq:
cd5466
+      #    DH.generate(size, generator = 2) -> dh
cd5466
+      #
cd5466
+      # Creates a new DH instance from scratch by generating random parameters
cd5466
+      # and a key pair.
cd5466
+      #
cd5466
+      # See also OpenSSL::PKey.generate_parameters and
cd5466
+      # OpenSSL::PKey.generate_key.
cd5466
+      #
cd5466
+      # +size+::
cd5466
+      #   The desired key size in bits.
cd5466
+      # +generator+::
cd5466
+      #   The generator.
cd5466
+      def generate(size, generator = 2, &blk)
cd5466
+        dhparams = OpenSSL::PKey.generate_parameters("DH", {
cd5466
+          "dh_paramgen_prime_len" => size,
cd5466
+          "dh_paramgen_generator" => generator,
cd5466
+        }, &blk)
cd5466
+        OpenSSL::PKey.generate_key(dhparams)
cd5466
+      end
cd5466
+
cd5466
+      # Handle DH.new(size, generator) form here; new(str) and new() forms
cd5466
+      # are handled by #initialize
cd5466
+      def new(*args, &blk) # :nodoc:
cd5466
+        if args[0].is_a?(Integer)
cd5466
+          generate(*args, &blk)
cd5466
+        else
cd5466
+          super
cd5466
+        end
cd5466
+      end
cd5466
+    end
cd5466
   end
cd5466
 
cd5466
   class DSA
cd5466
diff --git a/ext/openssl/ossl_pkey_dh.c b/ext/openssl/ossl_pkey_dh.c
cd5466
index 5bc1c49ca1..6b477b077c 100644
cd5466
--- a/ext/openssl/ossl_pkey_dh.c
cd5466
+++ b/ext/openssl/ossl_pkey_dh.c
cd5466
@@ -32,147 +32,56 @@ VALUE eDHError;
cd5466
 /*
cd5466
  * Private
cd5466
  */
cd5466
-struct dh_blocking_gen_arg {
cd5466
-    DH *dh;
cd5466
-    int size;
cd5466
-    int gen;
cd5466
-    BN_GENCB *cb;
cd5466
-    int result;
cd5466
-};
cd5466
-
cd5466
-static void *
cd5466
-dh_blocking_gen(void *arg)
cd5466
-{
cd5466
-    struct dh_blocking_gen_arg *gen = (struct dh_blocking_gen_arg *)arg;
cd5466
-    gen->result = DH_generate_parameters_ex(gen->dh, gen->size, gen->gen, gen->cb);
cd5466
-    return 0;
cd5466
-}
cd5466
-
cd5466
-static DH *
cd5466
-dh_generate(int size, int gen)
cd5466
-{
cd5466
-    struct ossl_generate_cb_arg cb_arg = { 0 };
cd5466
-    struct dh_blocking_gen_arg gen_arg;
cd5466
-    DH *dh = DH_new();
cd5466
-    BN_GENCB *cb = BN_GENCB_new();
cd5466
-
cd5466
-    if (!dh || !cb) {
cd5466
-	DH_free(dh);
cd5466
-	BN_GENCB_free(cb);
cd5466
-        ossl_raise(eDHError, "malloc failure");
cd5466
-    }
cd5466
-
cd5466
-    if (rb_block_given_p())
cd5466
-	cb_arg.yield = 1;
cd5466
-    BN_GENCB_set(cb, ossl_generate_cb_2, &cb_arg);
cd5466
-    gen_arg.dh = dh;
cd5466
-    gen_arg.size = size;
cd5466
-    gen_arg.gen = gen;
cd5466
-    gen_arg.cb = cb;
cd5466
-    if (cb_arg.yield == 1) {
cd5466
-	/* we cannot release GVL when callback proc is supplied */
cd5466
-	dh_blocking_gen(&gen_arg);
cd5466
-    } else {
cd5466
-	/* there's a chance to unblock */
cd5466
-	rb_thread_call_without_gvl(dh_blocking_gen, &gen_arg, ossl_generate_cb_stop, &cb_arg);
cd5466
-    }
cd5466
-
cd5466
-    BN_GENCB_free(cb);
cd5466
-    if (!gen_arg.result) {
cd5466
-	DH_free(dh);
cd5466
-	if (cb_arg.state) {
cd5466
-	    /* Clear OpenSSL error queue before re-raising. */
cd5466
-	    ossl_clear_error();
cd5466
-	    rb_jump_tag(cb_arg.state);
cd5466
-	}
cd5466
-        ossl_raise(eDHError, "DH_generate_parameters_ex");
cd5466
-    }
cd5466
-
cd5466
-    if (!DH_generate_key(dh)) {
cd5466
-        DH_free(dh);
cd5466
-        ossl_raise(eDHError, "DH_generate_key");
cd5466
-    }
cd5466
-
cd5466
-    return dh;
cd5466
-}
cd5466
-
cd5466
-/*
cd5466
- *  call-seq:
cd5466
- *     DH.generate(size [, generator]) -> dh
cd5466
- *
cd5466
- * Creates a new DH instance from scratch by generating the private and public
cd5466
- * components alike.
cd5466
- *
cd5466
- * === Parameters
cd5466
- * * _size_ is an integer representing the desired key size. Keys smaller than 1024 bits should be considered insecure.
cd5466
- * * _generator_ is a small number > 1, typically 2 or 5.
cd5466
- *
cd5466
- */
cd5466
-static VALUE
cd5466
-ossl_dh_s_generate(int argc, VALUE *argv, VALUE klass)
cd5466
-{
cd5466
-    EVP_PKEY *pkey;
cd5466
-    DH *dh ;
cd5466
-    int g = 2;
cd5466
-    VALUE size, gen, obj;
cd5466
-
cd5466
-    if (rb_scan_args(argc, argv, "11", &size, &gen) == 2) {
cd5466
-	g = NUM2INT(gen);
cd5466
-    }
cd5466
-    obj = rb_obj_alloc(klass);
cd5466
-    GetPKey(obj, pkey);
cd5466
-
cd5466
-    dh = dh_generate(NUM2INT(size), g);
cd5466
-    if (!EVP_PKEY_assign_DH(pkey, dh)) {
cd5466
-        DH_free(dh);
cd5466
-        ossl_raise(eDHError, "EVP_PKEY_assign_DH");
cd5466
-    }
cd5466
-    return obj;
cd5466
-}
cd5466
-
cd5466
 /*
cd5466
  * call-seq:
cd5466
  *   DH.new -> dh
cd5466
  *   DH.new(string) -> dh
cd5466
  *   DH.new(size [, generator]) -> dh
cd5466
  *
cd5466
- * Either generates a DH instance from scratch or by reading already existing
cd5466
- * DH parameters from _string_. Note that when reading a DH instance from
cd5466
- * data that was encoded from a DH instance by using DH#to_pem or DH#to_der
cd5466
- * the result will *not* contain a public/private key pair yet. This needs to
cd5466
- * be generated using DH#generate_key! first.
cd5466
+ * Creates a new instance of OpenSSL::PKey::DH.
cd5466
+ *
cd5466
+ * If called without arguments, an empty instance without any parameter or key
cd5466
+ * components is created. Use #set_pqg to manually set the parameters afterwards
cd5466
+ * (and optionally #set_key to set private and public key components).
cd5466
+ *
cd5466
+ * If a String is given, tries to parse it as a DER- or PEM- encoded parameters.
cd5466
+ * See also OpenSSL::PKey.read which can parse keys of any kinds.
cd5466
+ *
cd5466
+ * The DH.new(size [, generator]) form is an alias of DH.generate.
cd5466
  *
cd5466
- * === Parameters
cd5466
- * * _size_ is an integer representing the desired key size. Keys smaller than 1024 bits should be considered insecure.
cd5466
- * * _generator_ is a small number > 1, typically 2 or 5.
cd5466
- * * _string_ contains the DER or PEM encoded key.
cd5466
+ * +string+::
cd5466
+ *   A String that contains the DER or PEM encoded key.
cd5466
+ * +size+::
cd5466
+ *   See DH.generate.
cd5466
+ * +generator+::
cd5466
+ *   See DH.generate.
cd5466
  *
cd5466
- * === Examples
cd5466
- *  DH.new # -> dh
cd5466
- *  DH.new(1024) # -> dh
cd5466
- *  DH.new(1024, 5) # -> dh
cd5466
- *  #Reading DH parameters
cd5466
- *  dh = DH.new(File.read('parameters.pem')) # -> dh, but no public/private key yet
cd5466
- *  dh.generate_key! # -> dh with public and private key
cd5466
+ * Examples:
cd5466
+ *   # Creating an instance from scratch
cd5466
+ *   dh = DH.new
cd5466
+ *   dh.set_pqg(bn_p, nil, bn_g)
cd5466
+ *
cd5466
+ *   # Generating a parameters and a key pair
cd5466
+ *   dh = DH.new(2048) # An alias of DH.generate(2048)
cd5466
+ *
cd5466
+ *   # Reading DH parameters
cd5466
+ *   dh = DH.new(File.read('parameters.pem')) # -> dh, but no public/private key yet
cd5466
+ *   dh.generate_key! # -> dh with public and private key
cd5466
  */
cd5466
 static VALUE
cd5466
 ossl_dh_initialize(int argc, VALUE *argv, VALUE self)
cd5466
 {
cd5466
     EVP_PKEY *pkey;
cd5466
     DH *dh;
cd5466
-    int g = 2;
cd5466
     BIO *in;
cd5466
-    VALUE arg, gen;
cd5466
+    VALUE arg;
cd5466
 
cd5466
     GetPKey(self, pkey);
cd5466
-    if(rb_scan_args(argc, argv, "02", &arg, &gen) == 0) {
cd5466
-      dh = DH_new();
cd5466
-    }
cd5466
-    else if (RB_INTEGER_TYPE_P(arg)) {
cd5466
-	if (!NIL_P(gen)) {
cd5466
-	    g = NUM2INT(gen);
cd5466
-	}
cd5466
-        dh = dh_generate(NUM2INT(arg), g);
cd5466
+    /* The DH.new(size, generator) form is handled by lib/openssl/pkey.rb */
cd5466
+    if (rb_scan_args(argc, argv, "01", &arg) == 0) {
cd5466
+        dh = DH_new();
cd5466
+        if (!dh)
cd5466
+            ossl_raise(eDHError, "DH_new");
cd5466
     }
cd5466
     else {
cd5466
 	arg = ossl_to_der_if_possible(arg);
cd5466
@@ -449,33 +358,6 @@ ossl_dh_check_params(VALUE self)
cd5466
     return codes == 0 ? Qtrue : Qfalse;
cd5466
 }
cd5466
 
cd5466
-/*
cd5466
- *  call-seq:
cd5466
- *     dh.generate_key! -> self
cd5466
- *
cd5466
- * Generates a private and public key unless a private key already exists.
cd5466
- * If this DH instance was generated from public DH parameters (e.g. by
cd5466
- * encoding the result of DH#public_key), then this method needs to be
cd5466
- * called first in order to generate the per-session keys before performing
cd5466
- * the actual key exchange.
cd5466
- *
cd5466
- * === Example
cd5466
- *   dh = OpenSSL::PKey::DH.new(2048)
cd5466
- *   public_key = dh.public_key #contains no private/public key yet
cd5466
- *   public_key.generate_key!
cd5466
- *   puts public_key.private? # => true
cd5466
- */
cd5466
-static VALUE
cd5466
-ossl_dh_generate_key(VALUE self)
cd5466
-{
cd5466
-    DH *dh;
cd5466
-
cd5466
-    GetDH(self, dh);
cd5466
-    if (!DH_generate_key(dh))
cd5466
-	ossl_raise(eDHError, "Failed to generate key");
cd5466
-    return self;
cd5466
-}
cd5466
-
cd5466
 /*
cd5466
  * Document-method: OpenSSL::PKey::DH#set_pqg
cd5466
  * call-seq:
cd5466
@@ -540,7 +422,6 @@ Init_ossl_dh(void)
cd5466
      *  puts symm_key1 == symm_key2 # => true
cd5466
      */
cd5466
     cDH = rb_define_class_under(mPKey, "DH", cPKey);
cd5466
-    rb_define_singleton_method(cDH, "generate", ossl_dh_s_generate, -1);
cd5466
     rb_define_method(cDH, "initialize", ossl_dh_initialize, -1);
cd5466
     rb_define_method(cDH, "initialize_copy", ossl_dh_initialize_copy, 1);
cd5466
     rb_define_method(cDH, "public?", ossl_dh_is_public, 0);
cd5466
@@ -552,7 +433,6 @@ Init_ossl_dh(void)
cd5466
     rb_define_method(cDH, "to_der", ossl_dh_to_der, 0);
cd5466
     rb_define_method(cDH, "public_key", ossl_dh_to_public_key, 0);
cd5466
     rb_define_method(cDH, "params_ok?", ossl_dh_check_params, 0);
cd5466
-    rb_define_method(cDH, "generate_key!", ossl_dh_generate_key, 0);
cd5466
 
cd5466
     DEF_OSSL_PKEY_BN(cDH, dh, p);
cd5466
     DEF_OSSL_PKEY_BN(cDH, dh, q);
cd5466
diff --git a/test/openssl/test_pkey_dh.rb b/test/openssl/test_pkey_dh.rb
cd5466
index 9efc3ba68d..279ce1984c 100644
cd5466
--- a/test/openssl/test_pkey_dh.rb
cd5466
+++ b/test/openssl/test_pkey_dh.rb
cd5466
@@ -4,12 +4,19 @@
cd5466
 if defined?(OpenSSL) && defined?(OpenSSL::PKey::DH)
cd5466
 
cd5466
 class OpenSSL::TestPKeyDH < OpenSSL::PKeyTestCase
cd5466
-  NEW_KEYLEN = 256
cd5466
+  NEW_KEYLEN = 2048
cd5466
 
cd5466
-  def test_new
cd5466
+  def test_new_empty
cd5466
+    dh = OpenSSL::PKey::DH.new
cd5466
+    assert_equal nil, dh.p
cd5466
+    assert_equal nil, dh.priv_key
cd5466
+  end
cd5466
+
cd5466
+  def test_new_generate
cd5466
+    # This test is slow
cd5466
     dh = OpenSSL::PKey::DH.new(NEW_KEYLEN)
cd5466
     assert_key(dh)
cd5466
-  end
cd5466
+  end if ENV["OSSL_TEST_ALL"]
cd5466
 
cd5466
   def test_new_break
cd5466
     assert_nil(OpenSSL::PKey::DH.new(NEW_KEYLEN) { break })
cd5466
@@ -80,7 +87,7 @@ def test_key_exchange
cd5466
   end
cd5466
 
cd5466
   def test_dup
cd5466
-    dh = OpenSSL::PKey::DH.new(NEW_KEYLEN)
cd5466
+    dh = Fixtures.pkey("dh1024")
cd5466
     dh2 = dh.dup
cd5466
     assert_equal dh.to_der, dh2.to_der # params
cd5466
     assert_equal_params dh, dh2 # keys
cd5466
-- 
cd5466
2.32.0
cd5466
cd5466
cd5466
From ba1d1d68ac2b489691eb3fe2052e77b3e57a372b Mon Sep 17 00:00:00 2001
cd5466
From: Kazuki Yamaguchi <k@rhe.jp>
cd5466
Date: Sun, 17 May 2020 20:48:23 +0900
cd5466
Subject: [PATCH 3/5] pkey/rsa: use high level EVP interface to generate
cd5466
 parameters and keys
cd5466
cd5466
Implement PKey::RSA.new(size, exponent) and PKey::RSA.generate using
cd5466
OpenSSL::PKey.generate_key instead of the low level RSA functions.
cd5466
---
cd5466
 ext/openssl/lib/openssl/pkey.rb |  30 ++++++++
cd5466
 ext/openssl/ossl_pkey_rsa.c     | 132 ++++----------------------------
cd5466
 2 files changed, 46 insertions(+), 116 deletions(-)
cd5466
cd5466
diff --git a/ext/openssl/lib/openssl/pkey.rb b/ext/openssl/lib/openssl/pkey.rb
cd5466
index 5a3d0ed1ef..3bef06e3b3 100644
cd5466
--- a/ext/openssl/lib/openssl/pkey.rb
cd5466
+++ b/ext/openssl/lib/openssl/pkey.rb
cd5466
@@ -128,5 +128,35 @@ def to_bn(conversion_form = group.point_conversion_form)
cd5466
 
cd5466
   class RSA
cd5466
     include OpenSSL::Marshal
cd5466
+
cd5466
+    class << self
cd5466
+      # :call-seq:
cd5466
+      #    RSA.generate(size, exponent = 65537) -> RSA
cd5466
+      #
cd5466
+      # Generates an \RSA keypair.
cd5466
+      #
cd5466
+      # See also OpenSSL::PKey.generate_key.
cd5466
+      #
cd5466
+      # +size+::
cd5466
+      #   The desired key size in bits.
cd5466
+      # +exponent+::
cd5466
+      #   An odd Integer, normally 3, 17, or 65537.
cd5466
+      def generate(size, exp = 0x10001, &blk)
cd5466
+        OpenSSL::PKey.generate_key("RSA", {
cd5466
+          "rsa_keygen_bits" => size,
cd5466
+          "rsa_keygen_pubexp" => exp,
cd5466
+        }, &blk)
cd5466
+      end
cd5466
+
cd5466
+      # Handle RSA.new(size, exponent) form here; new(str) and new() forms
cd5466
+      # are handled by #initialize
cd5466
+      def new(*args, &blk) # :nodoc:
cd5466
+        if args[0].is_a?(Integer)
cd5466
+          generate(*args, &blk)
cd5466
+        else
cd5466
+          super
cd5466
+        end
cd5466
+      end
cd5466
+    end
cd5466
   end
cd5466
 end
cd5466
diff --git a/ext/openssl/ossl_pkey_rsa.c b/ext/openssl/ossl_pkey_rsa.c
cd5466
index 3c298a2aea..43f82cb29e 100644
cd5466
--- a/ext/openssl/ossl_pkey_rsa.c
cd5466
+++ b/ext/openssl/ossl_pkey_rsa.c
cd5466
@@ -47,125 +47,28 @@ VALUE eRSAError;
cd5466
 /*
cd5466
  * Private
cd5466
  */
cd5466
-struct rsa_blocking_gen_arg {
cd5466
-    RSA *rsa;
cd5466
-    BIGNUM *e;
cd5466
-    int size;
cd5466
-    BN_GENCB *cb;
cd5466
-    int result;
cd5466
-};
cd5466
-
cd5466
-static void *
cd5466
-rsa_blocking_gen(void *arg)
cd5466
-{
cd5466
-    struct rsa_blocking_gen_arg *gen = (struct rsa_blocking_gen_arg *)arg;
cd5466
-    gen->result = RSA_generate_key_ex(gen->rsa, gen->size, gen->e, gen->cb);
cd5466
-    return 0;
cd5466
-}
cd5466
-
cd5466
-static RSA *
cd5466
-rsa_generate(int size, unsigned long exp)
cd5466
-{
cd5466
-    int i;
cd5466
-    struct ossl_generate_cb_arg cb_arg = { 0 };
cd5466
-    struct rsa_blocking_gen_arg gen_arg;
cd5466
-    RSA *rsa = RSA_new();
cd5466
-    BIGNUM *e = BN_new();
cd5466
-    BN_GENCB *cb = BN_GENCB_new();
cd5466
-
cd5466
-    if (!rsa || !e || !cb) {
cd5466
-	RSA_free(rsa);
cd5466
-	BN_free(e);
cd5466
-	BN_GENCB_free(cb);
cd5466
-        ossl_raise(eRSAError, "malloc failure");
cd5466
-    }
cd5466
-    for (i = 0; i < (int)sizeof(exp) * 8; ++i) {
cd5466
-	if (exp & (1UL << i)) {
cd5466
-	    if (BN_set_bit(e, i) == 0) {
cd5466
-		BN_free(e);
cd5466
-		RSA_free(rsa);
cd5466
-		BN_GENCB_free(cb);
cd5466
-                ossl_raise(eRSAError, "BN_set_bit");
cd5466
-	    }
cd5466
-	}
cd5466
-    }
cd5466
-
cd5466
-    if (rb_block_given_p())
cd5466
-	cb_arg.yield = 1;
cd5466
-    BN_GENCB_set(cb, ossl_generate_cb_2, &cb_arg);
cd5466
-    gen_arg.rsa = rsa;
cd5466
-    gen_arg.e = e;
cd5466
-    gen_arg.size = size;
cd5466
-    gen_arg.cb = cb;
cd5466
-    if (cb_arg.yield == 1) {
cd5466
-	/* we cannot release GVL when callback proc is supplied */
cd5466
-	rsa_blocking_gen(&gen_arg);
cd5466
-    } else {
cd5466
-	/* there's a chance to unblock */
cd5466
-	rb_thread_call_without_gvl(rsa_blocking_gen, &gen_arg, ossl_generate_cb_stop, &cb_arg);
cd5466
-    }
cd5466
-
cd5466
-    BN_GENCB_free(cb);
cd5466
-    BN_free(e);
cd5466
-    if (!gen_arg.result) {
cd5466
-	RSA_free(rsa);
cd5466
-	if (cb_arg.state) {
cd5466
-	    /* must clear OpenSSL error stack */
cd5466
-	    ossl_clear_error();
cd5466
-	    rb_jump_tag(cb_arg.state);
cd5466
-	}
cd5466
-        ossl_raise(eRSAError, "RSA_generate_key_ex");
cd5466
-    }
cd5466
-
cd5466
-    return rsa;
cd5466
-}
cd5466
-
cd5466
 /*
cd5466
  * call-seq:
cd5466
- *   RSA.generate(size)           => RSA instance
cd5466
- *   RSA.generate(size, exponent) => RSA instance
cd5466
+ *   RSA.new -> rsa
cd5466
+ *   RSA.new(encoded_key [, passphrase]) -> rsa
cd5466
+ *   RSA.new(encoded_key) { passphrase } -> rsa
cd5466
+ *   RSA.new(size [, exponent]) -> rsa
cd5466
  *
cd5466
- * Generates an RSA keypair.  _size_ is an integer representing the desired key
cd5466
- * size.  Keys smaller than 1024 should be considered insecure.  _exponent_ is
cd5466
- * an odd number normally 3, 17, or 65537.
cd5466
- */
cd5466
-static VALUE
cd5466
-ossl_rsa_s_generate(int argc, VALUE *argv, VALUE klass)
cd5466
-{
cd5466
-/* why does this method exist?  why can't initialize take an optional exponent? */
cd5466
-    EVP_PKEY *pkey;
cd5466
-    RSA *rsa;
cd5466
-    VALUE size, exp;
cd5466
-    VALUE obj;
cd5466
-
cd5466
-    rb_scan_args(argc, argv, "11", &size, &exp);
cd5466
-    obj = rb_obj_alloc(klass);
cd5466
-    GetPKey(obj, pkey);
cd5466
-
cd5466
-    rsa = rsa_generate(NUM2INT(size), NIL_P(exp) ? RSA_F4 : NUM2ULONG(exp));
cd5466
-    if (!EVP_PKEY_assign_RSA(pkey, rsa)) {
cd5466
-        RSA_free(rsa);
cd5466
-        ossl_raise(eRSAError, "EVP_PKEY_assign_RSA");
cd5466
-    }
cd5466
-    return obj;
cd5466
-}
cd5466
-
cd5466
-/*
cd5466
- * call-seq:
cd5466
- *   RSA.new(size [, exponent])        => RSA instance
cd5466
- *   RSA.new(encoded_key)              => RSA instance
cd5466
- *   RSA.new(encoded_key, pass_phrase) => RSA instance
cd5466
+ * Generates or loads an \RSA keypair.
cd5466
  *
cd5466
- * Generates or loads an RSA keypair.  If an integer _key_size_ is given it
cd5466
- * represents the desired key size.  Keys less than 1024 bits should be
cd5466
- * considered insecure.
cd5466
+ * If called without arguments, creates a new instance with no key components
cd5466
+ * set. They can be set individually by #set_key, #set_factors, and
cd5466
+ * #set_crt_params.
cd5466
  *
cd5466
- * A key can instead be loaded from an _encoded_key_ which must be PEM or DER
cd5466
- * encoded.  A _pass_phrase_ can be used to decrypt the key.  If none is given
cd5466
- * OpenSSL will prompt for the pass phrase.
cd5466
+ * If called with a String, tries to parse as DER or PEM encoding of an \RSA key.
cd5466
+ * Note that, if _passphrase_ is not specified but the key is encrypted with a
cd5466
+ * passphrase, \OpenSSL will prompt for it.
cd5466
+ * See also OpenSSL::PKey.read which can parse keys of any kinds.
cd5466
  *
cd5466
- * = Examples
cd5466
+ * If called with a number, generates a new key pair. This form works as an
cd5466
+ * alias of RSA.generate.
cd5466
  *
cd5466
+ * Examples:
cd5466
  *   OpenSSL::PKey::RSA.new 2048
cd5466
  *   OpenSSL::PKey::RSA.new File.read 'rsa.pem'
cd5466
  *   OpenSSL::PKey::RSA.new File.read('rsa.pem'), 'my pass phrase'
cd5466
@@ -179,15 +82,13 @@ ossl_rsa_initialize(int argc, VALUE *argv, VALUE self)
cd5466
     VALUE arg, pass;
cd5466
 
cd5466
     GetPKey(self, pkey);
cd5466
+    /* The RSA.new(size, generator) form is handled by lib/openssl/pkey.rb */
cd5466
     rb_scan_args(argc, argv, "02", &arg, &pass);
cd5466
     if (argc == 0) {
cd5466
 	rsa = RSA_new();
cd5466
         if (!rsa)
cd5466
             ossl_raise(eRSAError, "RSA_new");
cd5466
     }
cd5466
-    else if (RB_INTEGER_TYPE_P(arg)) {
cd5466
-	rsa = rsa_generate(NUM2INT(arg), NIL_P(pass) ? RSA_F4 : NUM2ULONG(pass));
cd5466
-    }
cd5466
     else {
cd5466
 	pass = ossl_pem_passwd_value(pass);
cd5466
 	arg = ossl_to_der_if_possible(arg);
cd5466
@@ -832,7 +733,6 @@ Init_ossl_rsa(void)
cd5466
      */
cd5466
     cRSA = rb_define_class_under(mPKey, "RSA", cPKey);
cd5466
 
cd5466
-    rb_define_singleton_method(cRSA, "generate", ossl_rsa_s_generate, -1);
cd5466
     rb_define_method(cRSA, "initialize", ossl_rsa_initialize, -1);
cd5466
     rb_define_method(cRSA, "initialize_copy", ossl_rsa_initialize_copy, 1);
cd5466
 
cd5466
-- 
cd5466
2.32.0
cd5466
cd5466
cd5466
From a6c4a8116c09243c39cc8d1e7ececcd8be0cfaf2 Mon Sep 17 00:00:00 2001
cd5466
From: Kazuki Yamaguchi <k@rhe.jp>
cd5466
Date: Sun, 17 May 2020 22:14:03 +0900
cd5466
Subject: [PATCH 4/5] pkey/dsa: use high level EVP interface to generate
cd5466
 parameters and keys
cd5466
cd5466
Implement PKey::DSA.new(size) and PKey::DSA.generate using
cd5466
OpenSSL::PKey.generate_parameters and .generate_key instead of the low
cd5466
level DSA functions.
cd5466
---
cd5466
 ext/openssl/lib/openssl/pkey.rb |  30 +++++++
cd5466
 ext/openssl/ossl_pkey_dsa.c     | 140 ++++++--------------------------
cd5466
 test/openssl/test_pkey_dsa.rb   |  23 ++----
cd5466
 3 files changed, 64 insertions(+), 129 deletions(-)
cd5466
cd5466
diff --git a/ext/openssl/lib/openssl/pkey.rb b/ext/openssl/lib/openssl/pkey.rb
cd5466
index 3bef06e3b3..53ee52f98b 100644
cd5466
--- a/ext/openssl/lib/openssl/pkey.rb
cd5466
+++ b/ext/openssl/lib/openssl/pkey.rb
cd5466
@@ -88,6 +88,36 @@ def new(*args, &blk) # :nodoc:
cd5466
 
cd5466
   class DSA
cd5466
     include OpenSSL::Marshal
cd5466
+
cd5466
+    class << self
cd5466
+      # :call-seq:
cd5466
+      #    DSA.generate(size) -> dsa
cd5466
+      #
cd5466
+      # Creates a new DSA instance by generating a private/public key pair
cd5466
+      # from scratch.
cd5466
+      #
cd5466
+      # See also OpenSSL::PKey.generate_parameters and
cd5466
+      # OpenSSL::PKey.generate_key.
cd5466
+      #
cd5466
+      # +size+::
cd5466
+      #   The desired key size in bits.
cd5466
+      def generate(size, &blk)
cd5466
+        dsaparams = OpenSSL::PKey.generate_parameters("DSA", {
cd5466
+          "dsa_paramgen_bits" => size,
cd5466
+        }, &blk)
cd5466
+        OpenSSL::PKey.generate_key(dsaparams)
cd5466
+      end
cd5466
+
cd5466
+      # Handle DSA.new(size) form here; new(str) and new() forms
cd5466
+      # are handled by #initialize
cd5466
+      def new(*args, &blk) # :nodoc:
cd5466
+        if args[0].is_a?(Integer)
cd5466
+          generate(*args, &blk)
cd5466
+        else
cd5466
+          super
cd5466
+        end
cd5466
+      end
cd5466
+    end
cd5466
   end
cd5466
 
cd5466
   if defined?(EC)
cd5466
diff --git a/ext/openssl/ossl_pkey_dsa.c b/ext/openssl/ossl_pkey_dsa.c
cd5466
index 0e68f7f27f..1c5a8a737e 100644
cd5466
--- a/ext/openssl/ossl_pkey_dsa.c
cd5466
+++ b/ext/openssl/ossl_pkey_dsa.c
cd5466
@@ -46,126 +46,39 @@ VALUE eDSAError;
cd5466
 /*
cd5466
  * Private
cd5466
  */
cd5466
-struct dsa_blocking_gen_arg {
cd5466
-    DSA *dsa;
cd5466
-    int size;
cd5466
-    int *counter;
cd5466
-    unsigned long *h;
cd5466
-    BN_GENCB *cb;
cd5466
-    int result;
cd5466
-};
cd5466
-
cd5466
-static void *
cd5466
-dsa_blocking_gen(void *arg)
cd5466
-{
cd5466
-    struct dsa_blocking_gen_arg *gen = (struct dsa_blocking_gen_arg *)arg;
cd5466
-    gen->result = DSA_generate_parameters_ex(gen->dsa, gen->size, NULL, 0,
cd5466
-					     gen->counter, gen->h, gen->cb);
cd5466
-    return 0;
cd5466
-}
cd5466
-
cd5466
-static DSA *
cd5466
-dsa_generate(int size)
cd5466
-{
cd5466
-    struct ossl_generate_cb_arg cb_arg = { 0 };
cd5466
-    struct dsa_blocking_gen_arg gen_arg;
cd5466
-    DSA *dsa = DSA_new();
cd5466
-    BN_GENCB *cb = BN_GENCB_new();
cd5466
-    int counter;
cd5466
-    unsigned long h;
cd5466
-
cd5466
-    if (!dsa || !cb) {
cd5466
-        DSA_free(dsa);
cd5466
-        BN_GENCB_free(cb);
cd5466
-        ossl_raise(eDSAError, "malloc failure");
cd5466
-    }
cd5466
-
cd5466
-    if (rb_block_given_p())
cd5466
-	cb_arg.yield = 1;
cd5466
-    BN_GENCB_set(cb, ossl_generate_cb_2, &cb_arg);
cd5466
-    gen_arg.dsa = dsa;
cd5466
-    gen_arg.size = size;
cd5466
-    gen_arg.counter = &counter;
cd5466
-    gen_arg.h = &h;
cd5466
-    gen_arg.cb = cb;
cd5466
-    if (cb_arg.yield == 1) {
cd5466
-	/* we cannot release GVL when callback proc is supplied */
cd5466
-	dsa_blocking_gen(&gen_arg);
cd5466
-    } else {
cd5466
-	/* there's a chance to unblock */
cd5466
-	rb_thread_call_without_gvl(dsa_blocking_gen, &gen_arg, ossl_generate_cb_stop, &cb_arg);
cd5466
-    }
cd5466
-
cd5466
-    BN_GENCB_free(cb);
cd5466
-    if (!gen_arg.result) {
cd5466
-	DSA_free(dsa);
cd5466
-	if (cb_arg.state) {
cd5466
-	    /* Clear OpenSSL error queue before re-raising. By the way, the
cd5466
-	     * documentation of DSA_generate_parameters_ex() says the error code
cd5466
-	     * can be obtained by ERR_get_error(), but the default
cd5466
-	     * implementation, dsa_builtin_paramgen() doesn't put any error... */
cd5466
-	    ossl_clear_error();
cd5466
-	    rb_jump_tag(cb_arg.state);
cd5466
-	}
cd5466
-        ossl_raise(eDSAError, "DSA_generate_parameters_ex");
cd5466
-    }
cd5466
-
cd5466
-    if (!DSA_generate_key(dsa)) {
cd5466
-        DSA_free(dsa);
cd5466
-        ossl_raise(eDSAError, "DSA_generate_key");
cd5466
-    }
cd5466
-
cd5466
-    return dsa;
cd5466
-}
cd5466
-
cd5466
-/*
cd5466
- *  call-seq:
cd5466
- *    DSA.generate(size) -> dsa
cd5466
- *
cd5466
- * Creates a new DSA instance by generating a private/public key pair
cd5466
- * from scratch.
cd5466
- *
cd5466
- * === Parameters
cd5466
- * * _size_ is an integer representing the desired key size.
cd5466
- *
cd5466
- */
cd5466
-static VALUE
cd5466
-ossl_dsa_s_generate(VALUE klass, VALUE size)
cd5466
-{
cd5466
-    EVP_PKEY *pkey;
cd5466
-    DSA *dsa;
cd5466
-    VALUE obj;
cd5466
-
cd5466
-    obj = rb_obj_alloc(klass);
cd5466
-    GetPKey(obj, pkey);
cd5466
-
cd5466
-    dsa = dsa_generate(NUM2INT(size));
cd5466
-    if (!EVP_PKEY_assign_DSA(pkey, dsa)) {
cd5466
-        DSA_free(dsa);
cd5466
-        ossl_raise(eDSAError, "EVP_PKEY_assign_DSA");
cd5466
-    }
cd5466
-    return obj;
cd5466
-}
cd5466
-
cd5466
 /*
cd5466
  *  call-seq:
cd5466
  *    DSA.new -> dsa
cd5466
- *    DSA.new(size) -> dsa
cd5466
  *    DSA.new(string [, pass]) -> dsa
cd5466
+ *    DSA.new(size) -> dsa
cd5466
  *
cd5466
  * Creates a new DSA instance by reading an existing key from _string_.
cd5466
  *
cd5466
- * === Parameters
cd5466
- * * _size_ is an integer representing the desired key size.
cd5466
- * * _string_ contains a DER or PEM encoded key.
cd5466
- * * _pass_ is a string that contains an optional password.
cd5466
+ * If called without arguments, creates a new instance with no key components
cd5466
+ * set. They can be set individually by #set_pqg and #set_key.
cd5466
  *
cd5466
- * === Examples
cd5466
- *  DSA.new -> dsa
cd5466
- *  DSA.new(1024) -> dsa
cd5466
- *  DSA.new(File.read('dsa.pem')) -> dsa
cd5466
- *  DSA.new(File.read('dsa.pem'), 'mypassword') -> dsa
cd5466
+ * If called with a String, tries to parse as DER or PEM encoding of a \DSA key.
cd5466
+ * See also OpenSSL::PKey.read which can parse keys of any kinds.
cd5466
+ *
cd5466
+ * If called with a number, generates random parameters and a key pair. This
cd5466
+ * form works as an alias of DSA.generate.
cd5466
+ *
cd5466
+ * +string+::
cd5466
+ *   A String that contains a DER or PEM encoded key.
cd5466
+ * +pass+::
cd5466
+ *   A String that contains an optional password.
cd5466
+ * +size+::
cd5466
+ *   See DSA.generate.
cd5466
  *
cd5466
+ * Examples:
cd5466
+ *   p OpenSSL::PKey::DSA.new(1024)
cd5466
+ *   #=> #<OpenSSL::PKey::DSA:0x000055a8d6025bf0 oid=DSA>
cd5466
+ *
cd5466
+ *   p OpenSSL::PKey::DSA.new(File.read('dsa.pem'))
cd5466
+ *   #=> #<OpenSSL::PKey::DSA:0x000055555d6b8110 oid=DSA>
cd5466
+ *
cd5466
+ *   p OpenSSL::PKey::DSA.new(File.read('dsa.pem'), 'mypassword')
cd5466
+ *   #=> #<OpenSSL::PKey::DSA:0x0000556f973c40b8 oid=DSA>
cd5466
  */
cd5466
 static VALUE
cd5466
 ossl_dsa_initialize(int argc, VALUE *argv, VALUE self)
cd5466
@@ -176,15 +89,13 @@ ossl_dsa_initialize(int argc, VALUE *argv, VALUE self)
cd5466
     VALUE arg, pass;
cd5466
 
cd5466
     GetPKey(self, pkey);
cd5466
+    /* The DSA.new(size, generator) form is handled by lib/openssl/pkey.rb */
cd5466
     rb_scan_args(argc, argv, "02", &arg, &pass);
cd5466
     if (argc == 0) {
cd5466
         dsa = DSA_new();
cd5466
         if (!dsa)
cd5466
             ossl_raise(eDSAError, "DSA_new");
cd5466
     }
cd5466
-    else if (argc == 1 && RB_INTEGER_TYPE_P(arg)) {
cd5466
-        dsa = dsa_generate(NUM2INT(arg));
cd5466
-    }
cd5466
     else {
cd5466
 	pass = ossl_pem_passwd_value(pass);
cd5466
 	arg = ossl_to_der_if_possible(arg);
cd5466
@@ -553,7 +464,6 @@ Init_ossl_dsa(void)
cd5466
      */
cd5466
     cDSA = rb_define_class_under(mPKey, "DSA", cPKey);
cd5466
 
cd5466
-    rb_define_singleton_method(cDSA, "generate", ossl_dsa_s_generate, 1);
cd5466
     rb_define_method(cDSA, "initialize", ossl_dsa_initialize, -1);
cd5466
     rb_define_method(cDSA, "initialize_copy", ossl_dsa_initialize_copy, 1);
cd5466
 
cd5466
diff --git a/test/openssl/test_pkey_dsa.rb b/test/openssl/test_pkey_dsa.rb
cd5466
index 4bf8a7b374..85bb6ec0ae 100644
cd5466
--- a/test/openssl/test_pkey_dsa.rb
cd5466
+++ b/test/openssl/test_pkey_dsa.rb
cd5466
@@ -5,31 +5,26 @@
cd5466
 
cd5466
 class OpenSSL::TestPKeyDSA < OpenSSL::PKeyTestCase
cd5466
   def test_private
cd5466
-    key = OpenSSL::PKey::DSA.new(256)
cd5466
-    assert(key.private?)
cd5466
+    key = Fixtures.pkey("dsa1024")
cd5466
+    assert_equal true, key.private?
cd5466
     key2 = OpenSSL::PKey::DSA.new(key.to_der)
cd5466
-    assert(key2.private?)
cd5466
+    assert_equal true, key2.private?
cd5466
     key3 = key.public_key
cd5466
-    assert(!key3.private?)
cd5466
+    assert_equal false, key3.private?
cd5466
     key4 = OpenSSL::PKey::DSA.new(key3.to_der)
cd5466
-    assert(!key4.private?)
cd5466
+    assert_equal false, key4.private?
cd5466
   end
cd5466
 
cd5466
   def test_new
cd5466
-    key = OpenSSL::PKey::DSA.new 256
cd5466
+    key = OpenSSL::PKey::DSA.new(2048)
cd5466
     pem  = key.public_key.to_pem
cd5466
     OpenSSL::PKey::DSA.new pem
cd5466
-    if $0 == __FILE__
cd5466
-      assert_nothing_raised {
cd5466
-        key = OpenSSL::PKey::DSA.new 2048
cd5466
-      }
cd5466
-    end
cd5466
   end
cd5466
 
cd5466
   def test_new_break
cd5466
-    assert_nil(OpenSSL::PKey::DSA.new(512) { break })
cd5466
+    assert_nil(OpenSSL::PKey::DSA.new(2048) { break })
cd5466
     assert_raise(RuntimeError) do
cd5466
-      OpenSSL::PKey::DSA.new(512) { raise }
cd5466
+      OpenSSL::PKey::DSA.new(2048) { raise }
cd5466
     end
cd5466
   end
cd5466
 
cd5466
@@ -184,7 +179,7 @@ def test_read_DSAPublicKey_pem
cd5466
   end
cd5466
 
cd5466
   def test_dup
cd5466
-    key = OpenSSL::PKey::DSA.new(256)
cd5466
+    key = Fixtures.pkey("dsa1024")
cd5466
     key2 = key.dup
cd5466
     assert_equal key.params, key2.params
cd5466
     key2.set_pqg(key2.p + 1, key2.q, key2.g)
cd5466
-- 
cd5466
2.32.0
cd5466
cd5466
cd5466
From ba5a3a5c3eabf969f5cd2232b022e440af803b5b Mon Sep 17 00:00:00 2001
cd5466
From: Kazuki Yamaguchi <k@rhe.jp>
cd5466
Date: Mon, 5 Apr 2021 00:39:04 +0900
cd5466
Subject: [PATCH 5/5] pkey: remove unused ossl_generate_cb_2() helper function
cd5466
cd5466
The previous series of commits re-implemented key generation with the
cd5466
low level API with the EVP API. The BN_GENCB-based callback function is
cd5466
no longer used.
cd5466
---
cd5466
 ext/openssl/extconf.rb        |  3 --
cd5466
 ext/openssl/openssl_missing.h | 12 ------
cd5466
 ext/openssl/ossl_pkey.c       | 73 +++++++----------------------------
cd5466
 ext/openssl/ossl_pkey.h       |  8 ----
cd5466
 4 files changed, 15 insertions(+), 81 deletions(-)
cd5466
cd5466
diff --git a/ext/openssl/extconf.rb b/ext/openssl/extconf.rb
cd5466
index 693e55cd97..b3c6647faf 100644
cd5466
--- a/ext/openssl/extconf.rb
cd5466
+++ b/ext/openssl/extconf.rb
cd5466
@@ -136,9 +136,6 @@ def find_openssl_library
cd5466
   $defs.push("-DHAVE_OPAQUE_OPENSSL")
cd5466
 end
cd5466
 have_func("CRYPTO_lock") || $defs.push("-DHAVE_OPENSSL_110_THREADING_API")
cd5466
-have_func("BN_GENCB_new")
cd5466
-have_func("BN_GENCB_free")
cd5466
-have_func("BN_GENCB_get_arg")
cd5466
 have_func("EVP_MD_CTX_new")
cd5466
 have_func("EVP_MD_CTX_free")
cd5466
 have_func("EVP_MD_CTX_pkey_ctx")
cd5466
diff --git a/ext/openssl/openssl_missing.h b/ext/openssl/openssl_missing.h
cd5466
index 7d218f86f5..e575415f49 100644
cd5466
--- a/ext/openssl/openssl_missing.h
cd5466
+++ b/ext/openssl/openssl_missing.h
cd5466
@@ -34,18 +34,6 @@ int ossl_EC_curve_nist2nid(const char *);
cd5466
 #endif
cd5466
 
cd5466
 /* added in 1.1.0 */
cd5466
-#if !defined(HAVE_BN_GENCB_NEW)
cd5466
-#  define BN_GENCB_new() ((BN_GENCB *)OPENSSL_malloc(sizeof(BN_GENCB)))
cd5466
-#endif
cd5466
-
cd5466
-#if !defined(HAVE_BN_GENCB_FREE)
cd5466
-#  define BN_GENCB_free(cb) OPENSSL_free(cb)
cd5466
-#endif
cd5466
-
cd5466
-#if !defined(HAVE_BN_GENCB_GET_ARG)
cd5466
-#  define BN_GENCB_get_arg(cb) (cb)->arg
cd5466
-#endif
cd5466
-
cd5466
 #if !defined(HAVE_EVP_MD_CTX_NEW)
cd5466
 #  define EVP_MD_CTX_new EVP_MD_CTX_create
cd5466
 #endif
cd5466
diff --git a/ext/openssl/ossl_pkey.c b/ext/openssl/ossl_pkey.c
cd5466
index d76f0600d1..f9282b9417 100644
cd5466
--- a/ext/openssl/ossl_pkey.c
cd5466
+++ b/ext/openssl/ossl_pkey.c
cd5466
@@ -17,64 +17,6 @@ VALUE cPKey;
cd5466
 VALUE ePKeyError;
cd5466
 static ID id_private_q;
cd5466
 
cd5466
-/*
cd5466
- * callback for generating keys
cd5466
- */
cd5466
-static VALUE
cd5466
-call_check_ints0(VALUE arg)
cd5466
-{
cd5466
-    rb_thread_check_ints();
cd5466
-    return Qnil;
cd5466
-}
cd5466
-
cd5466
-static void *
cd5466
-call_check_ints(void *arg)
cd5466
-{
cd5466
-    int state;
cd5466
-    rb_protect(call_check_ints0, Qnil, &state);
cd5466
-    return (void *)(VALUE)state;
cd5466
-}
cd5466
-
cd5466
-int
cd5466
-ossl_generate_cb_2(int p, int n, BN_GENCB *cb)
cd5466
-{
cd5466
-    VALUE ary;
cd5466
-    struct ossl_generate_cb_arg *arg;
cd5466
-    int state;
cd5466
-
cd5466
-    arg = (struct ossl_generate_cb_arg *)BN_GENCB_get_arg(cb);
cd5466
-    if (arg->yield) {
cd5466
-	ary = rb_ary_new2(2);
cd5466
-	rb_ary_store(ary, 0, INT2NUM(p));
cd5466
-	rb_ary_store(ary, 1, INT2NUM(n));
cd5466
-
cd5466
-	/*
cd5466
-	* can be break by raising exception or 'break'
cd5466
-	*/
cd5466
-	rb_protect(rb_yield, ary, &state);
cd5466
-	if (state) {
cd5466
-	    arg->state = state;
cd5466
-	    return 0;
cd5466
-	}
cd5466
-    }
cd5466
-    if (arg->interrupted) {
cd5466
-	arg->interrupted = 0;
cd5466
-	state = (int)(VALUE)rb_thread_call_with_gvl(call_check_ints, NULL);
cd5466
-	if (state) {
cd5466
-	    arg->state = state;
cd5466
-	    return 0;
cd5466
-	}
cd5466
-    }
cd5466
-    return 1;
cd5466
-}
cd5466
-
cd5466
-void
cd5466
-ossl_generate_cb_stop(void *ptr)
cd5466
-{
cd5466
-    struct ossl_generate_cb_arg *arg = (struct ossl_generate_cb_arg *)ptr;
cd5466
-    arg->interrupted = 1;
cd5466
-}
cd5466
-
cd5466
 static void
cd5466
 ossl_evp_pkey_free(void *ptr)
cd5466
 {
cd5466
@@ -257,6 +199,21 @@ pkey_gen_cb_yield(VALUE ctx_v)
cd5466
     return rb_yield_values2(info_num, argv);
cd5466
 }
cd5466
 
cd5466
+static VALUE
cd5466
+call_check_ints0(VALUE arg)
cd5466
+{
cd5466
+    rb_thread_check_ints();
cd5466
+    return Qnil;
cd5466
+}
cd5466
+
cd5466
+static void *
cd5466
+call_check_ints(void *arg)
cd5466
+{
cd5466
+    int state;
cd5466
+    rb_protect(call_check_ints0, Qnil, &state);
cd5466
+    return (void *)(VALUE)state;
cd5466
+}
cd5466
+
cd5466
 static int
cd5466
 pkey_gen_cb(EVP_PKEY_CTX *ctx)
cd5466
 {
cd5466
diff --git a/ext/openssl/ossl_pkey.h b/ext/openssl/ossl_pkey.h
cd5466
index 7dbaed47bc..629c16ae1f 100644
cd5466
--- a/ext/openssl/ossl_pkey.h
cd5466
+++ b/ext/openssl/ossl_pkey.h
cd5466
@@ -35,14 +35,6 @@ extern const rb_data_type_t ossl_evp_pkey_type;
cd5466
     } \
cd5466
 } while (0)
cd5466
 
cd5466
-struct ossl_generate_cb_arg {
cd5466
-    int yield;
cd5466
-    int interrupted;
cd5466
-    int state;
cd5466
-};
cd5466
-int ossl_generate_cb_2(int p, int n, BN_GENCB *cb);
cd5466
-void ossl_generate_cb_stop(void *ptr);
cd5466
-
cd5466
 VALUE ossl_pkey_new(EVP_PKEY *);
cd5466
 void ossl_pkey_check_public_key(const EVP_PKEY *);
cd5466
 EVP_PKEY *ossl_pkey_read_generic(BIO *, VALUE);
cd5466
-- 
cd5466
2.32.0
cd5466