summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKazuki Yamaguchi <k@rhe.jp>2017-06-13 23:39:41 +0900
committerKazuki Yamaguchi <k@rhe.jp>2021-03-16 19:16:10 +0900
commit707e3d49cbd8e648c6e6496daedb98bf17674dc7 (patch)
tree56a6dac859e81e562528c8992e053ef98daaff2c
parent10d360847baf3394b7d9cd0dca6fa6908a2ce604 (diff)
[ruby/openssl] 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. https://github.com/ruby/openssl/commit/d963d4e276
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/4275
-rw-r--r--ext/openssl/ossl_pkey.c57
-rw-r--r--ext/openssl/ossl_pkey.h1
-rw-r--r--ext/openssl/ossl_pkey_dsa.c37
-rw-r--r--ext/openssl/ossl_pkey_ec.c29
-rw-r--r--ext/openssl/ossl_pkey_rsa.c26
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");
}
}