From 63abe0078521d91db7a28de1db14bd193f74aad3 Mon Sep 17 00:00:00 2001 From: rhe Date: Sun, 5 Jun 2016 15:00:47 +0000 Subject: openssl: adapt OpenSSL::PKey to OpenSSL 1.1.0 opaque structs * ext/openssl/openssl_missing.[ch]: Implement EVP_PKEY_get0_*() and {RSA,DSA,EC_KEY,DH}_get0_*() functions. OpenSSL 1.1.0 makes EVP_PKEY/RSA/DSA/DH opaque. We used to provide setter methods for each parameter of each PKey type, for example PKey::RSA#e=, but this is no longer possible because the new API RSA_set0_key() requires the 'n' at the same time. This commit adds deprecation warning to them and adds PKey::*#set_* methods as direct wrapper for those new APIs. For example, 'rsa.e = 3' now needs to be rewritten as 'rsa.set_key(rsa.n, 3, rsa.d)'. [ruby-core:75225] [Feature #12324] * ext/openssl/ossl_pkey*.[ch]: Use the new accessor functions. Implement RSA#set_{key,factors,crt_params}, DSA#set_{key,pqg}, DH#set_{key,pqg}. Emit a warning with rb_warning() when old setter methods are used. * test/drb/ut_array_drbssl.rb, test/drb/ut_drb_drbssl.rb, test/rubygems/test_gem_remote_fetcher.rb: Don't set a priv_key for DH object that are used in tmp_dh_callback. Generating a new key pair every time should be fine - actually the private exponent is ignored in OpenSSL >= 1.0.2f/1.0.1r even if we explicitly set. https://www.openssl.org/news/secadv/20160128.txt git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@55285 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ext/openssl/ossl_pkey_rsa.c | 183 +++++++++++++++++++++++++------------------- 1 file changed, 103 insertions(+), 80 deletions(-) (limited to 'ext/openssl/ossl_pkey_rsa.c') diff --git a/ext/openssl/ossl_pkey_rsa.c b/ext/openssl/ossl_pkey_rsa.c index ea2af251cf..5d9bcb96be 100644 --- a/ext/openssl/ossl_pkey_rsa.c +++ b/ext/openssl/ossl_pkey_rsa.c @@ -7,19 +7,36 @@ * This program is licensed under the same licence as Ruby. * (See the file 'LICENCE'.) */ -#if !defined(OPENSSL_NO_RSA) - #include "ossl.h" +#if !defined(OPENSSL_NO_RSA) + #define GetPKeyRSA(obj, pkey) do { \ GetPKey((obj), (pkey)); \ - if (EVP_PKEY_type((pkey)->type) != EVP_PKEY_RSA) { /* PARANOIA? */ \ + if (EVP_PKEY_base_id(pkey) != EVP_PKEY_RSA) { /* PARANOIA? */ \ ossl_raise(rb_eRuntimeError, "THIS IS NOT A RSA!") ; \ } \ } while (0) +#define GetRSA(obj, rsa) do { \ + EVP_PKEY *_pkey; \ + GetPKeyRSA((obj), _pkey); \ + (rsa) = EVP_PKEY_get0_RSA(_pkey); \ +} while (0) + +static inline int +RSA_HAS_PRIVATE(RSA *rsa) +{ + BIGNUM *p, *q; + + RSA_get0_factors(rsa, &p, &q); + return p && q; /* d? why? */ +} -#define RSA_HAS_PRIVATE(rsa) ((rsa)->p && (rsa)->q) -#define RSA_PRIVATE(obj,rsa) (RSA_HAS_PRIVATE(rsa)||OSSL_PKEY_IS_PRIVATE(obj)) +static inline int +RSA_PRIVATE(VALUE obj, RSA *rsa) +{ + return RSA_HAS_PRIVATE(rsa) || OSSL_PKEY_IS_PRIVATE(obj); +} /* * Classes @@ -62,7 +79,7 @@ ossl_rsa_new(EVP_PKEY *pkey) } else { obj = NewPKey(cRSA); - if (EVP_PKEY_type(pkey->type) != EVP_PKEY_RSA) { + if (EVP_PKEY_base_id(pkey) != EVP_PKEY_RSA) { ossl_raise(rb_eTypeError, "Not a RSA key!"); } SetPKey(obj, pkey); @@ -262,12 +279,13 @@ ossl_rsa_initialize(int argc, VALUE *argv, VALUE self) static VALUE ossl_rsa_is_public(VALUE self) { - EVP_PKEY *pkey; + RSA *rsa; - GetPKeyRSA(self, pkey); + GetRSA(self, rsa); /* * This method should check for n and e. BUG. */ + (void)rsa; return Qtrue; } @@ -280,11 +298,11 @@ ossl_rsa_is_public(VALUE self) static VALUE ossl_rsa_is_private(VALUE self) { - EVP_PKEY *pkey; + RSA *rsa; - GetPKeyRSA(self, pkey); + GetRSA(self, rsa); - return (RSA_PRIVATE(self, pkey->pkey.rsa)) ? Qtrue : Qfalse; + return RSA_PRIVATE(self, rsa) ? Qtrue : Qfalse; } /* @@ -300,12 +318,12 @@ ossl_rsa_is_private(VALUE self) static VALUE ossl_rsa_export(int argc, VALUE *argv, VALUE self) { - EVP_PKEY *pkey; + RSA *rsa; BIO *out; const EVP_CIPHER *ciph = NULL; VALUE cipher, pass, str; - GetPKeyRSA(self, pkey); + GetRSA(self, rsa); rb_scan_args(argc, argv, "02", &cipher, &pass); @@ -316,14 +334,14 @@ ossl_rsa_export(int argc, VALUE *argv, VALUE self) if (!(out = BIO_new(BIO_s_mem()))) { ossl_raise(eRSAError, NULL); } - if (RSA_HAS_PRIVATE(pkey->pkey.rsa)) { - if (!PEM_write_bio_RSAPrivateKey(out, pkey->pkey.rsa, ciph, - NULL, 0, ossl_pem_passwd_cb, (void *)pass)) { + if (RSA_HAS_PRIVATE(rsa)) { + 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, pkey->pkey.rsa)) { + if (!PEM_write_bio_RSA_PUBKEY(out, rsa)) { BIO_free(out); ossl_raise(eRSAError, NULL); } @@ -342,29 +360,29 @@ ossl_rsa_export(int argc, VALUE *argv, VALUE self) static VALUE ossl_rsa_to_der(VALUE self) { - EVP_PKEY *pkey; + RSA *rsa; int (*i2d_func)_((const RSA*, unsigned char**)); unsigned char *p; long len; VALUE str; - GetPKeyRSA(self, pkey); - if(RSA_HAS_PRIVATE(pkey->pkey.rsa)) + GetRSA(self, rsa); + if (RSA_HAS_PRIVATE(rsa)) i2d_func = i2d_RSAPrivateKey; else i2d_func = (int (*)(const RSA*, unsigned char**))i2d_RSA_PUBKEY; - if((len = i2d_func(pkey->pkey.rsa, NULL)) <= 0) + if((len = i2d_func(rsa, NULL)) <= 0) ossl_raise(eRSAError, NULL); str = rb_str_new(0, len); p = (unsigned char *)RSTRING_PTR(str); - if(i2d_func(pkey->pkey.rsa, &p) < 0) + if(i2d_func(rsa, &p) < 0) ossl_raise(eRSAError, NULL); ossl_str_adjust(str, p); return str; } -#define ossl_rsa_buf_size(pkey) (RSA_size((pkey)->pkey.rsa)+16) +#define ossl_rsa_buf_size(rsa) (RSA_size(rsa)+16) /* * call-seq: @@ -377,20 +395,21 @@ ossl_rsa_to_der(VALUE self) static VALUE ossl_rsa_public_encrypt(int argc, VALUE *argv, VALUE self) { - EVP_PKEY *pkey; + RSA *rsa; + BIGNUM *rsa_n; int buf_len, pad; VALUE str, buffer, padding; - GetPKeyRSA(self, pkey); - if (!pkey->pkey.rsa->n) + GetRSA(self, rsa); + RSA_get0_key(rsa, &rsa_n, NULL, NULL); + if (!rsa_n) ossl_raise(eRSAError, "incomplete RSA"); rb_scan_args(argc, argv, "11", &buffer, &padding); pad = (argc == 1) ? RSA_PKCS1_PADDING : NUM2INT(padding); StringValue(buffer); - str = rb_str_new(0, ossl_rsa_buf_size(pkey)); + str = rb_str_new(0, ossl_rsa_buf_size(rsa)); buf_len = RSA_public_encrypt(RSTRING_LENINT(buffer), (unsigned char *)RSTRING_PTR(buffer), - (unsigned char *)RSTRING_PTR(str), pkey->pkey.rsa, - pad); + (unsigned char *)RSTRING_PTR(str), rsa, pad); if (buf_len < 0) ossl_raise(eRSAError, NULL); rb_str_set_len(str, buf_len); @@ -408,20 +427,21 @@ ossl_rsa_public_encrypt(int argc, VALUE *argv, VALUE self) static VALUE ossl_rsa_public_decrypt(int argc, VALUE *argv, VALUE self) { - EVP_PKEY *pkey; + RSA *rsa; + BIGNUM *rsa_n; int buf_len, pad; VALUE str, buffer, padding; - GetPKeyRSA(self, pkey); - if (!pkey->pkey.rsa->n) + GetRSA(self, rsa); + RSA_get0_key(rsa, &rsa_n, NULL, NULL); + if (!rsa_n) ossl_raise(eRSAError, "incomplete RSA"); rb_scan_args(argc, argv, "11", &buffer, &padding); pad = (argc == 1) ? RSA_PKCS1_PADDING : NUM2INT(padding); StringValue(buffer); - str = rb_str_new(0, ossl_rsa_buf_size(pkey)); + str = rb_str_new(0, ossl_rsa_buf_size(rsa)); buf_len = RSA_public_decrypt(RSTRING_LENINT(buffer), (unsigned char *)RSTRING_PTR(buffer), - (unsigned char *)RSTRING_PTR(str), pkey->pkey.rsa, - pad); + (unsigned char *)RSTRING_PTR(str), rsa, pad); if (buf_len < 0) ossl_raise(eRSAError, NULL); rb_str_set_len(str, buf_len); @@ -439,22 +459,23 @@ ossl_rsa_public_decrypt(int argc, VALUE *argv, VALUE self) static VALUE ossl_rsa_private_encrypt(int argc, VALUE *argv, VALUE self) { - EVP_PKEY *pkey; + RSA *rsa; + BIGNUM *rsa_n; int buf_len, pad; VALUE str, buffer, padding; - GetPKeyRSA(self, pkey); - if (!pkey->pkey.rsa->n) + GetRSA(self, rsa); + RSA_get0_key(rsa, &rsa_n, NULL, NULL); + if (!rsa_n) ossl_raise(eRSAError, "incomplete RSA"); - if (!RSA_PRIVATE(self, pkey->pkey.rsa)) - ossl_raise(eRSAError, "private key needed"); + if (!RSA_PRIVATE(self, rsa)) + ossl_raise(eRSAError, "private key needed."); rb_scan_args(argc, argv, "11", &buffer, &padding); pad = (argc == 1) ? RSA_PKCS1_PADDING : NUM2INT(padding); StringValue(buffer); - str = rb_str_new(0, ossl_rsa_buf_size(pkey)); + str = rb_str_new(0, ossl_rsa_buf_size(rsa)); buf_len = RSA_private_encrypt(RSTRING_LENINT(buffer), (unsigned char *)RSTRING_PTR(buffer), - (unsigned char *)RSTRING_PTR(str), pkey->pkey.rsa, - pad); + (unsigned char *)RSTRING_PTR(str), rsa, pad); if (buf_len < 0) ossl_raise(eRSAError, NULL); rb_str_set_len(str, buf_len); @@ -472,22 +493,23 @@ ossl_rsa_private_encrypt(int argc, VALUE *argv, VALUE self) static VALUE ossl_rsa_private_decrypt(int argc, VALUE *argv, VALUE self) { - EVP_PKEY *pkey; + RSA *rsa; + BIGNUM *rsa_n; int buf_len, pad; VALUE str, buffer, padding; - GetPKeyRSA(self, pkey); - if (!pkey->pkey.rsa->n) + GetRSA(self, rsa); + RSA_get0_key(rsa, &rsa_n, NULL, NULL); + if (!rsa_n) ossl_raise(eRSAError, "incomplete RSA"); - if (!RSA_PRIVATE(self, pkey->pkey.rsa)) - ossl_raise(eRSAError, "private key needed"); + if (!RSA_PRIVATE(self, rsa)) + ossl_raise(eRSAError, "private key needed."); rb_scan_args(argc, argv, "11", &buffer, &padding); pad = (argc == 1) ? RSA_PKCS1_PADDING : NUM2INT(padding); StringValue(buffer); - str = rb_str_new(0, ossl_rsa_buf_size(pkey)); + str = rb_str_new(0, ossl_rsa_buf_size(rsa)); buf_len = RSA_private_decrypt(RSTRING_LENINT(buffer), (unsigned char *)RSTRING_PTR(buffer), - (unsigned char *)RSTRING_PTR(str), pkey->pkey.rsa, - pad); + (unsigned char *)RSTRING_PTR(str), rsa, pad); if (buf_len < 0) ossl_raise(eRSAError, NULL); rb_str_set_len(str, buf_len); @@ -508,21 +530,24 @@ ossl_rsa_private_decrypt(int argc, VALUE *argv, VALUE self) static VALUE ossl_rsa_get_params(VALUE self) { - EVP_PKEY *pkey; + RSA *rsa; VALUE hash; + BIGNUM *n, *e, *d, *p, *q, *dmp1, *dmq1, *iqmp; - GetPKeyRSA(self, pkey); + GetRSA(self, rsa); + RSA_get0_key(rsa, &n, &e, &d); + RSA_get0_factors(rsa, &p, &q); + RSA_get0_crt_params(rsa, &dmp1, &dmq1, &iqmp); hash = rb_hash_new(); - - rb_hash_aset(hash, rb_str_new2("n"), ossl_bn_new(pkey->pkey.rsa->n)); - rb_hash_aset(hash, rb_str_new2("e"), ossl_bn_new(pkey->pkey.rsa->e)); - rb_hash_aset(hash, rb_str_new2("d"), ossl_bn_new(pkey->pkey.rsa->d)); - rb_hash_aset(hash, rb_str_new2("p"), ossl_bn_new(pkey->pkey.rsa->p)); - rb_hash_aset(hash, rb_str_new2("q"), ossl_bn_new(pkey->pkey.rsa->q)); - rb_hash_aset(hash, rb_str_new2("dmp1"), ossl_bn_new(pkey->pkey.rsa->dmp1)); - rb_hash_aset(hash, rb_str_new2("dmq1"), ossl_bn_new(pkey->pkey.rsa->dmq1)); - rb_hash_aset(hash, rb_str_new2("iqmp"), ossl_bn_new(pkey->pkey.rsa->iqmp)); + rb_hash_aset(hash, rb_str_new2("n"), ossl_bn_new(n)); + rb_hash_aset(hash, rb_str_new2("e"), ossl_bn_new(e)); + rb_hash_aset(hash, rb_str_new2("d"), ossl_bn_new(d)); + rb_hash_aset(hash, rb_str_new2("p"), ossl_bn_new(p)); + rb_hash_aset(hash, rb_str_new2("q"), ossl_bn_new(q)); + rb_hash_aset(hash, rb_str_new2("dmp1"), ossl_bn_new(dmp1)); + rb_hash_aset(hash, rb_str_new2("dmq1"), ossl_bn_new(dmq1)); + rb_hash_aset(hash, rb_str_new2("iqmp"), ossl_bn_new(iqmp)); return hash; } @@ -540,15 +565,15 @@ ossl_rsa_get_params(VALUE self) static VALUE ossl_rsa_to_text(VALUE self) { - EVP_PKEY *pkey; + RSA *rsa; BIO *out; VALUE str; - GetPKeyRSA(self, pkey); + GetRSA(self, rsa); if (!(out = BIO_new(BIO_s_mem()))) { ossl_raise(eRSAError, NULL); } - if (!RSA_print(out, pkey->pkey.rsa, 0)) { /* offset = 0 */ + if (!RSA_print(out, rsa, 0)) { /* offset = 0 */ BIO_free(out); ossl_raise(eRSAError, NULL); } @@ -572,7 +597,7 @@ ossl_rsa_to_public_key(VALUE self) GetPKeyRSA(self, pkey); /* err check performed by rsa_instance */ - rsa = RSAPublicKey_dup(pkey->pkey.rsa); + rsa = RSAPublicKey_dup(EVP_PKEY_get0_RSA(pkey)); obj = rsa_instance(CLASS_OF(self), rsa); if (obj == Qfalse) { RSA_free(rsa); @@ -587,11 +612,11 @@ ossl_rsa_to_public_key(VALUE self) static VALUE ossl_rsa_blinding_on(VALUE self) { - EVP_PKEY *pkey; + RSA *rsa; - GetPKeyRSA(self, pkey); + GetRSA(self, rsa); - if (RSA_blinding_on(pkey->pkey.rsa, ossl_bn_ctx) != 1) { + if (RSA_blinding_on(rsa, ossl_bn_ctx) != 1) { ossl_raise(eRSAError, NULL); } return self; @@ -600,23 +625,18 @@ ossl_rsa_blinding_on(VALUE self) static VALUE ossl_rsa_blinding_off(VALUE self) { - EVP_PKEY *pkey; + RSA *rsa; - GetPKeyRSA(self, pkey); - RSA_blinding_off(pkey->pkey.rsa); + GetRSA(self, rsa); + RSA_blinding_off(rsa); return self; } */ -OSSL_PKEY_BN(rsa, n) -OSSL_PKEY_BN(rsa, e) -OSSL_PKEY_BN(rsa, d) -OSSL_PKEY_BN(rsa, p) -OSSL_PKEY_BN(rsa, q) -OSSL_PKEY_BN(rsa, dmp1) -OSSL_PKEY_BN(rsa, dmq1) -OSSL_PKEY_BN(rsa, iqmp) +OSSL_PKEY_BN_DEF3(rsa, RSA, key, n, e, d); +OSSL_PKEY_BN_DEF2(rsa, RSA, factors, p, q); +OSSL_PKEY_BN_DEF3(rsa, RSA, crt_params, dmp1, dmq1, iqmp); /* * INIT @@ -675,6 +695,9 @@ Init_ossl_rsa(void) DEF_OSSL_PKEY_BN(cRSA, rsa, dmp1); DEF_OSSL_PKEY_BN(cRSA, rsa, dmq1); DEF_OSSL_PKEY_BN(cRSA, rsa, iqmp); + rb_define_method(cRSA, "set_key", ossl_rsa_set_key, 3); + rb_define_method(cRSA, "set_factors", ossl_rsa_set_factors, 2); + rb_define_method(cRSA, "set_crt_params", ossl_rsa_set_crt_params, 3); rb_define_method(cRSA, "params", ossl_rsa_get_params, 0); -- cgit v1.2.3