631 lines
19 KiB
Diff
631 lines
19 KiB
Diff
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;
|
|
}
|
|
|