Skip to content

Commit 4beb383

Browse files
authored
Merge pull request #481 from rhenium/ky/openssl-3.0.0-part2
Miscellaneous changes for OpenSSL 3.0 support (part 2)
2 parents 5d0df40 + fd4dd6d commit 4beb383

File tree

10 files changed

+111
-65
lines changed

10 files changed

+111
-65
lines changed

.github/workflows/test.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ jobs:
7474
- openssl-1.0.2u # EOL
7575
- openssl-1.1.0l # EOL
7676
- openssl-1.1.1l
77+
- openssl-3.0.1
7778
- libressl-3.1.5 # EOL
7879
- libressl-3.2.6
7980
- libressl-3.3.4
@@ -89,7 +90,7 @@ jobs:
8990
curl -OL https://ftp.openssl.org/source/${{ matrix.openssl }}.tar.gz
9091
tar xf ${{ matrix.openssl }}.tar.gz && cd ${{ matrix.openssl }}
9192
# shared is required for 1.0.x.
92-
./Configure --prefix=$HOME/.openssl/${{ matrix.openssl }} \
93+
./Configure --prefix=$HOME/.openssl/${{ matrix.openssl }} --libdir=lib \
9394
shared linux-x86_64
9495
make depend
9596
;;

ext/openssl/openssl_missing.c

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,6 @@
1010
#include RUBY_EXTCONF_H
1111

1212
#include <string.h> /* memcpy() */
13-
#if !defined(OPENSSL_NO_ENGINE)
14-
# include <openssl/engine.h>
15-
#endif
1613
#include <openssl/x509_vfy.h>
1714

1815
#include "openssl_missing.h"

ext/openssl/ossl.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <ruby/io.h>
1919
#include <ruby/thread.h>
2020
#include <openssl/opensslv.h>
21+
2122
#include <openssl/err.h>
2223
#include <openssl/asn1.h>
2324
#include <openssl/x509v3.h>
@@ -30,9 +31,6 @@
3031
#include <openssl/ts.h>
3132
#endif
3233
#include <openssl/crypto.h>
33-
#if !defined(OPENSSL_NO_ENGINE)
34-
# include <openssl/engine.h>
35-
#endif
3634
#if !defined(OPENSSL_NO_OCSP)
3735
# include <openssl/ocsp.h>
3836
#endif
@@ -54,6 +52,10 @@
5452
(LIBRESSL_VERSION_NUMBER >= (maj << 28) | (min << 20) | (pat << 12))
5553
#endif
5654

55+
#if !defined(OPENSSL_NO_ENGINE) && !OSSL_OPENSSL_PREREQ(3, 0, 0)
56+
# define OSSL_USE_ENGINE
57+
#endif
58+
5759
/*
5860
* Common Module
5961
*/

ext/openssl/ossl_engine.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@
99
*/
1010
#include "ossl.h"
1111

12-
#if !defined(OPENSSL_NO_ENGINE)
12+
#ifdef OSSL_USE_ENGINE
13+
# include <openssl/engine.h>
1314

1415
#define NewEngine(klass) \
1516
TypedData_Wrap_Struct((klass), &ossl_engine_type, 0)

