6daba0
From 8b8e1d7f9b6b5a335864bbd0716df2af1ec41d91 Mon Sep 17 00:00:00 2001
6daba0
From: Kazuki Yamaguchi <k@rhe.jp>
6daba0
Date: Thu, 16 Mar 2017 16:06:53 +0900
6daba0
Subject: [PATCH 1/5] pkey: simplify ossl_pkey_new()
6daba0
6daba0
ossl_{rsa,dsa,dh,ec}_new() called from this function are not used
6daba0
anywhere else. Inline them into pkey_new0() and reduce code
6daba0
duplication.
6daba0
---
6daba0
 ext/openssl/ossl_pkey.c     | 22 +++++++++-------------
6daba0
 ext/openssl/ossl_pkey.h     |  3 ---
6daba0
 ext/openssl/ossl_pkey_dh.c  | 21 ---------------------
6daba0
 ext/openssl/ossl_pkey_dsa.c | 21 ---------------------
6daba0
 ext/openssl/ossl_pkey_ec.c  | 20 --------------------
6daba0
 ext/openssl/ossl_pkey_rsa.c | 22 ----------------------
6daba0
 6 files changed, 9 insertions(+), 100 deletions(-)
6daba0
6daba0
diff --git a/ext/openssl/ossl_pkey.c b/ext/openssl/ossl_pkey.c
6daba0
index 23204087ac..c6dbf57272 100644
6daba0
--- a/ext/openssl/ossl_pkey.c
6daba0
+++ b/ext/openssl/ossl_pkey.c
6daba0
@@ -95,7 +95,7 @@ const rb_data_type_t ossl_evp_pkey_type = {
6daba0
 static VALUE
6daba0
 pkey_new0(EVP_PKEY *pkey)
6daba0
 {
6daba0
-    VALUE obj;
6daba0
+    VALUE klass, obj;
6daba0
     int type;
6daba0
 
6daba0
     if (!pkey || (type = EVP_PKEY_base_id(pkey)) == EVP_PKEY_NONE)
6daba0
@@ -103,26 +103,22 @@ pkey_new0(EVP_PKEY *pkey)
6daba0
 
6daba0
     switch (type) {
6daba0
 #if !defined(OPENSSL_NO_RSA)
6daba0
-    case EVP_PKEY_RSA:
6daba0
-	return ossl_rsa_new(pkey);
6daba0
+      case EVP_PKEY_RSA: klass = cRSA; break;
6daba0
 #endif
6daba0
 #if !defined(OPENSSL_NO_DSA)
6daba0
-    case EVP_PKEY_DSA:
6daba0
-	return ossl_dsa_new(pkey);
6daba0
+      case EVP_PKEY_DSA: klass = cDSA; break;
6daba0
 #endif
6daba0
 #if !defined(OPENSSL_NO_DH)
6daba0
-    case EVP_PKEY_DH:
6daba0
-	return ossl_dh_new(pkey);
6daba0
+      case EVP_PKEY_DH:  klass = cDH; break;
6daba0
 #endif
6daba0
 #if !defined(OPENSSL_NO_EC)
6daba0
-    case EVP_PKEY_EC:
6daba0
-	return ossl_ec_new(pkey);
6daba0
+      case EVP_PKEY_EC:  klass = cEC; break;
6daba0
 #endif
6daba0
-    default:
6daba0
-	obj = NewPKey(cPKey);
6daba0
-	SetPKey(obj, pkey);
6daba0
-	return obj;
6daba0
+      default:           klass = cPKey; break;
6daba0
     }
6daba0
+    obj = NewPKey(klass);
6daba0
+    SetPKey(obj, pkey);
6daba0
+    return obj;
6daba0
 }
6daba0
 
6daba0
 VALUE
6daba0
diff --git a/ext/openssl/ossl_pkey.h b/ext/openssl/ossl_pkey.h
6daba0
index 0db59305f7..e363a261c2 100644
6daba0
--- a/ext/openssl/ossl_pkey.h
6daba0
+++ b/ext/openssl/ossl_pkey.h
6daba0
@@ -56,7 +56,6 @@ void Init_ossl_pkey(void);
6daba0
 extern VALUE cRSA;
6daba0
 extern VALUE eRSAError;
6daba0
 
6daba0
-VALUE ossl_rsa_new(EVP_PKEY *);
6daba0
 void Init_ossl_rsa(void);
6daba0
 
6daba0
 /*
6daba0
@@ -65,7 +64,6 @@ void Init_ossl_rsa(void);
6daba0
 extern VALUE cDSA;
6daba0
 extern VALUE eDSAError;
6daba0
 
6daba0
-VALUE ossl_dsa_new(EVP_PKEY *);
6daba0
 void Init_ossl_dsa(void);
6daba0
 
6daba0
 /*
6daba0
@@ -74,7 +72,6 @@ void Init_ossl_dsa(void);
6daba0
 extern VALUE cDH;
6daba0
 extern VALUE eDHError;
6daba0
 
6daba0
-VALUE ossl_dh_new(EVP_PKEY *);
6daba0
 void Init_ossl_dh(void);
6daba0
 
6daba0
 /*
6daba0
diff --git a/ext/openssl/ossl_pkey_dh.c b/ext/openssl/ossl_pkey_dh.c
6daba0
index bf4e3f9322..dff69cfc33 100644
6daba0
--- a/ext/openssl/ossl_pkey_dh.c
6daba0
+++ b/ext/openssl/ossl_pkey_dh.c
6daba0
@@ -54,27 +54,6 @@ dh_instance(VALUE klass, DH *dh)
6daba0
     return obj;
6daba0
 }
6daba0
 
6daba0
-VALUE
6daba0
-ossl_dh_new(EVP_PKEY *pkey)
6daba0
-{
6daba0
-    VALUE obj;
6daba0
-
6daba0
-    if (!pkey) {
6daba0
-	obj = dh_instance(cDH, DH_new());
6daba0
-    } else {
6daba0
-	obj = NewPKey(cDH);
6daba0
-	if (EVP_PKEY_base_id(pkey) != EVP_PKEY_DH) {
6daba0
-	    ossl_raise(rb_eTypeError, "Not a DH key!");
6daba0
-	}
6daba0
-	SetPKey(obj, pkey);
6daba0
-    }
6daba0
-    if (obj == Qfalse) {
6daba0
-	ossl_raise(eDHError, NULL);
6daba0
-    }
6daba0
-
6daba0
-    return obj;
6daba0
-}
6daba0
-
6daba0
 /*
6daba0
  * Private
6daba0
  */
6daba0
diff --git a/ext/openssl/ossl_pkey_dsa.c b/ext/openssl/ossl_pkey_dsa.c
6daba0
index 431c20e05c..e9be9ac482 100644
6daba0
--- a/ext/openssl/ossl_pkey_dsa.c
6daba0
+++ b/ext/openssl/ossl_pkey_dsa.c
6daba0
@@ -68,27 +68,6 @@ dsa_instance(VALUE klass, DSA *dsa)
6daba0
     return obj;
6daba0
 }
6daba0
 
6daba0
-VALUE
6daba0
-ossl_dsa_new(EVP_PKEY *pkey)
6daba0
-{
6daba0
-    VALUE obj;
6daba0
-
6daba0
-    if (!pkey) {
6daba0
-	obj = dsa_instance(cDSA, DSA_new());
6daba0
-    } else {
6daba0
-	obj = NewPKey(cDSA);
6daba0
-	if (EVP_PKEY_base_id(pkey) != EVP_PKEY_DSA) {
6daba0
-	    ossl_raise(rb_eTypeError, "Not a DSA key!");
6daba0
-	}
6daba0
-	SetPKey(obj, pkey);
6daba0
-    }
6daba0
-    if (obj == Qfalse) {
6daba0
-	ossl_raise(eDSAError, NULL);
6daba0
-    }
6daba0
-
6daba0
-    return obj;
6daba0
-}
6daba0
-
6daba0
 /*
6daba0
  * Private
6daba0
  */
6daba0
diff --git a/ext/openssl/ossl_pkey_ec.c b/ext/openssl/ossl_pkey_ec.c
6daba0
index fc2bc6c815..eabf495f19 100644
6daba0
--- a/ext/openssl/ossl_pkey_ec.c
6daba0
+++ b/ext/openssl/ossl_pkey_ec.c
6daba0
@@ -84,26 +84,6 @@ static VALUE ec_instance(VALUE klass, EC_KEY *ec)
6daba0
     return obj;
6daba0
 }
6daba0
 
