Package: release.debian.org Severity: normal User: release.debian....@packages.debian.org Usertags: unblock X-Debbugs-Cc: ruby...@packages.debian.org Control: affects -1 + src:ruby3.1
Please unblock package ruby3.1 [ Reason ] This release updates the openssl bindings, fixing a few regressions that have been identified. [ Impact ] Without these changes, at least gitlab doesn't work correctly. [ Tests ] I had uploaded this to experimental some time ago, and the pseudo excuses against unstable showed no regressions. [ Risks ] The changes are contained to the implementatin of a few openssl methods. I think the risk is low. I had also tried updating to the new upstream release 3.1.3, which includes this change, but thought that contained too many non-critical changes. [ Checklist ] [x] all changes are documented in the d/changelog [x] I reviewed all changes and I approve them [x] attach debdiff against the package in testing [ Other info ] I'm also attaching the actual patch included in this upload as it is easier to read than the diff-in-diff in the debdiff. unblock ruby3.1/3.1.2-7
diff --git a/debian/changelog b/debian/changelog index c6bd035fc..54e474d21 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,15 @@ +ruby3.1 (3.1.2-7) unstable; urgency=medium + + * Upload to unstable + + -- Antonio Terceiro <terce...@debian.org> Sat, 25 Mar 2023 14:20:34 -0300 + +ruby3.1 (3.1.2-7~exp) experimental; urgency=medium + + * Update openssl extension to to 3.0.1 (Closes: #1032070) + + -- Antonio Terceiro <terce...@debian.org> Sun, 05 Mar 2023 17:13:36 -0300 + ruby3.1 (3.1.2-6) unstable; urgency=medium * Add missing dependencies for pkg-config test diff --git a/debian/patches/openssl-3.0.1.patch b/debian/patches/openssl-3.0.1.patch new file mode 100644 index 000000000..0762cb65e --- /dev/null +++ b/debian/patches/openssl-3.0.1.patch @@ -0,0 +1,495 @@ +From: Antonio Terceiro <terce...@debian.org> +Date: Sun, 5 Mar 2023 17:09:05 -0300 +Subject: openssl 3.0.1 + +This is a combination of several patches for openssl extension that fix +bugs in its version 3.0.0. + +Forwarded: not-needed +--- + ext/openssl/History.md | 40 +++++++++++++++++++++++++++++++++ + ext/openssl/extconf.rb | 5 +++-- + ext/openssl/lib/openssl/pkey.rb | 8 +++++++ + ext/openssl/lib/openssl/version.rb | 2 +- + ext/openssl/openssl.gemspec | 2 +- + ext/openssl/ossl_hmac.c | 8 +++++++ + ext/openssl/ossl_pkey.c | 46 +++++++++++++++++++++++++++++++++++--- + ext/openssl/ossl_pkey_ec.c | 4 ++++ + ext/openssl/ossl_x509cert.c | 6 ++--- + ext/openssl/ossl_x509crl.c | 6 ++--- + ext/openssl/ossl_x509req.c | 6 ++--- + ext/openssl/ossl_x509revoked.c | 6 ++--- + test/openssl/test_hmac.rb | 8 +++++++ + test/openssl/test_pkey_dsa.rb | 19 ++++++++++++++++ + test/openssl/test_pkey_ec.rb | 25 +++++++++++++++++++++ + test/openssl/test_pkey_rsa.rb | 5 +++++ + test/openssl/test_ssl.rb | 6 +++++ + 17 files changed, 183 insertions(+), 19 deletions(-) + +diff --git a/ext/openssl/History.md b/ext/openssl/History.md +index 479ec3b..a4f6bd7 100644 +--- a/ext/openssl/History.md ++++ b/ext/openssl/History.md +@@ -1,3 +1,27 @@ ++Version 3.0.1 ++============= ++ ++Merged changes in 2.1.4 and 2.2.2. Additionally, the following issues are fixed ++by this release. ++ ++Bug fixes ++--------- ++ ++* Add missing type check in OpenSSL::PKey::PKey#sign's optional parameters. ++ [[GitHub #531]](https://github.com/ruby/openssl/pull/531) ++* Work around OpenSSL 3.0's HMAC issues with a zero-length key. ++ [[GitHub #538]](https://github.com/ruby/openssl/pull/538) ++* Fix a regression in OpenSSL::PKey::DSA.generate's default of 'q' size. ++ [[GitHub #483]](https://github.com/ruby/openssl/issues/483) ++ [[GitHub #539]](https://github.com/ruby/openssl/pull/539) ++* Restore OpenSSL::PKey.read's ability to decode "openssl ecparam -genkey" ++ output when linked against OpenSSL 3.0. ++ [[GitHub #535]](https://github.com/ruby/openssl/pull/535) ++ [[GitHub #540]](https://github.com/ruby/openssl/pull/540) ++* Restore error checks in OpenSSL::PKey::EC#{to_der,to_pem}. ++ [[GitHub #541]](https://github.com/ruby/openssl/pull/541) ++ ++ + Version 3.0.0 + ============= + +@@ -100,6 +124,12 @@ Notable changes + [[GitHub #342]](https://github.com/ruby/openssl/issues/342) + + ++Version 2.2.2 ++============= ++ ++Merged changes in 2.1.4. ++ ++ + Version 2.2.1 + ============= + +@@ -194,6 +224,16 @@ Notable changes + [[GitHub #297]](https://github.com/ruby/openssl/pull/297) + + ++Version 2.1.4 ++============= ++ ++Bug fixes ++--------- ++ ++* Do not use pkg-config if --with-openssl-dir option is specified. ++ [[GitHub #486]](https://github.com/ruby/openssl/pull/486) ++ ++ + Version 2.1.3 + ============= + +diff --git a/ext/openssl/extconf.rb b/ext/openssl/extconf.rb +index fedcb93..d2d7893 100644 +--- a/ext/openssl/extconf.rb ++++ b/ext/openssl/extconf.rb +@@ -13,7 +13,7 @@ + + require "mkmf" + +-dir_config("openssl") ++dir_config_given = dir_config("openssl").any? + dir_config("kerberos") + + Logging::message "=== OpenSSL for Ruby configurator ===\n" +@@ -92,7 +92,7 @@ def find_openssl_library + end + + Logging::message "=== Checking for required stuff... ===\n" +-pkg_config_found = pkg_config("openssl") && have_header("openssl/ssl.h") ++pkg_config_found = !dir_config_given && pkg_config("openssl") && have_header("openssl/ssl.h") + + if !pkg_config_found && !find_openssl_library + Logging::message "=== Checking for required stuff failed. ===\n" +@@ -169,6 +169,7 @@ have_func("SSL_CTX_set_post_handshake_auth") + + # added in 1.1.1 + have_func("EVP_PKEY_check") ++have_func("EVP_PKEY_new_raw_private_key") + + # added in 3.0.0 + have_func("SSL_set0_tmp_dh_pkey") +diff --git a/ext/openssl/lib/openssl/pkey.rb b/ext/openssl/lib/openssl/pkey.rb +index c3e0629..d51f066 100644 +--- a/ext/openssl/lib/openssl/pkey.rb ++++ b/ext/openssl/lib/openssl/pkey.rb +@@ -167,8 +167,16 @@ module OpenSSL::PKey + # +size+:: + # The desired key size in bits. + def generate(size, &blk) ++ # FIPS 186-4 specifies four (L,N) pairs: (1024,160), (2048,224), ++ # (2048,256), and (3072,256). ++ # ++ # q size is derived here with compatibility with ++ # DSA_generator_parameters_ex() which previous versions of ruby/openssl ++ # used to call. ++ qsize = size >= 2048 ? 256 : 160 + dsaparams = OpenSSL::PKey.generate_parameters("DSA", { + "dsa_paramgen_bits" => size, ++ "dsa_paramgen_q_bits" => qsize, + }, &blk) + OpenSSL::PKey.generate_key(dsaparams) + end +diff --git a/ext/openssl/lib/openssl/version.rb b/ext/openssl/lib/openssl/version.rb +index 5e60604..b9e8444 100644 +--- a/ext/openssl/lib/openssl/version.rb ++++ b/ext/openssl/lib/openssl/version.rb +@@ -1,5 +1,5 @@ + # frozen_string_literal: true + + module OpenSSL +- VERSION = "3.0.0" ++ VERSION = "3.0.1" + end +diff --git a/ext/openssl/openssl.gemspec b/ext/openssl/openssl.gemspec +index c6cd818..1c13505 100644 +--- a/ext/openssl/openssl.gemspec ++++ b/ext/openssl/openssl.gemspec +@@ -1,6 +1,6 @@ + Gem::Specification.new do |spec| + spec.name = "openssl" +- spec.version = "3.0.0" ++ spec.version = "3.0.1" + spec.authors = ["Martin Bosslet", "SHIBATA Hiroshi", "Zachary Scott", "Kazuki Yamaguchi"] + spec.email = ["ruby-c...@ruby-lang.org"] + spec.summary = %q{OpenSSL provides SSL, TLS and general purpose cryptography.} +diff --git a/ext/openssl/ossl_hmac.c b/ext/openssl/ossl_hmac.c +index bfe3a74..1a5f471 100644 +--- a/ext/openssl/ossl_hmac.c ++++ b/ext/openssl/ossl_hmac.c +@@ -97,11 +97,19 @@ ossl_hmac_initialize(VALUE self, VALUE key, VALUE digest) + + GetHMAC(self, ctx); + StringValue(key); ++#ifdef HAVE_EVP_PKEY_NEW_RAW_PRIVATE_KEY ++ pkey = EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, NULL, ++ (unsigned char *)RSTRING_PTR(key), ++ RSTRING_LENINT(key)); ++ if (!pkey) ++ ossl_raise(eHMACError, "EVP_PKEY_new_raw_private_key"); ++#else + pkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, + (unsigned char *)RSTRING_PTR(key), + RSTRING_LENINT(key)); + if (!pkey) + ossl_raise(eHMACError, "EVP_PKEY_new_mac_key"); ++#endif + if (EVP_DigestSignInit(ctx, NULL, ossl_evp_get_digestbyname(digest), + NULL, pkey) != 1) { + EVP_PKEY_free(pkey); +diff --git a/ext/openssl/ossl_pkey.c b/ext/openssl/ossl_pkey.c +index 2a4835a..ee143d6 100644 +--- a/ext/openssl/ossl_pkey.c ++++ b/ext/openssl/ossl_pkey.c +@@ -99,17 +99,56 @@ ossl_pkey_read_generic(BIO *bio, VALUE pass) + /* First check DER */ + if (OSSL_DECODER_from_bio(dctx, bio) == 1) + goto out; ++ OSSL_BIO_reset(bio); + + /* Then check PEM; multiple OSSL_DECODER_from_bio() calls may be needed */ +- OSSL_BIO_reset(bio); + if (OSSL_DECODER_CTX_set_input_type(dctx, "PEM") != 1) + goto out; +- while (OSSL_DECODER_from_bio(dctx, bio) != 1) { +- if (BIO_eof(bio)) ++ /* ++ * First check for private key formats. This is to keep compatibility with ++ * ruby/openssl < 3.0 which decoded the following as a private key. ++ * ++ * $ openssl ecparam -name prime256v1 -genkey -outform PEM ++ * -----BEGIN EC PARAMETERS----- ++ * BggqhkjOPQMBBw== ++ * -----END EC PARAMETERS----- ++ * -----BEGIN EC PRIVATE KEY----- ++ * MHcCAQEEIAG8ugBbA5MHkqnZ9ujQF93OyUfL9tk8sxqM5Wv5tKg5oAoGCCqGSM49 ++ * AwEHoUQDQgAEVcjhJfkwqh5C7kGuhAf8XaAjVuG5ADwb5ayg/cJijCgs+GcXeedj ++ * 86avKpGH84DXUlB23C/kPt+6fXYlitUmXQ== ++ * -----END EC PRIVATE KEY----- ++ * ++ * While the first PEM block is a proper encoding of ECParameters, thus ++ * OSSL_DECODER_from_bio() would pick it up, ruby/openssl used to return ++ * the latter instead. Existing applications expect this behavior. ++ * ++ * Note that normally, the input is supposed to contain a single decodable ++ * PEM block only, so this special handling should not create a new problem. ++ */ ++ OSSL_DECODER_CTX_set_selection(dctx, EVP_PKEY_KEYPAIR); ++ while (1) { ++ if (OSSL_DECODER_from_bio(dctx, bio) == 1) + goto out; ++ if (BIO_eof(bio)) ++ break; + pos2 = BIO_tell(bio); + if (pos2 < 0 || pos2 <= pos) ++ break; ++ ossl_clear_error(); ++ pos = pos2; ++ } ++ ++ OSSL_BIO_reset(bio); ++ OSSL_DECODER_CTX_set_selection(dctx, 0); ++ while (1) { ++ if (OSSL_DECODER_from_bio(dctx, bio) == 1) + goto out; ++ if (BIO_eof(bio)) ++ break; ++ pos2 = BIO_tell(bio); ++ if (pos2 < 0 || pos2 <= pos) ++ break; ++ ossl_clear_error(); + pos = pos2; + } + +@@ -200,6 +239,7 @@ static VALUE + pkey_ctx_apply_options0(VALUE args_v) + { + VALUE *args = (VALUE *)args_v; ++ Check_Type(args[1], T_HASH); + + rb_block_call(args[1], rb_intern("each"), 0, NULL, + pkey_ctx_apply_options_i, args[0]); +diff --git a/ext/openssl/ossl_pkey_ec.c b/ext/openssl/ossl_pkey_ec.c +index dee2154..06d59c2 100644 +--- a/ext/openssl/ossl_pkey_ec.c ++++ b/ext/openssl/ossl_pkey_ec.c +@@ -414,6 +414,8 @@ ossl_ec_key_export(int argc, VALUE *argv, VALUE self) + EC_KEY *ec; + + GetEC(self, ec); ++ if (EC_KEY_get0_public_key(ec) == NULL) ++ ossl_raise(eECError, "can't export - no public key set"); + if (EC_KEY_get0_private_key(ec)) + return ossl_pkey_export_traditional(argc, argv, self, 0); + else +@@ -432,6 +434,8 @@ ossl_ec_key_to_der(VALUE self) + EC_KEY *ec; + + GetEC(self, ec); ++ if (EC_KEY_get0_public_key(ec) == NULL) ++ ossl_raise(eECError, "can't export - no public key set"); + if (EC_KEY_get0_private_key(ec)) + return ossl_pkey_export_traditional(0, NULL, self, 1); + else +diff --git a/ext/openssl/ossl_x509cert.c b/ext/openssl/ossl_x509cert.c +index 996f184..9443541 100644 +--- a/ext/openssl/ossl_x509cert.c ++++ b/ext/openssl/ossl_x509cert.c +@@ -642,12 +642,12 @@ ossl_x509_set_extensions(VALUE self, VALUE ary) + OSSL_Check_Kind(RARRAY_AREF(ary, i), cX509Ext); + } + GetX509(self, x509); +- while ((ext = X509_delete_ext(x509, 0))) +- X509_EXTENSION_free(ext); ++ for (i = X509_get_ext_count(x509); i > 0; i--) ++ X509_EXTENSION_free(X509_delete_ext(x509, 0)); + for (i=0; i<RARRAY_LEN(ary); i++) { + ext = GetX509ExtPtr(RARRAY_AREF(ary, i)); + if (!X509_add_ext(x509, ext, -1)) { /* DUPs ext */ +- ossl_raise(eX509CertError, NULL); ++ ossl_raise(eX509CertError, "X509_add_ext"); + } + } + +diff --git a/ext/openssl/ossl_x509crl.c b/ext/openssl/ossl_x509crl.c +index 863f028..6c1d915 100644 +--- a/ext/openssl/ossl_x509crl.c ++++ b/ext/openssl/ossl_x509crl.c +@@ -474,12 +474,12 @@ ossl_x509crl_set_extensions(VALUE self, VALUE ary) + OSSL_Check_Kind(RARRAY_AREF(ary, i), cX509Ext); + } + GetX509CRL(self, crl); +- while ((ext = X509_CRL_delete_ext(crl, 0))) +- X509_EXTENSION_free(ext); ++ for (i = X509_CRL_get_ext_count(crl); i > 0; i--) ++ X509_EXTENSION_free(X509_CRL_delete_ext(crl, 0)); + for (i=0; i<RARRAY_LEN(ary); i++) { + ext = GetX509ExtPtr(RARRAY_AREF(ary, i)); /* NO NEED TO DUP */ + if (!X509_CRL_add_ext(crl, ext, -1)) { +- ossl_raise(eX509CRLError, NULL); ++ ossl_raise(eX509CRLError, "X509_CRL_add_ext"); + } + } + +diff --git a/ext/openssl/ossl_x509req.c b/ext/openssl/ossl_x509req.c +index 6eb91e9..77a7d3f 100644 +--- a/ext/openssl/ossl_x509req.c ++++ b/ext/openssl/ossl_x509req.c +@@ -380,13 +380,13 @@ ossl_x509req_set_attributes(VALUE self, VALUE ary) + OSSL_Check_Kind(RARRAY_AREF(ary, i), cX509Attr); + } + GetX509Req(self, req); +- while ((attr = X509_REQ_delete_attr(req, 0))) +- X509_ATTRIBUTE_free(attr); ++ for (i = X509_REQ_get_attr_count(req); i > 0; i--) ++ X509_ATTRIBUTE_free(X509_REQ_delete_attr(req, 0)); + for (i=0;i<RARRAY_LEN(ary); i++) { + item = RARRAY_AREF(ary, i); + attr = GetX509AttrPtr(item); + if (!X509_REQ_add1_attr(req, attr)) { +- ossl_raise(eX509ReqError, NULL); ++ ossl_raise(eX509ReqError, "X509_REQ_add1_attr"); + } + } + return ary; +diff --git a/ext/openssl/ossl_x509revoked.c b/ext/openssl/ossl_x509revoked.c +index 5fe6853..10b8aa4 100644 +--- a/ext/openssl/ossl_x509revoked.c ++++ b/ext/openssl/ossl_x509revoked.c +@@ -223,13 +223,13 @@ ossl_x509revoked_set_extensions(VALUE self, VALUE ary) + OSSL_Check_Kind(RARRAY_AREF(ary, i), cX509Ext); + } + GetX509Rev(self, rev); +- while ((ext = X509_REVOKED_delete_ext(rev, 0))) +- X509_EXTENSION_free(ext); ++ for (i = X509_REVOKED_get_ext_count(rev); i > 0; i--) ++ X509_EXTENSION_free(X509_REVOKED_delete_ext(rev, 0)); + for (i=0; i<RARRAY_LEN(ary); i++) { + item = RARRAY_AREF(ary, i); + ext = GetX509ExtPtr(item); + if(!X509_REVOKED_add_ext(rev, ext, -1)) { +- ossl_raise(eX509RevError, NULL); ++ ossl_raise(eX509RevError, "X509_REVOKED_add_ext"); + } + } + +diff --git a/test/openssl/test_hmac.rb b/test/openssl/test_hmac.rb +index 47cb371..08b888d 100644 +--- a/test/openssl/test_hmac.rb ++++ b/test/openssl/test_hmac.rb +@@ -63,6 +63,14 @@ class OpenSSL::TestHMAC < OpenSSL::TestCase + b64digest = OpenSSL::HMAC.base64digest("MD5", key, "Hi There") + assert_equal "kpRyejY4uxwT9I74FYv8nQ==", b64digest + end ++ ++ def test_zero_length_key ++ # Empty string as the key ++ hexdigest = OpenSSL::HMAC.hexdigest("SHA256", "\0"*32, "test") ++ assert_equal "43b0cef99265f9e34c10ea9d3501926d27b39f57c6d674561d8ba236e7a819fb", hexdigest ++ hexdigest = OpenSSL::HMAC.hexdigest("SHA256", "", "test") ++ assert_equal "43b0cef99265f9e34c10ea9d3501926d27b39f57c6d674561d8ba236e7a819fb", hexdigest ++ end + end + + end +diff --git a/test/openssl/test_pkey_dsa.rb b/test/openssl/test_pkey_dsa.rb +index 726b7db..de6aa63 100644 +--- a/test/openssl/test_pkey_dsa.rb ++++ b/test/openssl/test_pkey_dsa.rb +@@ -28,6 +28,25 @@ class OpenSSL::TestPKeyDSA < OpenSSL::PKeyTestCase + end + end + ++ def test_generate ++ # DSA.generate used to call DSA_generate_parameters_ex(), which adjusts the ++ # size of q according to the size of p ++ key1024 = OpenSSL::PKey::DSA.generate(1024) ++ assert_predicate key1024, :private? ++ assert_equal 1024, key1024.p.num_bits ++ assert_equal 160, key1024.q.num_bits ++ ++ key2048 = OpenSSL::PKey::DSA.generate(2048) ++ assert_equal 2048, key2048.p.num_bits ++ assert_equal 256, key2048.q.num_bits ++ ++ if ENV["OSSL_TEST_ALL"] == "1" # slow ++ key3072 = OpenSSL::PKey::DSA.generate(3072) ++ assert_equal 3072, key3072.p.num_bits ++ assert_equal 256, key3072.q.num_bits ++ end ++ end ++ + def test_sign_verify + dsa512 = Fixtures.pkey("dsa512") + data = "Sign me!" +diff --git a/test/openssl/test_pkey_ec.rb b/test/openssl/test_pkey_ec.rb +index ffe5a94..9a4818d 100644 +--- a/test/openssl/test_pkey_ec.rb ++++ b/test/openssl/test_pkey_ec.rb +@@ -61,8 +61,10 @@ class OpenSSL::TestEC < OpenSSL::PKeyTestCase + def test_generate_key + ec = OpenSSL::PKey::EC.new("prime256v1") + assert_equal false, ec.private? ++ assert_raise(OpenSSL::PKey::ECError) { ec.to_der } + ec.generate_key! + assert_equal true, ec.private? ++ assert_nothing_raised { ec.to_der } + end if !openssl?(3, 0, 0) + + def test_marshal +@@ -199,6 +201,29 @@ class OpenSSL::TestEC < OpenSSL::PKeyTestCase + assert_equal pem, p256.export + end + ++ def test_ECPrivateKey_with_parameters ++ p256 = Fixtures.pkey("p256") ++ ++ # The format used by "openssl ecparam -name prime256v1 -genkey -outform PEM" ++ # ++ # "EC PARAMETERS" block should be ignored if it is followed by an ++ # "EC PRIVATE KEY" block ++ in_pem = <<~EOF ++ -----BEGIN EC PARAMETERS----- ++ BggqhkjOPQMBBw== ++ -----END EC PARAMETERS----- ++ -----BEGIN EC PRIVATE KEY----- ++ MHcCAQEEIID49FDqcf1O1eO8saTgG70UbXQw9Fqwseliit2aWhH1oAoGCCqGSM49 ++ AwEHoUQDQgAEFglk2c+oVUIKQ64eZG9bhLNPWB7lSZ/ArK41eGy5wAzU/0G51Xtt ++ CeBUl+MahZtn9fO1JKdF4qJmS39dXnpENg== ++ -----END EC PRIVATE KEY----- ++ EOF ++ ++ key = OpenSSL::PKey::EC.new(in_pem) ++ assert_same_ec p256, key ++ assert_equal p256.to_der, key.to_der ++ end ++ + def test_ECPrivateKey_encrypted + p256 = Fixtures.pkey("p256") + # key = abcdef +diff --git a/test/openssl/test_pkey_rsa.rb b/test/openssl/test_pkey_rsa.rb +index 4bb39ed..fa84b76 100644 +--- a/test/openssl/test_pkey_rsa.rb ++++ b/test/openssl/test_pkey_rsa.rb +@@ -108,6 +108,11 @@ class OpenSSL::TestPKeyRSA < OpenSSL::PKeyTestCase + salt_length: 20, mgf1_hash: "SHA1") + # Defaults to PKCS #1 v1.5 padding => verification failure + assert_equal false, key.verify("SHA256", sig_pss, data) ++ ++ # option type check ++ assert_raise_with_message(TypeError, /expected Hash/) { ++ key.sign("SHA256", data, ["x"]) ++ } + end + + def test_sign_verify_raw +diff --git a/test/openssl/test_ssl.rb b/test/openssl/test_ssl.rb +index a7607da..39964bf 100644 +--- a/test/openssl/test_ssl.rb ++++ b/test/openssl/test_ssl.rb +@@ -676,10 +676,16 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase + # buzz.example.net, respectively). ... + assert_equal(true, OpenSSL::SSL.verify_certificate_identity( + create_cert_with_san('DNS:baz*.example.com'), 'baz1.example.com')) ++ ++ # LibreSSL 3.5.0+ doesn't support other wildcard certificates ++ # (it isn't required to, as RFC states MAY, not MUST) ++ return if libressl?(3, 5, 0) ++ + assert_equal(true, OpenSSL::SSL.verify_certificate_identity( + create_cert_with_san('DNS:*baz.example.com'), 'foobaz.example.com')) + assert_equal(true, OpenSSL::SSL.verify_certificate_identity( + create_cert_with_san('DNS:b*z.example.com'), 'buzz.example.com')) ++ + # Section 6.4.3 of RFC6125 states that client should NOT match identifier + # where wildcard is other than left-most label. + # diff --git a/debian/patches/series b/debian/patches/series index e2febb232..50eaef8ce 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -14,3 +14,4 @@ Fallback-PKG_CONFIG-to-the-configured-pkg-config-always.patch Honor-the-tool-prefix-against-pkg-config.patch Fix-for-tzdata-2022g.patch Merge-CGI-0.3.5.patch +openssl-3.0.1.patch
From: Antonio Terceiro <terce...@debian.org> Date: Sun, 5 Mar 2023 17:09:05 -0300 Subject: openssl 3.0.1 This is a combination of several patches for openssl extension that fix bugs in its version 3.0.0. Forwarded: not-needed --- ext/openssl/History.md | 40 +++++++++++++++++++++++++++++++++ ext/openssl/extconf.rb | 5 +++-- ext/openssl/lib/openssl/pkey.rb | 8 +++++++ ext/openssl/lib/openssl/version.rb | 2 +- ext/openssl/openssl.gemspec | 2 +- ext/openssl/ossl_hmac.c | 8 +++++++ ext/openssl/ossl_pkey.c | 46 +++++++++++++++++++++++++++++++++++--- ext/openssl/ossl_pkey_ec.c | 4 ++++ ext/openssl/ossl_x509cert.c | 6 ++--- ext/openssl/ossl_x509crl.c | 6 ++--- ext/openssl/ossl_x509req.c | 6 ++--- ext/openssl/ossl_x509revoked.c | 6 ++--- test/openssl/test_hmac.rb | 8 +++++++ test/openssl/test_pkey_dsa.rb | 19 ++++++++++++++++ test/openssl/test_pkey_ec.rb | 25 +++++++++++++++++++++ test/openssl/test_pkey_rsa.rb | 5 +++++ test/openssl/test_ssl.rb | 6 +++++ 17 files changed, 183 insertions(+), 19 deletions(-) diff --git a/ext/openssl/History.md b/ext/openssl/History.md index 479ec3b..a4f6bd7 100644 --- a/ext/openssl/History.md +++ b/ext/openssl/History.md @@ -1,3 +1,27 @@ +Version 3.0.1 +============= + +Merged changes in 2.1.4 and 2.2.2. Additionally, the following issues are fixed +by this release. + +Bug fixes +--------- + +* Add missing type check in OpenSSL::PKey::PKey#sign's optional parameters. + [[GitHub #531]](https://github.com/ruby/openssl/pull/531) +* Work around OpenSSL 3.0's HMAC issues with a zero-length key. + [[GitHub #538]](https://github.com/ruby/openssl/pull/538) +* Fix a regression in OpenSSL::PKey::DSA.generate's default of 'q' size. + [[GitHub #483]](https://github.com/ruby/openssl/issues/483) + [[GitHub #539]](https://github.com/ruby/openssl/pull/539) +* Restore OpenSSL::PKey.read's ability to decode "openssl ecparam -genkey" + output when linked against OpenSSL 3.0. + [[GitHub #535]](https://github.com/ruby/openssl/pull/535) + [[GitHub #540]](https://github.com/ruby/openssl/pull/540) +* Restore error checks in OpenSSL::PKey::EC#{to_der,to_pem}. + [[GitHub #541]](https://github.com/ruby/openssl/pull/541) + + Version 3.0.0 ============= @@ -100,6 +124,12 @@ Notable changes [[GitHub #342]](https://github.com/ruby/openssl/issues/342) +Version 2.2.2 +============= + +Merged changes in 2.1.4. + + Version 2.2.1 ============= @@ -194,6 +224,16 @@ Notable changes [[GitHub #297]](https://github.com/ruby/openssl/pull/297) +Version 2.1.4 +============= + +Bug fixes +--------- + +* Do not use pkg-config if --with-openssl-dir option is specified. + [[GitHub #486]](https://github.com/ruby/openssl/pull/486) + + Version 2.1.3 ============= diff --git a/ext/openssl/extconf.rb b/ext/openssl/extconf.rb index fedcb93..d2d7893 100644 --- a/ext/openssl/extconf.rb +++ b/ext/openssl/extconf.rb @@ -13,7 +13,7 @@ require "mkmf" -dir_config("openssl") +dir_config_given = dir_config("openssl").any? dir_config("kerberos") Logging::message "=== OpenSSL for Ruby configurator ===\n" @@ -92,7 +92,7 @@ def find_openssl_library end Logging::message "=== Checking for required stuff... ===\n" -pkg_config_found = pkg_config("openssl") && have_header("openssl/ssl.h") +pkg_config_found = !dir_config_given && pkg_config("openssl") && have_header("openssl/ssl.h") if !pkg_config_found && !find_openssl_library Logging::message "=== Checking for required stuff failed. ===\n" @@ -169,6 +169,7 @@ have_func("SSL_CTX_set_post_handshake_auth") # added in 1.1.1 have_func("EVP_PKEY_check") +have_func("EVP_PKEY_new_raw_private_key") # added in 3.0.0 have_func("SSL_set0_tmp_dh_pkey") diff --git a/ext/openssl/lib/openssl/pkey.rb b/ext/openssl/lib/openssl/pkey.rb index c3e0629..d51f066 100644 --- a/ext/openssl/lib/openssl/pkey.rb +++ b/ext/openssl/lib/openssl/pkey.rb @@ -167,8 +167,16 @@ module OpenSSL::PKey # +size+:: # The desired key size in bits. def generate(size, &blk) + # FIPS 186-4 specifies four (L,N) pairs: (1024,160), (2048,224), + # (2048,256), and (3072,256). + # + # q size is derived here with compatibility with + # DSA_generator_parameters_ex() which previous versions of ruby/openssl + # used to call. + qsize = size >= 2048 ? 256 : 160 dsaparams = OpenSSL::PKey.generate_parameters("DSA", { "dsa_paramgen_bits" => size, + "dsa_paramgen_q_bits" => qsize, }, &blk) OpenSSL::PKey.generate_key(dsaparams) end diff --git a/ext/openssl/lib/openssl/version.rb b/ext/openssl/lib/openssl/version.rb index 5e60604..b9e8444 100644 --- a/ext/openssl/lib/openssl/version.rb +++ b/ext/openssl/lib/openssl/version.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true module OpenSSL - VERSION = "3.0.0" + VERSION = "3.0.1" end diff --git a/ext/openssl/openssl.gemspec b/ext/openssl/openssl.gemspec index c6cd818..1c13505 100644 --- a/ext/openssl/openssl.gemspec +++ b/ext/openssl/openssl.gemspec @@ -1,6 +1,6 @@ Gem::Specification.new do |spec| spec.name = "openssl" - spec.version = "3.0.0" + spec.version = "3.0.1" spec.authors = ["Martin Bosslet", "SHIBATA Hiroshi", "Zachary Scott", "Kazuki Yamaguchi"] spec.email = ["ruby-c...@ruby-lang.org"] spec.summary = %q{OpenSSL provides SSL, TLS and general purpose cryptography.} diff --git a/ext/openssl/ossl_hmac.c b/ext/openssl/ossl_hmac.c index bfe3a74..1a5f471 100644 --- a/ext/openssl/ossl_hmac.c +++ b/ext/openssl/ossl_hmac.c @@ -97,11 +97,19 @@ ossl_hmac_initialize(VALUE self, VALUE key, VALUE digest) GetHMAC(self, ctx); StringValue(key); +#ifdef HAVE_EVP_PKEY_NEW_RAW_PRIVATE_KEY + pkey = EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, NULL, + (unsigned char *)RSTRING_PTR(key), + RSTRING_LENINT(key)); + if (!pkey) + ossl_raise(eHMACError, "EVP_PKEY_new_raw_private_key"); +#else pkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, (unsigned char *)RSTRING_PTR(key), RSTRING_LENINT(key)); if (!pkey) ossl_raise(eHMACError, "EVP_PKEY_new_mac_key"); +#endif if (EVP_DigestSignInit(ctx, NULL, ossl_evp_get_digestbyname(digest), NULL, pkey) != 1) { EVP_PKEY_free(pkey); diff --git a/ext/openssl/ossl_pkey.c b/ext/openssl/ossl_pkey.c index 2a4835a..ee143d6 100644 --- a/ext/openssl/ossl_pkey.c +++ b/ext/openssl/ossl_pkey.c @@ -99,17 +99,56 @@ ossl_pkey_read_generic(BIO *bio, VALUE pass) /* First check DER */ if (OSSL_DECODER_from_bio(dctx, bio) == 1) goto out; + OSSL_BIO_reset(bio); /* Then check PEM; multiple OSSL_DECODER_from_bio() calls may be needed */ - OSSL_BIO_reset(bio); if (OSSL_DECODER_CTX_set_input_type(dctx, "PEM") != 1) goto out; - while (OSSL_DECODER_from_bio(dctx, bio) != 1) { - if (BIO_eof(bio)) + /* + * First check for private key formats. This is to keep compatibility with + * ruby/openssl < 3.0 which decoded the following as a private key. + * + * $ openssl ecparam -name prime256v1 -genkey -outform PEM + * -----BEGIN EC PARAMETERS----- + * BggqhkjOPQMBBw== + * -----END EC PARAMETERS----- + * -----BEGIN EC PRIVATE KEY----- + * MHcCAQEEIAG8ugBbA5MHkqnZ9ujQF93OyUfL9tk8sxqM5Wv5tKg5oAoGCCqGSM49 + * AwEHoUQDQgAEVcjhJfkwqh5C7kGuhAf8XaAjVuG5ADwb5ayg/cJijCgs+GcXeedj + * 86avKpGH84DXUlB23C/kPt+6fXYlitUmXQ== + * -----END EC PRIVATE KEY----- + * + * While the first PEM block is a proper encoding of ECParameters, thus + * OSSL_DECODER_from_bio() would pick it up, ruby/openssl used to return + * the latter instead. Existing applications expect this behavior. + * + * Note that normally, the input is supposed to contain a single decodable + * PEM block only, so this special handling should not create a new problem. + */ + OSSL_DECODER_CTX_set_selection(dctx, EVP_PKEY_KEYPAIR); + while (1) { + if (OSSL_DECODER_from_bio(dctx, bio) == 1) goto out; + if (BIO_eof(bio)) + break; pos2 = BIO_tell(bio); if (pos2 < 0 || pos2 <= pos) + break; + ossl_clear_error(); + pos = pos2; + } + + OSSL_BIO_reset(bio); + OSSL_DECODER_CTX_set_selection(dctx, 0); + while (1) { + if (OSSL_DECODER_from_bio(dctx, bio) == 1) goto out; + if (BIO_eof(bio)) + break; + pos2 = BIO_tell(bio); + if (pos2 < 0 || pos2 <= pos) + break; + ossl_clear_error(); pos = pos2; } @@ -200,6 +239,7 @@ static VALUE pkey_ctx_apply_options0(VALUE args_v) { VALUE *args = (VALUE *)args_v; + Check_Type(args[1], T_HASH); rb_block_call(args[1], rb_intern("each"), 0, NULL, pkey_ctx_apply_options_i, args[0]); diff --git a/ext/openssl/ossl_pkey_ec.c b/ext/openssl/ossl_pkey_ec.c index dee2154..06d59c2 100644 --- a/ext/openssl/ossl_pkey_ec.c +++ b/ext/openssl/ossl_pkey_ec.c @@ -414,6 +414,8 @@ ossl_ec_key_export(int argc, VALUE *argv, VALUE self) EC_KEY *ec; GetEC(self, ec); + if (EC_KEY_get0_public_key(ec) == NULL) + ossl_raise(eECError, "can't export - no public key set"); if (EC_KEY_get0_private_key(ec)) return ossl_pkey_export_traditional(argc, argv, self, 0); else @@ -432,6 +434,8 @@ ossl_ec_key_to_der(VALUE self) EC_KEY *ec; GetEC(self, ec); + if (EC_KEY_get0_public_key(ec) == NULL) + ossl_raise(eECError, "can't export - no public key set"); if (EC_KEY_get0_private_key(ec)) return ossl_pkey_export_traditional(0, NULL, self, 1); else diff --git a/ext/openssl/ossl_x509cert.c b/ext/openssl/ossl_x509cert.c index 996f184..9443541 100644 --- a/ext/openssl/ossl_x509cert.c +++ b/ext/openssl/ossl_x509cert.c @@ -642,12 +642,12 @@ ossl_x509_set_extensions(VALUE self, VALUE ary) OSSL_Check_Kind(RARRAY_AREF(ary, i), cX509Ext); } GetX509(self, x509); - while ((ext = X509_delete_ext(x509, 0))) - X509_EXTENSION_free(ext); + for (i = X509_get_ext_count(x509); i > 0; i--) + X509_EXTENSION_free(X509_delete_ext(x509, 0)); for (i=0; i<RARRAY_LEN(ary); i++) { ext = GetX509ExtPtr(RARRAY_AREF(ary, i)); if (!X509_add_ext(x509, ext, -1)) { /* DUPs ext */ - ossl_raise(eX509CertError, NULL); + ossl_raise(eX509CertError, "X509_add_ext"); } } diff --git a/ext/openssl/ossl_x509crl.c b/ext/openssl/ossl_x509crl.c index 863f028..6c1d915 100644 --- a/ext/openssl/ossl_x509crl.c +++ b/ext/openssl/ossl_x509crl.c @@ -474,12 +474,12 @@ ossl_x509crl_set_extensions(VALUE self, VALUE ary) OSSL_Check_Kind(RARRAY_AREF(ary, i), cX509Ext); } GetX509CRL(self, crl); - while ((ext = X509_CRL_delete_ext(crl, 0))) - X509_EXTENSION_free(ext); + for (i = X509_CRL_get_ext_count(crl); i > 0; i--) + X509_EXTENSION_free(X509_CRL_delete_ext(crl, 0)); for (i=0; i<RARRAY_LEN(ary); i++) { ext = GetX509ExtPtr(RARRAY_AREF(ary, i)); /* NO NEED TO DUP */ if (!X509_CRL_add_ext(crl, ext, -1)) { - ossl_raise(eX509CRLError, NULL); + ossl_raise(eX509CRLError, "X509_CRL_add_ext"); } } diff --git a/ext/openssl/ossl_x509req.c b/ext/openssl/ossl_x509req.c index 6eb91e9..77a7d3f 100644 --- a/ext/openssl/ossl_x509req.c +++ b/ext/openssl/ossl_x509req.c @@ -380,13 +380,13 @@ ossl_x509req_set_attributes(VALUE self, VALUE ary) OSSL_Check_Kind(RARRAY_AREF(ary, i), cX509Attr); } GetX509Req(self, req); - while ((attr = X509_REQ_delete_attr(req, 0))) - X509_ATTRIBUTE_free(attr); + for (i = X509_REQ_get_attr_count(req); i > 0; i--) + X509_ATTRIBUTE_free(X509_REQ_delete_attr(req, 0)); for (i=0;i<RARRAY_LEN(ary); i++) { item = RARRAY_AREF(ary, i); attr = GetX509AttrPtr(item); if (!X509_REQ_add1_attr(req, attr)) { - ossl_raise(eX509ReqError, NULL); + ossl_raise(eX509ReqError, "X509_REQ_add1_attr"); } } return ary; diff --git a/ext/openssl/ossl_x509revoked.c b/ext/openssl/ossl_x509revoked.c index 5fe6853..10b8aa4 100644 --- a/ext/openssl/ossl_x509revoked.c +++ b/ext/openssl/ossl_x509revoked.c @@ -223,13 +223,13 @@ ossl_x509revoked_set_extensions(VALUE self, VALUE ary) OSSL_Check_Kind(RARRAY_AREF(ary, i), cX509Ext); } GetX509Rev(self, rev); - while ((ext = X509_REVOKED_delete_ext(rev, 0))) - X509_EXTENSION_free(ext); + for (i = X509_REVOKED_get_ext_count(rev); i > 0; i--) + X509_EXTENSION_free(X509_REVOKED_delete_ext(rev, 0)); for (i=0; i<RARRAY_LEN(ary); i++) { item = RARRAY_AREF(ary, i); ext = GetX509ExtPtr(item); if(!X509_REVOKED_add_ext(rev, ext, -1)) { - ossl_raise(eX509RevError, NULL); + ossl_raise(eX509RevError, "X509_REVOKED_add_ext"); } } diff --git a/test/openssl/test_hmac.rb b/test/openssl/test_hmac.rb index 47cb371..08b888d 100644 --- a/test/openssl/test_hmac.rb +++ b/test/openssl/test_hmac.rb @@ -63,6 +63,14 @@ class OpenSSL::TestHMAC < OpenSSL::TestCase b64digest = OpenSSL::HMAC.base64digest("MD5", key, "Hi There") assert_equal "kpRyejY4uxwT9I74FYv8nQ==", b64digest end + + def test_zero_length_key + # Empty string as the key + hexdigest = OpenSSL::HMAC.hexdigest("SHA256", "\0"*32, "test") + assert_equal "43b0cef99265f9e34c10ea9d3501926d27b39f57c6d674561d8ba236e7a819fb", hexdigest + hexdigest = OpenSSL::HMAC.hexdigest("SHA256", "", "test") + assert_equal "43b0cef99265f9e34c10ea9d3501926d27b39f57c6d674561d8ba236e7a819fb", hexdigest + end end end diff --git a/test/openssl/test_pkey_dsa.rb b/test/openssl/test_pkey_dsa.rb index 726b7db..de6aa63 100644 --- a/test/openssl/test_pkey_dsa.rb +++ b/test/openssl/test_pkey_dsa.rb @@ -28,6 +28,25 @@ class OpenSSL::TestPKeyDSA < OpenSSL::PKeyTestCase end end + def test_generate + # DSA.generate used to call DSA_generate_parameters_ex(), which adjusts the + # size of q according to the size of p + key1024 = OpenSSL::PKey::DSA.generate(1024) + assert_predicate key1024, :private? + assert_equal 1024, key1024.p.num_bits + assert_equal 160, key1024.q.num_bits + + key2048 = OpenSSL::PKey::DSA.generate(2048) + assert_equal 2048, key2048.p.num_bits + assert_equal 256, key2048.q.num_bits + + if ENV["OSSL_TEST_ALL"] == "1" # slow + key3072 = OpenSSL::PKey::DSA.generate(3072) + assert_equal 3072, key3072.p.num_bits + assert_equal 256, key3072.q.num_bits + end + end + def test_sign_verify dsa512 = Fixtures.pkey("dsa512") data = "Sign me!" diff --git a/test/openssl/test_pkey_ec.rb b/test/openssl/test_pkey_ec.rb index ffe5a94..9a4818d 100644 --- a/test/openssl/test_pkey_ec.rb +++ b/test/openssl/test_pkey_ec.rb @@ -61,8 +61,10 @@ class OpenSSL::TestEC < OpenSSL::PKeyTestCase def test_generate_key ec = OpenSSL::PKey::EC.new("prime256v1") assert_equal false, ec.private? + assert_raise(OpenSSL::PKey::ECError) { ec.to_der } ec.generate_key! assert_equal true, ec.private? + assert_nothing_raised { ec.to_der } end if !openssl?(3, 0, 0) def test_marshal @@ -199,6 +201,29 @@ class OpenSSL::TestEC < OpenSSL::PKeyTestCase assert_equal pem, p256.export end + def test_ECPrivateKey_with_parameters + p256 = Fixtures.pkey("p256") + + # The format used by "openssl ecparam -name prime256v1 -genkey -outform PEM" + # + # "EC PARAMETERS" block should be ignored if it is followed by an + # "EC PRIVATE KEY" block + in_pem = <<~EOF + -----BEGIN EC PARAMETERS----- + BggqhkjOPQMBBw== + -----END EC PARAMETERS----- + -----BEGIN EC PRIVATE KEY----- + MHcCAQEEIID49FDqcf1O1eO8saTgG70UbXQw9Fqwseliit2aWhH1oAoGCCqGSM49 + AwEHoUQDQgAEFglk2c+oVUIKQ64eZG9bhLNPWB7lSZ/ArK41eGy5wAzU/0G51Xtt + CeBUl+MahZtn9fO1JKdF4qJmS39dXnpENg== + -----END EC PRIVATE KEY----- + EOF + + key = OpenSSL::PKey::EC.new(in_pem) + assert_same_ec p256, key + assert_equal p256.to_der, key.to_der + end + def test_ECPrivateKey_encrypted p256 = Fixtures.pkey("p256") # key = abcdef diff --git a/test/openssl/test_pkey_rsa.rb b/test/openssl/test_pkey_rsa.rb index 4bb39ed..fa84b76 100644 --- a/test/openssl/test_pkey_rsa.rb +++ b/test/openssl/test_pkey_rsa.rb @@ -108,6 +108,11 @@ class OpenSSL::TestPKeyRSA < OpenSSL::PKeyTestCase salt_length: 20, mgf1_hash: "SHA1") # Defaults to PKCS #1 v1.5 padding => verification failure assert_equal false, key.verify("SHA256", sig_pss, data) + + # option type check + assert_raise_with_message(TypeError, /expected Hash/) { + key.sign("SHA256", data, ["x"]) + } end def test_sign_verify_raw diff --git a/test/openssl/test_ssl.rb b/test/openssl/test_ssl.rb index a7607da..39964bf 100644 --- a/test/openssl/test_ssl.rb +++ b/test/openssl/test_ssl.rb @@ -676,10 +676,16 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase # buzz.example.net, respectively). ... assert_equal(true, OpenSSL::SSL.verify_certificate_identity( create_cert_with_san('DNS:baz*.example.com'), 'baz1.example.com')) + + # LibreSSL 3.5.0+ doesn't support other wildcard certificates + # (it isn't required to, as RFC states MAY, not MUST) + return if libressl?(3, 5, 0) + assert_equal(true, OpenSSL::SSL.verify_certificate_identity( create_cert_with_san('DNS:*baz.example.com'), 'foobaz.example.com')) assert_equal(true, OpenSSL::SSL.verify_certificate_identity( create_cert_with_san('DNS:b*z.example.com'), 'buzz.example.com')) + # Section 6.4.3 of RFC6125 states that client should NOT match identifier # where wildcard is other than left-most label. #
signature.asc
Description: PGP signature