ext/openssl/ossl_hmac.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ static VALUE
175175
ossl_hmac_digest(VALUE self)
176176
{
177177
EVP_MD_CTX *ctx;
178-
size_t buf_len;
178+
size_t buf_len = EVP_MAX_MD_SIZE;
179179
VALUE ret;
180180

181181
GetHMAC(self, ctx);
@@ -200,7 +200,7 @@ ossl_hmac_hexdigest(VALUE self)
200200
{
201201
EVP_MD_CTX *ctx;
202202
unsigned char buf[EVP_MAX_MD_SIZE];
203-
size_t buf_len;
203+
size_t buf_len = EVP_MAX_MD_SIZE;
204204
VALUE ret;
205205

206206
GetHMAC(self, ctx);

ext/openssl/ossl_pkey.c

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@
99
*/
1010
#include "ossl.h"
1111

12+
#ifdef OSSL_USE_ENGINE
13+
# include <openssl/engine.h>
14+
#endif
15+
1216
/*
1317
* Classes
1418
*/
@@ -312,6 +316,11 @@ pkey_generate(int argc, VALUE *argv, VALUE self, int genparam)
312316
ossl_raise(ePKeyError, "EVP_PKEY_CTX_new");
313317
}
314318
else {
319+
#if OSSL_OPENSSL_PREREQ(3, 0, 0)
320+
ctx = EVP_PKEY_CTX_new_from_name(NULL, StringValueCStr(alg), NULL);
321+
if (!ctx)
322+
ossl_raise(ePKeyError, "EVP_PKEY_CTX_new_from_name");
323+
#else
315324
const EVP_PKEY_ASN1_METHOD *ameth;
316325
ENGINE *tmpeng;
317326
int pkey_id;
@@ -330,6 +339,7 @@ pkey_generate(int argc, VALUE *argv, VALUE self, int genparam)
330339
ctx = EVP_PKEY_CTX_new_id(pkey_id, NULL/* engine */);
331340
if (!ctx)
332341
ossl_raise(ePKeyError, "EVP_PKEY_CTX_new_id");
342+
#endif
333343
}
334344

335345
if (genparam && EVP_PKEY_paramgen_init(ctx) <= 0) {
@@ -425,9 +435,19 @@ ossl_pkey_s_generate_key(int argc, VALUE *argv, VALUE self)
425435
return pkey_generate(argc, argv, self, 0);
426436
}
427437

438+
/*
439+
* TODO: There is no convenient way to check the presence of public key
440+
* components on OpenSSL 3.0. But since keys are immutable on 3.0, pkeys without
441+
* these should only be created by OpenSSL::PKey.generate_parameters or by
442+
* parsing DER-/PEM-encoded string. We would need another flag for that.
443+
*/
428444
void
429445
ossl_pkey_check_public_key(const EVP_PKEY *pkey)
430446
{
447+
#if OSSL_OPENSSL_PREREQ(3, 0, 0)
448+
if (EVP_PKEY_missing_parameters(pkey))
449+
ossl_raise(ePKeyError, "parameters missing");
450+
#else
431451
void *ptr;
432452
const BIGNUM *n, *e, *pubkey;
433453

@@ -463,6 +483,7 @@ ossl_pkey_check_public_key(const EVP_PKEY *pkey)
463483
return;
464484
}
465485
ossl_raise(ePKeyError, "public key missing");
486+
#endif
466487
}
467488

468489
EVP_PKEY *

ext/openssl/ossl_ssl.c

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2825,9 +2825,24 @@ Init_ossl_ssl(void)
28252825
rb_define_const(mSSL, "VERIFY_CLIENT_ONCE", INT2NUM(SSL_VERIFY_CLIENT_ONCE));
28262826