6daba0
-VALUE ossl_ec_new(EVP_PKEY *pkey)
6daba0
-{
6daba0
-    VALUE obj;
6daba0
-
6daba0
-    if (!pkey) {
6daba0
-	obj = ec_instance(cEC, EC_KEY_new());
6daba0
-    } else {
6daba0
-	obj = NewPKey(cEC);
6daba0
-	if (EVP_PKEY_base_id(pkey) != EVP_PKEY_EC) {
6daba0
-	    ossl_raise(rb_eTypeError, "Not a EC key!");
6daba0
-	}
6daba0
-	SetPKey(obj, pkey);
6daba0
-    }
6daba0
-    if (obj == Qfalse) {
6daba0
-	ossl_raise(eECError, NULL);
6daba0
-    }
6daba0
-
6daba0
-    return obj;
6daba0
-}
6daba0
-
6daba0
 /*
6daba0
  * Creates a new EC_KEY on the EC group obj. arg can be an EC::Group or a String
6daba0
  * representing an OID.
6daba0
diff --git a/ext/openssl/ossl_pkey_rsa.c b/ext/openssl/ossl_pkey_rsa.c
6daba0
index 761866c66a..c1ae44fe40 100644
6daba0
--- a/ext/openssl/ossl_pkey_rsa.c
6daba0
+++ b/ext/openssl/ossl_pkey_rsa.c
6daba0
@@ -69,28 +69,6 @@ rsa_instance(VALUE klass, RSA *rsa)
6daba0
     return obj;
6daba0
 }
6daba0
 
6daba0
-VALUE
6daba0
-ossl_rsa_new(EVP_PKEY *pkey)
6daba0
-{
6daba0
-    VALUE obj;
6daba0
-
6daba0
-    if (!pkey) {
6daba0
-	obj = rsa_instance(cRSA, RSA_new());
6daba0
-    }
6daba0
-    else {
6daba0
-	obj = NewPKey(cRSA);
6daba0
-	if (EVP_PKEY_base_id(pkey) != EVP_PKEY_RSA) {
6daba0
-	    ossl_raise(rb_eTypeError, "Not a RSA key!");
6daba0
-	}
6daba0
-	SetPKey(obj, pkey);
6daba0
-    }
6daba0
-    if (obj == Qfalse) {
6daba0
-	ossl_raise(eRSAError, NULL);
6daba0
-    }
6daba0
-
6daba0
-    return obj;
6daba0
-}
6daba0
-
6daba0
 /*
6daba0
  * Private
6daba0
  */
6daba0
-- 
6daba0
2.32.0
6daba0
6daba0
6daba0
From 2b0d259ef7aae707922996d305675a68dad27abd Mon Sep 17 00:00:00 2001
6daba0
From: Kazuki Yamaguchi <k@rhe.jp>
6daba0
Date: Thu, 16 Mar 2017 16:09:35 +0900
6daba0
Subject: [PATCH 2/5] pkey: inline {rsa,dsa,dh,ec}_instance()
6daba0
6daba0
Merge the code into the callers so that the wrapping Ruby object is
6daba0
allocated before the raw key object is allocated. This prevents possible
6daba0
memory leak on Ruby object allocation failure, and also reduces the
6daba0
lines of code.
6daba0
---
6daba0
 ext/openssl/ossl_pkey_dh.c  | 63 ++++++++++++----------------------
6daba0
 ext/openssl/ossl_pkey_dsa.c | 68 ++++++++++++++-----------------------
6daba0
 ext/openssl/ossl_pkey_ec.c  | 34 ++++---------------
6daba0
 ext/openssl/ossl_pkey_rsa.c | 67 +++++++++++++-----------------------
6daba0
 4 files changed, 76 insertions(+), 156 deletions(-)
6daba0
6daba0
diff --git a/ext/openssl/ossl_pkey_dh.c b/ext/openssl/ossl_pkey_dh.c
6daba0
index dff69cfc33..bc50e5566b 100644
6daba0
--- a/ext/openssl/ossl_pkey_dh.c
6daba0
+++ b/ext/openssl/ossl_pkey_dh.c
6daba0
@@ -29,31 +29,6 @@
6daba0
 VALUE cDH;
6daba0
 VALUE eDHError;
6daba0
 
6daba0
-/*
6daba0
- * Public
6daba0
- */
6daba0
-static VALUE
6daba0
-dh_instance(VALUE klass, DH *dh)
6daba0
-{
6daba0
-    EVP_PKEY *pkey;
6daba0
-    VALUE obj;
6daba0
-
6daba0
-    if (!dh) {
6daba0
-	return Qfalse;
6daba0
-    }
6daba0
-    obj = NewPKey(klass);
6daba0
-    if (!(pkey = EVP_PKEY_new())) {
6daba0
-	return Qfalse;
6daba0
-    }
6daba0
-    if (!EVP_PKEY_assign_DH(pkey, dh)) {
6daba0
-	EVP_PKEY_free(pkey);
6daba0
-	return Qfalse;
6daba0
-    }
6daba0
-    SetPKey(obj, pkey);
6daba0
-
6daba0
-    return obj;
6daba0
-}
6daba0
-
6daba0
 /*
6daba0
  * Private
6daba0
  */
6daba0
@@ -84,7 +59,7 @@ dh_generate(int size, int gen)
6daba0
     if (!dh || !cb) {
6daba0
 	DH_free(dh);
6daba0
 	BN_GENCB_free(cb);
6daba0
-	return NULL;
6daba0
+        ossl_raise(eDHError, "malloc failure");
6daba0
     }
6daba0
 
6daba0
     if (rb_block_given_p())
6daba0
@@ -110,12 +85,12 @@ dh_generate(int size, int gen)
6daba0
 	    ossl_clear_error();
6daba0
 	    rb_jump_tag(cb_arg.state);
6daba0
 	}
6daba0
-	return NULL;
6daba0
+        ossl_raise(eDHError, "DH_generate_parameters_ex");
6daba0
     }
6daba0
 
6daba0
     if (!DH_generate_key(dh)) {
6daba0
         DH_free(dh);
6daba0
-        return NULL;
6daba0
+        ossl_raise(eDHError, "DH_generate_key");
6daba0
     }
6daba0
 
6daba0
     return dh;
6daba0
@@ -136,6 +111,7 @@ dh_generate(int size, int gen)
6daba0
 static VALUE
6daba0
 ossl_dh_s_generate(int argc, VALUE *argv, VALUE klass)
6daba0
 {
6daba0
+    EVP_PKEY *pkey;
6daba0
     DH *dh ;
6daba0
     int g = 2;
6daba0
     VALUE size, gen, obj;
6daba0
@@ -143,13 +119,14 @@ ossl_dh_s_generate(int argc, VALUE *argv, VALUE klass)
6daba0
     if (rb_scan_args(argc, argv, "11", &size, &gen) == 2) {
6daba0
 	g = NUM2INT(gen);
6daba0
     }
6daba0
+    obj = rb_obj_alloc(klass);
6daba0
+    GetPKey(obj, pkey);
6daba0
+
6daba0
     dh = dh_generate(NUM2INT(size), g);
6daba0
-    obj = dh_instance(klass, dh);
6daba0
-    if (obj == Qfalse) {
6daba0
-	DH_free(dh);
6daba0
-	ossl_raise(eDHError, NULL);
6daba0
+    if (!EVP_PKEY_assign_DH(pkey, dh)) {
6daba0
+        DH_free(dh);
6daba0
+        ossl_raise(eDHError, "EVP_PKEY_assign_DH");
6daba0
     }
6daba0
-
6daba0
     return obj;
6daba0
 }
6daba0
 
6daba0
@@ -195,9 +172,7 @@ ossl_dh_initialize(int argc, VALUE *argv, VALUE self)
6daba0
 	if (!NIL_P(gen)) {
6daba0
 	    g = NUM2INT(gen);
6daba0
 	}
6daba0
-	if (!(dh = dh_generate(NUM2INT(arg), g))) {
6daba0
-	    ossl_raise(eDHError, NULL);
6daba0
-	}
6daba0
+        dh = dh_generate(NUM2INT(arg), g);
6daba0
     }
6daba0
     else {
6daba0
 	arg = ossl_to_der_if_possible(arg);
6daba0
@@ -434,17 +409,21 @@ ossl_dh_to_text(VALUE self)
6daba0
 static VALUE
6daba0
 ossl_dh_to_public_key(VALUE self)
6daba0
 {
6daba0
+    EVP_PKEY *pkey;
6daba0
     DH *orig_dh, *dh;
6daba0
     VALUE obj;
6daba0
 
6daba0
+    obj = rb_obj_alloc(rb_obj_class(self));
6daba0
+    GetPKey(obj, pkey);
6daba0
+
6daba0
     GetDH(self, orig_dh);
6daba0
-    dh = DHparams_dup(orig_dh); /* err check perfomed by dh_instance */
6daba0
-    obj = dh_instance(rb_obj_class(self), dh);
6daba0
-    if (obj == Qfalse) {
6daba0
-	DH_free(dh);
6daba0
-	ossl_raise(eDHError, NULL);
6daba0
+    dh = DHparams_dup(orig_dh);
6daba0
+    if (!dh)
6daba0
+        ossl_raise(eDHError, "DHparams_dup");
6daba0
+    if (!EVP_PKEY_assign_DH(pkey, dh)) {
6daba0
+        DH_free(dh);
6daba0
+        ossl_raise(eDHError, "EVP_PKEY_assign_DH");
6daba0
     }
6daba0
-
6daba0
     return obj;
6daba0
 }
6daba0
 
6daba0
diff --git a/ext/openssl/ossl_pkey_dsa.c b/ext/openssl/ossl_pkey_dsa.c
6daba0
index e9be9ac482..c907f31c19 100644
6daba0
--- a/ext/openssl/ossl_pkey_dsa.c
6daba0
+++ b/ext/openssl/ossl_pkey_dsa.c
6daba0
@@ -43,31 +43,6 @@ DSA_PRIVATE(VALUE obj, DSA *dsa)
6daba0
 VALUE cDSA;
6daba0
 VALUE eDSAError;
6daba0
 
6daba0
-/*
6daba0
- * Public
6daba0
- */
6daba0
-static VALUE
6daba0
-dsa_instance(VALUE klass, DSA *dsa)
6daba0
-{
6daba0
-    EVP_PKEY *pkey;
6daba0
-    VALUE obj;
6daba0
-
6daba0
-    if (!dsa) {
6daba0
-	return Qfalse;
6daba0
-    }
6daba0
-    obj = NewPKey(klass);
6daba0
-    if (!(pkey = EVP_PKEY_new())) {
6daba0
-	return Qfalse;
6daba0
-    }
6daba0
-    if (!EVP_PKEY_assign_DSA(pkey, dsa)) {
6daba0
-	EVP_PKEY_free(pkey);
6daba0
-	return Qfalse;
6daba0
-    }
6daba0
-    SetPKey(obj, pkey);
6daba0
-
6daba0
-    return obj;
6daba0
-}
6daba0
-
6daba0
 /*
6daba0
  * Private
6daba0
  */
6daba0
@@ -100,9 +75,9 @@ dsa_generate(int size)
6daba0
     unsigned long h;
6daba0
 
6daba0
     if (!dsa || !cb) {
6daba0
-	DSA_free(dsa);
6daba0
-	BN_GENCB_free(cb);
6daba0
-	return NULL;
6daba0
+        DSA_free(dsa);
6daba0
+        BN_GENCB_free(cb);
6daba0
+        ossl_raise(eDSAError, "malloc failure");
6daba0
     }
6daba0
 
6daba0
     if (rb_block_given_p())
6daba0
@@ -132,12 +107,12 @@ dsa_generate(int size)
6daba0
 	    ossl_clear_error();
6daba0
 	    rb_jump_tag(cb_arg.state);
6daba0
 	}
6daba0
-	return NULL;
6daba0
+        ossl_raise(eDSAError, "DSA_generate_parameters_ex");
6daba0
     }
