1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

openssl: import v2.2.1

Bring the local copy of ruby/openssl in sync with the upstream gem
release v2.2.1. The commits happened in the upstream repository can be
found at:

	https://github.com/ruby/openssl/compare/v2.2.0...v2.2.1

Note that many of these have already been applied to ruby.git and don't
appear in the file changes of this commit.
This commit is contained in:
Kazuki Yamaguchi 2021-09-28 18:03:24 +09:00 committed by nagachika
parent 5427b08381
commit 00e89fe36b
18 changed files with 375 additions and 102 deletions

View file

@ -1,3 +1,20 @@
Version 2.2.1
=============
Merged changes in 2.1.3. Additionally, the following issues are fixed by this
release.
Bug fixes
---------
* Fix crash in `OpenSSL::Timestamp::{Request,Response,TokenInfo}.new` when
invalid arguments are given.
[[GitHub #407]](https://github.com/ruby/openssl/pull/407)
* Fix `OpenSSL::Timestamp::Factory#create_timestamp` with LibreSSL on platforms
where `time_t` has a different size from `long`.
[[GitHub #454]](https://github.com/ruby/openssl/pull/454)
Version 2.2.0 Version 2.2.0
============= =============
@ -75,6 +92,42 @@ Notable changes
[[GitHub #297]](https://github.com/ruby/openssl/pull/297) [[GitHub #297]](https://github.com/ruby/openssl/pull/297)
Version 2.1.3
=============
Bug fixes
---------
* Fix deprecation warnings on Ruby 3.0.
* Add ".include" directive support in `OpenSSL::Config`.
[[GitHub #216]](https://github.com/ruby/openssl/pull/216)
* Fix handling of IPv6 address SANs.
[[GitHub #185]](https://github.com/ruby/openssl/pull/185)
* Hostname verification failure with `OpenSSL::SSL::SSLContext#verify_hostname=`
sets a proper error code.
[[GitHub #350]](https://github.com/ruby/openssl/pull/350)
* Fix crash with `OpenSSL::BN.new(nil, 2)`.
[[Bug #15760]](https://bugs.ruby-lang.org/issues/15760)
* `OpenSSL::SSL::SSLSocket#sys{read,write}` prevent internal string buffers from
being modified by another thread.
[[GitHub #453]](https://github.com/ruby/openssl/pull/453)
* Fix misuse of input record separator in `OpenSSL::Buffering` where it was
for output.
* Fix wrong interger casting in `OpenSSL::PKey::EC#dsa_verify_asn1`.
[[GitHub #460]](https://github.com/ruby/openssl/pull/460)
* `extconf.rb` explicitly checks that OpenSSL's version number is 1.0.1 or
newer but also less than 3.0. Ruby/OpenSSL v2.1.x and v2.2.x will not support
OpenSSL 3.0 API.
[[GitHub #458]](https://github.com/ruby/openssl/pull/458)
* Activate `digest` gem correctly. `digest` library could go into an
inconsistent state if there are multiple versions of `digest` is installed
and `openssl` is `require`d before `digest`.
[[GitHub #463]](https://github.com/ruby/openssl/pull/463)
* Fix GC.compact compatibility.
[[GitHub #464]](https://github.com/ruby/openssl/issues/464)
[[GitHub #465]](https://github.com/ruby/openssl/pull/465)
Version 2.1.2 Version 2.1.2
============= =============

View file

@ -33,9 +33,6 @@ if $mswin || $mingw
have_library("ws2_32") have_library("ws2_32")
end end
Logging::message "=== Checking for required stuff... ===\n"
result = pkg_config("openssl") && have_header("openssl/ssl.h")
if $mingw if $mingw
append_cflags '-D_FORTIFY_SOURCE=2' append_cflags '-D_FORTIFY_SOURCE=2'
append_ldflags '-fstack-protector' append_ldflags '-fstack-protector'
@ -92,19 +89,33 @@ def find_openssl_library
return false return false
end end
unless result Logging::message "=== Checking for required stuff... ===\n"
unless find_openssl_library pkg_config_found = pkg_config("openssl") && have_header("openssl/ssl.h")
Logging::message "=== Checking for required stuff failed. ===\n"
Logging::message "Makefile wasn't created. Fix the errors above.\n" if !pkg_config_found && !find_openssl_library
raise "OpenSSL library could not be found. You might want to use " \ Logging::message "=== Checking for required stuff failed. ===\n"
"--with-openssl-dir=<dir> option to specify the prefix where OpenSSL " \ Logging::message "Makefile wasn't created. Fix the errors above.\n"
"is installed." raise "OpenSSL library could not be found. You might want to use " \
end "--with-openssl-dir=<dir> option to specify the prefix where OpenSSL " \
"is installed."
end end
unless checking_for("OpenSSL version is 1.0.1 or later") { version_ok = if have_macro("LIBRESSL_VERSION_NUMBER", "openssl/opensslv.h")
try_static_assert("OPENSSL_VERSION_NUMBER >= 0x10001000L", "openssl/opensslv.h") } is_libressl = true
raise "OpenSSL >= 1.0.1 or LibreSSL is required" checking_for("LibreSSL version >= 2.5.0") {
try_static_assert("LIBRESSL_VERSION_NUMBER >= 0x20500000L", "openssl/opensslv.h") }
else
checking_for("OpenSSL version >= 1.0.1 and < 3.0.0") {
try_static_assert("OPENSSL_VERSION_NUMBER >= 0x10001000L", "openssl/opensslv.h") &&
!try_static_assert("OPENSSL_VERSION_MAJOR >= 3", "openssl/opensslv.h") }
end
unless version_ok
raise "OpenSSL >= 1.0.1, < 3.0.0 or LibreSSL >= 2.5.0 is required"
end
# Prevent wincrypt.h from being included, which defines conflicting macro with openssl/x509.h
if is_libressl && ($mswin || $mingw)
$defs.push("-DNOCRYPT")
end end
Logging::message "=== Checking for OpenSSL features... ===\n" Logging::message "=== Checking for OpenSSL features... ===\n"
@ -116,10 +127,6 @@ engines.each { |name|
have_func("ENGINE_load_#{name}()", "openssl/engine.h") have_func("ENGINE_load_#{name}()", "openssl/engine.h")
} }
if ($mswin || $mingw) && have_macro("LIBRESSL_VERSION_NUMBER", "openssl/opensslv.h")
$defs.push("-DNOCRYPT")
end
# added in 1.0.2 # added in 1.0.2
have_func("EC_curve_nist2nid") have_func("EC_curve_nist2nid")
have_func("X509_REVOKED_dup") have_func("X509_REVOKED_dup")

View file

@ -1,5 +1,5 @@
# frozen_string_literal: true # frozen_string_literal: true
module OpenSSL module OpenSSL
VERSION = "2.2.0" VERSION = "2.2.1"
end end

View file

@ -1,6 +1,6 @@
Gem::Specification.new do |spec| Gem::Specification.new do |spec|
spec.name = "openssl" spec.name = "openssl"
spec.version = "2.2.0" spec.version = "2.2.1"
spec.authors = ["Martin Bosslet", "SHIBATA Hiroshi", "Zachary Scott", "Kazuki Yamaguchi"] spec.authors = ["Martin Bosslet", "SHIBATA Hiroshi", "Zachary Scott", "Kazuki Yamaguchi"]
spec.email = ["ruby-core@ruby-lang.org"] spec.email = ["ruby-core@ruby-lang.org"]
spec.summary = %q{OpenSSL provides SSL, TLS and general purpose cryptography.} spec.summary = %q{OpenSSL provides SSL, TLS and general purpose cryptography.}
@ -17,6 +17,7 @@ Gem::Specification.new do |spec|
spec.required_ruby_version = ">= 2.3.0" spec.required_ruby_version = ">= 2.3.0"
spec.add_runtime_dependency "ipaddr"
spec.add_development_dependency "rake" spec.add_development_dependency "rake"
spec.add_development_dependency "rake-compiler" spec.add_development_dependency "rake-compiler"
spec.add_development_dependency "test-unit", "~> 3.0" spec.add_development_dependency "test-unit", "~> 3.0"

View file

@ -453,7 +453,7 @@ ossl_bn_is_negative(VALUE self)
if (!(result = BN_new())) { \ if (!(result = BN_new())) { \
ossl_raise(eBNError, NULL); \ ossl_raise(eBNError, NULL); \
} \ } \
if (!BN_##func(result, bn, ossl_bn_ctx)) { \ if (BN_##func(result, bn, ossl_bn_ctx) <= 0) { \
BN_free(result); \ BN_free(result); \
ossl_raise(eBNError, NULL); \ ossl_raise(eBNError, NULL); \
} \ } \
@ -479,7 +479,7 @@ BIGNUM_1c(sqr)
if (!(result = BN_new())) { \ if (!(result = BN_new())) { \
ossl_raise(eBNError, NULL); \ ossl_raise(eBNError, NULL); \
} \ } \
if (!BN_##func(result, bn1, bn2)) { \ if (BN_##func(result, bn1, bn2) <= 0) { \
BN_free(result); \ BN_free(result); \
ossl_raise(eBNError, NULL); \ ossl_raise(eBNError, NULL); \
} \ } \
@ -512,7 +512,7 @@ BIGNUM_2(sub)
if (!(result = BN_new())) { \ if (!(result = BN_new())) { \
ossl_raise(eBNError, NULL); \ ossl_raise(eBNError, NULL); \
} \ } \
if (!BN_##func(result, bn1, bn2, ossl_bn_ctx)) { \ if (BN_##func(result, bn1, bn2, ossl_bn_ctx) <= 0) { \
BN_free(result); \ BN_free(result); \
ossl_raise(eBNError, NULL); \ ossl_raise(eBNError, NULL); \
} \ } \
@ -556,11 +556,21 @@ BIGNUM_2c(gcd)
BIGNUM_2c(mod_sqr) BIGNUM_2c(mod_sqr)
/* /*
* Document-method: OpenSSL::BN#mod_inverse
* call-seq: * call-seq:
* bn.mod_inverse(bn2) => aBN * bn.mod_inverse(bn2) => aBN
*/ */
BIGNUM_2c(mod_inverse) static VALUE
ossl_bn_mod_inverse(VALUE self, VALUE other)
{
BIGNUM *bn1, *bn2 = GetBNPtr(other), *result;
VALUE obj;
GetBN(self, bn1);
obj = NewBN(rb_obj_class(self));
if (!(result = BN_mod_inverse(NULL, bn1, bn2, ossl_bn_ctx)))
ossl_raise(eBNError, "BN_mod_inverse");
SetBN(obj, result);
return obj;
}
/* /*
* call-seq: * call-seq:
@ -609,7 +619,7 @@ ossl_bn_div(VALUE self, VALUE other)
if (!(result = BN_new())) { \ if (!(result = BN_new())) { \
ossl_raise(eBNError, NULL); \ ossl_raise(eBNError, NULL); \
} \ } \
if (!BN_##func(result, bn1, bn2, bn3, ossl_bn_ctx)) { \ if (BN_##func(result, bn1, bn2, bn3, ossl_bn_ctx) <= 0) { \
BN_free(result); \ BN_free(result); \
ossl_raise(eBNError, NULL); \ ossl_raise(eBNError, NULL); \
} \ } \
@ -651,7 +661,7 @@ BIGNUM_3c(mod_exp)
{ \ { \
BIGNUM *bn; \ BIGNUM *bn; \
GetBN(self, bn); \ GetBN(self, bn); \
if (!BN_##func(bn, NUM2INT(bit))) { \ if (BN_##func(bn, NUM2INT(bit)) <= 0) { \
ossl_raise(eBNError, NULL); \ ossl_raise(eBNError, NULL); \
} \ } \
return self; \ return self; \
@ -711,7 +721,7 @@ ossl_bn_is_bit_set(VALUE self, VALUE bit)
if (!(result = BN_new())) { \ if (!(result = BN_new())) { \
ossl_raise(eBNError, NULL); \ ossl_raise(eBNError, NULL); \
} \ } \
if (!BN_##func(result, bn, b)) { \ if (BN_##func(result, bn, b) <= 0) { \
BN_free(result); \ BN_free(result); \
ossl_raise(eBNError, NULL); \ ossl_raise(eBNError, NULL); \
} \ } \
@ -741,7 +751,7 @@ BIGNUM_SHIFT(rshift)
int b; \ int b; \
b = NUM2INT(bits); \ b = NUM2INT(bits); \
GetBN(self, bn); \ GetBN(self, bn); \
if (!BN_##func(bn, bn, b)) \ if (BN_##func(bn, bn, b) <= 0) \
ossl_raise(eBNError, NULL); \ ossl_raise(eBNError, NULL); \
return self; \ return self; \
} }
@ -780,7 +790,7 @@ BIGNUM_SELF_SHIFT(rshift)
if (!(result = BN_new())) { \ if (!(result = BN_new())) { \
ossl_raise(eBNError, NULL); \ ossl_raise(eBNError, NULL); \
} \ } \
if (!BN_##func(result, b, top, bottom)) { \ if (BN_##func(result, b, top, bottom) <= 0) { \
BN_free(result); \ BN_free(result); \
ossl_raise(eBNError, NULL); \ ossl_raise(eBNError, NULL); \
} \ } \
@ -809,7 +819,7 @@ BIGNUM_RAND(pseudo_rand)
if (!(result = BN_new())) { \ if (!(result = BN_new())) { \
ossl_raise(eBNError, NULL); \ ossl_raise(eBNError, NULL); \
} \ } \
if (!BN_##func##_range(result, bn)) { \ if (BN_##func##_range(result, bn) <= 0) { \
BN_free(result); \ BN_free(result); \
ossl_raise(eBNError, NULL); \ ossl_raise(eBNError, NULL); \
} \ } \

View file

@ -813,6 +813,31 @@ ossl_cipher_block_size(VALUE self)
return INT2NUM(EVP_CIPHER_CTX_block_size(ctx)); return INT2NUM(EVP_CIPHER_CTX_block_size(ctx));
} }
/*
* call-seq:
* cipher.ccm_data_len = integer -> integer
*
* Sets the length of the plaintext / ciphertext message that will be
* processed in CCM mode. Make sure to call this method after #key= and
* #iv= have been set, and before #auth_data=.
*
* Only call this method after calling Cipher#encrypt or Cipher#decrypt.
*/
static VALUE
ossl_cipher_set_ccm_data_len(VALUE self, VALUE data_len)
{
int in_len, out_len;
EVP_CIPHER_CTX *ctx;
in_len = NUM2INT(data_len);
GetCipher(self, ctx);
if (EVP_CipherUpdate(ctx, NULL, &out_len, NULL, in_len) != 1)
ossl_raise(eCipherError, NULL);
return data_len;
}
/* /*
* INIT * INIT
*/ */
@ -1043,6 +1068,7 @@ Init_ossl_cipher(void)
rb_define_method(cCipher, "iv_len", ossl_cipher_iv_length, 0); rb_define_method(cCipher, "iv_len", ossl_cipher_iv_length, 0);
rb_define_method(cCipher, "block_size", ossl_cipher_block_size, 0); rb_define_method(cCipher, "block_size", ossl_cipher_block_size, 0);
rb_define_method(cCipher, "padding=", ossl_cipher_set_padding, 1); rb_define_method(cCipher, "padding=", ossl_cipher_set_padding, 1);
rb_define_method(cCipher, "ccm_data_len=", ossl_cipher_set_ccm_data_len, 1);
id_auth_tag_len = rb_intern_const("auth_tag_len"); id_auth_tag_len = rb_intern_const("auth_tag_len");
id_key_set = rb_intern_const("key_set"); id_key_set = rb_intern_const("key_set");

View file

@ -313,8 +313,6 @@ ossl_digest_block_length(VALUE self)
void void
Init_ossl_digest(void) Init_ossl_digest(void)
{ {
rb_require("digest");
#if 0 #if 0
mOSSL = rb_define_module("OpenSSL"); mOSSL = rb_define_module("OpenSSL");
eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError); eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
@ -398,6 +396,12 @@ Init_ossl_digest(void)
* digest2 = sha256.digest(data2) * digest2 = sha256.digest(data2)
* *
*/ */
/*
* Digest::Class is defined by the digest library. rb_require() cannot be
* used here because it bypasses RubyGems.
*/
rb_funcall(Qnil, rb_intern_const("require"), 1, rb_str_new_cstr("digest"));
cDigest = rb_define_class_under(mOSSL, "Digest", rb_path2class("Digest::Class")); cDigest = rb_define_class_under(mOSSL, "Digest", rb_path2class("Digest::Class"));
/* Document-class: OpenSSL::Digest::DigestError /* Document-class: OpenSSL::Digest::DigestError
* *

View file

@ -653,15 +653,15 @@ static VALUE ossl_ec_key_dsa_verify_asn1(VALUE self, VALUE data, VALUE sig)
StringValue(data); StringValue(data);
StringValue(sig); StringValue(sig);
switch (ECDSA_verify(0, (unsigned char *) RSTRING_PTR(data), RSTRING_LENINT(data), (unsigned char *) RSTRING_PTR(sig), (int)RSTRING_LEN(sig), ec)) { switch (ECDSA_verify(0, (unsigned char *)RSTRING_PTR(data), RSTRING_LENINT(data),
case 1: return Qtrue; (unsigned char *)RSTRING_PTR(sig), RSTRING_LENINT(sig), ec)) {
case 0: return Qfalse; case 1:
default: break; return Qtrue;
case 0:
return Qfalse;
default:
ossl_raise(eECError, "ECDSA_verify");
} }
ossl_raise(eECError, "ECDSA_verify");
UNREACHABLE;
} }
/* /*

View file

@ -13,6 +13,12 @@
#define numberof(ary) (int)(sizeof(ary)/sizeof((ary)[0])) #define numberof(ary) (int)(sizeof(ary)/sizeof((ary)[0]))
#if !defined(TLS1_3_VERSION) && \
defined(LIBRESSL_VERSION_NUMBER) && \
LIBRESSL_VERSION_NUMBER >= 0x3020000fL
# define TLS1_3_VERSION 0x0304
#endif
#ifdef _WIN32 #ifdef _WIN32
# define TO_SOCKET(s) _get_osfhandle(s) # define TO_SOCKET(s) _get_osfhandle(s)
#else #else
@ -33,7 +39,7 @@ static VALUE eSSLErrorWaitReadable;
static VALUE eSSLErrorWaitWritable; static VALUE eSSLErrorWaitWritable;
static ID id_call, ID_callback_state, id_tmp_dh_callback, id_tmp_ecdh_callback, static ID id_call, ID_callback_state, id_tmp_dh_callback, id_tmp_ecdh_callback,
id_npn_protocols_encoded; id_npn_protocols_encoded, id_each;
static VALUE sym_exception, sym_wait_readable, sym_wait_writable; static VALUE sym_exception, sym_wait_readable, sym_wait_writable;
static ID id_i_cert_store, id_i_ca_file, id_i_ca_path, id_i_verify_mode, static ID id_i_cert_store, id_i_ca_file, id_i_ca_path, id_i_verify_mode,
@ -53,6 +59,13 @@ static int ossl_sslctx_ex_ptr_idx;
static int ossl_sslctx_ex_store_p; static int ossl_sslctx_ex_store_p;
#endif #endif
static void
ossl_sslctx_mark(void *ptr)
{
SSL_CTX *ctx = ptr;
rb_gc_mark((VALUE)SSL_CTX_get_ex_data(ctx, ossl_sslctx_ex_ptr_idx));
}
static void static void
ossl_sslctx_free(void *ptr) ossl_sslctx_free(void *ptr)
{ {
@ -67,7 +80,7 @@ ossl_sslctx_free(void *ptr)
static const rb_data_type_t ossl_sslctx_type = { static const rb_data_type_t ossl_sslctx_type = {
"OpenSSL/SSL/CTX", "OpenSSL/SSL/CTX",
{ {
0, ossl_sslctx_free, ossl_sslctx_mark, ossl_sslctx_free,
}, },
0, 0, RUBY_TYPED_FREE_IMMEDIATELY, 0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
}; };
@ -616,7 +629,7 @@ static VALUE
ssl_encode_npn_protocols(VALUE protocols) ssl_encode_npn_protocols(VALUE protocols)
{ {
VALUE encoded = rb_str_new(NULL, 0); VALUE encoded = rb_str_new(NULL, 0);
rb_iterate(rb_each, protocols, ssl_npn_encode_protocol_i, encoded); rb_block_call(protocols, id_each, 0, 0, ssl_npn_encode_protocol_i, encoded);
return encoded; return encoded;
} }
@ -686,7 +699,7 @@ static int
ssl_npn_advertise_cb(SSL *ssl, const unsigned char **out, unsigned int *outlen, ssl_npn_advertise_cb(SSL *ssl, const unsigned char **out, unsigned int *outlen,
void *arg) void *arg)
{ {
VALUE protocols = (VALUE)arg; VALUE protocols = rb_attr_get((VALUE)arg, id_npn_protocols_encoded);
*out = (const unsigned char *) RSTRING_PTR(protocols); *out = (const unsigned char *) RSTRING_PTR(protocols);
*outlen = RSTRING_LENINT(protocols); *outlen = RSTRING_LENINT(protocols);
@ -908,7 +921,7 @@ ossl_sslctx_setup(VALUE self)
if (!NIL_P(val)) { if (!NIL_P(val)) {
VALUE encoded = ssl_encode_npn_protocols(val); VALUE encoded = ssl_encode_npn_protocols(val);
rb_ivar_set(self, id_npn_protocols_encoded, encoded); rb_ivar_set(self, id_npn_protocols_encoded, encoded);
SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_npn_advertise_cb, (void *)encoded); SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_npn_advertise_cb, (void *)self);
OSSL_Debug("SSL NPN advertise callback added"); OSSL_Debug("SSL NPN advertise callback added");
} }
if (RTEST(rb_attr_get(self, id_i_npn_select_cb))) { if (RTEST(rb_attr_get(self, id_i_npn_select_cb))) {
@ -1526,6 +1539,14 @@ ssl_started(SSL *ssl)
return SSL_get_fd(ssl) >= 0; return SSL_get_fd(ssl) >= 0;
} }
static void
ossl_ssl_mark(void *ptr)
{
SSL *ssl = ptr;
rb_gc_mark((VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx));
rb_gc_mark((VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_vcb_idx));
}
static void static void
ossl_ssl_free(void *ssl) ossl_ssl_free(void *ssl)
{ {
@ -1535,7 +1556,7 @@ ossl_ssl_free(void *ssl)
const rb_data_type_t ossl_ssl_type = { const rb_data_type_t ossl_ssl_type = {
"OpenSSL/SSL", "OpenSSL/SSL",
{ {
0, ossl_ssl_free, ossl_ssl_mark, ossl_ssl_free,
}, },
0, 0, RUBY_TYPED_FREE_IMMEDIATELY, 0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
}; };
@ -1691,6 +1712,11 @@ ossl_start_ssl(VALUE self, int (*func)(), const char *funcname, VALUE opts)
rb_io_wait_readable(fptr->fd); rb_io_wait_readable(fptr->fd);
continue; continue;
case SSL_ERROR_SYSCALL: case SSL_ERROR_SYSCALL:
#ifdef __APPLE__
/* See ossl_ssl_write_internal() */
if (errno == EPROTOTYPE)
continue;
#endif
if (errno) rb_sys_fail(funcname); if (errno) rb_sys_fail(funcname);
ossl_raise(eSSLError, "%s SYSCALL returned=%d errno=%d state=%s", funcname, ret2, errno, SSL_state_string_long(ssl)); ossl_raise(eSSLError, "%s SYSCALL returned=%d errno=%d state=%s", funcname, ret2, errno, SSL_state_string_long(ssl));
#if defined(SSL_R_CERTIFICATE_VERIFY_FAILED) #if defined(SSL_R_CERTIFICATE_VERIFY_FAILED)
@ -1847,26 +1873,36 @@ ossl_ssl_read_internal(int argc, VALUE *argv, VALUE self, int nonblock)
io = rb_attr_get(self, id_i_io); io = rb_attr_get(self, id_i_io);
GetOpenFile(io, fptr); GetOpenFile(io, fptr);
if (ssl_started(ssl)) { if (ssl_started(ssl)) {
for (;;){ rb_str_locktmp(str);
for (;;) {
nread = SSL_read(ssl, RSTRING_PTR(str), ilen); nread = SSL_read(ssl, RSTRING_PTR(str), ilen);
switch(ssl_get_error(ssl, nread)){ switch(ssl_get_error(ssl, nread)){
case SSL_ERROR_NONE: case SSL_ERROR_NONE:
rb_str_unlocktmp(str);
goto end; goto end;
case SSL_ERROR_ZERO_RETURN: case SSL_ERROR_ZERO_RETURN:
rb_str_unlocktmp(str);
if (no_exception_p(opts)) { return Qnil; } if (no_exception_p(opts)) { return Qnil; }
rb_eof_error(); rb_eof_error();
case SSL_ERROR_WANT_WRITE: case SSL_ERROR_WANT_WRITE:
if (no_exception_p(opts)) { return sym_wait_writable; } if (nonblock) {
write_would_block(nonblock); rb_str_unlocktmp(str);
if (no_exception_p(opts)) { return sym_wait_writable; }
write_would_block(nonblock);
}
rb_io_wait_writable(fptr->fd); rb_io_wait_writable(fptr->fd);
continue; continue;
case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_READ:
if (no_exception_p(opts)) { return sym_wait_readable; } if (nonblock) {
read_would_block(nonblock); rb_str_unlocktmp(str);
if (no_exception_p(opts)) { return sym_wait_readable; }
read_would_block(nonblock);
}
rb_io_wait_readable(fptr->fd); rb_io_wait_readable(fptr->fd);
continue; continue;
case SSL_ERROR_SYSCALL: case SSL_ERROR_SYSCALL:
if (!ERR_peek_error()) { if (!ERR_peek_error()) {
rb_str_unlocktmp(str);
if (errno) if (errno)
rb_sys_fail(0); rb_sys_fail(0);
else { else {
@ -1883,6 +1919,7 @@ ossl_ssl_read_internal(int argc, VALUE *argv, VALUE self, int nonblock)
} }
/* fall through */ /* fall through */
default: default:
rb_str_unlocktmp(str);
ossl_raise(eSSLError, "SSL_read"); ossl_raise(eSSLError, "SSL_read");
} }
} }
@ -1953,21 +1990,21 @@ ossl_ssl_write_internal(VALUE self, VALUE str, VALUE opts)
int nwrite = 0; int nwrite = 0;
rb_io_t *fptr; rb_io_t *fptr;
int nonblock = opts != Qfalse; int nonblock = opts != Qfalse;
VALUE io; VALUE tmp, io;
StringValue(str); tmp = rb_str_new_frozen(StringValue(str));
GetSSL(self, ssl); GetSSL(self, ssl);
io = rb_attr_get(self, id_i_io); io = rb_attr_get(self, id_i_io);
GetOpenFile(io, fptr); GetOpenFile(io, fptr);
if (ssl_started(ssl)) { if (ssl_started(ssl)) {
for (;;){ for (;;) {
int num = RSTRING_LENINT(str); int num = RSTRING_LENINT(tmp);
/* SSL_write(3ssl) manpage states num == 0 is undefined */ /* SSL_write(3ssl) manpage states num == 0 is undefined */
if (num == 0) if (num == 0)
goto end; goto end;
nwrite = SSL_write(ssl, RSTRING_PTR(str), num); nwrite = SSL_write(ssl, RSTRING_PTR(tmp), num);
switch(ssl_get_error(ssl, nwrite)){ switch(ssl_get_error(ssl, nwrite)){
case SSL_ERROR_NONE: case SSL_ERROR_NONE:
goto end; goto end;
@ -1982,6 +2019,16 @@ ossl_ssl_write_internal(VALUE self, VALUE str, VALUE opts)
rb_io_wait_readable(fptr->fd); rb_io_wait_readable(fptr->fd);
continue; continue;
case SSL_ERROR_SYSCALL: case SSL_ERROR_SYSCALL:
#ifdef __APPLE__
/*
* It appears that send syscall can return EPROTOTYPE if the
* socket is being torn down. Retry to get a proper errno to
* make the error handling in line with the socket library.
* [Bug #14713] https://bugs.ruby-lang.org/issues/14713
*/
if (errno == EPROTOTYPE)
continue;
#endif
if (errno) rb_sys_fail(0); if (errno) rb_sys_fail(0);
default: default:
ossl_raise(eSSLError, "SSL_write"); ossl_raise(eSSLError, "SSL_write");
@ -2997,6 +3044,7 @@ Init_ossl_ssl(void)
id_tmp_dh_callback = rb_intern_const("tmp_dh_callback"); id_tmp_dh_callback = rb_intern_const("tmp_dh_callback");
id_tmp_ecdh_callback = rb_intern_const("tmp_ecdh_callback"); id_tmp_ecdh_callback = rb_intern_const("tmp_ecdh_callback");
id_npn_protocols_encoded = rb_intern_const("npn_protocols_encoded"); id_npn_protocols_encoded = rb_intern_const("npn_protocols_encoded");
id_each = rb_intern_const("each");
#define DefIVarID(name) do \ #define DefIVarID(name) do \
id_i_##name = rb_intern_const("@"#name); while (0) id_i_##name = rb_intern_const("@"#name); while (0)

View file

@ -205,8 +205,10 @@ ossl_ts_req_initialize(int argc, VALUE *argv, VALUE self)
in = ossl_obj2bio(&arg); in = ossl_obj2bio(&arg);
ts_req = d2i_TS_REQ_bio(in, &ts_req); ts_req = d2i_TS_REQ_bio(in, &ts_req);
BIO_free(in); BIO_free(in);
if (!ts_req) if (!ts_req) {
DATA_PTR(self) = NULL;
ossl_raise(eTimestampError, "Error when decoding the timestamp request"); ossl_raise(eTimestampError, "Error when decoding the timestamp request");
}
DATA_PTR(self) = ts_req; DATA_PTR(self) = ts_req;
return self; return self;
@ -529,8 +531,10 @@ ossl_ts_resp_initialize(VALUE self, VALUE der)
in = ossl_obj2bio(&der); in = ossl_obj2bio(&der);
ts_resp = d2i_TS_RESP_bio(in, &ts_resp); ts_resp = d2i_TS_RESP_bio(in, &ts_resp);
BIO_free(in); BIO_free(in);
if (!ts_resp) if (!ts_resp) {
DATA_PTR(self) = NULL;
ossl_raise(eTimestampError, "Error when decoding the timestamp response"); ossl_raise(eTimestampError, "Error when decoding the timestamp response");
}
DATA_PTR(self) = ts_resp; DATA_PTR(self) = ts_resp;
return self; return self;
@ -871,8 +875,10 @@ ossl_ts_token_info_initialize(VALUE self, VALUE der)
in = ossl_obj2bio(&der); in = ossl_obj2bio(&der);
info = d2i_TS_TST_INFO_bio(in, &info); info = d2i_TS_TST_INFO_bio(in, &info);
BIO_free(in); BIO_free(in);
if (!info) if (!info) {
DATA_PTR(self) = NULL;
ossl_raise(eTimestampError, "Error when decoding the timestamp token info"); ossl_raise(eTimestampError, "Error when decoding the timestamp token info");
}
DATA_PTR(self) = info; DATA_PTR(self) = info;
return self; return self;
@ -1074,7 +1080,11 @@ ossl_tsfac_serial_cb(struct TS_resp_ctx *ctx, void *data)
} }
static int static int
#if !defined(LIBRESSL_VERSION_NUMBER)
ossl_tsfac_time_cb(struct TS_resp_ctx *ctx, void *data, long *sec, long *usec) ossl_tsfac_time_cb(struct TS_resp_ctx *ctx, void *data, long *sec, long *usec)
#else
ossl_tsfac_time_cb(struct TS_resp_ctx *ctx, void *data, time_t *sec, long *usec)
#endif
{ {
*sec = *((long *)data); *sec = *((long *)data);
*usec = 0; *usec = 0;

View file

@ -105,6 +105,13 @@ VALUE cX509Store;
VALUE cX509StoreContext; VALUE cX509StoreContext;
VALUE eX509StoreError; VALUE eX509StoreError;
static void
ossl_x509store_mark(void *ptr)
{
X509_STORE *store = ptr;
rb_gc_mark((VALUE)X509_STORE_get_ex_data(store, store_ex_verify_cb_idx));
}
static void static void
ossl_x509store_free(void *ptr) ossl_x509store_free(void *ptr)
{ {
@ -114,7 +121,7 @@ ossl_x509store_free(void *ptr)
static const rb_data_type_t ossl_x509store_type = { static const rb_data_type_t ossl_x509store_type = {
"OpenSSL/X509/STORE", "OpenSSL/X509/STORE",
{ {
0, ossl_x509store_free, ossl_x509store_mark, ossl_x509store_free,
}, },
0, 0, RUBY_TYPED_FREE_IMMEDIATELY, 0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
}; };
@ -456,23 +463,16 @@ ossl_x509store_verify(int argc, VALUE *argv, VALUE self)
return result; return result;
} }
/*
* Public Functions
*/
static void ossl_x509stctx_free(void*);
static const rb_data_type_t ossl_x509stctx_type = {
"OpenSSL/X509/STORE_CTX",
{
0, ossl_x509stctx_free,
},
0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
};
/* /*
* Private functions * Private functions
*/ */
static void
ossl_x509stctx_mark(void *ptr)
{
X509_STORE_CTX *ctx = ptr;
rb_gc_mark((VALUE)X509_STORE_CTX_get_ex_data(ctx, stctx_ex_verify_cb_idx));
}
static void static void
ossl_x509stctx_free(void *ptr) ossl_x509stctx_free(void *ptr)
{ {
@ -484,6 +484,14 @@ ossl_x509stctx_free(void *ptr)
X509_STORE_CTX_free(ctx); X509_STORE_CTX_free(ctx);
} }
static const rb_data_type_t ossl_x509stctx_type = {
"OpenSSL/X509/STORE_CTX",
{
ossl_x509stctx_mark, ossl_x509stctx_free,
},
0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
};
static VALUE static VALUE
ossl_x509stctx_alloc(VALUE klass) ossl_x509stctx_alloc(VALUE klass)
{ {
@ -517,7 +525,9 @@ static VALUE ossl_x509stctx_set_time(VALUE, VALUE);
/* /*
* call-seq: * call-seq:
* StoreContext.new(store, cert = nil, chain = nil) * StoreContext.new(store, cert = nil, untrusted = nil)
*
* Sets up a StoreContext for a verification of the X.509 certificate _cert_.
*/ */
static VALUE static VALUE
ossl_x509stctx_initialize(int argc, VALUE *argv, VALUE self) ossl_x509stctx_initialize(int argc, VALUE *argv, VALUE self)
@ -527,15 +537,24 @@ ossl_x509stctx_initialize(int argc, VALUE *argv, VALUE self)
X509_STORE *x509st; X509_STORE *x509st;
X509 *x509 = NULL; X509 *x509 = NULL;
STACK_OF(X509) *x509s = NULL; STACK_OF(X509) *x509s = NULL;
int state;
rb_scan_args(argc, argv, "12", &store, &cert, &chain); rb_scan_args(argc, argv, "12", &store, &cert, &chain);
GetX509StCtx(self, ctx); GetX509StCtx(self, ctx);
GetX509Store(store, x509st); GetX509Store(store, x509st);
if(!NIL_P(cert)) x509 = DupX509CertPtr(cert); /* NEED TO DUP */ if (!NIL_P(cert))
if(!NIL_P(chain)) x509s = ossl_x509_ary2sk(chain); x509 = DupX509CertPtr(cert); /* NEED TO DUP */
if(X509_STORE_CTX_init(ctx, x509st, x509, x509s) != 1){ if (!NIL_P(chain)) {
x509s = ossl_protect_x509_ary2sk(chain, &state);
if (state) {
X509_free(x509);
rb_jump_tag(state);
}
}
if (X509_STORE_CTX_init(ctx, x509st, x509, x509s) != 1){
X509_free(x509);
sk_X509_pop_free(x509s, X509_free); sk_X509_pop_free(x509s, X509_free);
ossl_raise(eX509StoreError, NULL); ossl_raise(eX509StoreError, "X509_STORE_CTX_init");
} }
if (!NIL_P(t = rb_iv_get(store, "@time"))) if (!NIL_P(t = rb_iv_get(store, "@time")))
ossl_x509stctx_set_time(self, t); ossl_x509stctx_set_time(self, t);

View file

@ -174,6 +174,48 @@ class OpenSSL::TestCipher < OpenSSL::TestCase
assert_not_predicate(cipher, :authenticated?) assert_not_predicate(cipher, :authenticated?)
end end
def test_aes_ccm
# RFC 3610 Section 8, Test Case 1
key = ["c0c1c2c3c4c5c6c7c8c9cacbcccdcecf"].pack("H*")
iv = ["00000003020100a0a1a2a3a4a5"].pack("H*")
aad = ["0001020304050607"].pack("H*")
pt = ["08090a0b0c0d0e0f101112131415161718191a1b1c1d1e"].pack("H*")
ct = ["588c979a61c663d2f066d0c2c0f989806d5f6b61dac384"].pack("H*")
tag = ["17e8d12cfdf926e0"].pack("H*")
kwargs = {auth_tag_len: 8, iv_len: 13, key: key, iv: iv}
cipher = new_encryptor("aes-128-ccm", **kwargs, ccm_data_len: pt.length, auth_data: aad)
assert_equal ct, cipher.update(pt) << cipher.final
assert_equal tag, cipher.auth_tag
cipher = new_decryptor("aes-128-ccm", **kwargs, ccm_data_len: ct.length, auth_tag: tag, auth_data: aad)
assert_equal pt, cipher.update(ct) << cipher.final
# truncated tag is accepted
cipher = new_encryptor("aes-128-ccm", **kwargs, ccm_data_len: pt.length, auth_data: aad)
assert_equal ct, cipher.update(pt) << cipher.final
assert_equal tag[0, 8], cipher.auth_tag(8)
cipher = new_decryptor("aes-128-ccm", **kwargs, ccm_data_len: ct.length, auth_tag: tag[0, 8], auth_data: aad)
assert_equal pt, cipher.update(ct) << cipher.final
# wrong tag is rejected
tag2 = tag.dup
tag2.setbyte(-1, (tag2.getbyte(-1) + 1) & 0xff)
cipher = new_decryptor("aes-128-ccm", **kwargs, ccm_data_len: ct.length, auth_tag: tag2, auth_data: aad)
assert_raise(OpenSSL::Cipher::CipherError) { cipher.update(ct) }
# wrong aad is rejected
aad2 = aad[0..-2] << aad[-1].succ
cipher = new_decryptor("aes-128-ccm", **kwargs, ccm_data_len: ct.length, auth_tag: tag, auth_data: aad2)
assert_raise(OpenSSL::Cipher::CipherError) { cipher.update(ct) }
# wrong ciphertext is rejected
ct2 = ct[0..-2] << ct[-1].succ
cipher = new_decryptor("aes-128-ccm", **kwargs, ccm_data_len: ct2.length, auth_tag: tag, auth_data: aad)
assert_raise(OpenSSL::Cipher::CipherError) { cipher.update(ct2) }
end if has_cipher?("aes-128-ccm") &&
OpenSSL::Cipher.new("aes-128-ccm").authenticated? &&
OpenSSL::OPENSSL_VERSION_NUMBER >= 0x10101000 # version >= v1.1.1
def test_aes_gcm def test_aes_gcm
# GCM spec Appendix B Test Case 4 # GCM spec Appendix B Test Case 4
key = ["feffe9928665731c6d6a8f9467308308"].pack("H*") key = ["feffe9928665731c6d6a8f9467308308"].pack("H*")

View file

@ -61,14 +61,14 @@ foo\\bar::foo\\bar = baz
[default1 default2]\t\t # space is allowed in section name [default1 default2]\t\t # space is allowed in section name
fo =b ar # space allowed in value fo =b ar # space allowed in value
[emptysection] [emptysection]
[doller ] [dollar ]
foo=bar foo=bar
bar = $(foo) bar = $(foo)
baz = 123$(default::bar)456${foo}798 baz = 123$(default::bar)456${foo}798
qux = ${baz} qux = ${baz}
quxx = $qux.$qux quxx = $qux.$qux
__EOC__ __EOC__
assert_equal(['default', 'default1 default2', 'doller', 'emptysection', 'foo', 'foo\\bar'], c.sections.sort) assert_equal(['default', 'default1 default2', 'dollar', 'emptysection', 'foo', 'foo\\bar'], c.sections.sort)
assert_equal(['', 'a', 'bar', 'baz', 'd', 'dq', 'dq2', 'esc', 'foo\\bar', 'sq'], c['default'].keys.sort) assert_equal(['', 'a', 'bar', 'baz', 'd', 'dq', 'dq2', 'esc', 'foo\\bar', 'sq'], c['default'].keys.sort)
assert_equal('c', c['default']['']) assert_equal('c', c['default'][''])
assert_equal('', c['default']['a']) assert_equal('', c['default']['a'])
@ -84,12 +84,12 @@ __EOC__
assert_equal('baz', c['foo\\bar']['foo\\bar']) assert_equal('baz', c['foo\\bar']['foo\\bar'])
assert_equal('b ar', c['default1 default2']['fo']) assert_equal('b ar', c['default1 default2']['fo'])
# dolloer # dollar
assert_equal('bar', c['doller']['foo']) assert_equal('bar', c['dollar']['foo'])
assert_equal('bar', c['doller']['bar']) assert_equal('bar', c['dollar']['bar'])
assert_equal('123baz456bar798', c['doller']['baz']) assert_equal('123baz456bar798', c['dollar']['baz'])
assert_equal('123baz456bar798', c['doller']['qux']) assert_equal('123baz456bar798', c['dollar']['qux'])
assert_equal('123baz456bar798.123baz456bar798', c['doller']['quxx']) assert_equal('123baz456bar798.123baz456bar798', c['dollar']['quxx'])
excn = assert_raise(OpenSSL::ConfigError) do excn = assert_raise(OpenSSL::ConfigError) do
OpenSSL::Config.parse("foo = $bar") OpenSSL::Config.parse("foo = $bar")

View file

@ -257,7 +257,10 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
def test_client_auth_success def test_client_auth_success
vflag = OpenSSL::SSL::VERIFY_PEER|OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT vflag = OpenSSL::SSL::VERIFY_PEER|OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT
start_server(verify_mode: vflag) { |port| start_server(verify_mode: vflag,
ctx_proc: proc { |ctx|
ctx.max_version = OpenSSL::SSL::TLS1_2_VERSION if libressl?(3, 2, 0)
}) { |port|
ctx = OpenSSL::SSL::SSLContext.new ctx = OpenSSL::SSL::SSLContext.new
ctx.key = @cli_key ctx.key = @cli_key
ctx.cert = @cli_cert ctx.cert = @cli_cert
@ -303,6 +306,8 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
end end
def test_client_ca def test_client_ca
pend "LibreSSL 3.2 has broken client CA support" if libressl?(3, 2, 0)
ctx_proc = Proc.new do |ctx| ctx_proc = Proc.new do |ctx|
ctx.client_ca = [@ca_cert] ctx.client_ca = [@ca_cert]
end end
@ -481,6 +486,7 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
}) { |port| }) { |port|
ctx = OpenSSL::SSL::SSLContext.new ctx = OpenSSL::SSL::SSLContext.new
ctx.verify_mode = OpenSSL::SSL::VERIFY_NONE ctx.verify_mode = OpenSSL::SSL::VERIFY_NONE
ctx.max_version = :TLS1_2 if libressl?(3, 2, 0) && !libressl?(3, 3, 0)
server_connect(port, ctx) { |ssl| server_connect(port, ctx) { |ssl|
ssl.puts "abc"; ssl.gets ssl.puts "abc"; ssl.gets
@ -868,11 +874,13 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
def test_verify_hostname_on_connect def test_verify_hostname_on_connect
ctx_proc = proc { |ctx| ctx_proc = proc { |ctx|
san = "DNS:a.example.com,DNS:*.b.example.com"
san += ",DNS:c*.example.com,DNS:d.*.example.com" unless libressl?(3, 2, 2)
exts = [ exts = [
["keyUsage", "keyEncipherment,digitalSignature", true], ["keyUsage", "keyEncipherment,digitalSignature", true],
["subjectAltName", "DNS:a.example.com,DNS:*.b.example.com," \ ["subjectAltName", san],
"DNS:c*.example.com,DNS:d.*.example.com"],
] ]
ctx.cert = issue_cert(@svr, @svr_key, 4, exts, @ca_cert, @ca_key) ctx.cert = issue_cert(@svr, @svr_key, 4, exts, @ca_cert, @ca_key)
ctx.key = @svr_key ctx.key = @svr_key
} }
@ -893,6 +901,7 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
["cx.example.com", true], ["cx.example.com", true],
["d.x.example.com", false], ["d.x.example.com", false],
].each do |name, expected_ok| ].each do |name, expected_ok|
next if name.start_with?('cx') if libressl?(3, 2, 2)
begin begin
sock = TCPSocket.new("127.0.0.1", port) sock = TCPSocket.new("127.0.0.1", port)
ssl = OpenSSL::SSL::SSLSocket.new(sock, ctx) ssl = OpenSSL::SSL::SSLSocket.new(sock, ctx)
@ -1581,12 +1590,13 @@ end
end end
end end
def test_ecdh_curves def test_ecdh_curves_tls12
pend "EC is disabled" unless defined?(OpenSSL::PKey::EC) pend "EC is disabled" unless defined?(OpenSSL::PKey::EC)
ctx_proc = -> ctx { ctx_proc = -> ctx {
# Enable both ECDHE (~ TLS 1.2) cipher suites and TLS 1.3 # Enable both ECDHE (~ TLS 1.2) cipher suites and TLS 1.3
ctx.ciphers = "DEFAULT:!kRSA:!kEDH" ctx.max_version = OpenSSL::SSL::TLS1_2_VERSION
ctx.ciphers = "kEECDH"
ctx.ecdh_curves = "P-384:P-521" ctx.ecdh_curves = "P-384:P-521"
} }
start_server(ctx_proc: ctx_proc, ignore_listener_error: true) do |port| start_server(ctx_proc: ctx_proc, ignore_listener_error: true) do |port|
@ -1595,13 +1605,9 @@ end
server_connect(port, ctx) { |ssl| server_connect(port, ctx) { |ssl|
cs = ssl.cipher[0] cs = ssl.cipher[0]
if /\ATLS/ =~ cs # Is TLS 1.3 is used? assert_match (/\AECDH/), cs
if ssl.respond_to?(:tmp_key)
assert_equal "secp384r1", ssl.tmp_key.group.curve_name assert_equal "secp384r1", ssl.tmp_key.group.curve_name
else
assert_match (/\AECDH/), cs
if ssl.respond_to?(:tmp_key)
assert_equal "secp384r1", ssl.tmp_key.group.curve_name
end
end end
ssl.puts "abc"; assert_equal "abc\n", ssl.gets ssl.puts "abc"; assert_equal "abc\n", ssl.gets
} }
@ -1625,6 +1631,26 @@ end
end end
end end
def test_ecdh_curves_tls13
pend "EC is disabled" unless defined?(OpenSSL::PKey::EC)
pend "TLS 1.3 not supported" unless tls13_supported?
ctx_proc = -> ctx {
# Assume TLS 1.3 is enabled and chosen by default
ctx.ecdh_curves = "P-384:P-521"
}
start_server(ctx_proc: ctx_proc, ignore_listener_error: true) do |port|
ctx = OpenSSL::SSL::SSLContext.new
ctx.ecdh_curves = "P-256:P-384" # disable P-521
server_connect(port, ctx) { |ssl|
assert_equal "TLSv1.3", ssl.ssl_version
assert_equal "secp384r1", ssl.tmp_key.group.curve_name
ssl.puts "abc"; assert_equal "abc\n", ssl.gets
}
end
end
def test_security_level def test_security_level
ctx = OpenSSL::SSL::SSLContext.new ctx = OpenSSL::SSL::SSLContext.new
begin begin

View file

@ -122,6 +122,7 @@ __EOS__
ctx.options &= ~OpenSSL::SSL::OP_NO_TICKET ctx.options &= ~OpenSSL::SSL::OP_NO_TICKET
# Disable server-side session cache which is enabled by default # Disable server-side session cache which is enabled by default
ctx.session_cache_mode = OpenSSL::SSL::SSLContext::SESSION_CACHE_OFF ctx.session_cache_mode = OpenSSL::SSL::SSLContext::SESSION_CACHE_OFF
ctx.max_version = OpenSSL::SSL::TLS1_2_VERSION if libressl?(3, 2, 0)
} }
start_server(ctx_proc: ctx_proc) do |port| start_server(ctx_proc: ctx_proc) do |port|
sess1 = server_connect_with_session(port, nil, nil) { |ssl| sess1 = server_connect_with_session(port, nil, nil) { |ssl|

View file

@ -181,6 +181,12 @@ _end_of_pem_
assert_equal(42, qer2.nonce) assert_equal(42, qer2.nonce)
end end
def test_request_invalid_asn1
assert_raise(OpenSSL::Timestamp::TimestampError) do
OpenSSL::Timestamp::Request.new("*" * 44)
end
end
def test_response_constants def test_response_constants
assert_equal(0, OpenSSL::Timestamp::Response::GRANTED) assert_equal(0, OpenSSL::Timestamp::Response::GRANTED)
assert_equal(1, OpenSSL::Timestamp::Response::GRANTED_WITH_MODS) assert_equal(1, OpenSSL::Timestamp::Response::GRANTED_WITH_MODS)
@ -338,6 +344,12 @@ _end_of_pem_
end end
end end
def test_response_invalid_asn1
assert_raise(OpenSSL::Timestamp::TimestampError) do
OpenSSL::Timestamp::Response.new("*" * 44)
end
end
def test_no_cert_requested def test_no_cert_requested
req = OpenSSL::Timestamp::Request.new req = OpenSSL::Timestamp::Request.new
req.algorithm = "SHA1" req.algorithm = "SHA1"
@ -590,6 +602,12 @@ _end_of_pem_
assert_equal(123, info.nonce) assert_equal(123, info.nonce)
end end
def test_token_info_invalid_asn1
assert_raise(OpenSSL::Timestamp::TimestampError) do
OpenSSL::Timestamp::TokenInfo.new("*" * 44)
end
end
private private
def assert_cert expected, actual def assert_cert expected, actual

View file

@ -66,7 +66,7 @@ class OpenSSL::TestX509Store < OpenSSL::TestCase
ee1_cert = issue_cert(@ee1, @dsa256, 10, ee_exts, ca2_cert, @rsa1024) ee1_cert = issue_cert(@ee1, @dsa256, 10, ee_exts, ca2_cert, @rsa1024)
ee2_cert = issue_cert(@ee2, @dsa512, 20, ee_exts, ca2_cert, @rsa1024) ee2_cert = issue_cert(@ee2, @dsa512, 20, ee_exts, ca2_cert, @rsa1024)
ee3_cert = issue_cert(@ee2, @dsa512, 30, ee_exts, ca2_cert, @rsa1024, ee3_cert = issue_cert(@ee2, @dsa512, 30, ee_exts, ca2_cert, @rsa1024,
not_before: now-100, not_after: now-50) not_before: now-100, not_after: now-1)
ee4_cert = issue_cert(@ee2, @dsa512, 40, ee_exts, ca2_cert, @rsa1024, ee4_cert = issue_cert(@ee2, @dsa512, 40, ee_exts, ca2_cert, @rsa1024,
not_before: now+1000, not_after: now+2000,) not_before: now+1000, not_after: now+2000,)
@ -128,7 +128,7 @@ class OpenSSL::TestX509Store < OpenSSL::TestCase
assert_equal(@ee2.to_der, chain[0].subject.to_der) assert_equal(@ee2.to_der, chain[0].subject.to_der)
assert_equal(@ca2.to_der, chain[1].subject.to_der) assert_equal(@ca2.to_der, chain[1].subject.to_der)
assert_equal(@ca1.to_der, chain[2].subject.to_der) assert_equal(@ca1.to_der, chain[2].subject.to_der)
assert_equal(false, store.verify(ee3_cert), "now=#{now.inspect} Time.now=#{Time.now.inspect} store=#{store.inspect} ee3_cert=#{ee3_cert.inspect}") assert_equal(false, store.verify(ee3_cert))
assert_equal(OpenSSL::X509::V_ERR_CERT_HAS_EXPIRED, store.error) assert_equal(OpenSSL::X509::V_ERR_CERT_HAS_EXPIRED, store.error)
assert_match(/expire/i, store.error_string) assert_match(/expire/i, store.error_string)
assert_equal(false, store.verify(ee4_cert)) assert_equal(false, store.verify(ee4_cert))

View file

@ -199,6 +199,14 @@ class OpenSSL::SSLTestCase < OpenSSL::TestCase
rescue rescue
end end
def tls13_supported?
return false unless defined?(OpenSSL::SSL::TLS1_3_VERSION)
ctx = OpenSSL::SSL::SSLContext.new
ctx.min_version = ctx.max_version = OpenSSL::SSL::TLS1_3_VERSION
true
rescue
end
def readwrite_loop(ctx, ssl) def readwrite_loop(ctx, ssl)
while line = ssl.gets while line = ssl.gets
ssl.write(line) ssl.write(line)