ruby-changes:65493
From: Kazuki <ko1@a...>
Date: Tue, 16 Mar 2021 20:38:47 +0900 (JST)
Subject: [ruby-changes:65493] 707e3d49cb (master): [ruby/openssl] pkey: refactor DER/PEM-encoded string parsing code
https://git.ruby-lang.org/ruby.git/commit/?id=707e3d49cb From 707e3d49cbd8e648c6e6496daedb98bf17674dc7 Mon Sep 17 00:00:00 2001 From: Kazuki Yamaguchi <k@r...> Date: Tue, 13 Jun 2017 23:39:41 +0900 Subject: [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 --- 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 a00d66a..47ddd0f 100644 --- a/ext/openssl/ossl_pkey.c +++ b/ext/openssl/ossl_pkey.c @@ -136,6 +136,35 @@ ossl_pkey_new(EVP_PKEY *pkey) https://github.com/ruby/ruby/blob/trunk/ext/openssl/ossl_pkey.c#L136 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) https://github.com/ruby/ruby/blob/trunk/ext/openssl/ossl_pkey.c#L189 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 e363a26..895927e 100644 --- a/ext/openssl/ossl_pkey.h +++ b/ext/openssl/ossl_pkey.h @@ -45,6 +45,7 @@ void ossl_generate_cb_stop(void *ptr); https://github.com/ruby/ruby/blob/trunk/ext/openssl/ossl_pkey.h#L45 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 c907f31..56f5855 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) https://github.com/ruby/ruby/blob/trunk/ext/openssl/ossl_pkey_dsa.c#L170 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 aec9d1e..ca8f5c6 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) https://github.com/ruby/ruby/blob/trunk/ext/openssl/ossl_pkey_ec.c#L162 } 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 fbdb9c8..8415121 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) https://github.com/ruby/ruby/blob/trunk/ext/openssl/ossl_pkey_rsa.c#L179 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) https://github.com/ruby/ruby/blob/trunk/ext/openssl/ossl_pkey_rsa.c#L192 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) https://github.com/ruby/ruby/blob/trunk/ext/openssl/ossl_pkey_rsa.c#L211 } BIO_free(in); if (!rsa) { + ossl_clear_error(); ossl_raise(eRSAError, "Neither PUB key nor PRIV key"); } } -- cgit v1.1 -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/