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 73116c78c715a7277cbace7d8595c823d5ef1934 Mon Sep 17 00:00:00 2001 From: Pavel Valena Date: Thu, 20 May 2021 19:10:20 +0200 Subject: [PATCH] Compatibiblity with gem version 2.2.0 --- ext/openssl/ossl_pkey_rsa.c | 1 - 1 file changed, 1 deletion(-) diff --git a/ext/openssl/ossl_pkey_rsa.c b/ext/openssl/ossl_pkey_rsa.c index a928e92..6a57238 100644 --- a/ext/openssl/ossl_pkey_rsa.c +++ b/ext/openssl/ossl_pkey_rsa.c @@ -918,7 +918,6 @@ Init_ossl_rsa(void) rb_define_method(cRSA, "params", ossl_rsa_get_params, 0); DefRSAConst(PKCS1_PADDING); - DefRSAConst(SSLV23_PADDING); DefRSAConst(NO_PADDING); DefRSAConst(PKCS1_OAEP_PADDING); -- 2.31.1 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|