28272827
rb_define_const(mSSL, "OP_ALL", ULONG2NUM(SSL_OP_ALL));
2828+
#ifdef SSL_OP_CLEANSE_PLAINTEXT /* OpenSSL 3.0 */
2829+
rb_define_const(mSSL, "OP_CLEANSE_PLAINTEXT", ULONG2NUM(SSL_OP_CLEANSE_PLAINTEXT));
2830+
#endif
28282831
rb_define_const(mSSL, "OP_LEGACY_SERVER_CONNECT", ULONG2NUM(SSL_OP_LEGACY_SERVER_CONNECT));
2832+
#ifdef SSL_OP_ENABLE_KTLS /* OpenSSL 3.0 */
2833+
rb_define_const(mSSL, "OP_ENABLE_KTLS", ULONG2NUM(SSL_OP_ENABLE_KTLS));
2834+
#endif
28292835
rb_define_const(mSSL, "OP_TLSEXT_PADDING", ULONG2NUM(SSL_OP_TLSEXT_PADDING));
28302836
rb_define_const(mSSL, "OP_SAFARI_ECDHE_ECDSA_BUG", ULONG2NUM(SSL_OP_SAFARI_ECDHE_ECDSA_BUG));
2837+
#ifdef SSL_OP_IGNORE_UNEXPECTED_EOF /* OpenSSL 3.0 */
2838+
rb_define_const(mSSL, "OP_IGNORE_UNEXPECTED_EOF", ULONG2NUM(SSL_OP_IGNORE_UNEXPECTED_EOF));
2839+
#endif
2840+
#ifdef SSL_OP_ALLOW_CLIENT_RENEGOTIATION /* OpenSSL 3.0 */
2841+
rb_define_const(mSSL, "OP_ALLOW_CLIENT_RENEGOTIATION", ULONG2NUM(SSL_OP_ALLOW_CLIENT_RENEGOTIATION));
2842+
#endif
2843+
#ifdef SSL_OP_DISABLE_TLSEXT_CA_NAMES /* OpenSSL 3.0 */
2844+
rb_define_const(mSSL, "OP_DISABLE_TLSEXT_CA_NAMES", ULONG2NUM(SSL_OP_DISABLE_TLSEXT_CA_NAMES));
2845+
#endif
28312846
#ifdef SSL_OP_ALLOW_NO_DHE_KEX /* OpenSSL 1.1.1 */
28322847
rb_define_const(mSSL, "OP_ALLOW_NO_DHE_KEX", ULONG2NUM(SSL_OP_ALLOW_NO_DHE_KEX));
28332848
#endif
@@ -2839,20 +2854,28 @@ Init_ossl_ssl(void)
28392854
#ifdef SSL_OP_NO_ENCRYPT_THEN_MAC /* OpenSSL 1.1.1 */
28402855
rb_define_const(mSSL, "OP_NO_ENCRYPT_THEN_MAC", ULONG2NUM(SSL_OP_NO_ENCRYPT_THEN_MAC));
28412856
#endif
2842-
rb_define_const(mSSL, "OP_CIPHER_SERVER_PREFERENCE", ULONG2NUM(SSL_OP_CIPHER_SERVER_PREFERENCE));
2843-
rb_define_const(mSSL, "OP_TLS_ROLLBACK_BUG", ULONG2NUM(SSL_OP_TLS_ROLLBACK_BUG));
2844-
#ifdef SSL_OP_NO_RENEGOTIATION /* OpenSSL 1.1.1 */
2845-
rb_define_const(mSSL, "OP_NO_RENEGOTIATION", ULONG2NUM(SSL_OP_NO_RENEGOTIATION));
2857+
#ifdef SSL_OP_ENABLE_MIDDLEBOX_COMPAT /* OpenSSL 1.1.1 */
2858+
rb_define_const(mSSL, "OP_ENABLE_MIDDLEBOX_COMPAT", ULONG2NUM(SSL_OP_ENABLE_MIDDLEBOX_COMPAT));
2859+
#endif
2860+
#ifdef SSL_OP_PRIORITIZE_CHACHA /* OpenSSL 1.1.1 */
2861+
rb_define_const(mSSL, "OP_PRIORITIZE_CHACHA", ULONG2NUM(SSL_OP_PRIORITIZE_CHACHA));
2862+
#endif
2863+
#ifdef SSL_OP_NO_ANTI_REPLAY /* OpenSSL 1.1.1 */
2864+
rb_define_const(mSSL, "OP_NO_ANTI_REPLAY", ULONG2NUM(SSL_OP_NO_ANTI_REPLAY));
28462865
#endif
2847-
rb_define_const(mSSL, "OP_CRYPTOPRO_TLSEXT_BUG", ULONG2NUM(SSL_OP_CRYPTOPRO_TLSEXT_BUG));
2848-
28492866
rb_define_const(mSSL, "OP_NO_SSLv3", ULONG2NUM(SSL_OP_NO_SSLv3));
28502867
rb_define_const(mSSL, "OP_NO_TLSv1", ULONG2NUM(SSL_OP_NO_TLSv1));
28512868
rb_define_const(mSSL, "OP_NO_TLSv1_1", ULONG2NUM(SSL_OP_NO_TLSv1_1));
28522869
rb_define_const(mSSL, "OP_NO_TLSv1_2", ULONG2NUM(SSL_OP_NO_TLSv1_2));
28532870
#ifdef SSL_OP_NO_TLSv1_3 /* OpenSSL 1.1.1 */
28542871
rb_define_const(mSSL, "OP_NO_TLSv1_3", ULONG2NUM(SSL_OP_NO_TLSv1_3));
28552872
#endif
2873+
rb_define_const(mSSL, "OP_CIPHER_SERVER_PREFERENCE", ULONG2NUM(SSL_OP_CIPHER_SERVER_PREFERENCE));
2874+
rb_define_const(mSSL, "OP_TLS_ROLLBACK_BUG", ULONG2NUM(SSL_OP_TLS_ROLLBACK_BUG));
2875+
#ifdef SSL_OP_NO_RENEGOTIATION /* OpenSSL 1.1.1 */
2876+
rb_define_const(mSSL, "OP_NO_RENEGOTIATION", ULONG2NUM(SSL_OP_NO_RENEGOTIATION));
2877+
#endif
2878+
rb_define_const(mSSL, "OP_CRYPTOPRO_TLSEXT_BUG", ULONG2NUM(SSL_OP_CRYPTOPRO_TLSEXT_BUG));
28562879

