From 609103dbb5fb182eec12f052226c43e39b907682 Mon Sep 17 00:00:00 2001 From: rhe Date: Sun, 3 Sep 2017 12:35:27 +0000 Subject: openssl: import v2.1.0.beta1 Import Ruby/OpenSSL 2.1.0.beta1. The full commit log since v2.0.5 (imported by r59567) can be found at: https://github.com/ruby/openssl/compare/v2.0.5...v2.1.0.beta1 ---------------------------------------------------------------- Antonio Terceiro (1): test/test_ssl: explicitly accept TLS 1.1 in corresponding test Colby Swandale (1): document using secure protocol to fetch git master in Bundler Colton Jenkins (1): Add fips_mode_get to return fips_mode Kazuki Yamaguchi (85): Start preparing for 2.1.0 Remove support for OpenSSL 0.9.8 and 1.0.0 bn: refine tests bn: implement unary {plus,minus} operators for OpenSSL::BN bn: implement OpenSSL::BN#negative? Don't define main() when built with --enable-debug test: let OpenSSL::TestCase include OpenSSL::TestUtils test: prepare test PKey instances on demand Add OpenSSL.print_mem_leaks Enable OSSL_MDEBUG on CI builds ssl: move default DH parameters from OpenSSL::PKey::DH Make exceptions with the same format regardless of OpenSSL.debug ssl: show reason of 'certificate verify error' in exception message ssl: remove OpenSSL::ExtConfig::TLS_DH_anon_WITH_AES_256_GCM_SHA384 ssl: do not confuse different ex_data index registries ssl: assume SSL/SSL_CTX always have a valid reference to the Ruby object Fix RDoc markup ssl: suppress compiler warning ext/openssl/deprecation.rb: remove broken-apple-openssl extconf.rb: print informative message if OpenSSL can't be found Rakefile: compile the extension before test kdf: introduce OpenSSL::KDF module ossl.h: add NUM2UINT64T() macro kdf: add scrypt Expand rb_define_copy_func() macro Expand FPTR_TO_FD() macro Remove SafeGet*() macros cipher: rename GetCipherPtr() to ossl_evp_get_cipherbyname() digest: rename GetDigestPtr() to ossl_evp_get_digestbyname() Add ossl_str_new(), an exception-safe rb_str_new() bio: simplify ossl_membio2str() using ossl_str_new() Remove unused functions and macros Drop support for LibreSSL 2.3 ocsp: add OpenSSL::OCSP::Request#signed? asn1: infinite length -> indefinite length asn1: rearrange tests ssl: remove a needless NULL check in SSL::SSLContext#ciphers ssl: return nil in SSL::SSLSocket#cipher if session is not started asn1: remove an unnecessary function prototype asn1: require tag information when instantiating generic type asn1: initialize 'unused_bits' attribute of BitString with 0 asn1: check for illegal 'unused_bits' value of BitString asn1: disallow NULL to be passed to asn1time_to_time() asn1: avoid truncating OID in OpenSSL::ASN1::ObjectId#oid asn1: allow constructed encoding with definite length form asn1: prohibit indefinite length form for primitive encoding asn1: allow tag number to be >= 32 for universal tag class asn1: use ossl_asn1_tag() asn1: clean up OpenSSL::ASN1::Constructive#to_der asn1: harmonize OpenSSL::ASN1::*#to_der asn1: prevent EOC octets from being in the middle of the content asn1: do not treat EOC octets as part of content octets x509name: add 'loc' and 'set' kwargs to OpenSSL::X509::Name#add_entry ssl: do not call session_remove_cb during GC Backport "Merge branch 'topic/test-memory-leak'" to maint cipher: update the documentation for Cipher#auth_tag= Rakefile: let sync:to_ruby know about test/openssl/fixtures test: fix formatting test/utils: remove OpenSSL::TestUtils.silent test/utils: add SSLTestCase#tls12_supported? test/utils: have start_server yield only the port number test/utils: do not set ecdh_curves in start_server test/utils: let server_loop close socket test/utils: improve error handling in start_server test/utils: add OpenSSL::TestUtils.openssl? and .libressl? test/utils: do not use DSA certificates in SSL tests test/test_ssl: remove test_invalid_shutdown_by_gc test/test_ssl: move test_multibyte_read_write to test_pair test/test_ssl_session: rearrange tests test/test_pair, test/test_ssl: fix for TLS 1.3 ssl: remove useless call to rb_thread_wait_fd() ssl: fix NPN support ssl: mark OpenSSL::SSL::SSLContext::DEFAULT_{1024,2048} as private ssl: use 2048-bit group in the default tmp_dh_cb ssl: ensure that SSL option flags are non-negative ssl: update OpenSSL::SSL::OP_* flags ssl: prefer TLS_method() over SSLv23_method() ssl: add SSLContext#min_version= and #max_version= ssl: rework SSLContext#ssl_version= test/test_x509name: change script encoding to ASCII-8BIT x509name: refactor OpenSSL::X509::Name#to_s x509name: add OpenSSL::X509::Name#to_utf8 x509name: add OpenSSL::X509::Name#inspect x509name: update regexp in OpenSSL::X509::Name.parse Ruby/OpenSSL 2.1.0.beta1 Marcus Stollsteimer (1): Fix rdoc for core Integer class nobu (4): [DOC] {read,write}_nonblock with exception: false [DOC] keyword argument _exception_ [DOC] mark up literals Revert r57690 except for read_nonblock git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@59734 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ext/openssl/History.md | 31 ++ ext/openssl/depend | 134 +++---- ext/openssl/deprecation.rb | 3 - ext/openssl/extconf.rb | 48 +-- ext/openssl/lib/openssl.rb | 1 + ext/openssl/lib/openssl/bn.rb | 3 +- ext/openssl/lib/openssl/buffering.rb | 38 +- ext/openssl/lib/openssl/config.rb | 23 +- ext/openssl/lib/openssl/digest.rb | 9 +- ext/openssl/lib/openssl/pkcs5.rb | 22 ++ ext/openssl/lib/openssl/pkey.rb | 41 --- ext/openssl/lib/openssl/ssl.rb | 134 ++++++- ext/openssl/lib/openssl/x509.rb | 8 +- ext/openssl/openssl.gemspec | 12 +- ext/openssl/openssl_missing.c | 67 ---- ext/openssl/openssl_missing.h | 49 +-- ext/openssl/ossl.c | 195 ++++++++--- ext/openssl/ossl.h | 41 +-- ext/openssl/ossl_asn1.c | 660 +++++++++++++++-------------------- ext/openssl/ossl_asn1.h | 4 - ext/openssl/ossl_bio.c | 25 +- ext/openssl/ossl_bio.h | 2 - ext/openssl/ossl_bn.c | 96 +++-- ext/openssl/ossl_cipher.c | 68 ++-- ext/openssl/ossl_cipher.h | 2 +- ext/openssl/ossl_digest.c | 20 +- ext/openssl/ossl_digest.h | 2 +- ext/openssl/ossl_engine.c | 94 ++--- ext/openssl/ossl_hmac.c | 41 +-- ext/openssl/ossl_kdf.c | 221 ++++++++++++ ext/openssl/ossl_kdf.h | 6 + ext/openssl/ossl_ns_spki.c | 14 +- ext/openssl/ossl_ocsp.c | 165 ++++----- ext/openssl/ossl_pkcs12.c | 35 +- ext/openssl/ossl_pkcs5.c | 180 ---------- ext/openssl/ossl_pkcs5.h | 6 - ext/openssl/ossl_pkcs7.c | 28 +- ext/openssl/ossl_pkey.c | 34 +- ext/openssl/ossl_pkey.h | 4 - ext/openssl/ossl_pkey_dh.c | 22 +- ext/openssl/ossl_pkey_dsa.c | 38 +- ext/openssl/ossl_pkey_ec.c | 98 +++--- ext/openssl/ossl_pkey_rsa.c | 38 +- ext/openssl/ossl_rand.c | 24 +- ext/openssl/ossl_ssl.c | 506 +++++++++++++++------------ ext/openssl/ossl_ssl.h | 5 - ext/openssl/ossl_ssl_session.c | 16 +- ext/openssl/ossl_version.h | 2 +- ext/openssl/ossl_x509.c | 15 - ext/openssl/ossl_x509.h | 7 - ext/openssl/ossl_x509attr.c | 10 +- ext/openssl/ossl_x509cert.c | 56 +-- ext/openssl/ossl_x509crl.c | 35 +- ext/openssl/ossl_x509ext.c | 22 +- ext/openssl/ossl_x509name.c | 138 +++++--- ext/openssl/ossl_x509req.c | 45 +-- ext/openssl/ossl_x509revoked.c | 16 +- ext/openssl/ossl_x509store.c | 59 +--- ext/openssl/ruby_missing.h | 5 - 59 files changed, 1823 insertions(+), 1900 deletions(-) create mode 100644 ext/openssl/lib/openssl/pkcs5.rb create mode 100644 ext/openssl/ossl_kdf.c create mode 100644 ext/openssl/ossl_kdf.h delete mode 100644 ext/openssl/ossl_pkcs5.c delete mode 100644 ext/openssl/ossl_pkcs5.h (limited to 'ext') diff --git a/ext/openssl/History.md b/ext/openssl/History.md index 8baa0208ea..6e4baeb3be 100644 --- a/ext/openssl/History.md +++ b/ext/openssl/History.md @@ -1,3 +1,34 @@ +Version 2.1.0.beta1 +=================== + +Notable changes +--------------- + +* Support for OpenSSL versions before 1.0.1 is removed. + [[GitHub #86]](https://github.com/ruby/openssl/pull/86) +* OpenSSL::BN#negative?, #+@, and #-@ are added. +* OpenSSL::SSL::SSLSocket#connect raises a more informative exception when + certificate verification fails. + [[GitHub #99]](https://github.com/ruby/openssl/pull/99) +* OpenSSL::KDF module is newly added. Support for scrypt is added. + [[GitHub #109]](https://github.com/ruby/openssl/pull/109) +* OpenSSL.fips_mode is added. We have had the setter, but not the getter. + [[GitHub #125]](https://github.com/ruby/openssl/pull/125) +* OpenSSL::OCSP::Request#signed? is added. +* OpenSSL::ASN1 handles the indefinite length form better. OpenSSL::ASN1.decode + no longer wrongly treats the end-of-contents octets as part of the content. + OpenSSL::ASN1::ASN1Data#infinite_length is renamed to #indefinite_length. + [[GitHub #98]](https://github.com/ruby/openssl/pull/98) +* OpenSSL::X509::Name#add_entry now accepts two additional keyword arguments + 'loc' and 'set'. + [[GitHub #94]](https://github.com/ruby/openssl/issues/94) +* OpenSSL::SSL::SSLContext#min_version= and #max_version= are added. + [[GitHub #142]](https://github.com/ruby/openssl/pull/142) +* OpenSSL::X509::Name#to_utf8 is added. + [[GitHub #26]](https://github.com/ruby/openssl/issues/26) + [[GitHub #143]](https://github.com/ruby/openssl/pull/143) + + Version 2.0.5 ============= diff --git a/ext/openssl/depend b/ext/openssl/depend index 4e98617954..021c6d99a8 100644 --- a/ext/openssl/depend +++ b/ext/openssl/depend @@ -30,10 +30,10 @@ ossl.o: ossl_config.h ossl.o: ossl_digest.h ossl.o: ossl_engine.h ossl.o: ossl_hmac.h +ossl.o: ossl_kdf.h ossl.o: ossl_ns_spki.h ossl.o: ossl_ocsp.h ossl.o: ossl_pkcs12.h -ossl.o: ossl_pkcs5.h ossl.o: ossl_pkcs7.h ossl.o: ossl_pkey.h ossl.o: ossl_rand.h @@ -67,10 +67,10 @@ ossl_asn1.o: ossl_config.h ossl_asn1.o: ossl_digest.h ossl_asn1.o: ossl_engine.h ossl_asn1.o: ossl_hmac.h +ossl_asn1.o: ossl_kdf.h ossl_asn1.o: ossl_ns_spki.h ossl_asn1.o: ossl_ocsp.h ossl_asn1.o: ossl_pkcs12.h -ossl_asn1.o: ossl_pkcs5.h ossl_asn1.o: ossl_pkcs7.h ossl_asn1.o: ossl_pkey.h ossl_asn1.o: ossl_rand.h @@ -104,10 +104,10 @@ ossl_bio.o: ossl_config.h ossl_bio.o: ossl_digest.h ossl_bio.o: ossl_engine.h ossl_bio.o: ossl_hmac.h +ossl_bio.o: ossl_kdf.h ossl_bio.o: ossl_ns_spki.h ossl_bio.o: ossl_ocsp.h ossl_bio.o: ossl_pkcs12.h -ossl_bio.o: ossl_pkcs5.h ossl_bio.o: ossl_pkcs7.h ossl_bio.o: ossl_pkey.h ossl_bio.o: ossl_rand.h @@ -141,10 +141,10 @@ ossl_bn.o: ossl_config.h ossl_bn.o: ossl_digest.h ossl_bn.o: ossl_engine.h ossl_bn.o: ossl_hmac.h +ossl_bn.o: ossl_kdf.h ossl_bn.o: ossl_ns_spki.h ossl_bn.o: ossl_ocsp.h ossl_bn.o: ossl_pkcs12.h -ossl_bn.o: ossl_pkcs5.h ossl_bn.o: ossl_pkcs7.h ossl_bn.o: ossl_pkey.h ossl_bn.o: ossl_rand.h @@ -178,10 +178,10 @@ ossl_cipher.o: ossl_config.h ossl_cipher.o: ossl_digest.h ossl_cipher.o: ossl_engine.h ossl_cipher.o: ossl_hmac.h +ossl_cipher.o: ossl_kdf.h ossl_cipher.o: ossl_ns_spki.h ossl_cipher.o: ossl_ocsp.h ossl_cipher.o: ossl_pkcs12.h -ossl_cipher.o: ossl_pkcs5.h ossl_cipher.o: ossl_pkcs7.h ossl_cipher.o: ossl_pkey.h ossl_cipher.o: ossl_rand.h @@ -215,10 +215,10 @@ ossl_config.o: ossl_config.h ossl_config.o: ossl_digest.h ossl_config.o: ossl_engine.h ossl_config.o: ossl_hmac.h +ossl_config.o: ossl_kdf.h ossl_config.o: ossl_ns_spki.h ossl_config.o: ossl_ocsp.h ossl_config.o: ossl_pkcs12.h -ossl_config.o: ossl_pkcs5.h ossl_config.o: ossl_pkcs7.h ossl_config.o: ossl_pkey.h ossl_config.o: ossl_rand.h @@ -252,10 +252,10 @@ ossl_digest.o: ossl_digest.c ossl_digest.o: ossl_digest.h ossl_digest.o: ossl_engine.h ossl_digest.o: ossl_hmac.h +ossl_digest.o: ossl_kdf.h ossl_digest.o: ossl_ns_spki.h ossl_digest.o: ossl_ocsp.h ossl_digest.o: ossl_pkcs12.h -ossl_digest.o: ossl_pkcs5.h ossl_digest.o: ossl_pkcs7.h ossl_digest.o: ossl_pkey.h ossl_digest.o: ossl_rand.h @@ -289,10 +289,10 @@ ossl_engine.o: ossl_digest.h ossl_engine.o: ossl_engine.c ossl_engine.o: ossl_engine.h ossl_engine.o: ossl_hmac.h +ossl_engine.o: ossl_kdf.h ossl_engine.o: ossl_ns_spki.h ossl_engine.o: ossl_ocsp.h ossl_engine.o: ossl_pkcs12.h -ossl_engine.o: ossl_pkcs5.h ossl_engine.o: ossl_pkcs7.h ossl_engine.o: ossl_pkey.h ossl_engine.o: ossl_rand.h @@ -326,10 +326,10 @@ ossl_hmac.o: ossl_digest.h ossl_hmac.o: ossl_engine.h ossl_hmac.o: ossl_hmac.c ossl_hmac.o: ossl_hmac.h +ossl_hmac.o: ossl_kdf.h ossl_hmac.o: ossl_ns_spki.h ossl_hmac.o: ossl_ocsp.h ossl_hmac.o: ossl_pkcs12.h -ossl_hmac.o: ossl_pkcs5.h ossl_hmac.o: ossl_pkcs7.h ossl_hmac.o: ossl_pkey.h ossl_hmac.o: ossl_rand.h @@ -337,6 +337,43 @@ ossl_hmac.o: ossl_ssl.h ossl_hmac.o: ossl_version.h ossl_hmac.o: ossl_x509.h ossl_hmac.o: ruby_missing.h +ossl_kdf.o: $(RUBY_EXTCONF_H) +ossl_kdf.o: $(arch_hdrdir)/ruby/config.h +ossl_kdf.o: $(hdrdir)/ruby/backward.h +ossl_kdf.o: $(hdrdir)/ruby/defines.h +ossl_kdf.o: $(hdrdir)/ruby/encoding.h +ossl_kdf.o: $(hdrdir)/ruby/intern.h +ossl_kdf.o: $(hdrdir)/ruby/io.h +ossl_kdf.o: $(hdrdir)/ruby/missing.h +ossl_kdf.o: $(hdrdir)/ruby/onigmo.h +ossl_kdf.o: $(hdrdir)/ruby/oniguruma.h +ossl_kdf.o: $(hdrdir)/ruby/ruby.h +ossl_kdf.o: $(hdrdir)/ruby/st.h +ossl_kdf.o: $(hdrdir)/ruby/subst.h +ossl_kdf.o: $(hdrdir)/ruby/thread.h +ossl_kdf.o: $(top_srcdir)/include/ruby.h +ossl_kdf.o: openssl_missing.h +ossl_kdf.o: ossl.h +ossl_kdf.o: ossl_asn1.h +ossl_kdf.o: ossl_bio.h +ossl_kdf.o: ossl_bn.h +ossl_kdf.o: ossl_cipher.h +ossl_kdf.o: ossl_config.h +ossl_kdf.o: ossl_digest.h +ossl_kdf.o: ossl_engine.h +ossl_kdf.o: ossl_hmac.h +ossl_kdf.o: ossl_kdf.c +ossl_kdf.o: ossl_kdf.h +ossl_kdf.o: ossl_ns_spki.h +ossl_kdf.o: ossl_ocsp.h +ossl_kdf.o: ossl_pkcs12.h +ossl_kdf.o: ossl_pkcs7.h +ossl_kdf.o: ossl_pkey.h +ossl_kdf.o: ossl_rand.h +ossl_kdf.o: ossl_ssl.h +ossl_kdf.o: ossl_version.h +ossl_kdf.o: ossl_x509.h +ossl_kdf.o: ruby_missing.h ossl_ns_spki.o: $(RUBY_EXTCONF_H) ossl_ns_spki.o: $(arch_hdrdir)/ruby/config.h ossl_ns_spki.o: $(hdrdir)/ruby/backward.h @@ -362,11 +399,11 @@ ossl_ns_spki.o: ossl_config.h ossl_ns_spki.o: ossl_digest.h ossl_ns_spki.o: ossl_engine.h ossl_ns_spki.o: ossl_hmac.h +ossl_ns_spki.o: ossl_kdf.h ossl_ns_spki.o: ossl_ns_spki.c ossl_ns_spki.o: ossl_ns_spki.h ossl_ns_spki.o: ossl_ocsp.h ossl_ns_spki.o: ossl_pkcs12.h -ossl_ns_spki.o: ossl_pkcs5.h ossl_ns_spki.o: ossl_pkcs7.h ossl_ns_spki.o: ossl_pkey.h ossl_ns_spki.o: ossl_rand.h @@ -399,11 +436,11 @@ ossl_ocsp.o: ossl_config.h ossl_ocsp.o: ossl_digest.h ossl_ocsp.o: ossl_engine.h ossl_ocsp.o: ossl_hmac.h +ossl_ocsp.o: ossl_kdf.h ossl_ocsp.o: ossl_ns_spki.h ossl_ocsp.o: ossl_ocsp.c ossl_ocsp.o: ossl_ocsp.h ossl_ocsp.o: ossl_pkcs12.h -ossl_ocsp.o: ossl_pkcs5.h ossl_ocsp.o: ossl_pkcs7.h ossl_ocsp.o: ossl_pkey.h ossl_ocsp.o: ossl_rand.h @@ -436,11 +473,11 @@ ossl_pkcs12.o: ossl_config.h ossl_pkcs12.o: ossl_digest.h ossl_pkcs12.o: ossl_engine.h ossl_pkcs12.o: ossl_hmac.h +ossl_pkcs12.o: ossl_kdf.h ossl_pkcs12.o: ossl_ns_spki.h ossl_pkcs12.o: ossl_ocsp.h ossl_pkcs12.o: ossl_pkcs12.c ossl_pkcs12.o: ossl_pkcs12.h -ossl_pkcs12.o: ossl_pkcs5.h ossl_pkcs12.o: ossl_pkcs7.h ossl_pkcs12.o: ossl_pkey.h ossl_pkcs12.o: ossl_rand.h @@ -448,43 +485,6 @@ ossl_pkcs12.o: ossl_ssl.h ossl_pkcs12.o: ossl_version.h ossl_pkcs12.o: ossl_x509.h ossl_pkcs12.o: ruby_missing.h -ossl_pkcs5.o: $(RUBY_EXTCONF_H) -ossl_pkcs5.o: $(arch_hdrdir)/ruby/config.h -ossl_pkcs5.o: $(hdrdir)/ruby/backward.h -ossl_pkcs5.o: $(hdrdir)/ruby/defines.h -ossl_pkcs5.o: $(hdrdir)/ruby/encoding.h -ossl_pkcs5.o: $(hdrdir)/ruby/intern.h -ossl_pkcs5.o: $(hdrdir)/ruby/io.h -ossl_pkcs5.o: $(hdrdir)/ruby/missing.h -ossl_pkcs5.o: $(hdrdir)/ruby/onigmo.h -ossl_pkcs5.o: $(hdrdir)/ruby/oniguruma.h -ossl_pkcs5.o: $(hdrdir)/ruby/ruby.h -ossl_pkcs5.o: $(hdrdir)/ruby/st.h -ossl_pkcs5.o: $(hdrdir)/ruby/subst.h -ossl_pkcs5.o: $(hdrdir)/ruby/thread.h -ossl_pkcs5.o: $(top_srcdir)/include/ruby.h -ossl_pkcs5.o: openssl_missing.h -ossl_pkcs5.o: ossl.h -ossl_pkcs5.o: ossl_asn1.h -ossl_pkcs5.o: ossl_bio.h -ossl_pkcs5.o: ossl_bn.h -ossl_pkcs5.o: ossl_cipher.h -ossl_pkcs5.o: ossl_config.h -ossl_pkcs5.o: ossl_digest.h -ossl_pkcs5.o: ossl_engine.h -ossl_pkcs5.o: ossl_hmac.h -ossl_pkcs5.o: ossl_ns_spki.h -ossl_pkcs5.o: ossl_ocsp.h -ossl_pkcs5.o: ossl_pkcs12.h -ossl_pkcs5.o: ossl_pkcs5.c -ossl_pkcs5.o: ossl_pkcs5.h -ossl_pkcs5.o: ossl_pkcs7.h -ossl_pkcs5.o: ossl_pkey.h -ossl_pkcs5.o: ossl_rand.h -ossl_pkcs5.o: ossl_ssl.h -ossl_pkcs5.o: ossl_version.h -ossl_pkcs5.o: ossl_x509.h -ossl_pkcs5.o: ruby_missing.h ossl_pkcs7.o: $(RUBY_EXTCONF_H) ossl_pkcs7.o: $(arch_hdrdir)/ruby/config.h ossl_pkcs7.o: $(hdrdir)/ruby/backward.h @@ -510,10 +510,10 @@ ossl_pkcs7.o: ossl_config.h ossl_pkcs7.o: ossl_digest.h ossl_pkcs7.o: ossl_engine.h ossl_pkcs7.o: ossl_hmac.h +ossl_pkcs7.o: ossl_kdf.h ossl_pkcs7.o: ossl_ns_spki.h ossl_pkcs7.o: ossl_ocsp.h ossl_pkcs7.o: ossl_pkcs12.h -ossl_pkcs7.o: ossl_pkcs5.h ossl_pkcs7.o: ossl_pkcs7.c ossl_pkcs7.o: ossl_pkcs7.h ossl_pkcs7.o: ossl_pkey.h @@ -547,10 +547,10 @@ ossl_pkey.o: ossl_config.h ossl_pkey.o: ossl_digest.h ossl_pkey.o: ossl_engine.h ossl_pkey.o: ossl_hmac.h +ossl_pkey.o: ossl_kdf.h ossl_pkey.o: ossl_ns_spki.h ossl_pkey.o: ossl_ocsp.h ossl_pkey.o: ossl_pkcs12.h -ossl_pkey.o: ossl_pkcs5.h ossl_pkey.o: ossl_pkcs7.h ossl_pkey.o: ossl_pkey.c ossl_pkey.o: ossl_pkey.h @@ -584,10 +584,10 @@ ossl_pkey_dh.o: ossl_config.h ossl_pkey_dh.o: ossl_digest.h ossl_pkey_dh.o: ossl_engine.h ossl_pkey_dh.o: ossl_hmac.h +ossl_pkey_dh.o: ossl_kdf.h ossl_pkey_dh.o: ossl_ns_spki.h ossl_pkey_dh.o: ossl_ocsp.h ossl_pkey_dh.o: ossl_pkcs12.h -ossl_pkey_dh.o: ossl_pkcs5.h ossl_pkey_dh.o: ossl_pkcs7.h ossl_pkey_dh.o: ossl_pkey.h ossl_pkey_dh.o: ossl_pkey_dh.c @@ -621,10 +621,10 @@ ossl_pkey_dsa.o: ossl_config.h ossl_pkey_dsa.o: ossl_digest.h ossl_pkey_dsa.o: ossl_engine.h ossl_pkey_dsa.o: ossl_hmac.h +ossl_pkey_dsa.o: ossl_kdf.h ossl_pkey_dsa.o: ossl_ns_spki.h ossl_pkey_dsa.o: ossl_ocsp.h ossl_pkey_dsa.o: ossl_pkcs12.h -ossl_pkey_dsa.o: ossl_pkcs5.h ossl_pkey_dsa.o: ossl_pkcs7.h ossl_pkey_dsa.o: ossl_pkey.h ossl_pkey_dsa.o: ossl_pkey_dsa.c @@ -658,10 +658,10 @@ ossl_pkey_ec.o: ossl_config.h ossl_pkey_ec.o: ossl_digest.h ossl_pkey_ec.o: ossl_engine.h ossl_pkey_ec.o: ossl_hmac.h +ossl_pkey_ec.o: ossl_kdf.h ossl_pkey_ec.o: ossl_ns_spki.h ossl_pkey_ec.o: ossl_ocsp.h ossl_pkey_ec.o: ossl_pkcs12.h -ossl_pkey_ec.o: ossl_pkcs5.h ossl_pkey_ec.o: ossl_pkcs7.h ossl_pkey_ec.o: ossl_pkey.h ossl_pkey_ec.o: ossl_pkey_ec.c @@ -695,10 +695,10 @@ ossl_pkey_rsa.o: ossl_config.h ossl_pkey_rsa.o: ossl_digest.h ossl_pkey_rsa.o: ossl_engine.h ossl_pkey_rsa.o: ossl_hmac.h +ossl_pkey_rsa.o: ossl_kdf.h ossl_pkey_rsa.o: ossl_ns_spki.h ossl_pkey_rsa.o: ossl_ocsp.h ossl_pkey_rsa.o: ossl_pkcs12.h -ossl_pkey_rsa.o: ossl_pkcs5.h ossl_pkey_rsa.o: ossl_pkcs7.h ossl_pkey_rsa.o: ossl_pkey.h ossl_pkey_rsa.o: ossl_pkey_rsa.c @@ -732,10 +732,10 @@ ossl_rand.o: ossl_config.h ossl_rand.o: ossl_digest.h ossl_rand.o: ossl_engine.h ossl_rand.o: ossl_hmac.h +ossl_rand.o: ossl_kdf.h ossl_rand.o: ossl_ns_spki.h ossl_rand.o: ossl_ocsp.h ossl_rand.o: ossl_pkcs12.h -ossl_rand.o: ossl_pkcs5.h ossl_rand.o: ossl_pkcs7.h ossl_rand.o: ossl_pkey.h ossl_rand.o: ossl_rand.c @@ -769,10 +769,10 @@ ossl_ssl.o: ossl_config.h ossl_ssl.o: ossl_digest.h ossl_ssl.o: ossl_engine.h ossl_ssl.o: ossl_hmac.h +ossl_ssl.o: ossl_kdf.h ossl_ssl.o: ossl_ns_spki.h ossl_ssl.o: ossl_ocsp.h ossl_ssl.o: ossl_pkcs12.h -ossl_ssl.o: ossl_pkcs5.h ossl_ssl.o: ossl_pkcs7.h ossl_ssl.o: ossl_pkey.h ossl_ssl.o: ossl_rand.h @@ -806,10 +806,10 @@ ossl_ssl_session.o: ossl_config.h ossl_ssl_session.o: ossl_digest.h ossl_ssl_session.o: ossl_engine.h ossl_ssl_session.o: ossl_hmac.h +ossl_ssl_session.o: ossl_kdf.h ossl_ssl_session.o: ossl_ns_spki.h ossl_ssl_session.o: ossl_ocsp.h ossl_ssl_session.o: ossl_pkcs12.h -ossl_ssl_session.o: ossl_pkcs5.h ossl_ssl_session.o: ossl_pkcs7.h ossl_ssl_session.o: ossl_pkey.h ossl_ssl_session.o: ossl_rand.h @@ -843,10 +843,10 @@ ossl_x509.o: ossl_config.h ossl_x509.o: ossl_digest.h ossl_x509.o: ossl_engine.h ossl_x509.o: ossl_hmac.h +ossl_x509.o: ossl_kdf.h ossl_x509.o: ossl_ns_spki.h ossl_x509.o: ossl_ocsp.h ossl_x509.o: ossl_pkcs12.h -ossl_x509.o: ossl_pkcs5.h ossl_x509.o: ossl_pkcs7.h ossl_x509.o: ossl_pkey.h ossl_x509.o: ossl_rand.h @@ -880,10 +880,10 @@ ossl_x509attr.o: ossl_config.h ossl_x509attr.o: ossl_digest.h ossl_x509attr.o: ossl_engine.h ossl_x509attr.o: ossl_hmac.h +ossl_x509attr.o: ossl_kdf.h ossl_x509attr.o: ossl_ns_spki.h ossl_x509attr.o: ossl_ocsp.h ossl_x509attr.o: ossl_pkcs12.h -ossl_x509attr.o: ossl_pkcs5.h ossl_x509attr.o: ossl_pkcs7.h ossl_x509attr.o: ossl_pkey.h ossl_x509attr.o: ossl_rand.h @@ -917,10 +917,10 @@ ossl_x509cert.o: ossl_config.h ossl_x509cert.o: ossl_digest.h ossl_x509cert.o: ossl_engine.h ossl_x509cert.o: ossl_hmac.h +ossl_x509cert.o: ossl_kdf.h ossl_x509cert.o: ossl_ns_spki.h ossl_x509cert.o: ossl_ocsp.h ossl_x509cert.o: ossl_pkcs12.h -ossl_x509cert.o: ossl_pkcs5.h ossl_x509cert.o: ossl_pkcs7.h ossl_x509cert.o: ossl_pkey.h ossl_x509cert.o: ossl_rand.h @@ -954,10 +954,10 @@ ossl_x509crl.o: ossl_config.h ossl_x509crl.o: ossl_digest.h ossl_x509crl.o: ossl_engine.h ossl_x509crl.o: ossl_hmac.h +ossl_x509crl.o: ossl_kdf.h ossl_x509crl.o: ossl_ns_spki.h ossl_x509crl.o: ossl_ocsp.h ossl_x509crl.o: ossl_pkcs12.h -ossl_x509crl.o: ossl_pkcs5.h ossl_x509crl.o: ossl_pkcs7.h ossl_x509crl.o: ossl_pkey.h ossl_x509crl.o: ossl_rand.h @@ -991,10 +991,10 @@ ossl_x509ext.o: ossl_config.h ossl_x509ext.o: ossl_digest.h ossl_x509ext.o: ossl_engine.h ossl_x509ext.o: ossl_hmac.h +ossl_x509ext.o: ossl_kdf.h ossl_x509ext.o: ossl_ns_spki.h ossl_x509ext.o: ossl_ocsp.h ossl_x509ext.o: ossl_pkcs12.h -ossl_x509ext.o: ossl_pkcs5.h ossl_x509ext.o: ossl_pkcs7.h ossl_x509ext.o: ossl_pkey.h ossl_x509ext.o: ossl_rand.h @@ -1028,10 +1028,10 @@ ossl_x509name.o: ossl_config.h ossl_x509name.o: ossl_digest.h ossl_x509name.o: ossl_engine.h ossl_x509name.o: ossl_hmac.h +ossl_x509name.o: ossl_kdf.h ossl_x509name.o: ossl_ns_spki.h ossl_x509name.o: ossl_ocsp.h ossl_x509name.o: ossl_pkcs12.h -ossl_x509name.o: ossl_pkcs5.h ossl_x509name.o: ossl_pkcs7.h ossl_x509name.o: ossl_pkey.h ossl_x509name.o: ossl_rand.h @@ -1065,10 +1065,10 @@ ossl_x509req.o: ossl_config.h ossl_x509req.o: ossl_digest.h ossl_x509req.o: ossl_engine.h ossl_x509req.o: ossl_hmac.h +ossl_x509req.o: ossl_kdf.h ossl_x509req.o: ossl_ns_spki.h ossl_x509req.o: ossl_ocsp.h ossl_x509req.o: ossl_pkcs12.h -ossl_x509req.o: ossl_pkcs5.h ossl_x509req.o: ossl_pkcs7.h ossl_x509req.o: ossl_pkey.h ossl_x509req.o: ossl_rand.h @@ -1102,10 +1102,10 @@ ossl_x509revoked.o: ossl_config.h ossl_x509revoked.o: ossl_digest.h ossl_x509revoked.o: ossl_engine.h ossl_x509revoked.o: ossl_hmac.h +ossl_x509revoked.o: ossl_kdf.h ossl_x509revoked.o: ossl_ns_spki.h ossl_x509revoked.o: ossl_ocsp.h ossl_x509revoked.o: ossl_pkcs12.h -ossl_x509revoked.o: ossl_pkcs5.h ossl_x509revoked.o: ossl_pkcs7.h ossl_x509revoked.o: ossl_pkey.h ossl_x509revoked.o: ossl_rand.h @@ -1139,10 +1139,10 @@ ossl_x509store.o: ossl_config.h ossl_x509store.o: ossl_digest.h ossl_x509store.o: ossl_engine.h ossl_x509store.o: ossl_hmac.h +ossl_x509store.o: ossl_kdf.h ossl_x509store.o: ossl_ns_spki.h ossl_x509store.o: ossl_ocsp.h ossl_x509store.o: ossl_pkcs12.h -ossl_x509store.o: ossl_pkcs5.h ossl_x509store.o: ossl_pkcs7.h ossl_x509store.o: ossl_pkey.h ossl_x509store.o: ossl_rand.h diff --git a/ext/openssl/deprecation.rb b/ext/openssl/deprecation.rb index 0c3ab6287e..1d51d065a9 100644 --- a/ext/openssl/deprecation.rb +++ b/ext/openssl/deprecation.rb @@ -3,9 +3,6 @@ module OpenSSL def self.deprecated_warning_flag unless flag = (@deprecated_warning_flag ||= nil) if try_compile("", flag = "-Werror=deprecated-declarations") - if /darwin/ =~ RUBY_PLATFORM and with_config("broken-apple-openssl") - flag = "-Wno-deprecated-declarations" - end $warnflags << " #{flag}" else flag = "" diff --git a/ext/openssl/extconf.rb b/ext/openssl/extconf.rb index 75da65cde3..5212903b9a 100644 --- a/ext/openssl/extconf.rb +++ b/ext/openssl/extconf.rb @@ -91,30 +91,19 @@ unless result unless find_openssl_library Logging::message "=== Checking for required stuff failed. ===\n" Logging::message "Makefile wasn't created. Fix the errors above.\n" - exit 1 + raise "OpenSSL library could not be found. You might want to use " \ + "--with-openssl-dir= option to specify the prefix where OpenSSL " \ + "is installed." end end -result = checking_for("OpenSSL version is 0.9.8 or later") { - try_static_assert("OPENSSL_VERSION_NUMBER >= 0x00908000L", "openssl/opensslv.h") -} -unless result - raise "OpenSSL 0.9.8 or later required." -end - -if /darwin/ =~ RUBY_PLATFORM and !OpenSSL.check_func("SSL_library_init()", "openssl/ssl.h") - raise "Ignore OpenSSL broken by Apple.\nPlease use another openssl. (e.g. using `configure --with-openssl-dir=/path/to/openssl')" +unless checking_for("OpenSSL version is 1.0.1 or later") { + try_static_assert("OPENSSL_VERSION_NUMBER >= 0x10001000L", "openssl/opensslv.h") } + raise "OpenSSL >= 1.0.1 or LibreSSL is required" end Logging::message "=== Checking for OpenSSL features... ===\n" # compile options - -# SSLv2 and SSLv3 may be removed in future versions of OpenSSL, and even macros -# like OPENSSL_NO_SSL2 may not be defined. -have_func("SSLv2_method") -have_func("SSLv3_method") -have_func("TLSv1_1_method") -have_func("TLSv1_2_method") have_func("RAND_egd") engines = %w{builtin_engines openbsd_dev_crypto dynamic 4758cca aep atalla chil cswift nuron sureware ubsec padlock capi gmp gost cryptodev aesni} @@ -122,30 +111,6 @@ engines.each { |name| OpenSSL.check_func_or_macro("ENGINE_load_#{name}", "openssl/engine.h") } -# added in 0.9.8X -have_func("EVP_CIPHER_CTX_new") -have_func("EVP_CIPHER_CTX_free") -OpenSSL.check_func_or_macro("SSL_CTX_clear_options", "openssl/ssl.h") - -# 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") -have_func("X509_STORE_CTX_get0_current_crl") -have_func("X509_STORE_set_verify_cb") -have_func("i2d_ASN1_SET_ANY") -have_func("SSL_SESSION_cmp") # removed -OpenSSL.check_func_or_macro("SSL_set_tlsext_host_name", "openssl/ssl.h") -have_struct_member("CRYPTO_THREADID", "ptr", "openssl/crypto.h") -have_func("EVP_PKEY_get0") - -# added in 1.0.1 -have_func("SSL_CTX_set_next_proto_select_cb") -have_macro("EVP_CTRL_GCM_GET_TAG", ['openssl/evp.h']) && $defs.push("-DHAVE_AUTHENTICATED_ENCRYPTION") - # added in 1.0.2 have_func("EC_curve_nist2nid") have_func("X509_REVOKED_dup") @@ -189,6 +154,7 @@ OpenSSL.check_func_or_macro("SSL_CTX_set_min_proto_version", "openssl/ssl.h") have_func("SSL_CTX_get_security_level") have_func("X509_get0_notBefore") have_func("SSL_SESSION_get_protocol_version") +have_func("EVP_PBE_scrypt") Logging::message "=== Checking done. ===\n" diff --git a/ext/openssl/lib/openssl.rb b/ext/openssl/lib/openssl.rb index 26d167a9b4..0914282920 100644 --- a/ext/openssl/lib/openssl.rb +++ b/ext/openssl/lib/openssl.rb @@ -19,3 +19,4 @@ require 'openssl/config' require 'openssl/digest' require 'openssl/x509' require 'openssl/ssl' +require 'openssl/pkcs5' diff --git a/ext/openssl/lib/openssl/bn.rb b/ext/openssl/lib/openssl/bn.rb index 6d6c96e42d..8d1ebefb6e 100644 --- a/ext/openssl/lib/openssl/bn.rb +++ b/ext/openssl/lib/openssl/bn.rb @@ -27,8 +27,9 @@ module OpenSSL end # OpenSSL ## +#-- # Add double dispatch to Integer -# +#++ class Integer # Casts an Integer as an OpenSSL::BN # diff --git a/ext/openssl/lib/openssl/buffering.rb b/ext/openssl/lib/openssl/buffering.rb index d773637c0e..8b5dd9da57 100644 --- a/ext/openssl/lib/openssl/buffering.rb +++ b/ext/openssl/lib/openssl/buffering.rb @@ -63,7 +63,7 @@ module OpenSSL::Buffering end ## - # Consumes +size+ bytes from the buffer + # Consumes _size_ bytes from the buffer def consume_rbuff(size=nil) if @rbuffer.empty? @@ -79,7 +79,7 @@ module OpenSSL::Buffering public ## - # Reads +size+ bytes from the stream. If +buf+ is provided it must + # Reads _size_ bytes from the stream. If _buf_ is provided it must # reference a string which will receive the data. # # See IO#read for full details. @@ -106,7 +106,7 @@ module OpenSSL::Buffering end ## - # Reads at most +maxlen+ bytes from the stream. If +buf+ is provided it + # Reads at most _maxlen_ bytes from the stream. If _buf_ is provided it # must reference a string which will receive the data. # # See IO#readpartial for full details. @@ -136,7 +136,7 @@ module OpenSSL::Buffering end ## - # Reads at most +maxlen+ bytes in the non-blocking manner. + # Reads at most _maxlen_ bytes in the non-blocking manner. # # When no data can be read without blocking it raises # OpenSSL::SSL::SSLError extended by IO::WaitReadable or IO::WaitWritable. @@ -190,11 +190,11 @@ module OpenSSL::Buffering end ## - # Reads the next "line" from the stream. Lines are separated by +eol+. If - # +limit+ is provided the result will not be longer than the given number of + # Reads the next "line" from the stream. Lines are separated by _eol_. If + # _limit_ is provided the result will not be longer than the given number of # bytes. # - # +eol+ may be a String or Regexp. + # _eol_ may be a String or Regexp. # # Unlike IO#gets the line read will not be assigned to +$_+. # @@ -220,7 +220,7 @@ module OpenSSL::Buffering ## # Executes the block for every line in the stream where lines are separated - # by +eol+. + # by _eol_. # # See also #gets @@ -232,7 +232,7 @@ module OpenSSL::Buffering alias each_line each ## - # Reads lines from the stream which are separated by +eol+. + # Reads lines from the stream which are separated by _eol_. # # See also #gets @@ -245,7 +245,7 @@ module OpenSSL::Buffering end ## - # Reads a line from the stream which is separated by +eol+. + # Reads a line from the stream which is separated by _eol_. # # Raises EOFError if at end of file. @@ -281,7 +281,7 @@ module OpenSSL::Buffering end ## - # Pushes character +c+ back onto the stream such that a subsequent buffered + # Pushes character _c_ back onto the stream such that a subsequent buffered # character read will return it. # # Unlike IO#getc multiple bytes may be pushed back onto the stream. @@ -308,7 +308,7 @@ module OpenSSL::Buffering private ## - # Writes +s+ to the buffer. When the buffer is full or #sync is true the + # Writes _s_ to the buffer. When the buffer is full or #sync is true the # buffer is flushed to the underlying socket. def do_write(s) @@ -336,8 +336,8 @@ module OpenSSL::Buffering public ## - # Writes +s+ to the stream. If the argument is not a string it will be - # converted using String#to_s. Returns the number of bytes written. + # Writes _s_ to the stream. If the argument is not a String it will be + # converted using +.to_s+ method. Returns the number of bytes written. def write(s) do_write(s) @@ -345,7 +345,7 @@ module OpenSSL::Buffering end ## - # Writes +s+ in the non-blocking manner. + # Writes _s_ in the non-blocking manner. # # If there is buffered data, it is flushed first. This may block. # @@ -387,8 +387,8 @@ module OpenSSL::Buffering end ## - # Writes +s+ to the stream. +s+ will be converted to a String using - # String#to_s. + # Writes _s_ to the stream. _s_ will be converted to a String using + # +.to_s+ method. def <<(s) do_write(s) @@ -396,7 +396,7 @@ module OpenSSL::Buffering end ## - # Writes +args+ to the stream along with a record separator. + # Writes _args_ to the stream along with a record separator. # # See IO#puts for full details. @@ -416,7 +416,7 @@ module OpenSSL::Buffering end ## - # Writes +args+ to the stream. + # Writes _args_ to the stream. # # See IO#print for full details. diff --git a/ext/openssl/lib/openssl/config.rb b/ext/openssl/lib/openssl/config.rb index 8822545192..48d8be0069 100644 --- a/ext/openssl/lib/openssl/config.rb +++ b/ext/openssl/lib/openssl/config.rb @@ -30,7 +30,8 @@ module OpenSSL class << self ## - # Parses a given +string+ as a blob that contains configuration for openssl. + # Parses a given _string_ as a blob that contains configuration for + # OpenSSL. # # If the source of the IO is a file, then consider using #parse_config. def parse(string) @@ -46,7 +47,7 @@ module OpenSSL alias load new ## - # Parses the configuration data read from +io+, see also #parse. + # Parses the configuration data read from _io_, see also #parse. # # Raises a ConfigError on invalid configuration data. def parse_config(io) @@ -236,7 +237,7 @@ module OpenSSL # # This can be used in contexts like OpenSSL::X509::ExtensionFactory.config= # - # If the optional +filename+ parameter is provided, then it is read in and + # If the optional _filename_ parameter is provided, then it is read in and # parsed via #parse_config. # # This can raise IO exceptions based on the access, or availability of the @@ -255,7 +256,7 @@ module OpenSSL end ## - # Gets the value of +key+ from the given +section+ + # Gets the value of _key_ from the given _section_ # # Given the following configurating file being loaded: # @@ -265,8 +266,8 @@ module OpenSSL # #=> [ default ] # # foo=bar # - # You can get a specific value from the config if you know the +section+ - # and +key+ like so: + # You can get a specific value from the config if you know the _section_ + # and _key_ like so: # # config.get_value('default','foo') # #=> "bar" @@ -297,7 +298,7 @@ module OpenSSL end ## - # Set the target +key+ with a given +value+ under a specific +section+. + # Set the target _key_ with a given _value_ under a specific _section_. # # Given the following configurating file being loaded: # @@ -307,7 +308,7 @@ module OpenSSL # #=> [ default ] # # foo=bar # - # You can set the value of +foo+ under the +default+ section to a new + # You can set the value of _foo_ under the _default_ section to a new # value: # # config.add_value('default', 'foo', 'buzz') @@ -322,7 +323,7 @@ module OpenSSL end ## - # Get a specific +section+ from the current configuration + # Get a specific _section_ from the current configuration # # Given the following configurating file being loaded: # @@ -351,7 +352,7 @@ module OpenSSL end ## - # Sets a specific +section+ name with a Hash +pairs+ + # Sets a specific _section_ name with a Hash _pairs_. # # Given the following configuration being created: # @@ -365,7 +366,7 @@ module OpenSSL # # baz=buz # # It's important to note that this will essentially merge any of the keys - # in +pairs+ with the existing +section+. For example: + # in _pairs_ with the existing _section_. For example: # # config['default'] # #=> {"foo"=>"bar", "baz"=>"buz"} diff --git a/ext/openssl/lib/openssl/digest.rb b/ext/openssl/lib/openssl/digest.rb index 97ccbc9569..b6744de6bd 100644 --- a/ext/openssl/lib/openssl/digest.rb +++ b/ext/openssl/lib/openssl/digest.rb @@ -15,15 +15,12 @@ module OpenSSL class Digest - alg = %w(MD2 MD4 MD5 MDC2 RIPEMD160 SHA1) + alg = %w(MD2 MD4 MD5 MDC2 RIPEMD160 SHA1 SHA224 SHA256 SHA384 SHA512) if OPENSSL_VERSION_NUMBER < 0x10100000 alg += %w(DSS DSS1 SHA) end - if OPENSSL_VERSION_NUMBER > 0x00908000 - alg += %w(SHA224 SHA256 SHA384 SHA512) - end - # Return the +data+ hash computed with +name+ Digest. +name+ is either the + # Return the hash value computed with _name_ Digest. _name_ is either the # long name or short name of a supported digest algorithm. # # === Examples @@ -59,7 +56,7 @@ module OpenSSL end # Digest - # Returns a Digest subclass by +name+. + # Returns a Digest subclass by _name_ # # require 'openssl' # diff --git a/ext/openssl/lib/openssl/pkcs5.rb b/ext/openssl/lib/openssl/pkcs5.rb new file mode 100644 index 0000000000..959447df5e --- /dev/null +++ b/ext/openssl/lib/openssl/pkcs5.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: false +#-- +# Ruby/OpenSSL Project +# Copyright (C) 2017 Ruby/OpenSSL Project Authors +#++ + +module OpenSSL + module PKCS5 + module_function + + # OpenSSL::PKCS5.pbkdf2_hmac has been renamed to OpenSSL::KDF.pbkdf2_hmac. + # This method is provided for backwards compatibility. + def pbkdf2_hmac(pass, salt, iter, keylen, digest) + OpenSSL::KDF.pbkdf2_hmac(pass, salt: salt, iterations: iter, + length: keylen, hash: digest) + end + + def pbkdf2_hmac_sha1(pass, salt, iter, keylen) + pbkdf2_hmac(pass, salt, iter, keylen, "sha1") + end + end +end diff --git a/ext/openssl/lib/openssl/pkey.rb b/ext/openssl/lib/openssl/pkey.rb index 9af5f781f9..dcedd849a0 100644 --- a/ext/openssl/lib/openssl/pkey.rb +++ b/ext/openssl/lib/openssl/pkey.rb @@ -1,44 +1,3 @@ # frozen_string_literal: false module OpenSSL - module PKey - if defined?(OpenSSL::PKey::DH) - - class DH - # :nodoc: - DEFAULT_1024 = new <<-_end_of_pem_ ------BEGIN DH PARAMETERS----- -MIGHAoGBAJ0lOVy0VIr/JebWn0zDwY2h+rqITFOpdNr6ugsgvkDXuucdcChhYExJ -AV/ZD2AWPbrTqV76mGRgJg4EddgT1zG0jq3rnFdMj2XzkBYx3BVvfR0Arnby0RHR -T4h7KZ/2zmjvV+eF8kBUHBJAojUlzxKj4QeO2x20FP9X5xmNUXeDAgEC ------END DH PARAMETERS----- - _end_of_pem_ - - # :nodoc: - DEFAULT_2048 = new <<-_end_of_pem_ ------BEGIN DH PARAMETERS----- -MIIBCAKCAQEA7E6kBrYiyvmKAMzQ7i8WvwVk9Y/+f8S7sCTN712KkK3cqd1jhJDY -JbrYeNV3kUIKhPxWHhObHKpD1R84UpL+s2b55+iMd6GmL7OYmNIT/FccKhTcveab -VBmZT86BZKYyf45hUF9FOuUM9xPzuK3Vd8oJQvfYMCd7LPC0taAEljQLR4Edf8E6 -YoaOffgTf5qxiwkjnlVZQc3whgnEt9FpVMvQ9eknyeGB5KHfayAc3+hUAvI3/Cr3 -1bNveX5wInh5GDx1FGhKBZ+s1H+aedudCm7sCgRwv8lKWYGiHzObSma8A86KG+MD -7Lo5JquQ3DlBodj3IDyPrxIv96lvRPFtAwIBAg== ------END DH PARAMETERS----- - _end_of_pem_ - end - - # :nodoc: - DEFAULT_TMP_DH_CALLBACK = lambda { |ctx, is_export, keylen| - warn "using default DH parameters." if $VERBOSE - case keylen - when 1024 then OpenSSL::PKey::DH::DEFAULT_1024 - when 2048 then OpenSSL::PKey::DH::DEFAULT_2048 - else - nil - end - } - - else - DEFAULT_TMP_DH_CALLBACK = nil - end - end end diff --git a/ext/openssl/lib/openssl/ssl.rb b/ext/openssl/lib/openssl/ssl.rb index f40a451439..a628648e71 100644 --- a/ext/openssl/lib/openssl/ssl.rb +++ b/ext/openssl/lib/openssl/ssl.rb @@ -17,18 +17,36 @@ module OpenSSL module SSL class SSLContext DEFAULT_PARAMS = { # :nodoc: - :ssl_version => "SSLv23", + :min_version => OpenSSL::SSL::TLS1_VERSION, :verify_mode => OpenSSL::SSL::VERIFY_PEER, :verify_hostname => true, :options => -> { opts = OpenSSL::SSL::OP_ALL opts &= ~OpenSSL::SSL::OP_DONT_INSERT_EMPTY_FRAGMENTS - opts |= OpenSSL::SSL::OP_NO_COMPRESSION if defined?(OpenSSL::SSL::OP_NO_COMPRESSION) - opts |= OpenSSL::SSL::OP_NO_SSLv2 | OpenSSL::SSL::OP_NO_SSLv3 + opts |= OpenSSL::SSL::OP_NO_COMPRESSION opts }.call } + if defined?(OpenSSL::PKey::DH) + DEFAULT_2048 = OpenSSL::PKey::DH.new <<-_end_of_pem_ +-----BEGIN DH PARAMETERS----- +MIIBCAKCAQEA7E6kBrYiyvmKAMzQ7i8WvwVk9Y/+f8S7sCTN712KkK3cqd1jhJDY +JbrYeNV3kUIKhPxWHhObHKpD1R84UpL+s2b55+iMd6GmL7OYmNIT/FccKhTcveab +VBmZT86BZKYyf45hUF9FOuUM9xPzuK3Vd8oJQvfYMCd7LPC0taAEljQLR4Edf8E6 +YoaOffgTf5qxiwkjnlVZQc3whgnEt9FpVMvQ9eknyeGB5KHfayAc3+hUAvI3/Cr3 +1bNveX5wInh5GDx1FGhKBZ+s1H+aedudCm7sCgRwv8lKWYGiHzObSma8A86KG+MD +7Lo5JquQ3DlBodj3IDyPrxIv96lvRPFtAwIBAg== +-----END DH PARAMETERS----- + _end_of_pem_ + private_constant :DEFAULT_2048 + + DEFAULT_TMP_DH_CALLBACK = lambda { |ctx, is_export, keylen| # :nodoc: + warn "using default DH parameters." if $VERBOSE + DEFAULT_2048 + } + end + if !(OpenSSL::OPENSSL_VERSION.start_with?("OpenSSL") && OpenSSL::OPENSSL_VERSION_NUMBER >= 0x10100000) DEFAULT_PARAMS.merge!( @@ -87,14 +105,18 @@ module OpenSSL # # The callback is invoked with an SSLSocket and a server name. The # callback must return an SSLContext for the server name or nil. - attr_accessor :servername_cb if ExtConfig::HAVE_TLSEXT_HOST_NAME + attr_accessor :servername_cb # call-seq: - # SSLContext.new => ctx - # SSLContext.new(:TLSv1) => ctx - # SSLContext.new("SSLv23_client") => ctx + # SSLContext.new -> ctx + # SSLContext.new(:TLSv1) -> ctx + # SSLContext.new("SSLv23") -> ctx # - # You can get a list of valid methods with OpenSSL::SSL::SSLContext::METHODS + # Creates a new SSL context. + # + # If an argument is given, #ssl_version= is called with the value. Note + # that this form is deprecated. New applications should use #min_version= + # and #max_version= as necessary. def initialize(version = nil) self.options |= OpenSSL::SSL::OP_ALL self.ssl_version = version if version @@ -106,8 +128,8 @@ module OpenSSL # # Sets saner defaults optimized for the use with HTTP-like protocols. # - # If a Hash +params+ is given, the parameters are overridden with it. - # The keys in +params+ must be assignment methods on SSLContext. + # If a Hash _params_ is given, the parameters are overridden with it. + # The keys in _params_ must be assignment methods on SSLContext. # # If the verify_mode is not VERIFY_NONE and ca_file, ca_path and # cert_store are not set then the system default certificate store is @@ -122,6 +144,88 @@ module OpenSSL end return params end + + # call-seq: + # ctx.min_version = OpenSSL::SSL::TLS1_2_VERSION + # ctx.min_version = :TLS1_2 + # ctx.min_version = nil + # + # Sets the lower bound on the supported SSL/TLS protocol version. The + # version may be specified by an integer constant named + # OpenSSL::SSL::*_VERSION, a Symbol, or +nil+ which means "any version". + # + # Be careful that you don't overwrite OpenSSL::SSL::OP_NO_{SSL,TLS}v* + # options by #options= once you have called #min_version= or + # #max_version=. + # + # === Example + # ctx = OpenSSL::SSL::SSLContext.new + # ctx.min_version = OpenSSL::SSL::TLS1_1_VERSION + # ctx.max_version = OpenSSL::SSL::TLS1_2_VERSION + # + # sock = OpenSSL::SSL::SSLSocket.new(tcp_sock, ctx) + # sock.connect # Initiates a connection using either TLS 1.1 or TLS 1.2 + def min_version=(version) + set_minmax_proto_version(version, @max_proto_version ||= nil) + @min_proto_version = version + end + + # call-seq: + # ctx.max_version = OpenSSL::SSL::TLS1_2_VERSION + # ctx.max_version = :TLS1_2 + # ctx.max_version = nil + # + # Sets the upper bound of the supported SSL/TLS protocol version. See + # #min_version= for the possible values. + def max_version=(version) + set_minmax_proto_version(@min_proto_version ||= nil, version) + @max_proto_version = version + end + + # call-seq: + # ctx.ssl_version = :TLSv1 + # ctx.ssl_version = "SSLv23" + # + # Sets the SSL/TLS protocol version for the context. This forces + # connections to use only the specified protocol version. This is + # deprecated and only provided for backwards compatibility. Use + # #min_version= and #max_version= instead. + # + # === History + # As the name hints, this used to call the SSL_CTX_set_ssl_version() + # function which sets the SSL method used for connections created from + # the context. As of Ruby/OpenSSL 2.1, this accessor method is + # implemented to call #min_version= and #max_version= instead. + def ssl_version=(meth) + meth = meth.to_s if meth.is_a?(Symbol) + if /(?_client|_server)\z/ =~ meth + meth = $` + if $VERBOSE + warn "#{caller(1)[0]}: method type #{type.inspect} is ignored" + end + end + version = METHODS_MAP[meth.intern] or + raise ArgumentError, "unknown SSL method `%s'" % meth + set_minmax_proto_version(version, version) + @min_proto_version = @max_proto_version = version + end + + METHODS_MAP = { + SSLv23: 0, + SSLv2: OpenSSL::SSL::SSL2_VERSION, + SSLv3: OpenSSL::SSL::SSL3_VERSION, + TLSv1: OpenSSL::SSL::TLS1_VERSION, + TLSv1_1: OpenSSL::SSL::TLS1_1_VERSION, + TLSv1_2: OpenSSL::SSL::TLS1_2_VERSION, + }.freeze + private_constant :METHODS_MAP + + # The list of available SSL/TLS methods. This constant is only provided + # for backwards compatibility. + METHODS = METHODS_MAP.flat_map { |name,| + [name, :"#{name}_client", :"#{name}_server"] + }.freeze + deprecate_constant :METHODS end module SocketForwarder @@ -242,9 +346,7 @@ module OpenSSL include Buffering include SocketForwarder - if ExtConfig::HAVE_TLSEXT_HOST_NAME - attr_reader :hostname - end + attr_reader :hostname # The underlying IO object. attr_reader :io @@ -317,7 +419,7 @@ module OpenSSL end def tmp_dh_callback - @context.tmp_dh_callback || OpenSSL::PKey::DEFAULT_TMP_DH_CALLBACK + @context.tmp_dh_callback || OpenSSL::SSL::SSLContext::DEFAULT_TMP_DH_CALLBACK end def tmp_ecdh_callback @@ -341,8 +443,8 @@ module OpenSSL attr_accessor :start_immediately # Creates a new instance of SSLServer. - # * +srv+ is an instance of TCPServer. - # * +ctx+ is an instance of OpenSSL::SSL::SSLContext. + # * _srv_ is an instance of TCPServer. + # * _ctx_ is an instance of OpenSSL::SSL::SSLContext. def initialize(svr, ctx) @svr = svr @ctx = ctx diff --git a/ext/openssl/lib/openssl/x509.rb b/ext/openssl/lib/openssl/x509.rb index aef3456e0f..6d31b98c68 100644 --- a/ext/openssl/lib/openssl/x509.rb +++ b/ext/openssl/lib/openssl/x509.rb @@ -139,7 +139,13 @@ module OpenSSL end def parse_openssl(str, template=OBJECT_TYPE_TEMPLATE) - ary = str.scan(/\s*([^\/,]+)\s*/).collect{|i| i[0].split("=", 2) } + if str.start_with?("/") + # /A=B/C=D format + ary = str[1..-1].split("/").map { |i| i.split("=", 2) } + else + # Comma-separated + ary = str.split(",").map { |i| i.strip.split("=", 2) } + end self.new(ary, template) end diff --git a/ext/openssl/openssl.gemspec b/ext/openssl/openssl.gemspec index 7cbbfeb513..2c2e300bb9 100644 --- a/ext/openssl/openssl.gemspec +++ b/ext/openssl/openssl.gemspec @@ -1,26 +1,26 @@ # -*- encoding: utf-8 -*- -# stub: openssl 2.0.5 ruby lib +# stub: openssl 2.1.0.beta1 ruby lib # stub: ext/openssl/extconf.rb Gem::Specification.new do |s| s.name = "openssl".freeze - s.version = "2.0.5" + s.version = "2.1.0.beta1" - s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version= + s.required_rubygems_version = Gem::Requirement.new("> 1.3.1".freeze) if s.respond_to? :required_rubygems_version= s.metadata = { "msys2_mingw_dependencies" => "openssl" } if s.respond_to? :metadata= s.require_paths = ["lib".freeze] s.authors = ["Martin Bosslet".freeze, "SHIBATA Hiroshi".freeze, "Zachary Scott".freeze, "Kazuki Yamaguchi".freeze] - s.date = "2017-08-08" + s.date = "2017-09-03" s.description = "It wraps the OpenSSL library.".freeze s.email = ["ruby-core@ruby-lang.org".freeze] s.extensions = ["ext/openssl/extconf.rb".freeze] s.extra_rdoc_files = ["CONTRIBUTING.md".freeze, "README.md".freeze, "History.md".freeze] - s.files = ["BSDL".freeze, "CONTRIBUTING.md".freeze, "History.md".freeze, "LICENSE.txt".freeze, "README.md".freeze, "ext/openssl/deprecation.rb".freeze, "ext/openssl/extconf.rb".freeze, "ext/openssl/openssl_missing.c".freeze, "ext/openssl/openssl_missing.h".freeze, "ext/openssl/ossl.c".freeze, "ext/openssl/ossl.h".freeze, "ext/openssl/ossl_asn1.c".freeze, "ext/openssl/ossl_asn1.h".freeze, "ext/openssl/ossl_bio.c".freeze, "ext/openssl/ossl_bio.h".freeze, "ext/openssl/ossl_bn.c".freeze, "ext/openssl/ossl_bn.h".freeze, "ext/openssl/ossl_cipher.c".freeze, "ext/openssl/ossl_cipher.h".freeze, "ext/openssl/ossl_config.c".freeze, "ext/openssl/ossl_config.h".freeze, "ext/openssl/ossl_digest.c".freeze, "ext/openssl/ossl_digest.h".freeze, "ext/openssl/ossl_engine.c".freeze, "ext/openssl/ossl_engine.h".freeze, "ext/openssl/ossl_hmac.c".freeze, "ext/openssl/ossl_hmac.h".freeze, "ext/openssl/ossl_ns_spki.c".freeze, "ext/openssl/ossl_ns_spki.h".freeze, "ext/openssl/ossl_ocsp.c".freeze, "ext/openssl/ossl_ocsp.h".freeze, "ext/openssl/ossl_pkcs12.c".freeze, "ext/openssl/ossl_pkcs12.h".freeze, "ext/openssl/ossl_pkcs5.c".freeze, "ext/openssl/ossl_pkcs5.h".freeze, "ext/openssl/ossl_pkcs7.c".freeze, "ext/openssl/ossl_pkcs7.h".freeze, "ext/openssl/ossl_pkey.c".freeze, "ext/openssl/ossl_pkey.h".freeze, "ext/openssl/ossl_pkey_dh.c".freeze, "ext/openssl/ossl_pkey_dsa.c".freeze, "ext/openssl/ossl_pkey_ec.c".freeze, "ext/openssl/ossl_pkey_rsa.c".freeze, "ext/openssl/ossl_rand.c".freeze, "ext/openssl/ossl_rand.h".freeze, "ext/openssl/ossl_ssl.c".freeze, "ext/openssl/ossl_ssl.h".freeze, "ext/openssl/ossl_ssl_session.c".freeze, "ext/openssl/ossl_version.h".freeze, "ext/openssl/ossl_x509.c".freeze, "ext/openssl/ossl_x509.h".freeze, "ext/openssl/ossl_x509attr.c".freeze, "ext/openssl/ossl_x509cert.c".freeze, "ext/openssl/ossl_x509crl.c".freeze, "ext/openssl/ossl_x509ext.c".freeze, "ext/openssl/ossl_x509name.c".freeze, "ext/openssl/ossl_x509req.c".freeze, "ext/openssl/ossl_x509revoked.c".freeze, "ext/openssl/ossl_x509store.c".freeze, "ext/openssl/ruby_missing.h".freeze, "lib/openssl.rb".freeze, "lib/openssl/bn.rb".freeze, "lib/openssl/buffering.rb".freeze, "lib/openssl/cipher.rb".freeze, "lib/openssl/config.rb".freeze, "lib/openssl/digest.rb".freeze, "lib/openssl/pkey.rb".freeze, "lib/openssl/ssl.rb".freeze, "lib/openssl/x509.rb".freeze] + s.files = ["BSDL".freeze, "CONTRIBUTING.md".freeze, "History.md".freeze, "LICENSE.txt".freeze, "README.md".freeze, "ext/openssl/deprecation.rb".freeze, "ext/openssl/extconf.rb".freeze, "ext/openssl/openssl_missing.c".freeze, "ext/openssl/openssl_missing.h".freeze, "ext/openssl/ossl.c".freeze, "ext/openssl/ossl.h".freeze, "ext/openssl/ossl_asn1.c".freeze, "ext/openssl/ossl_asn1.h".freeze, "ext/openssl/ossl_bio.c".freeze, "ext/openssl/ossl_bio.h".freeze, "ext/openssl/ossl_bn.c".freeze, "ext/openssl/ossl_bn.h".freeze, "ext/openssl/ossl_cipher.c".freeze, "ext/openssl/ossl_cipher.h".freeze, "ext/openssl/ossl_config.c".freeze, "ext/openssl/ossl_config.h".freeze, "ext/openssl/ossl_digest.c".freeze, "ext/openssl/ossl_digest.h".freeze, "ext/openssl/ossl_engine.c".freeze, "ext/openssl/ossl_engine.h".freeze, "ext/openssl/ossl_hmac.c".freeze, "ext/openssl/ossl_hmac.h".freeze, "ext/openssl/ossl_kdf.c".freeze, "ext/openssl/ossl_kdf.h".freeze, "ext/openssl/ossl_ns_spki.c".freeze, "ext/openssl/ossl_ns_spki.h".freeze, "ext/openssl/ossl_ocsp.c".freeze, "ext/openssl/ossl_ocsp.h".freeze, "ext/openssl/ossl_pkcs12.c".freeze, "ext/openssl/ossl_pkcs12.h".freeze, "ext/openssl/ossl_pkcs7.c".freeze, "ext/openssl/ossl_pkcs7.h".freeze, "ext/openssl/ossl_pkey.c".freeze, "ext/openssl/ossl_pkey.h".freeze, "ext/openssl/ossl_pkey_dh.c".freeze, "ext/openssl/ossl_pkey_dsa.c".freeze, "ext/openssl/ossl_pkey_ec.c".freeze, "ext/openssl/ossl_pkey_rsa.c".freeze, "ext/openssl/ossl_rand.c".freeze, "ext/openssl/ossl_rand.h".freeze, "ext/openssl/ossl_ssl.c".freeze, "ext/openssl/ossl_ssl.h".freeze, "ext/openssl/ossl_ssl_session.c".freeze, "ext/openssl/ossl_version.h".freeze, "ext/openssl/ossl_x509.c".freeze, "ext/openssl/ossl_x509.h".freeze, "ext/openssl/ossl_x509attr.c".freeze, "ext/openssl/ossl_x509cert.c".freeze, "ext/openssl/ossl_x509crl.c".freeze, "ext/openssl/ossl_x509ext.c".freeze, "ext/openssl/ossl_x509name.c".freeze, "ext/openssl/ossl_x509req.c".freeze, "ext/openssl/ossl_x509revoked.c".freeze, "ext/openssl/ossl_x509store.c".freeze, "ext/openssl/ruby_missing.h".freeze, "lib/openssl.rb".freeze, "lib/openssl/bn.rb".freeze, "lib/openssl/buffering.rb".freeze, "lib/openssl/cipher.rb".freeze, "lib/openssl/config.rb".freeze, "lib/openssl/digest.rb".freeze, "lib/openssl/pkcs5.rb".freeze, "lib/openssl/pkey.rb".freeze, "lib/openssl/ssl.rb".freeze, "lib/openssl/x509.rb".freeze] s.homepage = "https://www.ruby-lang.org/".freeze s.licenses = ["Ruby".freeze] s.rdoc_options = ["--main".freeze, "README.md".freeze] s.required_ruby_version = Gem::Requirement.new(">= 2.3.0".freeze) - s.rubygems_version = "2.6.12".freeze + s.rubygems_version = "2.6.13".freeze s.summary = "OpenSSL provides SSL, TLS and general purpose cryptography.".freeze if s.respond_to? :specification_version then diff --git a/ext/openssl/openssl_missing.c b/ext/openssl/openssl_missing.c index 94ce85aff4..b36ef0288e 100644 --- a/ext/openssl/openssl_missing.c +++ b/ext/openssl/openssl_missing.c @@ -20,73 +20,6 @@ #include "openssl_missing.h" -/* added in 0.9.8X */ -#if !defined(HAVE_EVP_CIPHER_CTX_NEW) -EVP_CIPHER_CTX * -ossl_EVP_CIPHER_CTX_new(void) -{ - EVP_CIPHER_CTX *ctx = OPENSSL_malloc(sizeof(EVP_CIPHER_CTX)); - if (!ctx) - return NULL; - EVP_CIPHER_CTX_init(ctx); - return ctx; -} -#endif - -#if !defined(HAVE_EVP_CIPHER_CTX_FREE) -void -ossl_EVP_CIPHER_CTX_free(EVP_CIPHER_CTX *ctx) -{ - if (ctx) { - EVP_CIPHER_CTX_cleanup(ctx); - OPENSSL_free(ctx); - } -} -#endif - -/* added in 1.0.0 */ -#if !defined(HAVE_EVP_CIPHER_CTX_COPY) -/* - * this function does not exist in OpenSSL yet... or ever?. - * a future version may break this function. - * tested on 0.9.7d. - */ -int -ossl_EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out, const EVP_CIPHER_CTX *in) -{ - memcpy(out, in, sizeof(EVP_CIPHER_CTX)); - -#if !defined(OPENSSL_NO_ENGINE) - if (in->engine) ENGINE_add(out->engine); - if (in->cipher_data) { - out->cipher_data = OPENSSL_malloc(in->cipher->ctx_size); - memcpy(out->cipher_data, in->cipher_data, in->cipher->ctx_size); - } -#endif - - return 1; -} -#endif - -#if !defined(OPENSSL_NO_HMAC) -#if !defined(HAVE_HMAC_CTX_COPY) -int -ossl_HMAC_CTX_copy(HMAC_CTX *out, HMAC_CTX *in) -{ - if (!out || !in) - return 0; - - memcpy(out, in, sizeof(HMAC_CTX)); - - EVP_MD_CTX_copy(&out->md_ctx, &in->md_ctx); - EVP_MD_CTX_copy(&out->i_ctx, &in->i_ctx); - EVP_MD_CTX_copy(&out->o_ctx, &in->o_ctx); - - return 1; -} -#endif /* HAVE_HMAC_CTX_COPY */ -#endif /* NO_HMAC */ - /* added in 1.0.2 */ #if !defined(OPENSSL_NO_EC) #if !defined(HAVE_EC_CURVE_NIST2NID) diff --git a/ext/openssl/openssl_missing.h b/ext/openssl/openssl_missing.h index 3d11aec2d2..cc31f6ace7 100644 --- a/ext/openssl/openssl_missing.h +++ b/ext/openssl/openssl_missing.h @@ -12,53 +12,6 @@ #include "ruby/config.h" -/* added in 0.9.8X */ -#if !defined(HAVE_EVP_CIPHER_CTX_NEW) -EVP_CIPHER_CTX *ossl_EVP_CIPHER_CTX_new(void); -# define EVP_CIPHER_CTX_new ossl_EVP_CIPHER_CTX_new -#endif - -#if !defined(HAVE_EVP_CIPHER_CTX_FREE) -void ossl_EVP_CIPHER_CTX_free(EVP_CIPHER_CTX *); -# define EVP_CIPHER_CTX_free ossl_EVP_CIPHER_CTX_free -#endif - -#if !defined(HAVE_SSL_CTX_CLEAR_OPTIONS) -# define SSL_CTX_clear_options(ctx, op) ((ctx)->options &= ~(op)) -#endif - -/* 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 ossl_EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *, const EVP_CIPHER_CTX *); -# define EVP_CIPHER_CTX_copy ossl_EVP_CIPHER_CTX_copy -#endif - -#if !defined(HAVE_HMAC_CTX_COPY) -int ossl_HMAC_CTX_copy(HMAC_CTX *out, HMAC_CTX *in); -# define HMAC_CTX_copy ossl_HMAC_CTX_copy -#endif - -#if !defined(HAVE_X509_STORE_CTX_GET0_CURRENT_CRL) -# define X509_STORE_CTX_get0_current_crl(x) ((x)->current_crl) -#endif - -#if !defined(HAVE_X509_STORE_SET_VERIFY_CB) -# define X509_STORE_set_verify_cb X509_STORE_set_verify_cb_func -#endif - -#if !defined(HAVE_I2D_ASN1_SET_ANY) -# define i2d_ASN1_SET_ANY(sk, x) i2d_ASN1_SET_OF_ASN1_TYPE((sk), (x), \ - i2d_ASN1_TYPE, V_ASN1_SET, V_ASN1_UNIVERSAL, 0) -#endif - -#if !defined(HAVE_EVP_PKEY_GET0) -# define EVP_PKEY_get0(pk) (pk->pkey.ptr) -#endif - /* added in 1.0.2 */ #if !defined(OPENSSL_NO_EC) #if !defined(HAVE_EC_CURVE_NIST2NID) @@ -245,7 +198,7 @@ IMPL_PKEY_GETTER(EC_KEY, ec) #undef IMPL_KEY_ACCESSOR3 #endif /* HAVE_OPAQUE_OPENSSL */ -#if defined(HAVE_AUTHENTICATED_ENCRYPTION) && !defined(EVP_CTRL_AEAD_GET_TAG) +#if !defined(EVP_CTRL_AEAD_GET_TAG) # define EVP_CTRL_AEAD_GET_TAG EVP_CTRL_GCM_GET_TAG # define EVP_CTRL_AEAD_SET_TAG EVP_CTRL_GCM_SET_TAG # define EVP_CTRL_AEAD_SET_IVLEN EVP_CTRL_GCM_SET_IVLEN diff --git a/ext/openssl/ossl.c b/ext/openssl/ossl.c index c22966df5a..6ec5e91c66 100644 --- a/ext/openssl/ossl.c +++ b/ext/openssl/ossl.c @@ -92,22 +92,40 @@ OSSL_IMPL_SK2ARY(x509crl, X509_CRL) OSSL_IMPL_SK2ARY(x509name, X509_NAME) static VALUE -ossl_str_new(int size) +ossl_str_new_i(VALUE size) { - return rb_str_new(0, size); + return rb_str_new(NULL, (long)size); +} + +VALUE +ossl_str_new(const char *ptr, long len, int *pstate) +{ + VALUE str; + int state; + + str = rb_protect(ossl_str_new_i, len, &state); + if (pstate) + *pstate = state; + if (state) { + if (!pstate) + rb_set_errinfo(Qnil); + return Qnil; + } + if (ptr) + memcpy(RSTRING_PTR(str), ptr, len); + return str; } VALUE ossl_buf2str(char *buf, int len) { VALUE str; - int status = 0; + int state; - str = rb_protect((VALUE (*)(VALUE))ossl_str_new, len, &status); - if(!NIL_P(str)) memcpy(RSTRING_PTR(str), buf, len); + str = ossl_str_new(buf, len, &state); OPENSSL_free(buf); - if(status) rb_jump_tag(status); - + if (state) + rb_jump_tag(state); return str; } @@ -220,7 +238,7 @@ VALUE eOSSLError; /* * Convert to DER string */ -ID ossl_s_to_der; +static ID ossl_s_to_der; VALUE ossl_to_der(VALUE obj) @@ -248,18 +266,15 @@ static VALUE ossl_make_error(VALUE exc, const char *fmt, va_list args) { VALUE str = Qnil; - const char *msg; - long e; + unsigned long e; - e = ERR_peek_last_error(); if (fmt) { str = rb_vsprintf(fmt, args); } + e = ERR_peek_last_error(); if (e) { - if (dOSSL == Qtrue) /* FULL INFO */ - msg = ERR_error_string(e, NULL); - else - msg = ERR_reason_error_string(e); + const char *msg = ERR_reason_error_string(e); + if (NIL_P(str)) { if (msg) str = rb_str_new_cstr(msg); } @@ -267,8 +282,8 @@ ossl_make_error(VALUE exc, const char *fmt, va_list args) if (RSTRING_LEN(str)) rb_str_cat2(str, ": "); rb_str_cat2(str, msg ? msg : "(null)"); } + ossl_clear_error(); } - ossl_clear_error(); if (NIL_P(str)) str = rb_str_new(0, 0); return rb_exc_new3(exc, str); @@ -319,7 +334,8 @@ ossl_clear_error(void) * * See any remaining errors held in queue. * - * Any errors you see here are probably due to a bug in ruby's OpenSSL implementation. + * Any errors you see here are probably due to a bug in Ruby's OpenSSL + * implementation. */ VALUE ossl_get_errors(void) @@ -381,6 +397,23 @@ ossl_debug_set(VALUE self, VALUE val) return val; } +/* + * call-seq + * OpenSSL.fips_mode -> true | false + */ +static VALUE +ossl_fips_mode_get(VALUE self) +{ + +#ifdef OPENSSL_FIPS + VALUE enabled; + enabled = FIPS_mode() ? Qtrue : Qfalse; + return enabled; +#else + return Qfalse; +#endif +} + /* * call-seq: * OpenSSL.fips_mode = boolean -> boolean @@ -414,6 +447,72 @@ ossl_fips_mode_set(VALUE self, VALUE enabled) #endif } +#if defined(OSSL_DEBUG) +#if !defined(LIBRESSL_VERSION_NUMBER) && \ + (OPENSSL_VERSION_NUMBER >= 0x10100000 && !defined(OPENSSL_NO_CRYPTO_MDEBUG) || \ + defined(CRYPTO_malloc_debug_init)) +/* + * call-seq: + * OpenSSL.mem_check_start -> nil + * + * Calls CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON). Starts tracking memory + * allocations. See also OpenSSL.print_mem_leaks. + * + * This is available only when built with a capable OpenSSL and --enable-debug + * configure option. + */ +static VALUE +mem_check_start(VALUE self) +{ + CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON); + return Qnil; +} + +/* + * call-seq: + * OpenSSL.print_mem_leaks -> true | false + * + * For debugging the Ruby/OpenSSL library. Calls CRYPTO_mem_leaks_fp(stderr). + * Prints detected memory leaks to standard error. This cleans the global state + * up thus you cannot use any methods of the library after calling this. + * + * Returns +true+ if leaks detected, +false+ otherwise. + * + * This is available only when built with a capable OpenSSL and --enable-debug + * configure option. + * + * === Example + * OpenSSL.mem_check_start + * NOT_GCED = OpenSSL::PKey::RSA.new(256) + * + * END { + * GC.start + * OpenSSL.print_mem_leaks # will print the leakage + * } + */ +static VALUE +print_mem_leaks(VALUE self) +{ +#if OPENSSL_VERSION_NUMBER >= 0x10100000 + int ret; +#endif + + BN_CTX_free(ossl_bn_ctx); + ossl_bn_ctx = NULL; + +#if OPENSSL_VERSION_NUMBER >= 0x10100000 + ret = CRYPTO_mem_leaks_fp(stderr); + if (ret < 0) + ossl_raise(eOSSLError, "CRYPTO_mem_leaks_fp"); + return ret ? Qfalse : Qtrue; +#else + CRYPTO_mem_leaks_fp(stderr); + return Qnil; +#endif +} +#endif +#endif + #if !defined(HAVE_OPENSSL_110_THREADING_API) /** * Stores locks needed for OpenSSL thread safety @@ -461,19 +560,11 @@ ossl_dyn_destroy_callback(struct CRYPTO_dynlock_value *l, const char *file, int OPENSSL_free(l); } -#ifdef HAVE_CRYPTO_THREADID_PTR static void ossl_threadid_func(CRYPTO_THREADID *id) { /* register native thread id */ CRYPTO_THREADID_set_pointer(id, (void *)rb_nativethread_self()); } -#else -static unsigned long ossl_thread_id(void) -{ - /* before OpenSSL 1.0, this is 'unsigned long' */ - return (unsigned long)rb_nativethread_self(); -} -#endif static void Init_ossl_locks(void) { @@ -491,11 +582,7 @@ static void Init_ossl_locks(void) rb_nativethread_lock_initialize(&ossl_locks[i]); } -#ifdef HAVE_CRYPTO_THREADID_PTR CRYPTO_THREADID_set_callback(ossl_threadid_func); -#else - CRYPTO_set_id_callback(ossl_thread_id); -#endif CRYPTO_set_locking_callback(ossl_lock_callback); CRYPTO_set_dynlock_create_callback(ossl_dyn_create_callback); CRYPTO_set_dynlock_lock_callback(ossl_dyn_lock_callback); @@ -505,7 +592,7 @@ static void Init_ossl_locks(void) /* * OpenSSL provides SSL, TLS and general purpose cryptography. It wraps the - * OpenSSL[http://www.openssl.org/] library. + * OpenSSL[https://www.openssl.org/] library. * * = Examples * @@ -1057,7 +1144,7 @@ Init_openssl(void) rb_define_const(mOSSL, "OPENSSL_VERSION_NUMBER", INT2NUM(OPENSSL_VERSION_NUMBER)); /* - * Boolean indicating whether OpenSSL is FIPS-enabled or not + * Boolean indicating whether OpenSSL is FIPS-capable or not */ rb_define_const(mOSSL, "OPENSSL_FIPS", #ifdef OPENSSL_FIPS @@ -1067,6 +1154,7 @@ Init_openssl(void) #endif ); + rb_define_module_function(mOSSL, "fips_mode", ossl_fips_mode_get, 0); rb_define_module_function(mOSSL, "fips_mode=", ossl_fips_mode_set, 1); /* @@ -1106,7 +1194,6 @@ Init_openssl(void) Init_ossl_ns_spki(); Init_ossl_pkcs12(); Init_ossl_pkcs7(); - Init_ossl_pkcs5(); Init_ossl_pkey(); Init_ossl_rand(); Init_ossl_ssl(); @@ -1114,15 +1201,41 @@ Init_openssl(void) Init_ossl_ocsp(); Init_ossl_engine(); Init_ossl_asn1(); -} + Init_ossl_kdf(); #if defined(OSSL_DEBUG) -/* - * Check if all symbols are OK with 'make LDSHARED=gcc all' - */ -int -main(int argc, char *argv[]) -{ - return 0; + /* + * For debugging Ruby/OpenSSL. Enable only when built with --enable-debug + */ +#if !defined(LIBRESSL_VERSION_NUMBER) && \ + (OPENSSL_VERSION_NUMBER >= 0x10100000 && !defined(OPENSSL_NO_CRYPTO_MDEBUG) || \ + defined(CRYPTO_malloc_debug_init)) + rb_define_module_function(mOSSL, "mem_check_start", mem_check_start, 0); + rb_define_module_function(mOSSL, "print_mem_leaks", print_mem_leaks, 0); + +#if defined(CRYPTO_malloc_debug_init) /* <= 1.0.2 */ + CRYPTO_malloc_debug_init(); +#endif + +#if defined(V_CRYPTO_MDEBUG_ALL) /* <= 1.0.2 */ + CRYPTO_set_mem_debug_options(V_CRYPTO_MDEBUG_ALL); +#endif + +#if OPENSSL_VERSION_NUMBER < 0x10100000 /* <= 1.0.2 */ + { + int i; + /* + * See crypto/ex_data.c; call def_get_class() immediately to avoid + * allocations. 15 is the maximum number that is used as the class index + * in OpenSSL 1.0.2. + */ + for (i = 0; i <= 15; i++) { + if (CRYPTO_get_ex_new_index(i, 0, (void *)"ossl-mdebug-dummy", 0, 0, 0) < 0) + rb_raise(rb_eRuntimeError, "CRYPTO_get_ex_new_index for " + "class index %d failed", i); + } + } +#endif +#endif +#endif } -#endif /* OSSL_DEBUG */ diff --git a/ext/openssl/ossl.h b/ext/openssl/ossl.h index 78eddd09b4..f08889b22e 100644 --- a/ext/openssl/ossl.h +++ b/ext/openssl/ossl.h @@ -56,29 +56,29 @@ extern VALUE eOSSLError; }\ } while (0) -#define OSSL_Check_Instance(obj, klass) do {\ - if (!rb_obj_is_instance_of((obj), (klass))) {\ - ossl_raise(rb_eTypeError, "wrong argument (%"PRIsVALUE")! (Expected instance of %"PRIsVALUE")",\ - rb_obj_class(obj), (klass));\ - }\ -} while (0) - -#define OSSL_Check_Same_Class(obj1, obj2) do {\ - if (!rb_obj_is_instance_of((obj1), rb_obj_class(obj2))) {\ - ossl_raise(rb_eTypeError, "wrong argument type");\ - }\ -} while (0) +/* + * Type conversions + */ +#if !defined(NUM2UINT64T) /* in case Ruby starts to provide */ +# if SIZEOF_LONG == 8 +# define NUM2UINT64T(x) ((uint64_t)NUM2ULONG(x)) +# elif defined(HAVE_LONG_LONG) && SIZEOF_LONG_LONG == 8 +# define NUM2UINT64T(x) ((uint64_t)NUM2ULL(x)) +# else +# error "unknown platform; no 64-bit width integer" +# endif +#endif /* * Data Conversion */ -STACK_OF(X509) *ossl_x509_ary2sk0(VALUE); STACK_OF(X509) *ossl_x509_ary2sk(VALUE); STACK_OF(X509) *ossl_protect_x509_ary2sk(VALUE,int*); VALUE ossl_x509_sk2ary(const STACK_OF(X509) *certs); VALUE ossl_x509crl_sk2ary(const STACK_OF(X509_CRL) *crl); VALUE ossl_x509name_sk2ary(const STACK_OF(X509_NAME) *names); VALUE ossl_buf2str(char *buf, int len); +VALUE ossl_str_new(const char *, long, int *); #define ossl_str_adjust(str, p) \ do{\ long len = RSTRING_LEN(str);\ @@ -115,7 +115,6 @@ int ossl_pem_passwd_cb(char *, int, int, void *); /* * ERRor messages */ -#define OSSL_ErrMsg() ERR_reason_error_string(ERR_get_error()) NORETURN(void ossl_raise(VALUE, const char *, ...)); /* Clear OpenSSL error queue. If dOSSL is set, rb_warn() them. */ void ossl_clear_error(void); @@ -123,7 +122,6 @@ void ossl_clear_error(void); /* * String to DER String */ -extern ID ossl_s_to_der; VALUE ossl_to_der(VALUE); VALUE ossl_to_der_if_possible(VALUE); @@ -141,20 +139,9 @@ extern VALUE dOSSL; } \ } while (0) -#define OSSL_Warning(fmt, ...) do { \ - OSSL_Debug((fmt), ##__VA_ARGS__); \ - rb_warning((fmt), ##__VA_ARGS__); \ -} while (0) - -#define OSSL_Warn(fmt, ...) do { \ - OSSL_Debug((fmt), ##__VA_ARGS__); \ - rb_warn((fmt), ##__VA_ARGS__); \ -} while (0) #else void ossl_debug(const char *, ...); #define OSSL_Debug ossl_debug -#define OSSL_Warning rb_warning -#define OSSL_Warn rb_warn #endif /* @@ -173,13 +160,13 @@ void ossl_debug(const char *, ...); #include "ossl_ocsp.h" #include "ossl_pkcs12.h" #include "ossl_pkcs7.h" -#include "ossl_pkcs5.h" #include "ossl_pkey.h" #include "ossl_rand.h" #include "ossl_ssl.h" #include "ossl_version.h" #include "ossl_x509.h" #include "ossl_engine.h" +#include "ossl_kdf.h" void Init_openssl(void); diff --git a/ext/openssl/ossl_asn1.c b/ext/openssl/ossl_asn1.c index 1d3ee4ac18..efa6b78742 100644 --- a/ext/openssl/ossl_asn1.c +++ b/ext/openssl/ossl_asn1.c @@ -9,11 +9,9 @@ */ #include "ossl.h" -static VALUE join_der(VALUE enumerable); static VALUE ossl_asn1_decode0(unsigned char **pp, long length, long *offset, int depth, int yield, long *num_read); static VALUE ossl_asn1_initialize(int argc, VALUE *argv, VALUE self); -static VALUE ossl_asn1eoc_initialize(VALUE self); /* * DATE conversion @@ -25,7 +23,6 @@ asn1time_to_time(const ASN1_TIME *time) VALUE argv[6]; int count; - if (!time || !time->data) return Qnil; memset(&tm, 0, sizeof(struct tm)); switch (time->type) { @@ -72,7 +69,6 @@ asn1time_to_time(const ASN1_TIME *time) return rb_funcall2(rb_cTime, rb_intern("utc"), 6, argv); } -#if defined(HAVE_ASN1_TIME_ADJ) void ossl_time_split(VALUE time, time_t *sec, int *days) { @@ -88,13 +84,6 @@ ossl_time_split(VALUE time, time_t *sec, int *days) *sec = NUM2TIMET(rb_funcall(num, rb_intern("%"), 1, INT2FIX(86400))); } } -#else -time_t -time_to_time_t(VALUE time) -{ - return (time_t)NUM2TIMET(rb_Integer(time)); -} -#endif /* * STRING conversion @@ -155,13 +144,13 @@ num_to_asn1integer(VALUE obj, ASN1_INTEGER *ai) #define ossl_asn1_get_tag(o) rb_attr_get((o),sivTAG) #define ossl_asn1_get_tagging(o) rb_attr_get((o),sivTAGGING) #define ossl_asn1_get_tag_class(o) rb_attr_get((o),sivTAG_CLASS) -#define ossl_asn1_get_infinite_length(o) rb_attr_get((o),sivINFINITE_LENGTH) +#define ossl_asn1_get_indefinite_length(o) rb_attr_get((o),sivINDEFINITE_LENGTH) #define ossl_asn1_set_value(o,v) rb_ivar_set((o),sivVALUE,(v)) #define ossl_asn1_set_tag(o,v) rb_ivar_set((o),sivTAG,(v)) #define ossl_asn1_set_tagging(o,v) rb_ivar_set((o),sivTAGGING,(v)) #define ossl_asn1_set_tag_class(o,v) rb_ivar_set((o),sivTAG_CLASS,(v)) -#define ossl_asn1_set_infinite_length(o,v) rb_ivar_set((o),sivINFINITE_LENGTH,(v)) +#define ossl_asn1_set_indefinite_length(o,v) rb_ivar_set((o),sivINDEFINITE_LENGTH,(v)) VALUE mASN1; VALUE eASN1Error; @@ -187,7 +176,7 @@ VALUE cASN1Sequence, cASN1Set; /* CONSTRUCTIVE */ static VALUE sym_IMPLICIT, sym_EXPLICIT; static VALUE sym_UNIVERSAL, sym_APPLICATION, sym_CONTEXT_SPECIFIC, sym_PRIVATE; -static ID sivVALUE, sivTAG, sivTAG_CLASS, sivTAGGING, sivINFINITE_LENGTH, sivUNUSED_BITS; +static ID sivVALUE, sivTAG, sivTAG_CLASS, sivTAGGING, sivINDEFINITE_LENGTH, sivUNUSED_BITS; static ID id_each; /* @@ -213,13 +202,15 @@ obj_to_asn1bstr(VALUE obj, long unused_bits) { ASN1_BIT_STRING *bstr; - if(unused_bits < 0) unused_bits = 0; + if (unused_bits < 0 || unused_bits > 7) + ossl_raise(eASN1Error, "unused_bits for a bitstring value must be in "\ + "the range 0 to 7"); StringValue(obj); if(!(bstr = ASN1_BIT_STRING_new())) ossl_raise(eASN1Error, NULL); ASN1_BIT_STRING_set(bstr, (unsigned char *)RSTRING_PTR(obj), RSTRING_LENINT(obj)); bstr->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07); /* clear */ - bstr->flags |= ASN1_STRING_FLAG_BITS_LEFT|(unused_bits&0x07); + bstr->flags |= ASN1_STRING_FLAG_BITS_LEFT | unused_bits; return bstr; } @@ -269,15 +260,10 @@ obj_to_asn1utime(VALUE time) time_t sec; ASN1_UTCTIME *t; -#if defined(HAVE_ASN1_TIME_ADJ) int off_days; ossl_time_split(time, &sec, &off_days); if (!(t = ASN1_UTCTIME_adj(NULL, sec, off_days, 0))) -#else - sec = time_to_time_t(time); - if (!(t = ASN1_UTCTIME_set(NULL, sec))) -#endif ossl_raise(eASN1Error, NULL); return t; @@ -289,15 +275,10 @@ obj_to_asn1gtime(VALUE time) time_t sec; ASN1_GENERALIZEDTIME *t; -#if defined(HAVE_ASN1_TIME_ADJ) int off_days; ossl_time_split(time, &sec, &off_days); if (!(t = ASN1_GENERALIZEDTIME_adj(NULL, sec, off_days, 0))) -#else - sec = time_to_time_t(time); - if (!(t = ASN1_GENERALIZEDTIME_set(NULL, sec))) -#endif ossl_raise(eASN1Error, NULL); return t; @@ -517,7 +498,7 @@ ossl_asn1_get_asn1type(VALUE obj) VALUE value, rflag; void *ptr; void (*free_func)(); - int tag, flag; + int tag; tag = ossl_asn1_default_tag(obj); value = ossl_asn1_get_value(obj); @@ -533,8 +514,7 @@ ossl_asn1_get_asn1type(VALUE obj) break; case V_ASN1_BIT_STRING: rflag = rb_attr_get(obj, sivUNUSED_BITS); - flag = NIL_P(rflag) ? -1 : NUM2INT(rflag); - ptr = obj_to_asn1bstr(value, flag); + ptr = obj_to_asn1bstr(value, NUM2INT(rflag)); free_func = ASN1_BIT_STRING_free; break; case V_ASN1_NULL: @@ -598,8 +578,8 @@ ossl_asn1_default_tag(VALUE obj) return NUM2INT(tag); tmp_class = rb_class_superclass(tmp_class); } - ossl_raise(eASN1Error, "universal tag for %"PRIsVALUE" not found", - rb_obj_class(obj)); + + return -1; } static int @@ -614,20 +594,6 @@ ossl_asn1_tag(VALUE obj) return NUM2INT(tag); } -static int -ossl_asn1_is_explicit(VALUE obj) -{ - VALUE s; - - s = ossl_asn1_get_tagging(obj); - if (NIL_P(s) || s == sym_IMPLICIT) - return 0; - else if (s == sym_EXPLICIT) - return 1; - else - ossl_raise(eASN1Error, "invalid tag default"); -} - static int ossl_asn1_tag_class(VALUE obj) { @@ -663,12 +629,12 @@ ossl_asn1_class2sym(int tc) * call-seq: * OpenSSL::ASN1::ASN1Data.new(value, tag, tag_class) => ASN1Data * - * +value+: Please have a look at Constructive and Primitive to see how Ruby + * _value_: Please have a look at Constructive and Primitive to see how Ruby * types are mapped to ASN.1 types and vice versa. * - * +tag+: A +Number+ indicating the tag number. + * _tag_: An Integer indicating the tag number. * - * +tag_class+: A +Symbol+ indicating the tag class. Please cf. ASN1 for + * _tag_class_: A Symbol indicating the tag class. Please cf. ASN1 for * possible values. * * == Example @@ -680,73 +646,85 @@ ossl_asn1data_initialize(VALUE self, VALUE value, VALUE tag, VALUE tag_class) { if(!SYMBOL_P(tag_class)) ossl_raise(eASN1Error, "invalid tag class"); - if (tag_class == sym_UNIVERSAL && NUM2INT(tag) > 31) - ossl_raise(eASN1Error, "tag number for Universal too large"); ossl_asn1_set_tag(self, tag); ossl_asn1_set_value(self, value); ossl_asn1_set_tag_class(self, tag_class); - ossl_asn1_set_infinite_length(self, Qfalse); + ossl_asn1_set_indefinite_length(self, Qfalse); return self; } static VALUE -join_der_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, str)) +to_der_internal(VALUE self, int constructed, int indef_len, VALUE body) { - i = ossl_to_der_if_possible(i); - StringValue(i); - rb_str_append(str, i); - return Qnil; -} + int encoding = constructed ? indef_len ? 2 : 1 : 0; + int tag_class = ossl_asn1_tag_class(self); + int tag_number = ossl_asn1_tag(self); + int default_tag_number = ossl_asn1_default_tag(self); + int body_length, total_length; + VALUE str; + unsigned char *p; -static VALUE -join_der(VALUE enumerable) -{ - VALUE str = rb_str_new(0, 0); - rb_block_call(enumerable, id_each, 0, 0, join_der_i, str); + body_length = RSTRING_LENINT(body); + if (ossl_asn1_get_tagging(self) == sym_EXPLICIT) { + int inner_length, e_encoding = indef_len ? 2 : 1; + + if (default_tag_number == -1) + ossl_raise(eASN1Error, "explicit tagging of unknown tag"); + + inner_length = ASN1_object_size(encoding, body_length, default_tag_number); + total_length = ASN1_object_size(e_encoding, inner_length, tag_number); + str = rb_str_new(NULL, total_length); + p = (unsigned char *)RSTRING_PTR(str); + /* Put explicit tag */ + ASN1_put_object(&p, e_encoding, inner_length, tag_number, tag_class); + /* Append inner object */ + ASN1_put_object(&p, encoding, body_length, default_tag_number, V_ASN1_UNIVERSAL); + memcpy(p, RSTRING_PTR(body), body_length); + p += body_length; + if (indef_len) { + ASN1_put_eoc(&p); /* For inner object */ + ASN1_put_eoc(&p); /* For wrapper object */ + } + } + else { + total_length = ASN1_object_size(encoding, body_length, tag_number); + str = rb_str_new(NULL, total_length); + p = (unsigned char *)RSTRING_PTR(str); + ASN1_put_object(&p, encoding, body_length, tag_number, tag_class); + memcpy(p, RSTRING_PTR(body), body_length); + p += body_length; + if (indef_len) + ASN1_put_eoc(&p); + } + assert(p - (unsigned char *)RSTRING_PTR(str) == total_length); return str; } +static VALUE ossl_asn1prim_to_der(VALUE); +static VALUE ossl_asn1cons_to_der(VALUE); /* * call-seq: * asn1.to_der => DER-encoded String * * Encodes this ASN1Data into a DER-encoded String value. The result is - * DER-encoded except for the possibility of infinite length encodings. - * Infinite length encodings are not allowed in strict DER, so strictly - * speaking the result of such an encoding would be a BER-encoding. + * DER-encoded except for the possibility of indefinite length forms. + * Indefinite length forms are not allowed in strict DER, so strictly speaking + * the result of such an encoding would be a BER-encoding. */ static VALUE ossl_asn1data_to_der(VALUE self) { - VALUE value, der, inf_length; - int tag, tag_class, is_cons = 0; - long length; - unsigned char *p; - - value = ossl_asn1_get_value(self); - if(rb_obj_is_kind_of(value, rb_cArray)){ - is_cons = 1; - value = join_der(value); - } - StringValue(value); + VALUE value = ossl_asn1_get_value(self); - tag = ossl_asn1_tag(self); - tag_class = ossl_asn1_tag_class(self); - inf_length = ossl_asn1_get_infinite_length(self); - if (inf_length == Qtrue) { - is_cons = 2; + if (rb_obj_is_kind_of(value, rb_cArray)) + return ossl_asn1cons_to_der(self); + else { + if (RTEST(ossl_asn1_get_indefinite_length(self))) + ossl_raise(eASN1Error, "indefinite length form cannot be used " \ + "with primitive encoding"); + return ossl_asn1prim_to_der(self); } - if((length = ASN1_object_size(is_cons, RSTRING_LENINT(value), tag)) <= 0) - ossl_raise(eASN1Error, NULL); - der = rb_str_new(0, length); - p = (unsigned char *)RSTRING_PTR(der); - ASN1_put_object(&p, is_cons, RSTRING_LENINT(value), tag, tag_class); - memcpy(p, RSTRING_PTR(value), RSTRING_LEN(value)); - p += RSTRING_LEN(value); - ossl_str_adjust(der, p); - - return der; } static VALUE @@ -829,46 +807,33 @@ int_ossl_asn1_decode0_cons(unsigned char **pp, long max_len, long length, int tag, VALUE tc, long *num_read) { VALUE value, asn1data, ary; - int infinite; + int indefinite; long available_len, off = *offset; - infinite = (j == 0x21); + indefinite = (j == 0x21); ary = rb_ary_new(); - available_len = infinite ? max_len : length; + available_len = indefinite ? max_len : length; while (available_len > 0) { long inner_read = 0; value = ossl_asn1_decode0(pp, available_len, &off, depth + 1, yield, &inner_read); *num_read += inner_read; available_len -= inner_read; - rb_ary_push(ary, value); - if (infinite && - NUM2INT(ossl_asn1_get_tag(value)) == V_ASN1_EOC && + if (indefinite && + ossl_asn1_tag(value) == V_ASN1_EOC && ossl_asn1_get_tag_class(value) == sym_UNIVERSAL) { break; } + rb_ary_push(ary, value); } if (tc == sym_UNIVERSAL) { VALUE args[4]; - int not_sequence_or_set; - - not_sequence_or_set = tag != V_ASN1_SEQUENCE && tag != V_ASN1_SET; - - if (not_sequence_or_set) { - if (infinite) { - asn1data = rb_obj_alloc(cASN1Constructive); - } - else { - ossl_raise(eASN1Error, "invalid non-infinite tag"); - return Qnil; - } - } - else { - VALUE klass = *ossl_asn1_info[tag].klass; - asn1data = rb_obj_alloc(klass); - } + if (tag == V_ASN1_SEQUENCE || tag == V_ASN1_SET) + asn1data = rb_obj_alloc(*ossl_asn1_info[tag].klass); + else + asn1data = rb_obj_alloc(cASN1Constructive); args[0] = ary; args[1] = INT2NUM(tag); args[2] = Qnil; @@ -880,10 +845,10 @@ int_ossl_asn1_decode0_cons(unsigned char **pp, long max_len, long length, ossl_asn1data_initialize(asn1data, ary, INT2NUM(tag), tc); } - if (infinite) - ossl_asn1_set_infinite_length(asn1data, Qtrue); + if (indefinite) + ossl_asn1_set_indefinite_length(asn1data, Qtrue); else - ossl_asn1_set_infinite_length(asn1data, Qfalse); + ossl_asn1_set_indefinite_length(asn1data, Qfalse); *offset = off; return asn1data; @@ -936,7 +901,8 @@ ossl_asn1_decode0(unsigned char **pp, long length, long *offset, int depth, inner_read += hlen; } else { - if ((j & 0x01) && (len == 0)) ossl_raise(eASN1Error, "Infinite length for primitive value"); + if ((j & 0x01) && (len == 0)) + ossl_raise(eASN1Error, "indefinite length for primitive value"); asn1data = int_ossl_asn1_decode0_prim(pp, len, hlen, tag, tag_class, &inner_read); off += hlen + len; } @@ -968,13 +934,13 @@ int_ossl_decode_sanity_check(long len, long read, long offset) * * If a block is given, it prints out each of the elements encountered. * Block parameters are (in that order): - * * depth: The recursion depth, plus one with each constructed value being encountered (Number) - * * offset: Current byte offset (Number) - * * header length: Combined length in bytes of the Tag and Length headers. (Number) - * * length: The overall remaining length of the entire data (Number) + * * depth: The recursion depth, plus one with each constructed value being encountered (Integer) + * * offset: Current byte offset (Integer) + * * header length: Combined length in bytes of the Tag and Length headers. (Integer) + * * length: The overall remaining length of the entire data (Integer) * * constructed: Whether this value is constructed or not (Boolean) * * tag_class: Current tag class (Symbol) - * * tag: The current tag (Number) + * * tag: The current tag number (Integer) * * == Example * der = File.binread('asn1data.der') @@ -1004,9 +970,9 @@ ossl_asn1_traverse(VALUE self, VALUE obj) * call-seq: * OpenSSL::ASN1.decode(der) -> ASN1Data * - * Decodes a BER- or DER-encoded value and creates an ASN1Data instance. +der+ - * may be a +String+ or any object that features a +#to_der+ method transforming - * it into a BER-/DER-encoded +String+. + * Decodes a BER- or DER-encoded value and creates an ASN1Data instance. _der_ + * may be a String or any object that features a +.to_der+ method transforming + * it into a BER-/DER-encoded String+ * * == Example * der = File.binread('asn1data') @@ -1034,9 +1000,9 @@ ossl_asn1_decode(VALUE self, VALUE obj) * call-seq: * OpenSSL::ASN1.decode_all(der) -> Array of ASN1Data * - * Similar to +decode+ with the difference that +decode+ expects one - * distinct value represented in +der+. +decode_all+ on the contrary - * decodes a sequence of sequential BER/DER values lined up in +der+ + * Similar to #decode with the difference that #decode expects one + * distinct value represented in _der_. #decode_all on the contrary + * decodes a sequence of sequential BER/DER values lined up in _der_ * and returns them as an array. * * == Example @@ -1071,19 +1037,19 @@ ossl_asn1_decode_all(VALUE self, VALUE obj) /* * call-seq: - * OpenSSL::ASN1::Primitive.new( value [, tag, tagging, tag_class ]) => Primitive + * OpenSSL::ASN1::Primitive.new(value [, tag, tagging, tag_class ]) => Primitive * - * +value+: is mandatory. + * _value_: is mandatory. * - * +tag+: optional, may be specified for tagged values. If no +tag+ is + * _tag_: optional, may be specified for tagged values. If no _tag_ is * specified, the UNIVERSAL tag corresponding to the Primitive sub-class * is used by default. * - * +tagging+: may be used as an encoding hint to encode a value either + * _tagging_: may be used as an encoding hint to encode a value either * explicitly or implicitly, see ASN1 for possible values. * - * +tag_class+: if +tag+ and +tagging+ are +nil+ then this is set to - * +:UNIVERSAL+ by default. If either +tag+ or +tagging+ are set then + * _tag_class_: if _tag_ and _tagging_ are +nil+ then this is set to + * +:UNIVERSAL+ by default. If either _tag_ or _tagging_ are set then * +:CONTEXT_SPECIFIC+ is used as the default. For possible values please * cf. ASN1. * @@ -1096,9 +1062,12 @@ static VALUE ossl_asn1_initialize(int argc, VALUE *argv, VALUE self) { VALUE value, tag, tagging, tag_class; + int default_tag; rb_scan_args(argc, argv, "13", &value, &tag, &tagging, &tag_class); - if(argc > 1){ + default_tag = ossl_asn1_default_tag(self); + + if (default_tag == -1 || argc > 1) { if(NIL_P(tag)) ossl_raise(eASN1Error, "must specify tag number"); if(!NIL_P(tagging) && !SYMBOL_P(tagging)) @@ -1111,11 +1080,9 @@ ossl_asn1_initialize(int argc, VALUE *argv, VALUE self) } if(!SYMBOL_P(tag_class)) ossl_raise(eASN1Error, "invalid tag class"); - if (tagging == sym_IMPLICIT && NUM2INT(tag) > 31) - ossl_raise(eASN1Error, "tag number for Universal too large"); } else{ - tag = INT2NUM(ossl_asn1_default_tag(self)); + tag = INT2NUM(default_tag); tagging = Qnil; tag_class = sym_UNIVERSAL; } @@ -1123,7 +1090,9 @@ ossl_asn1_initialize(int argc, VALUE *argv, VALUE self) ossl_asn1_set_value(self, value); ossl_asn1_set_tagging(self, tagging); ossl_asn1_set_tag_class(self, tag_class); - ossl_asn1_set_infinite_length(self, Qfalse); + ossl_asn1_set_indefinite_length(self, Qfalse); + if (default_tag == V_ASN1_BIT_STRING) + rb_ivar_set(self, sivUNUSED_BITS, INT2FIX(0)); return self; } @@ -1131,7 +1100,7 @@ ossl_asn1_initialize(int argc, VALUE *argv, VALUE self) static VALUE ossl_asn1eoc_initialize(VALUE self) { VALUE tag, tagging, tag_class, value; - tag = INT2NUM(ossl_asn1_default_tag(self)); + tag = INT2FIX(0); tagging = Qnil; tag_class = sym_UNIVERSAL; value = rb_str_new("", 0); @@ -1139,51 +1108,58 @@ ossl_asn1eoc_initialize(VALUE self) { ossl_asn1_set_value(self, value); ossl_asn1_set_tagging(self, tagging); ossl_asn1_set_tag_class(self, tag_class); - ossl_asn1_set_infinite_length(self, Qfalse); + ossl_asn1_set_indefinite_length(self, Qfalse); return self; } +static VALUE +ossl_asn1eoc_to_der(VALUE self) +{ + return rb_str_new("\0\0", 2); +} + /* * call-seq: * asn1.to_der => DER-encoded String * - * See ASN1Data#to_der for details. * + * See ASN1Data#to_der for details. */ static VALUE ossl_asn1prim_to_der(VALUE self) { ASN1_TYPE *asn1; - int tn, tc, explicit; - long len, reallen; - unsigned char *buf, *p; + long alllen, bodylen; + unsigned char *p0, *p1; + int j, tag, tc, state; VALUE str; - tn = NUM2INT(ossl_asn1_get_tag(self)); - tc = ossl_asn1_tag_class(self); - explicit = ossl_asn1_is_explicit(self); - asn1 = ossl_asn1_get_asn1type(self); + if (ossl_asn1_default_tag(self) == -1) { + str = ossl_asn1_get_value(self); + return to_der_internal(self, 0, 0, StringValue(str)); + } - len = ASN1_object_size(1, i2d_ASN1_TYPE(asn1, NULL), tn); - if(!(buf = OPENSSL_malloc(len))){ + asn1 = ossl_asn1_get_asn1type(self); + alllen = i2d_ASN1_TYPE(asn1, NULL); + if (alllen < 0) { ASN1_TYPE_free(asn1); - ossl_raise(eASN1Error, "cannot alloc buffer"); + ossl_raise(eASN1Error, "i2d_ASN1_TYPE"); } - p = buf; - if (tc == V_ASN1_UNIVERSAL) { - i2d_ASN1_TYPE(asn1, &p); - } else if (explicit) { - ASN1_put_object(&p, 1, i2d_ASN1_TYPE(asn1, NULL), tn, tc); - i2d_ASN1_TYPE(asn1, &p); - } else { - i2d_ASN1_TYPE(asn1, &p); - *buf = tc | tn | (*buf & V_ASN1_CONSTRUCTED); + str = ossl_str_new(NULL, alllen, &state); + if (state) { + ASN1_TYPE_free(asn1); + rb_jump_tag(state); } + p0 = p1 = (unsigned char *)RSTRING_PTR(str); + i2d_ASN1_TYPE(asn1, &p0); ASN1_TYPE_free(asn1); - reallen = p - buf; - assert(reallen <= len); - str = ossl_buf2str((char *)buf, rb_long2int(reallen)); /* buf will be free in ossl_buf2str */ + assert(p0 - p1 == alllen); - return str; + /* Strip header since to_der_internal() wants only the payload */ + j = ASN1_get_object((const unsigned char **)&p1, &bodylen, &tag, &tc, alllen); + if (j & 0x80) + ossl_raise(eASN1Error, "ASN1_get_object"); /* should not happen */ + + return to_der_internal(self, 0, 0, rb_str_drop_bytes(str, alllen - bodylen)); } /* @@ -1195,92 +1171,41 @@ ossl_asn1prim_to_der(VALUE self) static VALUE ossl_asn1cons_to_der(VALUE self) { - int tag, tn, tc, explicit, constructed = 1; - int found_prim = 0, seq_len; - long length; - unsigned char *p; - VALUE value, str, inf_length; - - tn = NUM2INT(ossl_asn1_get_tag(self)); - tc = ossl_asn1_tag_class(self); - inf_length = ossl_asn1_get_infinite_length(self); - if (inf_length == Qtrue) { - VALUE ary, example; - constructed = 2; - if (rb_obj_class(self) == cASN1Sequence || - rb_obj_class(self) == cASN1Set) { - tag = ossl_asn1_default_tag(self); - } - else { /* must be a constructive encoding of a primitive value */ - ary = ossl_asn1_get_value(self); - if (!rb_obj_is_kind_of(ary, rb_cArray)) - ossl_raise(eASN1Error, "Constructive value must be an Array"); - /* Recursively descend until a primitive value is found. - The overall value of the entire constructed encoding - is of the type of the first primitive encoding to be - found. */ - while (!found_prim){ - example = rb_ary_entry(ary, 0); - if (rb_obj_is_kind_of(example, cASN1Primitive)){ - found_prim = 1; - } - else { - /* example is another ASN1Constructive */ - if (!rb_obj_is_kind_of(example, cASN1Constructive)){ - ossl_raise(eASN1Error, "invalid constructed encoding"); - return Qnil; /* dummy */ - } - ary = ossl_asn1_get_value(example); - } - } - tag = ossl_asn1_default_tag(example); - } - } - else { - if (rb_obj_class(self) == cASN1Constructive) - ossl_raise(eASN1Error, "Constructive shall only be used with infinite length"); - tag = ossl_asn1_default_tag(self); - } - explicit = ossl_asn1_is_explicit(self); - value = join_der(ossl_asn1_get_value(self)); - - seq_len = ASN1_object_size(constructed, RSTRING_LENINT(value), tag); - length = ASN1_object_size(constructed, seq_len, tn); - str = rb_str_new(0, length); - p = (unsigned char *)RSTRING_PTR(str); - if(tc == V_ASN1_UNIVERSAL) - ASN1_put_object(&p, constructed, RSTRING_LENINT(value), tn, tc); - else{ - if(explicit){ - ASN1_put_object(&p, constructed, seq_len, tn, tc); - ASN1_put_object(&p, constructed, RSTRING_LENINT(value), tag, V_ASN1_UNIVERSAL); - } - else{ - ASN1_put_object(&p, constructed, RSTRING_LENINT(value), tn, tc); + VALUE ary, str; + long i; + int indef_len; + + indef_len = RTEST(ossl_asn1_get_indefinite_length(self)); + ary = rb_convert_type(ossl_asn1_get_value(self), T_ARRAY, "Array", "to_a"); + str = rb_str_new(NULL, 0); + for (i = 0; i < RARRAY_LEN(ary); i++) { + VALUE item = RARRAY_AREF(ary, i); + + if (indef_len && rb_obj_is_kind_of(item, cASN1EndOfContent)) { + if (i != RARRAY_LEN(ary) - 1) + ossl_raise(eASN1Error, "illegal EOC octets in value"); + + /* + * EOC is not really part of the content, but we required to add one + * at the end in the past. + */ + break; } - } - memcpy(p, RSTRING_PTR(value), RSTRING_LEN(value)); - p += RSTRING_LEN(value); - /* In this case we need an additional EOC (one for the explicit part and - * one for the Constructive itself. The EOC for the Constructive is - * supplied by the user, but that for the "explicit wrapper" must be - * added here. - */ - if (explicit && inf_length == Qtrue) { - ASN1_put_eoc(&p); + item = ossl_to_der_if_possible(item); + StringValue(item); + rb_str_append(str, item); } - ossl_str_adjust(str, p); - return str; + return to_der_internal(self, 1, indef_len, str); } /* * call-seq: * asn1_ary.each { |asn1| block } => asn1_ary * - * Calls block once for each element in +self+, passing that element - * as parameter +asn1+. If no block is given, an enumerator is returned + * Calls the given block once for each element in self, passing that element + * as parameter _asn1_. If no block is given, an enumerator is returned * instead. * * == Example @@ -1300,8 +1225,8 @@ ossl_asn1cons_each(VALUE self) * call-seq: * OpenSSL::ASN1::ObjectId.register(object_id, short_name, long_name) * - * This adds a new ObjectId to the internal tables. Where +object_id+ is the - * numerical form, +short_name+ is the short name, and +long_name+ is the long + * This adds a new ObjectId to the internal tables. Where _object_id_ is the + * numerical form, _short_name_ is the short name, and _long_name_ is the long * name. * * Returns +true+ if successful. Raises an OpenSSL::ASN1::ASN1Error if it fails. @@ -1320,14 +1245,13 @@ ossl_asn1obj_s_register(VALUE self, VALUE oid, VALUE sn, VALUE ln) return Qtrue; } -/* Document-method: OpenSSL::ASN1::ObjectId#sn +/* + * call-seq: + * oid.sn -> string + * oid.short_name -> string * * The short name of the ObjectId, as defined in . */ -/* Document-method: OpenSSL::ASN1::ObjectId#short_name - * - * +short_name+ is an alias to +sn+ - */ static VALUE ossl_asn1obj_get_sn(VALUE self) { @@ -1341,14 +1265,13 @@ ossl_asn1obj_get_sn(VALUE self) return ret; } -/* Document-method: OpenSSL::ASN1::ObjectId#ln +/* + * call-seq: + * oid.ln -> string + * oid.long_name -> string * * The long name of the ObjectId, as defined in . */ -/* Document-method: OpenSSL::ASN1::ObjectId#long_name - * - * +long_name+ is an alias to +ln+ - */ static VALUE ossl_asn1obj_get_ln(VALUE self) { @@ -1362,23 +1285,48 @@ ossl_asn1obj_get_ln(VALUE self) return ret; } -/* Document-method: OpenSSL::ASN1::ObjectId#oid +static VALUE +asn1obj_get_oid_i(VALUE vobj) +{ + ASN1_OBJECT *a1obj = (void *)vobj; + VALUE str; + int len; + + str = rb_usascii_str_new(NULL, 127); + len = OBJ_obj2txt(RSTRING_PTR(str), RSTRING_LENINT(str), a1obj, 1); + if (len <= 0 || len == INT_MAX) + ossl_raise(eASN1Error, "OBJ_obj2txt"); + if (len > RSTRING_LEN(str)) { + /* +1 is for the \0 terminator added by OBJ_obj2txt() */ + rb_str_resize(str, len + 1); + len = OBJ_obj2txt(RSTRING_PTR(str), len + 1, a1obj, 1); + if (len <= 0) + ossl_raise(eASN1Error, "OBJ_obj2txt"); + } + rb_str_set_len(str, len); + return str; +} + +/* + * call-seq: + * oid.oid -> string * - * The object identifier as a +String+, e.g. "1.2.3.4.5" + * Returns a String representing the Object Identifier in the dot notation, + * e.g. "1.2.3.4.5" */ static VALUE ossl_asn1obj_get_oid(VALUE self) { - VALUE val; + VALUE str; ASN1_OBJECT *a1obj; - char buf[128]; + int state; - val = ossl_asn1_get_value(self); - a1obj = obj_to_asn1obj(val); - OBJ_obj2txt(buf, sizeof(buf), a1obj, 1); + a1obj = obj_to_asn1obj(ossl_asn1_get_value(self)); + str = rb_protect(asn1obj_get_oid_i, (VALUE)a1obj, &state); ASN1_OBJECT_free(a1obj); - - return rb_str_new2(buf); + if (state) + rb_jump_tag(state); + return str; } #define OSSL_ASN1_IMPL_FACTORY_METHOD(klass) \ @@ -1431,7 +1379,7 @@ Init_ossl_asn1(void) sivTAG = rb_intern("@tag"); sivTAGGING = rb_intern("@tagging"); sivTAG_CLASS = rb_intern("@tag_class"); - sivINFINITE_LENGTH = rb_intern("@infinite_length"); + sivINDEFINITE_LENGTH = rb_intern("@indefinite_length"); sivUNUSED_BITS = rb_intern("@unused_bits"); /* @@ -1457,24 +1405,21 @@ Init_ossl_asn1(void) * == ASN.1 class hierarchy * * The base class representing ASN.1 structures is ASN1Data. ASN1Data offers - * attributes to read and set the +tag+, the +tag_class+ and finally the - * +value+ of a particular ASN.1 item. Upon parsing, any tagged values + * attributes to read and set the _tag_, the _tag_class_ and finally the + * _value_ of a particular ASN.1 item. Upon parsing, any tagged values * (implicit or explicit) will be represented by ASN1Data instances because * their "real type" can only be determined using out-of-band information * from the ASN.1 type declaration. Since this information is normally * known when encoding a type, all sub-classes of ASN1Data offer an - * additional attribute +tagging+ that allows to encode a value implicitly + * additional attribute _tagging_ that allows to encode a value implicitly * (+:IMPLICIT+) or explicitly (+:EXPLICIT+). * * === Constructive * * Constructive is, as its name implies, the base class for all * constructed encodings, i.e. those that consist of several values, - * opposed to "primitive" encodings with just one single value. - * Primitive values that are encoded with "infinite length" are typically - * constructed (their values come in multiple chunks) and are therefore - * represented by instances of Constructive. The value of an Constructive - * is always an Array. + * opposed to "primitive" encodings with just one single value. The value of + * an Constructive is always an Array. * * ==== ASN1::Set and ASN1::Sequence * @@ -1491,18 +1436,18 @@ Init_ossl_asn1(void) * Please cf. Primitive documentation for details on sub-classes and * their respective mappings of ASN.1 data types to Ruby objects. * - * == Possible values for +tagging+ + * == Possible values for _tagging_ * * When constructing an ASN1Data object the ASN.1 type definition may * require certain elements to be either implicitly or explicitly tagged. - * This can be achieved by setting the +tagging+ attribute manually for + * This can be achieved by setting the _tagging_ attribute manually for * sub-classes of ASN1Data. Use the symbol +:IMPLICIT+ for implicit * tagging and +:EXPLICIT+ if the element requires explicit tagging. * - * == Possible values for +tag_class+ + * == Possible values for _tag_class_ * * It is possible to create arbitrary ASN1Data objects that also support - * a PRIVATE or APPLICATION tag class. Possible values for the +tag_class+ + * a PRIVATE or APPLICATION tag class. Possible values for the _tag_class_ * attribute are: * * +:UNIVERSAL+ (the default for untagged values) * * +:CONTEXT_SPECIFIC+ (the default for tagged values) @@ -1604,9 +1549,9 @@ Init_ossl_asn1(void) * * An implicitly 1-tagged INTEGER value will be parsed as an * ASN1Data with - * * +tag+ equal to 1 - * * +tag_class+ equal to +:CONTEXT_SPECIFIC+ - * * +value+ equal to a +String+ that carries the raw encoding + * * _tag_ equal to 1 + * * _tag_class_ equal to +:CONTEXT_SPECIFIC+ + * * _value_ equal to a String that carries the raw encoding * of the INTEGER. * This implies that a subsequent decoding step is required to * completely decode implicitly tagged values. @@ -1615,9 +1560,9 @@ Init_ossl_asn1(void) * * An explicitly 1-tagged INTEGER value will be parsed as an * ASN1Data with - * * +tag+ equal to 1 - * * +tag_class+ equal to +:CONTEXT_SPECIFIC+ - * * +value+ equal to an +Array+ with one single element, an + * * _tag_ equal to 1 + * * _tag_class_ equal to +:CONTEXT_SPECIFIC+ + * * _value_ equal to an Array with one single element, an * instance of OpenSSL::ASN1::Integer, i.e. the inner element * is the non-tagged primitive value, and the tagging is represented * in the outer ASN1Data @@ -1628,13 +1573,13 @@ Init_ossl_asn1(void) * der = seq.to_der * asn1 = OpenSSL::ASN1.decode(der) * # pp asn1 => #]> @@ -1651,18 +1596,18 @@ Init_ossl_asn1(void) * der = seq.to_der * asn1 = OpenSSL::ASN1.decode(der) * # pp asn1 => # +value+ is always +nil+ - * * OpenSSL::ASN1::Boolean <=> +value+ is a +Boolean+ - * * OpenSSL::ASN1::Integer <=> +value+ is a +Number+ - * * OpenSSL::ASN1::BitString <=> +value+ is a +String+ - * * OpenSSL::ASN1::OctetString <=> +value+ is a +String+ - * * OpenSSL::ASN1::Null <=> +value+ is always +nil+ - * * OpenSSL::ASN1::Object <=> +value+ is a +String+ - * * OpenSSL::ASN1::Enumerated <=> +value+ is a +Number+ - * * OpenSSL::ASN1::UTF8String <=> +value+ is a +String+ - * * OpenSSL::ASN1::NumericString <=> +value+ is a +String+ - * * OpenSSL::ASN1::PrintableString <=> +value+ is a +String+ - * * OpenSSL::ASN1::T61String <=> +value+ is a +String+ - * * OpenSSL::ASN1::VideotexString <=> +value+ is a +String+ - * * OpenSSL::ASN1::IA5String <=> +value+ is a +String+ - * * OpenSSL::ASN1::UTCTime <=> +value+ is a +Time+ - * * OpenSSL::ASN1::GeneralizedTime <=> +value+ is a +Time+ - * * OpenSSL::ASN1::GraphicString <=> +value+ is a +String+ - * * OpenSSL::ASN1::ISO64String <=> +value+ is a +String+ - * * OpenSSL::ASN1::GeneralString <=> +value+ is a +String+ - * * OpenSSL::ASN1::UniversalString <=> +value+ is a +String+ - * * OpenSSL::ASN1::BMPString <=> +value+ is a +String+ + * * OpenSSL::ASN1::EndOfContent <=> _value_ is always +nil+ + * * OpenSSL::ASN1::Boolean <=> _value_ is +true+ or +false+ + * * OpenSSL::ASN1::Integer <=> _value_ is an Integer + * * OpenSSL::ASN1::BitString <=> _value_ is a String + * * OpenSSL::ASN1::OctetString <=> _value_ is a String + * * OpenSSL::ASN1::Null <=> _value_ is always +nil+ + * * OpenSSL::ASN1::Object <=> _value_ is a String + * * OpenSSL::ASN1::Enumerated <=> _value_ is an Integer + * * OpenSSL::ASN1::UTF8String <=> _value_ is a String + * * OpenSSL::ASN1::NumericString <=> _value_ is a String + * * OpenSSL::ASN1::PrintableString <=> _value_ is a String + * * OpenSSL::ASN1::T61String <=> _value_ is a String + * * OpenSSL::ASN1::VideotexString <=> _value_ is a String + * * OpenSSL::ASN1::IA5String <=> _value_ is a String + * * OpenSSL::ASN1::UTCTime <=> _value_ is a Time + * * OpenSSL::ASN1::GeneralizedTime <=> _value_ is a Time + * * OpenSSL::ASN1::GraphicString <=> _value_ is a String + * * OpenSSL::ASN1::ISO64String <=> _value_ is a String + * * OpenSSL::ASN1::GeneralString <=> _value_ is a String + * * OpenSSL::ASN1::UniversalString <=> _value_ is a String + * * OpenSSL::ASN1::BMPString <=> _value_ is a String * * == OpenSSL::ASN1::BitString * * === Additional attributes - * +unused_bits+: if the underlying BIT STRING's - * length is a multiple of 8 then +unused_bits+ is 0. Otherwise - * +unused_bits+ indicates the number of bits that are to be ignored in - * the final octet of the +BitString+'s +value+. + * _unused_bits_: if the underlying BIT STRING's + * length is a multiple of 8 then _unused_bits_ is 0. Otherwise + * _unused_bits_ indicates the number of bits that are to be ignored in + * the final octet of the BitString's _value_. * * == OpenSSL::ASN1::ObjectId * @@ -1753,15 +1700,15 @@ Init_ossl_asn1(void) * parsed ASN1 encodings. * * === Additional attributes - * * +sn+: the short name as defined in . - * * +ln+: the long name as defined in . - * * +oid+: the object identifier as a +String+, e.g. "1.2.3.4.5" - * * +short_name+: alias for +sn+. - * * +long_name+: alias for +ln+. + * * _sn_: the short name as defined in . + * * _ln_: the long name as defined in . + * * _oid_: the object identifier as a String, e.g. "1.2.3.4.5" + * * _short_name_: alias for _sn_. + * * _long_name_: alias for _ln_. * * == Examples * With the Exception of OpenSSL::ASN1::EndOfContent, each Primitive class - * constructor takes at least one parameter, the +value+. + * constructor takes at least one parameter, the _value_. * * === Creating EndOfContent * eoc = OpenSSL::ASN1::EndOfContent.new @@ -1775,19 +1722,20 @@ Init_ossl_asn1(void) /* * May be used as a hint for encoding a value either implicitly or * explicitly by setting it either to +:IMPLICIT+ or to +:EXPLICIT+. - * +tagging+ is not set when a ASN.1 structure is parsed using + * _tagging_ is not set when a ASN.1 structure is parsed using * OpenSSL::ASN1.decode. */ rb_attr(cASN1Primitive, rb_intern("tagging"), 1, 1, Qtrue); + rb_undef_method(cASN1Primitive, "indefinite_length="); rb_undef_method(cASN1Primitive, "infinite_length="); rb_define_method(cASN1Primitive, "initialize", ossl_asn1_initialize, -1); rb_define_method(cASN1Primitive, "to_der", ossl_asn1prim_to_der, 0); /* Document-class: OpenSSL::ASN1::Constructive * - * The parent class for all constructed encodings. The +value+ attribute - * of a Constructive is always an +Array+. Attributes are the same as - * for ASN1Data, with the addition of +tagging+. + * The parent class for all constructed encodings. The _value_ attribute + * of a Constructive is always an Array. Attributes are the same as + * for ASN1Data, with the addition of _tagging_. * * == SET and SEQUENCE * @@ -1809,48 +1757,13 @@ Init_ossl_asn1(void) * int = OpenSSL::ASN1::Integer.new(1) * str = OpenSSL::ASN1::PrintableString.new('abc') * set = OpenSSL::ASN1::Set.new( [ int, str ] ) - * - * == Infinite length primitive values - * - * The only case where Constructive is used directly is for infinite - * length encodings of primitive values. These encodings are always - * constructed, with the contents of the +value+ +Array+ being either - * UNIVERSAL non-infinite length partial encodings of the actual value - * or again constructive encodings with infinite length (i.e. infinite - * length primitive encodings may be constructed recursively with another - * infinite length value within an already infinite length value). Each - * partial encoding must be of the same UNIVERSAL type as the overall - * encoding. The value of the overall encoding consists of the - * concatenation of each partial encoding taken in sequence. The +value+ - * array of the outer infinite length value must end with a - * OpenSSL::ASN1::EndOfContent instance. - * - * Please note that it is not possible to encode Constructive without - * the +infinite_length+ attribute being set to +true+, use - * OpenSSL::ASN1::Sequence or OpenSSL::ASN1::Set in these cases instead. - * - * === Example - Infinite length OCTET STRING - * partial1 = OpenSSL::ASN1::OctetString.new("\x01") - * partial2 = OpenSSL::ASN1::OctetString.new("\x02") - * inf_octets = OpenSSL::ASN1::Constructive.new( [ partial1, - * partial2, - * OpenSSL::ASN1::EndOfContent.new ], - * OpenSSL::ASN1::OCTET_STRING, - * nil, - * :UNIVERSAL ) - * # The real value of inf_octets is "\x01\x02", i.e. the concatenation - * # of partial1 and partial2 - * inf_octets.infinite_length = true - * der = inf_octets.to_der - * asn1 = OpenSSL::ASN1.decode(der) - * puts asn1.infinite_length # => true */ cASN1Constructive = rb_define_class_under(mASN1,"Constructive", cASN1Data); rb_include_module(cASN1Constructive, rb_mEnumerable); /* * May be used as a hint for encoding a value either implicitly or * explicitly by setting it either to +:IMPLICIT+ or to +:EXPLICIT+. - * +tagging+ is not set when a ASN.1 structure is parsed using + * _tagging_ is not set when a ASN.1 structure is parsed using * OpenSSL::ASN1.decode. */ rb_attr(cASN1Constructive, rb_intern("tagging"), 1, 1, Qtrue); @@ -1907,6 +1820,7 @@ do{\ rb_attr(cASN1BitString, rb_intern("unused_bits"), 1, 1, 0); rb_define_method(cASN1EndOfContent, "initialize", ossl_asn1eoc_initialize, 0); + rb_define_method(cASN1EndOfContent, "to_der", ossl_asn1eoc_to_der, 0); class_tag_map = rb_hash_new(); rb_hash_aset(class_tag_map, cASN1EndOfContent, INT2NUM(V_ASN1_EOC)); diff --git a/ext/openssl/ossl_asn1.h b/ext/openssl/ossl_asn1.h index d6a170c86c..939a96ce74 100644 --- a/ext/openssl/ossl_asn1.h +++ b/ext/openssl/ossl_asn1.h @@ -14,15 +14,11 @@ * ASN1_DATE conversions */ VALUE asn1time_to_time(const ASN1_TIME *); -#if defined(HAVE_ASN1_TIME_ADJ) /* Splits VALUE to seconds and offset days. VALUE is typically a Time or an * Integer. This is used when updating ASN1_*TIME with ASN1_TIME_adj() or * X509_time_adj_ex(). We can't use ASN1_TIME_set() and X509_time_adj() because * they have the Year 2038 issue on sizeof(time_t) == 4 environment */ void ossl_time_split(VALUE, time_t *, int *); -#else -time_t time_to_time_t(VALUE); -#endif /* * ASN1_STRING conversions diff --git a/ext/openssl/ossl_bio.c b/ext/openssl/ossl_bio.c index 8fa0b6966d..42833d901a 100644 --- a/ext/openssl/ossl_bio.c +++ b/ext/openssl/ossl_bio.c @@ -26,32 +26,17 @@ ossl_obj2bio(volatile VALUE *pobj) } VALUE -ossl_membio2str0(BIO *bio) +ossl_membio2str(BIO *bio) { VALUE ret; + int state; BUF_MEM *buf; BIO_get_mem_ptr(bio, &buf); - ret = rb_str_new(buf->data, buf->length); - - return ret; -} - -VALUE -ossl_protect_membio2str(BIO *bio, int *status) -{ - return rb_protect((VALUE (*)(VALUE))ossl_membio2str0, (VALUE)bio, status); -} - -VALUE -ossl_membio2str(BIO *bio) -{ - VALUE ret; - int status = 0; - - ret = ossl_protect_membio2str(bio, &status); + ret = ossl_str_new(buf->data, buf->length, &state); BIO_free(bio); - if(status) rb_jump_tag(status); + if (state) + rb_jump_tag(state); return ret; } diff --git a/ext/openssl/ossl_bio.h b/ext/openssl/ossl_bio.h index 2c3d952b38..da68c5e5a2 100644 --- a/ext/openssl/ossl_bio.h +++ b/ext/openssl/ossl_bio.h @@ -11,8 +11,6 @@ #define _OSSL_BIO_H_ BIO *ossl_obj2bio(volatile VALUE *); -VALUE ossl_membio2str0(BIO*); VALUE ossl_membio2str(BIO*); -VALUE ossl_protect_membio2str(BIO*,int*); #endif diff --git a/ext/openssl/ossl_bn.c b/ext/openssl/ossl_bn.c index aa0f2c605f..94ef6fd6f7 100644 --- a/ext/openssl/ossl_bn.c +++ b/ext/openssl/ossl_bn.c @@ -26,11 +26,6 @@ } \ } while (0) -#define SafeGetBN(obj, bn) do { \ - OSSL_Check_Kind((obj), cBN); \ - GetBN((obj), (bn)); \ -} while (0) - static void ossl_bn_free(void *ptr) { @@ -176,8 +171,7 @@ ossl_bn_alloc(VALUE klass) return obj; } -/* Document-method: OpenSSL::BN.new - * +/* * call-seq: * OpenSSL::BN.new => aBN * OpenSSL::BN.new(bn) => aBN @@ -185,7 +179,7 @@ ossl_bn_alloc(VALUE klass) * OpenSSL::BN.new(string) => aBN * OpenSSL::BN.new(string, 0 | 2 | 10 | 16) => aBN * - * Construct a new OpenSSL BigNum object. + * Construct a new OpenSSL BIGNUM object. */ static VALUE ossl_bn_initialize(int argc, VALUE *argv, VALUE self) @@ -250,7 +244,7 @@ ossl_bn_initialize(int argc, VALUE *argv, VALUE self) * bn.to_s(base) => string * * === Parameters - * * +base+ - integer + * * _base_ - Integer * Valid values: * * 0 - MPI * * 2 - binary @@ -377,6 +371,21 @@ BIGNUM_BOOL1(is_one) */ BIGNUM_BOOL1(is_odd) +/* + * call-seq: + * bn.negative? => true | false + */ +static VALUE +ossl_bn_is_negative(VALUE self) +{ + BIGNUM *bn; + + GetBN(self, bn); + if (BN_is_zero(bn)) + return Qfalse; + return BN_is_negative(bn) ? Qtrue : Qfalse; +} + #define BIGNUM_1c(func) \ static VALUE \ ossl_bn_##func(VALUE self) \ @@ -498,7 +507,6 @@ BIGNUM_2c(mod_sqr) BIGNUM_2c(mod_inverse) /* - * Document-method: OpenSSL::BN#/ * call-seq: * bn1 / bn2 => [result, remainder] * @@ -614,12 +622,11 @@ BIGNUM_BIT(clear_bit) */ BIGNUM_BIT(mask_bits) -/* Document-method: OpenSSL::BN#bit_set? +/* * call-seq: * bn.bit_set?(bit) => true | false * - * Returns boolean of whether +bit+ is set. - * Bitwise operations for openssl BIGNUMs. + * Tests bit _bit_ in _bn_ and returns +true+ if set, +false+ if not set. */ static VALUE ossl_bn_is_bit_set(VALUE self, VALUE bit) @@ -774,15 +781,15 @@ BIGNUM_RAND_RANGE(pseudo_rand) * call-seq: * BN.generate_prime(bits, [, safe [, add [, rem]]]) => bn * - * Generates a random prime number of bit length +bits+. If +safe+ is true, - * generates a safe prime. If +add+ is specified, generates a prime that + * Generates a random prime number of bit length _bits_. If _safe_ is set to + * +true+, generates a safe prime. If _add_ is specified, generates a prime that * fulfills condition p % add = rem. * * === Parameters - * * +bits+ - integer - * * +safe+ - boolean - * * +add+ - BN - * * +rem+ - BN + * * _bits_ - integer + * * _safe_ - boolean + * * _add_ - BN + * * _rem_ - BN */ static VALUE ossl_bn_s_generate_prime(int argc, VALUE *argv, VALUE klass) @@ -856,6 +863,37 @@ ossl_bn_copy(VALUE self, VALUE other) return self; } +/* + * call-seq: + * +bn -> aBN + */ +static VALUE +ossl_bn_uplus(VALUE self) +{ + return self; +} + +/* + * call-seq: + * -bn -> aBN + */ +static VALUE +ossl_bn_uminus(VALUE self) +{ + VALUE obj; + BIGNUM *bn1, *bn2; + + GetBN(self, bn1); + obj = NewBN(cBN); + bn2 = BN_dup(bn1); + if (!bn2) + ossl_raise(eBNError, "BN_dup"); + SetBN(obj, bn2); + BN_set_negative(bn2, !BN_is_negative(bn2)); + + return obj; +} + #define BIGNUM_CMP(func) \ static VALUE \ ossl_bn_##func(VALUE self, VALUE other) \ @@ -888,7 +926,7 @@ BIGNUM_CMP(ucmp) * call-seq: * bn == obj => true or false * - * Returns +true+ only if +obj+ has the same value as +bn+. Contrast this + * Returns +true+ only if _obj_ has the same value as _bn_. Contrast this * with OpenSSL::BN#eql?, which requires obj to be OpenSSL::BN. */ static VALUE @@ -913,7 +951,7 @@ ossl_bn_eq(VALUE self, VALUE other) * bn.eql?(obj) => true or false * * Returns true only if obj is a - * OpenSSL::BN with the same value as big. Contrast this + * OpenSSL::BN with the same value as bn. Contrast this * with OpenSSL::BN#==, which performs type conversions. */ static VALUE @@ -964,12 +1002,12 @@ ossl_bn_hash(VALUE self) * bn.prime? => true | false * bn.prime?(checks) => true | false * - * Performs a Miller-Rabin probabilistic primality test with +checks+ - * iterations. If +nchecks+ is not specified, a number of iterations is used + * Performs a Miller-Rabin probabilistic primality test with _checks_ + * iterations. If _checks_ is not specified, a number of iterations is used * that yields a false positive rate of at most 2^-80 for random input. * * === Parameters - * * +checks+ - integer + * * _checks_ - integer */ static VALUE ossl_bn_is_prime(int argc, VALUE *argv, VALUE self) @@ -1004,8 +1042,8 @@ ossl_bn_is_prime(int argc, VALUE *argv, VALUE self) * first attempts trial divisions with some small primes. * * === Parameters - * * +checks+ - integer - * * +trial_div+ - boolean + * * _checks_ - integer + * * _trial_div_ - boolean */ static VALUE ossl_bn_is_prime_fasttest(int argc, VALUE *argv, VALUE self) @@ -1059,7 +1097,7 @@ Init_ossl_bn(void) rb_define_alloc_func(cBN, ossl_bn_alloc); rb_define_method(cBN, "initialize", ossl_bn_initialize, -1); - rb_define_copy_func(cBN, ossl_bn_copy); + rb_define_method(cBN, "initialize_copy", ossl_bn_copy, 1); rb_define_method(cBN, "copy", ossl_bn_copy, 1); /* swap (=coerce?) */ @@ -1068,6 +1106,9 @@ Init_ossl_bn(void) rb_define_method(cBN, "num_bits", ossl_bn_num_bits, 0); /* num_bits_word */ + rb_define_method(cBN, "+@", ossl_bn_uplus, 0); + rb_define_method(cBN, "-@", ossl_bn_uminus, 0); + rb_define_method(cBN, "+", ossl_bn_add, 1); rb_define_method(cBN, "-", ossl_bn_sub, 1); rb_define_method(cBN, "*", ossl_bn_mul, 1); @@ -1101,6 +1142,7 @@ Init_ossl_bn(void) rb_define_method(cBN, "one?", ossl_bn_is_one, 0); /* is_word */ rb_define_method(cBN, "odd?", ossl_bn_is_odd, 0); + rb_define_method(cBN, "negative?", ossl_bn_is_negative, 0); /* zero * one diff --git a/ext/openssl/ossl_cipher.c b/ext/openssl/ossl_cipher.c index c2f0927a75..bfa76c1aab 100644 --- a/ext/openssl/ossl_cipher.c +++ b/ext/openssl/ossl_cipher.c @@ -26,10 +26,6 @@ ossl_raise(rb_eRuntimeError, "Cipher not initialized!"); \ } \ } while (0) -#define SafeGetCipher(obj, ctx) do { \ - OSSL_Check_Kind((obj), cCipher); \ - GetCipher((obj), (ctx)); \ -} while (0) /* * Classes @@ -53,7 +49,7 @@ static const rb_data_type_t ossl_cipher_type = { * PUBLIC */ const EVP_CIPHER * -GetCipherPtr(VALUE obj) +ossl_evp_get_cipherbyname(VALUE obj) { if (rb_obj_is_kind_of(obj, cCipher)) { EVP_CIPHER_CTX *ctx; @@ -108,7 +104,7 @@ ossl_cipher_alloc(VALUE klass) * call-seq: * Cipher.new(string) -> cipher * - * The string must contain a valid cipher name like "AES-128-CBC" or "3DES". + * The string must be a valid cipher name like "AES-128-CBC" or "3DES". * * A list of cipher names is available by calling OpenSSL::Cipher.ciphers. */ @@ -146,7 +142,7 @@ ossl_cipher_copy(VALUE self, VALUE other) if (!ctx1) { AllocCipher(self, ctx1); } - SafeGetCipher(other, ctx2); + GetCipher(other, ctx2); if (EVP_CIPHER_CTX_copy(ctx1, ctx2) != 1) ossl_raise(eCipherError, NULL); @@ -296,9 +292,9 @@ ossl_cipher_decrypt(int argc, VALUE *argv, VALUE self) * OpenSSL::PKCS5 instead. * * === Parameters - * * +salt+ must be an 8 byte string if provided. - * * +iterations+ is an integer with a default of 2048. - * * +digest+ is a Digest object that defaults to 'MD5' + * * _salt_ must be an 8 byte string if provided. + * * _iterations_ is an integer with a default of 2048. + * * _digest_ is a Digest object that defaults to 'MD5' * * A minimum of 1000 iterations is recommended. * @@ -321,7 +317,7 @@ ossl_cipher_pkcs5_keyivgen(int argc, VALUE *argv, VALUE self) salt = (unsigned char *)RSTRING_PTR(vsalt); } iter = NIL_P(viter) ? 2048 : NUM2INT(viter); - digest = NIL_P(vdigest) ? EVP_md5() : GetDigestPtr(vdigest); + digest = NIL_P(vdigest) ? EVP_md5() : ossl_evp_get_digestbyname(vdigest); GetCipher(self, ctx); EVP_BytesToKey(EVP_CIPHER_CTX_cipher(ctx), digest, salt, (unsigned char *)RSTRING_PTR(vpass), RSTRING_LENINT(vpass), iter, key, iv); @@ -365,12 +361,12 @@ ossl_cipher_update_long(EVP_CIPHER_CTX *ctx, unsigned char *out, long *out_len_p * cipher.update(data [, buffer]) -> string or buffer * * Encrypts data in a streaming fashion. Hand consecutive blocks of data - * to the +update+ method in order to encrypt it. Returns the encrypted + * to the #update method in order to encrypt it. Returns the encrypted * data chunk. When done, the output of Cipher#final should be additionally * added to the result. * - * If +buffer+ is given, the encryption/decryption result will be written to - * it. +buffer+ will be resized automatically. + * If _buffer_ is given, the encryption/decryption result will be written to + * it. _buffer_ will be resized automatically. */ static VALUE ossl_cipher_update(int argc, VALUE *argv, VALUE self) @@ -512,10 +508,8 @@ ossl_cipher_set_iv(VALUE self, VALUE iv) StringValue(iv); GetCipher(self, ctx); -#if defined(HAVE_AUTHENTICATED_ENCRYPTION) if (EVP_CIPHER_CTX_flags(ctx) & EVP_CIPH_FLAG_AEAD_CIPHER) iv_len = (int)(VALUE)EVP_CIPHER_CTX_get_app_data(ctx); -#endif if (!iv_len) iv_len = EVP_CIPHER_CTX_iv_length(ctx); if (RSTRING_LEN(iv) != iv_len) @@ -541,14 +535,9 @@ ossl_cipher_is_authenticated(VALUE self) GetCipher(self, ctx); -#if defined(HAVE_AUTHENTICATED_ENCRYPTION) return (EVP_CIPHER_CTX_flags(ctx) & EVP_CIPH_FLAG_AEAD_CIPHER) ? Qtrue : Qfalse; -#else - return Qfalse; -#endif } -#ifdef HAVE_AUTHENTICATED_ENCRYPTION /* * call-seq: * cipher.auth_data = string -> string @@ -594,8 +583,8 @@ ossl_cipher_set_auth_data(VALUE self, VALUE data) * Gets the authentication tag generated by Authenticated Encryption Cipher * modes (GCM for example). This tag may be stored along with the ciphertext, * then set on the decryption cipher to authenticate the contents of the - * ciphertext against changes. If the optional integer parameter +tag_len+ is - * given, the returned tag will be +tag_len+ bytes long. If the parameter is + * ciphertext against changes. If the optional integer parameter _tag_len_ is + * given, the returned tag will be _tag_len_ bytes long. If the parameter is * omitted, the default length of 16 bytes or the length previously set by * #auth_tag_len= will be used. For maximum security, the longest possible * should be chosen. @@ -631,13 +620,11 @@ ossl_cipher_get_auth_tag(int argc, VALUE *argv, VALUE self) * call-seq: * cipher.auth_tag = string -> string * - * Sets the authentication tag to verify the contents of the - * ciphertext. The tag must be set after calling Cipher#decrypt, - * Cipher#key= and Cipher#iv=, but before assigning the associated - * authenticated data using Cipher#auth_data= and of course, before - * decrypting any of the ciphertext. After all decryption is - * performed, the tag is verified automatically in the call to - * Cipher#final. + * Sets the authentication tag to verify the integrity of the ciphertext. + * This can be called only when the cipher supports AE. The tag must be set + * after calling Cipher#decrypt, Cipher#key= and Cipher#iv=, but before + * calling Cipher#final. After all decryption is performed, the tag is + * verified automatically in the call to Cipher#final. * * For OCB mode, the tag length must be supplied with #auth_tag_len= * beforehand. @@ -722,13 +709,6 @@ ossl_cipher_set_iv_length(VALUE self, VALUE iv_length) return iv_length; } -#else -#define ossl_cipher_set_auth_data rb_f_notimplement -#define ossl_cipher_get_auth_tag rb_f_notimplement -#define ossl_cipher_set_auth_tag rb_f_notimplement -#define ossl_cipher_set_auth_tag_len rb_f_notimplement -#define ossl_cipher_set_iv_length rb_f_notimplement -#endif /* * call-seq: @@ -806,10 +786,8 @@ ossl_cipher_iv_length(VALUE self) int len = 0; GetCipher(self, ctx); -#if defined(HAVE_AUTHENTICATED_ENCRYPTION) if (EVP_CIPHER_CTX_flags(ctx) & EVP_CIPH_FLAG_AEAD_CIPHER) len = (int)(VALUE)EVP_CIPHER_CTX_get_app_data(ctx); -#endif if (!len) len = EVP_CIPHER_CTX_iv_length(ctx); @@ -1020,9 +998,9 @@ Init_ossl_cipher(void) * encryption and later decryption, the OpenSSL library still requires a * value to be set - "" may be used in case none is available. * - * An example using the GCM (Galois/Counter Mode). You have 16 bytes +key+, - * 12 bytes (96 bits) +nonce+ and the associated data +auth_data+. Be sure - * not to reuse the +key+ and +nonce+ pair. Reusing an nonce ruins the + * An example using the GCM (Galois/Counter Mode). You have 16 bytes _key_, + * 12 bytes (96 bits) _nonce_ and the associated data _auth_data_. Be sure + * not to reuse the _key_ and _nonce_ pair. Reusing an nonce ruins the * security guarantees of GCM mode. * * cipher = OpenSSL::Cipher::AES.new(128, :GCM).encrypt @@ -1033,8 +1011,8 @@ Init_ossl_cipher(void) * encrypted = cipher.update(data) + cipher.final * tag = cipher.auth_tag # produces 16 bytes tag by default * - * Now you are the receiver. You know the +key+ and have received +nonce+, - * +auth_data+, +encrypted+ and +tag+ through an untrusted network. Note + * Now you are the receiver. You know the _key_ and have received _nonce_, + * _auth_data_, _encrypted_ and _tag_ through an untrusted network. Note * that GCM accepts an arbitrary length tag between 1 and 16 bytes. You may * additionally need to check that the received tag has the correct length, * or you allow attackers to forge a valid single byte tag for the tampered @@ -1055,7 +1033,7 @@ Init_ossl_cipher(void) eCipherError = rb_define_class_under(cCipher, "CipherError", eOSSLError); rb_define_alloc_func(cCipher, ossl_cipher_alloc); - rb_define_copy_func(cCipher, ossl_cipher_copy); + rb_define_method(cCipher, "initialize_copy", ossl_cipher_copy, 1); rb_define_module_function(cCipher, "ciphers", ossl_s_ciphers, 0); rb_define_method(cCipher, "initialize", ossl_cipher_initialize, 1); rb_define_method(cCipher, "reset", ossl_cipher_reset, 0); diff --git a/ext/openssl/ossl_cipher.h b/ext/openssl/ossl_cipher.h index c444089fc2..2392d41c6a 100644 --- a/ext/openssl/ossl_cipher.h +++ b/ext/openssl/ossl_cipher.h @@ -13,7 +13,7 @@ extern VALUE cCipher; extern VALUE eCipherError; -const EVP_CIPHER *GetCipherPtr(VALUE); +const EVP_CIPHER *ossl_evp_get_cipherbyname(VALUE); VALUE ossl_cipher_new(const EVP_CIPHER *); void Init_ossl_cipher(void); diff --git a/ext/openssl/ossl_digest.c b/ext/openssl/ossl_digest.c index fdafda0074..112ce33647 100644 --- a/ext/openssl/ossl_digest.c +++ b/ext/openssl/ossl_digest.c @@ -15,10 +15,6 @@ ossl_raise(rb_eRuntimeError, "Digest CTX wasn't initialized!"); \ } \ } while (0) -#define SafeGetDigest(obj, ctx) do { \ - OSSL_Check_Kind((obj), cDigest); \ - GetDigest((obj), (ctx)); \ -} while (0) /* * Classes @@ -46,7 +42,7 @@ static const rb_data_type_t ossl_digest_type = { * Public */ const EVP_MD * -GetDigestPtr(VALUE obj) +ossl_evp_get_digestbyname(VALUE obj) { const EVP_MD *md; ASN1_OBJECT *oid = NULL; @@ -65,7 +61,7 @@ GetDigestPtr(VALUE obj) } else { EVP_MD_CTX *ctx; - SafeGetDigest(obj, ctx); + GetDigest(obj, ctx); md = EVP_MD_CTX_md(ctx); } @@ -106,15 +102,15 @@ VALUE ossl_digest_update(VALUE, VALUE); * call-seq: * Digest.new(string [, data]) -> Digest * - * Creates a Digest instance based on +string+, which is either the ln + * Creates a Digest instance based on _string_, which is either the ln * (long name) or sn (short name) of a supported digest algorithm. * - * If +data+ (a +String+) is given, it is used as the initial input to the + * If _data_ (a String) is given, it is used as the initial input to the * Digest instance, i.e. * * digest = OpenSSL::Digest.new('sha256', 'digestdata') * - * is equal to + * is equivalent to * * digest = OpenSSL::Digest.new('sha256') * digest.update('digestdata') @@ -127,7 +123,7 @@ ossl_digest_initialize(int argc, VALUE *argv, VALUE self) VALUE type, data; rb_scan_args(argc, argv, "11", &type, &data); - md = GetDigestPtr(type); + md = ossl_evp_get_digestbyname(type); if (!NIL_P(data)) StringValue(data); TypedData_Get_Struct(self, EVP_MD_CTX, &ossl_digest_type, ctx); @@ -158,7 +154,7 @@ ossl_digest_copy(VALUE self, VALUE other) if (!ctx1) ossl_raise(eDigestError, "EVP_MD_CTX_new"); } - SafeGetDigest(other, ctx2); + GetDigest(other, ctx2); if (!EVP_MD_CTX_copy(ctx1, ctx2)) { ossl_raise(eDigestError, NULL); @@ -448,7 +444,7 @@ Init_ossl_digest(void) rb_define_alloc_func(cDigest, ossl_digest_alloc); rb_define_method(cDigest, "initialize", ossl_digest_initialize, -1); - rb_define_copy_func(cDigest, ossl_digest_copy); + rb_define_method(cDigest, "initialize_copy", ossl_digest_copy, 1); rb_define_method(cDigest, "reset", ossl_digest_reset, 0); rb_define_method(cDigest, "update", ossl_digest_update, 1); rb_define_alias(cDigest, "<<", "update"); diff --git a/ext/openssl/ossl_digest.h b/ext/openssl/ossl_digest.h index 512f7d3a39..50bf5666a3 100644 --- a/ext/openssl/ossl_digest.h +++ b/ext/openssl/ossl_digest.h @@ -13,7 +13,7 @@ extern VALUE cDigest; extern VALUE eDigestError; -const EVP_MD *GetDigestPtr(VALUE); +const EVP_MD *ossl_evp_get_digestbyname(VALUE); VALUE ossl_digest_new(const EVP_MD *); void Init_ossl_digest(void); diff --git a/ext/openssl/ossl_engine.c b/ext/openssl/ossl_engine.c index e840bfd92c..d69b5dcac5 100644 --- a/ext/openssl/ossl_engine.c +++ b/ext/openssl/ossl_engine.c @@ -25,10 +25,6 @@ ossl_raise(rb_eRuntimeError, "ENGINE wasn't initialized."); \ } \ } while (0) -#define SafeGetEngine(obj, engine) do { \ - OSSL_Check_Kind((obj), cEngine); \ - GetPKCS7((obj), (engine)); \ -} while (0) /* * Classes @@ -72,14 +68,13 @@ static const rb_data_type_t ossl_engine_type = { 0, 0, RUBY_TYPED_FREE_IMMEDIATELY, }; -/* Document-method: OpenSSL::Engine.load - * +/* * call-seq: - * load(enginename = nil) + * OpenSSL::Engine.load(name = nil) * - * This method loads engines. If +name+ is nil, then all builtin engines are - * loaded. Otherwise, the given +name+, as a string, is loaded if available to - * your runtime, and returns true. If +name+ is not found, then nil is + * This method loads engines. If _name_ is nil, then all builtin engines are + * loaded. Otherwise, the given _name_, as a String, is loaded if available to + * your runtime, and returns true. If _name_ is not found, then nil is * returned. * */ @@ -153,9 +148,9 @@ ossl_engine_s_load(int argc, VALUE *argv, VALUE klass) #endif /* HAVE_ENGINE_LOAD_BUILTIN_ENGINES */ } -/* Document-method: OpenSSL::Engine.cleanup +/* * call-seq: - * OpenSSL::Engine.cleanup + * OpenSSL::Engine.cleanup * * It is only necessary to run cleanup when engines are loaded via * OpenSSL::Engine.load. However, running cleanup before exit is recommended. @@ -169,7 +164,9 @@ ossl_engine_s_cleanup(VALUE self) return Qnil; } -/* Document-method: OpenSSL::Engine.engines +/* + * call-seq: + * OpenSSL::Engine.engines -> [engine, ...] * * Returns an array of currently loaded engines. */ @@ -193,17 +190,16 @@ ossl_engine_s_engines(VALUE klass) return ary; } -/* Document-method: OpenSSL::Engine.by_id - * +/* * call-seq: - * by_id(name) -> engine + * OpenSSL::Engine.by_id(name) -> engine * - * Fetch the engine as specified by the +id+ String + * Fetches the engine as specified by the _id_ String. * * OpenSSL::Engine.by_id("openssl") * => # * - * See OpenSSL::Engine.engines for the currently loaded engines + * See OpenSSL::Engine.engines for the currently loaded engines. */ static VALUE ossl_engine_s_by_id(VALUE klass, VALUE id) @@ -227,9 +223,11 @@ ossl_engine_s_by_id(VALUE klass, VALUE id) return obj; } -/* Document-method: OpenSSL::Engine#id +/* + * call-seq: + * engine.id -> string * - * Get the id for this engine + * Gets the id for this engine. * * OpenSSL::Engine.load * OpenSSL::Engine.engines #=> [#, ...] @@ -244,9 +242,11 @@ ossl_engine_get_id(VALUE self) return rb_str_new2(ENGINE_get_id(e)); } -/* Document-method: OpenSSL::Engine#name +/* + * call-seq: + * engine.name -> string * - * Get the descriptive name for this engine + * Get the descriptive name for this engine. * * OpenSSL::Engine.load * OpenSSL::Engine.engines #=> [#, ...] @@ -262,7 +262,9 @@ ossl_engine_get_name(VALUE self) return rb_str_new2(ENGINE_get_name(e)); } -/* Document-method: OpenSSL::Engine#finish +/* + * call-seq: + * engine.finish -> nil * * Releases all internal structural references for this engine. * @@ -279,13 +281,12 @@ ossl_engine_finish(VALUE self) return Qnil; } -/* Document-method: OpenSSL::Engine#cipher - * +/* * call-seq: * engine.cipher(name) -> OpenSSL::Cipher * - * This returns an OpenSSL::Cipher by +name+, if it is available in this - * engine. + * Returns a new instance of OpenSSL::Cipher by _name_, if it is available in + * this engine. * * An EngineError will be raised if the cipher is unavailable. * @@ -312,12 +313,11 @@ ossl_engine_get_cipher(VALUE self, VALUE name) return ossl_cipher_new(ciph); } -/* Document-method: OpenSSL::Engine#digest - * +/* * call-seq: * engine.digest(name) -> OpenSSL::Digest * - * This returns an OpenSSL::Digest by +name+. + * Returns a new instance of OpenSSL::Digest by _name_. * * Will raise an EngineError if the digest is unavailable. * @@ -345,12 +345,11 @@ ossl_engine_get_digest(VALUE self, VALUE name) return ossl_digest_new(md); } -/* Document-method: OpenSSL::Engine#load_private_key - * +/* * call-seq: * engine.load_private_key(id = nil, data = nil) -> OpenSSL::PKey * - * Loads the given private key by +id+ and +data+. + * Loads the given private key identified by _id_ and _data_. * * An EngineError is raised of the OpenSSL::PKey is unavailable. * @@ -375,12 +374,11 @@ ossl_engine_load_privkey(int argc, VALUE *argv, VALUE self) return obj; } -/* Document-method: OpenSSL::Engine#load_public_key - * +/* * call-seq: * engine.load_public_key(id = nil, data = nil) -> OpenSSL::PKey * - * Loads the given private key by +id+ and +data+. + * Loads the given public key identified by _id_ and _data_. * * An EngineError is raised of the OpenSSL::PKey is unavailable. * @@ -403,16 +401,15 @@ ossl_engine_load_pubkey(int argc, VALUE *argv, VALUE self) return ossl_pkey_new(pkey); } -/* Document-method: OpenSSL::Engine#set_default - * +/* * call-seq: * engine.set_default(flag) * - * Set the defaults for this engine with the given +flag+. + * Set the defaults for this engine with the given _flag_. * * These flags are used to control combinations of algorithm methods. * - * +flag+ can be one of the following, other flags are available depending on + * _flag_ can be one of the following, other flags are available depending on * your OS. * * [All flags] 0xFFFF @@ -432,14 +429,13 @@ ossl_engine_set_default(VALUE self, VALUE flag) return Qtrue; } -/* Document-method: OpenSSL::Engine#ctrl_cmd - * +/* * call-seq: * engine.ctrl_cmd(command, value = nil) -> engine * - * Send the given +command+ to this engine. + * Sends the given _command_ to this engine. * - * Raises an EngineError if the +command+ fails. + * Raises an EngineError if the command fails. */ static VALUE ossl_engine_ctrl_cmd(int argc, VALUE *argv, VALUE self) @@ -469,7 +465,9 @@ ossl_engine_cmd_flag_to_name(int flag) } } -/* Document-method: OpenSSL::Engine#cmds +/* + * call-seq: + * engine.cmds -> [["name", "description", "flags"], ...] * * Returns an array of command definitions for the current engine */ @@ -495,9 +493,11 @@ ossl_engine_get_cmds(VALUE self) return ary; } -/* Document-method: OpenSSL::Engine#inspect +/* + * call-seq: + * engine.inspect -> string * - * Pretty print this engine + * Pretty prints this engine. */ static VALUE ossl_engine_inspect(VALUE self) diff --git a/ext/openssl/ossl_hmac.c b/ext/openssl/ossl_hmac.c index 270979ed92..564dcab522 100644 --- a/ext/openssl/ossl_hmac.c +++ b/ext/openssl/ossl_hmac.c @@ -19,10 +19,6 @@ ossl_raise(rb_eRuntimeError, "HMAC wasn't initialized"); \ } \ } while (0) -#define SafeGetHMAC(obj, ctx) do { \ - OSSL_Check_Kind((obj), cHMAC); \ - GetHMAC((obj), (ctx)); \ -} while (0) /* * Classes @@ -110,7 +106,7 @@ ossl_hmac_initialize(VALUE self, VALUE key, VALUE digest) StringValue(key); GetHMAC(self, ctx); HMAC_Init_ex(ctx, RSTRING_PTR(key), RSTRING_LENINT(key), - GetDigestPtr(digest), NULL); + ossl_evp_get_digestbyname(digest), NULL); return self; } @@ -124,7 +120,7 @@ ossl_hmac_copy(VALUE self, VALUE other) if (self == other) return self; GetHMAC(self, ctx1); - SafeGetHMAC(other, ctx2); + GetHMAC(other, ctx2); if (!HMAC_CTX_copy(ctx1, ctx2)) ossl_raise(eHMACError, "HMAC_CTX_copy"); @@ -135,7 +131,7 @@ ossl_hmac_copy(VALUE self, VALUE other) * call-seq: * hmac.update(string) -> self * - * Returns +self+ updated with the message to be authenticated. + * Returns _hmac_ updated with the message to be authenticated. * Can be called repeatedly with chunks of the message. * * === Example @@ -234,7 +230,7 @@ ossl_hmac_hexdigest(VALUE self) * call-seq: * hmac.reset -> self * - * Returns +self+ as it was when it was first initialized, with all processed + * Returns _hmac_ as it was when it was first initialized, with all processed * data cleared from it. * * === Example @@ -264,16 +260,16 @@ ossl_hmac_reset(VALUE self) * call-seq: * HMAC.digest(digest, key, data) -> aString * - * Returns the authentication code as a binary string. The +digest+ parameter - * must be an instance of OpenSSL::Digest. + * Returns the authentication code as a binary string. The _digest_ parameter + * specifies the digest algorithm to use. This may be a String representing + * the algorithm name or an instance of OpenSSL::Digest. * * === Example * * key = 'key' * data = 'The quick brown fox jumps over the lazy dog' - * digest = OpenSSL::Digest.new('sha1') * - * hmac = OpenSSL::HMAC.digest(digest, key, data) + * hmac = OpenSSL::HMAC.digest('sha1', key, data) * #=> "\xDE|\x9B\x85\xB8\xB7\x8A\xA6\xBC\x8Az6\xF7\n\x90p\x1C\x9D\xB4\xD9" * */ @@ -285,8 +281,9 @@ ossl_hmac_s_digest(VALUE klass, VALUE digest, VALUE key, VALUE data) StringValue(key); StringValue(data); - buf = HMAC(GetDigestPtr(digest), RSTRING_PTR(key), RSTRING_LENINT(key), - (unsigned char *)RSTRING_PTR(data), RSTRING_LEN(data), NULL, &buf_len); + buf = HMAC(ossl_evp_get_digestbyname(digest), RSTRING_PTR(key), + RSTRING_LENINT(key), (unsigned char *)RSTRING_PTR(data), + RSTRING_LEN(data), NULL, &buf_len); return rb_str_new((const char *)buf, buf_len); } @@ -295,16 +292,16 @@ ossl_hmac_s_digest(VALUE klass, VALUE digest, VALUE key, VALUE data) * call-seq: * HMAC.hexdigest(digest, key, data) -> aString * - * Returns the authentication code as a hex-encoded string. The +digest+ - * parameter must be an instance of OpenSSL::Digest. + * Returns the authentication code as a hex-encoded string. The _digest_ + * parameter specifies the digest algorithm to use. This may be a String + * representing the algorithm name or an instance of OpenSSL::Digest. * * === Example * * key = 'key' * data = 'The quick brown fox jumps over the lazy dog' - * digest = OpenSSL::Digest.new('sha1') * - * hmac = OpenSSL::HMAC.hexdigest(digest, key, data) + * hmac = OpenSSL::HMAC.hexdigest('sha1', key, data) * #=> "de7c9b85b8b78aa6bc8a7a36f70a90701c9db4d9" * */ @@ -318,9 +315,9 @@ ossl_hmac_s_hexdigest(VALUE klass, VALUE digest, VALUE key, VALUE data) StringValue(key); StringValue(data); - if (!HMAC(GetDigestPtr(digest), RSTRING_PTR(key), RSTRING_LENINT(key), - (unsigned char *)RSTRING_PTR(data), RSTRING_LEN(data), - buf, &buf_len)) + if (!HMAC(ossl_evp_get_digestbyname(digest), RSTRING_PTR(key), + RSTRING_LENINT(key), (unsigned char *)RSTRING_PTR(data), + RSTRING_LEN(data), buf, &buf_len)) ossl_raise(eHMACError, "HMAC"); ret = rb_str_new(NULL, buf_len * 2); @@ -377,7 +374,7 @@ Init_ossl_hmac(void) rb_define_singleton_method(cHMAC, "hexdigest", ossl_hmac_s_hexdigest, 3); rb_define_method(cHMAC, "initialize", ossl_hmac_initialize, 2); - rb_define_copy_func(cHMAC, ossl_hmac_copy); + rb_define_method(cHMAC, "initialize_copy", ossl_hmac_copy, 1); rb_define_method(cHMAC, "reset", ossl_hmac_reset, 0); rb_define_method(cHMAC, "update", ossl_hmac_update, 1); diff --git a/ext/openssl/ossl_kdf.c b/ext/openssl/ossl_kdf.c new file mode 100644 index 0000000000..9fa42e174a --- /dev/null +++ b/ext/openssl/ossl_kdf.c @@ -0,0 +1,221 @@ +/* + * Ruby/OpenSSL Project + * Copyright (C) 2007, 2017 Ruby/OpenSSL Project Authors + */ +#include "ossl.h" + +static VALUE mKDF, eKDF; + +/* + * call-seq: + * KDF.pbkdf2_hmac(pass, salt:, iterations:, length:, hash:) -> aString + * + * PKCS #5 PBKDF2 (Password-Based Key Derivation Function 2) in combination + * with HMAC. Takes _pass_, _salt_ and _iterations_, and then derives a key + * of _length_ bytes. + * + * For more information about PBKDF2, see RFC 2898 Section 5.2 + * (https://tools.ietf.org/html/rfc2898#section-5.2). + * + * === Parameters + * pass :: The passphrase. + * salt :: The salt. Salts prevent attacks based on dictionaries of common + * passwords and attacks based on rainbow tables. It is a public + * value that can be safely stored along with the password (e.g. + * if the derived value is used for password storage). + * iterations :: The iteration count. This provides the ability to tune the + * algorithm. It is better to use the highest count possible for + * the maximum resistance to brute-force attacks. + * length :: The desired length of the derived key in octets. + * hash :: The hash algorithm used with HMAC for the PRF. May be a String + * representing the algorithm name, or an instance of + * OpenSSL::Digest. + */ +static VALUE +kdf_pbkdf2_hmac(int argc, VALUE *argv, VALUE self) +{ + VALUE pass, salt, opts, kwargs[4], str; + static ID kwargs_ids[4]; + int iters, len; + const EVP_MD *md; + + if (!kwargs_ids[0]) { + kwargs_ids[0] = rb_intern_const("salt"); + kwargs_ids[1] = rb_intern_const("iterations"); + kwargs_ids[2] = rb_intern_const("length"); + kwargs_ids[3] = rb_intern_const("hash"); + } + rb_scan_args(argc, argv, "1:", &pass, &opts); + rb_get_kwargs(opts, kwargs_ids, 4, 0, kwargs); + + StringValue(pass); + salt = StringValue(kwargs[0]); + iters = NUM2INT(kwargs[1]); + len = NUM2INT(kwargs[2]); + md = ossl_evp_get_digestbyname(kwargs[3]); + + str = rb_str_new(0, len); + if (!PKCS5_PBKDF2_HMAC(RSTRING_PTR(pass), RSTRING_LENINT(pass), + (unsigned char *)RSTRING_PTR(salt), + RSTRING_LENINT(salt), iters, md, len, + (unsigned char *)RSTRING_PTR(str))) + ossl_raise(eKDF, "PKCS5_PBKDF2_HMAC"); + + return str; +} + +#if defined(HAVE_EVP_PBE_SCRYPT) +/* + * call-seq: + * KDF.scrypt(pass, salt:, N:, r:, p:, length:) -> aString + * + * Derives a key from _pass_ using given parameters with the scrypt + * password-based key derivation function. The result can be used for password + * storage. + * + * scrypt is designed to be memory-hard and more secure against brute-force + * attacks using custom hardwares than alternative KDFs such as PBKDF2 or + * bcrypt. + * + * The keyword arguments _N_, _r_ and _p_ can be used to tune scrypt. RFC 7914 + * (published on 2016-08, https://tools.ietf.org/html/rfc7914#section-2) states + * that using values r=8 and p=1 appears to yield good results. + * + * See RFC 7914 (https://tools.ietf.org/html/rfc7914) for more information. + * + * === Parameters + * pass :: Passphrase. + * salt :: Salt. + * N :: CPU/memory cost parameter. This must be a power of 2. + * r :: Block size parameter. + * p :: Parallelization parameter. + * length :: Length in octets of the derived key. + * + * === Example + * pass = "password" + * salt = SecureRandom.random_bytes(16) + * dk = OpenSSL::KDF.scrypt(pass, salt: salt, N: 2**14, r: 8, p: 1, length: 32) + * p dk #=> "\xDA\xE4\xE2...\x7F\xA1\x01T" + */ +static VALUE +kdf_scrypt(int argc, VALUE *argv, VALUE self) +{ + VALUE pass, salt, opts, kwargs[5], str; + static ID kwargs_ids[5]; + size_t len; + uint64_t N, r, p, maxmem; + + if (!kwargs_ids[0]) { + kwargs_ids[0] = rb_intern_const("salt"); + kwargs_ids[1] = rb_intern_const("N"); + kwargs_ids[2] = rb_intern_const("r"); + kwargs_ids[3] = rb_intern_const("p"); + kwargs_ids[4] = rb_intern_const("length"); + } + rb_scan_args(argc, argv, "1:", &pass, &opts); + rb_get_kwargs(opts, kwargs_ids, 5, 0, kwargs); + + StringValue(pass); + salt = StringValue(kwargs[0]); + N = NUM2UINT64T(kwargs[1]); + r = NUM2UINT64T(kwargs[2]); + p = NUM2UINT64T(kwargs[3]); + len = NUM2LONG(kwargs[4]); + /* + * OpenSSL uses 32MB by default (if zero is specified), which is too small. + * Let's not limit memory consumption but just let malloc() fail inside + * OpenSSL. The amount is controllable by other parameters. + */ + maxmem = SIZE_MAX; + + str = rb_str_new(0, len); + if (!EVP_PBE_scrypt(RSTRING_PTR(pass), RSTRING_LEN(pass), + (unsigned char *)RSTRING_PTR(salt), RSTRING_LEN(salt), + N, r, p, maxmem, (unsigned char *)RSTRING_PTR(str), len)) + ossl_raise(eKDF, "EVP_PBE_scrypt"); + + return str; +} +#endif + +void +Init_ossl_kdf(void) +{ +#if 0 + mOSSL = rb_define_module("OpenSSL"); + eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError); +#endif + + /* + * Document-module: OpenSSL::KDF + * + * Provides functionality of various KDFs (key derivation function). + * + * KDF is typically used for securely deriving arbitrary length symmetric + * keys to be used with an OpenSSL::Cipher from passwords. Another use case + * is for storing passwords: Due to the ability to tweak the effort of + * computation by increasing the iteration count, computation can be slowed + * down artificially in order to render possible attacks infeasible. + * + * Currently, OpenSSL::KDF provides implementations for the following KDF: + * + * * PKCS #5 PBKDF2 (Password-Based Key Derivation Function 2) in + * combination with HMAC + * * scrypt + * + * == Examples + * === Generating a 128 bit key for a Cipher (e.g. AES) + * pass = "secret" + * salt = OpenSSL::Random.random_bytes(16) + * iter = 20_000 + * key_len = 16 + * key = OpenSSL::KDF.pbkdf2_hmac(pass, salt: salt, iterations: iter, + * length: key_len, hash: "sha1") + * + * === Storing Passwords + * pass = "secret" + * # store this with the generated value + * salt = OpenSSL::Random.random_bytes(16) + * iter = 20_000 + * hash = OpenSSL::Digest::SHA256.new + * len = hash.digest_length + * # the final value to be stored + * value = OpenSSL::KDF.pbkdf2_hmac(pass, salt: salt, iterations: iter, + * length: len, hash: hash) + * + * == Important Note on Checking Passwords + * When comparing passwords provided by the user with previously stored + * values, a common mistake made is comparing the two values using "==". + * Typically, "==" short-circuits on evaluation, and is therefore + * vulnerable to timing attacks. The proper way is to use a method that + * always takes the same amount of time when comparing two values, thus + * not leaking any information to potential attackers. To compare two + * values, the following could be used: + * + * def eql_time_cmp(a, b) + * unless a.length == b.length + * return false + * end + * cmp = b.bytes + * result = 0 + * a.bytes.each_with_index {|c,i| + * result |= c ^ cmp[i] + * } + * result == 0 + * end + * + * Please note that the premature return in case of differing lengths + * typically does not leak valuable information - when using PBKDF2, the + * length of the values to be compared is of fixed size. + */ + mKDF = rb_define_module_under(mOSSL, "KDF"); + /* + * Generic exception class raised if an error occurs in OpenSSL::KDF module. + */ + eKDF = rb_define_class_under(mKDF, "KDFError", eOSSLError); + + rb_define_module_function(mKDF, "pbkdf2_hmac", kdf_pbkdf2_hmac, -1); +#if defined(HAVE_EVP_PBE_SCRYPT) + rb_define_module_function(mKDF, "scrypt", kdf_scrypt, -1); +#endif +} diff --git a/ext/openssl/ossl_kdf.h b/ext/openssl/ossl_kdf.h new file mode 100644 index 0000000000..b6503f8d9d --- /dev/null +++ b/ext/openssl/ossl_kdf.h @@ -0,0 +1,6 @@ +#if !defined(OSSL_KDF_H) +#define OSSL_KDF_H + +void Init_ossl_kdf(void); + +#endif diff --git a/ext/openssl/ossl_ns_spki.c b/ext/openssl/ossl_ns_spki.c index 4d978bd009..f17b9509c6 100644 --- a/ext/openssl/ossl_ns_spki.c +++ b/ext/openssl/ossl_ns_spki.c @@ -73,7 +73,7 @@ ossl_spki_alloc(VALUE klass) * SPKI.new([request]) => spki * * === Parameters - * * +request+ - optional raw request, either in PEM or DER format. + * * _request_ - optional raw request, either in PEM or DER format. */ static VALUE ossl_spki_initialize(int argc, VALUE *argv, VALUE self) @@ -198,7 +198,7 @@ ossl_spki_get_public_key(VALUE self) * spki.public_key = pub => pkey * * === Parameters - * * +pub+ - the public key to be set for this instance + * * _pub_ - the public key to be set for this instance * * Sets the public key to be associated with the SPKI, an instance of * OpenSSL::PKey. This should be the public key corresponding to the @@ -243,7 +243,7 @@ ossl_spki_get_challenge(VALUE self) * spki.challenge = str => string * * === Parameters - * * +str+ - the challenge string to be set for this instance + * * _str_ - the challenge string to be set for this instance * * Sets the challenge to be associated with the SPKI. May be used by the * server, e.g. to prevent replay. @@ -268,8 +268,8 @@ ossl_spki_set_challenge(VALUE self, VALUE str) * spki.sign(key, digest) => spki * * === Parameters - * * +key+ - the private key to be used for signing this instance - * * +digest+ - the digest to be used for signing this instance + * * _key_ - the private key to be used for signing this instance + * * _digest_ - the digest to be used for signing this instance * * To sign an SPKI, the private key corresponding to the public key set * for this instance should be used, in addition to a digest algorithm in @@ -284,7 +284,7 @@ ossl_spki_sign(VALUE self, VALUE key, VALUE digest) const EVP_MD *md; pkey = GetPrivPKeyPtr(key); /* NO NEED TO DUP */ - md = GetDigestPtr(digest); + md = ossl_evp_get_digestbyname(digest); GetSPKI(self, spki); if (!NETSCAPE_SPKI_sign(spki, pkey, md)) { ossl_raise(eSPKIError, NULL); @@ -298,7 +298,7 @@ ossl_spki_sign(VALUE self, VALUE key, VALUE digest) * spki.verify(key) => boolean * * === Parameters - * * +key+ - the public key to be used for verifying the SPKI signature + * * _key_ - the public key to be used for verifying the SPKI signature * * Returns +true+ if the signature is valid, +false+ otherwise. To verify an * SPKI, the public key contained within the SPKI should be used. diff --git a/ext/openssl/ossl_ocsp.c b/ext/openssl/ossl_ocsp.c index a8b3503d2a..c0237791da 100644 --- a/ext/openssl/ossl_ocsp.c +++ b/ext/openssl/ossl_ocsp.c @@ -22,10 +22,6 @@ TypedData_Get_Struct((obj), OCSP_REQUEST, &ossl_ocsp_request_type, (req)); \ if(!(req)) ossl_raise(rb_eRuntimeError, "Request wasn't initialized!"); \ } while (0) -#define SafeGetOCSPReq(obj, req) do { \ - OSSL_Check_Kind((obj), cOCSPReq); \ - GetOCSPReq((obj), (req)); \ -} while (0) #define NewOCSPRes(klass) \ TypedData_Wrap_Struct((klass), &ossl_ocsp_response_type, 0) @@ -37,10 +33,6 @@ TypedData_Get_Struct((obj), OCSP_RESPONSE, &ossl_ocsp_response_type, (res)); \ if(!(res)) ossl_raise(rb_eRuntimeError, "Response wasn't initialized!"); \ } while (0) -#define SafeGetOCSPRes(obj, res) do { \ - OSSL_Check_Kind((obj), cOCSPRes); \ - GetOCSPRes((obj), (res)); \ -} while (0) #define NewOCSPBasicRes(klass) \ TypedData_Wrap_Struct((klass), &ossl_ocsp_basicresp_type, 0) @@ -52,10 +44,6 @@ TypedData_Get_Struct((obj), OCSP_BASICRESP, &ossl_ocsp_basicresp_type, (res)); \ if(!(res)) ossl_raise(rb_eRuntimeError, "Response wasn't initialized!"); \ } while (0) -#define SafeGetOCSPBasicRes(obj, res) do { \ - OSSL_Check_Kind((obj), cOCSPBasicRes); \ - GetOCSPBasicRes((obj), (res)); \ -} while (0) #define NewOCSPSingleRes(klass) \ TypedData_Wrap_Struct((klass), &ossl_ocsp_singleresp_type, 0) @@ -67,10 +55,6 @@ TypedData_Get_Struct((obj), OCSP_SINGLERESP, &ossl_ocsp_singleresp_type, (res)); \ if(!(res)) ossl_raise(rb_eRuntimeError, "SingleResponse wasn't initialized!"); \ } while (0) -#define SafeGetOCSPSingleRes(obj, res) do { \ - OSSL_Check_Kind((obj), cOCSPSingleRes); \ - GetOCSPSingleRes((obj), (res)); \ -} while (0) #define NewOCSPCertId(klass) \ TypedData_Wrap_Struct((klass), &ossl_ocsp_certid_type, 0) @@ -82,10 +66,6 @@ TypedData_Get_Struct((obj), OCSP_CERTID, &ossl_ocsp_certid_type, (cid)); \ if(!(cid)) ossl_raise(rb_eRuntimeError, "Cert ID wasn't initialized!"); \ } while (0) -#define SafeGetOCSPCertId(obj, cid) do { \ - OSSL_Check_Kind((obj), cOCSPCertId); \ - GetOCSPCertId((obj), (cid)); \ -} while (0) VALUE mOCSP; VALUE eOCSPError; @@ -200,7 +180,7 @@ ossl_ocspreq_initialize_copy(VALUE self, VALUE other) rb_check_frozen(self); GetOCSPReq(self, req_old); - SafeGetOCSPReq(other, req); + GetOCSPReq(other, req); req_new = ASN1_item_dup(ASN1_ITEM_rptr(OCSP_REQUEST), req); if (!req_new) @@ -218,7 +198,7 @@ ossl_ocspreq_initialize_copy(VALUE self, VALUE other) * OpenSSL::OCSP::Request.new(request_der) -> request * * Creates a new OpenSSL::OCSP::Request. The request may be created empty or - * from a +request_der+ string. + * from a _request_der_ string. */ static VALUE @@ -248,7 +228,7 @@ ossl_ocspreq_initialize(int argc, VALUE *argv, VALUE self) * call-seq: * request.add_nonce(nonce = nil) -> request * - * Adds a +nonce+ to the OCSP request. If no nonce is given a random one will + * Adds a _nonce_ to the OCSP request. If no nonce is given a random one will * be generated. * * The nonce is used to prevent replay attacks but some servers do not support @@ -281,7 +261,7 @@ ossl_ocspreq_add_nonce(int argc, VALUE *argv, VALUE self) * call-seq: * request.check_nonce(response) -> result * - * Checks the nonce validity for this request and +response+. + * Checks the nonce validity for this request and _response_. * * The return value is one of the following: * @@ -291,7 +271,7 @@ ossl_ocspreq_add_nonce(int argc, VALUE *argv, VALUE self) * 2 :: nonces both absent. * 3 :: nonce present in response only. * - * For most responses, clients can check +result+ > 0. If a responder doesn't + * For most responses, clients can check _result_ > 0. If a responder doesn't * handle nonces result.nonzero? may be necessary. A result of * 0 is always an error. */ @@ -304,7 +284,7 @@ ossl_ocspreq_check_nonce(VALUE self, VALUE basic_resp) int res; GetOCSPReq(self, req); - SafeGetOCSPBasicRes(basic_resp, bs); + GetOCSPBasicRes(basic_resp, bs); res = OCSP_check_nonce(req, bs); return INT2NUM(res); @@ -314,7 +294,7 @@ ossl_ocspreq_check_nonce(VALUE self, VALUE basic_resp) * call-seq: * request.add_certid(certificate_id) -> request * - * Adds +certificate_id+ to the request. + * Adds _certificate_id_ to the request. */ static VALUE @@ -371,17 +351,17 @@ ossl_ocspreq_get_certid(VALUE self) * call-seq: * request.sign(cert, key, certs = nil, flags = 0, digest = nil) -> self * - * Signs this OCSP request using +cert+, +key+ and optional +digest+. If - * +digest+ is not specified, SHA-1 is used. +certs+ is an optional Array of + * Signs this OCSP request using _cert_, _key_ and optional _digest_. If + * _digest_ is not specified, SHA-1 is used. _certs_ is an optional Array of * additional certificates which are included in the request in addition to - * the signer certificate. Note that if +certs+ is nil or not given, flag + * the signer certificate. Note that if _certs_ is +nil+ or not given, flag * OpenSSL::OCSP::NOCERTS is enabled. Pass an empty array to include only the * signer certificate. * - * +flags+ can be a bitwise OR of the following constants: + * _flags_ is a bitwise OR of the following constants: * * OpenSSL::OCSP::NOCERTS:: - * Don't include any certificates in the request. +certs+ will be ignored. + * Don't include any certificates in the request. _certs_ will be ignored. */ static VALUE ossl_ocspreq_sign(int argc, VALUE *argv, VALUE self) @@ -404,7 +384,7 @@ ossl_ocspreq_sign(int argc, VALUE *argv, VALUE self) if (NIL_P(digest)) md = EVP_sha1(); else - md = GetDigestPtr(digest); + md = ossl_evp_get_digestbyname(digest); if (NIL_P(certs)) flg |= OCSP_NOCERTS; else @@ -421,9 +401,12 @@ ossl_ocspreq_sign(int argc, VALUE *argv, VALUE self) * call-seq: * request.verify(certificates, store, flags = 0) -> true or false * - * Verifies this request using the given +certificates+ and +store+. - * +certificates+ is an array of OpenSSL::X509::Certificate, +store+ is an + * Verifies this request using the given _certificates_ and _store_. + * _certificates_ is an array of OpenSSL::X509::Certificate, _store_ is an * OpenSSL::X509::Store. + * + * Note that +false+ is returned if the request does not have a signature. + * Use #signed? to check whether the request is signed or not. */ static VALUE @@ -472,6 +455,22 @@ ossl_ocspreq_to_der(VALUE self) return str; } +/* + * call-seq: + * request.signed? -> true or false + * + * Returns +true+ if the request is signed, +false+ otherwise. Note that the + * validity of the signature is *not* checked. Use #verify to verify that. + */ +static VALUE +ossl_ocspreq_signed_p(VALUE self) +{ + OCSP_REQUEST *req; + + GetOCSPReq(self, req); + return OCSP_request_is_signed(req) ? Qtrue : Qfalse; +} + /* * OCSP::Response */ @@ -479,7 +478,7 @@ ossl_ocspreq_to_der(VALUE self) /* call-seq: * OpenSSL::OCSP::Response.create(status, basic_response = nil) -> response * - * Creates an OpenSSL::OCSP::Response from +status+ and +basic_response+. + * Creates an OpenSSL::OCSP::Response from _status_ and _basic_response_. */ static VALUE @@ -521,7 +520,7 @@ ossl_ocspres_initialize_copy(VALUE self, VALUE other) rb_check_frozen(self); GetOCSPRes(self, res_old); - SafeGetOCSPRes(other, res); + GetOCSPRes(other, res); res_new = ASN1_item_dup(ASN1_ITEM_rptr(OCSP_RESPONSE), res); if (!res_new) @@ -539,7 +538,7 @@ ossl_ocspres_initialize_copy(VALUE self, VALUE other) * OpenSSL::OCSP::Response.new(response_der) -> response * * Creates a new OpenSSL::OCSP::Response. The response may be created empty or - * from a +response_der+ string. + * from a _response_der_ string. */ static VALUE @@ -677,7 +676,7 @@ ossl_ocspbres_initialize_copy(VALUE self, VALUE other) rb_check_frozen(self); GetOCSPBasicRes(self, bs_old); - SafeGetOCSPBasicRes(other, bs); + GetOCSPBasicRes(other, bs); bs_new = ASN1_item_dup(ASN1_ITEM_rptr(OCSP_BASICRESP), bs); if (!bs_new) @@ -693,7 +692,7 @@ ossl_ocspbres_initialize_copy(VALUE self, VALUE other) * call-seq: * OpenSSL::OCSP::BasicResponse.new(der_string = nil) -> basic_response * - * Creates a new BasicResponse. If +der_string+ is given, decodes +der_string+ + * Creates a new BasicResponse. If _der_string_ is given, decodes _der_string_ * as DER. */ @@ -724,7 +723,7 @@ ossl_ocspbres_initialize(int argc, VALUE *argv, VALUE self) * call-seq: * basic_response.copy_nonce(request) -> Integer * - * Copies the nonce from +request+ into this response. Returns 1 on success + * Copies the nonce from _request_ into this response. Returns 1 on success * and 0 on failure. */ @@ -736,7 +735,7 @@ ossl_ocspbres_copy_nonce(VALUE self, VALUE request) int ret; GetOCSPBasicRes(self, bs); - SafeGetOCSPReq(request, req); + GetOCSPReq(request, req); ret = OCSP_copy_nonce(bs, req); return INT2NUM(ret); @@ -746,7 +745,7 @@ ossl_ocspbres_copy_nonce(VALUE self, VALUE request) * call-seq: * basic_response.add_nonce(nonce = nil) * - * Adds +nonce+ to this response. If no nonce was provided a random nonce + * Adds _nonce_ to this response. If no nonce was provided a random nonce * will be added. */ @@ -792,26 +791,26 @@ add_status_convert_time(VALUE obj) * call-seq: * basic_response.add_status(certificate_id, status, reason, revocation_time, this_update, next_update, extensions) -> basic_response * - * Adds a certificate status for +certificate_id+. +status+ is the status, and + * Adds a certificate status for _certificate_id_. _status_ is the status, and * must be one of these: * * - OpenSSL::OCSP::V_CERTSTATUS_GOOD * - OpenSSL::OCSP::V_CERTSTATUS_REVOKED * - OpenSSL::OCSP::V_CERTSTATUS_UNKNOWN * - * +reason+ and +revocation_time+ can be given only when +status+ is - * OpenSSL::OCSP::V_CERTSTATUS_REVOKED. +reason+ describes the reason for the + * _reason_ and _revocation_time_ can be given only when _status_ is + * OpenSSL::OCSP::V_CERTSTATUS_REVOKED. _reason_ describes the reason for the * revocation, and must be one of OpenSSL::OCSP::REVOKED_STATUS_* constants. - * +revocation_time+ is the time when the certificate is revoked. + * _revocation_time_ is the time when the certificate is revoked. * - * +this_update+ and +next_update+ indicate the time at which ths status is + * _this_update_ and _next_update_ indicate the time at which ths status is * verified to be correct and the time at or before which newer information - * will be available, respectively. +next_update+ is optional. + * will be available, respectively. _next_update_ is optional. * - * +extensions+ is an Array of OpenSSL::X509::Extension to be included in the + * _extensions_ is an Array of OpenSSL::X509::Extension to be included in the * SingleResponse. This is also optional. * - * Note that the times, +revocation_time+, +this_update+ and +next_update+ + * Note that the times, _revocation_time_, _this_update_ and _next_update_ * can be specified in either of Integer or Time object. If they are Integer, it * is treated as the relative seconds from the current time. */ @@ -829,7 +828,7 @@ ossl_ocspbres_add_status(VALUE self, VALUE cid, VALUE status, VALUE tmp; GetOCSPBasicRes(self, bs); - SafeGetOCSPCertId(cid, id); + GetOCSPCertId(cid, id); st = NUM2INT(status); if (!NIL_P(ext)) { /* All ext's members must be X509::Extension */ ext = rb_check_array_type(ext); @@ -888,7 +887,7 @@ ossl_ocspbres_add_status(VALUE self, VALUE cid, VALUE status, * Returns an Array of statuses for this response. Each status contains a * CertificateId, the status (0 for good, 1 for revoked, 2 for unknown), the * reason for the status, the revocation time, the time of this update, the time - * for the next update and a list of OpenSSL::X509::Extensions. + * for the next update and a list of OpenSSL::X509::Extension. * * This should be superseded by BasicResponse#responses and #find_response that * return SingleResponse. @@ -977,7 +976,7 @@ ossl_ocspbres_get_responses(VALUE self) * call-seq: * basic_response.find_response(certificate_id) -> SingleResponse | nil * - * Returns a SingleResponse whose CertId matches with +certificate_id+, or nil + * Returns a SingleResponse whose CertId matches with _certificate_id_, or +nil+ * if this BasicResponse does not contain it. */ static VALUE @@ -988,7 +987,7 @@ ossl_ocspbres_find_response(VALUE self, VALUE target) OCSP_CERTID *id; int n; - SafeGetOCSPCertId(target, id); + GetOCSPCertId(target, id); GetOCSPBasicRes(self, bs); if ((n = OCSP_resp_find(bs, id, -1)) == -1) @@ -1006,10 +1005,10 @@ ossl_ocspbres_find_response(VALUE self, VALUE target) * call-seq: * basic_response.sign(cert, key, certs = nil, flags = 0, digest = nil) -> self * - * Signs this OCSP response using the +cert+, +key+ and optional +digest+. This + * Signs this OCSP response using the _cert_, _key_ and optional _digest_. This * behaves in the similar way as OpenSSL::OCSP::Request#sign. * - * +flags+ can include: + * _flags_ can include: * OpenSSL::OCSP::NOCERTS:: don't include certificates * OpenSSL::OCSP::NOTIME:: don't set producedAt * OpenSSL::OCSP::RESPID_KEY:: use signer's public key hash as responderID @@ -1036,7 +1035,7 @@ ossl_ocspbres_sign(int argc, VALUE *argv, VALUE self) if (NIL_P(digest)) md = EVP_sha1(); else - md = GetDigestPtr(digest); + md = ossl_evp_get_digestbyname(digest); if (NIL_P(certs)) flg |= OCSP_NOCERTS; else @@ -1053,8 +1052,8 @@ ossl_ocspbres_sign(int argc, VALUE *argv, VALUE self) * call-seq: * basic_response.verify(certificates, store, flags = 0) -> true or false * - * Verifies the signature of the response using the given +certificates+ and - * +store+. This works in the similar way as OpenSSL::OCSP::Request#verify. + * Verifies the signature of the response using the given _certificates_ and + * _store_. This works in the similar way as OpenSSL::OCSP::Request#verify. */ static VALUE ossl_ocspbres_verify(int argc, VALUE *argv, VALUE self) @@ -1184,7 +1183,7 @@ ossl_ocspsres_alloc(VALUE klass) * call-seq: * OpenSSL::OCSP::SingleResponse.new(der_string) -> SingleResponse * - * Creates a new SingleResponse from +der_string+. + * Creates a new SingleResponse from _der_string_. */ static VALUE ossl_ocspsres_initialize(VALUE self, VALUE arg) @@ -1213,7 +1212,7 @@ ossl_ocspsres_initialize_copy(VALUE self, VALUE other) rb_check_frozen(self); GetOCSPSingleRes(self, sres_old); - SafeGetOCSPSingleRes(other, sres); + GetOCSPSingleRes(other, sres); sres_new = ASN1_item_dup(ASN1_ITEM_rptr(OCSP_SINGLERESP), sres); if (!sres_new) @@ -1235,10 +1234,10 @@ ossl_ocspsres_initialize_copy(VALUE self, VALUE other) * * It is possible that the OCSP request takes a few seconds or the time is not * accurate. To avoid rejecting a valid response, this method allows the times - * to be within +nsec+ of the current time. + * to be within _nsec_ seconds of the current time. * * Some responders don't set the nextUpdate field. This may cause a very old - * response to be considered valid. The +maxsec+ parameter can be used to limit + * response to be considered valid. The _maxsec_ parameter can be used to limit * the age of responses. */ static VALUE @@ -1329,8 +1328,10 @@ ossl_ocspsres_get_this_update(VALUE self) status = OCSP_single_get0_status(sres, NULL, NULL, &time, NULL); if (status < 0) ossl_raise(eOCSPError, "OCSP_single_get0_status"); + if (!time) + return Qnil; - return asn1time_to_time(time); /* will handle NULL */ + return asn1time_to_time(time); } /* @@ -1348,6 +1349,8 @@ ossl_ocspsres_get_next_update(VALUE self) status = OCSP_single_get0_status(sres, NULL, NULL, NULL, &time); if (status < 0) ossl_raise(eOCSPError, "OCSP_single_get0_status"); + if (!time) + return Qnil; return asn1time_to_time(time); } @@ -1369,6 +1372,8 @@ ossl_ocspsres_get_revocation_time(VALUE self) ossl_raise(eOCSPError, "OCSP_single_get0_status"); if (status != V_OCSP_CERTSTATUS_REVOKED) ossl_raise(eOCSPError, "certificate is not revoked"); + if (!time) + return Qnil; return asn1time_to_time(time); } @@ -1468,7 +1473,7 @@ ossl_ocspcid_initialize_copy(VALUE self, VALUE other) rb_check_frozen(self); GetOCSPCertId(self, cid_old); - SafeGetOCSPCertId(other, cid); + GetOCSPCertId(other, cid); cid_new = OCSP_CERTID_dup(cid); if (!cid_new) @@ -1485,14 +1490,13 @@ ossl_ocspcid_initialize_copy(VALUE self, VALUE other) * OpenSSL::OCSP::CertificateId.new(subject, issuer, digest = nil) -> certificate_id * OpenSSL::OCSP::CertificateId.new(der_string) -> certificate_id * - * Creates a new OpenSSL::OCSP::CertificateId for the given +subject+ and - * +issuer+ X509 certificates. The +digest+ is used to compute the - * certificate ID and must be an OpenSSL::Digest instance. + * Creates a new OpenSSL::OCSP::CertificateId for the given _subject_ and + * _issuer_ X509 certificates. The _digest_ is a digest algorithm that is used + * to compute the hash values. This defaults to SHA-1. * * If only one argument is given, decodes it as DER representation of a * certificate ID. */ - static VALUE ossl_ocspcid_initialize(int argc, VALUE *argv, VALUE self) { @@ -1517,7 +1521,7 @@ ossl_ocspcid_initialize(int argc, VALUE *argv, VALUE self) x509s = GetX509CertPtr(subject); /* NO NEED TO DUP */ x509i = GetX509CertPtr(issuer); /* NO NEED TO DUP */ - md = !NIL_P(digest) ? GetDigestPtr(digest) : NULL; + md = !NIL_P(digest) ? ossl_evp_get_digestbyname(digest) : NULL; newid = OCSP_cert_to_id(md, x509s, x509i); if (!newid) @@ -1534,7 +1538,7 @@ ossl_ocspcid_initialize(int argc, VALUE *argv, VALUE self) * call-seq: * certificate_id.cmp(other) -> true or false * - * Compares this certificate id with +other+ and returns true if they are the + * Compares this certificate id with _other_ and returns +true+ if they are the * same. */ static VALUE @@ -1544,7 +1548,7 @@ ossl_ocspcid_cmp(VALUE self, VALUE other) int result; GetOCSPCertId(self, id); - SafeGetOCSPCertId(other, id2); + GetOCSPCertId(other, id2); result = OCSP_id_cmp(id, id2); return (result == 0) ? Qtrue : Qfalse; @@ -1554,7 +1558,7 @@ ossl_ocspcid_cmp(VALUE self, VALUE other) * call-seq: * certificate_id.cmp_issuer(other) -> true or false * - * Compares this certificate id's issuer with +other+ and returns true if + * Compares this certificate id's issuer with _other_ and returns +true+ if * they are the same. */ @@ -1565,7 +1569,7 @@ ossl_ocspcid_cmp_issuer(VALUE self, VALUE other) int result; GetOCSPCertId(self, id); - SafeGetOCSPCertId(other, id2); + GetOCSPCertId(other, id2); result = OCSP_id_issuer_cmp(id, id2); return (result == 0) ? Qtrue : Qfalse; @@ -1824,12 +1828,13 @@ Init_ossl_ocsp(void) cOCSPReq = rb_define_class_under(mOCSP, "Request", rb_cObject); rb_define_alloc_func(cOCSPReq, ossl_ocspreq_alloc); - rb_define_copy_func(cOCSPReq, ossl_ocspreq_initialize_copy); + rb_define_method(cOCSPReq, "initialize_copy", ossl_ocspreq_initialize_copy, 1); rb_define_method(cOCSPReq, "initialize", ossl_ocspreq_initialize, -1); rb_define_method(cOCSPReq, "add_nonce", ossl_ocspreq_add_nonce, -1); rb_define_method(cOCSPReq, "check_nonce", ossl_ocspreq_check_nonce, 1); rb_define_method(cOCSPReq, "add_certid", ossl_ocspreq_add_certid, 1); rb_define_method(cOCSPReq, "certid", ossl_ocspreq_get_certid, 0); + rb_define_method(cOCSPReq, "signed?", ossl_ocspreq_signed_p, 0); rb_define_method(cOCSPReq, "sign", ossl_ocspreq_sign, -1); rb_define_method(cOCSPReq, "verify", ossl_ocspreq_verify, -1); rb_define_method(cOCSPReq, "to_der", ossl_ocspreq_to_der, 0); @@ -1842,7 +1847,7 @@ Init_ossl_ocsp(void) cOCSPRes = rb_define_class_under(mOCSP, "Response", rb_cObject); rb_define_singleton_method(cOCSPRes, "create", ossl_ocspres_s_create, 2); rb_define_alloc_func(cOCSPRes, ossl_ocspres_alloc); - rb_define_copy_func(cOCSPRes, ossl_ocspres_initialize_copy); + rb_define_method(cOCSPRes, "initialize_copy", ossl_ocspres_initialize_copy, 1); rb_define_method(cOCSPRes, "initialize", ossl_ocspres_initialize, -1); rb_define_method(cOCSPRes, "status", ossl_ocspres_status, 0); rb_define_method(cOCSPRes, "status_string", ossl_ocspres_status_string, 0); @@ -1857,7 +1862,7 @@ Init_ossl_ocsp(void) cOCSPBasicRes = rb_define_class_under(mOCSP, "BasicResponse", rb_cObject); rb_define_alloc_func(cOCSPBasicRes, ossl_ocspbres_alloc); - rb_define_copy_func(cOCSPBasicRes, ossl_ocspbres_initialize_copy); + rb_define_method(cOCSPBasicRes, "initialize_copy", ossl_ocspbres_initialize_copy, 1); rb_define_method(cOCSPBasicRes, "initialize", ossl_ocspbres_initialize, -1); rb_define_method(cOCSPBasicRes, "copy_nonce", ossl_ocspbres_copy_nonce, 1); rb_define_method(cOCSPBasicRes, "add_nonce", ossl_ocspbres_add_nonce, -1); @@ -1876,7 +1881,7 @@ Init_ossl_ocsp(void) */ cOCSPSingleRes = rb_define_class_under(mOCSP, "SingleResponse", rb_cObject); rb_define_alloc_func(cOCSPSingleRes, ossl_ocspsres_alloc); - rb_define_copy_func(cOCSPSingleRes, ossl_ocspsres_initialize_copy); + rb_define_method(cOCSPSingleRes, "initialize_copy", ossl_ocspsres_initialize_copy, 1); rb_define_method(cOCSPSingleRes, "initialize", ossl_ocspsres_initialize, 1); rb_define_method(cOCSPSingleRes, "check_validity", ossl_ocspsres_check_validity, -1); rb_define_method(cOCSPSingleRes, "certid", ossl_ocspsres_get_certid, 0); @@ -1895,7 +1900,7 @@ Init_ossl_ocsp(void) cOCSPCertId = rb_define_class_under(mOCSP, "CertificateId", rb_cObject); rb_define_alloc_func(cOCSPCertId, ossl_ocspcid_alloc); - rb_define_copy_func(cOCSPCertId, ossl_ocspcid_initialize_copy); + rb_define_method(cOCSPCertId, "initialize_copy", ossl_ocspcid_initialize_copy, 1); rb_define_method(cOCSPCertId, "initialize", ossl_ocspcid_initialize, -1); rb_define_method(cOCSPCertId, "cmp", ossl_ocspcid_cmp, 1); rb_define_method(cOCSPCertId, "cmp_issuer", ossl_ocspcid_cmp_issuer, 1); diff --git a/ext/openssl/ossl_pkcs12.c b/ext/openssl/ossl_pkcs12.c index 8502a6de0d..ddb7d939cf 100644 --- a/ext/openssl/ossl_pkcs12.c +++ b/ext/openssl/ossl_pkcs12.c @@ -17,11 +17,6 @@ if(!(p12)) ossl_raise(rb_eRuntimeError, "PKCS12 wasn't initialized."); \ } while (0) -#define SafeGetPKCS12(obj, p12) do { \ - OSSL_Check_Kind((obj), cPKCS12); \ - GetPKCS12((obj), (p12)); \ -} while (0) - #define ossl_pkcs12_set_key(o,v) rb_iv_set((o), "@key", (v)) #define ossl_pkcs12_set_cert(o,v) rb_iv_set((o), "@certificate", (v)) #define ossl_pkcs12_set_ca_certs(o,v) rb_iv_set((o), "@ca_certs", (v)) @@ -72,7 +67,7 @@ ossl_pkcs12_initialize_copy(VALUE self, VALUE other) rb_check_frozen(self); GetPKCS12(self, p12_old); - SafeGetPKCS12(other, p12); + GetPKCS12(other, p12); p12_new = ASN1_dup((i2d_of_void *)i2d_PKCS12, (d2i_of_void *)d2i_PKCS12, (char *)p12); if (!p12_new) @@ -89,20 +84,20 @@ ossl_pkcs12_initialize_copy(VALUE self, VALUE other) * PKCS12.create(pass, name, key, cert [, ca, [, key_pbe [, cert_pbe [, key_iter [, mac_iter [, keytype]]]]]]) * * === Parameters - * * +pass+ - string - * * +name+ - A string describing the key. - * * +key+ - Any PKey. - * * +cert+ - A X509::Certificate. + * * _pass_ - string + * * _name_ - A string describing the key. + * * _key_ - Any PKey. + * * _cert_ - A X509::Certificate. * * The public_key portion of the certificate must contain a valid public key. * * The not_before and not_after fields must be filled in. - * * +ca+ - An optional array of X509::Certificate's. - * * +key_pbe+ - string - * * +cert_pbe+ - string - * * +key_iter+ - integer - * * +mac_iter+ - integer - * * +keytype+ - An integer representing an MSIE specific extension. + * * _ca_ - An optional array of X509::Certificate's. + * * _key_pbe_ - string + * * _cert_pbe_ - string + * * _key_iter_ - integer + * * _mac_iter_ - integer + * * _keytype_ - An integer representing an MSIE specific extension. * - * Any optional arguments may be supplied as nil to preserve the OpenSSL defaults. + * Any optional arguments may be supplied as +nil+ to preserve the OpenSSL defaults. * * See the OpenSSL documentation for PKCS12_create(). */ @@ -161,8 +156,8 @@ ossl_pkcs12_s_create(int argc, VALUE *argv, VALUE self) * PKCS12.new(str, pass) -> pkcs12 * * === Parameters - * * +str+ - Must be a DER encoded PKCS12 string. - * * +pass+ - string + * * _str_ - Must be a DER encoded PKCS12 string. + * * _pass_ - string */ static VALUE ossl_pkcs12_initialize(int argc, VALUE *argv, VALUE self) @@ -252,7 +247,7 @@ Init_ossl_pkcs12(void) rb_define_singleton_method(cPKCS12, "create", ossl_pkcs12_s_create, -1); rb_define_alloc_func(cPKCS12, ossl_pkcs12_s_allocate); - rb_define_copy_func(cPKCS12, ossl_pkcs12_initialize_copy); + rb_define_method(cPKCS12, "initialize_copy", ossl_pkcs12_initialize_copy, 1); rb_attr(cPKCS12, rb_intern("key"), 1, 0, Qfalse); rb_attr(cPKCS12, rb_intern("certificate"), 1, 0, Qfalse); rb_attr(cPKCS12, rb_intern("ca_certs"), 1, 0, Qfalse); diff --git a/ext/openssl/ossl_pkcs5.c b/ext/openssl/ossl_pkcs5.c deleted file mode 100644 index 47c5bfa3b8..0000000000 --- a/ext/openssl/ossl_pkcs5.c +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright (C) 2007 Technorama Ltd. - */ -#include "ossl.h" - -VALUE mPKCS5; -VALUE ePKCS5; - -#ifdef HAVE_PKCS5_PBKDF2_HMAC -/* - * call-seq: - * PKCS5.pbkdf2_hmac(pass, salt, iter, keylen, digest) => string - * - * === Parameters - * * +pass+ - string - * * +salt+ - string - should be at least 8 bytes long. - * * +iter+ - integer - should be greater than 1000. 20000 is better. - * * +keylen+ - integer - * * +digest+ - a string or OpenSSL::Digest object. - * - * Available in OpenSSL >= 1.0.0. - * - * Digests other than SHA1 may not be supported by other cryptography libraries. - */ -static VALUE -ossl_pkcs5_pbkdf2_hmac(VALUE self, VALUE pass, VALUE salt, VALUE iter, VALUE keylen, VALUE digest) -{ - VALUE str; - const EVP_MD *md; - int len = NUM2INT(keylen); - - StringValue(pass); - StringValue(salt); - md = GetDigestPtr(digest); - - str = rb_str_new(0, len); - - if (PKCS5_PBKDF2_HMAC(RSTRING_PTR(pass), RSTRING_LENINT(pass), - (unsigned char *)RSTRING_PTR(salt), RSTRING_LENINT(salt), - NUM2INT(iter), md, len, - (unsigned char *)RSTRING_PTR(str)) != 1) - ossl_raise(ePKCS5, "PKCS5_PBKDF2_HMAC"); - - return str; -} -#else -#define ossl_pkcs5_pbkdf2_hmac rb_f_notimplement -#endif - - -/* - * call-seq: - * PKCS5.pbkdf2_hmac_sha1(pass, salt, iter, keylen) => string - * - * === Parameters - * * +pass+ - string - * * +salt+ - string - should be at least 8 bytes long. - * * +iter+ - integer - should be greater than 1000. 20000 is better. - * * +keylen+ - integer - * - * This method is available in almost any version of OpenSSL. - * - * Conforms to RFC 2898. - */ -static VALUE -ossl_pkcs5_pbkdf2_hmac_sha1(VALUE self, VALUE pass, VALUE salt, VALUE iter, VALUE keylen) -{ - VALUE str; - int len = NUM2INT(keylen); - - StringValue(pass); - StringValue(salt); - - str = rb_str_new(0, len); - - if (PKCS5_PBKDF2_HMAC_SHA1(RSTRING_PTR(pass), RSTRING_LENINT(pass), - (const unsigned char *)RSTRING_PTR(salt), RSTRING_LENINT(salt), NUM2INT(iter), - len, (unsigned char *)RSTRING_PTR(str)) != 1) - ossl_raise(ePKCS5, "PKCS5_PBKDF2_HMAC_SHA1"); - - return str; -} - -void -Init_ossl_pkcs5(void) -{ -#if 0 - mOSSL = rb_define_module("OpenSSL"); - eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError); -#endif - - /* Document-class: OpenSSL::PKCS5 - * - * Provides password-based encryption functionality based on PKCS#5. - * Typically used for securely deriving arbitrary length symmetric keys - * to be used with an OpenSSL::Cipher from passwords. Another use case - * is for storing passwords: Due to the ability to tweak the effort of - * computation by increasing the iteration count, computation can be - * slowed down artificially in order to render possible attacks infeasible. - * - * PKCS5 offers support for PBKDF2 with an OpenSSL::Digest::SHA1-based - * HMAC, or an arbitrary Digest if the underlying version of OpenSSL - * already supports it (>= 1.0.0). - * - * === Parameters - * ==== Password - * Typically an arbitrary String that represents the password to be used - * for deriving a key. - * ==== Salt - * Prevents attacks based on dictionaries of common passwords. It is a - * public value that can be safely stored along with the password (e.g. - * if PBKDF2 is used for password storage). For maximum security, a fresh, - * random salt should be generated for each stored password. According - * to PKCS#5, a salt should be at least 8 bytes long. - * ==== Iteration Count - * Allows to tweak the length that the actual computation will take. The - * larger the iteration count, the longer it will take. - * ==== Key Length - * Specifies the length in bytes of the output that will be generated. - * Typically, the key length should be larger than or equal to the output - * length of the underlying digest function, otherwise an attacker could - * simply try to brute-force the key. According to PKCS#5, security is - * limited by the output length of the underlying digest function, i.e. - * security is not improved if a key length strictly larger than the - * digest output length is chosen. Therefore, when using PKCS5 for - * password storage, it suffices to store values equal to the digest - * output length, nothing is gained by storing larger values. - * - * == Examples - * === Generating a 128 bit key for a Cipher (e.g. AES) - * pass = "secret" - * salt = OpenSSL::Random.random_bytes(16) - * iter = 20000 - * key_len = 16 - * key = OpenSSL::PKCS5.pbkdf2_hmac_sha1(pass, salt, iter, key_len) - * - * === Storing Passwords - * pass = "secret" - * salt = OpenSSL::Random.random_bytes(16) #store this with the generated value - * iter = 20000 - * digest = OpenSSL::Digest::SHA256.new - * len = digest.digest_length - * #the final value to be stored - * value = OpenSSL::PKCS5.pbkdf2_hmac(pass, salt, iter, len, digest) - * - * === Important Note on Checking Passwords - * When comparing passwords provided by the user with previously stored - * values, a common mistake made is comparing the two values using "==". - * Typically, "==" short-circuits on evaluation, and is therefore - * vulnerable to timing attacks. The proper way is to use a method that - * always takes the same amount of time when comparing two values, thus - * not leaking any information to potential attackers. To compare two - * values, the following could be used: - * def eql_time_cmp(a, b) - * unless a.length == b.length - * return false - * end - * cmp = b.bytes.to_a - * result = 0 - * a.bytes.each_with_index {|c,i| - * result |= c ^ cmp[i] - * } - * result == 0 - * end - * Please note that the premature return in case of differing lengths - * typically does not leak valuable information - when using PKCS#5, the - * length of the values to be compared is of fixed size. - */ - - mPKCS5 = rb_define_module_under(mOSSL, "PKCS5"); - /* Document-class: OpenSSL::PKCS5::PKCS5Error - * - * Generic Exception class that is raised if an error occurs during a - * computation. - */ - ePKCS5 = rb_define_class_under(mPKCS5, "PKCS5Error", eOSSLError); - - rb_define_module_function(mPKCS5, "pbkdf2_hmac", ossl_pkcs5_pbkdf2_hmac, 5); - rb_define_module_function(mPKCS5, "pbkdf2_hmac_sha1", ossl_pkcs5_pbkdf2_hmac_sha1, 4); -} diff --git a/ext/openssl/ossl_pkcs5.h b/ext/openssl/ossl_pkcs5.h deleted file mode 100644 index a3b132bc50..0000000000 --- a/ext/openssl/ossl_pkcs5.h +++ /dev/null @@ -1,6 +0,0 @@ -#if !defined(_OSSL_PKCS5_H_) -#define _OSSL_PKCS5_H_ - -void Init_ossl_pkcs5(void); - -#endif /* _OSSL_PKCS5_H_ */ diff --git a/ext/openssl/ossl_pkcs7.c b/ext/openssl/ossl_pkcs7.c index 40cc5f230e..6395fa6f5c 100644 --- a/ext/openssl/ossl_pkcs7.c +++ b/ext/openssl/ossl_pkcs7.c @@ -23,10 +23,6 @@ ossl_raise(rb_eRuntimeError, "PKCS7 wasn't initialized."); \ } \ } while (0) -#define SafeGetPKCS7(obj, pkcs7) do { \ - OSSL_Check_Kind((obj), cPKCS7); \ - GetPKCS7((obj), (pkcs7)); \ -} while (0) #define NewPKCS7si(klass) \ TypedData_Wrap_Struct((klass), &ossl_pkcs7_signer_info_type, 0) @@ -42,10 +38,6 @@ ossl_raise(rb_eRuntimeError, "PKCS7si wasn't initialized."); \ } \ } while (0) -#define SafeGetPKCS7si(obj, p7si) do { \ - OSSL_Check_Kind((obj), cPKCS7Signer); \ - GetPKCS7si((obj), (p7si)); \ -} while (0) #define NewPKCS7ri(klass) \ TypedData_Wrap_Struct((klass), &ossl_pkcs7_recip_info_type, 0) @@ -61,10 +53,6 @@ ossl_raise(rb_eRuntimeError, "PKCS7ri wasn't initialized."); \ } \ } while (0) -#define SafeGetPKCS7ri(obj, p7ri) do { \ - OSSL_Check_Kind((obj), cPKCS7Recipient); \ - GetPKCS7ri((obj), (p7ri)); \ -} while (0) #define numberof(ary) (int)(sizeof(ary)/sizeof((ary)[0])) @@ -162,7 +150,7 @@ DupPKCS7SignerPtr(VALUE obj) { PKCS7_SIGNER_INFO *p7si, *pkcs7; - SafeGetPKCS7si(obj, p7si); + GetPKCS7si(obj, p7si); if (!(pkcs7 = ossl_PKCS7_SIGNER_INFO_dup(p7si))) { ossl_raise(ePKCS7Error, NULL); } @@ -189,7 +177,7 @@ DupPKCS7RecipientPtr(VALUE obj) { PKCS7_RECIP_INFO *p7ri, *pkcs7; - SafeGetPKCS7ri(obj, p7ri); + GetPKCS7ri(obj, p7ri); if (!(pkcs7 = ossl_PKCS7_RECIP_INFO_dup(p7ri))) { ossl_raise(ePKCS7Error, NULL); } @@ -238,7 +226,7 @@ ossl_pkcs7_s_write_smime(int argc, VALUE *argv, VALUE klass) rb_scan_args(argc, argv, "12", &pkcs7, &data, &flags); flg = NIL_P(flags) ? 0 : NUM2INT(flags); if(NIL_P(data)) data = ossl_pkcs7_get_data(pkcs7); - SafeGetPKCS7(pkcs7, p7); + GetPKCS7(pkcs7, p7); if(!NIL_P(data) && PKCS7_is_detached(p7)) flg |= PKCS7_DETACHED; in = NIL_P(data) ? NULL : ossl_obj2bio(&data); @@ -331,7 +319,7 @@ ossl_pkcs7_s_encrypt(int argc, VALUE *argv, VALUE klass) #endif } - else ciph = GetCipherPtr(cipher); /* NO NEED TO DUP */ + else ciph = ossl_evp_get_cipherbyname(cipher); flg = NIL_P(flags) ? 0 : NUM2INT(flags); ret = NewPKCS7(cPKCS7); in = ossl_obj2bio(&data); @@ -414,7 +402,7 @@ ossl_pkcs7_copy(VALUE self, VALUE other) if (self == other) return self; GetPKCS7(self, a); - SafeGetPKCS7(other, b); + GetPKCS7(other, b); pkcs7 = PKCS7_dup(b); if (!pkcs7) { @@ -537,7 +525,7 @@ ossl_pkcs7_set_cipher(VALUE self, VALUE cipher) PKCS7 *pkcs7; GetPKCS7(self, pkcs7); - if (!PKCS7_set_cipher(pkcs7, GetCipherPtr(cipher))) { + if (!PKCS7_set_cipher(pkcs7, ossl_evp_get_cipherbyname(cipher))) { ossl_raise(ePKCS7Error, NULL); } @@ -933,7 +921,7 @@ ossl_pkcs7si_initialize(VALUE self, VALUE cert, VALUE key, VALUE digest) pkey = GetPrivPKeyPtr(key); /* NO NEED TO DUP */ x509 = GetX509CertPtr(cert); /* NO NEED TO DUP */ - md = GetDigestPtr(digest); + md = ossl_evp_get_digestbyname(digest); GetPKCS7si(self, p7si); if (!(PKCS7_SIGNER_INFO_set(p7si, x509, pkey, (EVP_MD*)md))) { ossl_raise(ePKCS7Error, NULL); @@ -1068,7 +1056,7 @@ Init_ossl_pkcs7(void) rb_attr(cPKCS7, rb_intern("data"), 1, 0, Qfalse); rb_attr(cPKCS7, rb_intern("error_string"), 1, 1, Qfalse); rb_define_alloc_func(cPKCS7, ossl_pkcs7_alloc); - rb_define_copy_func(cPKCS7, ossl_pkcs7_copy); + rb_define_method(cPKCS7, "initialize_copy", ossl_pkcs7_copy, 1); rb_define_method(cPKCS7, "initialize", ossl_pkcs7_initialize, -1); rb_define_method(cPKCS7, "type=", ossl_pkcs7_set_type, 1); rb_define_method(cPKCS7, "type", ossl_pkcs7_get_type, 0); diff --git a/ext/openssl/ossl_pkey.c b/ext/openssl/ossl_pkey.c index 314d1d94af..23e2115409 100644 --- a/ext/openssl/ossl_pkey.c +++ b/ext/openssl/ossl_pkey.c @@ -92,7 +92,7 @@ pkey_new0(EVP_PKEY *pkey) case EVP_PKEY_DH: return ossl_dh_new(pkey); #endif -#if !defined(OPENSSL_NO_EC) && (OPENSSL_VERSION_NUMBER >= 0x0090802fL) +#if !defined(OPENSSL_NO_EC) case EVP_PKEY_EC: return ossl_ec_new(pkey); #endif @@ -123,15 +123,15 @@ ossl_pkey_new(EVP_PKEY *pkey) * OpenSSL::PKey.read(string [, pwd ]) -> PKey * OpenSSL::PKey.read(io [, pwd ]) -> PKey * - * Reads a DER or PEM encoded string from +string+ or +io+ and returns an + * Reads a DER or PEM encoded string from _string_ or _io_ and returns an * instance of the appropriate PKey class. * * === Parameters - * * +string+ is a DER- or PEM-encoded string containing an arbitrary private + * * _string+ is a DER- or PEM-encoded string containing an arbitrary private * or public key. - * * +io+ is an instance of +IO+ containing a DER- or PEM-encoded + * * _io_ is an instance of IO containing a DER- or PEM-encoded * arbitrary private or public key. - * * +pwd+ is an optional password in case +string+ or +file+ is an encrypted + * * _pwd_ is an optional password in case _string_ or _io_ is an encrypted * PEM resource. */ static VALUE @@ -207,7 +207,7 @@ GetPKeyPtr(VALUE obj) { EVP_PKEY *pkey; - SafeGetPKey(obj, pkey); + GetPKey(obj, pkey); return pkey; } @@ -220,7 +220,7 @@ GetPrivPKeyPtr(VALUE obj) if (rb_funcallv(obj, id_private_q, 0, NULL) != Qtrue) { ossl_raise(rb_eArgError, "Private key is needed."); } - SafeGetPKey(obj, pkey); + GetPKey(obj, pkey); return pkey; } @@ -230,7 +230,7 @@ DupPKeyPtr(VALUE obj) { EVP_PKEY *pkey; - SafeGetPKey(obj, pkey); + GetPKey(obj, pkey); EVP_PKEY_up_ref(pkey); return pkey; @@ -259,7 +259,7 @@ ossl_pkey_alloc(VALUE klass) * PKeyClass.new -> self * * Because PKey is an abstract class, actually calling this method explicitly - * will raise a +NotImplementedError+. + * will raise a NotImplementedError. */ static VALUE ossl_pkey_initialize(VALUE self) @@ -274,10 +274,10 @@ ossl_pkey_initialize(VALUE self) * call-seq: * pkey.sign(digest, data) -> String * - * To sign the +String+ +data+, +digest+, an instance of OpenSSL::Digest, must - * be provided. The return value is again a +String+ containing the signature. + * To sign the String _data_, _digest_, an instance of OpenSSL::Digest, must + * be provided. The return value is again a String containing the signature. * A PKeyError is raised should errors occur. - * Any previous state of the +Digest+ instance is irrelevant to the signature + * Any previous state of the Digest instance is irrelevant to the signature * outcome, the digest instance is reset to its initial state during the * operation. * @@ -298,7 +298,7 @@ ossl_pkey_sign(VALUE self, VALUE digest, VALUE data) int result; pkey = GetPrivPKeyPtr(self); - md = GetDigestPtr(digest); + md = ossl_evp_get_digestbyname(digest); StringValue(data); str = rb_str_new(0, EVP_PKEY_size(pkey)); @@ -326,12 +326,12 @@ ossl_pkey_sign(VALUE self, VALUE digest, VALUE data) * call-seq: * pkey.verify(digest, signature, data) -> String * - * To verify the +String+ +signature+, +digest+, an instance of + * To verify the String _signature_, _digest_, an instance of * OpenSSL::Digest, must be provided to re-compute the message digest of the - * original +data+, also a +String+. The return value is +true+ if the + * original _data_, also a String. The return value is +true+ if the * signature is valid, +false+ otherwise. A PKeyError is raised should errors * occur. - * Any previous state of the +Digest+ instance is irrelevant to the validation + * Any previous state of the Digest instance is irrelevant to the validation * outcome, the digest instance is reset to its initial state during the * operation. * @@ -353,7 +353,7 @@ ossl_pkey_verify(VALUE self, VALUE digest, VALUE sig, VALUE data) GetPKey(self, pkey); pkey_check_public_key(pkey); - md = GetDigestPtr(digest); + md = ossl_evp_get_digestbyname(digest); StringValue(sig); siglen = RSTRING_LENINT(sig); StringValue(data); diff --git a/ext/openssl/ossl_pkey.h b/ext/openssl/ossl_pkey.h index e3b723cd68..a87472ad09 100644 --- a/ext/openssl/ossl_pkey.h +++ b/ext/openssl/ossl_pkey.h @@ -34,10 +34,6 @@ extern const rb_data_type_t ossl_evp_pkey_type; rb_raise(rb_eRuntimeError, "PKEY wasn't initialized!");\ } \ } while (0) -#define SafeGetPKey(obj, pkey) do { \ - OSSL_Check_Kind((obj), cPKey); \ - GetPKey((obj), (pkey)); \ -} while (0) struct ossl_generate_cb_arg { int yield; diff --git a/ext/openssl/ossl_pkey_dh.c b/ext/openssl/ossl_pkey_dh.c index 9283271093..31f3b8e726 100644 --- a/ext/openssl/ossl_pkey_dh.c +++ b/ext/openssl/ossl_pkey_dh.c @@ -150,8 +150,8 @@ dh_generate(int size, int gen) * components alike. * * === Parameters - * * +size+ is an integer representing the desired key size. Keys smaller than 1024 bits should be considered insecure. - * * +generator+ is a small number > 1, typically 2 or 5. + * * _size_ is an integer representing the desired key size. Keys smaller than 1024 bits should be considered insecure. + * * _generator_ is a small number > 1, typically 2 or 5. * */ static VALUE @@ -181,15 +181,15 @@ ossl_dh_s_generate(int argc, VALUE *argv, VALUE klass) * DH.new(size [, generator]) -> dh * * Either generates a DH instance from scratch or by reading already existing - * DH parameters from +string+. Note that when reading a DH instance from + * DH parameters from _string_. Note that when reading a DH instance from * data that was encoded from a DH instance by using DH#to_pem or DH#to_der * the result will *not* contain a public/private key pair yet. This needs to * be generated using DH#generate_key! first. * * === Parameters - * * +size+ is an integer representing the desired key size. Keys smaller than 1024 bits should be considered insecure. - * * +generator+ is a small number > 1, typically 2 or 5. - * * +string+ contains the DER or PEM encoded key. + * * _size_ is an integer representing the desired key size. Keys smaller than 1024 bits should be considered insecure. + * * _generator_ is a small number > 1, typically 2 or 5. + * * _string_ contains the DER or PEM encoded key. * * === Examples * DH.new # -> dh @@ -436,7 +436,7 @@ ossl_dh_to_text(VALUE self) * dh.public_key -> aDH * * Returns a new DH instance that carries just the public information, i.e. - * the prime +p+ and the generator +g+, but no public/private key yet. Such + * the prime _p_ and the generator _g_, but no public/private key yet. Such * a pair may be generated using DH#generate_key!. The "public key" needed * for a key exchange with DH#compute_key is considered as per-session * information and may be retrieved with DH#pub_key once a key pair has @@ -526,7 +526,7 @@ ossl_dh_generate_key(VALUE self) * See DH_compute_key() for further information. * * === Parameters - * * +pub_bn+ is a OpenSSL::BN, *not* the DH instance returned by + * * _pub_bn_ is a OpenSSL::BN, *not* the DH instance returned by * DH#public_key as that contains the DH parameters only. */ static VALUE @@ -557,7 +557,7 @@ ossl_dh_compute_key(VALUE self, VALUE pub) * call-seq: * dh.set_pqg(p, q, g) -> self * - * Sets +p+, +q+, +g+ for the DH instance. + * Sets _p_, _q_, _g_ to the DH instance. */ OSSL_PKEY_BN_DEF3(dh, DH, pqg, p, q, g) /* @@ -565,7 +565,7 @@ OSSL_PKEY_BN_DEF3(dh, DH, pqg, p, q, g) * call-seq: * dh.set_key(pub_key, priv_key) -> self * - * Sets +pub_key+ and +priv_key+ for the DH instance. +priv_key+ may be nil. + * Sets _pub_key_ and _priv_key_ for the DH instance. _priv_key_ may be +nil+. */ OSSL_PKEY_BN_DEF2(dh, DH, key, pub_key, priv_key) @@ -618,7 +618,7 @@ Init_ossl_dh(void) cDH = rb_define_class_under(mPKey, "DH", cPKey); rb_define_singleton_method(cDH, "generate", ossl_dh_s_generate, -1); rb_define_method(cDH, "initialize", ossl_dh_initialize, -1); - rb_define_copy_func(cDH, ossl_dh_initialize_copy); + rb_define_method(cDH, "initialize_copy", ossl_dh_initialize_copy, 1); rb_define_method(cDH, "public?", ossl_dh_is_public, 0); rb_define_method(cDH, "private?", ossl_dh_is_private, 0); rb_define_method(cDH, "to_text", ossl_dh_to_text, 0); diff --git a/ext/openssl/ossl_pkey_dsa.c b/ext/openssl/ossl_pkey_dsa.c index cd4313b1ff..56cc9dd4f1 100644 --- a/ext/openssl/ossl_pkey_dsa.c +++ b/ext/openssl/ossl_pkey_dsa.c @@ -172,7 +172,7 @@ dsa_generate(int size) * from scratch. * * === Parameters - * * +size+ is an integer representing the desired key size. + * * _size_ is an integer representing the desired key size. * */ static VALUE @@ -195,12 +195,12 @@ ossl_dsa_s_generate(VALUE klass, VALUE size) * DSA.new(size) -> dsa * DSA.new(string [, pass]) -> dsa * - * Creates a new DSA instance by reading an existing key from +string+. + * Creates a new DSA instance by reading an existing key from _string_. * * === Parameters - * * +size+ is an integer representing the desired key size. - * * +string+ contains a DER or PEM encoded key. - * * +pass+ is a string that contains an optional password. + * * _size_ is an integer representing the desired key size. + * * _string_ contains a DER or PEM encoded key. + * * _pass_ is a string that contains an optional password. * * === Examples * DSA.new -> dsa @@ -329,8 +329,8 @@ ossl_dsa_is_private(VALUE self) * Encodes this DSA to its PEM encoding. * * === Parameters - * * +cipher+ is an OpenSSL::Cipher. - * * +password+ is a string containing your password. + * * _cipher_ is an OpenSSL::Cipher. + * * _password_ is a string containing your password. * * === Examples * DSA.to_pem -> aString @@ -348,7 +348,7 @@ ossl_dsa_export(int argc, VALUE *argv, VALUE self) GetDSA(self, dsa); rb_scan_args(argc, argv, "02", &cipher, &pass); if (!NIL_P(cipher)) { - ciph = GetCipherPtr(cipher); + ciph = ossl_evp_get_cipherbyname(cipher); pass = ossl_pem_passwd_value(pass); } if (!(out = BIO_new(BIO_s_mem()))) { @@ -503,12 +503,12 @@ ossl_dsa_to_public_key(VALUE self) * call-seq: * dsa.syssign(string) -> aString * - * Computes and returns the DSA signature of +string+, where +string+ is + * Computes and returns the DSA signature of _string_, where _string_ is * expected to be an already-computed message digest of the original input * data. The signature is issued using the private key of this DSA instance. * * === Parameters - * * +string+ is a message digest of the original input data to be signed + * * _string_ is a message digest of the original input data to be signed. * * === Example * dsa = OpenSSL::PKey::DSA.new(2048) @@ -549,11 +549,11 @@ ossl_dsa_sign(VALUE self, VALUE data) * dsa.sysverify(digest, sig) -> true | false * * Verifies whether the signature is valid given the message digest input. It - * does so by validating +sig+ using the public key of this DSA instance. + * does so by validating _sig_ using the public key of this DSA instance. * * === Parameters - * * +digest+ is a message digest of the original input data to be signed - * * +sig+ is a DSA signature value + * * _digest_ is a message digest of the original input data to be signed + * * _sig_ is a DSA signature value * * === Example * dsa = OpenSSL::PKey::DSA.new(2048) @@ -590,7 +590,7 @@ ossl_dsa_verify(VALUE self, VALUE digest, VALUE sig) * call-seq: * dsa.set_pqg(p, q, g) -> self * - * Sets +p+, +q+, +g+ for the DSA instance. + * Sets _p_, _q_, _g_ to the DSA instance. */ OSSL_PKEY_BN_DEF3(dsa, DSA, pqg, p, q, g) /* @@ -598,7 +598,7 @@ OSSL_PKEY_BN_DEF3(dsa, DSA, pqg, p, q, g) * call-seq: * dsa.set_key(pub_key, priv_key) -> self * - * Sets +pub_key+ and +priv_key+ for the DSA instance. +priv_key+ may be nil. + * Sets _pub_key_ and _priv_key_ for the DSA instance. _priv_key_ may be +nil+. */ OSSL_PKEY_BN_DEF2(dsa, DSA, key, pub_key, priv_key) @@ -627,18 +627,12 @@ Init_ossl_dsa(void) * DSA, the Digital Signature Algorithm, is specified in NIST's * FIPS 186-3. It is an asymmetric public key algorithm that may be used * similar to e.g. RSA. - * Please note that for OpenSSL versions prior to 1.0.0 the digest - * algorithms OpenSSL::Digest::DSS (equivalent to SHA) or - * OpenSSL::Digest::DSS1 (equivalent to SHA-1) must be used for issuing - * signatures with a DSA key using OpenSSL::PKey#sign. - * Starting with OpenSSL 1.0.0, digest algorithms are no longer restricted, - * any Digest may be used for signing. */ cDSA = rb_define_class_under(mPKey, "DSA", cPKey); rb_define_singleton_method(cDSA, "generate", ossl_dsa_s_generate, 1); rb_define_method(cDSA, "initialize", ossl_dsa_initialize, -1); - rb_define_copy_func(cDSA, ossl_dsa_initialize_copy); + rb_define_method(cDSA, "initialize_copy", ossl_dsa_initialize_copy, 1); rb_define_method(cDSA, "public?", ossl_dsa_is_public, 0); rb_define_method(cDSA, "private?", ossl_dsa_is_private, 0); diff --git a/ext/openssl/ossl_pkey_ec.c b/ext/openssl/ossl_pkey_ec.c index 5262d3b206..9c406931a9 100644 --- a/ext/openssl/ossl_pkey_ec.c +++ b/ext/openssl/ossl_pkey_ec.c @@ -4,7 +4,7 @@ #include "ossl.h" -#if !defined(OPENSSL_NO_EC) && (OPENSSL_VERSION_NUMBER >= 0x0090802fL) +#if !defined(OPENSSL_NO_EC) #define EXPORT_PEM 0 #define EXPORT_DER 1 @@ -23,33 +23,21 @@ static const rb_data_type_t ossl_ec_point_type; GetPKeyEC(obj, _pkey); \ (key) = EVP_PKEY_get0_EC_KEY(_pkey); \ } while (0) -#define SafeGetEC(obj, key) do { \ - OSSL_Check_Kind(obj, cEC); \ - GetEC(obj, key); \ -} while (0) #define GetECGroup(obj, group) do { \ TypedData_Get_Struct(obj, EC_GROUP, &ossl_ec_group_type, group); \ if ((group) == NULL) \ ossl_raise(eEC_GROUP, "EC_GROUP is not initialized"); \ } while (0) -#define SafeGetECGroup(obj, group) do { \ - OSSL_Check_Kind((obj), cEC_GROUP); \ - GetECGroup(obj, group); \ -} while (0) #define GetECPoint(obj, point) do { \ TypedData_Get_Struct(obj, EC_POINT, &ossl_ec_point_type, point); \ if ((point) == NULL) \ ossl_raise(eEC_POINT, "EC_POINT is not initialized"); \ } while (0) -#define SafeGetECPoint(obj, point) do { \ - OSSL_Check_Kind((obj), cEC_POINT); \ - GetECPoint(obj, point); \ -} while(0) #define GetECPointGroup(obj, group) do { \ VALUE _group = rb_attr_get(obj, id_i_group); \ - SafeGetECGroup(_group, group); \ + GetECGroup(_group, group); \ } while (0) VALUE cEC; @@ -128,7 +116,7 @@ ec_key_new_from_group(VALUE arg) if (rb_obj_is_kind_of(arg, cEC_GROUP)) { EC_GROUP *group; - SafeGetECGroup(arg, group); + GetECGroup(arg, group); if (!(ec = EC_KEY_new())) ossl_raise(eECError, NULL); @@ -208,7 +196,7 @@ static VALUE ossl_ec_key_initialize(int argc, VALUE *argv, VALUE self) } else if (rb_obj_is_kind_of(arg, cEC)) { EC_KEY *other_ec = NULL; - SafeGetEC(arg, other_ec); + 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)) { @@ -257,7 +245,7 @@ ossl_ec_key_initialize_copy(VALUE self, VALUE other) GetPKey(self, pkey); if (EVP_PKEY_base_id(pkey) != EVP_PKEY_NONE) ossl_raise(eECError, "EC already initialized"); - SafeGetEC(other, ec); + GetEC(other, ec); ec_new = EC_KEY_dup(ec); if (!ec_new) @@ -275,7 +263,7 @@ ossl_ec_key_initialize_copy(VALUE self, VALUE other) * key.group => group * * Returns the EC::Group that the key is associated with. Modifying the returned - * group does not affect +key+. + * group does not affect _key_. */ static VALUE ossl_ec_key_get_group(VALUE self) @@ -296,7 +284,7 @@ ossl_ec_key_get_group(VALUE self) * key.group = group * * Sets the EC::Group for the key. The group structure is internally copied so - * modification to +group+ after assigning to a key has no effect on the key. + * modification to _group_ after assigning to a key has no effect on the key. */ static VALUE ossl_ec_key_set_group(VALUE self, VALUE group_v) @@ -305,7 +293,7 @@ ossl_ec_key_set_group(VALUE self, VALUE group_v) EC_GROUP *group; GetEC(self, ec); - SafeGetECGroup(group_v, group); + GetECGroup(group_v, group); if (EC_KEY_set_group(ec, group) != 1) ossl_raise(eECError, "EC_KEY_set_group"); @@ -390,7 +378,7 @@ static VALUE ossl_ec_key_set_public_key(VALUE self, VALUE public_key) GetEC(self, ec); if (!NIL_P(public_key)) - SafeGetECPoint(public_key, point); + GetECPoint(public_key, point); switch (EC_KEY_set_public_key(ec, point)) { case 1: @@ -458,7 +446,7 @@ static VALUE ossl_ec_key_to_string(VALUE self, VALUE ciph, VALUE pass, int forma private = 1; if (!NIL_P(ciph)) { - cipher = GetCipherPtr(ciph); + cipher = ossl_evp_get_cipherbyname(ciph); pass = ossl_pem_passwd_value(pass); } @@ -502,8 +490,8 @@ static VALUE ossl_ec_key_to_string(VALUE self, VALUE ciph, VALUE pass, int forma * key.export([cipher, pass_phrase]) => String * key.to_pem([cipher, pass_phrase]) => String * - * Outputs the EC key in PEM encoding. If +cipher+ and +pass_phrase+ are given - * they will be used to encrypt the key. +cipher+ must be an OpenSSL::Cipher + * Outputs the EC key in PEM encoding. If _cipher_ and _pass_phrase_ are given + * they will be used to encrypt the key. _cipher_ must be an OpenSSL::Cipher * instance. Note that encryption will only be effective for a private key, * public keys will always be encoded in plain text. */ @@ -608,7 +596,7 @@ static VALUE ossl_ec_key_dh_compute_key(VALUE self, VALUE pubkey) VALUE str; GetEC(self, ec); - SafeGetECPoint(pubkey, point); + GetECPoint(pubkey, point); /* BUG: need a way to figure out the maximum string size */ buf_len = 1024; @@ -724,7 +712,7 @@ ec_group_new(const EC_GROUP *group) * * Creates a new EC::Group object. * - * +ec_method+ is a symbol that represents an EC_METHOD. Currently the following + * _ec_method_ is a symbol that represents an EC_METHOD. Currently the following * are supported: * * * :GFp_simple @@ -771,7 +759,7 @@ static VALUE ossl_ec_group_initialize(int argc, VALUE *argv, VALUE self) } else if (rb_obj_is_kind_of(arg1, cEC_GROUP)) { const EC_GROUP *arg1_group; - SafeGetECGroup(arg1, arg1_group); + GetECGroup(arg1, arg1_group); if ((group = EC_GROUP_dup(arg1_group)) == NULL) ossl_raise(eEC_GROUP, "EC_GROUP_dup"); } else { @@ -847,7 +835,7 @@ ossl_ec_group_initialize_copy(VALUE self, VALUE other) TypedData_Get_Struct(self, EC_GROUP, &ossl_ec_group_type, group_new); if (group_new) ossl_raise(eEC_GROUP, "EC::Group already initialized"); - SafeGetECGroup(other, group); + GetECGroup(other, group); group_new = EC_GROUP_dup(group); if (!group_new) @@ -862,15 +850,15 @@ ossl_ec_group_initialize_copy(VALUE self, VALUE other) * group1.eql?(group2) => true | false * group1 == group2 => true | false * - * Returns true if the two groups use the same curve and have the same - * parameters, false otherwise. + * Returns +true+ if the two groups use the same curve and have the same + * parameters, +false+ otherwise. */ static VALUE ossl_ec_group_eql(VALUE a, VALUE b) { EC_GROUP *group1 = NULL, *group2 = NULL; GetECGroup(a, group1); - SafeGetECGroup(b, group2); + GetECGroup(b, group2); if (EC_GROUP_cmp(group1, group2, ossl_bn_ctx) == 1) return Qfalse; @@ -903,8 +891,8 @@ static VALUE ossl_ec_group_get_generator(VALUE self) * call-seq: * group.set_generator(generator, order, cofactor) => self * - * Sets the curve parameters. +generator+ must be an instance of EC::Point that - * is on the curve. +order+ and +cofactor+ are integers. + * Sets the curve parameters. _generator_ must be an instance of EC::Point that + * is on the curve. _order_ and _cofactor_ are integers. * * See the OpenSSL documentation for EC_GROUP_set_generator() */ @@ -915,7 +903,7 @@ static VALUE ossl_ec_group_set_generator(VALUE self, VALUE generator, VALUE orde const BIGNUM *o, *co; GetECGroup(self, group); - SafeGetECPoint(generator, point); + GetECPoint(generator, point); o = GetBNPtr(order); co = GetBNPtr(cofactor); @@ -1127,14 +1115,14 @@ parse_point_conversion_form_symbol(VALUE sym) * * Sets the form how EC::Point data is encoded as ASN.1 as defined in X9.62. * - * +format+ can be one of these: + * _format_ can be one of these: * - * :compressed:: + * +:compressed+:: * Encoded as z||x, where z is an octet indicating which solution of the * equation y is. z will be 0x02 or 0x03. - * :uncompressed:: + * +:uncompressed+:: * Encoded as z||x||y, where z is an octet 0x04. - * :hybrid:: + * +:hybrid+:: * Encodes as z||x||y, where z is an octet indicating which solution of the * equation y is. z will be 0x06 or 0x07. * @@ -1356,13 +1344,13 @@ static VALUE ossl_ec_point_initialize(int argc, VALUE *argv, VALUE self) const EC_POINT *arg_point; group_v = rb_attr_get(arg1, id_i_group); - SafeGetECGroup(group_v, group); - SafeGetECPoint(arg1, arg_point); + GetECGroup(group_v, group); + GetECPoint(arg1, arg_point); point = EC_POINT_dup(arg_point, group); } else if (rb_obj_is_kind_of(arg1, cEC_GROUP)) { group_v = arg1; - SafeGetECGroup(group_v, group); + GetECGroup(group_v, group); point = EC_POINT_new(group); } else { @@ -1374,7 +1362,7 @@ static VALUE ossl_ec_point_initialize(int argc, VALUE *argv, VALUE self) if (!rb_obj_is_kind_of(arg1, cEC_GROUP)) ossl_raise(rb_eArgError, "1st argument must be OpenSSL::PKey::EC::Group"); group_v = arg1; - SafeGetECGroup(group_v, group); + GetECGroup(group_v, group); if (rb_obj_is_kind_of(arg2, cBN)) { const BIGNUM *bn = GetBNPtr(arg2); @@ -1418,10 +1406,10 @@ ossl_ec_point_initialize_copy(VALUE self, VALUE other) TypedData_Get_Struct(self, EC_POINT, &ossl_ec_point_type, point_new); if (point_new) ossl_raise(eEC_POINT, "EC::Point already initialized"); - SafeGetECPoint(other, point); + GetECPoint(other, point); group_v = rb_obj_dup(rb_attr_get(other, id_i_group)); - SafeGetECGroup(group_v, group); + GetECGroup(group_v, group); point_new = EC_POINT_dup(point, group); if (!point_new) @@ -1448,8 +1436,8 @@ static VALUE ossl_ec_point_eql(VALUE a, VALUE b) return Qfalse; GetECPoint(a, point1); - SafeGetECPoint(b, point2); - SafeGetECGroup(group_v1, group); + GetECPoint(b, point2); + GetECGroup(group_v1, group); if (EC_POINT_cmp(group, point1, point2, ossl_bn_ctx) == 1) return Qfalse; @@ -1558,7 +1546,7 @@ static VALUE ossl_ec_point_set_to_infinity(VALUE self) * point.to_bn(conversion_form = nil) => OpenSSL::BN * * Convert the EC point into an octet string and store in an OpenSSL::BN. If - * +conversion_form+ is given, the point data is converted using the specified + * _conversion_form_ is given, the point data is converted using the specified * form. If not given, the default form set in the EC::Group object is used. * * See also EC::Point#point_conversion_form=. @@ -1597,12 +1585,12 @@ ossl_ec_point_to_bn(int argc, VALUE *argv, VALUE self) * Performs elliptic curve point multiplication. * * The first form calculates bn1 * point + bn2 * G, where +G+ is the - * generator of the group of +point+. +bn2+ may be omitted, and in that case, + * generator of the group of _point_. _bn2_ may be omitted, and in that case, * the result is just bn1 * point. * * The second form calculates bns[0] * point + bns[1] * points[0] + ... - * + bns[-1] * points[-1] + bn2 * G. +bn2+ may be omitted. +bns+ must be - * an array of OpenSSL::BN. +points+ must be an array of + * + bns[-1] * points[-1] + bn2 * G. _bn2_ may be omitted. _bns_ must be + * an array of OpenSSL::BN. _points_ must be an array of * OpenSSL::PKey::EC::Point. Please note that points[0] is not * multiplied by bns[0], but bns[1]. */ @@ -1615,7 +1603,7 @@ static VALUE ossl_ec_point_mul(int argc, VALUE *argv, VALUE self) const BIGNUM *bn_g = NULL; GetECPoint(self, point_self); - SafeGetECGroup(group_v, group); + GetECGroup(group_v, group); result = rb_obj_alloc(cEC_POINT); ossl_ec_point_initialize(1, &group_v, result); @@ -1656,7 +1644,7 @@ static VALUE ossl_ec_point_mul(int argc, VALUE *argv, VALUE self) points = ALLOCV_N(const EC_POINT *, tmp_p, num); points[0] = point_self; /* self */ for (i = 0; i < num - 1; i++) - SafeGetECPoint(RARRAY_AREF(arg2, i), points[i + 1]); + GetECPoint(RARRAY_AREF(arg2, i), points[i + 1]); if (!NIL_P(arg3)) bn_g = GetBNPtr(arg3); @@ -1726,7 +1714,7 @@ void Init_ossl_ec(void) rb_define_singleton_method(cEC, "generate", ossl_ec_key_s_generate, 1); rb_define_method(cEC, "initialize", ossl_ec_key_initialize, -1); - rb_define_copy_func(cEC, ossl_ec_key_initialize_copy); + rb_define_method(cEC, "initialize_copy", ossl_ec_key_initialize_copy, 1); /* copy/dup/cmp */ rb_define_method(cEC, "group", ossl_ec_key_get_group, 0); @@ -1763,7 +1751,7 @@ void Init_ossl_ec(void) rb_define_alloc_func(cEC_GROUP, ossl_ec_group_alloc); rb_define_method(cEC_GROUP, "initialize", ossl_ec_group_initialize, -1); - rb_define_copy_func(cEC_GROUP, ossl_ec_group_initialize_copy); + rb_define_method(cEC_GROUP, "initialize_copy", ossl_ec_group_initialize_copy, 1); rb_define_method(cEC_GROUP, "eql?", ossl_ec_group_eql, 1); rb_define_alias(cEC_GROUP, "==", "eql?"); /* copy/dup/cmp */ @@ -1799,7 +1787,7 @@ void Init_ossl_ec(void) rb_define_alloc_func(cEC_POINT, ossl_ec_point_alloc); rb_define_method(cEC_POINT, "initialize", ossl_ec_point_initialize, -1); - rb_define_copy_func(cEC_POINT, ossl_ec_point_initialize_copy); + rb_define_method(cEC_POINT, "initialize_copy", ossl_ec_point_initialize_copy, 1); rb_attr(cEC_POINT, rb_intern("group"), 1, 0, 0); rb_define_method(cEC_POINT, "eql?", ossl_ec_point_eql, 1); rb_define_alias(cEC_POINT, "==", "eql?"); diff --git a/ext/openssl/ossl_pkey_rsa.c b/ext/openssl/ossl_pkey_rsa.c index 1fcdd52cf4..26397bd021 100644 --- a/ext/openssl/ossl_pkey_rsa.c +++ b/ext/openssl/ossl_pkey_rsa.c @@ -172,8 +172,8 @@ rsa_generate(int size, unsigned long exp) * RSA.generate(size) => RSA instance * RSA.generate(size, exponent) => RSA instance * - * Generates an RSA keypair. +size+ is an integer representing the desired key - * size. Keys smaller than 1024 should be considered insecure. +exponent+ is + * Generates an RSA keypair. _size_ is an integer representing the desired key + * size. Keys smaller than 1024 should be considered insecure. _exponent_ is * an odd number normally 3, 17, or 65537. */ static VALUE @@ -203,12 +203,12 @@ ossl_rsa_s_generate(int argc, VALUE *argv, VALUE klass) * RSA.new(encoded_key) => RSA instance * RSA.new(encoded_key, pass_phrase) => RSA instance * - * Generates or loads an RSA keypair. If an integer +key_size+ is given it + * Generates or loads an RSA keypair. If an integer _key_size_ is given it * represents the desired key size. Keys less than 1024 bits should be * considered insecure. * - * A key can instead be loaded from an +encoded_key+ which must be PEM or DER - * encoded. A +pass_phrase+ can be used to decrypt the key. If none is given + * A key can instead be loaded from an _encoded_key_ which must be PEM or DER + * encoded. A _pass_phrase_ can be used to decrypt the key. If none is given * OpenSSL will prompt for the pass phrase. * * = Examples @@ -295,7 +295,7 @@ ossl_rsa_initialize_copy(VALUE self, VALUE other) * call-seq: * rsa.public? => true * - * The return value is always true since every private key is also a public + * The return value is always +true+ since every private key is also a public * key. */ static VALUE @@ -333,8 +333,8 @@ ossl_rsa_is_private(VALUE self) * rsa.to_pem([cipher, pass_phrase]) => PEM-format String * rsa.to_s([cipher, pass_phrase]) => PEM-format String * - * Outputs this keypair in PEM encoding. If +cipher+ and +pass_phrase+ are - * given they will be used to encrypt the key. +cipher+ must be an + * Outputs this keypair in PEM encoding. If _cipher_ and _pass_phrase_ are + * given they will be used to encrypt the key. _cipher_ must be an * OpenSSL::Cipher instance. */ static VALUE @@ -350,7 +350,7 @@ ossl_rsa_export(int argc, VALUE *argv, VALUE self) rb_scan_args(argc, argv, "02", &cipher, &pass); if (!NIL_P(cipher)) { - ciph = GetCipherPtr(cipher); + ciph = ossl_evp_get_cipherbyname(cipher); pass = ossl_pem_passwd_value(pass); } if (!(out = BIO_new(BIO_s_mem()))) { @@ -409,7 +409,7 @@ ossl_rsa_to_der(VALUE self) * rsa.public_encrypt(string) => String * rsa.public_encrypt(string, padding) => String * - * Encrypt +string+ with the public key. +padding+ defaults to PKCS1_PADDING. + * Encrypt _string_ with the public key. _padding_ defaults to PKCS1_PADDING. * The encrypted string output can be decrypted using #private_decrypt. */ static VALUE @@ -441,8 +441,8 @@ ossl_rsa_public_encrypt(int argc, VALUE *argv, VALUE self) * rsa.public_decrypt(string) => String * rsa.public_decrypt(string, padding) => String * - * Decrypt +string+, which has been encrypted with the private key, with the - * public key. +padding+ defaults to PKCS1_PADDING. + * Decrypt _string_, which has been encrypted with the private key, with the + * public key. _padding_ defaults to PKCS1_PADDING. */ static VALUE ossl_rsa_public_decrypt(int argc, VALUE *argv, VALUE self) @@ -473,7 +473,7 @@ ossl_rsa_public_decrypt(int argc, VALUE *argv, VALUE self) * rsa.private_encrypt(string) => String * rsa.private_encrypt(string, padding) => String * - * Encrypt +string+ with the private key. +padding+ defaults to PKCS1_PADDING. + * Encrypt _string_ with the private key. _padding_ defaults to PKCS1_PADDING. * The encrypted string output can be decrypted using #public_decrypt. */ static VALUE @@ -507,8 +507,8 @@ ossl_rsa_private_encrypt(int argc, VALUE *argv, VALUE self) * rsa.private_decrypt(string) => String * rsa.private_decrypt(string, padding) => String * - * Decrypt +string+, which has been encrypted with the public key, with the - * private key. +padding+ defaults to PKCS1_PADDING. + * Decrypt _string_, which has been encrypted with the public key, with the + * private key. _padding_ defaults to PKCS1_PADDING. */ static VALUE ossl_rsa_private_decrypt(int argc, VALUE *argv, VALUE self) @@ -659,7 +659,7 @@ ossl_rsa_blinding_off(VALUE self) * call-seq: * rsa.set_key(n, e, d) -> self * - * Sets +n+, +e+, +d+ for the RSA instance. + * Sets _n_, _e_, _d_ for the RSA instance. */ OSSL_PKEY_BN_DEF3(rsa, RSA, key, n, e, d) /* @@ -667,7 +667,7 @@ OSSL_PKEY_BN_DEF3(rsa, RSA, key, n, e, d) * call-seq: * rsa.set_factors(p, q) -> self * - * Sets +p+, +q+ for the RSA instance. + * Sets _p_, _q_ for the RSA instance. */ OSSL_PKEY_BN_DEF2(rsa, RSA, factors, p, q) /* @@ -675,7 +675,7 @@ OSSL_PKEY_BN_DEF2(rsa, RSA, factors, p, q) * call-seq: * rsa.set_crt_params(dmp1, dmq1, iqmp) -> self * - * Sets +dmp1+, +dmq1+, +iqmp+ for the RSA instance. They are calculated by + * Sets _dmp1_, _dmq1_, _iqmp_ for the RSA instance. They are calculated by * d mod (p - 1), d mod (q - 1) and q^(-1) mod p * respectively. */ @@ -717,7 +717,7 @@ Init_ossl_rsa(void) rb_define_singleton_method(cRSA, "generate", ossl_rsa_s_generate, -1); rb_define_method(cRSA, "initialize", ossl_rsa_initialize, -1); - rb_define_copy_func(cRSA, ossl_rsa_initialize_copy); + rb_define_method(cRSA, "initialize_copy", ossl_rsa_initialize_copy, 1); rb_define_method(cRSA, "public?", ossl_rsa_is_public, 0); rb_define_method(cRSA, "private?", ossl_rsa_is_private, 0); diff --git a/ext/openssl/ossl_rand.c b/ext/openssl/ossl_rand.c index 688c525afa..c95857060a 100644 --- a/ext/openssl/ossl_rand.c +++ b/ext/openssl/ossl_rand.c @@ -16,7 +16,7 @@ VALUE eRandomError; * call-seq: * seed(str) -> str * - * ::seed is equivalent to ::add where +entropy+ is length of +str+. + * ::seed is equivalent to ::add where _entropy_ is length of _str_. */ static VALUE ossl_rand_seed(VALUE self, VALUE str) @@ -31,15 +31,15 @@ ossl_rand_seed(VALUE self, VALUE str) * call-seq: * add(str, entropy) -> self * - * Mixes the bytes from +str+ into the Pseudo Random Number Generator(PRNG) + * Mixes the bytes from _str_ into the Pseudo Random Number Generator(PRNG) * state. * - * Thus, if the data from +str+ are unpredictable to an adversary, this + * Thus, if the data from _str_ are unpredictable to an adversary, this * increases the uncertainty about the state and makes the PRNG output less * predictable. * - * The +entropy+ argument is (the lower bound of) an estimate of how much - * randomness is contained in +str+, measured in bytes. + * The _entropy_ argument is (the lower bound of) an estimate of how much + * randomness is contained in _str_, measured in bytes. * * === Example * @@ -62,7 +62,7 @@ ossl_rand_add(VALUE self, VALUE str, VALUE entropy) * call-seq: * load_random_file(filename) -> true * - * Reads bytes from +filename+ and adds them to the PRNG. + * Reads bytes from _filename_ and adds them to the PRNG. */ static VALUE ossl_rand_load_file(VALUE self, VALUE filename) @@ -79,7 +79,7 @@ ossl_rand_load_file(VALUE self, VALUE filename) * call-seq: * write_random_file(filename) -> true * - * Writes a number of random generated bytes (currently 1024) to +filename+ + * Writes a number of random generated bytes (currently 1024) to _filename_ * which can be used to initialize the PRNG by calling ::load_random_file in a * later session. */ @@ -98,7 +98,7 @@ ossl_rand_write_file(VALUE self, VALUE filename) * call-seq: * random_bytes(length) -> string * - * Generates +string+ with +length+ number of cryptographically strong + * Generates a String with _length_ number of cryptographically strong * pseudo-random bytes. * * === Example @@ -129,7 +129,7 @@ ossl_rand_bytes(VALUE self, VALUE len) * call-seq: * pseudo_bytes(length) -> string * - * Generates +string+ with +length+ number of pseudo-random bytes. + * Generates a String with _length_ number of pseudo-random bytes. * * Pseudo-random byte sequences generated by ::pseudo_bytes will be unique if * they are of sufficient length, but are not necessarily unpredictable. @@ -176,9 +176,9 @@ ossl_rand_egd(VALUE self, VALUE filename) * call-seq: * egd_bytes(filename, length) -> true * - * Queries the entropy gathering daemon EGD on socket path given by +filename+. + * Queries the entropy gathering daemon EGD on socket path given by _filename_. * - * Fetches +length+ number of bytes and uses ::add to seed the OpenSSL built-in + * Fetches _length_ number of bytes and uses ::add to seed the OpenSSL built-in * PRNG. */ static VALUE @@ -199,7 +199,7 @@ ossl_rand_egd_bytes(VALUE self, VALUE filename, VALUE len) * call-seq: * status? => true | false * - * Return true if the PRNG has been seeded with enough data, false otherwise. + * Return +true+ if the PRNG has been seeded with enough data, +false+ otherwise. */ static VALUE ossl_rand_status(VALUE self) diff --git a/ext/openssl/ossl_ssl.c b/ext/openssl/ossl_ssl.c index f9c9d76fc2..18d5f5e9ec 100644 --- a/ext/openssl/ossl_ssl.c +++ b/ext/openssl/ossl_ssl.c @@ -46,54 +46,19 @@ static ID id_i_cert_store, id_i_ca_file, id_i_ca_path, id_i_verify_mode, id_i_verify_hostname; static ID id_i_io, id_i_context, id_i_hostname; -/* - * SSLContext class - */ -static const struct { - const char *name; - SSL_METHOD *(*func)(void); /* FIXME: constify when dropping 0.9.8 */ - int version; -} ossl_ssl_method_tab[] = { -#if defined(HAVE_SSL_CTX_SET_MIN_PROTO_VERSION) -#define OSSL_SSL_METHOD_ENTRY(name, version) \ - { #name, (SSL_METHOD *(*)(void))TLS_method, version }, \ - { #name"_server", (SSL_METHOD *(*)(void))TLS_server_method, version }, \ - { #name"_client", (SSL_METHOD *(*)(void))TLS_client_method, version } -#else -#define OSSL_SSL_METHOD_ENTRY(name, version) \ - { #name, (SSL_METHOD *(*)(void))name##_method, version }, \ - { #name"_server", (SSL_METHOD *(*)(void))name##_server_method, version }, \ - { #name"_client", (SSL_METHOD *(*)(void))name##_client_method, version } -#endif -#if !defined(OPENSSL_NO_SSL2) && !defined(OPENSSL_NO_SSL2_METHOD) && defined(HAVE_SSLV2_METHOD) - OSSL_SSL_METHOD_ENTRY(SSLv2, SSL2_VERSION), -#endif -#if !defined(OPENSSL_NO_SSL3) && !defined(OPENSSL_NO_SSL3_METHOD) && defined(HAVE_SSLV3_METHOD) - OSSL_SSL_METHOD_ENTRY(SSLv3, SSL3_VERSION), -#endif -#if !defined(OPENSSL_NO_TLS1) && !defined(OPENSSL_NO_TLS1_METHOD) - OSSL_SSL_METHOD_ENTRY(TLSv1, TLS1_VERSION), -#endif -#if !defined(OPENSSL_NO_TLS1_1) && !defined(OPENSSL_NO_TLS1_1_METHOD) && defined(HAVE_TLSV1_1_METHOD) - OSSL_SSL_METHOD_ENTRY(TLSv1_1, TLS1_1_VERSION), -#endif -#if !defined(OPENSSL_NO_TLS1_2) && !defined(OPENSSL_NO_TLS1_2_METHOD) && defined(HAVE_TLSV1_2_METHOD) - OSSL_SSL_METHOD_ENTRY(TLSv1_2, TLS1_2_VERSION), -#endif - OSSL_SSL_METHOD_ENTRY(SSLv23, 0), -#undef OSSL_SSL_METHOD_ENTRY -}; - static int ossl_ssl_ex_vcb_idx; -static int ossl_ssl_ex_store_p; static int ossl_ssl_ex_ptr_idx; +static int ossl_sslctx_ex_ptr_idx; +#if !defined(HAVE_X509_STORE_UP_REF) +static int ossl_sslctx_ex_store_p; +#endif static void ossl_sslctx_free(void *ptr) { SSL_CTX *ctx = ptr; #if !defined(HAVE_X509_STORE_UP_REF) - if(ctx && SSL_CTX_get_ex_data(ctx, ossl_ssl_ex_store_p)== (void*)1) + if (ctx && SSL_CTX_get_ex_data(ctx, ossl_sslctx_ex_store_p)) ctx->cert_store = NULL; #endif SSL_CTX_free(ctx); @@ -111,22 +76,24 @@ static VALUE ossl_sslctx_s_alloc(VALUE klass) { SSL_CTX *ctx; - long mode = SSL_MODE_ENABLE_PARTIAL_WRITE | - SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER; + long mode = 0 | + SSL_MODE_ENABLE_PARTIAL_WRITE | + SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER | + SSL_MODE_RELEASE_BUFFERS; VALUE obj; -#ifdef SSL_MODE_RELEASE_BUFFERS - mode |= SSL_MODE_RELEASE_BUFFERS; -#endif - obj = TypedData_Wrap_Struct(klass, &ossl_sslctx_type, 0); +#if OPENSSL_VERSION_NUMBER >= 0x10100000 && !defined(LIBRESSL_VERSION_NUMBER) + ctx = SSL_CTX_new(TLS_method()); +#else ctx = SSL_CTX_new(SSLv23_method()); +#endif if (!ctx) { ossl_raise(eSSLError, "SSL_CTX_new"); } SSL_CTX_set_mode(ctx, mode); RTYPEDDATA_DATA(obj) = ctx; - SSL_CTX_set_ex_data(ctx, ossl_ssl_ex_ptr_idx, (void*)obj); + SSL_CTX_set_ex_data(ctx, ossl_sslctx_ex_ptr_idx, (void *)obj); #if !defined(OPENSSL_NO_EC) && defined(HAVE_SSL_CTX_SET_ECDH_AUTO) /* We use SSL_CTX_set1_curves_list() to specify the curve used in ECDH. It @@ -143,49 +110,89 @@ ossl_sslctx_s_alloc(VALUE klass) return obj; } +static int +parse_proto_version(VALUE str) +{ + int i; + static const struct { + const char *name; + int version; + } map[] = { + { "SSL2", SSL2_VERSION }, + { "SSL3", SSL3_VERSION }, + { "TLS1", TLS1_VERSION }, + { "TLS1_1", TLS1_1_VERSION }, + { "TLS1_2", TLS1_2_VERSION }, +#ifdef TLS1_3_VERSION + { "TLS1_3", TLS1_3_VERSION }, +#endif + }; + + if (NIL_P(str)) + return 0; + if (RB_INTEGER_TYPE_P(str)) + return NUM2INT(str); + + if (SYMBOL_P(str)) + str = rb_sym2str(str); + StringValue(str); + for (i = 0; i < numberof(map); i++) + if (!strncmp(map[i].name, RSTRING_PTR(str), RSTRING_LEN(str))) + return map[i].version; + rb_raise(rb_eArgError, "unrecognized version %+"PRIsVALUE, str); +} + /* * call-seq: - * ctx.ssl_version = :TLSv1 - * ctx.ssl_version = "SSLv23_client" + * ctx.set_minmax_proto_version(min, max) -> nil * - * Sets the SSL/TLS protocol version for the context. This forces connections to - * use only the specified protocol version. - * - * You can get a list of valid versions with OpenSSL::SSL::SSLContext::METHODS + * Sets the minimum and maximum supported protocol versions. See #min_version= + * and #max_version=. */ static VALUE -ossl_sslctx_set_ssl_version(VALUE self, VALUE ssl_method) +ossl_sslctx_set_minmax_proto_version(VALUE self, VALUE min_v, VALUE max_v) { SSL_CTX *ctx; - const char *s; - VALUE m = ssl_method; - int i; + int min, max; GetSSLCTX(self, ctx); - if (RB_TYPE_P(ssl_method, T_SYMBOL)) - m = rb_sym2str(ssl_method); - s = StringValueCStr(m); - for (i = 0; i < numberof(ossl_ssl_method_tab); i++) { - if (strcmp(ossl_ssl_method_tab[i].name, s) == 0) { -#if defined(HAVE_SSL_CTX_SET_MIN_PROTO_VERSION) - int version = ossl_ssl_method_tab[i].version; -#endif - SSL_METHOD *method = ossl_ssl_method_tab[i].func(); - - if (SSL_CTX_set_ssl_version(ctx, method) != 1) - ossl_raise(eSSLError, "SSL_CTX_set_ssl_version"); + min = parse_proto_version(min_v); + max = parse_proto_version(max_v); + +#ifdef HAVE_SSL_CTX_SET_MIN_PROTO_VERSION + if (!SSL_CTX_set_min_proto_version(ctx, min)) + ossl_raise(eSSLError, "SSL_CTX_set_min_proto_version"); + if (!SSL_CTX_set_max_proto_version(ctx, max)) + ossl_raise(eSSLError, "SSL_CTX_set_max_proto_version"); +#else + { + unsigned long sum = 0, opts = 0; + int i; + static const struct { + int ver; + unsigned long opts; + } options_map[] = { + { SSL2_VERSION, SSL_OP_NO_SSLv2 }, + { SSL3_VERSION, SSL_OP_NO_SSLv3 }, + { TLS1_VERSION, SSL_OP_NO_TLSv1 }, + { TLS1_1_VERSION, SSL_OP_NO_TLSv1_1 }, + { TLS1_2_VERSION, SSL_OP_NO_TLSv1_2 }, +# if defined(TLS1_3_VERSION) + { TLS1_3_VERSION, SSL_OP_NO_TLSv1_3 }, +# endif + }; -#if defined(HAVE_SSL_CTX_SET_MIN_PROTO_VERSION) - if (!SSL_CTX_set_min_proto_version(ctx, version)) - ossl_raise(eSSLError, "SSL_CTX_set_min_proto_version"); - if (!SSL_CTX_set_max_proto_version(ctx, version)) - ossl_raise(eSSLError, "SSL_CTX_set_max_proto_version"); -#endif - return ssl_method; - } + for (i = 0; i < numberof(options_map); i++) { + sum |= options_map[i].opts; + if (min && min > options_map[i].ver || max && max < options_map[i].ver) + opts |= options_map[i].opts; + } + SSL_CTX_clear_options(ctx, sum); + SSL_CTX_set_options(ctx, opts); } +#endif - ossl_raise(rb_eArgError, "unknown SSL method `%"PRIsVALUE"'.", m); + return Qnil; } static VALUE @@ -380,13 +387,10 @@ ossl_sslctx_session_get_cb(SSL *ssl, unsigned char *buf, int len, int *copy) { VALUE ary, ssl_obj, ret_obj; SSL_SESSION *sess; - void *ptr; int state = 0; OSSL_Debug("SSL SESSION get callback entered"); - if ((ptr = SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx)) == NULL) - return NULL; - ssl_obj = (VALUE)ptr; + ssl_obj = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx); ary = rb_ary_new2(2); rb_ary_push(ary, ssl_obj); rb_ary_push(ary, rb_str_new((const char *)buf, len)); @@ -399,7 +403,7 @@ ossl_sslctx_session_get_cb(SSL *ssl, unsigned char *buf, int len, int *copy) if (!rb_obj_is_instance_of(ret_obj, cSSLSession)) return NULL; - SafeGetSSLSession(ret_obj, sess); + GetSSLSession(ret_obj, sess); *copy = 1; return sess; @@ -424,14 +428,11 @@ static int ossl_sslctx_session_new_cb(SSL *ssl, SSL_SESSION *sess) { VALUE ary, ssl_obj, sess_obj; - void *ptr; int state = 0; OSSL_Debug("SSL SESSION new callback entered"); - if ((ptr = SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx)) == NULL) - return 1; - ssl_obj = (VALUE)ptr; + ssl_obj = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx); sess_obj = rb_obj_alloc(cSSLSession); SSL_SESSION_up_ref(sess); DATA_PTR(sess_obj) = sess; @@ -473,14 +474,18 @@ static void ossl_sslctx_session_remove_cb(SSL_CTX *ctx, SSL_SESSION *sess) { VALUE ary, sslctx_obj, sess_obj; - void *ptr; int state = 0; + /* + * This callback is also called for all sessions in the internal store + * when SSL_CTX_free() is called. + */ + if (rb_during_gc()) + return; + OSSL_Debug("SSL SESSION remove callback entered"); - if ((ptr = SSL_CTX_get_ex_data(ctx, ossl_ssl_ex_ptr_idx)) == NULL) - return; - sslctx_obj = (VALUE)ptr; + sslctx_obj = (VALUE)SSL_CTX_get_ex_data(ctx, ossl_sslctx_ex_ptr_idx); sess_obj = rb_obj_alloc(cSSLSession); SSL_SESSION_up_ref(sess); DATA_PTR(sess_obj) = sess; @@ -516,7 +521,6 @@ ossl_sslctx_add_extra_chain_cert_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, arg)) static VALUE ossl_sslctx_setup(VALUE self); -#ifdef HAVE_SSL_SET_TLSEXT_HOST_NAME static VALUE ossl_call_servername_cb(VALUE ary) { @@ -551,16 +555,13 @@ static int ssl_servername_cb(SSL *ssl, int *ad, void *arg) { VALUE ary, ssl_obj; - void *ptr; int state = 0; const char *servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name); if (!servername) return SSL_TLSEXT_ERR_OK; - if ((ptr = SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx)) == NULL) - return SSL_TLSEXT_ERR_ALERT_FATAL; - ssl_obj = (VALUE)ptr; + ssl_obj = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx); ary = rb_ary_new2(2); rb_ary_push(ary, ssl_obj); rb_ary_push(ary, rb_str_new2(servername)); @@ -573,18 +574,13 @@ ssl_servername_cb(SSL *ssl, int *ad, void *arg) return SSL_TLSEXT_ERR_OK; } -#endif static void ssl_renegotiation_cb(const SSL *ssl) { VALUE ssl_obj, sslctx_obj, cb; - void *ptr; - - if ((ptr = SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx)) == NULL) - ossl_raise(eSSLError, "SSL object could not be retrieved"); - ssl_obj = (VALUE)ptr; + ssl_obj = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx); sslctx_obj = rb_attr_get(ssl_obj, id_i_context); cb = rb_attr_get(sslctx_obj, id_i_renegotiation_cb); if (NIL_P(cb)) return; @@ -592,7 +588,7 @@ ssl_renegotiation_cb(const SSL *ssl) (void) rb_funcall(cb, rb_intern("call"), 1, ssl_obj); } -#if defined(HAVE_SSL_CTX_SET_NEXT_PROTO_SELECT_CB) || \ +#if !defined(OPENSSL_NO_NEXTPROTONEG) || \ defined(HAVE_SSL_CTX_SET_ALPN_SELECT_CB) static VALUE ssl_npn_encode_protocol_i(VALUE cur, VALUE encoded) @@ -677,7 +673,7 @@ ssl_npn_select_cb_common(SSL *ssl, VALUE cb, const unsigned char **out, } #endif -#ifdef HAVE_SSL_CTX_SET_NEXT_PROTO_SELECT_CB +#ifndef OPENSSL_NO_NEXTPROTONEG static int ssl_npn_advertise_cb(SSL *ssl, const unsigned char **out, unsigned int *outlen, void *arg) @@ -737,7 +733,11 @@ ossl_sslctx_get_options(VALUE self) { SSL_CTX *ctx; GetSSLCTX(self, ctx); - return LONG2NUM(SSL_CTX_get_options(ctx)); + /* + * Do explicit cast because SSL_CTX_get_options() returned (signed) long in + * OpenSSL before 1.1.0. + */ + return ULONG2NUM((unsigned long)SSL_CTX_get_options(ctx)); } /* @@ -756,7 +756,7 @@ ossl_sslctx_set_options(VALUE self, VALUE options) if (NIL_P(options)) { SSL_CTX_set_options(ctx, SSL_OP_ALL); } else { - SSL_CTX_set_options(ctx, NUM2LONG(options)); + SSL_CTX_set_options(ctx, NUM2ULONG(options)); } return self; @@ -820,7 +820,7 @@ ossl_sslctx_setup(VALUE self) * X509_STORE_free() doesn't care it. * So we won't increment it but mark it by ex_data. */ - SSL_CTX_set_ex_data(ctx, ossl_ssl_ex_store_p, (void *)1); + SSL_CTX_set_ex_data(ctx, ossl_sslctx_ex_store_p, ctx); #else /* Fixed in OpenSSL 1.0.2; bff9ce4db38b (master), 5b4b9ce976fc (1.0.2) */ X509_STORE_up_ref(store); #endif @@ -891,7 +891,7 @@ ossl_sslctx_setup(VALUE self) val = rb_attr_get(self, id_i_verify_depth); if(!NIL_P(val)) SSL_CTX_set_verify_depth(ctx, NUM2INT(val)); -#ifdef HAVE_SSL_CTX_SET_NEXT_PROTO_SELECT_CB +#ifndef OPENSSL_NO_NEXTPROTONEG val = rb_attr_get(self, id_i_npn_protocols); if (!NIL_P(val)) { VALUE encoded = ssl_encode_npn_protocols(val); @@ -946,13 +946,11 @@ ossl_sslctx_setup(VALUE self) OSSL_Debug("SSL SESSION remove callback added"); } -#ifdef HAVE_SSL_SET_TLSEXT_HOST_NAME val = rb_attr_get(self, id_i_servername_cb); if (!NIL_P(val)) { SSL_CTX_set_tlsext_servername_callback(ctx, ssl_servername_cb); OSSL_Debug("SSL TLSEXT servername callback added"); } -#endif return Qtrue; } @@ -989,12 +987,7 @@ ossl_sslctx_get_ciphers(VALUE self) int i, num; GetSSLCTX(self, ctx); - if(!ctx){ - rb_warning("SSL_CTX is not initialized."); - return Qnil; - } ciphers = SSL_CTX_get_ciphers(ctx); - if (!ciphers) return rb_ary_new(); @@ -1204,7 +1197,7 @@ ossl_sslctx_set_security_level(VALUE self, VALUE value) * call-seq: * ctx.session_add(session) -> true | false * - * Adds +session+ to the session cache. + * Adds _session_ to the session cache. */ static VALUE ossl_sslctx_session_add(VALUE self, VALUE arg) @@ -1213,7 +1206,7 @@ ossl_sslctx_session_add(VALUE self, VALUE arg) SSL_SESSION *sess; GetSSLCTX(self, ctx); - SafeGetSSLSession(arg, sess); + GetSSLSession(arg, sess); return SSL_CTX_add_session(ctx, sess) == 1 ? Qtrue : Qfalse; } @@ -1222,7 +1215,7 @@ ossl_sslctx_session_add(VALUE self, VALUE arg) * call-seq: * ctx.session_remove(session) -> true | false * - * Removes +session+ from the session cache. + * Removes _session_ from the session cache. */ static VALUE ossl_sslctx_session_remove(VALUE self, VALUE arg) @@ -1231,7 +1224,7 @@ ossl_sslctx_session_remove(VALUE self, VALUE arg) SSL_SESSION *sess; GetSSLCTX(self, ctx); - SafeGetSSLSession(arg, sess); + GetSSLSession(arg, sess); return SSL_CTX_remove_session(ctx, sess) == 1 ? Qtrue : Qfalse; } @@ -1358,9 +1351,9 @@ ossl_sslctx_get_session_cache_stats(VALUE self) /* * call-seq: - * ctx.flush_sessions(time | nil) -> self + * ctx.flush_sessions(time) -> self * - * Removes sessions in the internal cache that have expired at +time+. + * Removes sessions in the internal cache that have expired at _time_. */ static VALUE ossl_sslctx_flush_sessions(int argc, VALUE *argv, VALUE self) @@ -1422,10 +1415,10 @@ ossl_ssl_s_alloc(VALUE klass) * SSLSocket.new(io) => aSSLSocket * SSLSocket.new(io, ctx) => aSSLSocket * - * Creates a new SSL socket from +io+ which must be a real IO object (not an + * Creates a new SSL socket from _io_ which must be a real IO object (not an * IO-like object that responds to read/write). * - * If +ctx+ is provided the SSL Sockets initial params will be taken from + * If _ctx_ is provided the SSL Sockets initial params will be taken from * the context. * * The OpenSSL::Buffering module provides additional IO methods. @@ -1485,7 +1478,7 @@ ossl_ssl_setup(VALUE self) GetOpenFile(io, fptr); rb_io_check_readable(fptr); rb_io_check_writable(fptr); - if (!SSL_set_fd(ssl, TO_SOCKET(FPTR_TO_FD(fptr)))) + if (!SSL_set_fd(ssl, TO_SOCKET(fptr->fd))) ossl_raise(eSSLError, "SSL_set_fd"); return Qtrue; @@ -1528,6 +1521,9 @@ ossl_start_ssl(VALUE self, int (*func)(), const char *funcname, VALUE opts) int ret, ret2; VALUE cb_state; int nonblock = opts != Qfalse; +#if defined(SSL_R_CERTIFICATE_VERIFY_FAILED) + unsigned long err; +#endif rb_ivar_set(self, ID_callback_state, Qnil); @@ -1551,16 +1547,33 @@ ossl_start_ssl(VALUE self, int (*func)(), const char *funcname, VALUE opts) case SSL_ERROR_WANT_WRITE: if (no_exception_p(opts)) { return sym_wait_writable; } write_would_block(nonblock); - rb_io_wait_writable(FPTR_TO_FD(fptr)); + rb_io_wait_writable(fptr->fd); continue; case SSL_ERROR_WANT_READ: if (no_exception_p(opts)) { return sym_wait_readable; } read_would_block(nonblock); - rb_io_wait_readable(FPTR_TO_FD(fptr)); + rb_io_wait_readable(fptr->fd); continue; case SSL_ERROR_SYSCALL: if (errno) rb_sys_fail(funcname); ossl_raise(eSSLError, "%s SYSCALL returned=%d errno=%d state=%s", funcname, ret2, errno, SSL_state_string_long(ssl)); +#if defined(SSL_R_CERTIFICATE_VERIFY_FAILED) + case SSL_ERROR_SSL: + err = ERR_peek_last_error(); + if (ERR_GET_LIB(err) == ERR_LIB_SSL && + ERR_GET_REASON(err) == SSL_R_CERTIFICATE_VERIFY_FAILED) { + const char *err_msg = ERR_reason_error_string(err), + *verify_msg = X509_verify_cert_error_string(SSL_get_verify_result(ssl)); + if (!err_msg) + err_msg = "(null)"; + if (!verify_msg) + verify_msg = "(null)"; + ossl_clear_error(); /* let ossl_raise() not append message */ + ossl_raise(eSSLError, "%s returned=%d errno=%d state=%s: %s (%s)", + funcname, ret2, errno, SSL_state_string_long(ssl), + err_msg, verify_msg); + } +#endif default: ossl_raise(eSSLError, "%s returned=%d errno=%d state=%s", funcname, ret2, errno, SSL_state_string_long(ssl)); } @@ -1693,8 +1706,6 @@ ossl_ssl_read_internal(int argc, VALUE *argv, VALUE self, int nonblock) io = rb_attr_get(self, id_i_io); GetOpenFile(io, fptr); if (ssl_started(ssl)) { - if(!nonblock && SSL_pending(ssl) <= 0) - rb_thread_wait_fd(FPTR_TO_FD(fptr)); for (;;){ nread = SSL_read(ssl, RSTRING_PTR(str), RSTRING_LENINT(str)); switch(ssl_get_error(ssl, nread)){ @@ -1706,12 +1717,12 @@ ossl_ssl_read_internal(int argc, VALUE *argv, VALUE self, int nonblock) case SSL_ERROR_WANT_WRITE: if (no_exception_p(opts)) { return sym_wait_writable; } write_would_block(nonblock); - rb_io_wait_writable(FPTR_TO_FD(fptr)); + rb_io_wait_writable(fptr->fd); continue; case SSL_ERROR_WANT_READ: if (no_exception_p(opts)) { return sym_wait_readable; } read_would_block(nonblock); - rb_io_wait_readable(FPTR_TO_FD(fptr)); + rb_io_wait_readable(fptr->fd); continue; case SSL_ERROR_SYSCALL: if (!ERR_peek_error()) { @@ -1756,7 +1767,7 @@ ossl_ssl_read_internal(int argc, VALUE *argv, VALUE self, int nonblock) * ssl.sysread(length) => string * ssl.sysread(length, buffer) => buffer * - * Reads +length+ bytes from the SSL connection. If a pre-allocated +buffer+ + * Reads _length_ bytes from the SSL connection. If a pre-allocated _buffer_ * is provided the data will be written into it. */ static VALUE @@ -1775,7 +1786,7 @@ ossl_ssl_read(int argc, VALUE *argv, VALUE self) * block. If "exception: false" is passed, this method returns a symbol of * :wait_readable, :wait_writable, or nil, rather than raising an exception. * - * Reads +length+ bytes from the SSL connection. If a pre-allocated +buffer+ + * Reads _length_ bytes from the SSL connection. If a pre-allocated _buffer_ * is provided the data will be written into it. */ static VALUE @@ -1812,12 +1823,12 @@ ossl_ssl_write_internal(VALUE self, VALUE str, VALUE opts) case SSL_ERROR_WANT_WRITE: if (no_exception_p(opts)) { return sym_wait_writable; } write_would_block(nonblock); - rb_io_wait_writable(FPTR_TO_FD(fptr)); + rb_io_wait_writable(fptr->fd); continue; case SSL_ERROR_WANT_READ: if (no_exception_p(opts)) { return sym_wait_readable; } read_would_block(nonblock); - rb_io_wait_readable(FPTR_TO_FD(fptr)); + rb_io_wait_readable(fptr->fd); continue; case SSL_ERROR_SYSCALL: if (errno) rb_sys_fail(0); @@ -1845,7 +1856,7 @@ ossl_ssl_write_internal(VALUE self, VALUE str, VALUE opts) * call-seq: * ssl.syswrite(string) => Integer * - * Writes +string+ to the SSL connection. + * Writes _string_ to the SSL connection. */ static VALUE ossl_ssl_write(VALUE self, VALUE str) @@ -1857,7 +1868,7 @@ ossl_ssl_write(VALUE self, VALUE str) * call-seq: * ssl.syswrite_nonblock(string) => Integer * - * Writes +string+ to the SSL connection in a non-blocking manner. Raises an + * Writes _string_ to the SSL connection in a non-blocking manner. Raises an * SSLError if writing would block. */ static VALUE @@ -2001,22 +2012,21 @@ ossl_ssl_get_version(VALUE self) } /* -* call-seq: -* ssl.cipher => [name, version, bits, alg_bits] -* -* The cipher being used for the current connection -*/ + * call-seq: + * ssl.cipher -> nil or [name, version, bits, alg_bits] + * + * Returns the cipher suite actually used in the current session, or nil if + * no session has been established. + */ static VALUE ossl_ssl_get_cipher(VALUE self) { SSL *ssl; - SSL_CIPHER *cipher; + const SSL_CIPHER *cipher; GetSSL(self, ssl); - - cipher = (SSL_CIPHER *)SSL_get_current_cipher(ssl); - - return ossl_ssl_cipher_to_ary(cipher); + cipher = SSL_get_current_cipher(ssl); + return cipher ? ossl_ssl_cipher_to_ary(cipher) : Qnil; } /* @@ -2062,7 +2072,7 @@ ossl_ssl_pending(VALUE self) * call-seq: * ssl.session_reused? -> true | false * - * Returns true if a reused session was negotiated during the handshake. + * Returns +true+ if a reused session was negotiated during the handshake. */ static VALUE ossl_ssl_session_reused(VALUE self) @@ -2087,7 +2097,7 @@ ossl_ssl_set_session(VALUE self, VALUE arg1) SSL_SESSION *sess; GetSSL(self, ssl); - SafeGetSSLSession(arg1, sess); + GetSSLSession(arg1, sess); if (SSL_set_session(ssl, sess) != 1) ossl_raise(eSSLError, "SSL_set_session"); @@ -2095,7 +2105,6 @@ ossl_ssl_set_session(VALUE self, VALUE arg1) return arg1; } -#ifdef HAVE_SSL_SET_TLSEXT_HOST_NAME /* * call-seq: * ssl.hostname = hostname -> hostname @@ -2122,7 +2131,6 @@ ossl_ssl_set_hostname(VALUE self, VALUE arg) return arg; } -#endif /* * call-seq: @@ -2166,7 +2174,7 @@ ossl_ssl_get_client_ca_list(VALUE self) return ossl_x509name_sk2ary(ca); } -# ifdef HAVE_SSL_CTX_SET_NEXT_PROTO_SELECT_CB +# ifndef OPENSSL_NO_NEXTPROTONEG /* * call-seq: * ssl.npn_protocol => String | nil @@ -2242,9 +2250,6 @@ ossl_ssl_tmp_key(VALUE self) void Init_ossl_ssl(void) { - int i; - VALUE ary; - #if 0 mOSSL = rb_define_module("OpenSSL"); eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError); @@ -2254,9 +2259,20 @@ Init_ossl_ssl(void) ID_callback_state = rb_intern("callback_state"); - ossl_ssl_ex_vcb_idx = SSL_get_ex_new_index(0,(void *)"ossl_ssl_ex_vcb_idx",0,0,0); - ossl_ssl_ex_store_p = SSL_get_ex_new_index(0,(void *)"ossl_ssl_ex_store_p",0,0,0); - ossl_ssl_ex_ptr_idx = SSL_get_ex_new_index(0,(void *)"ossl_ssl_ex_ptr_idx",0,0,0); + ossl_ssl_ex_vcb_idx = SSL_get_ex_new_index(0, (void *)"ossl_ssl_ex_vcb_idx", 0, 0, 0); + if (ossl_ssl_ex_vcb_idx < 0) + ossl_raise(rb_eRuntimeError, "SSL_get_ex_new_index"); + ossl_ssl_ex_ptr_idx = SSL_get_ex_new_index(0, (void *)"ossl_ssl_ex_ptr_idx", 0, 0, 0); + if (ossl_ssl_ex_ptr_idx < 0) + ossl_raise(rb_eRuntimeError, "SSL_get_ex_new_index"); + ossl_sslctx_ex_ptr_idx = SSL_CTX_get_ex_new_index(0, (void *)"ossl_sslctx_ex_ptr_idx", 0, 0, 0); + if (ossl_sslctx_ex_ptr_idx < 0) + ossl_raise(rb_eRuntimeError, "SSL_CTX_get_ex_new_index"); +#if !defined(HAVE_X509_STORE_UP_REF) + ossl_sslctx_ex_store_p = SSL_CTX_get_ex_new_index(0, (void *)"ossl_sslctx_ex_store_p", 0, 0, 0); + if (ossl_sslctx_ex_store_p < 0) + ossl_raise(rb_eRuntimeError, "SSL_CTX_get_ex_new_index"); +#endif /* Document-module: OpenSSL::SSL * @@ -2272,7 +2288,7 @@ Init_ossl_ssl(void) * This module contains configuration information about the SSL extension, * for example if socket support is enabled, or the host name TLS extension * is enabled. Constants in this module will always be defined, but contain - * `true` or `false` values depending on the configuration of your OpenSSL + * +true+ or +false+ values depending on the configuration of your OpenSSL * installation. */ mSSLExtConfig = rb_define_module_under(mOSSL, "ExtConfig"); @@ -2356,12 +2372,12 @@ Init_ossl_ssl(void) * A callback for additional certificate verification. The callback is * invoked for each certificate in the chain. * - * The callback is invoked with two values. +preverify_ok+ indicates - * indicates if the verification was passed (true) or not (false). - * +store_context+ is an OpenSSL::X509::StoreContext containing the + * The callback is invoked with two values. _preverify_ok_ indicates + * indicates if the verification was passed (+true+) or not (+false+). + * _store_context_ is an OpenSSL::X509::StoreContext containing the * context used for certificate verification. * - * If the callback returns false, the chain verification is immediately + * If the callback returns +false+, the chain verification is immediately * stopped and a bad_certificate alert is then sent. */ rb_attr(cSSLContext, rb_intern("verify_callback"), 1, 1, Qfalse); @@ -2428,7 +2444,7 @@ Init_ossl_ssl(void) /* * A callback invoked when a new session was negotiated. * - * The callback is invoked with an SSLSocket. If false is returned the + * The callback is invoked with an SSLSocket. If +false+ is returned the * session will be removed from the internal cache. */ rb_attr(cSSLContext, rb_intern("session_new_cb"), 1, 1, Qfalse); @@ -2440,17 +2456,7 @@ Init_ossl_ssl(void) */ rb_attr(cSSLContext, rb_intern("session_remove_cb"), 1, 1, Qfalse); -#ifdef HAVE_SSL_SET_TLSEXT_HOST_NAME rb_define_const(mSSLExtConfig, "HAVE_TLSEXT_HOST_NAME", Qtrue); -#else - rb_define_const(mSSLExtConfig, "HAVE_TLSEXT_HOST_NAME", Qfalse); -#endif - -#ifdef TLS_DH_anon_WITH_AES_256_GCM_SHA384 - rb_define_const(mSSLExtConfig, "TLS_DH_anon_WITH_AES_256_GCM_SHA384", Qtrue); -#else - rb_define_const(mSSLExtConfig, "TLS_DH_anon_WITH_AES_256_GCM_SHA384", Qfalse); -#endif /* * A callback invoked whenever a new handshake is initiated. May be used @@ -2474,7 +2480,7 @@ Init_ossl_ssl(void) * end */ rb_attr(cSSLContext, rb_intern("renegotiation_cb"), 1, 1, Qfalse); -#ifdef HAVE_SSL_CTX_SET_NEXT_PROTO_SELECT_CB +#ifndef OPENSSL_NO_NEXTPROTONEG /* * An Enumerable of Strings. Each String represents a protocol to be * advertised as the list of supported protocols for Next Protocol @@ -2540,7 +2546,8 @@ Init_ossl_ssl(void) rb_define_alias(cSSLContext, "ssl_timeout", "timeout"); rb_define_alias(cSSLContext, "ssl_timeout=", "timeout="); - rb_define_method(cSSLContext, "ssl_version=", ossl_sslctx_set_ssl_version, 1); + rb_define_private_method(cSSLContext, "set_minmax_proto_version", + ossl_sslctx_set_minmax_proto_version, 2); rb_define_method(cSSLContext, "ciphers", ossl_sslctx_get_ciphers, 0); rb_define_method(cSSLContext, "ciphers=", ossl_sslctx_set_ciphers, 1); rb_define_method(cSSLContext, "ecdh_curves=", ossl_sslctx_set_ecdh_curves, 1); @@ -2608,14 +2615,6 @@ Init_ossl_ssl(void) rb_define_method(cSSLContext, "options", ossl_sslctx_get_options, 0); rb_define_method(cSSLContext, "options=", ossl_sslctx_set_options, 1); - ary = rb_ary_new2(numberof(ossl_ssl_method_tab)); - for (i = 0; i < numberof(ossl_ssl_method_tab); i++) { - rb_ary_push(ary, ID2SYM(rb_intern(ossl_ssl_method_tab[i].name))); - } - rb_obj_freeze(ary); - /* The list of available SSL/TLS methods */ - rb_define_const(cSSLContext, "METHODS", ary); - /* * Document-class: OpenSSL::SSL::SSLSocket */ @@ -2649,67 +2648,120 @@ Init_ossl_ssl(void) rb_define_method(cSSLSocket, "session=", ossl_ssl_set_session, 1); rb_define_method(cSSLSocket, "verify_result", ossl_ssl_get_verify_result, 0); rb_define_method(cSSLSocket, "client_ca", ossl_ssl_get_client_ca_list, 0); -#ifdef HAVE_SSL_SET_TLSEXT_HOST_NAME /* #hostname is defined in lib/openssl/ssl.rb */ rb_define_method(cSSLSocket, "hostname=", ossl_ssl_set_hostname, 1); -#endif # ifdef HAVE_SSL_GET_SERVER_TMP_KEY rb_define_method(cSSLSocket, "tmp_key", ossl_ssl_tmp_key, 0); # endif # ifdef HAVE_SSL_CTX_SET_ALPN_SELECT_CB rb_define_method(cSSLSocket, "alpn_protocol", ossl_ssl_alpn_protocol, 0); # endif -# ifdef HAVE_SSL_CTX_SET_NEXT_PROTO_SELECT_CB +# ifndef OPENSSL_NO_NEXTPROTONEG rb_define_method(cSSLSocket, "npn_protocol", ossl_ssl_npn_protocol, 0); # endif #endif -#define ossl_ssl_def_const(x) rb_define_const(mSSL, #x, LONG2NUM(SSL_##x)) + rb_define_const(mSSL, "VERIFY_NONE", INT2NUM(SSL_VERIFY_NONE)); + rb_define_const(mSSL, "VERIFY_PEER", INT2NUM(SSL_VERIFY_PEER)); + rb_define_const(mSSL, "VERIFY_FAIL_IF_NO_PEER_CERT", INT2NUM(SSL_VERIFY_FAIL_IF_NO_PEER_CERT)); + rb_define_const(mSSL, "VERIFY_CLIENT_ONCE", INT2NUM(SSL_VERIFY_CLIENT_ONCE)); - ossl_ssl_def_const(VERIFY_NONE); - ossl_ssl_def_const(VERIFY_PEER); - ossl_ssl_def_const(VERIFY_FAIL_IF_NO_PEER_CERT); - ossl_ssl_def_const(VERIFY_CLIENT_ONCE); - /* Introduce constants included in OP_ALL. These constants are mostly for - * unset some bits in OP_ALL such as; - * ctx.options = OP_ALL & ~OP_DONT_INSERT_EMPTY_FRAGMENTS - */ - ossl_ssl_def_const(OP_MICROSOFT_SESS_ID_BUG); - ossl_ssl_def_const(OP_NETSCAPE_CHALLENGE_BUG); - ossl_ssl_def_const(OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG); - ossl_ssl_def_const(OP_SSLREF2_REUSE_CERT_TYPE_BUG); - ossl_ssl_def_const(OP_MICROSOFT_BIG_SSLV3_BUFFER); - ossl_ssl_def_const(OP_MSIE_SSLV2_RSA_PADDING); - ossl_ssl_def_const(OP_SSLEAY_080_CLIENT_DH_BUG); - ossl_ssl_def_const(OP_TLS_D5_BUG); - ossl_ssl_def_const(OP_TLS_BLOCK_PADDING_BUG); - ossl_ssl_def_const(OP_DONT_INSERT_EMPTY_FRAGMENTS); - ossl_ssl_def_const(OP_ALL); - ossl_ssl_def_const(OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION); - ossl_ssl_def_const(OP_SINGLE_ECDH_USE); - ossl_ssl_def_const(OP_SINGLE_DH_USE); - ossl_ssl_def_const(OP_EPHEMERAL_RSA); - ossl_ssl_def_const(OP_CIPHER_SERVER_PREFERENCE); - ossl_ssl_def_const(OP_TLS_ROLLBACK_BUG); - ossl_ssl_def_const(OP_NO_SSLv2); - ossl_ssl_def_const(OP_NO_SSLv3); - ossl_ssl_def_const(OP_NO_TLSv1); -#if defined(SSL_OP_NO_TLSv1_1) - ossl_ssl_def_const(OP_NO_TLSv1_1); + rb_define_const(mSSL, "OP_ALL", ULONG2NUM(SSL_OP_ALL)); + rb_define_const(mSSL, "OP_LEGACY_SERVER_CONNECT", ULONG2NUM(SSL_OP_LEGACY_SERVER_CONNECT)); +#ifdef SSL_OP_TLSEXT_PADDING /* OpenSSL 1.0.1h and OpenSSL 1.0.2 */ + rb_define_const(mSSL, "OP_TLSEXT_PADDING", ULONG2NUM(SSL_OP_TLSEXT_PADDING)); +#endif +#ifdef SSL_OP_SAFARI_ECDHE_ECDSA_BUG /* OpenSSL 1.0.1f and OpenSSL 1.0.2 */ + rb_define_const(mSSL, "OP_SAFARI_ECDHE_ECDSA_BUG", ULONG2NUM(SSL_OP_SAFARI_ECDHE_ECDSA_BUG)); #endif -#if defined(SSL_OP_NO_TLSv1_2) - ossl_ssl_def_const(OP_NO_TLSv1_2); +#ifdef SSL_OP_ALLOW_NO_DHE_KEX /* OpenSSL 1.1.1 */ + rb_define_const(mSSL, "OP_ALLOW_NO_DHE_KEX", ULONG2NUM(SSL_OP_ALLOW_NO_DHE_KEX)); #endif -#if defined(SSL_OP_NO_TICKET) - ossl_ssl_def_const(OP_NO_TICKET); + rb_define_const(mSSL, "OP_DONT_INSERT_EMPTY_FRAGMENTS", ULONG2NUM(SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS)); + rb_define_const(mSSL, "OP_NO_TICKET", ULONG2NUM(SSL_OP_NO_TICKET)); + rb_define_const(mSSL, "OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION", ULONG2NUM(SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION)); + rb_define_const(mSSL, "OP_NO_COMPRESSION", ULONG2NUM(SSL_OP_NO_COMPRESSION)); + rb_define_const(mSSL, "OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION", ULONG2NUM(SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION)); +#ifdef SSL_OP_NO_ENCRYPT_THEN_MAC /* OpenSSL 1.1.1 */ + rb_define_const(mSSL, "OP_NO_ENCRYPT_THEN_MAC", ULONG2NUM(SSL_OP_NO_ENCRYPT_THEN_MAC)); #endif -#if defined(SSL_OP_NO_COMPRESSION) - ossl_ssl_def_const(OP_NO_COMPRESSION); + rb_define_const(mSSL, "OP_CIPHER_SERVER_PREFERENCE", ULONG2NUM(SSL_OP_CIPHER_SERVER_PREFERENCE)); + rb_define_const(mSSL, "OP_TLS_ROLLBACK_BUG", ULONG2NUM(SSL_OP_TLS_ROLLBACK_BUG)); +#ifdef SSL_OP_NO_RENEGOTIATION /* OpenSSL 1.1.1 */ + rb_define_const(mSSL, "OP_NO_RENEGOTIATION", ULONG2NUM(SSL_OP_NO_RENEGOTIATION)); #endif - ossl_ssl_def_const(OP_PKCS1_CHECK_1); - ossl_ssl_def_const(OP_PKCS1_CHECK_2); - ossl_ssl_def_const(OP_NETSCAPE_CA_DN_BUG); - ossl_ssl_def_const(OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG); + rb_define_const(mSSL, "OP_CRYPTOPRO_TLSEXT_BUG", ULONG2NUM(SSL_OP_CRYPTOPRO_TLSEXT_BUG)); + + rb_define_const(mSSL, "OP_NO_SSLv3", ULONG2NUM(SSL_OP_NO_SSLv3)); + rb_define_const(mSSL, "OP_NO_TLSv1", ULONG2NUM(SSL_OP_NO_TLSv1)); + rb_define_const(mSSL, "OP_NO_TLSv1_1", ULONG2NUM(SSL_OP_NO_TLSv1_1)); + rb_define_const(mSSL, "OP_NO_TLSv1_2", ULONG2NUM(SSL_OP_NO_TLSv1_2)); +#ifdef SSL_OP_NO_TLSv1_3 /* OpenSSL 1.1.1 */ + rb_define_const(mSSL, "OP_NO_TLSv1_3", ULONG2NUM(SSL_OP_NO_TLSv1_3)); +#endif + + /* SSL_OP_* flags for DTLS */ +#if 0 + rb_define_const(mSSL, "OP_NO_QUERY_MTU", ULONG2NUM(SSL_OP_NO_QUERY_MTU)); + rb_define_const(mSSL, "OP_COOKIE_EXCHANGE", ULONG2NUM(SSL_OP_COOKIE_EXCHANGE)); + rb_define_const(mSSL, "OP_CISCO_ANYCONNECT", ULONG2NUM(SSL_OP_CISCO_ANYCONNECT)); +#endif + + /* Deprecated in OpenSSL 1.1.0. */ + rb_define_const(mSSL, "OP_MICROSOFT_SESS_ID_BUG", ULONG2NUM(SSL_OP_MICROSOFT_SESS_ID_BUG)); + /* Deprecated in OpenSSL 1.1.0. */ + rb_define_const(mSSL, "OP_NETSCAPE_CHALLENGE_BUG", ULONG2NUM(SSL_OP_NETSCAPE_CHALLENGE_BUG)); + /* Deprecated in OpenSSL 0.9.8q and 1.0.0c. */ + rb_define_const(mSSL, "OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG", ULONG2NUM(SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG)); + /* Deprecated in OpenSSL 1.0.1h and 1.0.2. */ + rb_define_const(mSSL, "OP_SSLREF2_REUSE_CERT_TYPE_BUG", ULONG2NUM(SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG)); + /* Deprecated in OpenSSL 1.1.0. */ + rb_define_const(mSSL, "OP_MICROSOFT_BIG_SSLV3_BUFFER", ULONG2NUM(SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER)); + /* Deprecated in OpenSSL 0.9.7h and 0.9.8b. */ + rb_define_const(mSSL, "OP_MSIE_SSLV2_RSA_PADDING", ULONG2NUM(SSL_OP_MSIE_SSLV2_RSA_PADDING)); + /* Deprecated in OpenSSL 1.1.0. */ + rb_define_const(mSSL, "OP_SSLEAY_080_CLIENT_DH_BUG", ULONG2NUM(SSL_OP_SSLEAY_080_CLIENT_DH_BUG)); + /* Deprecated in OpenSSL 1.1.0. */ + rb_define_const(mSSL, "OP_TLS_D5_BUG", ULONG2NUM(SSL_OP_TLS_D5_BUG)); + /* Deprecated in OpenSSL 1.1.0. */ + rb_define_const(mSSL, "OP_TLS_BLOCK_PADDING_BUG", ULONG2NUM(SSL_OP_TLS_BLOCK_PADDING_BUG)); + /* Deprecated in OpenSSL 1.1.0. */ + rb_define_const(mSSL, "OP_SINGLE_ECDH_USE", ULONG2NUM(SSL_OP_SINGLE_ECDH_USE)); + /* Deprecated in OpenSSL 1.1.0. */ + rb_define_const(mSSL, "OP_SINGLE_DH_USE", ULONG2NUM(SSL_OP_SINGLE_DH_USE)); + /* Deprecated in OpenSSL 1.0.1k and 1.0.2. */ + rb_define_const(mSSL, "OP_EPHEMERAL_RSA", ULONG2NUM(SSL_OP_EPHEMERAL_RSA)); + /* Deprecated in OpenSSL 1.1.0. */ + rb_define_const(mSSL, "OP_NO_SSLv2", ULONG2NUM(SSL_OP_NO_SSLv2)); + /* Deprecated in OpenSSL 1.0.1. */ + rb_define_const(mSSL, "OP_PKCS1_CHECK_1", ULONG2NUM(SSL_OP_PKCS1_CHECK_1)); + /* Deprecated in OpenSSL 1.0.1. */ + rb_define_const(mSSL, "OP_PKCS1_CHECK_2", ULONG2NUM(SSL_OP_PKCS1_CHECK_2)); + /* Deprecated in OpenSSL 1.1.0. */ + rb_define_const(mSSL, "OP_NETSCAPE_CA_DN_BUG", ULONG2NUM(SSL_OP_NETSCAPE_CA_DN_BUG)); + /* Deprecated in OpenSSL 1.1.0. */ + rb_define_const(mSSL, "OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG", ULONG2NUM(SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG)); + + + /* + * SSL/TLS version constants. Used by SSLContext#min_version= and + * #max_version= + */ + /* SSL 2.0 */ + rb_define_const(mSSL, "SSL2_VERSION", INT2NUM(SSL2_VERSION)); + /* SSL 3.0 */ + rb_define_const(mSSL, "SSL3_VERSION", INT2NUM(SSL3_VERSION)); + /* TLS 1.0 */ + rb_define_const(mSSL, "TLS1_VERSION", INT2NUM(TLS1_VERSION)); + /* TLS 1.1 */ + rb_define_const(mSSL, "TLS1_1_VERSION", INT2NUM(TLS1_1_VERSION)); + /* TLS 1.2 */ + rb_define_const(mSSL, "TLS1_2_VERSION", INT2NUM(TLS1_2_VERSION)); +#ifdef TLS1_3_VERSION /* OpenSSL 1.1.1 */ + /* TLS 1.3 */ + rb_define_const(mSSL, "TLS1_3_VERSION", INT2NUM(TLS1_3_VERSION)); +#endif + sym_exception = ID2SYM(rb_intern("exception")); sym_wait_readable = ID2SYM(rb_intern("wait_readable")); diff --git a/ext/openssl/ossl_ssl.h b/ext/openssl/ossl_ssl.h index c1a3cd6c1d..535c56097c 100644 --- a/ext/openssl/ossl_ssl.h +++ b/ext/openssl/ossl_ssl.h @@ -24,11 +24,6 @@ } \ } while (0) -#define SafeGetSSLSession(obj, sess) do { \ - OSSL_Check_Kind((obj), cSSLSession); \ - GetSSLSession((obj), (sess)); \ -} while (0) - extern const rb_data_type_t ossl_ssl_type; extern const rb_data_type_t ossl_ssl_session_type; extern VALUE mSSL; diff --git a/ext/openssl/ossl_ssl_session.c b/ext/openssl/ossl_ssl_session.c index 661f53eefb..5514087387 100644 --- a/ext/openssl/ossl_ssl_session.c +++ b/ext/openssl/ossl_ssl_session.c @@ -80,7 +80,7 @@ ossl_ssl_session_initialize_copy(VALUE self, VALUE other) rb_check_frozen(self); sess = RTYPEDDATA_DATA(self); /* XXX */ - SafeGetSSLSession(other, sess_other); + GetSSLSession(other, sess_other); sess_new = ASN1_dup((i2d_of_void *)i2d_SSL_SESSION, (d2i_of_void *)d2i_SSL_SESSION, (char *)sess_other); @@ -93,8 +93,8 @@ ossl_ssl_session_initialize_copy(VALUE self, VALUE other) return self; } -#if !defined(HAVE_SSL_SESSION_CMP) -int ossl_SSL_SESSION_cmp(const SSL_SESSION *a, const SSL_SESSION *b) +static int +ossl_SSL_SESSION_cmp(const SSL_SESSION *a, const SSL_SESSION *b) { unsigned int a_len; const unsigned char *a_sid = SSL_SESSION_get_id(a, &a_len); @@ -108,23 +108,21 @@ int ossl_SSL_SESSION_cmp(const SSL_SESSION *a, const SSL_SESSION *b) return CRYPTO_memcmp(a_sid, b_sid, a_len); } -#define SSL_SESSION_cmp(a, b) ossl_SSL_SESSION_cmp(a, b) -#endif /* * call-seq: * session1 == session2 -> boolean * - * Returns true if the two Session is the same, false if not. + * Returns +true+ if the two Session is the same, +false+ if not. */ static VALUE ossl_ssl_session_eq(VALUE val1, VALUE val2) { SSL_SESSION *ctx1, *ctx2; GetSSLSession(val1, ctx1); - SafeGetSSLSession(val2, ctx2); + GetSSLSession(val2, ctx2); - switch (SSL_SESSION_cmp(ctx1, ctx2)) { + switch (ossl_SSL_SESSION_cmp(ctx1, ctx2)) { case 0: return Qtrue; default: return Qfalse; } @@ -319,7 +317,7 @@ void Init_ossl_ssl_session(void) rb_define_alloc_func(cSSLSession, ossl_ssl_session_alloc); rb_define_method(cSSLSession, "initialize", ossl_ssl_session_initialize, 1); - rb_define_copy_func(cSSLSession, ossl_ssl_session_initialize_copy); + rb_define_method(cSSLSession, "initialize_copy", ossl_ssl_session_initialize_copy, 1); rb_define_method(cSSLSession, "==", ossl_ssl_session_eq, 1); diff --git a/ext/openssl/ossl_version.h b/ext/openssl/ossl_version.h index be3eebe1f2..4167c9c83d 100644 --- a/ext/openssl/ossl_version.h +++ b/ext/openssl/ossl_version.h @@ -10,6 +10,6 @@ #if !defined(_OSSL_VERSION_H_) #define _OSSL_VERSION_H_ -#define OSSL_VERSION "2.0.5" +#define OSSL_VERSION "2.1.0" #endif /* _OSSL_VERSION_H_ */ diff --git a/ext/openssl/ossl_x509.c b/ext/openssl/ossl_x509.c index 19ec274ae1..8a061b0687 100644 --- a/ext/openssl/ossl_x509.c +++ b/ext/openssl/ossl_x509.c @@ -20,15 +20,10 @@ ossl_x509_time_adjust(ASN1_TIME *s, VALUE time) { time_t sec; -#if defined(HAVE_ASN1_TIME_ADJ) int off_days; ossl_time_split(time, &sec, &off_days); return X509_time_adj_ex(s, off_days, 0, &sec); -#else - sec = time_to_time_t(time); - return X509_time_adj(s, 0, &sec); -#endif } void @@ -112,21 +107,15 @@ Init_ossl_x509(void) DefX509Const(V_FLAG_INHIBIT_MAP); /* Set by Store#flags= and StoreContext#flags=. */ DefX509Const(V_FLAG_NOTIFY_POLICY); -#if defined(X509_V_FLAG_EXTENDED_CRL_SUPPORT) /* Set by Store#flags= and StoreContext#flags=. Enables some additional * features including support for indirect signed CRLs. */ DefX509Const(V_FLAG_EXTENDED_CRL_SUPPORT); -#endif -#if defined(X509_V_FLAG_USE_DELTAS) /* Set by Store#flags= and StoreContext#flags=. Uses delta CRLs. If not * specified, deltas are ignored. */ DefX509Const(V_FLAG_USE_DELTAS); -#endif -#if defined(X509_V_FLAG_CHECK_SS_SIGNATURE) /* Set by Store#flags= and StoreContext#flags=. Enables checking of the * signature of the root self-signed CA. */ DefX509Const(V_FLAG_CHECK_SS_SIGNATURE); -#endif #if defined(X509_V_FLAG_TRUSTED_FIRST) /* Set by Store#flags= and StoreContext#flags=. When constructing a * certificate chain, search the Store first for the issuer certificate. @@ -161,10 +150,8 @@ Init_ossl_x509(void) DefX509Const(PURPOSE_ANY); /* Set by Store#purpose=. OCSP helper. */ DefX509Const(PURPOSE_OCSP_HELPER); -#if defined(X509_PURPOSE_TIMESTAMP_SIGN) /* Set by Store#purpose=. Time stamps signer. */ DefX509Const(PURPOSE_TIMESTAMP_SIGN); -#endif DefX509Const(TRUST_COMPAT); DefX509Const(TRUST_SSL_CLIENT); @@ -173,9 +160,7 @@ Init_ossl_x509(void) DefX509Const(TRUST_OBJECT_SIGN); DefX509Const(TRUST_OCSP_SIGN); DefX509Const(TRUST_OCSP_REQUEST); -#if defined(X509_TRUST_TSA) DefX509Const(TRUST_TSA); -#endif DefX509Default(CERT_AREA, cert_area); DefX509Default(CERT_DIR, cert_dir); diff --git a/ext/openssl/ossl_x509.h b/ext/openssl/ossl_x509.h index a60f7c3da3..4fadfa6b82 100644 --- a/ext/openssl/ossl_x509.h +++ b/ext/openssl/ossl_x509.h @@ -41,7 +41,6 @@ extern VALUE cX509Cert; extern VALUE eX509CertError; VALUE ossl_x509_new(X509 *); -VALUE ossl_x509_new_from_file(VALUE); X509 *GetX509CertPtr(VALUE); X509 *DupX509CertPtr(VALUE); void Init_ossl_x509cert(void); @@ -54,7 +53,6 @@ extern VALUE eX509CRLError; VALUE ossl_x509crl_new(X509_CRL *); X509_CRL *GetX509CRLPtr(VALUE); -X509_CRL *DupX509CRLPtr(VALUE); void Init_ossl_x509crl(void); /* @@ -84,9 +82,7 @@ void Init_ossl_x509name(void); extern VALUE cX509Req; extern VALUE eX509ReqError; -VALUE ossl_x509req_new(X509_REQ *); X509_REQ *GetX509ReqPtr(VALUE); -X509_REQ *DupX509ReqPtr(VALUE); void Init_ossl_x509req(void); /* @@ -106,11 +102,8 @@ extern VALUE cX509Store; extern VALUE cX509StoreContext; extern VALUE eX509StoreError; -VALUE ossl_x509store_new(X509_STORE *); X509_STORE *GetX509StorePtr(VALUE); -X509_STORE *DupX509StorePtr(VALUE); -X509_STORE_CTX *GetX509StCtxtPtr(VALUE); void Init_ossl_x509store(void); /* diff --git a/ext/openssl/ossl_x509attr.c b/ext/openssl/ossl_x509attr.c index ae0b347b5f..60846cfe9d 100644 --- a/ext/openssl/ossl_x509attr.c +++ b/ext/openssl/ossl_x509attr.c @@ -23,10 +23,6 @@ ossl_raise(rb_eRuntimeError, "ATTR wasn't initialized!"); \ } \ } while (0) -#define SafeGetX509Attr(obj, attr) do { \ - OSSL_Check_Kind((obj), cX509Attr); \ - GetX509Attr((obj), (attr)); \ -} while (0) /* * Classes @@ -76,7 +72,7 @@ GetX509AttrPtr(VALUE obj) { X509_ATTRIBUTE *attr; - SafeGetX509Attr(obj, attr); + GetX509Attr(obj, attr); return attr; } @@ -134,7 +130,7 @@ ossl_x509attr_initialize_copy(VALUE self, VALUE other) rb_check_frozen(self); GetX509Attr(self, attr); - SafeGetX509Attr(other, attr_other); + GetX509Attr(other, attr_other); attr_new = X509_ATTRIBUTE_dup(attr_other); if (!attr_new) @@ -319,7 +315,7 @@ Init_ossl_x509attr(void) cX509Attr = rb_define_class_under(mX509, "Attribute", rb_cObject); rb_define_alloc_func(cX509Attr, ossl_x509attr_alloc); rb_define_method(cX509Attr, "initialize", ossl_x509attr_initialize, -1); - rb_define_copy_func(cX509Attr, ossl_x509attr_initialize_copy); + rb_define_method(cX509Attr, "initialize_copy", ossl_x509attr_initialize_copy, 1); rb_define_method(cX509Attr, "oid=", ossl_x509attr_set_oid, 1); rb_define_method(cX509Attr, "oid", ossl_x509attr_get_oid, 0); rb_define_method(cX509Attr, "value=", ossl_x509attr_set_value, 1); diff --git a/ext/openssl/ossl_x509cert.c b/ext/openssl/ossl_x509cert.c index 87086a7c59..003a9c1949 100644 --- a/ext/openssl/ossl_x509cert.c +++ b/ext/openssl/ossl_x509cert.c @@ -23,10 +23,6 @@ ossl_raise(rb_eRuntimeError, "CERT wasn't initialized!"); \ } \ } while (0) -#define SafeGetX509(obj, x509) do { \ - OSSL_Check_Kind((obj), cX509Cert); \ - GetX509((obj), (x509)); \ -} while (0) /* * Classes @@ -71,46 +67,12 @@ ossl_x509_new(X509 *x509) return obj; } -VALUE -ossl_x509_new_from_file(VALUE filename) -{ - X509 *x509; - FILE *fp; - VALUE obj; - - rb_check_safe_obj(filename); - obj = NewX509(cX509Cert); - if (!(fp = fopen(StringValueCStr(filename), "r"))) { - ossl_raise(eX509CertError, "%s", strerror(errno)); - } - rb_fd_fix_cloexec(fileno(fp)); - x509 = PEM_read_X509(fp, NULL, NULL, NULL); - /* - * prepare for DER... -#if !defined(OPENSSL_NO_FP_API) - if (!x509) { - (void)ERR_get_error(); - rewind(fp); - - x509 = d2i_X509_fp(fp, NULL); - } -#endif - */ - fclose(fp); - if (!x509) { - ossl_raise(eX509CertError, NULL); - } - SetX509(obj, x509); - - return obj; -} - X509 * GetX509CertPtr(VALUE obj) { X509 *x509; - SafeGetX509(obj, x509); + GetX509(obj, x509); return x509; } @@ -120,7 +82,7 @@ DupX509CertPtr(VALUE obj) { X509 *x509; - SafeGetX509(obj, x509); + GetX509(obj, x509); X509_up_ref(x509); @@ -184,7 +146,7 @@ ossl_x509_copy(VALUE self, VALUE other) if (self == other) return self; GetX509(self, a); - SafeGetX509(other, b); + GetX509(other, b); x509 = X509_dup(b); if (!x509) ossl_raise(eX509CertError, NULL); @@ -573,7 +535,7 @@ ossl_x509_sign(VALUE self, VALUE key, VALUE digest) const EVP_MD *md; pkey = GetPrivPKeyPtr(key); /* NO NEED TO DUP */ - md = GetDigestPtr(digest); + md = ossl_evp_get_digestbyname(digest); GetX509(self, x509); if (!X509_sign(x509, pkey, md)) { ossl_raise(eX509CertError, NULL); @@ -586,7 +548,8 @@ ossl_x509_sign(VALUE self, VALUE key, VALUE digest) * call-seq: * cert.verify(key) => true | false * - * Checks that cert signature is made with PRIVversion of this PUBLIC 'key' + * Verifies the signature of the certificate, with the public key _key_. _key_ + * must be an instance of OpenSSL::PKey. */ static VALUE ossl_x509_verify(VALUE self, VALUE key) @@ -610,9 +573,10 @@ ossl_x509_verify(VALUE self, VALUE key) /* * call-seq: - * cert.check_private_key(key) + * cert.check_private_key(key) -> true | false * - * Checks if 'key' is PRIV key for this cert + * Returns +true+ if _key_ is the corresponding private key to the Subject + * Public Key Information, +false+ otherwise. */ static VALUE ossl_x509_check_private_key(VALUE self, VALUE key) @@ -829,7 +793,7 @@ Init_ossl_x509cert(void) rb_define_alloc_func(cX509Cert, ossl_x509_alloc); rb_define_method(cX509Cert, "initialize", ossl_x509_initialize, -1); - rb_define_copy_func(cX509Cert, ossl_x509_copy); + rb_define_method(cX509Cert, "initialize_copy", ossl_x509_copy, 1); rb_define_method(cX509Cert, "to_der", ossl_x509_to_der, 0); rb_define_method(cX509Cert, "to_pem", ossl_x509_to_pem, 0); diff --git a/ext/openssl/ossl_x509crl.c b/ext/openssl/ossl_x509crl.c index 035025ab69..5ecd7ea0b2 100644 --- a/ext/openssl/ossl_x509crl.c +++ b/ext/openssl/ossl_x509crl.c @@ -23,10 +23,6 @@ ossl_raise(rb_eRuntimeError, "CRL wasn't initialized!"); \ } \ } while (0) -#define SafeGetX509CRL(obj, crl) do { \ - OSSL_Check_Kind((obj), cX509CRL); \ - GetX509CRL((obj), (crl)); \ -} while (0) /* * Classes @@ -56,18 +52,7 @@ GetX509CRLPtr(VALUE obj) { X509_CRL *crl; - SafeGetX509CRL(obj, crl); - - return crl; -} - -X509_CRL * -DupX509CRLPtr(VALUE obj) -{ - X509_CRL *crl; - - SafeGetX509CRL(obj, crl); - X509_CRL_up_ref(crl); + GetX509CRL(obj, crl); return crl; } @@ -137,7 +122,7 @@ ossl_x509crl_copy(VALUE self, VALUE other) rb_check_frozen(self); if (self == other) return self; GetX509CRL(self, a); - SafeGetX509CRL(other, b); + GetX509CRL(other, b); if (!(crl = X509_CRL_dup(b))) { ossl_raise(eX509CRLError, NULL); } @@ -223,10 +208,14 @@ static VALUE ossl_x509crl_get_last_update(VALUE self) { X509_CRL *crl; + const ASN1_TIME *time; GetX509CRL(self, crl); + time = X509_CRL_get0_lastUpdate(crl); + if (!time) + return Qnil; - return asn1time_to_time(X509_CRL_get0_lastUpdate(crl)); + return asn1time_to_time(time); } static VALUE @@ -250,10 +239,14 @@ static VALUE ossl_x509crl_get_next_update(VALUE self) { X509_CRL *crl; + const ASN1_TIME *time; GetX509CRL(self, crl); + time = X509_CRL_get0_nextUpdate(crl); + if (!time) + return Qnil; - return asn1time_to_time(X509_CRL_get0_nextUpdate(crl)); + return asn1time_to_time(time); } static VALUE @@ -354,7 +347,7 @@ ossl_x509crl_sign(VALUE self, VALUE key, VALUE digest) GetX509CRL(self, crl); pkey = GetPrivPKeyPtr(key); /* NO NEED TO DUP */ - md = GetDigestPtr(digest); + md = ossl_evp_get_digestbyname(digest); if (!X509_CRL_sign(crl, pkey, md)) { ossl_raise(eX509CRLError, NULL); } @@ -520,7 +513,7 @@ Init_ossl_x509crl(void) rb_define_alloc_func(cX509CRL, ossl_x509crl_alloc); rb_define_method(cX509CRL, "initialize", ossl_x509crl_initialize, -1); - rb_define_copy_func(cX509CRL, ossl_x509crl_copy); + rb_define_method(cX509CRL, "initialize_copy", ossl_x509crl_copy, 1); rb_define_method(cX509CRL, "version", ossl_x509crl_get_version, 0); rb_define_method(cX509CRL, "version=", ossl_x509crl_set_version, 1); diff --git a/ext/openssl/ossl_x509ext.c b/ext/openssl/ossl_x509ext.c index b92b0786b2..2d9a7a31e8 100644 --- a/ext/openssl/ossl_x509ext.c +++ b/ext/openssl/ossl_x509ext.c @@ -23,10 +23,6 @@ ossl_raise(rb_eRuntimeError, "EXT wasn't initialized!"); \ } \ } while (0) -#define SafeGetX509Ext(obj, ext) do { \ - OSSL_Check_Kind((obj), cX509Ext); \ - GetX509Ext((obj), (ext)); \ -} while (0) #define MakeX509ExtFactory(klass, obj, ctx) do { \ (obj) = TypedData_Wrap_Struct((klass), &ossl_x509extfactory_type, 0); \ if (!((ctx) = OPENSSL_malloc(sizeof(X509V3_CTX)))) \ @@ -90,7 +86,7 @@ GetX509ExtPtr(VALUE obj) { X509_EXTENSION *ext; - SafeGetX509Ext(obj, ext); + GetX509Ext(obj, ext); return ext; } @@ -263,15 +259,15 @@ ossl_x509ext_alloc(VALUE klass) /* * call-seq: - * OpenSSL::X509::Extension.new asn1 - * OpenSSL::X509::Extension.new name, value - * OpenSSL::X509::Extension.new name, value, critical + * OpenSSL::X509::Extension.new(der) + * OpenSSL::X509::Extension.new(oid, value) + * OpenSSL::X509::Extension.new(oid, value, critical) * * Creates an X509 extension. * - * The extension may be created from +asn1+ data or from an extension +name+ - * and +value+. The +name+ may be either an OID or an extension name. If - * +critical+ is true the extension is marked critical. + * The extension may be created from _der_ data or from an extension _oid_ + * and _value_. The _oid_ may be either an OID or an extension name. If + * _critical_ is +true+ the extension is marked critical. */ static VALUE ossl_x509ext_initialize(int argc, VALUE *argv, VALUE self) @@ -305,7 +301,7 @@ ossl_x509ext_initialize_copy(VALUE self, VALUE other) rb_check_frozen(self); GetX509Ext(self, ext); - SafeGetX509Ext(other, ext_other); + GetX509Ext(other, ext_other); ext_new = X509_EXTENSION_dup(ext_other); if (!ext_new) @@ -469,7 +465,7 @@ Init_ossl_x509ext(void) cX509Ext = rb_define_class_under(mX509, "Extension", rb_cObject); rb_define_alloc_func(cX509Ext, ossl_x509ext_alloc); rb_define_method(cX509Ext, "initialize", ossl_x509ext_initialize, -1); - rb_define_copy_func(cX509Ext, ossl_x509ext_initialize_copy); + rb_define_method(cX509Ext, "initialize_copy", ossl_x509ext_initialize_copy, 1); rb_define_method(cX509Ext, "oid=", ossl_x509ext_set_oid, 1); rb_define_method(cX509Ext, "value=", ossl_x509ext_set_value, 1); rb_define_method(cX509Ext, "critical=", ossl_x509ext_set_critical, 1); diff --git a/ext/openssl/ossl_x509name.c b/ext/openssl/ossl_x509name.c index ac98c1b94c..b2063954d1 100644 --- a/ext/openssl/ossl_x509name.c +++ b/ext/openssl/ossl_x509name.c @@ -23,10 +23,6 @@ ossl_raise(rb_eRuntimeError, "Name wasn't initialized."); \ } \ } while (0) -#define SafeGetX509Name(obj, name) do { \ - OSSL_Check_Kind((obj), cX509Name); \ - GetX509Name((obj), (name)); \ -} while (0) #define OBJECT_TYPE_TEMPLATE \ rb_const_get(cX509Name, rb_intern("OBJECT_TYPE_TEMPLATE")) @@ -81,7 +77,7 @@ GetX509NamePtr(VALUE obj) { X509_NAME *name; - SafeGetX509Name(obj, name); + GetX509Name(obj, name); return name; } @@ -135,15 +131,15 @@ ossl_x509name_init_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args)) * * Creates a new Name. * - * A name may be created from a DER encoded string +der+, an Array - * representing a +distinguished_name+ or a +distinguished_name+ along with a - * +template+. + * A name may be created from a DER encoded string _der_, an Array + * representing a _distinguished_name_ or a _distinguished_name_ along with a + * _template_. * * name = OpenSSL::X509::Name.new [['CN', 'nobody'], ['DC', 'example']] * * name = OpenSSL::X509::Name.new name.to_der * - * See add_entry for a description of the +distinguished_name+ Array's + * See add_entry for a description of the _distinguished_name_ Array's * contents */ static VALUE @@ -188,7 +184,7 @@ ossl_x509name_initialize_copy(VALUE self, VALUE other) rb_check_frozen(self); GetX509Name(self, name); - SafeGetX509Name(other, name_other); + GetX509Name(other, name_other); name_new = X509_NAME_dup(name_other); if (!name_new) @@ -202,9 +198,9 @@ ossl_x509name_initialize_copy(VALUE self, VALUE other) /* * call-seq: - * name.add_entry(oid, value [, type]) => self + * name.add_entry(oid, value [, type], loc: -1, set: 0) => self * - * Adds a new entry with the given +oid+ and +value+ to this name. The +oid+ + * Adds a new entry with the given _oid_ and _value_ to this name. The _oid_ * is an object identifier defined in ASN.1. Some common OIDs are: * * C:: Country Name @@ -213,24 +209,39 @@ ossl_x509name_initialize_copy(VALUE self, VALUE other) * O:: Organization Name * OU:: Organizational Unit Name * ST:: State or Province Name + * + * The optional keyword parameters _loc_ and _set_ specify where to insert the + * new attribute. Refer to the manpage of X509_NAME_add_entry(3) for details. + * _loc_ defaults to -1 and _set_ defaults to 0. This appends a single-valued + * RDN to the end. */ static VALUE ossl_x509name_add_entry(int argc, VALUE *argv, VALUE self) { X509_NAME *name; - VALUE oid, value, type; + VALUE oid, value, type, opts, kwargs[2]; + static ID kwargs_ids[2]; const char *oid_name; + int loc = -1, set = 0; - rb_scan_args(argc, argv, "21", &oid, &value, &type); + if (!kwargs_ids[0]) { + kwargs_ids[0] = rb_intern_const("loc"); + kwargs_ids[1] = rb_intern_const("set"); + } + rb_scan_args(argc, argv, "21:", &oid, &value, &type, &opts); + rb_get_kwargs(opts, kwargs_ids, 0, 2, kwargs); oid_name = StringValueCStr(oid); StringValue(value); if(NIL_P(type)) type = rb_aref(OBJECT_TYPE_TEMPLATE, oid); + if (kwargs[0] != Qundef) + loc = NUM2INT(kwargs[0]); + if (kwargs[1] != Qundef) + set = NUM2INT(kwargs[1]); GetX509Name(self, name); if (!X509_NAME_add_entry_by_txt(name, oid_name, NUM2INT(type), - (const unsigned char *)RSTRING_PTR(value), RSTRING_LENINT(value), -1, 0)) { - ossl_raise(eX509NameError, NULL); - } - + (unsigned char *)RSTRING_PTR(value), + RSTRING_LENINT(value), loc, set)) + ossl_raise(eX509NameError, "X509_NAME_add_entry_by_txt"); return self; } @@ -249,42 +260,73 @@ ossl_x509name_to_s_old(VALUE self) return str; } +static VALUE +x509name_print(VALUE self, unsigned long iflag) +{ + X509_NAME *name; + BIO *out; + + GetX509Name(self, name); + out = BIO_new(BIO_s_mem()); + if (!out) + ossl_raise(eX509NameError, NULL); + if (!X509_NAME_print_ex(out, name, 0, iflag)) { + BIO_free(out); + ossl_raise(eX509NameError, "X509_NAME_print_ex"); + } + return ossl_membio2str(out); +} + /* * call-seq: - * name.to_s => string - * name.to_s(flags) => string + * name.to_s -> string + * name.to_s(format) -> string * - * Returns this name as a Distinguished Name string. +flags+ may be one of: + * Returns a String representation of the Distinguished Name. _format_ is + * one of: * * * OpenSSL::X509::Name::COMPAT * * OpenSSL::X509::Name::RFC2253 * * OpenSSL::X509::Name::ONELINE * * OpenSSL::X509::Name::MULTILINE + * + * If _format_ is omitted, the largely broken and traditional OpenSSL format + * is used. */ static VALUE ossl_x509name_to_s(int argc, VALUE *argv, VALUE self) { - X509_NAME *name; - VALUE flag, str; - BIO *out; - unsigned long iflag; - - rb_scan_args(argc, argv, "01", &flag); - if (NIL_P(flag)) + rb_check_arity(argc, 0, 1); + /* name.to_s(nil) was allowed */ + if (!argc || NIL_P(argv[0])) return ossl_x509name_to_s_old(self); - else iflag = NUM2ULONG(flag); - if (!(out = BIO_new(BIO_s_mem()))) - ossl_raise(eX509NameError, NULL); - GetX509Name(self, name); - if (!X509_NAME_print_ex(out, name, 0, iflag)){ - BIO_free(out); - ossl_raise(eX509NameError, NULL); - } - str = ossl_membio2str(out); + else + return x509name_print(self, NUM2ULONG(argv[0])); +} +/* + * call-seq; + * name.to_utf8 -> string + * + * Returns an UTF-8 representation of the distinguished name, as specified + * in {RFC 2253}[https://www.ietf.org/rfc/rfc2253.txt]. + */ +static VALUE +ossl_x509name_to_utf8(VALUE self) +{ + VALUE str = x509name_print(self, XN_FLAG_RFC2253 & ~ASN1_STRFLGS_ESC_MSB); + rb_enc_associate_index(str, rb_utf8_encindex()); return str; } +/* :nodoc: */ +static VALUE +ossl_x509name_inspect(VALUE self) +{ + return rb_enc_sprintf(rb_utf8_encoding(), "#<%"PRIsVALUE" %"PRIsVALUE">", + rb_obj_class(self), ossl_x509name_to_utf8(self)); +} + /* * call-seq: * name.to_a => [[name, data, type], ...] @@ -338,18 +380,18 @@ ossl_x509name_cmp0(VALUE self, VALUE other) X509_NAME *name1, *name2; GetX509Name(self, name1); - SafeGetX509Name(other, name2); + GetX509Name(other, name2); return X509_NAME_cmp(name1, name2); } /* * call-seq: - * name.cmp other => integer - * name.<=> other => integer + * name.cmp(other) -> -1 | 0 | 1 + * name <=> other -> -1 | 0 | 1 * - * Compares this Name with +other+ and returns 0 if they are the same and -1 or - * +1 if they are greater or less than each other respectively. + * Compares this Name with _other_ and returns +0+ if they are the same and +-1+ + * or ++1+ if they are greater or less than each other respectively. */ static VALUE ossl_x509name_cmp(VALUE self, VALUE other) @@ -365,9 +407,9 @@ ossl_x509name_cmp(VALUE self, VALUE other) /* * call-seq: - * name.eql? other => boolean + * name.eql?(other) -> true | false * - * Returns true if +name+ and +other+ refer to the same hash key. + * Returns true if _name_ and _other_ refer to the same hash key. */ static VALUE ossl_x509name_eql(VALUE self, VALUE other) @@ -398,7 +440,6 @@ ossl_x509name_hash(VALUE self) return ULONG2NUM(hash); } -#ifdef HAVE_X509_NAME_HASH_OLD /* * call-seq: * name.hash_old => integer @@ -417,7 +458,6 @@ ossl_x509name_hash_old(VALUE self) return ULONG2NUM(hash); } -#endif /* * call-seq: @@ -478,17 +518,17 @@ Init_ossl_x509name(void) rb_define_alloc_func(cX509Name, ossl_x509name_alloc); rb_define_method(cX509Name, "initialize", ossl_x509name_initialize, -1); - rb_define_copy_func(cX509Name, ossl_x509name_initialize_copy); + rb_define_method(cX509Name, "initialize_copy", ossl_x509name_initialize_copy, 1); rb_define_method(cX509Name, "add_entry", ossl_x509name_add_entry, -1); rb_define_method(cX509Name, "to_s", ossl_x509name_to_s, -1); + rb_define_method(cX509Name, "to_utf8", ossl_x509name_to_utf8, 0); + rb_define_method(cX509Name, "inspect", ossl_x509name_inspect, 0); rb_define_method(cX509Name, "to_a", ossl_x509name_to_a, 0); rb_define_method(cX509Name, "cmp", ossl_x509name_cmp, 1); rb_define_alias(cX509Name, "<=>", "cmp"); rb_define_method(cX509Name, "eql?", ossl_x509name_eql, 1); rb_define_method(cX509Name, "hash", ossl_x509name_hash, 0); -#ifdef HAVE_X509_NAME_HASH_OLD rb_define_method(cX509Name, "hash_old", ossl_x509name_hash_old, 0); -#endif rb_define_method(cX509Name, "to_der", ossl_x509name_to_der, 0); utf8str = INT2NUM(V_ASN1_UTF8STRING); diff --git a/ext/openssl/ossl_x509req.c b/ext/openssl/ossl_x509req.c index 15bc7052d3..9f20dba311 100644 --- a/ext/openssl/ossl_x509req.c +++ b/ext/openssl/ossl_x509req.c @@ -23,10 +23,6 @@ ossl_raise(rb_eRuntimeError, "Req wasn't initialized!"); \ } \ } while (0) -#define SafeGetX509Req(obj, req) do { \ - OSSL_Check_Kind((obj), cX509Req); \ - GetX509Req((obj), (req)); \ -} while (0) /* * Classes @@ -51,49 +47,16 @@ static const rb_data_type_t ossl_x509req_type = { /* * Public functions */ -VALUE -ossl_x509req_new(X509_REQ *req) -{ - X509_REQ *new; - VALUE obj; - - obj = NewX509Req(cX509Req); - if (!req) { - new = X509_REQ_new(); - } else { - new = X509_REQ_dup(req); - } - if (!new) { - ossl_raise(eX509ReqError, NULL); - } - SetX509Req(obj, new); - - return obj; -} - X509_REQ * GetX509ReqPtr(VALUE obj) { X509_REQ *req; - SafeGetX509Req(obj, req); + GetX509Req(obj, req); return req; } -X509_REQ * -DupX509ReqPtr(VALUE obj) -{ - X509_REQ *req, *new; - - SafeGetX509Req(obj, req); - if (!(new = X509_REQ_dup(req))) { - ossl_raise(eX509ReqError, NULL); - } - - return new; -} - /* * Private functions */ @@ -145,7 +108,7 @@ ossl_x509req_copy(VALUE self, VALUE other) rb_check_frozen(self); if (self == other) return self; GetX509Req(self, a); - SafeGetX509Req(other, b); + GetX509Req(other, b); if (!(req = X509_REQ_dup(b))) { ossl_raise(eX509ReqError, NULL); } @@ -347,7 +310,7 @@ ossl_x509req_sign(VALUE self, VALUE key, VALUE digest) GetX509Req(self, req); pkey = GetPrivPKeyPtr(key); /* NO NEED TO DUP */ - md = GetDigestPtr(digest); + md = ossl_evp_get_digestbyname(digest); if (!X509_REQ_sign(req, pkey, md)) { ossl_raise(eX509ReqError, NULL); } @@ -457,7 +420,7 @@ Init_ossl_x509req(void) rb_define_alloc_func(cX509Req, ossl_x509req_alloc); rb_define_method(cX509Req, "initialize", ossl_x509req_initialize, -1); - rb_define_copy_func(cX509Req, ossl_x509req_copy); + rb_define_method(cX509Req, "initialize_copy", ossl_x509req_copy, 1); rb_define_method(cX509Req, "to_pem", ossl_x509req_to_pem, 0); rb_define_method(cX509Req, "to_der", ossl_x509req_to_der, 0); diff --git a/ext/openssl/ossl_x509revoked.c b/ext/openssl/ossl_x509revoked.c index 7960ea349e..85489efdb2 100644 --- a/ext/openssl/ossl_x509revoked.c +++ b/ext/openssl/ossl_x509revoked.c @@ -23,10 +23,6 @@ ossl_raise(rb_eRuntimeError, "REV wasn't initialized!"); \ } \ } while (0) -#define SafeGetX509Rev(obj, rev) do { \ - OSSL_Check_Kind((obj), cX509Rev); \ - GetX509Rev((obj), (rev)); \ -} while (0) /* * Classes @@ -76,7 +72,7 @@ DupX509RevokedPtr(VALUE obj) { X509_REVOKED *rev, *new; - SafeGetX509Rev(obj, rev); + GetX509Rev(obj, rev); if (!(new = X509_REVOKED_dup(rev))) { ossl_raise(eX509RevError, NULL); } @@ -116,7 +112,7 @@ ossl_x509revoked_initialize_copy(VALUE self, VALUE other) rb_check_frozen(self); GetX509Rev(self, rev); - SafeGetX509Rev(other, rev_other); + GetX509Rev(other, rev_other); rev_new = X509_REVOKED_dup(rev_other); if (!rev_new) @@ -159,10 +155,14 @@ static VALUE ossl_x509revoked_get_time(VALUE self) { X509_REVOKED *rev; + const ASN1_TIME *time; GetX509Rev(self, rev); + time = X509_REVOKED_get0_revocationDate(rev); + if (!time) + return Qnil; - return asn1time_to_time(X509_REVOKED_get0_revocationDate(rev)); + return asn1time_to_time(time); } static VALUE @@ -267,7 +267,7 @@ Init_ossl_x509revoked(void) rb_define_alloc_func(cX509Rev, ossl_x509revoked_alloc); rb_define_method(cX509Rev, "initialize", ossl_x509revoked_initialize, -1); - rb_define_copy_func(cX509Rev, ossl_x509revoked_initialize_copy); + rb_define_method(cX509Rev, "initialize_copy", ossl_x509revoked_initialize_copy, 1); rb_define_method(cX509Rev, "serial", ossl_x509revoked_get_serial, 0); rb_define_method(cX509Rev, "serial=", ossl_x509revoked_set_serial, 1); diff --git a/ext/openssl/ossl_x509store.c b/ext/openssl/ossl_x509store.c index 4becc8e3cd..c6cf67ad5d 100644 --- a/ext/openssl/ossl_x509store.c +++ b/ext/openssl/ossl_x509store.c @@ -23,10 +23,6 @@ ossl_raise(rb_eRuntimeError, "STORE wasn't initialized!"); \ } \ } while (0) -#define SafeGetX509Store(obj, st) do { \ - OSSL_Check_Kind((obj), cX509Store); \ - GetX509Store((obj), (st)); \ -} while (0) #define NewX509StCtx(klass) \ TypedData_Wrap_Struct((klass), &ossl_x509stctx_type, 0) @@ -42,10 +38,6 @@ ossl_raise(rb_eRuntimeError, "STORE_CTX is out of scope!"); \ } \ } while (0) -#define SafeGetX509StCtx(obj, storep) do { \ - OSSL_Check_Kind((obj), cX509StoreContext); \ - GetX509Store((obj), (ctx)); \ -} while (0) /* * Verify callback stuff @@ -130,34 +122,12 @@ static const rb_data_type_t ossl_x509store_type = { /* * Public functions */ -VALUE -ossl_x509store_new(X509_STORE *store) -{ - VALUE obj; - - obj = NewX509Store(cX509Store); - SetX509Store(obj, store); - - return obj; -} - X509_STORE * GetX509StorePtr(VALUE obj) { X509_STORE *store; - SafeGetX509Store(obj, store); - - return store; -} - -X509_STORE * -DupX509StorePtr(VALUE obj) -{ - X509_STORE *store; - - SafeGetX509Store(obj, store); - X509_STORE_up_ref(store); + GetX509Store(obj, store); return store; } @@ -242,9 +212,9 @@ ossl_x509store_initialize(int argc, VALUE *argv, VALUE self) /* * call-seq: - * store.flags = flag + * store.flags = flags * - * Sets +flag+ to the Store. +flag+ consists of zero or more of the constants + * Sets _flags_ to the Store. _flags_ consists of zero or more of the constants * defined in with name V_FLAG_* or'ed together. */ static VALUE @@ -263,7 +233,7 @@ ossl_x509store_set_flags(VALUE self, VALUE flags) * call-seq: * store.purpose = purpose * - * Sets the store's purpose to +purpose+. If specified, the verifications on + * Sets the store's purpose to _purpose_. If specified, the verifications on * the store will check every untrusted certificate's extensions are consistent * with the purpose. The purpose is specified by constants: * @@ -322,8 +292,9 @@ ossl_x509store_set_time(VALUE self, VALUE time) * call-seq: * store.add_file(file) -> self * - * Adds the certificates in +file+ to the certificate store. The +file+ can - * contain multiple PEM-encoded certificates. + * Adds the certificates in _file_ to the certificate store. _file_ is the path + * to the file, and the file contains one or more certificates in PEM format + * concatenated together. */ static VALUE ossl_x509store_add_file(VALUE self, VALUE file) @@ -359,7 +330,7 @@ ossl_x509store_add_file(VALUE self, VALUE file) * call-seq: * store.add_path(path) -> self * - * Adds +path+ as the hash dir to be looked up by the store. + * Adds _path_ as the hash dir to be looked up by the store. */ static VALUE ossl_x509store_add_path(VALUE self, VALUE dir) @@ -386,7 +357,7 @@ ossl_x509store_add_path(VALUE self, VALUE dir) * call-seq: * store.set_default_paths * - * Configures +store+ to look up CA certificates from the system default + * Configures _store_ to look up CA certificates from the system default * certificate store as needed basis. The location of the store can usually be * determined by: * @@ -410,7 +381,7 @@ ossl_x509store_set_default_paths(VALUE self) * call-seq: * store.add_cert(cert) * - * Adds the OpenSSL::X509::Certificate +cert+ to the certificate store. + * Adds the OpenSSL::X509::Certificate _cert_ to the certificate store. */ static VALUE ossl_x509store_add_cert(VALUE self, VALUE arg) @@ -431,7 +402,7 @@ ossl_x509store_add_cert(VALUE self, VALUE arg) * call-seq: * store.add_crl(crl) -> self * - * Adds the OpenSSL::X509::CRL +crl+ to the store. + * Adds the OpenSSL::X509::CRL _crl_ to the store. */ static VALUE ossl_x509store_add_crl(VALUE self, VALUE arg) @@ -456,15 +427,15 @@ static VALUE ossl_x509stctx_get_chain(VALUE); * call-seq: * store.verify(cert, chain = nil) -> true | false * - * Performs a certificate verification on the OpenSSL::X509::Certificate +cert+. + * Performs a certificate verification on the OpenSSL::X509::Certificate _cert_. * - * +chain+ can be an array of OpenSSL::X509::Certificate that is used to + * _chain_ can be an array of OpenSSL::X509::Certificate that is used to * construct the certificate chain. * * If a block is given, it overrides the callback set by #verify_callback=. * * After finishing the verification, the error information can be retrieved by - * #error, #error_string, and the resuting complete certificate chain can be + * #error, #error_string, and the resulting complete certificate chain can be * retrieved by #chain. */ static VALUE @@ -561,7 +532,7 @@ ossl_x509stctx_initialize(int argc, VALUE *argv, VALUE self) rb_scan_args(argc, argv, "12", &store, &cert, &chain); GetX509StCtx(self, ctx); - SafeGetX509Store(store, x509st); + GetX509Store(store, x509st); if(!NIL_P(cert)) x509 = DupX509CertPtr(cert); /* NEED TO DUP */ if(!NIL_P(chain)) x509s = ossl_x509_ary2sk(chain); if(X509_STORE_CTX_init(ctx, x509st, x509, x509s) != 1){ diff --git a/ext/openssl/ruby_missing.h b/ext/openssl/ruby_missing.h index 8dacc8266e..b8a0a0c180 100644 --- a/ext/openssl/ruby_missing.h +++ b/ext/openssl/ruby_missing.h @@ -10,11 +10,6 @@ #if !defined(_OSSL_RUBY_MISSING_H_) #define _OSSL_RUBY_MISSING_H_ -#define rb_define_copy_func(klass, func) \ - rb_define_method((klass), "initialize_copy", (func), 1) - -#define FPTR_TO_FD(fptr) ((fptr)->fd) - #ifndef RB_INTEGER_TYPE_P /* for Ruby 2.3 compatibility */ #define RB_INTEGER_TYPE_P(obj) (RB_FIXNUM_P(obj) || RB_TYPE_P(obj, T_BIGNUM)) -- cgit v1.2.3