Skip to content

Commit 719ba4a

Browse files
authored
Merge pull request #924 from rhenium/ky/ssl-dh-auto
ssl: use SSL_CTX_set_dh_auto() by default
2 parents 4aeef6f + b7cde6d commit 719ba4a

File tree

5 files changed

+50
-80
lines changed

5 files changed

+50
-80
lines changed

ext/openssl/extconf.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ def find_openssl_library
147147
have_func("EVP_PKEY_check(NULL)", evp_h)
148148

149149
# added in 3.0.0
150-
have_func("SSL_set0_tmp_dh_pkey(NULL, NULL)", ssl_h)
150+
have_func("SSL_CTX_set0_tmp_dh_pkey(NULL, NULL)", ssl_h)
151151
have_func("ERR_get_error_all(NULL, NULL, NULL, NULL, NULL)", "openssl/err.h")
152152
have_func("SSL_CTX_load_verify_file(NULL, \"\")", ssl_h)
153153
have_func("BN_check_prime(NULL, NULL, NULL)", "openssl/bn.h")

ext/openssl/ossl_ssl.c

Lines changed: 47 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,7 @@ VALUE cSSLSocket;
3636
static VALUE eSSLErrorWaitReadable;
3737
static VALUE eSSLErrorWaitWritable;
3838

39-
static ID id_call, ID_callback_state, id_tmp_dh_callback,
40-
id_npn_protocols_encoded, id_each;
39+
static ID id_call, ID_callback_state, id_npn_protocols_encoded, id_each;
4140
static VALUE sym_exception, sym_wait_readable, sym_wait_writable;
4241

4342
static ID id_i_cert_store, id_i_ca_file, id_i_ca_path, id_i_verify_mode,
@@ -47,7 +46,7 @@ static ID id_i_cert_store, id_i_ca_file, id_i_ca_path, id_i_verify_mode,
4746
id_i_session_id_context, id_i_session_get_cb, id_i_session_new_cb,
4847
id_i_session_remove_cb, id_i_npn_select_cb, id_i_npn_protocols,
4948
id_i_alpn_select_cb, id_i_alpn_protocols, id_i_servername_cb,
50-
id_i_verify_hostname, id_i_keylog_cb;
49+
id_i_verify_hostname, id_i_keylog_cb, id_i_tmp_dh_callback;
5150
static ID id_i_io, id_i_context, id_i_hostname;
5251

5352
static int ossl_ssl_ex_ptr_idx;
@@ -90,6 +89,7 @@ ossl_sslctx_s_alloc(VALUE klass)
9089
ossl_raise(eSSLError, "SSL_CTX_new");
9190
}
9291
SSL_CTX_set_mode(ctx, mode);
92+
SSL_CTX_set_dh_auto(ctx, 1);
9393
RTYPEDDATA_DATA(obj) = ctx;
9494
SSL_CTX_set_ex_data(ctx, ossl_sslctx_ex_ptr_idx, (void *)obj);
9595

@@ -133,8 +133,6 @@ ossl_client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey)
133133
#if !defined(OPENSSL_NO_DH)
134134
struct tmp_dh_callback_args {
135135
VALUE ssl_obj;
136-
ID id;
137-
int type;
138136
int is_export;
139137
int keylength;
140138
};
@@ -143,48 +141,36 @@ static VALUE
143141
ossl_call_tmp_dh_callback(VALUE arg)
144142
{
145143
struct tmp_dh_callback_args *args = (struct tmp_dh_callback_args *)arg;
146-
VALUE cb, dh;
147-
EVP_PKEY *pkey;
144+
VALUE ctx_obj, cb, obj;
145+
const DH *dh;
148146

149-
cb = rb_funcall(args->ssl_obj, args->id, 0);
147+
ctx_obj = rb_attr_get(args->ssl_obj, id_i_context);
148+
cb = rb_attr_get(ctx_obj, id_i_tmp_dh_callback);
150149
if (NIL_P(cb))
151-
return (VALUE)NULL;
152-
dh = rb_funcall(cb, id_call, 3, args->ssl_obj, INT2NUM(args->is_export),
153-
INT2NUM(args->keylength));
154-
pkey = GetPKeyPtr(dh);
155-
if (EVP_PKEY_base_id(pkey) != args->type)
156-
return (VALUE)NULL;
150+
return (VALUE)NULL;
151+
152+
obj = rb_funcall(cb, id_call, 3, args->ssl_obj, INT2NUM(args->is_export),
153+
INT2NUM(args->keylength));
154+
// TODO: We should riase if obj is not DH
155+
dh = EVP_PKEY_get0_DH(GetPKeyPtr(obj));
156+
if (!dh)
157+
ossl_clear_error();
157158

158-
return (VALUE)pkey;
159+
return (VALUE)dh;
159160
}
160-
#endif
161161

