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.
630 lines
19 KiB
630 lines
19 KiB
From 316cb2a41f154e4663d7e7fead60cfc0bfa86af9 Mon Sep 17 00:00:00 2001 |
|
From: Kazuki Yamaguchi <k@rhe.jp> |
|
Date: Mon, 12 Apr 2021 13:55:10 +0900 |
|
Subject: [PATCH 1/2] pkey: do not check NULL argument in ossl_pkey_new() |
|
|
|
Passing NULL to ossl_pkey_new() makes no sense in the first place, and |
|
in fact it is ensured not to be NULL in all cases. |
|
--- |
|
ext/openssl/ossl_pkey.c | 6 +----- |
|
ext/openssl/ossl_pkey.h | 1 + |
|
2 files changed, 2 insertions(+), 5 deletions(-) |
|
|
|
diff --git a/ext/openssl/ossl_pkey.c b/ext/openssl/ossl_pkey.c |
|
index f9f5162e..820e4a2c 100644 |
|
--- a/ext/openssl/ossl_pkey.c |
|
+++ b/ext/openssl/ossl_pkey.c |
|
@@ -38,12 +38,8 @@ static VALUE |
|
pkey_new0(EVP_PKEY *pkey) |
|
{ |
|
VALUE klass, obj; |
|
- int type; |
|
|
|
- if (!pkey || (type = EVP_PKEY_base_id(pkey)) == EVP_PKEY_NONE) |
|
- ossl_raise(rb_eRuntimeError, "pkey is empty"); |
|
- |
|
- switch (type) { |
|
+ switch (EVP_PKEY_base_id(pkey)) { |
|
#if !defined(OPENSSL_NO_RSA) |
|
case EVP_PKEY_RSA: klass = cRSA; break; |
|
#endif |
|
diff --git a/ext/openssl/ossl_pkey.h b/ext/openssl/ossl_pkey.h |
|
index 4beede22..f0476780 100644 |
|
--- a/ext/openssl/ossl_pkey.h |
|
+++ b/ext/openssl/ossl_pkey.h |
|
@@ -35,6 +35,7 @@ extern const rb_data_type_t ossl_evp_pkey_type; |
|
} \ |
|
} while (0) |
|
|
|
+/* Takes ownership of the EVP_PKEY */ |
|
VALUE ossl_pkey_new(EVP_PKEY *); |
|
void ossl_pkey_check_public_key(const EVP_PKEY *); |
|
EVP_PKEY *ossl_pkey_read_generic(BIO *, VALUE); |
|
|
|
From 74f6c6175688502a5bf27ae35367616858630c0f Mon Sep 17 00:00:00 2001 |
|
From: Kazuki Yamaguchi <k@rhe.jp> |
|
Date: Mon, 12 Apr 2021 18:32:40 +0900 |
|
Subject: [PATCH 2/2] pkey: allocate EVP_PKEY on #initialize |
|
|
|
Allocate an EVP_PKEY when the content is ready: when #initialize |
|
or #initialize_copy is called, rather than when a T_DATA is allocated. |
|
This is more natural because the lower level API has been deprecated |
|
and an EVP_PKEY is becoming the minimum unit of handling keys. |
|
--- |
|
ext/openssl/ossl_pkey.c | 15 ++---- |
|
ext/openssl/ossl_pkey.h | 15 ++---- |
|
ext/openssl/ossl_pkey_dh.c | 71 +++++++++++++++++++-------- |
|
ext/openssl/ossl_pkey_dsa.c | 93 ++++++++++++++++++++--------------- |
|
ext/openssl/ossl_pkey_ec.c | 91 +++++++++++++++++++---------------- |
|
ext/openssl/ossl_pkey_rsa.c | 96 ++++++++++++++++++++++--------------- |
|
6 files changed, 218 insertions(+), 163 deletions(-) |
|
|
|
diff --git a/ext/openssl/ossl_pkey.c b/ext/openssl/ossl_pkey.c |
|
index 820e4a2c..ea75d63f 100644 |
|
--- a/ext/openssl/ossl_pkey.c |
|
+++ b/ext/openssl/ossl_pkey.c |
|
@@ -54,8 +54,8 @@ pkey_new0(EVP_PKEY *pkey) |
|
#endif |
|
default: klass = cPKey; break; |
|
} |
|
- obj = NewPKey(klass); |
|
- SetPKey(obj, pkey); |
|
+ obj = rb_obj_alloc(klass); |
|
+ RTYPEDDATA_DATA(obj) = pkey; |
|
return obj; |
|
} |
|
|
|
@@ -511,16 +511,7 @@ DupPKeyPtr(VALUE obj) |
|
static VALUE |
|
ossl_pkey_alloc(VALUE klass) |
|
{ |
|
- EVP_PKEY *pkey; |
|
- VALUE obj; |
|
- |
|
- obj = NewPKey(klass); |
|
- if (!(pkey = EVP_PKEY_new())) { |
|
- ossl_raise(ePKeyError, NULL); |
|
- } |
|
- SetPKey(obj, pkey); |
|
- |
|
- return obj; |
|
+ return TypedData_Wrap_Struct(klass, &ossl_evp_pkey_type, NULL); |
|
} |
|
|
|
/* |
|
diff --git a/ext/openssl/ossl_pkey.h b/ext/openssl/ossl_pkey.h |
|
index f0476780..ed18bc69 100644 |
|
--- a/ext/openssl/ossl_pkey.h |
|
+++ b/ext/openssl/ossl_pkey.h |
|
@@ -15,19 +15,10 @@ extern VALUE cPKey; |
|
extern VALUE ePKeyError; |
|
extern const rb_data_type_t ossl_evp_pkey_type; |
|
|
|
-#define OSSL_PKEY_SET_PRIVATE(obj) rb_iv_set((obj), "private", Qtrue) |
|
-#define OSSL_PKEY_SET_PUBLIC(obj) rb_iv_set((obj), "private", Qfalse) |
|
-#define OSSL_PKEY_IS_PRIVATE(obj) (rb_iv_get((obj), "private") == Qtrue) |
|
+/* For ENGINE */ |
|
+#define OSSL_PKEY_SET_PRIVATE(obj) rb_ivar_set((obj), rb_intern("private"), Qtrue) |
|
+#define OSSL_PKEY_IS_PRIVATE(obj) (rb_attr_get((obj), rb_intern("private")) == Qtrue) |
|
|
|
-#define NewPKey(klass) \ |
|
- TypedData_Wrap_Struct((klass), &ossl_evp_pkey_type, 0) |
|
-#define SetPKey(obj, pkey) do { \ |
|
- if (!(pkey)) { \ |
|
- rb_raise(rb_eRuntimeError, "PKEY wasn't initialized!"); \ |
|
- } \ |
|
- RTYPEDDATA_DATA(obj) = (pkey); \ |
|
- OSSL_PKEY_SET_PUBLIC(obj); \ |
|
-} while (0) |
|
#define GetPKey(obj, pkey) do {\ |
|
TypedData_Get_Struct((obj), EVP_PKEY, &ossl_evp_pkey_type, (pkey)); \ |
|
if (!(pkey)) { \ |
|
diff --git a/ext/openssl/ossl_pkey_dh.c b/ext/openssl/ossl_pkey_dh.c |
|
index ca782bbe..04c11b21 100644 |
|
--- a/ext/openssl/ossl_pkey_dh.c |
|
+++ b/ext/openssl/ossl_pkey_dh.c |
|
@@ -72,34 +72,57 @@ static VALUE |
|
ossl_dh_initialize(int argc, VALUE *argv, VALUE self) |
|
{ |
|
EVP_PKEY *pkey; |
|
+ int type; |
|
DH *dh; |
|
- BIO *in; |
|
+ BIO *in = NULL; |
|
VALUE arg; |
|
|
|
- GetPKey(self, pkey); |
|
+ TypedData_Get_Struct(self, EVP_PKEY, &ossl_evp_pkey_type, pkey); |
|
+ if (pkey) |
|
+ rb_raise(rb_eTypeError, "pkey already initialized"); |
|
+ |
|
/* The DH.new(size, generator) form is handled by lib/openssl/pkey.rb */ |
|
if (rb_scan_args(argc, argv, "01", &arg) == 0) { |
|
dh = DH_new(); |
|
if (!dh) |
|
ossl_raise(eDHError, "DH_new"); |
|
+ goto legacy; |
|
} |
|
- else { |
|
- arg = ossl_to_der_if_possible(arg); |
|
- in = ossl_obj2bio(&arg); |
|
- dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL); |
|
- if (!dh){ |
|
- OSSL_BIO_reset(in); |
|
- dh = d2i_DHparams_bio(in, NULL); |
|
- } |
|
- BIO_free(in); |
|
- if (!dh) { |
|
- ossl_raise(eDHError, NULL); |
|
- } |
|
+ |
|
+ arg = ossl_to_der_if_possible(arg); |
|
+ in = ossl_obj2bio(&arg); |
|
+ |
|
+ /* |
|
+ * On OpenSSL <= 1.1.1 and current versions of LibreSSL, the generic |
|
+ * routine does not support DER-encoded parameters |
|
+ */ |
|
+ dh = d2i_DHparams_bio(in, NULL); |
|
+ if (dh) |
|
+ goto legacy; |
|
+ OSSL_BIO_reset(in); |
|
+ |
|
+ pkey = ossl_pkey_read_generic(in, Qnil); |
|
+ BIO_free(in); |
|
+ if (!pkey) |
|
+ ossl_raise(eDHError, "could not parse pkey"); |
|
+ |
|
+ type = EVP_PKEY_base_id(pkey); |
|
+ if (type != EVP_PKEY_DH) { |
|
+ EVP_PKEY_free(pkey); |
|
+ rb_raise(eDHError, "incorrect pkey type: %s", OBJ_nid2sn(type)); |
|
} |
|
- if (!EVP_PKEY_assign_DH(pkey, dh)) { |
|
- DH_free(dh); |
|
- ossl_raise(eDHError, NULL); |
|
+ RTYPEDDATA_DATA(self) = pkey; |
|
+ return self; |
|
+ |
|
+ legacy: |
|
+ BIO_free(in); |
|
+ pkey = EVP_PKEY_new(); |
|
+ if (!pkey || EVP_PKEY_assign_DH(pkey, dh) != 1) { |
|
+ EVP_PKEY_free(pkey); |
|
+ DH_free(dh); |
|
+ ossl_raise(eDHError, "EVP_PKEY_assign_DH"); |
|
} |
|
+ RTYPEDDATA_DATA(self) = pkey; |
|
return self; |
|
} |
|
|
|
@@ -110,15 +133,14 @@ ossl_dh_initialize_copy(VALUE self, VALUE other) |
|
DH *dh, *dh_other; |
|
const BIGNUM *pub, *priv; |
|
|
|
- GetPKey(self, pkey); |
|
- if (EVP_PKEY_base_id(pkey) != EVP_PKEY_NONE) |
|
- ossl_raise(eDHError, "DH already initialized"); |
|
+ TypedData_Get_Struct(self, EVP_PKEY, &ossl_evp_pkey_type, pkey); |
|
+ if (pkey) |
|
+ rb_raise(rb_eTypeError, "pkey already initialized"); |
|
GetDH(other, dh_other); |
|
|
|
dh = DHparams_dup(dh_other); |
|
if (!dh) |
|
ossl_raise(eDHError, "DHparams_dup"); |
|
- EVP_PKEY_assign_DH(pkey, dh); |
|
|
|
DH_get0_key(dh_other, &pub, &priv); |
|
if (pub) { |
|
@@ -133,6 +155,13 @@ ossl_dh_initialize_copy(VALUE self, VALUE other) |
|
DH_set0_key(dh, pub2, priv2); |
|
} |
|
|
|
+ pkey = EVP_PKEY_new(); |
|
+ if (!pkey || EVP_PKEY_assign_DH(pkey, dh) != 1) { |
|
+ EVP_PKEY_free(pkey); |
|
+ DH_free(dh); |
|
+ ossl_raise(eDHError, "EVP_PKEY_assign_DH"); |
|
+ } |
|
+ RTYPEDDATA_DATA(self) = pkey; |
|
return self; |
|
} |
|
|
|
diff --git a/ext/openssl/ossl_pkey_dsa.c b/ext/openssl/ossl_pkey_dsa.c |
|
index 7af00eeb..15724548 100644 |
|
--- a/ext/openssl/ossl_pkey_dsa.c |
|
+++ b/ext/openssl/ossl_pkey_dsa.c |
|
@@ -83,50 +83,59 @@ VALUE eDSAError; |
|
static VALUE |
|
ossl_dsa_initialize(int argc, VALUE *argv, VALUE self) |
|
{ |
|
- EVP_PKEY *pkey, *tmp; |
|
- DSA *dsa = NULL; |
|
- BIO *in; |
|
+ EVP_PKEY *pkey; |
|
+ DSA *dsa; |
|
+ BIO *in = NULL; |
|
VALUE arg, pass; |
|
+ int type; |
|
+ |
|
+ TypedData_Get_Struct(self, EVP_PKEY, &ossl_evp_pkey_type, pkey); |
|
+ if (pkey) |
|
+ rb_raise(rb_eTypeError, "pkey already initialized"); |
|
|
|
- GetPKey(self, pkey); |
|
/* The DSA.new(size, generator) form is handled by lib/openssl/pkey.rb */ |
|
rb_scan_args(argc, argv, "02", &arg, &pass); |
|
if (argc == 0) { |
|
dsa = DSA_new(); |
|
if (!dsa) |
|
ossl_raise(eDSAError, "DSA_new"); |
|
+ goto legacy; |
|
} |
|
- else { |
|
- pass = ossl_pem_passwd_value(pass); |
|
- arg = ossl_to_der_if_possible(arg); |
|
- in = ossl_obj2bio(&arg); |
|
- |
|
- 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( \ |
|
- (d2i_of_void *)d2i_DSAPublicKey, PEM_STRING_DSA_PUBLIC, (bp), (void **)(x), (cb), (u)) |
|
- dsa = PEM_read_bio_DSAPublicKey(in, NULL, NULL, NULL); |
|
-#undef PEM_read_bio_DSAPublicKey |
|
- } |
|
- BIO_free(in); |
|
- if (!dsa) { |
|
- ossl_clear_error(); |
|
- ossl_raise(eDSAError, "Neither PUB key nor PRIV key"); |
|
- } |
|
- } |
|
- if (!EVP_PKEY_assign_DSA(pkey, dsa)) { |
|
- DSA_free(dsa); |
|
- ossl_raise(eDSAError, NULL); |
|
+ |
|
+ pass = ossl_pem_passwd_value(pass); |
|
+ arg = ossl_to_der_if_possible(arg); |
|
+ in = ossl_obj2bio(&arg); |
|
+ |
|
+ /* DER-encoded DSAPublicKey format isn't supported by the generic routine */ |
|
+ dsa = (DSA *)PEM_ASN1_read_bio((d2i_of_void *)d2i_DSAPublicKey, |
|
+ PEM_STRING_DSA_PUBLIC, |
|
+ in, NULL, NULL, NULL); |
|
+ if (dsa) |
|
+ goto legacy; |
|
+ OSSL_BIO_reset(in); |
|
+ |
|
+ pkey = ossl_pkey_read_generic(in, pass); |
|
+ BIO_free(in); |
|
+ if (!pkey) |
|
+ ossl_raise(eDSAError, "Neither PUB key nor PRIV key"); |
|
+ |
|
+ type = EVP_PKEY_base_id(pkey); |
|
+ if (type != EVP_PKEY_DSA) { |
|
+ EVP_PKEY_free(pkey); |
|
+ rb_raise(eDSAError, "incorrect pkey type: %s", OBJ_nid2sn(type)); |
|
} |
|
+ RTYPEDDATA_DATA(self) = pkey; |
|
+ return self; |
|
|
|
+ legacy: |
|
+ BIO_free(in); |
|
+ pkey = EVP_PKEY_new(); |
|
+ if (!pkey || EVP_PKEY_assign_DSA(pkey, dsa) != 1) { |
|
+ EVP_PKEY_free(pkey); |
|
+ DSA_free(dsa); |
|
+ ossl_raise(eDSAError, "EVP_PKEY_assign_DSA"); |
|
+ } |
|
+ RTYPEDDATA_DATA(self) = pkey; |
|
return self; |
|
} |
|
|
|
@@ -136,16 +145,24 @@ ossl_dsa_initialize_copy(VALUE self, VALUE other) |
|
EVP_PKEY *pkey; |
|
DSA *dsa, *dsa_new; |
|
|
|
- GetPKey(self, pkey); |
|
- if (EVP_PKEY_base_id(pkey) != EVP_PKEY_NONE) |
|
- ossl_raise(eDSAError, "DSA already initialized"); |
|
+ TypedData_Get_Struct(self, EVP_PKEY, &ossl_evp_pkey_type, pkey); |
|
+ if (pkey) |
|
+ rb_raise(rb_eTypeError, "pkey already initialized"); |
|
GetDSA(other, dsa); |
|
|
|
- dsa_new = ASN1_dup((i2d_of_void *)i2d_DSAPrivateKey, (d2i_of_void *)d2i_DSAPrivateKey, (char *)dsa); |
|
+ dsa_new = (DSA *)ASN1_dup((i2d_of_void *)i2d_DSAPrivateKey, |
|
+ (d2i_of_void *)d2i_DSAPrivateKey, |
|
+ (char *)dsa); |
|
if (!dsa_new) |
|
ossl_raise(eDSAError, "ASN1_dup"); |
|
|
|
- EVP_PKEY_assign_DSA(pkey, dsa_new); |
|
+ pkey = EVP_PKEY_new(); |
|
+ if (!pkey || EVP_PKEY_assign_DSA(pkey, dsa_new) != 1) { |
|
+ EVP_PKEY_free(pkey); |
|
+ DSA_free(dsa_new); |
|
+ ossl_raise(eDSAError, "EVP_PKEY_assign_DSA"); |
|
+ } |
|
+ RTYPEDDATA_DATA(self) = pkey; |
|
|
|
return self; |
|
} |
|
diff --git a/ext/openssl/ossl_pkey_ec.c b/ext/openssl/ossl_pkey_ec.c |
|
index db80d112..71e63969 100644 |
|
--- a/ext/openssl/ossl_pkey_ec.c |
|
+++ b/ext/openssl/ossl_pkey_ec.c |
|
@@ -114,13 +114,16 @@ ossl_ec_key_s_generate(VALUE klass, VALUE arg) |
|
VALUE obj; |
|
|
|
obj = rb_obj_alloc(klass); |
|
- GetPKey(obj, pkey); |
|
|
|
ec = ec_key_new_from_group(arg); |
|
- if (!EVP_PKEY_assign_EC_KEY(pkey, ec)) { |
|
+ pkey = EVP_PKEY_new(); |
|
+ if (!pkey || EVP_PKEY_assign_EC_KEY(pkey, ec) != 1) { |
|
+ EVP_PKEY_free(pkey); |
|
EC_KEY_free(ec); |
|
ossl_raise(eECError, "EVP_PKEY_assign_EC_KEY"); |
|
} |
|
+ RTYPEDDATA_DATA(obj) = pkey; |
|
+ |
|
if (!EC_KEY_generate_key(ec)) |
|
ossl_raise(eECError, "EC_KEY_generate_key"); |
|
|
|
@@ -141,51 +144,54 @@ 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 = NULL; |
|
+ EC_KEY *ec; |
|
+ BIO *in; |
|
VALUE arg, pass; |
|
+ int type; |
|
|
|
- GetPKey(self, pkey); |
|
- if (EVP_PKEY_base_id(pkey) != EVP_PKEY_NONE) |
|
- ossl_raise(eECError, "EC_KEY already initialized"); |
|
+ TypedData_Get_Struct(self, EVP_PKEY, &ossl_evp_pkey_type, pkey); |
|
+ if (pkey) |
|
+ rb_raise(rb_eTypeError, "pkey already initialized"); |
|
|
|
rb_scan_args(argc, argv, "02", &arg, &pass); |
|
- |
|
if (NIL_P(arg)) { |
|
if (!(ec = EC_KEY_new())) |
|
- ossl_raise(eECError, NULL); |
|
- } else if (rb_obj_is_kind_of(arg, cEC)) { |
|
- EC_KEY *other_ec = NULL; |
|
+ ossl_raise(eECError, "EC_KEY_new"); |
|
+ goto legacy; |
|
+ } |
|
+ else if (rb_obj_is_kind_of(arg, cEC_GROUP)) { |
|
+ ec = ec_key_new_from_group(arg); |
|
+ goto legacy; |
|
+ } |
|
|
|
- GetEC(arg, other_ec); |
|
- if (!(ec = EC_KEY_dup(other_ec))) |
|
- ossl_raise(eECError, NULL); |
|
- } else if (rb_obj_is_kind_of(arg, cEC_GROUP)) { |
|
- ec = ec_key_new_from_group(arg); |
|
- } else { |
|
- 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); |
|
+ pass = ossl_pem_passwd_value(pass); |
|
+ arg = ossl_to_der_if_possible(arg); |
|
+ in = ossl_obj2bio(&arg); |
|
|
|
- if (!ec) { |
|
- ossl_clear_error(); |
|
- ec = ec_key_new_from_group(arg); |
|
- } |
|
+ pkey = ossl_pkey_read_generic(in, pass); |
|
+ BIO_free(in); |
|
+ if (!pkey) { |
|
+ ossl_clear_error(); |
|
+ ec = ec_key_new_from_group(arg); |
|
+ goto legacy; |
|
} |
|
|
|
- if (!EVP_PKEY_assign_EC_KEY(pkey, ec)) { |
|
- EC_KEY_free(ec); |
|
- ossl_raise(eECError, "EVP_PKEY_assign_EC_KEY"); |
|
+ type = EVP_PKEY_base_id(pkey); |
|
+ if (type != EVP_PKEY_EC) { |
|
+ EVP_PKEY_free(pkey); |
|
+ rb_raise(eDSAError, "incorrect pkey type: %s", OBJ_nid2sn(type)); |
|
} |
|
+ RTYPEDDATA_DATA(self) = pkey; |
|
+ return self; |
|
|
|
+ legacy: |
|
+ pkey = EVP_PKEY_new(); |
|
+ if (!pkey || EVP_PKEY_assign_EC_KEY(pkey, ec) != 1) { |
|
+ EVP_PKEY_free(pkey); |
|
+ EC_KEY_free(ec); |
|
+ ossl_raise(eECError, "EVP_PKEY_assign_EC_KEY"); |
|
+ } |
|
+ RTYPEDDATA_DATA(self) = pkey; |
|
return self; |
|
} |
|
|
|
@@ -195,18 +201,21 @@ ossl_ec_key_initialize_copy(VALUE self, VALUE other) |
|
EVP_PKEY *pkey; |
|
EC_KEY *ec, *ec_new; |
|
|
|
- GetPKey(self, pkey); |
|
- if (EVP_PKEY_base_id(pkey) != EVP_PKEY_NONE) |
|
- ossl_raise(eECError, "EC already initialized"); |
|
+ TypedData_Get_Struct(self, EVP_PKEY, &ossl_evp_pkey_type, pkey); |
|
+ if (pkey) |
|
+ rb_raise(rb_eTypeError, "pkey already initialized"); |
|
GetEC(other, ec); |
|
|
|
ec_new = EC_KEY_dup(ec); |
|
if (!ec_new) |
|
ossl_raise(eECError, "EC_KEY_dup"); |
|
- if (!EVP_PKEY_assign_EC_KEY(pkey, ec_new)) { |
|
- EC_KEY_free(ec_new); |
|
- ossl_raise(eECError, "EVP_PKEY_assign_EC_KEY"); |
|
+ |
|
+ pkey = EVP_PKEY_new(); |
|
+ if (!pkey || EVP_PKEY_assign_EC_KEY(pkey, ec_new) != 1) { |
|
+ EC_KEY_free(ec_new); |
|
+ ossl_raise(eECError, "EVP_PKEY_assign_EC_KEY"); |
|
} |
|
+ RTYPEDDATA_DATA(self) = pkey; |
|
|
|
return self; |
|
} |
|
diff --git a/ext/openssl/ossl_pkey_rsa.c b/ext/openssl/ossl_pkey_rsa.c |
|
index 8ebd3ec5..b8dbc0e1 100644 |
|
--- a/ext/openssl/ossl_pkey_rsa.c |
|
+++ b/ext/openssl/ossl_pkey_rsa.c |
|
@@ -76,51 +76,62 @@ VALUE eRSAError; |
|
static VALUE |
|
ossl_rsa_initialize(int argc, VALUE *argv, VALUE self) |
|
{ |
|
- EVP_PKEY *pkey, *tmp; |
|
- RSA *rsa = NULL; |
|
- BIO *in; |
|
+ EVP_PKEY *pkey; |
|
+ RSA *rsa; |
|
+ BIO *in = NULL; |
|
VALUE arg, pass; |
|
+ int type; |
|
+ |
|
+ TypedData_Get_Struct(self, EVP_PKEY, &ossl_evp_pkey_type, pkey); |
|
+ if (pkey) |
|
+ rb_raise(rb_eTypeError, "pkey already initialized"); |
|
|
|
- GetPKey(self, pkey); |
|
/* The RSA.new(size, generator) form is handled by lib/openssl/pkey.rb */ |
|
rb_scan_args(argc, argv, "02", &arg, &pass); |
|
if (argc == 0) { |
|
rsa = RSA_new(); |
|
if (!rsa) |
|
ossl_raise(eRSAError, "RSA_new"); |
|
+ goto legacy; |
|
} |
|
- else { |
|
- pass = ossl_pem_passwd_value(pass); |
|
- arg = ossl_to_der_if_possible(arg); |
|
- in = ossl_obj2bio(&arg); |
|
- |
|
- 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); |
|
- } |
|
- if (!rsa) { |
|
- OSSL_BIO_reset(in); |
|
- rsa = d2i_RSAPublicKey_bio(in, NULL); |
|
- } |
|
- BIO_free(in); |
|
- if (!rsa) { |
|
- ossl_clear_error(); |
|
- ossl_raise(eRSAError, "Neither PUB key nor PRIV key"); |
|
- } |
|
- } |
|
- if (!EVP_PKEY_assign_RSA(pkey, rsa)) { |
|
- RSA_free(rsa); |
|
- ossl_raise(eRSAError, "EVP_PKEY_assign_RSA"); |
|
+ |
|
+ pass = ossl_pem_passwd_value(pass); |
|
+ arg = ossl_to_der_if_possible(arg); |
|
+ in = ossl_obj2bio(&arg); |
|
+ |
|
+ /* First try RSAPublicKey format */ |
|
+ rsa = d2i_RSAPublicKey_bio(in, NULL); |
|
+ if (rsa) |
|
+ goto legacy; |
|
+ OSSL_BIO_reset(in); |
|
+ rsa = PEM_read_bio_RSAPublicKey(in, NULL, NULL, NULL); |
|
+ if (rsa) |
|
+ goto legacy; |
|
+ OSSL_BIO_reset(in); |
|
+ |
|
+ /* Use the generic routine */ |
|
+ pkey = ossl_pkey_read_generic(in, pass); |
|
+ BIO_free(in); |
|
+ if (!pkey) |
|
+ ossl_raise(eRSAError, "Neither PUB key nor PRIV key"); |
|
+ |
|
+ type = EVP_PKEY_base_id(pkey); |
|
+ if (type != EVP_PKEY_RSA) { |
|
+ EVP_PKEY_free(pkey); |
|
+ rb_raise(eRSAError, "incorrect pkey type: %s", OBJ_nid2sn(type)); |
|
} |
|
+ RTYPEDDATA_DATA(self) = pkey; |
|
+ return self; |
|
|
|
+ legacy: |
|
+ BIO_free(in); |
|
+ pkey = EVP_PKEY_new(); |
|
+ if (!pkey || EVP_PKEY_assign_RSA(pkey, rsa) != 1) { |
|
+ EVP_PKEY_free(pkey); |
|
+ RSA_free(rsa); |
|
+ ossl_raise(eRSAError, "EVP_PKEY_assign_RSA"); |
|
+ } |
|
+ RTYPEDDATA_DATA(self) = pkey; |
|
return self; |
|
} |
|
|
|
@@ -130,16 +141,23 @@ ossl_rsa_initialize_copy(VALUE self, VALUE other) |
|
EVP_PKEY *pkey; |
|
RSA *rsa, *rsa_new; |
|
|
|
- GetPKey(self, pkey); |
|
- if (EVP_PKEY_base_id(pkey) != EVP_PKEY_NONE) |
|
- ossl_raise(eRSAError, "RSA already initialized"); |
|
+ TypedData_Get_Struct(self, EVP_PKEY, &ossl_evp_pkey_type, pkey); |
|
+ if (pkey) |
|
+ rb_raise(rb_eTypeError, "pkey already initialized"); |
|
GetRSA(other, rsa); |
|
|
|
- rsa_new = ASN1_dup((i2d_of_void *)i2d_RSAPrivateKey, (d2i_of_void *)d2i_RSAPrivateKey, (char *)rsa); |
|
+ rsa_new = (RSA *)ASN1_dup((i2d_of_void *)i2d_RSAPrivateKey, |
|
+ (d2i_of_void *)d2i_RSAPrivateKey, |
|
+ (char *)rsa); |
|
if (!rsa_new) |
|
ossl_raise(eRSAError, "ASN1_dup"); |
|
|
|
- EVP_PKEY_assign_RSA(pkey, rsa_new); |
|
+ pkey = EVP_PKEY_new(); |
|
+ if (!pkey || EVP_PKEY_assign_RSA(pkey, rsa_new) != 1) { |
|
+ RSA_free(rsa_new); |
|
+ ossl_raise(eRSAError, "EVP_PKEY_assign_RSA"); |
|
+ } |
|
+ RTYPEDDATA_DATA(self) = pkey; |
|
|
|
return self; |
|
} |
|
|
|
|