28572880
/* SSL_OP_* flags for DTLS */
28582881
#if 0

test/openssl/test_cipher.rb

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -135,14 +135,11 @@ def test_ctr_if_exists
135135
end
136136

137137
def test_ciphers
138-
OpenSSL::Cipher.ciphers.each{|name|
139-
next if /netbsd/ =~ RUBY_PLATFORM && /idea|rc5/i =~ name
140-
begin
141-
assert_kind_of(OpenSSL::Cipher, OpenSSL::Cipher.new(name))
142-
rescue OpenSSL::Cipher::CipherError => e
143-
raise unless /wrap/ =~ name and /wrap mode not allowed/ =~ e.message
144-
end
145-
}
138+
ciphers = OpenSSL::Cipher.ciphers
139+
assert_kind_of Array, ciphers
140+
assert_include ciphers, "aes-128-cbc"
141+
assert_include ciphers, "aes128" # alias of aes-128-cbc
142+
assert_include ciphers, "aes-128-gcm"
146143
end
147144

148145
def test_AES

test/openssl/test_hmac.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ def test_hmac
2121
end
2222

2323
def test_dup
24+
pend "HMAC#initialize_copy is currently broken on OpenSSL 3.0.0" if openssl?(3, 0, 0)
2425
h1 = OpenSSL::HMAC.new("KEY", "MD5")
2526
h1.update("DATA")
2627
h = h1.dup

test/openssl/test_ssl.rb

Lines changed: 44 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -893,14 +893,12 @@ def test_accept_errors_include_peeraddr
893893
end
894894
end
895895

896-
begin
897-
sock = TCPSocket.new("127.0.0.1", port)
898-
sock.puts "abc"
899-
ensure
900-
sock&.close
901-
end
896+
sock = TCPSocket.new("127.0.0.1", port)
897+
sock << "\x00" * 1024
902898

903899
assert t.join
900+
ensure
901+
sock&.close
904902
server.close
905903
end
906904

@@ -1210,46 +1208,51 @@ def test_minmax_version
12101208
end
12111209

12121210
def test_options_disable_versions
1213-
# Note: Use of these OP_* flags has been deprecated since OpenSSL 1.1.0.
1211+
# It's recommended to use SSLContext#{min,max}_version= instead in real
1212+
# applications. The purpose of this test case is to check that SSL options
1213+
# are properly propagated to OpenSSL library.
12141214
supported = check_supported_protocol_versions
1215+
if !defined?(OpenSSL::SSL::TLS1_3_VERSION) ||
1216+
!supported.include?(OpenSSL::SSL::TLS1_2_VERSION) ||
1217+
!supported.include?(OpenSSL::SSL::TLS1_3_VERSION) ||
1218+
!defined?(OpenSSL::SSL::OP_NO_TLSv1_3) # LibreSSL < 3.4
1219+
pend "this test case requires both TLS 1.2 and TLS 1.3 to be supported " \
1220+
"and enabled by default"
1221+
end
12151222