162-
#if !defined(OPENSSL_NO_DH)
163162
static DH *
164163
ossl_tmp_dh_callback(SSL *ssl, int is_export, int keylength)
165164
{
166-
VALUE rb_ssl;
167-
EVP_PKEY *pkey;
168-
struct tmp_dh_callback_args args;
169165
int state;
170-
171-
rb_ssl = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx);
172-
args.ssl_obj = rb_ssl;
173-
args.id = id_tmp_dh_callback;
174-
args.is_export = is_export;
175-
args.keylength = keylength;
176-
args.type = EVP_PKEY_DH;
177-
178-
pkey = (EVP_PKEY *)rb_protect(ossl_call_tmp_dh_callback,
179-
(VALUE)&args, &state);
166+
VALUE rb_ssl = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx);
167+
struct tmp_dh_callback_args args = {rb_ssl, is_export, keylength};
168+
VALUE ret = rb_protect(ossl_call_tmp_dh_callback, (VALUE)&args, &state);
180169
if (state) {
181170
rb_ivar_set(rb_ssl, ID_callback_state, INT2NUM(state));
182171
return NULL;
183172
}
184-
if (!pkey)
185-
return NULL;
186-
187-
return (DH *)EVP_PKEY_get0_DH(pkey);
173+
return (DH *)ret;
188174
}
189175
#endif /* OPENSSL_NO_DH */
190176

@@ -703,7 +689,10 @@ ossl_sslctx_setup(VALUE self)
703689
GetSSLCTX(self, ctx);
704690

705691
#if !defined(OPENSSL_NO_DH)
706-
SSL_CTX_set_tmp_dh_callback(ctx, ossl_tmp_dh_callback);
692+
if (!NIL_P(rb_attr_get(self, id_i_tmp_dh_callback))) {
693+
SSL_CTX_set_tmp_dh_callback(ctx, ossl_tmp_dh_callback);
694+
SSL_CTX_set_dh_auto(ctx, 0);
695+
}
707696
#endif
708697

709698
#if !defined(OPENSSL_IS_AWSLC) /* AWS-LC has no support for TLS 1.3 PHA. */
@@ -1148,7 +1137,7 @@ ossl_sslctx_set_client_sigalgs(VALUE self, VALUE v)
11481137
* contained in the key object, if any, are ignored. The server will always
11491138
* generate a new key pair for each handshake.
11501139
*
1151-
* Added in version 3.0. See also the man page SSL_set0_tmp_dh_pkey(3).
1140+
* Added in version 3.0. See also the man page SSL_CTX_set0_tmp_dh_pkey(3).
11521141
*
11531142
* Example:
11541143
* ctx = OpenSSL::SSL::SSLContext.new
@@ -1169,7 +1158,7 @@ ossl_sslctx_set_tmp_dh(VALUE self, VALUE arg)
11691158
if (EVP_PKEY_base_id(pkey) != EVP_PKEY_DH)
11701159
rb_raise(eSSLError, "invalid pkey type %s (expected DH)",
11711160
OBJ_nid2sn(EVP_PKEY_base_id(pkey)));
1172-
#ifdef HAVE_SSL_SET0_TMP_DH_PKEY
1161+
#ifdef HAVE_SSL_CTX_SET0_TMP_DH_PKEY
11731162
if (!SSL_CTX_set0_tmp_dh_pkey(ctx, pkey))
11741163
ossl_raise(eSSLError, "SSL_CTX_set0_tmp_dh_pkey");
11751164
EVP_PKEY_up_ref(pkey);
@@ -1178,6 +1167,9 @@ ossl_sslctx_set_tmp_dh(VALUE self, VALUE arg)
11781167
ossl_raise(eSSLError, "SSL_CTX_set_tmp_dh");
11791168
#endif
11801169

1170+
// Turn off the "auto" DH parameters set by ossl_sslctx_s_alloc()
1171+
SSL_CTX_set_dh_auto(ctx, 0);
1172+
11811173
return arg;
11821174
}
11831175
#endif
@@ -2865,6 +2857,23 @@ Init_ossl_ssl(void)
28652857
*/
28662858
rb_attr(cSSLContext, rb_intern_const("client_cert_cb"), 1, 1, Qfalse);
28672859

