From 6de85412863a80ba80f534665b4491581ffd9237 Mon Sep 17 00:00:00 2001 From: Pavel Valena Date: Wed, 12 May 2021 16:10:28 +0200 Subject: [PATCH] Support Openssl 3.0. https://github.com/ruby/openssl/pull/399 With additional commit before openssl 3.0 compatibility patch, to be able to apply it. https://github.com/ruby/openssl/commit/d963d4e276658d110bcb796722d76efa7fb68efa Resolves: rhbz#1952925 --- ruby-3.0-support-openssl-3.0-pr399.patch | 2110 ++++++++++++++++++++++ ruby.spec | 9 + 2 files changed, 2119 insertions(+) create mode 100644 ruby-3.0-support-openssl-3.0-pr399.patch diff --git a/ruby-3.0-support-openssl-3.0-pr399.patch b/ruby-3.0-support-openssl-3.0-pr399.patch new file mode 100644 index 0000000..44061af --- /dev/null +++ b/ruby-3.0-support-openssl-3.0-pr399.patch @@ -0,0 +1,2110 @@ +From d963d4e276658d110bcb796722d76efa7fb68efa Mon Sep 17 00:00:00 2001 +From: Kazuki Yamaguchi +Date: Tue, 13 Jun 2017 23:39:41 +0900 +Subject: [PATCH] pkey: refactor DER/PEM-encoded string parsing code + +Export the flow used by OpenSSL::PKey.read and let the subclasses call +it before attempting other formats. +--- + + +diff --git a/ext/openssl/ossl_pkey.c b/ext/openssl/ossl_pkey.c +index 7ba7b37..3982b9c 100644 +--- a/ext/openssl/ossl_pkey.c ++++ b/ext/openssl/ossl_pkey.c +@@ -140,6 +140,35 @@ ossl_pkey_new(EVP_PKEY *pkey) + return obj; + } + ++EVP_PKEY * ++ossl_pkey_read_generic(BIO *bio, VALUE pass) ++{ ++ void *ppass = (void *)pass; ++ EVP_PKEY *pkey; ++ ++ if ((pkey = d2i_PrivateKey_bio(bio, NULL))) ++ goto out; ++ OSSL_BIO_reset(bio); ++ if ((pkey = d2i_PKCS8PrivateKey_bio(bio, NULL, ossl_pem_passwd_cb, ppass))) ++ goto out; ++ OSSL_BIO_reset(bio); ++ if ((pkey = d2i_PUBKEY_bio(bio, NULL))) ++ goto out; ++ OSSL_BIO_reset(bio); ++ /* PEM_read_bio_PrivateKey() also parses PKCS #8 formats */ ++ if ((pkey = PEM_read_bio_PrivateKey(bio, NULL, ossl_pem_passwd_cb, ppass))) ++ goto out; ++ OSSL_BIO_reset(bio); ++ if ((pkey = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL))) ++ goto out; ++ OSSL_BIO_reset(bio); ++ if ((pkey = PEM_read_bio_Parameters(bio, NULL))) ++ goto out; ++ ++ out: ++ return pkey; ++} ++ + /* + * call-seq: + * OpenSSL::PKey.read(string [, pwd ]) -> PKey +@@ -164,29 +193,14 @@ ossl_pkey_new_from_data(int argc, VALUE *argv, VALUE self) + VALUE data, pass; + + rb_scan_args(argc, argv, "11", &data, &pass); +- pass = ossl_pem_passwd_value(pass); + + bio = ossl_obj2bio(&data); +- if ((pkey = d2i_PrivateKey_bio(bio, NULL))) +- goto ok; +- OSSL_BIO_reset(bio); +- if ((pkey = d2i_PKCS8PrivateKey_bio(bio, NULL, ossl_pem_passwd_cb, (void *)pass))) +- goto ok; +- OSSL_BIO_reset(bio); +- if ((pkey = d2i_PUBKEY_bio(bio, NULL))) +- goto ok; +- OSSL_BIO_reset(bio); +- /* PEM_read_bio_PrivateKey() also parses PKCS #8 formats */ +- if ((pkey = PEM_read_bio_PrivateKey(bio, NULL, ossl_pem_passwd_cb, (void *)pass))) +- goto ok; +- OSSL_BIO_reset(bio); +- if ((pkey = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL))) +- goto ok; + ++ pkey = ossl_pkey_read_generic(bio, ossl_pem_passwd_value(pass)); + BIO_free(bio); +- ossl_raise(ePKeyError, "Could not parse PKey"); ++ if (!pkey) ++ ossl_raise(ePKeyError, "Could not parse PKey"); + +-ok: + BIO_free(bio); + return ossl_pkey_new(pkey); + } +diff --git a/ext/openssl/ossl_pkey.h b/ext/openssl/ossl_pkey.h +index e363a261..895927e3 100644 +--- a/ext/openssl/ossl_pkey.h ++++ b/ext/openssl/ossl_pkey.h +@@ -45,6 +45,7 @@ void ossl_generate_cb_stop(void *ptr); + + VALUE ossl_pkey_new(EVP_PKEY *); + void ossl_pkey_check_public_key(const EVP_PKEY *); ++EVP_PKEY *ossl_pkey_read_generic(BIO *, VALUE); + EVP_PKEY *GetPKeyPtr(VALUE); + EVP_PKEY *DupPKeyPtr(VALUE); + EVP_PKEY *GetPrivPKeyPtr(VALUE); +diff --git a/ext/openssl/ossl_pkey_dsa.c b/ext/openssl/ossl_pkey_dsa.c +index 431c20e..faa3dd6 100644 +--- a/ext/openssl/ossl_pkey_dsa.c ++++ b/ext/openssl/ossl_pkey_dsa.c +@@ -213,24 +213,24 @@ static VALUE + ossl_dsa_initialize(int argc, VALUE *argv, VALUE self) + { + EVP_PKEY *pkey; +- DSA *dsa; ++ DSA *dsa = NULL; + BIO *in; + VALUE arg, pass; + + GetPKey(self, pkey); +- if(rb_scan_args(argc, argv, "02", &arg, &pass) == 0) { ++ rb_scan_args(argc, argv, "02", &arg, &pass); ++ if (argc == 0) { + dsa = DSA_new(); ++ if (!dsa) ++ ossl_raise(eDSAError, "DSA_new"); + } +- else if (RB_INTEGER_TYPE_P(arg)) { +- if (!(dsa = dsa_generate(NUM2INT(arg)))) { +- ossl_raise(eDSAError, NULL); +- } ++ else if (argc == 1 && RB_INTEGER_TYPE_P(arg)) { ++ dsa = dsa_generate(NUM2INT(arg)); + } + else { + pass = ossl_pem_passwd_value(pass); + arg = ossl_to_der_if_possible(arg); + in = ossl_obj2bio(&arg); +- dsa = PEM_read_bio_DSAPrivateKey(in, NULL, ossl_pem_passwd_cb, (void *)pass); + if (!dsa) { + OSSL_BIO_reset(in); + dsa = PEM_read_bio_DSA_PUBKEY(in, NULL, NULL, NULL); +diff --git a/ext/openssl/ossl_pkey_ec.c b/ext/openssl/ossl_pkey_ec.c +index aec9d1e6..ca8f5c6e 100644 +--- a/ext/openssl/ossl_pkey_ec.c ++++ b/ext/openssl/ossl_pkey_ec.c +@@ -202,24 +202,17 @@ static VALUE ossl_ec_key_initialize(int argc, VALUE *argv, VALUE self) + } else if (rb_obj_is_kind_of(arg, cEC_GROUP)) { + ec = ec_key_new_from_group(arg); + } else { +- BIO *in; +- +- pass = ossl_pem_passwd_value(pass); +- in = ossl_obj2bio(&arg); +- +- ec = PEM_read_bio_ECPrivateKey(in, NULL, ossl_pem_passwd_cb, (void *)pass); +- if (!ec) { +- OSSL_BIO_reset(in); +- ec = PEM_read_bio_EC_PUBKEY(in, NULL, ossl_pem_passwd_cb, (void *)pass); +- } +- if (!ec) { +- OSSL_BIO_reset(in); +- ec = d2i_ECPrivateKey_bio(in, NULL); +- } +- if (!ec) { +- OSSL_BIO_reset(in); +- ec = d2i_EC_PUBKEY_bio(in, NULL); +- } ++ BIO *in = ossl_obj2bio(&arg); ++ EVP_PKEY *tmp; ++ pass = ossl_pem_passwd_value(pass); ++ tmp = ossl_pkey_read_generic(in, pass); ++ if (tmp) { ++ if (EVP_PKEY_base_id(tmp) != EVP_PKEY_EC) ++ rb_raise(eECError, "incorrect pkey type: %s", ++ OBJ_nid2sn(EVP_PKEY_base_id(tmp))); ++ ec = EVP_PKEY_get1_EC_KEY(tmp); ++ EVP_PKEY_free(tmp); ++ } + BIO_free(in); + + if (!ec) { +diff --git a/ext/openssl/ossl_pkey_rsa.c b/ext/openssl/ossl_pkey_rsa.c +index 6a57238..41844e5 100644 +--- a/ext/openssl/ossl_pkey_rsa.c ++++ b/ext/openssl/ossl_pkey_rsa.c +@@ -226,7 +226,8 @@ ossl_rsa_initialize(int argc, VALUE *argv, VALUE self) + VALUE arg, pass; + + GetPKey(self, pkey); +- if(rb_scan_args(argc, argv, "02", &arg, &pass) == 0) { ++ rb_scan_args(argc, argv, "02", &arg, &pass); ++ if (argc == 0) { + rsa = RSA_new(); + } + else if (RB_INTEGER_TYPE_P(arg)) { +@@ -265,6 +266,7 @@ ossl_rsa_initialize(int argc, VALUE *argv, VALUE self) + } + if (!EVP_PKEY_assign_RSA(pkey, rsa)) { + RSA_free(rsa); ++ ossl_clear_error(); + ossl_raise(eRSAError, NULL); + } + +From c2bb3f5411441b0dbe3085e1825d8479baef6ee4 Mon Sep 17 00:00:00 2001 +From: Kazuki Yamaguchi +Date: Sat, 22 Feb 2020 05:37:01 +0900 +Subject: [PATCH 01/21] ts: use TS_VERIFY_CTX_set_certs instead of + TS_VERIFY_CTS_set_certs + +OpenSSL 3.0 fixed the typo in the function name and replaced the +current 'CTS' version with a macro. +--- + ext/openssl/extconf.rb | 5 ++++- + ext/openssl/openssl_missing.h | 5 +++++ + ext/openssl/ossl_ts.c | 2 +- + 3 files changed, 10 insertions(+), 2 deletions(-) + +diff --git a/ext/openssl/extconf.rb b/ext/openssl/extconf.rb +index 5cb28f30..ea384fe9 100644 +--- a/ext/openssl/extconf.rb ++++ b/ext/openssl/extconf.rb +@@ -169,13 +169,16 @@ def find_openssl_library + have_func("TS_STATUS_INFO_get0_status") + have_func("TS_STATUS_INFO_get0_text") + have_func("TS_STATUS_INFO_get0_failure_info") +-have_func("TS_VERIFY_CTS_set_certs") ++have_func("TS_VERIFY_CTS_set_certs(NULL, NULL)", "openssl/ts.h") # became a macro in 3.0.0 + have_func("TS_VERIFY_CTX_set_store") + have_func("TS_VERIFY_CTX_add_flags") + have_func("TS_RESP_CTX_set_time_cb") + have_func("EVP_PBE_scrypt") + have_func("SSL_CTX_set_post_handshake_auth") + ++# added in 3.0.0 ++have_func("TS_VERIFY_CTX_set_certs(NULL, NULL)", "openssl/ts.h") ++ + Logging::message "=== Checking done. ===\n" + + create_header +diff --git a/ext/openssl/openssl_missing.h b/ext/openssl/openssl_missing.h +index 4d9b8801..1b1a54a8 100644 +--- a/ext/openssl/openssl_missing.h ++++ b/ext/openssl/openssl_missing.h +@@ -254,4 +254,9 @@ IMPL_PKEY_GETTER(EC_KEY, ec) + } while (0) + #endif + ++/* added in 3.0.0 */ ++#if !defined(HAVE_TS_VERIFY_CTX_SET_CERTS) ++# define TS_VERIFY_CTX_set_certs(ctx, crts) TS_VERIFY_CTS_set_certs(ctx, crts) ++#endif ++ + #endif /* _OSSL_OPENSSL_MISSING_H_ */ +diff --git a/ext/openssl/ossl_ts.c b/ext/openssl/ossl_ts.c +index 4654babf..9d91710a 100644 +--- a/ext/openssl/ossl_ts.c ++++ b/ext/openssl/ossl_ts.c +@@ -816,7 +816,7 @@ ossl_ts_resp_verify(int argc, VALUE *argv, VALUE self) + X509_up_ref(cert); + } + +- TS_VERIFY_CTS_set_certs(ctx, x509inter); ++ TS_VERIFY_CTX_set_certs(ctx, x509inter); + TS_VERIFY_CTX_add_flags(ctx, TS_VFY_SIGNATURE); + TS_VERIFY_CTX_set_store(ctx, x509st); + + +From 5780e43ceda843c38dc1493a81d8ef8615b2a42b Mon Sep 17 00:00:00 2001 +From: Kazuki Yamaguchi +Date: Sat, 22 Feb 2020 05:47:58 +0900 +Subject: [PATCH 02/21] ssl: use SSL_CTX_load_verify_{file,dir}() if available + +SSL_CTX_load_verify_locations() is deprecated in OpenSSL 3.0 and +replaced with those two separate functions. Use them if they exist. +--- + ext/openssl/extconf.rb | 1 + + ext/openssl/ossl_ssl.c | 7 +++++++ + 2 files changed, 8 insertions(+) + +diff --git a/ext/openssl/extconf.rb b/ext/openssl/extconf.rb +index ea384fe9..4b5ffd67 100644 +--- a/ext/openssl/extconf.rb ++++ b/ext/openssl/extconf.rb +@@ -178,6 +178,7 @@ def find_openssl_library + + # added in 3.0.0 + have_func("TS_VERIFY_CTX_set_certs(NULL, NULL)", "openssl/ts.h") ++have_func("SSL_CTX_load_verify_file") + + Logging::message "=== Checking done. ===\n" + +diff --git a/ext/openssl/ossl_ssl.c b/ext/openssl/ossl_ssl.c +index 76db821e..c80c939e 100644 +--- a/ext/openssl/ossl_ssl.c ++++ b/ext/openssl/ossl_ssl.c +@@ -886,10 +886,17 @@ ossl_sslctx_setup(VALUE self) + ca_file = NIL_P(val) ? NULL : StringValueCStr(val); + val = rb_attr_get(self, id_i_ca_path); + ca_path = NIL_P(val) ? NULL : StringValueCStr(val); ++#if defined(HAVE_SSL_CTX_LOAD_VERIFY_FILE) ++ if (ca_file && !SSL_CTX_load_verify_file(ctx, ca_file)) ++ ossl_raise(eSSLError, "SSL_CTX_load_verify_file"); ++ if (ca_path && !SSL_CTX_load_verify_dir(ctx, ca_path)) ++ ossl_raise(eSSLError, "SSL_CTX_load_verify_dir"); ++#else + if(ca_file || ca_path){ + if (!SSL_CTX_load_verify_locations(ctx, ca_file, ca_path)) + rb_warning("can't set verify locations"); + } ++#endif + + val = rb_attr_get(self, id_i_verify_mode); + verify_mode = NIL_P(val) ? SSL_VERIFY_NONE : NUM2INT(val); + +From c26272113074bfe3ebbc698741974fce86b1c25a Mon Sep 17 00:00:00 2001 +From: Kazuki Yamaguchi +Date: Sat, 22 Feb 2020 06:37:00 +0900 +Subject: [PATCH 03/21] bn: use BN_check_prime() in + OpenSSL::BN#prime{,_fasttest}? + +BN_is_prime_ex() and BN_is_prime_fasttest_ex() are deprecated in OpenSSL +3.0. Instead, BN_check_prime() is added. This is equivalent to +BN_is_prime_fasttest_ex(bn, 0, bn_ctx, 1, cb), which is what +OpenSSL::BN#prime_fasttest? has called. + +Let's make both OpenSSL::BN#prime? and #prime_fasttest? use +BN_check_prime() if available. Note that this implies that the +parameters of those two methods are now ignored, which could be used to +tune them to give up the test earlier. +--- + ext/openssl/extconf.rb | 1 + + ext/openssl/ossl_bn.c | 71 +++++++++++++----------------------------- + 2 files changed, 23 insertions(+), 49 deletions(-) + +diff --git a/ext/openssl/extconf.rb b/ext/openssl/extconf.rb +index 4b5ffd67..9fa092f5 100644 +--- a/ext/openssl/extconf.rb ++++ b/ext/openssl/extconf.rb +@@ -179,6 +179,7 @@ def find_openssl_library + # added in 3.0.0 + have_func("TS_VERIFY_CTX_set_certs(NULL, NULL)", "openssl/ts.h") + have_func("SSL_CTX_load_verify_file") ++have_func("BN_check_prime") + + Logging::message "=== Checking done. ===\n" + +diff --git a/ext/openssl/ossl_bn.c b/ext/openssl/ossl_bn.c +index 02530789..e0eef4cd 100644 +--- a/ext/openssl/ossl_bn.c ++++ b/ext/openssl/ossl_bn.c +@@ -1058,34 +1058,29 @@ 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 _checks_ is not specified, a number of iterations is used +- * that yields a false positive rate of at most 2^-80 for random input. ++ * Performs Miller-Rabin primality test for _bn_. + * +- * === Parameters +- * * _checks_ - integer ++ * As of Ruby/OpenSSL 2.3.0, the argument _checks_ is ignored. + */ + static VALUE + ossl_bn_is_prime(int argc, VALUE *argv, VALUE self) + { + BIGNUM *bn; +- VALUE vchecks; +- int checks = BN_prime_checks; ++ int ret; + +- if (rb_scan_args(argc, argv, "01", &vchecks) == 1) { +- checks = NUM2INT(vchecks); +- } ++ rb_check_arity(argc, 0, 1); + GetBN(self, bn); +- switch (BN_is_prime_ex(bn, checks, ossl_bn_ctx, NULL)) { +- case 1: +- return Qtrue; +- case 0: +- return Qfalse; +- default: +- ossl_raise(eBNError, NULL); +- } +- /* not reachable */ +- return Qnil; ++ ++#if defined(HAVE_BN_CHECK_PRIME) ++ ret = BN_check_prime(bn, ossl_bn_ctx, NULL); ++ if (ret < 0) ++ ossl_raise(eBNError, "BN_check_prime"); ++#else ++ ret = BN_is_prime_fasttest_ex(bn, BN_prime_checks, ossl_bn_ctx, 1, NULL); ++ if (ret < 0) ++ ossl_raise(eBNError, "BN_is_prime_fasttest_ex"); ++#endif ++ return ret ? Qtrue : Qfalse; + } + + /* +@@ -1094,40 +1089,18 @@ ossl_bn_is_prime(int argc, VALUE *argv, VALUE self) + * bn.prime_fasttest?(checks) => true | false + * bn.prime_fasttest?(checks, trial_div) => true | false + * +- * Performs a Miller-Rabin primality test. This is same as #prime? except this +- * first attempts trial divisions with some small primes. ++ * Performs Miller-Rabin primality test for _bn_. This is an alias of #prime?. + * +- * === Parameters +- * * _checks_ - integer +- * * _trial_div_ - boolean ++ * This method is deprecated. Use #prime? instead. ++ * ++ * As of Ruby/OpenSSL 2.3.0, the arguments _checks_ and _trial\_div_ are ++ * ignored. + */ + static VALUE + ossl_bn_is_prime_fasttest(int argc, VALUE *argv, VALUE self) + { +- BIGNUM *bn; +- VALUE vchecks, vtrivdiv; +- int checks = BN_prime_checks, do_trial_division = 1; +- +- rb_scan_args(argc, argv, "02", &vchecks, &vtrivdiv); +- +- if (!NIL_P(vchecks)) { +- checks = NUM2INT(vchecks); +- } +- GetBN(self, bn); +- /* handle true/false */ +- if (vtrivdiv == Qfalse) { +- do_trial_division = 0; +- } +- switch (BN_is_prime_fasttest_ex(bn, checks, ossl_bn_ctx, do_trial_division, NULL)) { +- case 1: +- return Qtrue; +- case 0: +- return Qfalse; +- default: +- ossl_raise(eBNError, NULL); +- } +- /* not reachable */ +- return Qnil; ++ rb_check_arity(argc, 0, 2); ++ return ossl_bn_is_prime(0, argv, self); + } + + /* + +From 1fdea13743e5ee70befdfc79f22473b88ffe2eef Mon Sep 17 00:00:00 2001 +From: Kazuki Yamaguchi +Date: Sat, 22 Feb 2020 18:58:29 +0900 +Subject: [PATCH 04/21] ossl.c: use ERR_get_error_all() if available + +OpenSSL 3.0 deprecated ERR_get_error_line_data() in favor of +ERR_get_error_all(), as part of the error queue structure changes. +--- + ext/openssl/extconf.rb | 1 + + ext/openssl/ossl.c | 40 +++++++++++++++++++++------------------- + 2 files changed, 22 insertions(+), 19 deletions(-) + +diff --git a/ext/openssl/extconf.rb b/ext/openssl/extconf.rb +index 9fa092f5..14e599ca 100644 +--- a/ext/openssl/extconf.rb ++++ b/ext/openssl/extconf.rb +@@ -180,6 +180,7 @@ def find_openssl_library + have_func("TS_VERIFY_CTX_set_certs(NULL, NULL)", "openssl/ts.h") + have_func("SSL_CTX_load_verify_file") + have_func("BN_check_prime") ++have_func("ERR_get_error_all") + + Logging::message "=== Checking done. ===\n" + +diff --git a/ext/openssl/ossl.c b/ext/openssl/ossl.c +index 358b3b29..a040deae 100644 +--- a/ext/openssl/ossl.c ++++ b/ext/openssl/ossl.c +@@ -304,27 +304,29 @@ void + ossl_clear_error(void) + { + if (dOSSL == Qtrue) { +- unsigned long e; +- const char *file, *data, *errstr; +- int line, flags; +- +- while ((e = ERR_get_error_line_data(&file, &line, &data, &flags))) { +- errstr = ERR_error_string(e, NULL); +- if (!errstr) +- errstr = "(null)"; +- +- if (flags & ERR_TXT_STRING) { +- if (!data) +- data = "(null)"; +- rb_warn("error on stack: %s (%s)", errstr, data); +- } +- else { +- rb_warn("error on stack: %s", errstr); +- } +- } ++ unsigned long e; ++ const char *file, *data; ++ int line, flags; ++ ++#if defined(HAVE_ERR_GET_ERROR_ALL) ++ const char *func; ++ while ((e = ERR_get_error_all(&file, &line, &func, &data, &flags))) { ++#else ++ while ((e = ERR_get_error_line_data(&file, &line, &data, &flags))) { ++ const char *func = ERR_func_error_string(e); ++#endif ++ const char *lib = ERR_lib_error_string(e), ++ *reason = ERR_reason_error_string(e); ++ char append[256] = ""; ++ ++ if (flags & ERR_TXT_STRING && data && strlen(data)) ++ snprintf(append, sizeof(append), " (%s)", data); ++ rb_warn("error on stack: error:%08lX:%s:%s:%s%s", e, lib ? lib : "", ++ func ? func : "", reason ? reason : "", append); ++ } + } + else { +- ERR_clear_error(); ++ ERR_clear_error(); + } + } + + +From ce0bf33dd0c5a2ba3d445ccf00175db91d78b5a7 Mon Sep 17 00:00:00 2001 +From: Kazuki Yamaguchi +Date: Sun, 17 May 2020 18:25:38 +0900 +Subject: [PATCH 05/21] pkey: implement #to_text using EVP API + +Use EVP_PKEY_print_private() instead of the low level *_print() +functions. Those low level functions are deprecated in OpenSSL 3.0. + +Note that it falls back to EVP_PKEY_print_public() and +EVP_PKEY_print_params() as necessary. This is required for EVP_PKEY_DH +type - _private() fails if the private component is not set. + +Since the new API works in the same way for all key types, we now +implement #to_text in the base class OpenSSL::PKey::PKey rather than in +each subclass. +--- + +diff --git a/ext/openssl/ossl_pkey.c b/ext/openssl/ossl_pkey.c +index 0540cd2..e02c84b 100644 +--- a/ext/openssl/ossl_pkey.c ++++ b/ext/openssl/ossl_pkey.c +@@ -349,6 +349,42 @@ ossl_pkey_inspect(VALUE self) + OBJ_nid2sn(nid)); + } + ++/* ++ * call-seq: ++ * pkey.to_text -> string ++ * ++ * THIS METHOD IS INSECURE, PRIVATE INFORMATION CAN LEAK OUT!!! ++ * ++ * Dumps all private, public, and parameter components of the key to a String ++ * in a human readable format. ++ */ ++static VALUE ++ossl_pkey_to_text(VALUE self) ++{ ++ EVP_PKEY *pkey; ++ BIO *bio; ++ ++ GetPKey(self, pkey); ++ if (!(bio = BIO_new(BIO_s_mem()))) ++ ossl_raise(ePKeyError, "BIO_new"); ++ ++ if (EVP_PKEY_print_private(bio, pkey, 0, NULL) == 1) ++ goto out; ++ OSSL_BIO_reset(bio); ++ if (EVP_PKEY_print_public(bio, pkey, 0, NULL) == 1) ++ goto out; ++ OSSL_BIO_reset(bio); ++ if (EVP_PKEY_print_params(bio, pkey, 0, NULL) == 1) ++ goto out; ++ ++ BIO_free(bio); ++ ossl_raise(ePKeyError, "EVP_PKEY_print_params"); ++ ++ out: ++ return ossl_membio2str(bio); ++} ++ ++ + static VALUE + do_pkcs8_export(int argc, VALUE *argv, VALUE self, int to_der) + { +diff --git a/ext/openssl/ossl_pkey_dh.c b/ext/openssl/ossl_pkey_dh.c +index 6b477b07..acd3bf47 100644 +--- a/ext/openssl/ossl_pkey_dh.c ++++ b/ext/openssl/ossl_pkey_dh.c +@@ -403,34 +403,6 @@ ossl_dh_get_params(VALUE self) + return hash; + } + +-/* +- * call-seq: +- * dh.to_text -> aString +- * +- * Prints all parameters of key to buffer +- * INSECURE: PRIVATE INFORMATIONS CAN LEAK OUT!!! +- * Don't use :-)) (I's up to you) +- */ +-static VALUE +-ossl_dh_to_text(VALUE self) +-{ +- DH *dh; +- BIO *out; +- VALUE str; +- +- GetDH(self, dh); +- if (!(out = BIO_new(BIO_s_mem()))) { +- ossl_raise(eDHError, NULL); +- } +- if (!DHparams_print(out, dh)) { +- BIO_free(out); +- ossl_raise(eDHError, NULL); +- } +- str = ossl_membio2str(out); +- +- return str; +-} +- + /* + * call-seq: + * dh.public_key -> aDH +@@ -621,7 +593,6 @@ Init_ossl_dh(void) + 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); + rb_define_method(cDH, "export", ossl_dh_export, 0); + rb_define_alias(cDH, "to_pem", "export"); + rb_define_alias(cDH, "to_s", "export"); +diff --git a/ext/openssl/ossl_pkey_dsa.c b/ext/openssl/ossl_pkey_dsa.c +index c2b68c32..640a243d 100644 +--- a/ext/openssl/ossl_pkey_dsa.c ++++ b/ext/openssl/ossl_pkey_dsa.c +@@ -433,34 +433,6 @@ ossl_dsa_get_params(VALUE self) + return hash; + } + +-/* +- * call-seq: +- * dsa.to_text -> aString +- * +- * Prints all parameters of key to buffer +- * INSECURE: PRIVATE INFORMATIONS CAN LEAK OUT!!! +- * Don't use :-)) (I's up to you) +- */ +-static VALUE +-ossl_dsa_to_text(VALUE self) +-{ +- DSA *dsa; +- BIO *out; +- VALUE str; +- +- GetDSA(self, dsa); +- if (!(out = BIO_new(BIO_s_mem()))) { +- ossl_raise(eDSAError, NULL); +- } +- if (!DSA_print(out, dsa, 0)) { /* offset = 0 */ +- BIO_free(out); +- ossl_raise(eDSAError, NULL); +- } +- str = ossl_membio2str(out); +- +- return str; +-} +- + /* + * call-seq: + * dsa.public_key -> aDSA +@@ -636,7 +608,6 @@ Init_ossl_dsa(void) + + rb_define_method(cDSA, "public?", ossl_dsa_is_public, 0); + rb_define_method(cDSA, "private?", ossl_dsa_is_private, 0); +- rb_define_method(cDSA, "to_text", ossl_dsa_to_text, 0); + rb_define_method(cDSA, "export", ossl_dsa_export, -1); + rb_define_alias(cDSA, "to_pem", "export"); + rb_define_alias(cDSA, "to_s", "export"); +diff --git a/ext/openssl/ossl_pkey_ec.c b/ext/openssl/ossl_pkey_ec.c +index 511e728..aa59c68 100644 +--- a/ext/openssl/ossl_pkey_ec.c ++++ b/ext/openssl/ossl_pkey_ec.c +@@ -506,31 +506,6 @@ static VALUE ossl_ec_key_to_der(VALUE self) + return ossl_ec_key_to_string(self, Qnil, Qnil, EXPORT_DER); + } + +-/* +- * call-seq: +- * key.to_text => String +- * +- * See the OpenSSL documentation for EC_KEY_print() +- */ +-static VALUE ossl_ec_key_to_text(VALUE self) +-{ +- EC_KEY *ec; +- BIO *out; +- VALUE str; +- +- GetEC(self, ec); +- if (!(out = BIO_new(BIO_s_mem()))) { +- ossl_raise(eECError, "BIO_new(BIO_s_mem())"); +- } +- if (!EC_KEY_print(out, ec, 0)) { +- BIO_free(out); +- ossl_raise(eECError, "EC_KEY_print"); +- } +- str = ossl_membio2str(out); +- +- return str; +-} +- + /* + * call-seq: + * key.generate_key! => self +diff --git a/ext/openssl/ossl_pkey_ec.c b/ext/openssl/ossl_pkey_ec.c +index aa59c68..1689200 100644 +--- a/ext/openssl/ossl_pkey_ec.c ++++ b/ext/openssl/ossl_pkey_ec.c +@@ -1728,8 +1728,6 @@ void Init_ossl_ec(void) + rb_define_method(cEC, "export", ossl_ec_key_export, -1); + rb_define_alias(cEC, "to_pem", "export"); + rb_define_method(cEC, "to_der", ossl_ec_key_to_der, 0); +- rb_define_method(cEC, "to_text", ossl_ec_key_to_text, 0); +- + + rb_define_alloc_func(cEC_GROUP, ossl_ec_group_alloc); + rb_define_method(cEC_GROUP, "initialize", ossl_ec_group_initialize, -1); +diff --git a/ext/openssl/ossl_pkey_rsa.c b/ext/openssl/ossl_pkey_rsa.c +index 6d337fe7..a522b819 100644 +--- a/ext/openssl/ossl_pkey_rsa.c ++++ b/ext/openssl/ossl_pkey_rsa.c +@@ -772,36 +772,6 @@ ossl_rsa_get_params(VALUE self) + return hash; + } + +-/* +- * call-seq: +- * rsa.to_text => String +- * +- * THIS METHOD IS INSECURE, PRIVATE INFORMATION CAN LEAK OUT!!! +- * +- * Dumps all parameters of a keypair to a String +- * +- * Don't use :-)) (It's up to you) +- */ +-static VALUE +-ossl_rsa_to_text(VALUE self) +-{ +- RSA *rsa; +- BIO *out; +- VALUE str; +- +- GetRSA(self, rsa); +- if (!(out = BIO_new(BIO_s_mem()))) { +- ossl_raise(eRSAError, NULL); +- } +- if (!RSA_print(out, rsa, 0)) { /* offset = 0 */ +- BIO_free(out); +- ossl_raise(eRSAError, NULL); +- } +- str = ossl_membio2str(out); +- +- return str; +-} +- + /* + * call-seq: + * rsa.public_key -> RSA +@@ -921,7 +891,6 @@ Init_ossl_rsa(void) + + rb_define_method(cRSA, "public?", ossl_rsa_is_public, 0); + rb_define_method(cRSA, "private?", ossl_rsa_is_private, 0); +- rb_define_method(cRSA, "to_text", ossl_rsa_to_text, 0); + rb_define_method(cRSA, "export", ossl_rsa_export, -1); + rb_define_alias(cRSA, "to_pem", "export"); + rb_define_alias(cRSA, "to_s", "export"); + +From b2e3ddab1c5dcda2003bfa9c06c424ac74e3e198 Mon Sep 17 00:00:00 2001 +From: Kazuki Yamaguchi +Date: Sun, 17 May 2020 21:29:48 +0900 +Subject: [PATCH 06/21] [WIP] pkey: try to parse algorithm-specific formats + first + +FIXME: NON-RSA NEEDS THIS TOO + +RSAPublicKey and DHParameters share the same structure: two INTEGERs in +a SEQUENCE. When parsing a DER- encoded data they are indistinguishable. + +With OpenSSL 3.0, OpenSSL::PKey.read will parse DER-encoded +DHParameters. However, OpenSSL::PKey::RSA.new naturally wants the data +to be parsed as RSAPublicKey instead when such a structure is given. + +So, try PEM_read_bio_RSAPublicKey() and d2i_RSAPublicKey_bio() before +falling back to ossl_pkey_read_generic(). +--- + ext/openssl/ossl_pkey_dsa.c | 27 +++++++++++++-------------- + ext/openssl/ossl_pkey_rsa.c | 32 ++++++++++++++++---------------- + +diff --git a/ext/openssl/ossl_pkey_dh.c b/ext/openssl/ossl_pkey_dh.c +index 29df5b3..60ded1c 100644 +--- a/ext/openssl/ossl_pkey_dh.c ++++ b/ext/openssl/ossl_pkey_dh.c +@@ -202,7 +202,7 @@ ossl_dh_s_generate(int argc, VALUE *argv, VALUE klass) + static VALUE + ossl_dh_initialize(int argc, VALUE *argv, VALUE self) + { +- EVP_PKEY *pkey; ++ EVP_PKEY *pkey, *tmp; + DH *dh; + int g = 2; + BIO *in; +@@ -221,14 +221,22 @@ ossl_dh_initialize(int argc, VALUE *argv, VALUE self) + } + } + else { +- arg = ossl_to_der_if_possible(arg); +- in = ossl_obj2bio(&arg); +- dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL); +- if (!dh){ +- OSSL_BIO_reset(in); +- dh = d2i_DHparams_bio(in, NULL); +- } +- BIO_free(in); ++ arg = ossl_to_der_if_possible(arg); ++ in = ossl_obj2bio(&arg); ++ ++ dh = d2i_DHparams_bio(in, NULL); ++ if (!dh) { ++ OSSL_BIO_reset(in); ++ tmp = ossl_pkey_read_generic(in, Qnil); ++ if (tmp) { ++ if (EVP_PKEY_base_id(tmp) != EVP_PKEY_DH) ++ rb_raise(eDHError, "incorrect pkey type: %s", ++ OBJ_nid2sn(EVP_PKEY_base_id(tmp))); ++ dh = EVP_PKEY_get1_DH(tmp); ++ EVP_PKEY_free(tmp); ++ } ++ } ++ BIO_free(in); + if (!dh) { + ossl_raise(eDHError, NULL); + } +diff --git a/ext/openssl/ossl_pkey_dsa.c b/ext/openssl/ossl_pkey_dsa.c +index e5a1f04..da58717 100644 +--- a/ext/openssl/ossl_pkey_dsa.c ++++ b/ext/openssl/ossl_pkey_dsa.c +@@ -212,7 +212,7 @@ ossl_dsa_s_generate(VALUE klass, VALUE size) + static VALUE + ossl_dsa_initialize(int argc, VALUE *argv, VALUE self) + { +- EVP_PKEY *pkey; ++ EVP_PKEY *pkey, *tmp; + DSA *dsa = NULL; + BIO *in; + VALUE arg, pass; +diff --git a/ext/openssl/ossl_pkey_dsa.c b/ext/openssl/ossl_pkey_dsa.c +index b19441c..804b652 100644 +--- a/ext/openssl/ossl_pkey_dsa.c ++++ b/ext/openssl/ossl_pkey_dsa.c +@@ -231,25 +231,20 @@ ossl_dsa_initialize(int argc, VALUE *argv, VALUE self) + pass = ossl_pem_passwd_value(pass); + arg = ossl_to_der_if_possible(arg); + in = ossl_obj2bio(&arg); +- if (!dsa) { +- OSSL_BIO_reset(in); +- dsa = PEM_read_bio_DSA_PUBKEY(in, NULL, NULL, NULL); +- } +- if (!dsa) { +- OSSL_BIO_reset(in); +- dsa = d2i_DSAPrivateKey_bio(in, NULL); +- } +- if (!dsa) { +- OSSL_BIO_reset(in); +- dsa = d2i_DSA_PUBKEY_bio(in, NULL); +- } +- if (!dsa) { +- OSSL_BIO_reset(in); +-#define PEM_read_bio_DSAPublicKey(bp,x,cb,u) (DSA *)PEM_ASN1_read_bio( \ +- (d2i_of_void *)d2i_DSAPublicKey, PEM_STRING_DSA_PUBLIC, (bp), (void **)(x), (cb), (u)) +- dsa = PEM_read_bio_DSAPublicKey(in, NULL, NULL, NULL); +-#undef PEM_read_bio_DSAPublicKey +- } ++ dsa = (DSA *)PEM_ASN1_read_bio((d2i_of_void *)d2i_DSAPublicKey, ++ PEM_STRING_DSA_PUBLIC, in, ++ NULL, NULL, NULL); ++ if (!dsa) { ++ OSSL_BIO_reset(in); ++ tmp = ossl_pkey_read_generic(in, pass); ++ if (tmp) { ++ if (EVP_PKEY_base_id(tmp) != EVP_PKEY_DSA) ++ rb_raise(eDSAError, "incorrect pkey type: %s", ++ OBJ_nid2sn(EVP_PKEY_base_id(tmp))); ++ dsa = EVP_PKEY_get1_DSA(tmp); ++ EVP_PKEY_free(tmp); ++ } ++ } + BIO_free(in); + if (!dsa) { + ossl_clear_error(); +diff --git a/ext/openssl/ossl_pkey_rsa.c b/ext/openssl/ossl_pkey_rsa.c +index 1a82f22..a928e92 100644 +--- a/ext/openssl/ossl_pkey_rsa.c ++++ b/ext/openssl/ossl_pkey_rsa.c +@@ -220,7 +220,7 @@ ossl_rsa_s_generate(int argc, VALUE *argv, VALUE klass) + static VALUE + ossl_rsa_initialize(int argc, VALUE *argv, VALUE self) + { +- EVP_PKEY *pkey; ++ EVP_PKEY *pkey, *tmp; + RSA *rsa; + BIO *in; + VALUE arg, pass; +@@ -238,28 +238,24 @@ ossl_rsa_initialize(int argc, VALUE *argv, VALUE self) + pass = ossl_pem_passwd_value(pass); + arg = ossl_to_der_if_possible(arg); + in = ossl_obj2bio(&arg); +- rsa = PEM_read_bio_RSAPrivateKey(in, NULL, ossl_pem_passwd_cb, (void *)pass); +- if (!rsa) { +- OSSL_BIO_reset(in); +- rsa = PEM_read_bio_RSA_PUBKEY(in, NULL, NULL, NULL); +- } +- if (!rsa) { +- OSSL_BIO_reset(in); +- rsa = d2i_RSAPrivateKey_bio(in, NULL); +- } +- if (!rsa) { +- OSSL_BIO_reset(in); +- rsa = d2i_RSA_PUBKEY_bio(in, NULL); +- } +- if (!rsa) { +- OSSL_BIO_reset(in); +- rsa = PEM_read_bio_RSAPublicKey(in, NULL, NULL, NULL); +- } +- if (!rsa) { +- OSSL_BIO_reset(in); +- rsa = d2i_RSAPublicKey_bio(in, NULL); +- } +- BIO_free(in); ++ ++ rsa = PEM_read_bio_RSAPublicKey(in, NULL, NULL, NULL); ++ if (!rsa) { ++ OSSL_BIO_reset(in); ++ rsa = d2i_RSAPublicKey_bio(in, NULL); ++ } ++ if (!rsa) { ++ OSSL_BIO_reset(in); ++ tmp = ossl_pkey_read_generic(in, pass); ++ if (tmp) { ++ if (EVP_PKEY_base_id(tmp) != EVP_PKEY_RSA) ++ rb_raise(eRSAError, "incorrect pkey type: %s", ++ OBJ_nid2sn(EVP_PKEY_base_id(tmp))); ++ rsa = EVP_PKEY_get1_RSA(tmp); ++ EVP_PKEY_free(tmp); ++ } ++ } ++ BIO_free(in); + if (!rsa) { + ossl_raise(eRSAError, "Neither PUB key nor PRIV key"); + } + +From 9f81a082e9aea407f722388397fd87ca75712ff1 Mon Sep 17 00:00:00 2001 +From: Kazuki Yamaguchi +Date: Tue, 30 Jun 2020 16:12:14 +0900 +Subject: [PATCH 07/21] pkey/ec: deprecate PKey::EC::Point#make_affine! and + make it no-op + +It forces the internal representation of the point object to the affine +coordinate system. However, as the difference of the internal +representation is not visible from Ruby/OpenSSL at all, it had no real +use case. + +EC_POINT_make_affine() is marked as deprecated in OpenSSL 3.0. +--- + ext/openssl/ossl_pkey_ec.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/ext/openssl/ossl_pkey_ec.c b/ext/openssl/ossl_pkey_ec.c +index c3ed21e0..4ab872ee 100644 +--- a/ext/openssl/ossl_pkey_ec.c ++++ b/ext/openssl/ossl_pkey_ec.c +@@ -1443,6 +1443,8 @@ static VALUE ossl_ec_point_is_on_curve(VALUE self) + /* + * call-seq: + * point.make_affine! => self ++ * ++ * This method is deprecated and should not be used. + */ + static VALUE ossl_ec_point_make_affine(VALUE self) + { +@@ -1452,8 +1454,12 @@ static VALUE ossl_ec_point_make_affine(VALUE self) + GetECPoint(self, point); + GetECPointGroup(self, group); + ++ rb_warn("OpenSSL::PKey::EC::Point#make_affine! is deprecated; " \ ++ "the conversion is automatically performed when necessary"); ++#if !(OPENSSL_VERSION_MAJOR+0 >= 3) + if (EC_POINT_make_affine(group, point, ossl_bn_ctx) != 1) + ossl_raise(cEC_POINT, "EC_POINT_make_affine"); ++#endif + + return self; + } + +From 9b2009868c523c02a4d695afcaaedad61f9eaba9 Mon Sep 17 00:00:00 2001 +From: Kazuki Yamaguchi +Date: Sat, 22 Feb 2020 05:52:01 +0900 +Subject: [PATCH 08/21] pkey/ec: use EC_GROUP_free() instead of + EC_GROUP_clear_free() + +EC_GROUP_clear_free() is deprecated in OpenSSL 3.0. + +The EC_GROUP does not include any sensitive data, so we can safely use +EC_GROUP_free() instead. +--- + ext/openssl/ossl_pkey_ec.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/ext/openssl/ossl_pkey_ec.c b/ext/openssl/ossl_pkey_ec.c +index 4ab872ee..e4e4141c 100644 +--- a/ext/openssl/ossl_pkey_ec.c ++++ b/ext/openssl/ossl_pkey_ec.c +@@ -638,7 +638,7 @@ static VALUE ossl_ec_key_check_key(VALUE self) + static void + ossl_ec_group_free(void *ptr) + { +- EC_GROUP_clear_free(ptr); ++ EC_GROUP_free(ptr); + } + + static const rb_data_type_t ossl_ec_group_type = { + +From 92a5cdd545d32cd66c61614c5975afac620de5f9 Mon Sep 17 00:00:00 2001 +From: Kazuki Yamaguchi +Date: Fri, 10 Jul 2020 14:34:51 +0900 +Subject: [PATCH 09/21] pkey/dh: let PKey::DH#params_ok? use + EVP_PKEY_param_check() + +Use EVP_PKEY_param_check() instead of DH_check() if available. It is +part of the EVP API and is preferred over the lower level API. + +EVP_PKEY_param_check() was added by OpenSSL 1.1.1. It is currently not +provided by LibreSSL. +--- + ext/openssl/extconf.rb | 3 +++ + ext/openssl/ossl_pkey_dh.c | 27 +++++++++++++++++++++++---- + +diff --git a/ext/openssl/extconf.rb b/ext/openssl/extconf.rb +index 14e599ca..e5b0fb65 100644 +--- a/ext/openssl/extconf.rb ++++ b/ext/openssl/extconf.rb +@@ -176,6 +176,9 @@ def find_openssl_library + have_func("EVP_PBE_scrypt") + have_func("SSL_CTX_set_post_handshake_auth") + ++# added in 1.1.1 ++have_func("EVP_PKEY_param_check") ++ + # added in 3.0.0 + have_func("TS_VERIFY_CTX_set_certs(NULL, NULL)", "openssl/ts.h") + have_func("SSL_CTX_load_verify_file") +diff --git a/ext/openssl/ossl_pkey_dh.c b/ext/openssl/ossl_pkey_dh.c +index 458721e2..a3628572 100644 +--- a/ext/openssl/ossl_pkey_dh.c ++++ b/ext/openssl/ossl_pkey_dh.c +@@ -456,19 +456,38 @@ ossl_dh_to_public_key(VALUE self) + * Validates the Diffie-Hellman parameters associated with this instance. + * It checks whether a safe prime and a suitable generator are used. If this + * is not the case, +false+ is returned. ++ * ++ * See also the man page EVP_PKEY_param_check(3). + */ + static VALUE + ossl_dh_check_params(VALUE self) + { ++ int ret; ++#ifdef HAVE_EVP_PKEY_PARAM_CHECK ++ EVP_PKEY *pkey; ++ EVP_PKEY_CTX *pctx; ++ ++ GetPKey(self, pkey); ++ pctx = EVP_PKEY_CTX_new(pkey, /* engine */NULL); ++ if (!pctx) ++ ossl_raise(eDHError, "EVP_PKEY_CTX_new"); ++ ret = EVP_PKEY_param_check(pctx); ++ EVP_PKEY_CTX_free(pctx); ++#else + DH *dh; + int codes; + + GetDH(self, dh); +- if (!DH_check(dh, &codes)) { +- return Qfalse; +- } ++ ret = DH_check(dh, &codes) == 1 && codes == 0; ++#endif + +- return codes == 0 ? Qtrue : Qfalse; ++ if (ret == 1) ++ return Qtrue; ++ else { ++ /* DH_check_ex() will put error entry on failure */ ++ ossl_clear_error(); ++ return Qfalse; ++ } + } + + /* +diff --git a/test/openssl/test_pkey_dh.rb b/test/openssl/test_pkey_dh.rb +index fd2c7a6..21a6dbc 100644 +--- a/test/openssl/test_pkey_dh.rb ++++ b/test/openssl/test_pkey_dh.rb +@@ -64,6 +64,14 @@ class OpenSSL::TestPKeyDH < OpenSSL::PKeyTestCase + assert_equal(dh.compute_key(dh2.pub_key), dh2.compute_key(dh.pub_key)) + end + ++ def test_params_ok? ++ dh1 = Fixtures.pkey("dh1024") ++ assert_equal(true, dh1.params_ok?) ++ ++ dh2 = Fixtures.pkey("dh1024").tap { |p| p.set_pqg(p.p + 1, p.q, p.g) } ++ assert_equal(false, dh2.params_ok?) ++ end ++ + def test_dup + dh = OpenSSL::PKey::DH.new(NEW_KEYLEN) + dh2 = dh.dup + +From af7aba5955685987409298e7b351d1dc7588b24e Mon Sep 17 00:00:00 2001 +From: Kazuki Yamaguchi +Date: Mon, 18 May 2020 02:17:28 +0900 +Subject: [PATCH 10/21] test/openssl/test_digest: do not test constants for + legacy algorithms + +Do not test availability of MD4 and RIPEMD160 as they are considered +legacy and can be missing. OpenSSL 3.0 by default does not enable it. +--- + test/openssl/test_digest.rb | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/test/openssl/test_digest.rb b/test/openssl/test_digest.rb +index 8d7046e8..84c128c1 100644 +--- a/test/openssl/test_digest.rb ++++ b/test/openssl/test_digest.rb +@@ -54,7 +54,7 @@ def test_reset + end + + def test_digest_constants +- %w{MD4 MD5 RIPEMD160 SHA1 SHA224 SHA256 SHA384 SHA512}.each do |name| ++ %w{MD5 SHA1 SHA224 SHA256 SHA384 SHA512}.each do |name| + assert_not_nil(OpenSSL::Digest.new(name)) + klass = OpenSSL::Digest.const_get(name.tr('-', '_')) + assert_not_nil(klass.new) + +From 5b7a1bd78278d6f0527501e34b6453fa004aa281 Mon Sep 17 00:00:00 2001 +From: Kazuki Yamaguchi +Date: Fri, 10 Jul 2020 13:56:38 +0900 +Subject: [PATCH 11/21] test/openssl/test_ssl: relax regex to match OpenSSL's + error message + +OpenSSL 3.0 has slightly changed the error message for a certificate +verification failure when an untrusted self-signed certificate is found. +--- + test/openssl/test_ssl.rb | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/test/openssl/test_ssl.rb b/test/openssl/test_ssl.rb +index f24aabe7..6c9547dc 100644 +--- a/test/openssl/test_ssl.rb ++++ b/test/openssl/test_ssl.rb +@@ -955,7 +955,9 @@ def test_connect_certificate_verify_failed_exception_message + start_server(ignore_listener_error: true) { |port| + ctx = OpenSSL::SSL::SSLContext.new + ctx.set_params +- assert_raise_with_message(OpenSSL::SSL::SSLError, /self signed/) { ++ # OpenSSL <= 1.1.0: "self signed certificate in certificate chain" ++ # OpenSSL >= 3.0.0: "self-signed certificate in certificate chain" ++ assert_raise_with_message(OpenSSL::SSL::SSLError, /self.signed/) { + server_connect(port, ctx) + } + } + +From 9b5d8f9698c2cf5c6ac28d3ccf51557a7cd6aa56 Mon Sep 17 00:00:00 2001 +From: Kazuki Yamaguchi +Date: Fri, 10 Jul 2020 14:06:04 +0900 +Subject: [PATCH 12/21] test/openssl/test_engine: relax assertions for the + number of engines + +It seems loading a specific engine with ENGINE_by_id() can load another +engine too. Just check that OpenSSL::Engine.load call increases the +counter for the engines which are currently loaded. +--- + test/openssl/test_engine.rb | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/test/openssl/test_engine.rb b/test/openssl/test_engine.rb +index 1ede6ed0..3caf1fb8 100644 +--- a/test/openssl/test_engine.rb ++++ b/test/openssl/test_engine.rb +@@ -18,7 +18,7 @@ def test_openssl_engine_builtin + pend "'openssl' is already loaded" if orig.any? { |e| e.id == "openssl" } + engine = OpenSSL::Engine.load("openssl") + assert_equal(true, engine) +- assert_equal(1, OpenSSL::Engine.engines.size - orig.size) ++ assert_operator(OpenSSL::Engine.engines.size, :>, orig.size) + end; + end + +@@ -28,7 +28,7 @@ def test_openssl_engine_by_id_string + pend "'openssl' is already loaded" if orig.any? { |e| e.id == "openssl" } + engine = get_engine + assert_not_nil(engine) +- assert_equal(1, OpenSSL::Engine.engines.size - orig.size) ++ assert_operator(OpenSSL::Engine.engines.size, :>, orig.size) + end; + end + + +From 74e5ed30f9bae21240e5e2209346fa91ef463393 Mon Sep 17 00:00:00 2001 +From: Kazuki Yamaguchi +Date: Mon, 18 May 2020 02:35:35 +0900 +Subject: [PATCH 13/21] test/openssl/test_pkey: use EC keys for testing + PKey.generate_parameters + +OpenSSL 3.0 refuses to generate DSA parameters shorter than 2048 bits, +but generating 2048 bits parameters takes very long. Let's use EC in +those test cases instead. +--- + test/openssl/test_pkey.rb | 143 ++++++++++++++++++++++++++++++++++++++ + 1 file changed, 143 insertions(+) + +diff --git a/test/openssl/test_pkey.rb b/test/openssl/test_pkey.rb +index 0bdc979..b4ddcfb 100644 +--- a/test/openssl/test_pkey.rb ++++ b/test/openssl/test_pkey.rb +@@ -25,4 +25,147 @@ class OpenSSL::TestPKey < OpenSSL::PKeyTestCase + assert_equal "X25519", x25519.oid + assert_match %r{oid=X25519}, x25519.inspect + end ++ ++ def test_s_generate_parameters ++ pend "EC is disabled" unless defined?(OpenSSL::PKey::EC) ++ ++ pkey = OpenSSL::PKey.generate_parameters("EC", { ++ "ec_paramgen_curve" => "secp384r1", ++ }) ++ assert_instance_of OpenSSL::PKey::EC, pkey ++ assert_equal "secp384r1", pkey.group.curve_name ++ assert_equal nil, pkey.private_key ++ ++ # Invalid options are checked ++ assert_raise(OpenSSL::PKey::PKeyError) { ++ OpenSSL::PKey.generate_parameters("EC", "invalid" => "option") ++ } ++ ++ # Parameter generation callback is called ++ cb_called = [] ++ assert_raise(RuntimeError) { ++ OpenSSL::PKey.generate_parameters("DSA") { |*args| ++ cb_called << args ++ raise "exit!" if cb_called.size == 3 ++ } ++ } ++ assert_not_empty cb_called ++ end ++ ++ def test_s_generate_key ++ pend "EC is disabled" unless defined?(OpenSSL::PKey::EC) ++ ++ assert_raise(OpenSSL::PKey::PKeyError) { ++ # DSA key pair cannot be generated without parameters ++ OpenSSL::PKey.generate_key("DSA") ++ } ++ pkey_params = OpenSSL::PKey.generate_parameters("EC", { ++ "ec_paramgen_curve" => "secp384r1", ++ }) ++ pkey = OpenSSL::PKey.generate_key(pkey_params) ++ assert_instance_of OpenSSL::PKey::EC, pkey ++ assert_equal "secp384r1", pkey.group.curve_name ++ assert_not_equal nil, pkey.private_key ++ end ++ ++ def test_hmac_sign_verify ++ pkey = OpenSSL::PKey.generate_key("HMAC", { "key" => "abcd" }) ++ ++ hmac = OpenSSL::HMAC.new("abcd", "SHA256").update("data").digest ++ assert_equal hmac, pkey.sign("SHA256", "data") ++ ++ # EVP_PKEY_HMAC does not support verify ++ assert_raise(OpenSSL::PKey::PKeyError) { ++ pkey.verify("SHA256", "data", hmac) ++ } ++ end ++ ++ def test_ed25519 ++ # Test vector from RFC 8032 Section 7.1 TEST 2 ++ priv_pem = <<~EOF ++ -----BEGIN PRIVATE KEY----- ++ MC4CAQAwBQYDK2VwBCIEIEzNCJso/5banbbDRuwRTg9bijGfNaumJNqM9u1PuKb7 ++ -----END PRIVATE KEY----- ++ EOF ++ pub_pem = <<~EOF ++ -----BEGIN PUBLIC KEY----- ++ MCowBQYDK2VwAyEAPUAXw+hDiVqStwqnTRt+vJyYLM8uxJaMwM1V8Sr0Zgw= ++ -----END PUBLIC KEY----- ++ EOF ++ begin ++ priv = OpenSSL::PKey.read(priv_pem) ++ pub = OpenSSL::PKey.read(pub_pem) ++ rescue OpenSSL::PKey::PKeyError ++ # OpenSSL < 1.1.1 ++ pend "Ed25519 is not implemented" ++ end ++ assert_instance_of OpenSSL::PKey::PKey, priv ++ assert_instance_of OpenSSL::PKey::PKey, pub ++ assert_equal priv_pem, priv.private_to_pem ++ assert_equal pub_pem, priv.public_to_pem ++ assert_equal pub_pem, pub.public_to_pem ++ ++ sig = [<<~EOF.gsub(/[^0-9a-f]/, "")].pack("H*") ++ 92a009a9f0d4cab8720e820b5f642540 ++ a2b27b5416503f8fb3762223ebdb69da ++ 085ac1e43e15996e458f3613d0f11d8c ++ 387b2eaeb4302aeeb00d291612bb0c00 ++ EOF ++ data = ["72"].pack("H*") ++ assert_equal sig, priv.sign(nil, data) ++ assert_equal true, priv.verify(nil, sig, data) ++ assert_equal true, pub.verify(nil, sig, data) ++ assert_equal false, pub.verify(nil, sig, data.succ) ++ ++ # PureEdDSA wants nil as the message digest ++ assert_raise(OpenSSL::PKey::PKeyError) { priv.sign("SHA512", data) } ++ assert_raise(OpenSSL::PKey::PKeyError) { pub.verify("SHA512", sig, data) } ++ ++ # Ed25519 pkey type does not support key derivation ++ assert_raise(OpenSSL::PKey::PKeyError) { priv.derive(pub) } ++ end ++ ++ def test_x25519 ++ # Test vector from RFC 7748 Section 6.1 ++ alice_pem = <<~EOF ++ -----BEGIN PRIVATE KEY----- ++ MC4CAQAwBQYDK2VuBCIEIHcHbQpzGKV9PBbBclGyZkXfTC+H68CZKrF3+6UduSwq ++ -----END PRIVATE KEY----- ++ EOF ++ bob_pem = <<~EOF ++ -----BEGIN PUBLIC KEY----- ++ MCowBQYDK2VuAyEA3p7bfXt9wbTTW2HC7OQ1Nz+DQ8hbeGdNrfx+FG+IK08= ++ -----END PUBLIC KEY----- ++ EOF ++ shared_secret = "4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742" ++ begin ++ alice = OpenSSL::PKey.read(alice_pem) ++ bob = OpenSSL::PKey.read(bob_pem) ++ rescue OpenSSL::PKey::PKeyError ++ # OpenSSL < 1.1.0 ++ pend "X25519 is not implemented" ++ end ++ assert_instance_of OpenSSL::PKey::PKey, alice ++ assert_equal alice_pem, alice.private_to_pem ++ assert_equal bob_pem, bob.public_to_pem ++ assert_equal [shared_secret].pack("H*"), alice.derive(bob) ++ end ++ ++ def test_compare? ++ key1 = Fixtures.pkey("rsa1024") ++ key2 = Fixtures.pkey("rsa1024") ++ key3 = Fixtures.pkey("rsa2048") ++ key4 = Fixtures.pkey("dh-1") ++ ++ assert_equal(true, key1.compare?(key2)) ++ assert_equal(true, key1.public_key.compare?(key2)) ++ assert_equal(true, key2.compare?(key1)) ++ assert_equal(true, key2.public_key.compare?(key1)) ++ ++ assert_equal(false, key1.compare?(key3)) ++ ++ assert_raise(TypeError) do ++ key1.compare?(key4) ++ end ++ end + end + +From 3376d11a39295b67086da4ebc4e5530e780a398d Mon Sep 17 00:00:00 2001 +From: Kazuki Yamaguchi +Date: Thu, 13 Aug 2020 19:36:31 +0900 +Subject: [PATCH 14/21] test/openssl/test_pkey_rsa: fix RSA key generation test + +OpenSSL 3.0 checks the public exponent value in a stricter manner and +does no longer allow values less than 65537, with the exception of 3. +--- + test/openssl/test_pkey_rsa.rb | 40 +++++++++++++++++------------------ + 1 file changed, 19 insertions(+), 21 deletions(-) + +diff --git a/test/openssl/test_pkey_rsa.rb b/test/openssl/test_pkey_rsa.rb +index 9dac06e2..544d28dc 100644 +--- a/test/openssl/test_pkey_rsa.rb ++++ b/test/openssl/test_pkey_rsa.rb +@@ -68,30 +68,28 @@ def test_private + assert(!key6.private?) + end + +- def test_new +- key = OpenSSL::PKey::RSA.new 512 +- pem = key.public_key.to_pem +- OpenSSL::PKey::RSA.new pem +- assert_equal([], OpenSSL.errors) ++ def test_new_generate ++ key1 = OpenSSL::PKey::RSA.new(512) ++ assert_equal 512, key1.n.num_bits ++ assert_equal 65537, key1.e ++ ++ # Specify public exponent ++ key2 = OpenSSL::PKey::RSA.new(512, 3) ++ assert_equal 512, key2.n.num_bits ++ assert_equal 3, key2.e ++ assert_not_equal 0, key2.d + end + +- def test_new_exponent_default +- assert_equal(65537, OpenSSL::PKey::RSA.new(512).e) +- end +- +- def test_new_with_exponent +- 1.upto(30) do |idx| +- e = (2 ** idx) + 1 +- key = OpenSSL::PKey::RSA.new(512, e) +- assert_equal(e, key.e) +- end +- end ++ def test_s_generate ++ key1 = OpenSSL::PKey::RSA.generate(512) ++ assert_equal 512, key1.n.num_bits ++ assert_equal 65537, key1.e + +- def test_generate +- key = OpenSSL::PKey::RSA.generate(512, 17) +- assert_equal 512, key.n.num_bits +- assert_equal 17, key.e +- assert_not_nil key.d ++ # Specify public exponent ++ key2 = OpenSSL::PKey::RSA.generate(512, 3) ++ assert_equal 512, key2.n.num_bits ++ assert_equal 3, key2.e ++ assert_not_equal 0, key2.d + end + + def test_new_break + +From 050760bb700a274cb5efe3211dae8f8e078f2f1a Mon Sep 17 00:00:00 2001 +From: Kazuki Yamaguchi +Date: Thu, 13 Aug 2020 23:20:55 +0900 +Subject: [PATCH 15/21] test/openssl/test_pkcs12: fix test failures with + OpenSSL 3.0 + +OpenSSL's PKCS12_create() by default uses pbewithSHAAnd40BitRC2-CBC for +encryption of the certificates. However, in OpenSSL 3.0, the algorithm +is part of the legacy provider and is not enabled by default. + +Specify another algorithm that is still in the default provider in the +test cases. +--- + test/openssl/test_pkcs12.rb | 297 ++++++++++++++++++------------------ + 1 file changed, 149 insertions(+), 148 deletions(-) + +diff --git a/test/openssl/test_pkcs12.rb b/test/openssl/test_pkcs12.rb +index fdbe753b..ec676743 100644 +--- a/test/openssl/test_pkcs12.rb ++++ b/test/openssl/test_pkcs12.rb +@@ -5,6 +5,9 @@ + + module OpenSSL + class TestPKCS12 < OpenSSL::TestCase ++ DEFAULT_PBE_PKEYS = "PBE-SHA1-3DES" ++ DEFAULT_PBE_CERTS = "PBE-SHA1-3DES" ++ + def setup + super + ca = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=CA") +@@ -14,47 +17,41 @@ def setup + ["subjectKeyIdentifier","hash",false], + ["authorityKeyIdentifier","keyid:always",false], + ] +- @cacert = issue_cert(ca, Fixtures.pkey("rsa2048"), 1, ca_exts, nil, nil) ++ ca_key = Fixtures.pkey("rsa-1") ++ @cacert = issue_cert(ca, ca_key, 1, ca_exts, nil, nil) + + inter_ca = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=Intermediate CA") +- inter_ca_key = OpenSSL::PKey.read <<-_EOS_ +------BEGIN RSA PRIVATE KEY----- +-MIICXAIBAAKBgQDp7hIG0SFMG/VWv1dBUWziAPrNmkMXJgTCAoB7jffzRtyyN04K +-oq/89HAszTMStZoMigQURfokzKsjpUp8OYCAEsBtt9d5zPndWMz/gHN73GrXk3LT +-ZsxEn7Xv5Da+Y9F/Hx2QZUHarV5cdZixq2NbzWGwrToogOQMh2pxN3Z/0wIDAQAB +-AoGBAJysUyx3olpsGzv3OMRJeahASbmsSKTXVLZvoIefxOINosBFpCIhZccAG6UV +-5c/xCvS89xBw8aD15uUfziw3AuT8QPEtHCgfSjeT7aWzBfYswEgOW4XPuWr7EeI9 +-iNHGD6z+hCN/IQr7FiEBgTp6A+i/hffcSdR83fHWKyb4M7TRAkEA+y4BNd668HmC +-G5MPRx25n6LixuBxrNp1umfjEI6UZgEFVpYOg4agNuimN6NqM253kcTR94QNTUs5 +-Kj3EhG1YWwJBAO5rUjiOyCNVX2WUQrOMYK/c1lU7fvrkdygXkvIGkhsPoNRzLPeA +-HGJszKtrKD8bNihWpWNIyqKRHfKVD7yXT+kCQGCAhVCIGTRoypcDghwljHqLnysf +-ci0h5ZdPcIqc7ODfxYhFsJ/Rql5ONgYsT5Ig/+lOQAkjf+TRYM4c2xKx2/8CQBvG +-jv6dy70qDgIUgqzONtlmHeYyFzn9cdBO5sShdVYHvRHjFSMEXsosqK9zvW2UqvuK +-FJx7d3f29gkzynCLJDkCQGQZlEZJC4vWmWJGRKJ24P6MyQn3VsPfErSKOg4lvyM3 +-Li8JsX5yIiuVYaBg/6ha3tOg4TCa5K/3r3tVliRZ2Es= +------END RSA PRIVATE KEY----- +- _EOS_ +- @inter_cacert = issue_cert(inter_ca, inter_ca_key, 2, ca_exts, @cacert, Fixtures.pkey("rsa2048")) ++ inter_ca_key = Fixtures.pkey("rsa-2") ++ @inter_cacert = issue_cert(inter_ca, inter_ca_key, 2, ca_exts, @cacert, ca_key) + + exts = [ + ["keyUsage","digitalSignature",true], + ["subjectKeyIdentifier","hash",false], + ] + ee = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=Ruby PKCS12 Test Certificate") +- @mykey = Fixtures.pkey("rsa1024") ++ @mykey = Fixtures.pkey("rsa-3") + @mycert = issue_cert(ee, @mykey, 3, exts, @inter_cacert, inter_ca_key) + end + +- def test_create ++ def test_create_single_key_single_cert + pkcs12 = OpenSSL::PKCS12.create( + "omg", + "hello", + @mykey, +- @mycert ++ @mycert, ++ nil, ++ DEFAULT_PBE_PKEYS, ++ DEFAULT_PBE_CERTS, + ) +- assert_equal @mycert.to_der, pkcs12.certificate.to_der ++ assert_equal @mycert, pkcs12.certificate + assert_equal @mykey.to_der, pkcs12.key.to_der + assert_nil pkcs12.ca_certs ++ ++ der = pkcs12.to_der ++ decoded = OpenSSL::PKCS12.new(der, "omg") ++ assert_equal @mykey.to_der, decoded.key.to_der ++ assert_equal @mycert, decoded.certificate ++ assert_equal [], Array(decoded.ca_certs) + end + + def test_create_no_pass +@@ -62,14 +59,17 @@ def test_create_no_pass + nil, + "hello", + @mykey, +- @mycert ++ @mycert, ++ nil, ++ DEFAULT_PBE_PKEYS, ++ DEFAULT_PBE_CERTS, + ) +- assert_equal @mycert.to_der, pkcs12.certificate.to_der ++ assert_equal @mycert, pkcs12.certificate + assert_equal @mykey.to_der, pkcs12.key.to_der + assert_nil pkcs12.ca_certs + + decoded = OpenSSL::PKCS12.new(pkcs12.to_der) +- assert_cert @mycert, decoded.certificate ++ assert_equal @mycert, decoded.certificate + end + + def test_create_with_chain +@@ -80,7 +80,9 @@ def test_create_with_chain + "hello", + @mykey, + @mycert, +- chain ++ chain, ++ DEFAULT_PBE_PKEYS, ++ DEFAULT_PBE_CERTS, + ) + assert_equal chain, pkcs12.ca_certs + end +@@ -95,14 +97,16 @@ def test_create_with_chain_decode + "hello", + @mykey, + @mycert, +- chain ++ chain, ++ DEFAULT_PBE_PKEYS, ++ DEFAULT_PBE_CERTS, + ) + + decoded = OpenSSL::PKCS12.new(pkcs12.to_der, passwd) + assert_equal chain.size, decoded.ca_certs.size +- assert_include_cert @cacert, decoded.ca_certs +- assert_include_cert @inter_cacert, decoded.ca_certs +- assert_cert @mycert, decoded.certificate ++ assert_include decoded.ca_certs, @cacert ++ assert_include decoded.ca_certs, @inter_cacert ++ assert_equal @mycert, decoded.certificate + assert_equal @mykey.to_der, decoded.key.to_der + end + +@@ -126,8 +130,8 @@ def test_create_with_itr + @mykey, + @mycert, + [], +- nil, +- nil, ++ DEFAULT_PBE_PKEYS, ++ DEFAULT_PBE_CERTS, + 2048 + ) + +@@ -138,8 +142,8 @@ def test_create_with_itr + @mykey, + @mycert, + [], +- nil, +- nil, ++ DEFAULT_PBE_PKEYS, ++ DEFAULT_PBE_CERTS, + "omg" + ) + end +@@ -152,7 +156,8 @@ def test_create_with_mac_itr + @mykey, + @mycert, + [], +- nil, ++ DEFAULT_PBE_PKEYS, ++ DEFAULT_PBE_CERTS, + nil, + nil, + 2048 +@@ -165,148 +170,144 @@ def test_create_with_mac_itr + @mykey, + @mycert, + [], +- nil, +- nil, ++ DEFAULT_PBE_PKEYS, ++ DEFAULT_PBE_CERTS, + nil, + "omg" + ) + end + end + +- def test_new_with_one_key_and_one_cert +- # generated with: +- # openssl version #=> OpenSSL 1.0.2h 3 May 2016 +- # openssl pkcs12 -in <@mycert> -inkey -export -out +- str = <<~EOF.unpack("m").first +-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 +-vyl2WuMdEwQIMWFFphPkIUICAggA +- EOF +- p12 = OpenSSL::PKCS12.new(str, "abc123") +- +- assert_equal @mykey.to_der, p12.key.to_der +- assert_equal @mycert.subject.to_der, p12.certificate.subject.to_der +- assert_equal [], Array(p12.ca_certs) +- end +- + def test_new_with_no_keys + # generated with: +- # openssl pkcs12 -in <@mycert> -nokeys -export -out ++ # openssl pkcs12 -certpbe PBE-SHA1-3DES -in <@mycert> -nokeys -export + str = <<~EOF.unpack("m").first +-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 ++AA== + EOF + p12 = OpenSSL::PKCS12.new(str, "abc123") + + assert_equal nil, p12.key + assert_equal nil, p12.certificate + assert_equal 1, p12.ca_certs.size +- assert_equal @mycert.subject.to_der, p12.ca_certs[0].subject.to_der ++ assert_equal @mycert.subject, p12.ca_certs[0].subject + end + + def test_new_with_no_certs + # generated with: +- # openssl pkcs12 -inkey -nocerts -export -out ++ # openssl pkcs12 -inkey fixtures/openssl/pkey/rsa-1.pem -nocerts -export + str = <<~EOF.unpack("m").first +-MIIDJwIBAzCCAu0GCSqGSIb3DQEHAaCCAt4EggLaMIIC1jCCAtIGCSqGSIb3DQEH +-AaCCAsMEggK/MIICuzCCArcGCyqGSIb3DQEMCgECoIICpjCCAqIwHAYKKoZIhvcN +-AQwBAzAOBAg6AaYnJs84SwICCAAEggKAQzZH+fWSpcQYD1J7PsGSune85A++fLCQ +-V7tacp2iv95GJkxwYmfTP176pJdgs00mceB9UJ/u9EX5nD0djdjjQjwo6sgKjY0q +-cpVhZw8CMxw7kBD2dhtui0zT8z5hy03LePxsjEKsGiSbeVeeGbSfw/I6AAYbv+Uh +-O/YPBGumeHj/D2WKnfsHJLQ9GAV3H6dv5VKYNxjciK7f/JEyZCuUQGIN64QFHDhJ +-7fzLqd/ul3FZzJZO6a+dwvcgux09SKVXDRSeFmRCEX4b486iWhJJVspCo9P2KNne +-ORrpybr3ZSwxyoICmjyo8gj0OSnEfdx9790Ej1takPqSA1wIdSdBLekbZqB0RBQg +-DEuPOsXNo3QFi8ji1vu0WBRJZZSNC2hr5NL6lNR+DKxG8yzDll2j4W4BBIp22mAE +-7QRX7kVxu17QJXQhOUac4Dd1qXmzebP8t6xkAxD9L7BWEN5OdiXWwSWGjVjMBneX +-nYObi/3UT/aVc5WHMHK2BhCI1bwH51E6yZh06d5m0TQpYGUTWDJdWGBSrp3A+8jN +-N2PMQkWBFrXP3smHoTEN4oZC4FWiPsIEyAkQsfKRhcV9lGKl2Xgq54ROTFLnwKoj +-Z3zJScnq9qmNzvVZSMmDLkjLyDq0pxRxGKBvgouKkWY7VFFIwwBIJM39iDJ5NbBY +-i1AQFTRsRSsZrNVPasCXrIq7bhMoJZb/YZOGBLNyJVqKUoYXhtwsajzSq54VlWft +-JxsPayEd4Vi6O9EU1ahnj6qFEZiKFzsicgK2J1Rb8cYagrp0XWjHW0SBn5GVUWCg +-GUokSFG/0JTdeYTo/sQuG4qNgJkOolRjpeI48Fciq5VUWLvVdKioXzAxMCEwCQYF +-Kw4DAhoFAAQUYAuwVtGD1TdgbFK4Yal2XBgwUR4ECEawsN3rNaa6AgIIAA== ++MIIJ7wIBAzCCCbUGCSqGSIb3DQEHAaCCCaYEggmiMIIJnjCCCZoGCSqGSIb3 ++DQEHAaCCCYsEggmHMIIJgzCCCX8GCyqGSIb3DQEMCgECoIIJbjCCCWowHAYK ++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 ++BC8fv38mue8LZVcbHQQIUNrWKEnskCoCAggA + EOF + p12 = OpenSSL::PKCS12.new(str, "abc123") + +- assert_equal @mykey.to_der, p12.key.to_der ++ assert_equal Fixtures.pkey("rsa-1").to_der, p12.key.to_der + assert_equal nil, p12.certificate + assert_equal [], Array(p12.ca_certs) + end + + def test_dup +- p12 = OpenSSL::PKCS12.create("pass", "name", @mykey, @mycert) ++ p12 = OpenSSL::PKCS12.create( ++ "pass", ++ "name", ++ @mykey, ++ @mycert, ++ nil, ++ DEFAULT_PBE_PKEYS, ++ DEFAULT_PBE_CERTS, ++ ) + assert_equal p12.to_der, p12.dup.to_der + end +- +- private +- def assert_cert expected, actual +- [ +- :subject, +- :issuer, +- :serial, +- :not_before, +- :not_after, +- ].each do |attribute| +- assert_equal expected.send(attribute), actual.send(attribute) +- end +- assert_equal expected.to_der, actual.to_der +- end +- +- def assert_include_cert cert, ary +- der = cert.to_der +- ary.each do |candidate| +- if candidate.to_der == der +- return true +- end +- end +- false +- end + end + end + + +From 1fc2fad3a163dc41e4e17dd1096e3e63f8e4f2dd Mon Sep 17 00:00:00 2001 +From: Kazuki Yamaguchi +Date: Fri, 19 Mar 2021 19:18:25 +0900 +Subject: [PATCH 16/21] ssl: use SSL_get_rbio() to check if SSL is started or + not + +Use SSL_get_rbio() instead of SSL_get_fd(). SSL_get_rbio() is simpler +and does not need error handling. +--- + ext/openssl/ossl_ssl.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/ext/openssl/ossl_ssl.c b/ext/openssl/ossl_ssl.c +index c80c939e..06bfd96d 100644 +--- a/ext/openssl/ossl_ssl.c ++++ b/ext/openssl/ossl_ssl.c +@@ -1529,8 +1529,8 @@ ossl_sslctx_flush_sessions(int argc, VALUE *argv, VALUE self) + static inline int + ssl_started(SSL *ssl) + { +- /* the FD is set in ossl_ssl_setup(), called by #connect or #accept */ +- return SSL_get_fd(ssl) >= 0; ++ /* BIO is created through ossl_ssl_setup(), called by #connect or #accept */ ++ return SSL_get_rbio(ssl) != NULL; + } + + static void + +From 01e123051d774355bdda1947d77a832216e5b595 Mon Sep 17 00:00:00 2001 +From: Kazuki Yamaguchi +Date: Sat, 20 Mar 2021 23:16:16 +0900 +Subject: [PATCH] pkey: use OSSL_STORE to load encrypted PEM on OpenSSL 3.0 + +--- + ext/openssl/ossl_pkey.c | 35 +++++++++++++++++++++++++++++++++++ + 1 file changed, 35 insertions(+) + +diff --git a/ext/openssl/ossl_pkey.c b/ext/openssl/ossl_pkey.c +index 3982b9c..f58a4c9 100644 +--- a/ext/openssl/ossl_pkey.c ++++ b/ext/openssl/ossl_pkey.c +@@ -140,12 +140,41 @@ ossl_pkey_new(EVP_PKEY *pkey) + return obj; + } + ++#if OPENSSL_VERSION_MAJOR+0 >= 3 ++# include ++static EVP_PKEY * ++ossl_pkey_read_decoder(BIO *bio, const char *input_type, void *ppass) ++{ ++ OSSL_DECODER_CTX *dctx; ++ EVP_PKEY *pkey = NULL; ++ ++ dctx = OSSL_DECODER_CTX_new_for_pkey(&pkey, input_type, NULL, NULL, 0, NULL, NULL); ++ if (!dctx) ++ goto out; ++ if (OSSL_DECODER_CTX_set_pem_password_cb(dctx, ossl_pem_passwd_cb, ppass) != 1) ++ goto out; ++ if (OSSL_DECODER_from_bio(dctx, bio) != 1) ++ goto out; ++ ++ out: ++ OSSL_DECODER_CTX_free(dctx); ++ return pkey; ++} ++#endif ++ + EVP_PKEY * + ossl_pkey_read_generic(BIO *bio, VALUE pass) + { + void *ppass = (void *)pass; + EVP_PKEY *pkey; + ++#if OPENSSL_VERSION_MAJOR+0 >= 3 ++ if ((pkey = ossl_pkey_read_decoder(bio, "DER", ppass))) ++ goto out; ++ OSSL_BIO_reset(bio); ++ if ((pkey = ossl_pkey_read_decoder(bio, "PEM", ppass))) ++ goto out; ++#else + if ((pkey = d2i_PrivateKey_bio(bio, NULL))) + goto out; + OSSL_BIO_reset(bio); +@@ -164,8 +193,14 @@ ossl_pkey_read_generic(BIO *bio, VALUE pass) + OSSL_BIO_reset(bio); + if ((pkey = PEM_read_bio_Parameters(bio, NULL))) + goto out; ++#endif + + out: ++#if OPENSSL_VERSION_MAJOR+0 >= 3 ++ /* FIXME: OpenSSL bug? */ ++ if (pkey) ++ ossl_clear_error(); ++#endif + return pkey; + } + + +From 2bfc05abddd80f927e164bfe4545c87f0b30da81 Mon Sep 17 00:00:00 2001 +From: Kazuki Yamaguchi +Date: Sat, 20 Mar 2021 23:16:41 +0900 +Subject: [PATCH 18/21] pkey: skip checking if pkey has public key components + on OpenSSL 3.0 + +--- + ext/openssl/ossl_pkey.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/ext/openssl/ossl_pkey.c b/ext/openssl/ossl_pkey.c +index df6aaa46..aceccb5b 100644 +--- a/ext/openssl/ossl_pkey.c ++++ b/ext/openssl/ossl_pkey.c +@@ -251,6 +251,12 @@ ossl_pkey_check_public_key(const EVP_PKEY *pkey) + + /* OpenSSL < 1.1.0 takes non-const pointer */ + ptr = EVP_PKEY_get0((EVP_PKEY *)pkey); ++ /* ++ * OpenSSL 3.0.0's EVP_PKEY_get0() returns NULL - the lower level object ++ * may not be accesible ++ */ ++ if (!ptr) ++ return; + switch (EVP_PKEY_base_id(pkey)) { + case EVP_PKEY_RSA: + RSA_get0_key(ptr, &n, &e, NULL); + +From 04a0948ab085ab8452dd2fcb507b1af1ff9e0ab2 Mon Sep 17 00:00:00 2001 +From: Kazuki Yamaguchi +Date: Sun, 21 Mar 2021 00:20:04 +0900 +Subject: [PATCH 19/21] bn: make BN.pseudo_rand{,_range} an alias of + BN.rand{,_range} + +BN_pseudo_rand() and BN_pseudo_rand_range() are deprecated in +OpenSSL 3.0. Since they are identical to their non-'pseudo' version +anyway, let's make them alias. +--- + ext/openssl/ossl_bn.c | 18 ++---------------- + test/openssl/test_bn.rb | 4 ++++ + 2 files changed, 6 insertions(+), 16 deletions(-) + +diff --git a/ext/openssl/ossl_bn.c b/ext/openssl/ossl_bn.c +index e0eef4cd..fe62442f 100644 +--- a/ext/openssl/ossl_bn.c ++++ b/ext/openssl/ossl_bn.c +@@ -794,12 +794,6 @@ BIGNUM_SELF_SHIFT(rshift) + */ + BIGNUM_RAND(rand) + +-/* +- * Document-method: OpenSSL::BN.pseudo_rand +- * BN.pseudo_rand(bits [, fill [, odd]]) -> aBN +- */ +-BIGNUM_RAND(pseudo_rand) +- + #define BIGNUM_RAND_RANGE(func) \ + static VALUE \ + ossl_bn_s_##func##_range(VALUE klass, VALUE range) \ +@@ -825,14 +819,6 @@ BIGNUM_RAND(pseudo_rand) + */ + BIGNUM_RAND_RANGE(rand) + +-/* +- * Document-method: OpenSSL::BN.pseudo_rand_range +- * call-seq: +- * BN.pseudo_rand_range(range) -> aBN +- * +- */ +-BIGNUM_RAND_RANGE(pseudo_rand) +- + /* + * call-seq: + * BN.generate_prime(bits, [, safe [, add [, rem]]]) => bn +@@ -1182,9 +1168,9 @@ Init_ossl_bn(void) + * get_word */ + + rb_define_singleton_method(cBN, "rand", ossl_bn_s_rand, -1); +- rb_define_singleton_method(cBN, "pseudo_rand", ossl_bn_s_pseudo_rand, -1); + rb_define_singleton_method(cBN, "rand_range", ossl_bn_s_rand_range, 1); +- rb_define_singleton_method(cBN, "pseudo_rand_range", ossl_bn_s_pseudo_rand_range, 1); ++ rb_define_alias(rb_singleton_class(cBN), "pseudo_rand", "rand"); ++ rb_define_alias(rb_singleton_class(cBN), "pseudo_rand_range", "rand_range"); + + rb_define_singleton_method(cBN, "generate_prime", ossl_bn_s_generate_prime, -1); + rb_define_method(cBN, "prime?", ossl_bn_is_prime, -1); +diff --git a/test/openssl/test_bn.rb b/test/openssl/test_bn.rb +index 1ed4bbee..36af9644 100644 +--- a/test/openssl/test_bn.rb ++++ b/test/openssl/test_bn.rb +@@ -228,6 +228,10 @@ def test_random + r5 = OpenSSL::BN.rand_range(256) + assert_include(0..255, r5) + } ++ ++ # Aliases ++ assert_include(128..255, OpenSSL::BN.pseudo_rand(8)) ++ assert_include(0..255, OpenSSL::BN.pseudo_rand_range(256)) + end + + def test_prime + +From a2de5b69f144491426cb393e1fc929af404fda12 Mon Sep 17 00:00:00 2001 +From: Kazuki Yamaguchi +Date: Sun, 21 Mar 2021 00:23:31 +0900 +Subject: [PATCH 20/21] test/openssl/test_ssl.rb: fix illegal SAN extension + +A certificate can only have one SubjectAltName extension. OpenSSL 3.0 +does a stricter validation and such a certificate is rejected. +--- + test/openssl/test_ssl.rb | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/test/openssl/test_ssl.rb b/test/openssl/test_ssl.rb +index 6c9547dc..60520b22 100644 +--- a/test/openssl/test_ssl.rb ++++ b/test/openssl/test_ssl.rb +@@ -551,8 +551,7 @@ def test_post_connection_check + + exts = [ + ["keyUsage","keyEncipherment,digitalSignature",true], +- ["subjectAltName","DNS:localhost.localdomain",false], +- ["subjectAltName","IP:127.0.0.1",false], ++ ["subjectAltName","DNS:localhost.localdomain,IP:127.0.0.1",false], + ] + @svr_cert = issue_cert(@svr, @svr_key, 4, exts, @ca_cert, @ca_key) + start_server { |port| diff --git a/ruby.spec b/ruby.spec index a9beac5..6d278d9 100644 --- a/ruby.spec +++ b/ruby.spec @@ -153,6 +153,10 @@ Patch15: ruby-dwarf5-avoid_crash-r1.patch # Avoid possible timeout errors in TestBugReporter#test_bug_reporter_add. # https://bugs.ruby-lang.org/issues/16492 Patch19: ruby-2.7.1-Timeout-the-test_bug_reporter_add-witout-raising-err.patch +# Support openssl 3.0 +# https://github.com/ruby/openssl/commit/d963d4e276658d110bcb796722d76efa7fb68efa +# https://github.com/ruby/openssl/pull/399/ +Patch20: ruby-3.0-support-openssl-3.0-pr399.patch Requires: %{name}-libs%{?_isa} = %{version}-%{release} Suggests: rubypick @@ -599,6 +603,7 @@ rm -rf ext/fiddle/libffi* %patch9 -p1 %patch15 -p1 %patch19 -p1 +%patch20 -p1 # Provide an example of usage of the tapset: cp -a %{SOURCE3} . @@ -1355,6 +1360,10 @@ MSPECOPTS="" %changelog +* Thu Jun 03 2021 Pavel Valena - 3.0.1-148 +- Support OpenSSL 3.0. + Resolves: rhbz#1952925 + * Fri Apr 16 2021 Vít Ondruch - 3.0.1-148 - Upgrade to Ruby 3.0.1.