6daba0
 
6daba0
     if (!DSA_generate_key(dsa)) {
6daba0
-	DSA_free(dsa);
6daba0
-	return NULL;
6daba0
+        DSA_free(dsa);
6daba0
+        ossl_raise(eDSAError, "DSA_generate_key");
6daba0
     }
6daba0
 
6daba0
     return dsa;
6daba0
@@ -157,14 +132,18 @@ dsa_generate(int size)
6daba0
 static VALUE
6daba0
 ossl_dsa_s_generate(VALUE klass, VALUE size)
6daba0
 {
6daba0
-    DSA *dsa = dsa_generate(NUM2INT(size)); /* err handled by dsa_instance */
6daba0
-    VALUE obj = dsa_instance(klass, dsa);
6daba0
+    EVP_PKEY *pkey;
6daba0
+    DSA *dsa;
6daba0
+    VALUE obj;
6daba0
 
6daba0
-    if (obj == Qfalse) {
6daba0
-	DSA_free(dsa);
6daba0
-	ossl_raise(eDSAError, NULL);
6daba0
-    }
6daba0
+    obj = rb_obj_alloc(klass);
6daba0
+    GetPKey(obj, pkey);
6daba0
 
6daba0
+    dsa = dsa_generate(NUM2INT(size));
6daba0
+    if (!EVP_PKEY_assign_DSA(pkey, dsa)) {
6daba0
+        DSA_free(dsa);
6daba0
+        ossl_raise(eDSAError, "EVP_PKEY_assign_DSA");
6daba0
+    }
6daba0
     return obj;
6daba0
 }
6daba0
 
6daba0
@@ -460,20 +439,23 @@ ossl_dsa_to_text(VALUE self)
6daba0
 static VALUE
6daba0
 ossl_dsa_to_public_key(VALUE self)
6daba0
 {
6daba0
-    EVP_PKEY *pkey;
6daba0
+    EVP_PKEY *pkey, *pkey_new;
6daba0
     DSA *dsa;
6daba0
     VALUE obj;
6daba0
 
6daba0
     GetPKeyDSA(self, pkey);
6daba0
-    /* err check performed by dsa_instance */
6daba0
+    obj = rb_obj_alloc(rb_obj_class(self));
6daba0
+    GetPKey(obj, pkey_new);
6daba0
+
6daba0
 #define DSAPublicKey_dup(dsa) (DSA *)ASN1_dup( \
6daba0
 	(i2d_of_void *)i2d_DSAPublicKey, (d2i_of_void *)d2i_DSAPublicKey, (char *)(dsa))
6daba0
     dsa = DSAPublicKey_dup(EVP_PKEY_get0_DSA(pkey));
6daba0
 #undef DSAPublicKey_dup
6daba0
-    obj = dsa_instance(rb_obj_class(self), dsa);
6daba0
-    if (obj == Qfalse) {
6daba0
-	DSA_free(dsa);
6daba0
-	ossl_raise(eDSAError, NULL);
6daba0
+    if (!dsa)
6daba0
+        ossl_raise(eDSAError, "DSAPublicKey_dup");
6daba0
+    if (!EVP_PKEY_assign_DSA(pkey_new, dsa)) {
6daba0
+        DSA_free(dsa);
6daba0
+        ossl_raise(eDSAError, "EVP_PKEY_assign_DSA");
6daba0
     }
6daba0
     return obj;
6daba0
 }
6daba0
diff --git a/ext/openssl/ossl_pkey_ec.c b/ext/openssl/ossl_pkey_ec.c
6daba0
index eabf495f19..aec9d1e60f 100644
6daba0
--- a/ext/openssl/ossl_pkey_ec.c
6daba0
+++ b/ext/openssl/ossl_pkey_ec.c
6daba0
@@ -63,27 +63,6 @@ static ID id_i_group;
6daba0
 static VALUE ec_group_new(const EC_GROUP *group);
6daba0
 static VALUE ec_point_new(const EC_POINT *point, const EC_GROUP *group);
6daba0
 
6daba0
-static VALUE ec_instance(VALUE klass, EC_KEY *ec)
6daba0
-{
6daba0
-    EVP_PKEY *pkey;
6daba0
-    VALUE obj;
6daba0
-
6daba0
-    if (!ec) {
6daba0
-	return Qfalse;
6daba0
-    }
6daba0
-    obj = NewPKey(klass);
6daba0
-    if (!(pkey = EVP_PKEY_new())) {
6daba0
-	return Qfalse;
6daba0
-    }
6daba0
-    if (!EVP_PKEY_assign_EC_KEY(pkey, ec)) {
6daba0
-	EVP_PKEY_free(pkey);
6daba0
-	return Qfalse;
6daba0
-    }
6daba0
-    SetPKey(obj, pkey);
6daba0
-
6daba0
-    return obj;
6daba0
-}
6daba0
-
6daba0
 /*
6daba0
  * Creates a new EC_KEY on the EC group obj. arg can be an EC::Group or a String
6daba0
  * representing an OID.
6daba0
@@ -130,17 +109,18 @@ ec_key_new_from_group(VALUE arg)
6daba0
 static VALUE
6daba0
 ossl_ec_key_s_generate(VALUE klass, VALUE arg)
6daba0
 {
6daba0
+    EVP_PKEY *pkey;
6daba0
     EC_KEY *ec;
6daba0
     VALUE obj;
6daba0
 
6daba0
-    ec = ec_key_new_from_group(arg);
6daba0
+    obj = rb_obj_alloc(klass);
6daba0
+    GetPKey(obj, pkey);
6daba0
 
6daba0
-    obj = ec_instance(klass, ec);
6daba0
-    if (obj == Qfalse) {
6daba0
-	EC_KEY_free(ec);
6daba0
-	ossl_raise(eECError, NULL);
6daba0
+    ec = ec_key_new_from_group(arg);
6daba0
+    if (!EVP_PKEY_assign_EC_KEY(pkey, ec)) {
6daba0
+        EC_KEY_free(ec);
6daba0
+        ossl_raise(eECError, "EVP_PKEY_assign_EC_KEY");
6daba0
     }
6daba0
-
6daba0
     if (!EC_KEY_generate_key(ec))
6daba0
 	ossl_raise(eECError, "EC_KEY_generate_key");
6daba0
 
6daba0
diff --git a/ext/openssl/ossl_pkey_rsa.c b/ext/openssl/ossl_pkey_rsa.c
6daba0
index c1ae44fe40..fbdb9c8960 100644
6daba0
--- a/ext/openssl/ossl_pkey_rsa.c
6daba0
+++ b/ext/openssl/ossl_pkey_rsa.c
6daba0
@@ -44,31 +44,6 @@ RSA_PRIVATE(VALUE obj, RSA *rsa)
6daba0
 VALUE cRSA;
6daba0
 VALUE eRSAError;
6daba0
 
6daba0
-/*
6daba0
- * Public
6daba0
- */
6daba0
-static VALUE
6daba0
-rsa_instance(VALUE klass, RSA *rsa)
6daba0
-{
6daba0
-    EVP_PKEY *pkey;
6daba0
-    VALUE obj;
6daba0
-
6daba0
-    if (!rsa) {
6daba0
-	return Qfalse;
6daba0
-    }
6daba0
-    obj = NewPKey(klass);
6daba0
-    if (!(pkey = EVP_PKEY_new())) {
6daba0
-	return Qfalse;
6daba0
-    }
6daba0
-    if (!EVP_PKEY_assign_RSA(pkey, rsa)) {
6daba0
-	EVP_PKEY_free(pkey);
6daba0
-	return Qfalse;
6daba0
-    }
6daba0
-    SetPKey(obj, pkey);
6daba0
-
6daba0
-    return obj;
6daba0
-}
6daba0
-
6daba0
 /*
6daba0
  * Private
6daba0
  */
6daba0
@@ -102,7 +77,7 @@ rsa_generate(int size, unsigned long exp)
6daba0
 	RSA_free(rsa);
6daba0
 	BN_free(e);
6daba0
 	BN_GENCB_free(cb);
6daba0
-	return NULL;
6daba0
+        ossl_raise(eRSAError, "malloc failure");
6daba0
     }
6daba0
     for (i = 0; i < (int)sizeof(exp) * 8; ++i) {
6daba0
 	if (exp & (1UL << i)) {
6daba0
@@ -110,7 +85,7 @@ rsa_generate(int size, unsigned long exp)
6daba0
 		BN_free(e);
6daba0
 		RSA_free(rsa);
6daba0
 		BN_GENCB_free(cb);
6daba0
-		return NULL;
6daba0
+                ossl_raise(eRSAError, "BN_set_bit");
6daba0
 	    }
6daba0
 	}
