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