1216-
if supported.include?(OpenSSL::SSL::TLS1_1_VERSION) &&
1217-
supported.include?(OpenSSL::SSL::TLS1_2_VERSION)
1218-
# Server disables ~ TLS 1.1
1219-
ctx_proc = proc { |ctx|
1220-
ctx.options |= OpenSSL::SSL::OP_NO_SSLv2 | OpenSSL::SSL::OP_NO_SSLv3 |
1221-
OpenSSL::SSL::OP_NO_TLSv1 | OpenSSL::SSL::OP_NO_TLSv1_1
1222-
}
1223-
start_server(ctx_proc: ctx_proc, ignore_listener_error: true) { |port|
1224-
# Client only supports TLS 1.1
1225-
ctx1 = OpenSSL::SSL::SSLContext.new
1226-
ctx1.min_version = ctx1.max_version = OpenSSL::SSL::TLS1_1_VERSION
1227-
assert_handshake_error { server_connect(port, ctx1) { } }
1223+
# Server disables TLS 1.2 and earlier
1224+
ctx_proc = proc { |ctx|
1225+
ctx.options |= OpenSSL::SSL::OP_NO_SSLv2 | OpenSSL::SSL::OP_NO_SSLv3 |
1226+
OpenSSL::SSL::OP_NO_TLSv1 | OpenSSL::SSL::OP_NO_TLSv1_1 |
1227+
OpenSSL::SSL::OP_NO_TLSv1_2
1228+
}
1229+
start_server(ctx_proc: ctx_proc, ignore_listener_error: true) { |port|
1230+
# Client only supports TLS 1.2
1231+
ctx1 = OpenSSL::SSL::SSLContext.new
1232+
ctx1.min_version = ctx1.max_version = OpenSSL::SSL::TLS1_2_VERSION
1233+
assert_handshake_error { server_connect(port, ctx1) { } }
12281234

1229-
# Client only supports TLS 1.2
1230-
ctx2 = OpenSSL::SSL::SSLContext.new
1231-
ctx2.min_version = ctx2.max_version = OpenSSL::SSL::TLS1_2_VERSION
1232-
assert_nothing_raised { server_connect(port, ctx2) { } }
1233-
}
1235+
# Client only supports TLS 1.3
1236+
ctx2 = OpenSSL::SSL::SSLContext.new
1237+
ctx2.min_version = ctx2.max_version = OpenSSL::SSL::TLS1_3_VERSION
1238+
assert_nothing_raised { server_connect(port, ctx2) { } }
1239+
}
12341240

1235-
# Server only supports TLS 1.1
1236-
ctx_proc = proc { |ctx|
1237-
ctx.min_version = ctx.max_version = OpenSSL::SSL::TLS1_1_VERSION
1238-
}
1239-
start_server(ctx_proc: ctx_proc, ignore_listener_error: true) { |port|
1240-
# Client disables TLS 1.1
1241-
ctx1 = OpenSSL::SSL::SSLContext.new
1242-
ctx1.options |= OpenSSL::SSL::OP_NO_TLSv1_1
1243-
assert_handshake_error { server_connect(port, ctx1) { } }
1241+
# Server only supports TLS 1.2
1242+
ctx_proc = proc { |ctx|
1243+
ctx.min_version = ctx.max_version = OpenSSL::SSL::TLS1_2_VERSION
1244+
}
1245+
start_server(ctx_proc: ctx_proc, ignore_listener_error: true) { |port|
1246+
# Client doesn't support TLS 1.2
1247+
ctx1 = OpenSSL::SSL::SSLContext.new
1248+
ctx1.options |= OpenSSL::SSL::OP_NO_TLSv1_2
1249+
assert_handshake_error { server_connect(port, ctx1) { } }
12441250

1245-
# Client disables TLS 1.2
1246-
ctx2 = OpenSSL::SSL::SSLContext.new
1247-
ctx2.options |= OpenSSL::SSL::OP_NO_TLSv1_2
1248-
assert_nothing_raised { server_connect(port, ctx2) { } }
1249-
}
1250-
else
1251-
pend "TLS 1.1 and TLS 1.2 must be supported; skipping"
1252-
end
1251+
# Client supports TLS 1.2 by default
1252+
ctx2 = OpenSSL::SSL::SSLContext.new
1253+
ctx2.options |= OpenSSL::SSL::OP_NO_TLSv1_3
1254+
assert_nothing_raised { server_connect(port, ctx2) { } }
1255+
}
12531256
end
12541257

12551258
def test_ssl_methods_constant

0 commit comments

Comments
 (0)