2860+
#ifndef OPENSSL_NO_DH
2861+
/*
2862+
* A callback invoked when DH parameters are required for ephemeral DH key
2863+
* exchange.
2864+
*
2865+
* The callback is invoked with the SSLSocket, a
2866+
* flag indicating the use of an export cipher and the keylength
2867+
* required.
2868+
*
2869+
* The callback must return an OpenSSL::PKey::DH instance of the correct
2870+
* key length.
2871+
*
2872+
* <b>Deprecated in version 3.0.</b> Use #tmp_dh= instead.
2873+
*/
2874+
rb_attr(cSSLContext, rb_intern_const("tmp_dh_callback"), 1, 1, Qfalse);
2875+
#endif
2876+
28682877
/*
28692878
* Sets the context in which a session can be reused. This allows
28702879
* sessions for multiple applications to be distinguished, for example, by
@@ -3258,7 +3267,6 @@ Init_ossl_ssl(void)
32583267
sym_wait_readable = ID2SYM(rb_intern_const("wait_readable"));
32593268
sym_wait_writable = ID2SYM(rb_intern_const("wait_writable"));
32603269

3261-
id_tmp_dh_callback = rb_intern_const("tmp_dh_callback");
32623270
id_npn_protocols_encoded = rb_intern_const("npn_protocols_encoded");
32633271
id_each = rb_intern_const("each");
32643272

@@ -3289,6 +3297,7 @@ Init_ossl_ssl(void)
32893297
DefIVarID(servername_cb);
32903298
DefIVarID(verify_hostname);
32913299
DefIVarID(keylog_cb);
3300+
DefIVarID(tmp_dh_callback);
32923301

32933302
DefIVarID(io);
32943303
DefIVarID(context);

lib/openssl/ssl.rb

Lines changed: 0 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -32,25 +32,6 @@ class SSLContext
3232
}.call
3333
}
3434

35-
if defined?(OpenSSL::PKey::DH)
36-
DH_ffdhe2048 = OpenSSL::PKey::DH.new <<-_end_of_pem_
37-
-----BEGIN DH PARAMETERS-----
38-
MIIBCAKCAQEA//////////+t+FRYortKmq/cViAnPTzx2LnFg84tNpWp4TZBFGQz
39-
+8yTnc4kmz75fS/jY2MMddj2gbICrsRhetPfHtXV/WVhJDP1H18GbtCFY2VVPe0a
40-
87VXE15/V8k1mE8McODmi3fipona8+/och3xWKE2rec1MKzKT0g6eXq8CrGCsyT7
41-
YdEIqUuyyOP7uWrat2DX9GgdT0Kj3jlN9K5W7edjcrsZCwenyO4KbXCeAvzhzffi
42-
7MA0BM0oNC9hkXL+nOmFg/+OTxIy7vKBg8P+OxtMb61zO7X8vC7CIAXFjvGDfRaD
43-
ssbzSibBsu/6iGtCOGEoXJf//////////wIBAg==
44-
-----END DH PARAMETERS-----
45-
_end_of_pem_
46-
private_constant :DH_ffdhe2048
47-
48-
DEFAULT_TMP_DH_CALLBACK = lambda { |ctx, is_export, keylen| # :nodoc:
49-
warn "using default DH parameters." if $VERBOSE
50-
DH_ffdhe2048
51-
}
52-
end
53-
5435
if !OpenSSL::OPENSSL_VERSION.start_with?("OpenSSL")
5536
DEFAULT_PARAMS.merge!(
5637
min_version: OpenSSL::SSL::TLS1_VERSION,
@@ -92,19 +73,6 @@ class SSLContext
9273
DEFAULT_CERT_STORE = OpenSSL::X509::Store.new # :nodoc:
9374
DEFAULT_CERT_STORE.set_default_paths
9475

95-
# A callback invoked when DH parameters are required for ephemeral DH key
96-
# exchange.
97-
#
98-
# The callback is invoked with the SSLSocket, a
99-
# flag indicating the use of an export cipher and the keylength
100-
# required.
101-
#
102-
# The callback must return an OpenSSL::PKey::DH instance of the correct
103-
# key length.
104-
#
105-
# <b>Deprecated in version 3.0.</b> Use #tmp_dh= instead.
106-
attr_accessor :tmp_dh_callback
107-
10876
# A callback invoked at connect time to distinguish between multiple
10977
# server names.
11078
#
@@ -456,10 +424,6 @@ def client_cert_cb
456424
@context.client_cert_cb
457425
end
458426

459-
def tmp_dh_callback
460-
@context.tmp_dh_callback || OpenSSL::SSL::SSLContext::DEFAULT_TMP_DH_CALLBACK
461-
end
462-
463427
def session_new_cb
464428
@context.session_new_cb
465429
end

test/openssl/test_provider.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ def test_openssl_legacy_provider
4646

4747
with_openssl(<<-'end;')
4848
begin
49+
OpenSSL::Provider.load("default")
4950
OpenSSL::Provider.load("legacy")
5051
rescue OpenSSL::Provider::ProviderError
5152
omit "Only for OpenSSL with legacy provider"

test/openssl/test_ssl.rb

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2129,11 +2129,7 @@ def test_connect_works_when_setting_dh_callback_to_nil
21292129
ctx.tmp_dh_callback = nil
21302130
}
21312131
start_server(ctx_proc: ctx_proc) do |port|
2132-
EnvUtil.suppress_warning { # uses default callback
2133-
assert_nothing_raised {
2134-
server_connect(port) { }
2135-
}
2136-
}
2132+
assert_nothing_raised { server_connect(port) { } }
21372133
end
21382134
end
21392135

0 commit comments

Comments
 (0)