From 00abee791da3ee9fd5d8d4ae904718edabb48333 Mon Sep 17 00:00:00 2001 From: Kazuki Yamaguchi Date: Mon, 27 Sep 2021 13:32:03 +0900 Subject: [PATCH 01/13] ext/openssl/ossl.h: add helper macros for OpenSSL/LibreSSL versions Add following convenient macros: - OSSL_IS_LIBRESSL - OSSL_OPENSSL_PREREQ(maj, min, pat) - OSSL_LIBRESSL_PREREQ(maj, min, pat) --- ext/openssl/ossl.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/ext/openssl/ossl.h b/ext/openssl/ossl.h index be9dcbdff..3a0ab1e59 100644 --- a/ext/openssl/ossl.h +++ b/ext/openssl/ossl.h @@ -42,6 +42,18 @@ #include #include +#ifndef LIBRESSL_VERSION_NUMBER +# define OSSL_IS_LIBRESSL 0 +# define OSSL_OPENSSL_PREREQ(maj, min, pat) \ + (OPENSSL_VERSION_NUMBER >= (maj << 28) | (min << 20) | (pat << 12)) +# define OSSL_LIBRESSL_PREREQ(maj, min, pat) 0 +#else +# define OSSL_IS_LIBRESSL 1 +# define OSSL_OPENSSL_PREREQ(maj, min, pat) 0 +# define OSSL_LIBRESSL_PREREQ(maj, min, pat) \ + (LIBRESSL_VERSION_NUMBER >= (maj << 28) | (min << 20) | (pat << 12)) +#endif + /* * Common Module */ From 8e98d2ecc8981fbd2782cf19113c1d3ab90329ed Mon Sep 17 00:00:00 2001 From: Kazuki Yamaguchi Date: Sat, 22 Feb 2020 18:58:29 +0900 Subject: [PATCH 02/13] 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 | 42 +++++++++++++++++++++++------------------- 2 files changed, 24 insertions(+), 19 deletions(-) diff --git a/ext/openssl/extconf.rb b/ext/openssl/extconf.rb index 9a822f60a..baf36e947 100644 --- a/ext/openssl/extconf.rb +++ b/ext/openssl/extconf.rb @@ -172,6 +172,7 @@ def find_openssl_library # added in 3.0.0 have_func("SSL_set0_tmp_dh_pkey") +have_func("ERR_get_error_all") Logging::message "=== Checking done. ===\n" diff --git a/ext/openssl/ossl.c b/ext/openssl/ossl.c index c7a755ced..6c532aca9 100644 --- a/ext/openssl/ossl.c +++ b/ext/openssl/ossl.c @@ -313,27 +313,31 @@ 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, *func, *lib, *reason; + char append[256] = ""; + int line, flags; + +#ifdef HAVE_ERR_GET_ERROR_ALL + while ((e = ERR_get_error_all(&file, &line, &func, &data, &flags))) { +#else + while ((e = ERR_get_error_line_data(&file, &line, &data, &flags))) { + func = ERR_func_error_string(e); +#endif + lib = ERR_lib_error_string(e); + reason = ERR_reason_error_string(e); + + if (flags & ERR_TXT_STRING) { + if (!data) + data = "(null)"; + 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 2be6779b08161a084a1a5d2758de21a913740b94 Mon Sep 17 00:00:00 2001 From: Kazuki Yamaguchi Date: Sat, 22 Feb 2020 05:37:01 +0900 Subject: [PATCH 03/13] 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 | 3 ++- ext/openssl/openssl_missing.h | 5 +++++ ext/openssl/ossl_ts.c | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/ext/openssl/extconf.rb b/ext/openssl/extconf.rb index baf36e947..e64fe32f2 100644 --- a/ext/openssl/extconf.rb +++ b/ext/openssl/extconf.rb @@ -160,7 +160,7 @@ 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") have_func("TS_VERIFY_CTX_set_store") have_func("TS_VERIFY_CTX_add_flags") have_func("TS_RESP_CTX_set_time_cb") @@ -173,6 +173,7 @@ def find_openssl_library # added in 3.0.0 have_func("SSL_set0_tmp_dh_pkey") have_func("ERR_get_error_all") +have_func("TS_VERIFY_CTX_set_certs(NULL, NULL)", "openssl/ts.h") Logging::message "=== Checking done. ===\n" diff --git a/ext/openssl/openssl_missing.h b/ext/openssl/openssl_missing.h index 4d9b88013..1b1a54a82 100644 --- a/ext/openssl/openssl_missing.h +++ b/ext/openssl/openssl_missing.h @@ -214,4 +214,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 b9a62fd9e..b33ff10c1 100644 --- a/ext/openssl/ossl_ts.c +++ b/ext/openssl/ossl_ts.c @@ -826,7 +826,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 5375a55ffc35cf378cd52aa4646028d7cbdbcb6f Mon Sep 17 00:00:00 2001 From: Kazuki Yamaguchi Date: Sat, 22 Feb 2020 05:47:58 +0900 Subject: [PATCH 04/13] 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 e64fe32f2..e6066d694 100644 --- a/ext/openssl/extconf.rb +++ b/ext/openssl/extconf.rb @@ -174,6 +174,7 @@ def find_openssl_library have_func("SSL_set0_tmp_dh_pkey") have_func("ERR_get_error_all") 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 1de0f9892..5d6c400c2 100644 --- a/ext/openssl/ossl_ssl.c +++ b/ext/openssl/ossl_ssl.c @@ -828,10 +828,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); +#ifdef 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 e95ee24867387dfe00fa5d3c4a6f28425a8eff5c Mon Sep 17 00:00:00 2001 From: Kazuki Yamaguchi Date: Fri, 19 Mar 2021 19:18:25 +0900 Subject: [PATCH 05/13] ssl: use SSL_get_rbio() to check if SSL is started or not Use SSL_get_rbio() instead of SSL_get_fd(). SSL_get_fd() internally calls SSL_get_rbio() and it's enough for our purpose. In OpenSSL 3.0, SSL_get_fd() leaves an entry in the OpenSSL error queue if BIO has not been set up yet, and we would have to clean it up. --- 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 5d6c400c2..a0f18d538 100644 --- a/ext/openssl/ossl_ssl.c +++ b/ext/openssl/ossl_ssl.c @@ -1443,8 +1443,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 90d51ef51091384cde33614d3665232be16682a0 Mon Sep 17 00:00:00 2001 From: Kazuki Yamaguchi Date: Sat, 22 Feb 2020 06:37:00 +0900 Subject: [PATCH 06/13] bn: use BN_check_prime() in OpenSSL::BN#prime{,_fasttest}? In OpenSSL 3.0, BN_is_prime_ex() and BN_is_prime_fasttest_ex() are deprecated in favor of BN_check_prime(). --- ext/openssl/extconf.rb | 1 + ext/openssl/ossl_bn.c | 70 +++++++++++++----------------------------- 2 files changed, 22 insertions(+), 49 deletions(-) diff --git a/ext/openssl/extconf.rb b/ext/openssl/extconf.rb index e6066d694..98f96afe7 100644 --- a/ext/openssl/extconf.rb +++ b/ext/openssl/extconf.rb @@ -175,6 +175,7 @@ def find_openssl_library have_func("ERR_get_error_all") 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 8d0f63a98..128ffabdd 100644 --- a/ext/openssl/ossl_bn.c +++ b/ext/openssl/ossl_bn.c @@ -1118,34 +1118,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 a Miller-Rabin probabilistic primality test for +bn+. * - * === Parameters - * * _checks_ - integer + * +checks+ parameter is deprecated in version 3.0. It has no effect. */ 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; + +#ifdef 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; } /* @@ -1154,40 +1149,17 @@ 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 a Miller-Rabin probabilistic primality test for +bn+. * - * === Parameters - * * _checks_ - integer - * * _trial_div_ - boolean + * Deprecated in version 3.0. Use #prime? instead. + * + * +checks+ and +trial_div+ parameters no longer have any effect. */ 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 0a253027e6be47c0b7fd8b664f1048f24d7ca657 Mon Sep 17 00:00:00 2001 From: Kazuki Yamaguchi Date: Thu, 22 Apr 2021 13:57:47 +0900 Subject: [PATCH 07/13] digest: use EVP_MD_CTX_get0_md() instead of EVP_MD_CTX_md() if exists The function was renamed in OpenSSL 3.0 due to the change of the lifetime of EVP_MD objects. They are no longer necessarily statically allocated and can be reference-counted -- when an EVP_MD_CTX is free'd, the associated EVP_MD can also become inaccessible. Currently Ruby/OpenSSL only handles builtin algorithms, so no special handling is needed except for adapting to the rename. --- ext/openssl/extconf.rb | 1 + ext/openssl/openssl_missing.h | 4 ++++ ext/openssl/ossl_digest.c | 6 +++--- ext/openssl/ossl_hmac.c | 2 +- 4 files changed, 9 insertions(+), 4 deletions(-) diff --git a/ext/openssl/extconf.rb b/ext/openssl/extconf.rb index 98f96afe7..842b7f5b1 100644 --- a/ext/openssl/extconf.rb +++ b/ext/openssl/extconf.rb @@ -176,6 +176,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("EVP_MD_CTX_get0_md") Logging::message "=== Checking done. ===\n" diff --git a/ext/openssl/openssl_missing.h b/ext/openssl/openssl_missing.h index 1b1a54a82..64212349c 100644 --- a/ext/openssl/openssl_missing.h +++ b/ext/openssl/openssl_missing.h @@ -219,4 +219,8 @@ IMPL_PKEY_GETTER(EC_KEY, ec) # define TS_VERIFY_CTX_set_certs(ctx, crts) TS_VERIFY_CTS_set_certs(ctx, crts) #endif +#ifndef HAVE_EVP_MD_CTX_GET0_MD +# define EVP_MD_CTX_get0_md(ctx) EVP_MD_CTX_md(ctx) +#endif + #endif /* _OSSL_OPENSSL_MISSING_H_ */ diff --git a/ext/openssl/ossl_digest.c b/ext/openssl/ossl_digest.c index b2506de7f..fc326ec14 100644 --- a/ext/openssl/ossl_digest.c +++ b/ext/openssl/ossl_digest.c @@ -63,7 +63,7 @@ ossl_evp_get_digestbyname(VALUE obj) GetDigest(obj, ctx); - md = EVP_MD_CTX_md(ctx); + md = EVP_MD_CTX_get0_md(ctx); } return md; @@ -176,7 +176,7 @@ ossl_digest_reset(VALUE self) EVP_MD_CTX *ctx; GetDigest(self, ctx); - if (EVP_DigestInit_ex(ctx, EVP_MD_CTX_md(ctx), NULL) != 1) { + if (EVP_DigestInit_ex(ctx, EVP_MD_CTX_get0_md(ctx), NULL) != 1) { ossl_raise(eDigestError, "Digest initialization failed."); } @@ -259,7 +259,7 @@ ossl_digest_name(VALUE self) GetDigest(self, ctx); - return rb_str_new2(EVP_MD_name(EVP_MD_CTX_md(ctx))); + return rb_str_new_cstr(EVP_MD_name(EVP_MD_CTX_get0_md(ctx))); } /* diff --git a/ext/openssl/ossl_hmac.c b/ext/openssl/ossl_hmac.c index a21db6c48..2642728b8 100644 --- a/ext/openssl/ossl_hmac.c +++ b/ext/openssl/ossl_hmac.c @@ -239,7 +239,7 @@ ossl_hmac_reset(VALUE self) GetHMAC(self, ctx); pkey = EVP_PKEY_CTX_get0_pkey(EVP_MD_CTX_pkey_ctx(ctx)); - if (EVP_DigestSignInit(ctx, NULL, EVP_MD_CTX_md(ctx), NULL, pkey) != 1) + if (EVP_DigestSignInit(ctx, NULL, EVP_MD_CTX_get0_md(ctx), NULL, pkey) != 1) ossl_raise(eHMACError, "EVP_DigestSignInit"); return self; From c106d888c62e44a11cdbba5e4d2d0cb837ec3e52 Mon Sep 17 00:00:00 2001 From: Kazuki Yamaguchi Date: Tue, 22 Jun 2021 18:50:17 +0900 Subject: [PATCH 08/13] hmac: use EVP_MD_CTX_get_pkey_ctx() instead of EVP_MD_CTX_pkey_ctx() OpenSSL 3.0 renamed EVP_MD_CTX_pkey_ctx() to include "get" in the function name. Adjust compatibility macro so that we can use the new function name for all OpenSSL 1.0.2-3.0. --- ext/openssl/extconf.rb | 1 + ext/openssl/openssl_missing.h | 16 ++++++++++++---- ext/openssl/ossl_hmac.c | 2 +- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/ext/openssl/extconf.rb b/ext/openssl/extconf.rb index 842b7f5b1..d9d34b7cf 100644 --- a/ext/openssl/extconf.rb +++ b/ext/openssl/extconf.rb @@ -177,6 +177,7 @@ def find_openssl_library have_func("SSL_CTX_load_verify_file") have_func("BN_check_prime") have_func("EVP_MD_CTX_get0_md") +have_func("EVP_MD_CTX_get_pkey_ctx") Logging::message "=== Checking done. ===\n" diff --git a/ext/openssl/openssl_missing.h b/ext/openssl/openssl_missing.h index 64212349c..55c4f378f 100644 --- a/ext/openssl/openssl_missing.h +++ b/ext/openssl/openssl_missing.h @@ -21,10 +21,6 @@ # define EVP_MD_CTX_free EVP_MD_CTX_destroy #endif -#if !defined(HAVE_EVP_MD_CTX_PKEY_CTX) -# define EVP_MD_CTX_pkey_ctx(x) (x)->pctx -#endif - #if !defined(HAVE_X509_STORE_GET_EX_DATA) # define X509_STORE_get_ex_data(x, idx) \ CRYPTO_get_ex_data(&(x)->ex_data, (idx)) @@ -223,4 +219,16 @@ IMPL_PKEY_GETTER(EC_KEY, ec) # define EVP_MD_CTX_get0_md(ctx) EVP_MD_CTX_md(ctx) #endif +/* + * OpenSSL 1.1.0 added EVP_MD_CTX_pkey_ctx(), and then it was renamed to + * EVP_MD_CTX_get_pkey_ctx(x) in OpenSSL 3.0. + */ +#ifndef HAVE_EVP_MD_CTX_GET_PKEY_CTX +# ifdef HAVE_EVP_MD_CTX_PKEY_CTX +# define EVP_MD_CTX_get_pkey_ctx(x) EVP_MD_CTX_pkey_ctx(x) +# else +# define EVP_MD_CTX_get_pkey_ctx(x) (x)->pctx +# endif +#endif + #endif /* _OSSL_OPENSSL_MISSING_H_ */ diff --git a/ext/openssl/ossl_hmac.c b/ext/openssl/ossl_hmac.c index 2642728b8..f89ff2f9a 100644 --- a/ext/openssl/ossl_hmac.c +++ b/ext/openssl/ossl_hmac.c @@ -238,7 +238,7 @@ ossl_hmac_reset(VALUE self) EVP_PKEY *pkey; GetHMAC(self, ctx); - pkey = EVP_PKEY_CTX_get0_pkey(EVP_MD_CTX_pkey_ctx(ctx)); + pkey = EVP_PKEY_CTX_get0_pkey(EVP_MD_CTX_get_pkey_ctx(ctx)); if (EVP_DigestSignInit(ctx, NULL, EVP_MD_CTX_get0_md(ctx), NULL, pkey) != 1) ossl_raise(eHMACError, "EVP_DigestSignInit"); From e2cc81fef7dffe5c4c543abe17cd7916915ecd5b Mon Sep 17 00:00:00 2001 From: Kazuki Yamaguchi Date: Tue, 30 Jun 2020 16:12:14 +0900 Subject: [PATCH 09/13] pkey/ec: deprecate PKey::EC::Point#make_affine! and make it a no-op It converts the internal representation of the point object to the affine coordinate system. However, it had no real use case because the difference in the internal representation has not been visible from Ruby/OpenSSL at all. EC_POINT_make_affine() is marked as deprecated in OpenSSL 3.0. --- ext/openssl/ossl_pkey_ec.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ext/openssl/ossl_pkey_ec.c b/ext/openssl/ossl_pkey_ec.c index 47de7ccdb..b317e45d6 100644 --- a/ext/openssl/ossl_pkey_ec.c +++ b/ext/openssl/ossl_pkey_ec.c @@ -1252,6 +1252,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. This is a no-op. */ static VALUE ossl_ec_point_make_affine(VALUE self) { @@ -1261,8 +1263,11 @@ 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"); +#if !OSSL_OPENSSL_PREREQ(3, 0, 0) if (EC_POINT_make_affine(group, point, ossl_bn_ctx) != 1) ossl_raise(cEC_POINT, "EC_POINT_make_affine"); +#endif return self; } From e93a5fdffc092e5cc215eb91a68bc0194d6535f3 Mon Sep 17 00:00:00 2001 From: Kazuki Yamaguchi Date: Sat, 22 Feb 2020 05:52:01 +0900 Subject: [PATCH 10/13] pkey/ec: use EC_GROUP_free() instead of EC_GROUP_clear_free() EC_GROUP_clear_free() is deprecated in OpenSSL 3.0. 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 b317e45d6..db80d112a 100644 --- a/ext/openssl/ossl_pkey_ec.c +++ b/ext/openssl/ossl_pkey_ec.c @@ -479,7 +479,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 d42bd7fcdb73b8d37f889b6e2dbf8508df7a335d Mon Sep 17 00:00:00 2001 From: Kazuki Yamaguchi Date: Mon, 17 May 2021 16:18:45 +0900 Subject: [PATCH 11/13] pkey, ssl: use EVP_PKEY_eq() instead of EVP_PKEY_cmp() OpenSSL 3.0 renamed EVP_PKEY_cmp() to EVP_PKEY_eq() because that was a confusing name. --- ext/openssl/extconf.rb | 1 + ext/openssl/openssl_missing.h | 4 ++++ ext/openssl/ossl_pkey.c | 4 ++-- ext/openssl/ossl_ssl.c | 2 +- 4 files changed, 8 insertions(+), 3 deletions(-) diff --git a/ext/openssl/extconf.rb b/ext/openssl/extconf.rb index d9d34b7cf..1d38b5699 100644 --- a/ext/openssl/extconf.rb +++ b/ext/openssl/extconf.rb @@ -178,6 +178,7 @@ def find_openssl_library have_func("BN_check_prime") have_func("EVP_MD_CTX_get0_md") have_func("EVP_MD_CTX_get_pkey_ctx") +have_func("EVP_PKEY_eq") Logging::message "=== Checking done. ===\n" diff --git a/ext/openssl/openssl_missing.h b/ext/openssl/openssl_missing.h index 55c4f378f..8629bfe50 100644 --- a/ext/openssl/openssl_missing.h +++ b/ext/openssl/openssl_missing.h @@ -231,4 +231,8 @@ IMPL_PKEY_GETTER(EC_KEY, ec) # endif #endif +#ifndef HAVE_EVP_PKEY_EQ +# define EVP_PKEY_eq(a, b) EVP_PKEY_cmp(a, b) +#endif + #endif /* _OSSL_OPENSSL_MISSING_H_ */ diff --git a/ext/openssl/ossl_pkey.c b/ext/openssl/ossl_pkey.c index 95a2ea1ed..f9f5162e4 100644 --- a/ext/openssl/ossl_pkey.c +++ b/ext/openssl/ossl_pkey.c @@ -769,14 +769,14 @@ ossl_pkey_compare(VALUE self, VALUE other) if (EVP_PKEY_id(selfPKey) != EVP_PKEY_id(otherPKey)) ossl_raise(rb_eTypeError, "cannot match different PKey types"); - ret = EVP_PKEY_cmp(selfPKey, otherPKey); + ret = EVP_PKEY_eq(selfPKey, otherPKey); if (ret == 0) return Qfalse; else if (ret == 1) return Qtrue; else - ossl_raise(ePKeyError, "EVP_PKEY_cmp"); + ossl_raise(ePKeyError, "EVP_PKEY_eq"); } /* diff --git a/ext/openssl/ossl_ssl.c b/ext/openssl/ossl_ssl.c index a0f18d538..282865745 100644 --- a/ext/openssl/ossl_ssl.c +++ b/ext/openssl/ossl_ssl.c @@ -1229,7 +1229,7 @@ ossl_sslctx_add_certificate(int argc, VALUE *argv, VALUE self) EVP_PKEY_free(pub_pkey); if (!pub_pkey) rb_raise(rb_eArgError, "certificate does not contain public key"); - if (EVP_PKEY_cmp(pub_pkey, pkey) != 1) + if (EVP_PKEY_eq(pub_pkey, pkey) != 1) rb_raise(rb_eArgError, "public key mismatch"); if (argc >= 3) From 2d34e85ddfaad673f7c756b215726a304b757215 Mon Sep 17 00:00:00 2001 From: Kazuki Yamaguchi Date: Sun, 21 Mar 2021 00:20:04 +0900 Subject: [PATCH 12/13] 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 128ffabdd..5d17b13a3 100644 --- a/ext/openssl/ossl_bn.c +++ b/ext/openssl/ossl_bn.c @@ -826,12 +826,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) \ @@ -857,14 +851,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 @@ -1278,9 +1264,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 c36d6b89d..3f0622f94 100644 --- a/test/openssl/test_bn.rb +++ b/test/openssl/test_bn.rb @@ -248,6 +248,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 begin From 7c2fc00dee2e30c392c0671976e7edf555165222 Mon Sep 17 00:00:00 2001 From: Kazuki Yamaguchi Date: Sat, 23 Oct 2021 19:24:02 +0900 Subject: [PATCH 13/13] bn: expand BIGNUM_RAND and BIGNUM_RAND_RANGE macros Now that BN.pseudo_rand{,_range} are alias, those macros are only used once. Let's expand the macros for better readability. --- ext/openssl/ossl_bn.c | 100 +++++++++++++++++++++--------------------- 1 file changed, 50 insertions(+), 50 deletions(-) diff --git a/ext/openssl/ossl_bn.c b/ext/openssl/ossl_bn.c index 5d17b13a3..56fa0ec30 100644 --- a/ext/openssl/ossl_bn.c +++ b/ext/openssl/ossl_bn.c @@ -792,64 +792,64 @@ BIGNUM_SELF_SHIFT(lshift) */ BIGNUM_SELF_SHIFT(rshift) -#define BIGNUM_RAND(func) \ - static VALUE \ - ossl_bn_s_##func(int argc, VALUE *argv, VALUE klass) \ - { \ - BIGNUM *result; \ - int bottom = 0, top = 0, b; \ - VALUE bits, fill, odd, obj; \ - \ - switch (rb_scan_args(argc, argv, "12", &bits, &fill, &odd)) { \ - case 3: \ - bottom = (odd == Qtrue) ? 1 : 0; \ - /* FALLTHROUGH */ \ - case 2: \ - top = NUM2INT(fill); \ - } \ - b = NUM2INT(bits); \ - obj = NewBN(klass); \ - if (!(result = BN_new())) { \ - ossl_raise(eBNError, NULL); \ - } \ - if (BN_##func(result, b, top, bottom) <= 0) { \ - BN_free(result); \ - ossl_raise(eBNError, NULL); \ - } \ - SetBN(obj, result); \ - return obj; \ - } - /* - * Document-method: OpenSSL::BN.rand - * BN.rand(bits [, fill [, odd]]) -> aBN + * call-seq: + * BN.rand(bits [, fill [, odd]]) -> aBN + * + * Generates a cryptographically strong pseudo-random number of +bits+. + * + * See also the man page BN_rand(3). */ -BIGNUM_RAND(rand) - -#define BIGNUM_RAND_RANGE(func) \ - static VALUE \ - ossl_bn_s_##func##_range(VALUE klass, VALUE range) \ - { \ - BIGNUM *bn = GetBNPtr(range), *result; \ - VALUE obj = NewBN(klass); \ - if (!(result = BN_new())) { \ - ossl_raise(eBNError, NULL); \ - } \ - if (BN_##func##_range(result, bn) <= 0) { \ - BN_free(result); \ - ossl_raise(eBNError, NULL); \ - } \ - SetBN(obj, result); \ - return obj; \ +static VALUE +ossl_bn_s_rand(int argc, VALUE *argv, VALUE klass) +{ + BIGNUM *result; + int bottom = 0, top = 0, b; + VALUE bits, fill, odd, obj; + + switch (rb_scan_args(argc, argv, "12", &bits, &fill, &odd)) { + case 3: + bottom = (odd == Qtrue) ? 1 : 0; + /* FALLTHROUGH */ + case 2: + top = NUM2INT(fill); + } + b = NUM2INT(bits); + obj = NewBN(klass); + if (!(result = BN_new())) { + ossl_raise(eBNError, "BN_new"); + } + if (BN_rand(result, b, top, bottom) <= 0) { + BN_free(result); + ossl_raise(eBNError, "BN_rand"); } + SetBN(obj, result); + return obj; +} /* - * Document-method: OpenSSL::BN.rand_range * call-seq: - * BN.rand_range(range) -> aBN + * BN.rand_range(range) -> aBN * + * Generates a cryptographically strong pseudo-random number in the range + * 0...+range+. + * + * See also the man page BN_rand_range(3). */ -BIGNUM_RAND_RANGE(rand) +static VALUE +ossl_bn_s_rand_range(VALUE klass, VALUE range) +{ + BIGNUM *bn = GetBNPtr(range), *result; + VALUE obj = NewBN(klass); + if (!(result = BN_new())) + ossl_raise(eBNError, "BN_new"); + if (BN_rand_range(result, bn) <= 0) { + BN_free(result); + ossl_raise(eBNError, "BN_rand_range"); + } + SetBN(obj, result); + return obj; +} /* * call-seq: