From 7ea72f1f50849ad0c36e08c0ac70bbdba1d96169 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/extconf.rb | 1 + ext/openssl/openssl_missing.h | 58 +++++++++++++ ext/openssl/ossl_pkey.c | 2 +- ext/openssl/ossl_pkey.h | 140 +++++++++++++++++++++++++++----- ext/openssl/ossl_pkey_dh.c | 115 +++++++++++++------------- ext/openssl/ossl_pkey_dsa.c | 122 ++++++++++++++++------------ ext/openssl/ossl_pkey_ec.c | 8 +- ext/openssl/ossl_pkey_rsa.c | 183 ++++++++++++++++++++++++------------------ ext/openssl/ossl_ssl.c | 8 +- test/utils.rb | 3 +- 10 files changed, 423 insertions(+), 217 deletions(-) diff --git a/ext/openssl/extconf.rb b/ext/openssl/extconf.rb index e7c9c4bc..d72517eb 100644 --- a/ext/openssl/extconf.rb +++ b/ext/openssl/extconf.rb @@ -87,6 +87,7 @@ engines.each { |name| # added in 1.0.0 have_func("ASN1_TIME_adj") have_func("EVP_CIPHER_CTX_copy") +have_func("EVP_PKEY_base_id") have_func("HMAC_CTX_copy") have_func("PKCS5_PBKDF2_HMAC") have_func("X509_NAME_hash_old") diff --git a/ext/openssl/openssl_missing.h b/ext/openssl/openssl_missing.h index d81d6a74..22f16bf0 100644 --- a/ext/openssl/openssl_missing.h +++ b/ext/openssl/openssl_missing.h @@ -11,6 +11,10 @@ #define _OSSL_OPENSSL_MISSING_H_ /* added in 1.0.0 */ +#if !defined(HAVE_EVP_PKEY_BASE_ID) +# define EVP_PKEY_base_id(pkey) EVP_PKEY_type((pkey)->type) +#endif + #if !defined(HAVE_EVP_CIPHER_CTX_COPY) int EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out, const EVP_CIPHER_CTX *in); #endif @@ -70,4 +74,58 @@ int EC_curve_nist2nid(const char *); CRYPTO_add(&(x)->references, 1, CRYPTO_LOCK_EVP_PKEY); #endif +#if !defined(HAVE_OPAQUE_OPENSSL) +#define IMPL_PKEY_GETTER(_type, _name) \ +static inline _type *EVP_PKEY_get0_##_type(EVP_PKEY *pkey) { \ + return pkey->pkey._name; } +#define IMPL_KEY_ACCESSOR2(_type, _group, a1, a2, _fail_cond) \ +static inline void _type##_get0_##_group(_type *obj, BIGNUM **a1, BIGNUM **a2) { \ + if (a1) *a1 = obj->a1; \ + if (a2) *a2 = obj->a2; } \ +static inline int _type##_set0_##_group(_type *obj, BIGNUM *a1, BIGNUM *a2) { \ + if (_fail_cond) return 0; \ + BN_clear_free(obj->a1); obj->a1 = a1; \ + BN_clear_free(obj->a2); obj->a2 = a2; \ + return 1; } +#define IMPL_KEY_ACCESSOR3(_type, _group, a1, a2, a3, _fail_cond) \ +static inline void _type##_get0_##_group(_type *obj, BIGNUM **a1, BIGNUM **a2, BIGNUM **a3) { \ + if (a1) *a1 = obj->a1; \ + if (a2) *a2 = obj->a2; \ + if (a3) *a3 = obj->a3; } \ +static inline int _type##_set0_##_group(_type *obj, BIGNUM *a1, BIGNUM *a2, BIGNUM *a3) { \ + if (_fail_cond) return 0; \ + BN_clear_free(obj->a1); obj->a1 = a1; \ + BN_clear_free(obj->a2); obj->a2 = a2; \ + BN_clear_free(obj->a3); obj->a3 = a3; \ + return 1; } + +#if !defined(OPENSSL_NO_RSA) +IMPL_PKEY_GETTER(RSA, rsa) +IMPL_KEY_ACCESSOR3(RSA, key, n, e, d, (n == obj->n || e == obj->e || (obj->d && e == obj->d))) +IMPL_KEY_ACCESSOR2(RSA, factors, p, q, (p == obj->p || q == obj->q)) +IMPL_KEY_ACCESSOR3(RSA, crt_params, dmp1, dmq1, iqmp, (dmp1 == obj->dmp1 || dmq1 == obj->dmq1 || iqmp == obj->iqmp)) +#endif + +#if !defined(OPENSSL_NO_DSA) +IMPL_PKEY_GETTER(DSA, dsa) +IMPL_KEY_ACCESSOR2(DSA, key, pub_key, priv_key, (pub_key == obj->pub_key || (obj->priv_key && priv_key == obj->priv_key))) +IMPL_KEY_ACCESSOR3(DSA, pqg, p, q, g, (p == obj->p || q == obj->q || g == obj->g)) +#endif + +#if !defined(OPENSSL_NO_DH) +IMPL_PKEY_GETTER(DH, dh) +IMPL_KEY_ACCESSOR2(DH, key, pub_key, priv_key, (pub_key == obj->pub_key || (obj->priv_key && priv_key == obj->priv_key))) +IMPL_KEY_ACCESSOR3(DH, pqg, p, q, g, (p == obj->p || q == obj->q || g == obj->g)) +static inline ENGINE *DH_get0_engine(DH *dh) { return dh->engine; } +#endif + +#if !defined(OPENSSL_NO_EC) +IMPL_PKEY_GETTER(EC_KEY, ec) +#endif + +#undef IMPL_PKEY_GETTER +#undef IMPL_KEY_ACCESSOR2 +#undef IMPL_KEY_ACCESSOR3 +#endif /* HAVE_OPAQUE_OPENSSL */ + #endif /* _OSSL_OPENSSL_MISSING_H_ */ diff --git a/ext/openssl/ossl_pkey.c b/ext/openssl/ossl_pkey.c index e795f424..c59a3646 100644 --- a/ext/openssl/ossl_pkey.c +++ b/ext/openssl/ossl_pkey.c @@ -76,7 +76,7 @@ ossl_pkey_new(EVP_PKEY *pkey) if (!pkey) { ossl_raise(ePKeyError, "Cannot make new key from NULL."); } - switch (EVP_PKEY_type(pkey->type)) { + switch (EVP_PKEY_base_id(pkey)) { #if !defined(OPENSSL_NO_RSA) case EVP_PKEY_RSA: return ossl_rsa_new(pkey); diff --git a/ext/openssl/ossl_pkey.h b/ext/openssl/ossl_pkey.h index b806d63e..6f9555e5 100644 --- a/ext/openssl/ossl_pkey.h +++ b/ext/openssl/ossl_pkey.h @@ -95,53 +95,153 @@ extern VALUE eEC_POINT; VALUE ossl_ec_new(EVP_PKEY *); void Init_ossl_ec(void); - -#define OSSL_PKEY_BN(keytype, name) \ +#define OSSL_PKEY_BN_DEF_GETTER0(_keytype, _type, _name, _get) \ /* \ * call-seq: \ - * key.##name -> aBN \ + * _keytype##.##_name -> aBN \ */ \ -static VALUE ossl_##keytype##_get_##name(VALUE self) \ +static VALUE ossl_##_keytype##_get_##_name(VALUE self) \ { \ - EVP_PKEY *pkey; \ + _type *obj; \ BIGNUM *bn; \ \ - GetPKey(self, pkey); \ - bn = pkey->pkey.keytype->name; \ + Get##_type(self, obj); \ + _get; \ if (bn == NULL) \ return Qnil; \ return ossl_bn_new(bn); \ -} \ +} + +#define OSSL_PKEY_BN_DEF_GETTER3(_keytype, _type, _group, a1, a2, a3) \ + OSSL_PKEY_BN_DEF_GETTER0(_keytype, _type, a1, \ + _type##_get0_##_group(obj, &bn, NULL, NULL)) \ + OSSL_PKEY_BN_DEF_GETTER0(_keytype, _type, a2, \ + _type##_get0_##_group(obj, NULL, &bn, NULL)) \ + OSSL_PKEY_BN_DEF_GETTER0(_keytype, _type, a3, \ + _type##_get0_##_group(obj, NULL, NULL, &bn)) + +#define OSSL_PKEY_BN_DEF_GETTER2(_keytype, _type, _group, a1, a2) \ + OSSL_PKEY_BN_DEF_GETTER0(_keytype, _type, a1, \ + _type##_get0_##_group(obj, &bn, NULL)) \ + OSSL_PKEY_BN_DEF_GETTER0(_keytype, _type, a2, \ + _type##_get0_##_group(obj, NULL, &bn)) + +#define OSSL_PKEY_BN_DEF_SETTER3(_keytype, _type, _group, a1, a2, a3) \ +/* \ + * call-seq: \ + * _keytype##.set_##_group(a1, a2, a3) -> self \ + */ \ +static VALUE ossl_##_keytype##_set_##_group(VALUE self, VALUE v1, VALUE v2, VALUE v3) \ +{ \ + _type *obj; \ + BIGNUM *bn1 = NULL, *orig_bn1 = NIL_P(v1) ? NULL : GetBNPtr(v1);\ + BIGNUM *bn2 = NULL, *orig_bn2 = NIL_P(v2) ? NULL : GetBNPtr(v2);\ + BIGNUM *bn3 = NULL, *orig_bn3 = NIL_P(v3) ? NULL : GetBNPtr(v3);\ + \ + Get##_type(self, obj); \ + if (orig_bn1 && !(bn1 = BN_dup(orig_bn1)) || \ + orig_bn2 && !(bn2 = BN_dup(orig_bn2)) || \ + orig_bn3 && !(bn3 = BN_dup(orig_bn3))) { \ + BN_clear_free(bn1); \ + BN_clear_free(bn2); \ + BN_clear_free(bn3); \ + ossl_raise(eBNError, NULL); \ + } \ + \ + if (!_type##_set0_##_group(obj, bn1, bn2, bn3)) { \ + BN_clear_free(bn1); \ + BN_clear_free(bn2); \ + BN_clear_free(bn3); \ + ossl_raise(ePKeyError, #_type"_set0_"#_group); \ + } \ + return self; \ +} + +#define OSSL_PKEY_BN_DEF_SETTER2(_keytype, _type, _group, a1, a2) \ /* \ * call-seq: \ - * key.##name = bn -> bn \ + * _keytype##.set_##_group(a1, a2) -> self \ */ \ -static VALUE ossl_##keytype##_set_##name(VALUE self, VALUE bignum) \ +static VALUE ossl_##_keytype##_set_##_group(VALUE self, VALUE v1, VALUE v2) \ { \ - EVP_PKEY *pkey; \ + _type *obj; \ + BIGNUM *bn1 = NULL, *orig_bn1 = NIL_P(v1) ? NULL : GetBNPtr(v1);\ + BIGNUM *bn2 = NULL, *orig_bn2 = NIL_P(v2) ? NULL : GetBNPtr(v2);\ + \ + Get##_type(self, obj); \ + if (orig_bn1 && !(bn1 = BN_dup(orig_bn1)) || \ + orig_bn2 && !(bn2 = BN_dup(orig_bn2))) { \ + BN_clear_free(bn1); \ + BN_clear_free(bn2); \ + ossl_raise(eBNError, NULL); \ + } \ + \ + if (!_type##_set0_##_group(obj, bn1, bn2)) { \ + BN_clear_free(bn1); \ + BN_clear_free(bn2); \ + ossl_raise(ePKeyError, #_type"_set0_"#_group); \ + } \ + return self; \ +} + +#define OSSL_PKEY_BN_DEF_SETTER_OLD(_keytype, _type, _group, _name) \ +/* \ + * call-seq: \ + * _keytype##.##_name = bn -> bn \ + */ \ +static VALUE ossl_##_keytype##_set_##_name(VALUE self, VALUE bignum) \ +{ \ + _type *obj; \ BIGNUM *bn; \ \ - GetPKey(self, pkey); \ + rb_warning("#"#_name"= is deprecated; use #set_"#_group); \ + Get##_type(self, obj); \ if (NIL_P(bignum)) { \ - BN_clear_free(pkey->pkey.keytype->name); \ - pkey->pkey.keytype->name = NULL; \ + BN_clear_free(obj->_name); \ + obj->_name = NULL; \ return Qnil; \ } \ \ bn = GetBNPtr(bignum); \ - if (pkey->pkey.keytype->name == NULL) \ - pkey->pkey.keytype->name = BN_new(); \ - if (pkey->pkey.keytype->name == NULL) \ + if (obj->_name == NULL) \ + obj->_name = BN_new(); \ + if (obj->_name == NULL) \ ossl_raise(eBNError, NULL); \ - if (BN_copy(pkey->pkey.keytype->name, bn) == NULL) \ + if (BN_copy(obj->_name, bn) == NULL) \ ossl_raise(eBNError, NULL); \ return bignum; \ } +#if defined(HAVE_OPAQUE_OPENSSL) /* OpenSSL 1.1.0 */ +#define OSSL_PKEY_BN_DEF3(_keytype, _type, _group, a1, a2, a3) \ + OSSL_PKEY_BN_DEF_GETTER3(_keytype, _type, _group, a1, a2, a3) \ + OSSL_PKEY_BN_DEF_SETTER3(_keytype, _type, _group, a1, a2, a3) + +#define OSSL_PKEY_BN_DEF2(_keytype, _type, _group, a1, a2) \ + OSSL_PKEY_BN_DEF_GETTER2(_keytype, _type, _group, a1, a2) \ + OSSL_PKEY_BN_DEF_SETTER2(_keytype, _type, _group, a1, a2) + #define DEF_OSSL_PKEY_BN(class, keytype, name) \ -do { \ - rb_define_method((class), #name, ossl_##keytype##_get_##name, 0); \ + rb_define_method((class), #name, ossl_##keytype##_get_##name, 0) + +#else +#define OSSL_PKEY_BN_DEF3(_keytype, _type, _group, a1, a2, a3) \ + OSSL_PKEY_BN_DEF_GETTER3(_keytype, _type, _group, a1, a2, a3) \ + OSSL_PKEY_BN_DEF_SETTER3(_keytype, _type, _group, a1, a2, a3) \ + OSSL_PKEY_BN_DEF_SETTER_OLD(_keytype, _type, _group, a1) \ + OSSL_PKEY_BN_DEF_SETTER_OLD(_keytype, _type, _group, a2) \ + OSSL_PKEY_BN_DEF_SETTER_OLD(_keytype, _type, _group, a3) + +#define OSSL_PKEY_BN_DEF2(_keytype, _type, _group, a1, a2) \ + OSSL_PKEY_BN_DEF_GETTER2(_keytype, _type, _group, a1, a2) \ + OSSL_PKEY_BN_DEF_SETTER2(_keytype, _type, _group, a1, a2) \ + OSSL_PKEY_BN_DEF_SETTER_OLD(_keytype, _type, _group, a1) \ + OSSL_PKEY_BN_DEF_SETTER_OLD(_keytype, _type, _group, a2) + +#define DEF_OSSL_PKEY_BN(class, keytype, name) do { \ + rb_define_method((class), #name, ossl_##keytype##_get_##name, 0);\ rb_define_method((class), #name "=", ossl_##keytype##_set_##name, 1);\ } while (0) +#endif /* HAVE_OPAQUE_OPENSSL */ #endif /* _OSSL_PKEY_H_ */ diff --git a/ext/openssl/ossl_pkey_dh.c b/ext/openssl/ossl_pkey_dh.c index ac951a6e..9fdc48a9 100644 --- a/ext/openssl/ossl_pkey_dh.c +++ b/ext/openssl/ossl_pkey_dh.c @@ -7,25 +7,21 @@ * This program is licensed under the same licence as Ruby. * (See the file 'LICENCE'.) */ -#if !defined(OPENSSL_NO_DH) - #include "ossl.h" +#if !defined(OPENSSL_NO_DH) + #define GetPKeyDH(obj, pkey) do { \ GetPKey((obj), (pkey)); \ - if (EVP_PKEY_type((pkey)->type) != EVP_PKEY_DH) { /* PARANOIA? */ \ + if (EVP_PKEY_base_id(pkey) != EVP_PKEY_DH) { /* PARANOIA? */ \ ossl_raise(rb_eRuntimeError, "THIS IS NOT A DH!") ; \ } \ } while (0) - -#define DH_HAS_PRIVATE(dh) ((dh)->priv_key) - -#if !defined(OPENSSL_NO_ENGINE) -# define DH_PRIVATE(dh) (DH_HAS_PRIVATE(dh) || (dh)->engine) -#else -# define DH_PRIVATE(dh) DH_HAS_PRIVATE(dh) -#endif - +#define GetDH(obj, dh) do { \ + EVP_PKEY *_pkey; \ + GetPKeyDH((obj), _pkey); \ + (dh) = EVP_PKEY_get0_DH(_pkey); \ +} while (0) /* * Classes @@ -67,7 +63,7 @@ ossl_dh_new(EVP_PKEY *pkey) obj = dh_instance(cDH, DH_new()); } else { obj = NewPKey(cDH); - if (EVP_PKEY_type(pkey->type) != EVP_PKEY_DH) { + if (EVP_PKEY_base_id(pkey) != EVP_PKEY_DH) { ossl_raise(rb_eTypeError, "Not a DH key!"); } SetPKey(obj, pkey); @@ -248,11 +244,13 @@ ossl_dh_initialize(int argc, VALUE *argv, VALUE self) static VALUE ossl_dh_is_public(VALUE self) { - EVP_PKEY *pkey; + DH *dh; + BIGNUM *bn; - GetPKeyDH(self, pkey); + GetDH(self, dh); + DH_get0_key(dh, &bn, NULL); - return (pkey->pkey.dh->pub_key) ? Qtrue : Qfalse; + return bn ? Qtrue : Qfalse; } /* @@ -265,11 +263,17 @@ ossl_dh_is_public(VALUE self) static VALUE ossl_dh_is_private(VALUE self) { - EVP_PKEY *pkey; + DH *dh; + BIGNUM *bn; - GetPKeyDH(self, pkey); + GetDH(self, dh); + DH_get0_key(dh, NULL, &bn); - return (DH_PRIVATE(pkey->pkey.dh)) ? Qtrue : Qfalse; +#if !defined(OPENSSL_NO_ENGINE) + return (bn || DH_get0_engine(dh)) ? Qtrue : Qfalse; +#else + return bn ? Qtrue : Qfalse; +#endif } /* @@ -285,15 +289,15 @@ ossl_dh_is_private(VALUE self) static VALUE ossl_dh_export(VALUE self) { - EVP_PKEY *pkey; + DH *dh; BIO *out; VALUE str; - GetPKeyDH(self, pkey); + GetDH(self, dh); if (!(out = BIO_new(BIO_s_mem()))) { ossl_raise(eDHError, NULL); } - if (!PEM_write_bio_DHparams(out, pkey->pkey.dh)) { + if (!PEM_write_bio_DHparams(out, dh)) { BIO_free(out); ossl_raise(eDHError, NULL); } @@ -314,17 +318,17 @@ ossl_dh_export(VALUE self) static VALUE ossl_dh_to_der(VALUE self) { - EVP_PKEY *pkey; + DH *dh; unsigned char *p; long len; VALUE str; - GetPKeyDH(self, pkey); - if((len = i2d_DHparams(pkey->pkey.dh, NULL)) <= 0) + GetDH(self, dh); + if((len = i2d_DHparams(dh, NULL)) <= 0) ossl_raise(eDHError, NULL); str = rb_str_new(0, len); p = (unsigned char *)RSTRING_PTR(str); - if(i2d_DHparams(pkey->pkey.dh, &p) < 0) + if(i2d_DHparams(dh, &p) < 0) ossl_raise(eDHError, NULL); ossl_str_adjust(str, p); @@ -342,17 +346,20 @@ ossl_dh_to_der(VALUE self) static VALUE ossl_dh_get_params(VALUE self) { - EVP_PKEY *pkey; + DH *dh; VALUE hash; + BIGNUM *p, *q, *g, *pub_key, *priv_key; - GetPKeyDH(self, pkey); + GetDH(self, dh); + DH_get0_pqg(dh, &p, &q, &g); + DH_get0_key(dh, &pub_key, &priv_key); hash = rb_hash_new(); - - rb_hash_aset(hash, rb_str_new2("p"), ossl_bn_new(pkey->pkey.dh->p)); - rb_hash_aset(hash, rb_str_new2("g"), ossl_bn_new(pkey->pkey.dh->g)); - rb_hash_aset(hash, rb_str_new2("pub_key"), ossl_bn_new(pkey->pkey.dh->pub_key)); - rb_hash_aset(hash, rb_str_new2("priv_key"), ossl_bn_new(pkey->pkey.dh->priv_key)); + 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("g"), ossl_bn_new(g)); + rb_hash_aset(hash, rb_str_new2("pub_key"), ossl_bn_new(pub_key)); + rb_hash_aset(hash, rb_str_new2("priv_key"), ossl_bn_new(priv_key)); return hash; } @@ -368,15 +375,15 @@ ossl_dh_get_params(VALUE self) static VALUE ossl_dh_to_text(VALUE self) { - EVP_PKEY *pkey; + DH *dh; BIO *out; VALUE str; - GetPKeyDH(self, pkey); + GetDH(self, dh); if (!(out = BIO_new(BIO_s_mem()))) { ossl_raise(eDHError, NULL); } - if (!DHparams_print(out, pkey->pkey.dh)) { + if (!DHparams_print(out, dh)) { BIO_free(out); ossl_raise(eDHError, NULL); } @@ -409,12 +416,11 @@ ossl_dh_to_text(VALUE self) static VALUE ossl_dh_to_public_key(VALUE self) { - EVP_PKEY *pkey; - DH *dh; + DH *orig_dh, *dh; VALUE obj; - GetPKeyDH(self, pkey); - dh = DHparams_dup(pkey->pkey.dh); /* err check perfomed by dh_instance */ + GetDH(self, orig_dh); + dh = DHparams_dup(orig_dh); /* err check perfomed by dh_instance */ obj = dh_instance(CLASS_OF(self), dh); if (obj == Qfalse) { DH_free(dh); @@ -436,12 +442,9 @@ static VALUE ossl_dh_check_params(VALUE self) { DH *dh; - EVP_PKEY *pkey; int codes; - GetPKeyDH(self, pkey); - dh = pkey->pkey.dh; - + GetDH(self, dh); if (!DH_check(dh, &codes)) { return Qfalse; } @@ -469,11 +472,8 @@ static VALUE ossl_dh_generate_key(VALUE self) { DH *dh; - EVP_PKEY *pkey; - - GetPKeyDH(self, pkey); - dh = pkey->pkey.dh; + GetDH(self, dh); if (!DH_generate_key(dh)) ossl_raise(eDHError, "Failed to generate key"); return self; @@ -494,14 +494,13 @@ static VALUE ossl_dh_compute_key(VALUE self, VALUE pub) { DH *dh; - EVP_PKEY *pkey; - BIGNUM *pub_key; + BIGNUM *pub_key, *dh_p; VALUE str; int len; - GetPKeyDH(self, pkey); - dh = pkey->pkey.dh; - if (!dh->p) + GetDH(self, dh); + DH_get0_pqg(dh, &dh_p, NULL, NULL); + if (!dh_p) ossl_raise(eDHError, "incomplete DH"); pub_key = GetBNPtr(pub); len = DH_size(dh); @@ -514,10 +513,8 @@ ossl_dh_compute_key(VALUE self, VALUE pub) return str; } -OSSL_PKEY_BN(dh, p) -OSSL_PKEY_BN(dh, g) -OSSL_PKEY_BN(dh, pub_key) -OSSL_PKEY_BN(dh, priv_key) +OSSL_PKEY_BN_DEF3(dh, DH, pqg, p, q, g) +OSSL_PKEY_BN_DEF2(dh, DH, key, pub_key, priv_key) /* * INIT @@ -580,9 +577,13 @@ Init_ossl_dh(void) rb_define_method(cDH, "compute_key", ossl_dh_compute_key, 1); DEF_OSSL_PKEY_BN(cDH, dh, p); + DEF_OSSL_PKEY_BN(cDH, dh, q); DEF_OSSL_PKEY_BN(cDH, dh, g); DEF_OSSL_PKEY_BN(cDH, dh, pub_key); DEF_OSSL_PKEY_BN(cDH, dh, priv_key); + rb_define_method(cDH, "set_pqg", ossl_dh_set_pqg, 3); + rb_define_method(cDH, "set_key", ossl_dh_set_key, 2); + rb_define_method(cDH, "params", ossl_dh_get_params, 0); } diff --git a/ext/openssl/ossl_pkey_dsa.c b/ext/openssl/ossl_pkey_dsa.c index 704fad6d..a30eba85 100644 --- a/ext/openssl/ossl_pkey_dsa.c +++ b/ext/openssl/ossl_pkey_dsa.c @@ -7,19 +7,35 @@ * This program is licensed under the same licence as Ruby. * (See the file 'LICENCE'.) */ -#if !defined(OPENSSL_NO_DSA) - #include "ossl.h" +#if !defined(OPENSSL_NO_DSA) + #define GetPKeyDSA(obj, pkey) do { \ GetPKey((obj), (pkey)); \ - if (EVP_PKEY_type((pkey)->type) != EVP_PKEY_DSA) { /* PARANOIA? */ \ + if (EVP_PKEY_base_id(pkey) != EVP_PKEY_DSA) { /* PARANOIA? */ \ ossl_raise(rb_eRuntimeError, "THIS IS NOT A DSA!"); \ } \ } while (0) +#define GetDSA(obj, dsa) do { \ + EVP_PKEY *_pkey; \ + GetPKeyDSA((obj), _pkey); \ + (dsa) = EVP_PKEY_get0_DSA(_pkey); \ +} while (0) -#define DSA_HAS_PRIVATE(dsa) ((dsa)->priv_key) -#define DSA_PRIVATE(obj,dsa) (DSA_HAS_PRIVATE(dsa)||OSSL_PKEY_IS_PRIVATE(obj)) +static inline int +DSA_HAS_PRIVATE(DSA *dsa) +{ + BIGNUM *bn; + DSA_get0_key(dsa, NULL, &bn); + return !!bn; +} + +static inline int +DSA_PRIVATE(VALUE obj, DSA *dsa) +{ + return DSA_HAS_PRIVATE(dsa) || OSSL_PKEY_IS_PRIVATE(obj); +} /* * Classes @@ -61,7 +77,7 @@ ossl_dsa_new(EVP_PKEY *pkey) obj = dsa_instance(cDSA, DSA_new()); } else { obj = NewPKey(cDSA); - if (EVP_PKEY_type(pkey->type) != EVP_PKEY_DSA) { + if (EVP_PKEY_base_id(pkey) != EVP_PKEY_DSA) { ossl_raise(rb_eTypeError, "Not a DSA key!"); } SetPKey(obj, pkey); @@ -259,11 +275,13 @@ ossl_dsa_initialize(int argc, VALUE *argv, VALUE self) static VALUE ossl_dsa_is_public(VALUE self) { - EVP_PKEY *pkey; + DSA *dsa; + BIGNUM *bn; - GetPKeyDSA(self, pkey); + GetDSA(self, dsa); + DSA_get0_key(dsa, &bn, NULL); - return (pkey->pkey.dsa->pub_key) ? Qtrue : Qfalse; + return bn ? Qtrue : Qfalse; } /* @@ -276,11 +294,11 @@ ossl_dsa_is_public(VALUE self) static VALUE ossl_dsa_is_private(VALUE self) { - EVP_PKEY *pkey; + DSA *dsa; - GetPKeyDSA(self, pkey); + GetDSA(self, dsa); - return (DSA_PRIVATE(self, pkey->pkey.dsa)) ? Qtrue : Qfalse; + return DSA_PRIVATE(self, dsa) ? Qtrue : Qfalse; } /* @@ -303,12 +321,12 @@ ossl_dsa_is_private(VALUE self) static VALUE ossl_dsa_export(int argc, VALUE *argv, VALUE self) { - EVP_PKEY *pkey; + DSA *dsa; BIO *out; const EVP_CIPHER *ciph = NULL; VALUE cipher, pass, str; - GetPKeyDSA(self, pkey); + GetDSA(self, dsa); rb_scan_args(argc, argv, "02", &cipher, &pass); if (!NIL_P(cipher)) { ciph = GetCipherPtr(cipher); @@ -317,14 +335,14 @@ ossl_dsa_export(int argc, VALUE *argv, VALUE self) if (!(out = BIO_new(BIO_s_mem()))) { ossl_raise(eDSAError, NULL); } - if (DSA_HAS_PRIVATE(pkey->pkey.dsa)) { - if (!PEM_write_bio_DSAPrivateKey(out, pkey->pkey.dsa, ciph, - NULL, 0, ossl_pem_passwd_cb, (void *)pass)){ + if (DSA_HAS_PRIVATE(dsa)) { + if (!PEM_write_bio_DSAPrivateKey(out, dsa, ciph, NULL, 0, + ossl_pem_passwd_cb, (void *)pass)){ BIO_free(out); ossl_raise(eDSAError, NULL); } } else { - if (!PEM_write_bio_DSA_PUBKEY(out, pkey->pkey.dsa)) { + if (!PEM_write_bio_DSA_PUBKEY(out, dsa)) { BIO_free(out); ossl_raise(eDSAError, NULL); } @@ -344,28 +362,29 @@ ossl_dsa_export(int argc, VALUE *argv, VALUE self) static VALUE ossl_dsa_to_der(VALUE self) { - EVP_PKEY *pkey; + DSA *dsa; int (*i2d_func)_((DSA*, unsigned char**)); unsigned char *p; long len; VALUE str; - GetPKeyDSA(self, pkey); - if(DSA_HAS_PRIVATE(pkey->pkey.dsa)) + GetDSA(self, dsa); + if(DSA_HAS_PRIVATE(dsa)) i2d_func = (int(*)_((DSA*,unsigned char**)))i2d_DSAPrivateKey; else i2d_func = i2d_DSA_PUBKEY; - if((len = i2d_func(pkey->pkey.dsa, NULL)) <= 0) + if((len = i2d_func(dsa, NULL)) <= 0) ossl_raise(eDSAError, NULL); str = rb_str_new(0, len); p = (unsigned char *)RSTRING_PTR(str); - if(i2d_func(pkey->pkey.dsa, &p) < 0) + if(i2d_func(dsa, &p) < 0) ossl_raise(eDSAError, NULL); ossl_str_adjust(str, p); return str; } + /* * call-seq: * dsa.params -> hash @@ -377,18 +396,20 @@ ossl_dsa_to_der(VALUE self) static VALUE ossl_dsa_get_params(VALUE self) { - EVP_PKEY *pkey; + DSA *dsa; VALUE hash; + BIGNUM *p, *q, *g, *pub_key, *priv_key; - GetPKeyDSA(self, pkey); + GetDSA(self, dsa); + DSA_get0_pqg(dsa, &p, &q, &g); + DSA_get0_key(dsa, &pub_key, &priv_key); hash = rb_hash_new(); - - rb_hash_aset(hash, rb_str_new2("p"), ossl_bn_new(pkey->pkey.dsa->p)); - rb_hash_aset(hash, rb_str_new2("q"), ossl_bn_new(pkey->pkey.dsa->q)); - rb_hash_aset(hash, rb_str_new2("g"), ossl_bn_new(pkey->pkey.dsa->g)); - rb_hash_aset(hash, rb_str_new2("pub_key"), ossl_bn_new(pkey->pkey.dsa->pub_key)); - rb_hash_aset(hash, rb_str_new2("priv_key"), ossl_bn_new(pkey->pkey.dsa->priv_key)); + 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("g"), ossl_bn_new(g)); + rb_hash_aset(hash, rb_str_new2("pub_key"), ossl_bn_new(pub_key)); + rb_hash_aset(hash, rb_str_new2("priv_key"), ossl_bn_new(priv_key)); return hash; } @@ -404,15 +425,15 @@ ossl_dsa_get_params(VALUE self) static VALUE ossl_dsa_to_text(VALUE self) { - EVP_PKEY *pkey; + DSA *dsa; BIO *out; VALUE str; - GetPKeyDSA(self, pkey); + GetDSA(self, dsa); if (!(out = BIO_new(BIO_s_mem()))) { ossl_raise(eDSAError, NULL); } - if (!DSA_print(out, pkey->pkey.dsa, 0)) { /* offset = 0 */ + if (!DSA_print(out, dsa, 0)) { /* offset = 0 */ BIO_free(out); ossl_raise(eDSAError, NULL); } @@ -449,7 +470,7 @@ ossl_dsa_to_public_key(VALUE self) /* err check performed by dsa_instance */ #define DSAPublicKey_dup(dsa) (DSA *)ASN1_dup( \ (i2d_of_void *)i2d_DSAPublicKey, (d2i_of_void *)d2i_DSAPublicKey, (char *)(dsa)) - dsa = DSAPublicKey_dup(pkey->pkey.dsa); + dsa = DSAPublicKey_dup(EVP_PKEY_get0_DSA(pkey)); #undef DSAPublicKey_dup obj = dsa_instance(CLASS_OF(self), dsa); if (obj == Qfalse) { @@ -459,7 +480,7 @@ ossl_dsa_to_public_key(VALUE self) return obj; } -#define ossl_dsa_buf_size(pkey) (DSA_size((pkey)->pkey.dsa)+16) +#define ossl_dsa_buf_size(dsa) (DSA_size(dsa) + 16) /* * call-seq: @@ -483,20 +504,22 @@ ossl_dsa_to_public_key(VALUE self) static VALUE ossl_dsa_sign(VALUE self, VALUE data) { - EVP_PKEY *pkey; + DSA *dsa; + BIGNUM *dsa_q; unsigned int buf_len; VALUE str; - GetPKeyDSA(self, pkey); - if (!pkey->pkey.dsa->q) + GetDSA(self, dsa); + DSA_get0_pqg(dsa, NULL, &dsa_q, NULL); + if (!dsa_q) ossl_raise(eDSAError, "incomplete DSA"); - if (!DSA_PRIVATE(self, pkey->pkey.dsa)) + if (!DSA_PRIVATE(self, dsa)) ossl_raise(eDSAError, "Private DSA key needed!"); StringValue(data); - str = rb_str_new(0, ossl_dsa_buf_size(pkey)); + str = rb_str_new(0, ossl_dsa_buf_size(dsa)); if (!DSA_sign(0, (unsigned char *)RSTRING_PTR(data), RSTRING_LENINT(data), (unsigned char *)RSTRING_PTR(str), - &buf_len, pkey->pkey.dsa)) { /* type is ignored (0) */ + &buf_len, dsa)) { /* type is ignored (0) */ ossl_raise(eDSAError, NULL); } rb_str_set_len(str, buf_len); @@ -526,15 +549,15 @@ ossl_dsa_sign(VALUE self, VALUE data) static VALUE ossl_dsa_verify(VALUE self, VALUE digest, VALUE sig) { - EVP_PKEY *pkey; + DSA *dsa; int ret; - GetPKeyDSA(self, pkey); + GetDSA(self, dsa); StringValue(digest); StringValue(sig); /* type is ignored (0) */ ret = DSA_verify(0, (unsigned char *)RSTRING_PTR(digest), RSTRING_LENINT(digest), - (unsigned char *)RSTRING_PTR(sig), RSTRING_LENINT(sig), pkey->pkey.dsa); + (unsigned char *)RSTRING_PTR(sig), RSTRING_LENINT(sig), dsa); if (ret < 0) { ossl_raise(eDSAError, NULL); } @@ -545,11 +568,8 @@ ossl_dsa_verify(VALUE self, VALUE digest, VALUE sig) return Qfalse; } -OSSL_PKEY_BN(dsa, p) -OSSL_PKEY_BN(dsa, q) -OSSL_PKEY_BN(dsa, g) -OSSL_PKEY_BN(dsa, pub_key) -OSSL_PKEY_BN(dsa, priv_key) +OSSL_PKEY_BN_DEF3(dsa, DSA, pqg, p, q, g) +OSSL_PKEY_BN_DEF2(dsa, DSA, key, pub_key, priv_key) /* * INIT @@ -603,6 +623,8 @@ Init_ossl_dsa(void) DEF_OSSL_PKEY_BN(cDSA, dsa, g); DEF_OSSL_PKEY_BN(cDSA, dsa, pub_key); DEF_OSSL_PKEY_BN(cDSA, dsa, priv_key); + rb_define_method(cDSA, "set_pqg", ossl_dsa_set_pqg, 3); + rb_define_method(cDSA, "set_key", ossl_dsa_set_key, 2); rb_define_method(cDSA, "params", ossl_dsa_get_params, 0); } diff --git a/ext/openssl/ossl_pkey_ec.c b/ext/openssl/ossl_pkey_ec.c index 958e7105..30ded33c 100644 --- a/ext/openssl/ossl_pkey_ec.c +++ b/ext/openssl/ossl_pkey_ec.c @@ -25,7 +25,7 @@ static const rb_data_type_t ossl_ec_point_type; #define GetPKeyEC(obj, pkey) do { \ GetPKey((obj), (pkey)); \ - if (EVP_PKEY_type((pkey)->type) != EVP_PKEY_EC) { \ + if (EVP_PKEY_base_id(pkey) != EVP_PKEY_EC) { \ ossl_raise(rb_eRuntimeError, "THIS IS NOT A EC PKEY!"); \ } \ } while (0) @@ -38,7 +38,7 @@ static const rb_data_type_t ossl_ec_point_type; #define Get_EC_KEY(obj, key) do { \ EVP_PKEY *pkey; \ GetPKeyEC((obj), pkey); \ - (key) = pkey->pkey.ec; \ + (key) = EVP_PKEY_get0_EC_KEY(pkey); \ } while(0) #define Require_EC_KEY(obj, key) do { \ @@ -137,7 +137,7 @@ VALUE ossl_ec_new(EVP_PKEY *pkey) obj = ec_instance(cEC, EC_KEY_new()); } else { obj = NewPKey(cEC); - if (EVP_PKEY_type(pkey->type) != EVP_PKEY_EC) { + if (EVP_PKEY_base_id(pkey) != EVP_PKEY_EC) { ossl_raise(rb_eTypeError, "Not a EC key!"); } SetPKey(obj, pkey); @@ -232,7 +232,7 @@ static VALUE ossl_ec_key_initialize(int argc, VALUE *argv, VALUE self) VALUE arg, pass; GetPKey(self, pkey); - if (pkey->pkey.ec) + if (EVP_PKEY_base_id(pkey) != EVP_PKEY_NONE) ossl_raise(eECError, "EC_KEY already initialized"); rb_scan_args(argc, argv, "02", &arg, &pass); diff --git a/ext/openssl/ossl_pkey_rsa.c b/ext/openssl/ossl_pkey_rsa.c index ea2af251..5d9bcb96 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); diff --git a/ext/openssl/ossl_ssl.c b/ext/openssl/ossl_ssl.c index cfb64d2c..fd1ad746 100644 --- a/ext/openssl/ossl_ssl.c +++ b/ext/openssl/ossl_ssl.c @@ -258,7 +258,7 @@ ossl_call_tmp_dh_callback(VALUE args) if (NIL_P(cb)) return Qfalse; dh = rb_apply(cb, rb_intern("call"), args); pkey = GetPKeyPtr(dh); - if (EVP_PKEY_type(pkey->type) != EVP_PKEY_DH) return Qfalse; + if (EVP_PKEY_base_id(pkey) != EVP_PKEY_DH) return Qfalse; return dh; } @@ -276,7 +276,7 @@ ossl_tmp_dh_callback(SSL *ssl, int is_export, int keylength) if (!RTEST(dh)) return NULL; ossl_ssl_set_tmp_dh(rb_ssl, dh); - return GetPKeyPtr(dh)->pkey.dh; + return EVP_PKEY_get0_DH(GetPKeyPtr(dh)); } #endif /* OPENSSL_NO_DH */ @@ -292,7 +292,7 @@ ossl_call_tmp_ecdh_callback(VALUE args) if (NIL_P(cb)) return Qfalse; ecdh = rb_apply(cb, rb_intern("call"), args); pkey = GetPKeyPtr(ecdh); - if (EVP_PKEY_type(pkey->type) != EVP_PKEY_EC) return Qfalse; + if (EVP_PKEY_base_id(pkey) != EVP_PKEY_EC) return Qfalse; return ecdh; } @@ -310,7 +310,7 @@ ossl_tmp_ecdh_callback(SSL *ssl, int is_export, int keylength) if (!RTEST(ecdh)) return NULL; ossl_ssl_set_tmp_ecdh(rb_ssl, ecdh); - return GetPKeyPtr(ecdh)->pkey.ec; + return EVP_PKEY_get0_EC_KEY(GetPKeyPtr(ecdh)); } #endif diff --git a/test/utils.rb b/test/utils.rb index b6cf6377..605c956c 100644 --- a/test/utils.rb +++ b/test/utils.rb @@ -106,7 +106,8 @@ AQjjxMXhwULlmuR/K+WwlaZPiLIBYalLAZQ7ZbOPeVkJ8ePao0eLAgEC -----END DH PARAMETERS----- _end_of_pem_ - TEST_KEY_DH1024.priv_key = OpenSSL::BN.new("48561834C67E65FFD2A9B47F41E5E78FDC95C387428FDB1E4B0188B64D1643C3A8D3455B945B7E8C4D166010C7C2CE23BFB9BEF43D0348FE7FA5284B0225E7FE1537546D114E3D8A4411B9B9351AB451E1A358F50ED61B1F00DA29336EEBBD649980AC86D76AF8BBB065298C2052672EEF3EF13AB47A15275FC2836F3AC74CEA", 16) + TEST_KEY_DH1024.set_key(OpenSSL::BN.new("556AF1598AE69899867CEBA9F29CE4862B884C2B43C9019EA0231908F6EFA785E3C462A6ECB16DF676866E997FFB72B487DC7967C58C3CA38CE974473BF19B2AA5DCBF102735572EBA6F353F6F0BBE7FF1DE1B07FE1381A355C275C33405004317F9491B5955F191F6615A63B30E55A027FB88A1A4B25608E09EEE68A7DF32D", 16), + OpenSSL::BN.new("48561834C67E65FFD2A9B47F41E5E78FDC95C387428FDB1E4B0188B64D1643C3A8D3455B945B7E8C4D166010C7C2CE23BFB9BEF43D0348FE7FA5284B0225E7FE1537546D114E3D8A4411B9B9351AB451E1A358F50ED61B1F00DA29336EEBBD649980AC86D76AF8BBB065298C2052672EEF3EF13AB47A15275FC2836F3AC74CEA", 16)) DSA_SIGNATURE_DIGEST = OpenSSL::OPENSSL_VERSION_NUMBER > 0x10000000 ? OpenSSL::Digest::SHA1 : -- cgit v1.2.3