6daba0
     }
6daba0
@@ -139,7 +114,7 @@ rsa_generate(int size, unsigned long exp)
6daba0
 	    ossl_clear_error();
6daba0
 	    rb_jump_tag(cb_arg.state);
6daba0
 	}
6daba0
-	return NULL;
6daba0
+        ossl_raise(eRSAError, "RSA_generate_key_ex");
6daba0
     }
6daba0
 
6daba0
     return rsa;
6daba0
@@ -158,26 +133,26 @@ static VALUE
6daba0
 ossl_rsa_s_generate(int argc, VALUE *argv, VALUE klass)
6daba0
 {
6daba0
 /* why does this method exist?  why can't initialize take an optional exponent? */
6daba0
+    EVP_PKEY *pkey;
6daba0
     RSA *rsa;
6daba0
     VALUE size, exp;
6daba0
     VALUE obj;
6daba0
 
6daba0
     rb_scan_args(argc, argv, "11", &size, &exp);
6daba0
+    obj = rb_obj_alloc(klass);
6daba0
+    GetPKey(obj, pkey);
6daba0
 
6daba0
-    rsa = rsa_generate(NUM2INT(size), NIL_P(exp) ? RSA_F4 : NUM2ULONG(exp)); /* err handled by rsa_instance */
6daba0
-    obj = rsa_instance(klass, rsa);
6daba0
-
6daba0
-    if (obj == Qfalse) {
6daba0
-	RSA_free(rsa);
6daba0
-	ossl_raise(eRSAError, NULL);
6daba0
+    rsa = rsa_generate(NUM2INT(size), NIL_P(exp) ? RSA_F4 : NUM2ULONG(exp));
6daba0
+    if (!EVP_PKEY_assign_RSA(pkey, rsa)) {
6daba0
+        RSA_free(rsa);
6daba0
+        ossl_raise(eRSAError, "EVP_PKEY_assign_RSA");
6daba0
     }
6daba0
-
6daba0
     return obj;
6daba0
 }
6daba0
 
6daba0
 /*
6daba0
  * call-seq:
6daba0
- *   RSA.new(key_size)                 => RSA instance
6daba0
+ *   RSA.new(size [, exponent])        => RSA instance
6daba0
  *   RSA.new(encoded_key)              => RSA instance
6daba0
  *   RSA.new(encoded_key, pass_phrase) => RSA instance
6daba0
  *
6daba0
@@ -206,10 +181,11 @@ ossl_rsa_initialize(int argc, VALUE *argv, VALUE self)
6daba0
     GetPKey(self, pkey);
6daba0
     if(rb_scan_args(argc, argv, "02", &arg, &pass) == 0) {
6daba0
 	rsa = RSA_new();
6daba0
+        if (!rsa)
6daba0
+            ossl_raise(eRSAError, "RSA_new");
6daba0
     }
6daba0
     else if (RB_INTEGER_TYPE_P(arg)) {
6daba0
 	rsa = rsa_generate(NUM2INT(arg), NIL_P(pass) ? RSA_F4 : NUM2ULONG(pass));
6daba0
-	if (!rsa) ossl_raise(eRSAError, NULL);
6daba0
     }
6daba0
     else {
6daba0
 	pass = ossl_pem_passwd_value(pass);
6daba0
@@ -243,7 +219,7 @@ ossl_rsa_initialize(int argc, VALUE *argv, VALUE self)
6daba0
     }
6daba0
     if (!EVP_PKEY_assign_RSA(pkey, rsa)) {
6daba0
 	RSA_free(rsa);
6daba0
-	ossl_raise(eRSAError, NULL);
6daba0
+	ossl_raise(eRSAError, "EVP_PKEY_assign_RSA");
6daba0
     }
6daba0
 
6daba0
     return self;
6daba0
@@ -787,17 +763,20 @@ ossl_rsa_to_text(VALUE self)
6daba0
 static VALUE
6daba0
 ossl_rsa_to_public_key(VALUE self)
6daba0
 {
6daba0
-    EVP_PKEY *pkey;
6daba0
+    EVP_PKEY *pkey, *pkey_new;
6daba0
     RSA *rsa;
6daba0
     VALUE obj;
6daba0
 
6daba0
     GetPKeyRSA(self, pkey);
6daba0
-    /* err check performed by rsa_instance */
6daba0
+    obj = rb_obj_alloc(rb_obj_class(self));
6daba0
+    GetPKey(obj, pkey_new);
6daba0
+
6daba0
     rsa = RSAPublicKey_dup(EVP_PKEY_get0_RSA(pkey));
6daba0
-    obj = rsa_instance(rb_obj_class(self), rsa);
6daba0
-    if (obj == Qfalse) {
6daba0
-	RSA_free(rsa);
6daba0
-	ossl_raise(eRSAError, NULL);
6daba0
+    if (!rsa)
6daba0
+        ossl_raise(eRSAError, "RSAPublicKey_dup");
6daba0
+    if (!EVP_PKEY_assign_RSA(pkey_new, rsa)) {
6daba0
+        RSA_free(rsa);
6daba0
+        ossl_raise(eRSAError, "EVP_PKEY_assign_RSA");
6daba0
     }
6daba0
     return obj;
6daba0
 }
6daba0
-- 
6daba0
2.32.0
6daba0
6daba0
6daba0
From 1e1fedc6c2c9d42bc76b5a24bf0f39c8101f8d53 Mon Sep 17 00:00:00 2001
6daba0
From: Kazuki Yamaguchi <k@rhe.jp>
6daba0
Date: Sat, 18 Mar 2017 17:26:33 +0900
6daba0
Subject: [PATCH 3/5] pkey: have PKey.read parse PEM-encoded DHParameter
6daba0
6daba0
Try PEM_read_bio_Parameters(). Only PEM format is supported at the
6daba0
moment since corresponding d2i_* functions are not provided by OpenSSL.
6daba0
---
6daba0
 ext/openssl/ossl_pkey.c      | 3 +++
6daba0
 test/openssl/test_pkey_dh.rb | 2 ++
6daba0
 test/openssl/utils.rb        | 3 ---
6daba0
 3 files changed, 5 insertions(+), 3 deletions(-)
6daba0
6daba0
diff --git a/ext/openssl/ossl_pkey.c b/ext/openssl/ossl_pkey.c
6daba0
index c6dbf57272..a00d66aada 100644
6daba0
--- a/ext/openssl/ossl_pkey.c
6daba0
+++ b/ext/openssl/ossl_pkey.c
6daba0
@@ -178,6 +178,9 @@ ossl_pkey_new_from_data(int argc, VALUE *argv, VALUE self)
6daba0
     OSSL_BIO_reset(bio);
6daba0
     if ((pkey = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL)))
6daba0
 	goto ok;
6daba0
+    OSSL_BIO_reset(bio);
6daba0
+    if ((pkey = PEM_read_bio_Parameters(bio, NULL)))
6daba0
+	goto ok;
6daba0
 
6daba0
     BIO_free(bio);
6daba0
     ossl_raise(ePKeyError, "Could not parse PKey");
6daba0
diff --git a/test/openssl/test_pkey_dh.rb b/test/openssl/test_pkey_dh.rb
6daba0
index fd2c7a66a9..4a05626a12 100644
6daba0
--- a/test/openssl/test_pkey_dh.rb
6daba0
+++ b/test/openssl/test_pkey_dh.rb
6daba0
@@ -36,6 +36,8 @@ def test_DHparams
6daba0
     EOF
6daba0
     key = OpenSSL::PKey::DH.new(pem)
6daba0
     assert_same_dh dup_public(dh1024), key
6daba0
+    key = OpenSSL::PKey.read(pem)
6daba0
+    assert_same_dh dup_public(dh1024), key
6daba0
 
6daba0
     assert_equal asn1.to_der, dh1024.to_der
6daba0
     assert_equal pem, dh1024.export
6daba0
diff --git a/test/openssl/utils.rb b/test/openssl/utils.rb
6daba0
index 3776fbac4e..c1d737b2ab 100644
6daba0
--- a/test/openssl/utils.rb
6daba0
+++ b/test/openssl/utils.rb
6daba0
@@ -42,9 +42,6 @@ module Fixtures
6daba0
 
6daba0
     def pkey(name)
6daba0
       OpenSSL::PKey.read(read_file("pkey", name))
6daba0
-    rescue OpenSSL::PKey::PKeyError
6daba0
-      # TODO: DH parameters can be read by OpenSSL::PKey.read atm
6daba0
-      OpenSSL::PKey::DH.new(read_file("pkey", name))
6daba0
     end
6daba0
 
6daba0
     def read_file(category, name)
6daba0
-- 
6daba0
2.32.0
6daba0
6daba0
6daba0
From 70655b40a980dad36dfb3054d309f6484e2a70b7 Mon Sep 17 00:00:00 2001
6daba0
From: Kazuki Yamaguchi <k@rhe.jp>
6daba0
Date: Tue, 13 Jun 2017 23:39:41 +0900
6daba0
Subject: [PATCH 4/5] pkey: refactor DER/PEM-encoded string parsing code
6daba0
6daba0
Export the flow used by OpenSSL::PKey.read and let the subclasses call
6daba0
it before attempting other formats.
6daba0
---
6daba0
 ext/openssl/ossl_pkey.c     | 57 +++++++++++++++++++++----------------
6daba0
 ext/openssl/ossl_pkey.h     |  1 +
6daba0
 ext/openssl/ossl_pkey_dsa.c | 37 +++++++++++-------------
6daba0
 ext/openssl/ossl_pkey_ec.c  | 29 +++++++------------
6daba0
 ext/openssl/ossl_pkey_rsa.c | 26 ++++++++---------
6daba0
 5 files changed, 73 insertions(+), 77 deletions(-)
6daba0
6daba0
diff --git a/ext/openssl/ossl_pkey.c b/ext/openssl/ossl_pkey.c
6daba0
index a00d66aada..47ddd0f014 100644
6daba0
--- a/ext/openssl/ossl_pkey.c
6daba0
+++ b/ext/openssl/ossl_pkey.c
6daba0
@@ -136,6 +136,35 @@ ossl_pkey_new(EVP_PKEY *pkey)
6daba0
     return obj;
6daba0
 }
6daba0
 
6daba0
+EVP_PKEY *
6daba0
+ossl_pkey_read_generic(BIO *bio, VALUE pass)
6daba0
+{
6daba0
+    void *ppass = (void *)pass;
6daba0
+    EVP_PKEY *pkey;
6daba0
+
6daba0
+    if ((pkey = d2i_PrivateKey_bio(bio, NULL)))
6daba0
+	goto out;
6daba0
+    OSSL_BIO_reset(bio);
6daba0
+    if ((pkey = d2i_PKCS8PrivateKey_bio(bio, NULL, ossl_pem_passwd_cb, ppass)))
6daba0
+	goto out;
6daba0
+    OSSL_BIO_reset(bio);
6daba0
+    if ((pkey = d2i_PUBKEY_bio(bio, NULL)))
6daba0
+	goto out;
6daba0
+    OSSL_BIO_reset(bio);
6daba0
+    /* PEM_read_bio_PrivateKey() also parses PKCS #8 formats */
6daba0
+    if ((pkey = PEM_read_bio_PrivateKey(bio, NULL, ossl_pem_passwd_cb, ppass)))
6daba0
+	goto out;
6daba0
+    OSSL_BIO_reset(bio);
6daba0
+    if ((pkey = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL)))
6daba0
+	goto out;
6daba0
+    OSSL_BIO_reset(bio);
6daba0
+    if ((pkey = PEM_read_bio_Parameters(bio, NULL)))
6daba0
+	goto out;
6daba0
+
6daba0
+  out:
6daba0
+    return pkey;
6daba0
+}
6daba0
+
6daba0
 /*
6daba0
  *  call-seq:
6daba0
  *     OpenSSL::PKey.read(string [, pwd ]) -> PKey
6daba0
@@ -160,33 +189,11 @@ ossl_pkey_new_from_data(int argc, VALUE *argv, VALUE self)
6daba0
     VALUE data, pass;
6daba0
 
6daba0
     rb_scan_args(argc, argv, "11", &data, &pass);
6daba0
-    pass = ossl_pem_passwd_value(pass);
6daba0
-
6daba0
     bio = ossl_obj2bio(&data);
6daba0
-    if ((pkey = d2i_PrivateKey_bio(bio, NULL)))
6daba0
-	goto ok;
6daba0
-    OSSL_BIO_reset(bio);
6daba0
-    if ((pkey = d2i_PKCS8PrivateKey_bio(bio, NULL, ossl_pem_passwd_cb, (void *)pass)))
6daba0
-	goto ok;
6daba0
-    OSSL_BIO_reset(bio);
6daba0
-    if ((pkey = d2i_PUBKEY_bio(bio, NULL)))
6daba0
-	goto ok;
6daba0
-    OSSL_BIO_reset(bio);
6daba0
-    /* PEM_read_bio_PrivateKey() also parses PKCS #8 formats */
6daba0
-    if ((pkey = PEM_read_bio_PrivateKey(bio, NULL, ossl_pem_passwd_cb, (void *)pass)))
6daba0
-	goto ok;
6daba0
-    OSSL_BIO_reset(bio);
6daba0
-    if ((pkey = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL)))
6daba0
-	goto ok;
6daba0
-    OSSL_BIO_reset(bio);
6daba0
-    if ((pkey = PEM_read_bio_Parameters(bio, NULL)))
6daba0
-	goto ok;
6daba0
-
6daba0
-    BIO_free(bio);
6daba0
-    ossl_raise(ePKeyError, "Could not parse PKey");
6daba0
-
6daba0
-ok:
6daba0
+    pkey = ossl_pkey_read_generic(bio, ossl_pem_passwd_value(pass));
6daba0
     BIO_free(bio);
6daba0
+    if (!pkey)
6daba0
+	ossl_raise(ePKeyError, "Could not parse PKey");
6daba0
     return ossl_pkey_new(pkey);
6daba0
 }
6daba0
 
6daba0
diff --git a/ext/openssl/ossl_pkey.h b/ext/openssl/ossl_pkey.h
6daba0
index e363a261c2..895927e3fb 100644
6daba0
--- a/ext/openssl/ossl_pkey.h
6daba0
+++ b/ext/openssl/ossl_pkey.h
6daba0
@@ -45,6 +45,7 @@ void ossl_generate_cb_stop(void *ptr);
6daba0
 
6daba0
 VALUE ossl_pkey_new(EVP_PKEY *);
6daba0
 void ossl_pkey_check_public_key(const EVP_PKEY *);
6daba0
+EVP_PKEY *ossl_pkey_read_generic(BIO *, VALUE);
6daba0
 EVP_PKEY *GetPKeyPtr(VALUE);
6daba0
 EVP_PKEY *DupPKeyPtr(VALUE);
6daba0
 EVP_PKEY *GetPrivPKeyPtr(VALUE);
6daba0
diff --git a/ext/openssl/ossl_pkey_dsa.c b/ext/openssl/ossl_pkey_dsa.c
6daba0
index c907f31c19..56f58559ed 100644
6daba0
--- a/ext/openssl/ossl_pkey_dsa.c
6daba0
+++ b/ext/openssl/ossl_pkey_dsa.c
6daba0
@@ -170,37 +170,34 @@ ossl_dsa_s_generate(VALUE klass, VALUE size)
6daba0
 static VALUE
6daba0
 ossl_dsa_initialize(int argc, VALUE *argv, VALUE self)
6daba0
 {
6daba0
-    EVP_PKEY *pkey;
6daba0
-    DSA *dsa;
6daba0
+    EVP_PKEY *pkey, *tmp;
6daba0
+    DSA *dsa = NULL;
6daba0
     BIO *in;
6daba0
     VALUE arg, pass;
6daba0
 
6daba0
     GetPKey(self, pkey);
6daba0
-    if(rb_scan_args(argc, argv, "02", &arg, &pass) == 0) {
6daba0
+    rb_scan_args(argc, argv, "02", &arg, &pass);
6daba0
+    if (argc == 0) {
6daba0
         dsa = DSA_new();
6daba0
+        if (!dsa)
6daba0
+            ossl_raise(eDSAError, "DSA_new");
6daba0
     }
6daba0
-    else if (RB_INTEGER_TYPE_P(arg)) {
6daba0
-	if (!(dsa = dsa_generate(NUM2INT(arg)))) {
6daba0
-	    ossl_raise(eDSAError, NULL);
6daba0
-	}
6daba0
+    else if (argc == 1 && RB_INTEGER_TYPE_P(arg)) {
6daba0
+        dsa = dsa_generate(NUM2INT(arg));
6daba0
     }
6daba0
     else {
6daba0
 	pass = ossl_pem_passwd_value(pass);
6daba0
 	arg = ossl_to_der_if_possible(arg);
6daba0
 	in = ossl_obj2bio(&arg;;
6daba0
-	dsa = PEM_read_bio_DSAPrivateKey(in, NULL, ossl_pem_passwd_cb, (void *)pass);
6daba0
-	if (!dsa) {
6daba0
-	    OSSL_BIO_reset(in);
6daba0
-	    dsa = PEM_read_bio_DSA_PUBKEY(in, NULL, NULL, NULL);
6daba0
-	}
6daba0
-	if (!dsa) {
6daba0
-	    OSSL_BIO_reset(in);
6daba0
-	    dsa = d2i_DSAPrivateKey_bio(in, NULL);
6daba0
-	}
6daba0
-	if (!dsa) {
6daba0
-	    OSSL_BIO_reset(in);
6daba0
-	    dsa = d2i_DSA_PUBKEY_bio(in, NULL);
6daba0
-	}
6daba0
+
6daba0
+        tmp = ossl_pkey_read_generic(in, pass);
6daba0
+        if (tmp) {
6daba0
+            if (EVP_PKEY_base_id(tmp) != EVP_PKEY_DSA)
6daba0
+                rb_raise(eDSAError, "incorrect pkey type: %s",
6daba0
+                         OBJ_nid2sn(EVP_PKEY_base_id(tmp)));
6daba0
+            dsa = EVP_PKEY_get1_DSA(tmp);
6daba0
+            EVP_PKEY_free(tmp);
6daba0
+        }
6daba0
 	if (!dsa) {
6daba0
 	    OSSL_BIO_reset(in);
6daba0
 #define PEM_read_bio_DSAPublicKey(bp,x,cb,u) (DSA *)PEM_ASN1_read_bio( \
6daba0
diff --git a/ext/openssl/ossl_pkey_ec.c b/ext/openssl/ossl_pkey_ec.c
6daba0
index aec9d1e60f..ca8f5c6e4e 100644
6daba0
--- a/ext/openssl/ossl_pkey_ec.c
6daba0
+++ b/ext/openssl/ossl_pkey_ec.c
6daba0
@@ -162,24 +162,17 @@ static VALUE ossl_ec_key_initialize(int argc, VALUE *argv, VALUE self)
6daba0
     } else if (rb_obj_is_kind_of(arg, cEC_GROUP)) {
6daba0
 	ec = ec_key_new_from_group(arg);
6daba0
     } else {
6daba0
-	BIO *in;
6daba0
-
6daba0
-	pass = ossl_pem_passwd_value(pass);
6daba0
-	in = ossl_obj2bio(&arg;;
6daba0
-
6daba0
-	ec = PEM_read_bio_ECPrivateKey(in, NULL, ossl_pem_passwd_cb, (void *)pass);
6daba0
-	if (!ec) {
6daba0
-	    OSSL_BIO_reset(in);
6daba0
-	    ec = PEM_read_bio_EC_PUBKEY(in, NULL, ossl_pem_passwd_cb, (void *)pass);
6daba0
-	}
6daba0
-	if (!ec) {
6daba0
-	    OSSL_BIO_reset(in);
6daba0
-	    ec = d2i_ECPrivateKey_bio(in, NULL);
6daba0
-	}
6daba0
-	if (!ec) {
6daba0
-	    OSSL_BIO_reset(in);
6daba0
-	    ec = d2i_EC_PUBKEY_bio(in, NULL);
6daba0
-	}
6daba0
+        BIO *in = ossl_obj2bio(&arg;;
6daba0
+        EVP_PKEY *tmp;
6daba0
+        pass = ossl_pem_passwd_value(pass);
6daba0
+        tmp = ossl_pkey_read_generic(in, pass);
6daba0
+        if (tmp) {
6daba0
+            if (EVP_PKEY_base_id(tmp) != EVP_PKEY_EC)
6daba0
+                rb_raise(eECError, "incorrect pkey type: %s",
6daba0
+                         OBJ_nid2sn(EVP_PKEY_base_id(tmp)));
6daba0
+            ec = EVP_PKEY_get1_EC_KEY(tmp);
6daba0
+            EVP_PKEY_free(tmp);
6daba0
+        }
6daba0
 	BIO_free(in);
6daba0
 
6daba0
 	if (!ec) {
6daba0
diff --git a/ext/openssl/ossl_pkey_rsa.c b/ext/openssl/ossl_pkey_rsa.c
6daba0
index fbdb9c8960..8415121c7d 100644
6daba0
--- a/ext/openssl/ossl_pkey_rsa.c
6daba0
+++ b/ext/openssl/ossl_pkey_rsa.c
6daba0
@@ -179,7 +179,8 @@ ossl_rsa_initialize(int argc, VALUE *argv, VALUE self)
6daba0
     VALUE arg, pass;
6daba0
 
6daba0
     GetPKey(self, pkey);
6daba0
-    if(rb_scan_args(argc, argv, "02", &arg, &pass) == 0) {
6daba0
+    rb_scan_args(argc, argv, "02", &arg, &pass);
6daba0
+    if (argc == 0) {
6daba0
 	rsa = RSA_new();
6daba0
         if (!rsa)
6daba0
             ossl_raise(eRSAError, "RSA_new");
6daba0
@@ -191,19 +192,15 @@ ossl_rsa_initialize(int argc, VALUE *argv, VALUE self)
6daba0
 	pass = ossl_pem_passwd_value(pass);
6daba0
 	arg = ossl_to_der_if_possible(arg);
6daba0
 	in = ossl_obj2bio(&arg;;
6daba0
-	rsa = PEM_read_bio_RSAPrivateKey(in, NULL, ossl_pem_passwd_cb, (void *)pass);
6daba0
-	if (!rsa) {
6daba0
-	    OSSL_BIO_reset(in);
6daba0
-	    rsa = PEM_read_bio_RSA_PUBKEY(in, NULL, NULL, NULL);
6daba0
-	}
6daba0
-	if (!rsa) {
6daba0
-	    OSSL_BIO_reset(in);
6daba0
-	    rsa = d2i_RSAPrivateKey_bio(in, NULL);
6daba0
-	}
6daba0
-	if (!rsa) {
6daba0
-	    OSSL_BIO_reset(in);
6daba0
-	    rsa = d2i_RSA_PUBKEY_bio(in, NULL);
6daba0
-	}
6daba0
+
6daba0
+        tmp = ossl_pkey_read_generic(in, pass);
6daba0
+        if (tmp) {
6daba0
+            if (EVP_PKEY_base_id(tmp) != EVP_PKEY_RSA)
6daba0
+                rb_raise(eRSAError, "incorrect pkey type: %s",
6daba0
+                         OBJ_nid2sn(EVP_PKEY_base_id(tmp)));
6daba0
+            rsa = EVP_PKEY_get1_RSA(tmp);
6daba0
+            EVP_PKEY_free(tmp);
6daba0
+        }
6daba0
 	if (!rsa) {
6daba0
 	    OSSL_BIO_reset(in);
6daba0
 	    rsa = PEM_read_bio_RSAPublicKey(in, NULL, NULL, NULL);
6daba0
@@ -214,6 +211,7 @@ ossl_rsa_initialize(int argc, VALUE *argv, VALUE self)
6daba0
 	}
6daba0
 	BIO_free(in);
6daba0
 	if (!rsa) {
6daba0
+            ossl_clear_error();
6daba0
 	    ossl_raise(eRSAError, "Neither PUB key nor PRIV key");
6daba0
 	}
6daba0
     }
6daba0
-- 
6daba0
2.32.0
6daba0
6daba0
6daba0
From eacc680b1efc82935efc945bbe23c9073f17f440 Mon Sep 17 00:00:00 2001
6daba0
From: Kazuki Yamaguchi <k@rhe.jp>
6daba0
Date: Wed, 14 Jun 2017 00:25:43 +0900
6daba0
Subject: [PATCH 5/5] pkey: refactor #export/#to_pem and #to_der
6daba0
6daba0
Add ossl_pkey_export_traditional() and ossl_pkey_export_spki() helper
6daba0
functions, and use them. This reduces code duplication.
6daba0
---
6daba0
 ext/openssl/ossl_pkey.c     | 54 +++++++++++++++++++++--
6daba0
 ext/openssl/ossl_pkey.h     | 14 ++++++
6daba0
 ext/openssl/ossl_pkey_dsa.c | 49 +++------------------
6daba0
 ext/openssl/ossl_pkey_ec.c  | 86 ++++++++-----------------------------
6daba0
 ext/openssl/ossl_pkey_rsa.c | 84 +++++++++++-------------------------
6daba0
 5 files changed, 114 insertions(+), 173 deletions(-)
6daba0
6daba0
diff --git a/ext/openssl/ossl_pkey.c b/ext/openssl/ossl_pkey.c
6daba0
index 47ddd0f014..610a83fd2d 100644
6daba0
--- a/ext/openssl/ossl_pkey.c
6daba0
+++ b/ext/openssl/ossl_pkey.c
6daba0
@@ -341,6 +341,52 @@ ossl_pkey_inspect(VALUE self)
6daba0
                       OBJ_nid2sn(nid));
6daba0
 }
6daba0
 
6daba0
+VALUE
6daba0
+ossl_pkey_export_traditional(int argc, VALUE *argv, VALUE self, int to_der)
6daba0
+{
6daba0
+    EVP_PKEY *pkey;
6daba0
+    VALUE cipher, pass;
6daba0
+    const EVP_CIPHER *enc = NULL;
6daba0
+    BIO *bio;
6daba0
+
6daba0
+    GetPKey(self, pkey);
6daba0
+    rb_scan_args(argc, argv, "02", &cipher, &pass);
6daba0
+    if (!NIL_P(cipher)) {
6daba0
+	enc = ossl_evp_get_cipherbyname(cipher);
6daba0
+	pass = ossl_pem_passwd_value(pass);
6daba0
+    }
6daba0
+
6daba0
+    bio = BIO_new(BIO_s_mem());
6daba0
+    if (!bio)
6daba0
+	ossl_raise(ePKeyError, "BIO_new");
6daba0
+    if (to_der) {
6daba0
+	if (!i2d_PrivateKey_bio(bio, pkey)) {
6daba0
+	    BIO_free(bio);
6daba0
+	    ossl_raise(ePKeyError, "i2d_PrivateKey_bio");
6daba0
+	}
6daba0
+    }
6daba0
+    else {
6daba0
+#if OPENSSL_VERSION_NUMBER >= 0x10100000 && !defined(LIBRESSL_VERSION_NUMBER)
6daba0
+	if (!PEM_write_bio_PrivateKey_traditional(bio, pkey, enc, NULL, 0,
6daba0
+						  ossl_pem_passwd_cb,
6daba0
+						  (void *)pass)) {
6daba0
+#else
6daba0
+	char pem_str[80];
6daba0
+	const char *aname;
6daba0
+
6daba0
+	EVP_PKEY_asn1_get0_info(NULL, NULL, NULL, NULL, &aname, pkey->ameth);
6daba0
+	snprintf(pem_str, sizeof(pem_str), "%s PRIVATE KEY", aname);
6daba0
+	if (!PEM_ASN1_write_bio((i2d_of_void *)i2d_PrivateKey, pem_str, bio,
6daba0
+				pkey, enc, NULL, 0, ossl_pem_passwd_cb,
6daba0
+				(void *)pass)) {
6daba0
+#endif
6daba0
+	    BIO_free(bio);
6daba0
+	    ossl_raise(ePKeyError, "PEM_write_bio_PrivateKey_traditional");
6daba0
+	}
6daba0
+    }
6daba0
+    return ossl_membio2str(bio);
6daba0
+}
6daba0
+
6daba0
 static VALUE
6daba0
 do_pkcs8_export(int argc, VALUE *argv, VALUE self, int to_der)
6daba0
 {
6daba0
@@ -410,8 +456,8 @@ ossl_pkey_private_to_pem(int argc, VALUE *argv, VALUE self)
6daba0
     return do_pkcs8_export(argc, argv, self, 0);
6daba0
 }
6daba0
 
6daba0
-static VALUE
6daba0
-do_spki_export(VALUE self, int to_der)
6daba0
+VALUE
6daba0
+ossl_pkey_export_spki(VALUE self, int to_der)
6daba0
 {
6daba0
     EVP_PKEY *pkey;
6daba0
     BIO *bio;
6daba0
@@ -444,7 +490,7 @@ do_spki_export(VALUE self, int to_der)
6daba0
 static VALUE
6daba0
 ossl_pkey_public_to_der(VALUE self)
6daba0
 {
6daba0
-    return do_spki_export(self, 1);
6daba0
+    return ossl_pkey_export_spki(self, 1);
6daba0
 }
6daba0
 
6daba0
 /*
6daba0
@@ -456,7 +502,7 @@ ossl_pkey_public_to_der(VALUE self)
6daba0
 static VALUE
6daba0
 ossl_pkey_public_to_pem(VALUE self)
6daba0
 {
6daba0
-    return do_spki_export(self, 0);
6daba0
+    return ossl_pkey_export_spki(self, 0);
6daba0
 }
6daba0
 
6daba0
 /*
6daba0
diff --git a/ext/openssl/ossl_pkey.h b/ext/openssl/ossl_pkey.h
6daba0
index 895927e3fb..7dbaed47bc 100644
6daba0
--- a/ext/openssl/ossl_pkey.h
6daba0
+++ b/ext/openssl/ossl_pkey.h
6daba0
@@ -49,6 +49,20 @@ EVP_PKEY *ossl_pkey_read_generic(BIO *, VALUE);
6daba0
 EVP_PKEY *GetPKeyPtr(VALUE);
6daba0
 EVP_PKEY *DupPKeyPtr(VALUE);
6daba0
 EVP_PKEY *GetPrivPKeyPtr(VALUE);
6daba0
+
6daba0
+/*
6daba0
+ * Serializes _self_ in X.509 SubjectPublicKeyInfo format and returns the
6daba0
+ * resulting String. Sub-classes use this when overriding #to_der.
6daba0
+ */
6daba0
+VALUE ossl_pkey_export_spki(VALUE self, int to_der);
6daba0
+/*
6daba0
+ * Serializes the private key _self_ in the traditional private key format
6daba0
+ * and returns the resulting String. Sub-classes use this when overriding
6daba0
+ * #to_der.
6daba0
+ */
6daba0
+VALUE ossl_pkey_export_traditional(int argc, VALUE *argv, VALUE self,
6daba0
+				   int to_der);
6daba0
+
6daba0
 void Init_ossl_pkey(void);
6daba0
 
6daba0
 /*
6daba0
diff --git a/ext/openssl/ossl_pkey_dsa.c b/ext/openssl/ossl_pkey_dsa.c
6daba0
index 56f58559ed..0e68f7f27f 100644
6daba0
--- a/ext/openssl/ossl_pkey_dsa.c
6daba0
+++ b/ext/openssl/ossl_pkey_dsa.c
6daba0
@@ -296,34 +296,12 @@ static VALUE
6daba0
 ossl_dsa_export(int argc, VALUE *argv, VALUE self)
6daba0
 {
6daba0
     DSA *dsa;
6daba0
-    BIO *out;
6daba0
-    const EVP_CIPHER *ciph = NULL;
6daba0
-    VALUE cipher, pass, str;
6daba0
 
6daba0
     GetDSA(self, dsa);
6daba0
-    rb_scan_args(argc, argv, "02", &cipher, &pass);
6daba0
-    if (!NIL_P(cipher)) {
6daba0
-	ciph = ossl_evp_get_cipherbyname(cipher);
6daba0
-	pass = ossl_pem_passwd_value(pass);
6daba0
-    }
6daba0
-    if (!(out = BIO_new(BIO_s_mem()))) {
6daba0
-	ossl_raise(eDSAError, NULL);
6daba0
-    }
6daba0
-    if (DSA_HAS_PRIVATE(dsa)) {
6daba0
-	if (!PEM_write_bio_DSAPrivateKey(out, dsa, ciph, NULL, 0,
6daba0
-					 ossl_pem_passwd_cb, (void *)pass)){
6daba0
-	    BIO_free(out);
6daba0
-	    ossl_raise(eDSAError, NULL);
6daba0
-	}
6daba0
-    } else {
6daba0
-	if (!PEM_write_bio_DSA_PUBKEY(out, dsa)) {
6daba0
-	    BIO_free(out);
6daba0
-	    ossl_raise(eDSAError, NULL);
6daba0
-	}
6daba0
-    }
6daba0
-    str = ossl_membio2str(out);
6daba0
-
6daba0
-    return str;
6daba0
+    if (DSA_HAS_PRIVATE(dsa))
6daba0
+        return ossl_pkey_export_traditional(argc, argv, self, 0);
6daba0
+    else
6daba0
+        return ossl_pkey_export_spki(self, 0);
6daba0
 }
6daba0
 
6daba0
 /*
6daba0
@@ -337,25 +315,12 @@ static VALUE
6daba0
 ossl_dsa_to_der(VALUE self)
6daba0
 {
6daba0
     DSA *dsa;
6daba0
-    int (*i2d_func)(DSA *, unsigned char **);
6daba0
-    unsigned char *p;
6daba0
-    long len;
6daba0
-    VALUE str;
6daba0
 
6daba0
     GetDSA(self, dsa);
6daba0
-    if(DSA_HAS_PRIVATE(dsa))
6daba0
-	i2d_func = (int (*)(DSA *,unsigned char **))i2d_DSAPrivateKey;
6daba0
+    if (DSA_HAS_PRIVATE(dsa))
6daba0
+        return ossl_pkey_export_traditional(0, NULL, self, 1);
6daba0
     else
6daba0
-	i2d_func = i2d_DSA_PUBKEY;
6daba0
-    if((len = i2d_func(dsa, NULL)) <= 0)
6daba0
-	ossl_raise(eDSAError, NULL);
6daba0
-    str = rb_str_new(0, len);
6daba0
-    p = (unsigned char *)RSTRING_PTR(str);
6daba0
-    if(i2d_func(dsa, &p) < 0)
6daba0
-	ossl_raise(eDSAError, NULL);
6daba0
-    ossl_str_adjust(str, p);
6daba0
-
6daba0
-    return str;
6daba0
+        return ossl_pkey_export_spki(self, 1);
6daba0
 }
6daba0
 
6daba0
 
6daba0
diff --git a/ext/openssl/ossl_pkey_ec.c b/ext/openssl/ossl_pkey_ec.c
6daba0
index ca8f5c6e4e..6fe2533e2a 100644
6daba0
--- a/ext/openssl/ossl_pkey_ec.c
6daba0
+++ b/ext/openssl/ossl_pkey_ec.c
6daba0
@@ -141,7 +141,7 @@ ossl_ec_key_s_generate(VALUE klass, VALUE arg)
6daba0
 static VALUE ossl_ec_key_initialize(int argc, VALUE *argv, VALUE self)
6daba0
 {
6daba0
     EVP_PKEY *pkey;
6daba0
-    EC_KEY *ec;
6daba0
+    EC_KEY *ec = NULL;
6daba0
     VALUE arg, pass;
6daba0
 
6daba0
     GetPKey(self, pkey);
6daba0
@@ -378,66 +378,6 @@ static VALUE ossl_ec_key_is_private(VALUE self)
6daba0
     return EC_KEY_get0_private_key(ec) ? Qtrue : Qfalse;
6daba0
 }
6daba0
 
6daba0
-static VALUE ossl_ec_key_to_string(VALUE self, VALUE ciph, VALUE pass, int format)
6daba0
-{
6daba0
-    EC_KEY *ec;
6daba0
-    BIO *out;
6daba0
-    int i = -1;
6daba0
-    int private = 0;
6daba0
-    VALUE str;
6daba0
-    const EVP_CIPHER *cipher = NULL;
6daba0
-
6daba0
-    GetEC(self, ec);
6daba0
-
6daba0
-    if (EC_KEY_get0_public_key(ec) == NULL)
6daba0
-        ossl_raise(eECError, "can't export - no public key set");
6daba0
-
6daba0
-    if (EC_KEY_check_key(ec) != 1)
6daba0
-	ossl_raise(eECError, "can't export - EC_KEY_check_key failed");
6daba0
-
6daba0
-    if (EC_KEY_get0_private_key(ec))
6daba0
-        private = 1;
6daba0
-
6daba0
-    if (!NIL_P(ciph)) {
6daba0
-	cipher = ossl_evp_get_cipherbyname(ciph);
6daba0
-	pass = ossl_pem_passwd_value(pass);
6daba0
-    }
6daba0
-
6daba0
-    if (!(out = BIO_new(BIO_s_mem())))
6daba0
-        ossl_raise(eECError, "BIO_new(BIO_s_mem())");
6daba0
-
6daba0
-    switch(format) {
6daba0
-    case EXPORT_PEM:
6daba0
-    	if (private) {
6daba0
-            i = PEM_write_bio_ECPrivateKey(out, ec, cipher, NULL, 0, ossl_pem_passwd_cb, (void *)pass);
6daba0
-    	} else {
6daba0
-            i = PEM_write_bio_EC_PUBKEY(out, ec);
6daba0
-        }
6daba0
-
6daba0
-    	break;
6daba0
-    case EXPORT_DER:
6daba0
-        if (private) {
6daba0
-            i = i2d_ECPrivateKey_bio(out, ec);
6daba0
-        } else {
6daba0
-            i = i2d_EC_PUBKEY_bio(out, ec);
6daba0
-        }
6daba0
-
6daba0
-    	break;
6daba0
-    default:
6daba0
-        BIO_free(out);
6daba0
-    	ossl_raise(rb_eRuntimeError, "unknown format (internal error)");
6daba0
-    }
6daba0
-
6daba0
-    if (i != 1) {
6daba0
-        BIO_free(out);
6daba0
-        ossl_raise(eECError, "outlen=%d", i);
6daba0
-    }
6daba0
-
6daba0
-    str = ossl_membio2str(out);
6daba0
-
6daba0
-    return str;
6daba0
-}
6daba0
-
6daba0
 /*
6daba0
  *  call-seq:
6daba0
  *     key.export([cipher, pass_phrase]) => String
6daba0
@@ -448,11 +388,16 @@ static VALUE ossl_ec_key_to_string(VALUE self, VALUE ciph, VALUE pass, int forma
6daba0
  * instance. Note that encryption will only be effective for a private key,
6daba0
  * public keys will always be encoded in plain text.
6daba0
  */
6daba0
-static VALUE ossl_ec_key_export(int argc, VALUE *argv, VALUE self)
6daba0
+static VALUE
6daba0
+ossl_ec_key_export(int argc, VALUE *argv, VALUE self)
6daba0
 {
6daba0
-    VALUE cipher, passwd;
6daba0
-    rb_scan_args(argc, argv, "02", &cipher, &passwd);
6daba0
-    return ossl_ec_key_to_string(self, cipher, passwd, EXPORT_PEM);
6daba0
+    EC_KEY *ec;
6daba0
+
6daba0
+    GetEC(self, ec);
6daba0
+    if (EC_KEY_get0_private_key(ec))
6daba0
+        return ossl_pkey_export_traditional(argc, argv, self, 0);
6daba0
+    else
6daba0
+        return ossl_pkey_export_spki(self, 0);
6daba0
 }
6daba0
 
6daba0
 /*
6daba0
@@ -461,9 +406,16 @@ static VALUE ossl_ec_key_export(int argc, VALUE *argv, VALUE self)
6daba0
  *
6daba0
  *  See the OpenSSL documentation for i2d_ECPrivateKey_bio()
6daba0
  */
6daba0
-static VALUE ossl_ec_key_to_der(VALUE self)
6daba0
+static VALUE
6daba0
+ossl_ec_key_to_der(VALUE self)
6daba0
 {
6daba0
-    return ossl_ec_key_to_string(self, Qnil, Qnil, EXPORT_DER);
6daba0
+    EC_KEY *ec;
6daba0
+
6daba0
+    GetEC(self, ec);
6daba0
+    if (EC_KEY_get0_private_key(ec))
6daba0
+        return ossl_pkey_export_traditional(0, NULL, self, 1);
6daba0
+    else
6daba0
+        return ossl_pkey_export_spki(self, 1);
6daba0
 }
6daba0
 
6daba0
 /*
6daba0
diff --git a/ext/openssl/ossl_pkey_rsa.c b/ext/openssl/ossl_pkey_rsa.c
6daba0
index 8415121c7d..3c298a2aea 100644
6daba0
--- a/ext/openssl/ossl_pkey_rsa.c
6daba0
+++ b/ext/openssl/ossl_pkey_rsa.c
6daba0
@@ -173,8 +173,8 @@ ossl_rsa_s_generate(int argc, VALUE *argv, VALUE klass)
6daba0
 static VALUE
6daba0
 ossl_rsa_initialize(int argc, VALUE *argv, VALUE self)
6daba0
 {
6daba0
-    EVP_PKEY *pkey;
6daba0
-    RSA *rsa;
6daba0
+    EVP_PKEY *pkey, *tmp;
6daba0
+    RSA *rsa = NULL;
6daba0
     BIO *in;
6daba0
     VALUE arg, pass;
6daba0
 
6daba0
@@ -279,6 +279,21 @@ ossl_rsa_is_private(VALUE self)
6daba0
     return RSA_PRIVATE(self, rsa) ? Qtrue : Qfalse;
6daba0
 }
6daba0
 
6daba0
+static int
6daba0
+can_export_rsaprivatekey(VALUE self)
6daba0
+{
6daba0
+    RSA *rsa;
6daba0
+    const BIGNUM *n, *e, *d, *p, *q, *dmp1, *dmq1, *iqmp;
6daba0
+
6daba0
+    GetRSA(self, rsa);
6daba0
+
6daba0
+    RSA_get0_key(rsa, &n, &e, &d);
6daba0
+    RSA_get0_factors(rsa, &p, &q);
6daba0
+    RSA_get0_crt_params(rsa, &dmp1, &dmq1, &iqmp);
6daba0
+
6daba0
+    return n && e && d && p && q && dmp1 && dmq1 && iqmp;
6daba0
+}
6daba0
+
6daba0
 /*
6daba0
  * call-seq:
6daba0
  *   rsa.export([cipher, pass_phrase]) => PEM-format String
6daba0
@@ -292,41 +307,10 @@ ossl_rsa_is_private(VALUE self)
6daba0
 static VALUE
6daba0
 ossl_rsa_export(int argc, VALUE *argv, VALUE self)
6daba0
 {
6daba0
-    RSA *rsa;
6daba0
-    const BIGNUM *n, *e, *d, *p, *q, *dmp1, *dmq1, *iqmp;
6daba0
-    BIO *out;
6daba0
-    const EVP_CIPHER *ciph = NULL;
6daba0
-    VALUE cipher, pass, str;
6daba0
-
6daba0
-    GetRSA(self, rsa);
6daba0
-
6daba0
-    rb_scan_args(argc, argv, "02", &cipher, &pass);
6daba0
-
6daba0
-    if (!NIL_P(cipher)) {
6daba0
-	ciph = ossl_evp_get_cipherbyname(cipher);
6daba0
-	pass = ossl_pem_passwd_value(pass);
6daba0
-    }
6daba0
-    if (!(out = BIO_new(BIO_s_mem()))) {
6daba0
-	ossl_raise(eRSAError, NULL);
6daba0
-    }
6daba0
-    RSA_get0_key(rsa, &n, &e, &d);
6daba0
-    RSA_get0_factors(rsa, &p, &q);
6daba0
-    RSA_get0_crt_params(rsa, &dmp1, &dmq1, &iqmp);
6daba0
-    if (n && e && d && p && q && dmp1 && dmq1 && iqmp) {
6daba0
-	if (!PEM_write_bio_RSAPrivateKey(out, rsa, ciph, NULL, 0,
6daba0
-					 ossl_pem_passwd_cb, (void *)pass)) {
6daba0
-	    BIO_free(out);
6daba0
-	    ossl_raise(eRSAError, NULL);
6daba0
-	}
6daba0
-    } else {
6daba0
-	if (!PEM_write_bio_RSA_PUBKEY(out, rsa)) {
6daba0
-	    BIO_free(out);
6daba0
-	    ossl_raise(eRSAError, NULL);
6daba0
-	}
6daba0
-    }
6daba0
-    str = ossl_membio2str(out);
6daba0
-
6daba0
-    return str;
6daba0
+    if (can_export_rsaprivatekey(self))
6daba0
+        return ossl_pkey_export_traditional(argc, argv, self, 0);
6daba0
+    else
6daba0
+        return ossl_pkey_export_spki(self, 0);
6daba0
 }
6daba0
 
6daba0
 /*
6daba0
@@ -338,30 +322,10 @@ ossl_rsa_export(int argc, VALUE *argv, VALUE self)
6daba0
 static VALUE
6daba0
 ossl_rsa_to_der(VALUE self)
6daba0
 {
6daba0
-    RSA *rsa;
6daba0
-    const BIGNUM *n, *e, *d, *p, *q, *dmp1, *dmq1, *iqmp;
6daba0
-    int (*i2d_func)(const RSA *, unsigned char **);
6daba0
-    unsigned char *ptr;
6daba0
-    long len;
6daba0
-    VALUE str;
6daba0
-
6daba0
-    GetRSA(self, rsa);
6daba0
-    RSA_get0_key(rsa, &n, &e, &d);
6daba0
-    RSA_get0_factors(rsa, &p, &q);
6daba0
-    RSA_get0_crt_params(rsa, &dmp1, &dmq1, &iqmp);
6daba0
-    if (n && e && d && p && q && dmp1 && dmq1 && iqmp)
6daba0
-	i2d_func = i2d_RSAPrivateKey;
6daba0
+    if (can_export_rsaprivatekey(self))
6daba0
+        return ossl_pkey_export_traditional(0, NULL, self, 1);
6daba0
     else
6daba0
-	i2d_func = (int (*)(const RSA *, unsigned char **))i2d_RSA_PUBKEY;
6daba0
-    if((len = i2d_func(rsa, NULL)) <= 0)
6daba0
-	ossl_raise(eRSAError, NULL);
6daba0
-    str = rb_str_new(0, len);
6daba0
-    ptr = (unsigned char *)RSTRING_PTR(str);
6daba0
-    if(i2d_func(rsa, &ptr) < 0)
6daba0
-	ossl_raise(eRSAError, NULL);
6daba0
-    ossl_str_adjust(str, ptr);
6daba0
-
6daba0
-    return str;
6daba0
+        return ossl_pkey_export_spki(self, 1);
6daba0
 }
6daba0
 
6daba0
 /*
6daba0
-- 
6daba0
2.32.0
6daba0