Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ssl: add SSLContext#tmp_dh= #459

Merged
merged 2 commits into from
Sep 27, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions ext/openssl/extconf.rb
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,9 @@ def find_openssl_library
# added in 1.1.1
have_func("EVP_PKEY_check")

# added in 3.0.0
have_func("SSL_set0_tmp_dh_pkey")

Logging::message "=== Checking done. ===\n"

create_header
Expand Down
49 changes: 49 additions & 0 deletions ext/openssl/ossl_ssl.c
Original file line number Diff line number Diff line change
Expand Up @@ -987,6 +987,52 @@ ossl_sslctx_set_ciphers(VALUE self, VALUE v)
return v;
}

#ifndef OPENSSL_NO_DH
/*
* call-seq:
* ctx.tmp_dh = pkey
*
* Sets DH parameters used for ephemeral DH key exchange. This is relevant for
* servers only.
*
* +pkey+ is an instance of OpenSSL::PKey::DH. Note that key components
* contained in the key object, if any, are ignored. The server will always
* generate a new key pair for each handshake.
*
* Added in version 3.0. See also the man page SSL_set0_tmp_dh_pkey(3).
*
* Example:
* ctx = OpenSSL::SSL::SSLContext.new
* ctx.tmp_dh = OpenSSL::DH.generate(2048)
* svr = OpenSSL::SSL::SSLServer.new(tcp_svr, ctx)
* Thread.new { svr.accept }
*/
static VALUE
ossl_sslctx_set_tmp_dh(VALUE self, VALUE arg)
{
SSL_CTX *ctx;
EVP_PKEY *pkey;

rb_check_frozen(self);
GetSSLCTX(self, ctx);
pkey = GetPKeyPtr(arg);

if (EVP_PKEY_base_id(pkey) != EVP_PKEY_DH)
rb_raise(eSSLError, "invalid pkey type %s (expected DH)",
OBJ_nid2sn(EVP_PKEY_base_id(pkey)));
#ifdef HAVE_SSL_SET0_TMP_DH_PKEY
if (!SSL_CTX_set0_tmp_dh_pkey(ctx, pkey))
ossl_raise(eSSLError, "SSL_CTX_set0_tmp_dh_pkey");
EVP_PKEY_up_ref(pkey);
#else
if (!SSL_CTX_set_tmp_dh(ctx, EVP_PKEY_get0_DH(pkey)))
ossl_raise(eSSLError, "SSL_CTX_set_tmp_dh");
#endif

return arg;
}
#endif

#if !defined(OPENSSL_NO_EC)
/*
* call-seq:
Expand Down Expand Up @@ -2670,6 +2716,9 @@ Init_ossl_ssl(void)
ossl_sslctx_set_minmax_proto_version, 2);
rb_define_method(cSSLContext, "ciphers", ossl_sslctx_get_ciphers, 0);
rb_define_method(cSSLContext, "ciphers=", ossl_sslctx_set_ciphers, 1);
#ifndef OPENSSL_NO_DH
rb_define_method(cSSLContext, "tmp_dh=", ossl_sslctx_set_tmp_dh, 1);
#endif
rb_define_method(cSSLContext, "ecdh_curves=", ossl_sslctx_set_ecdh_curves, 1);
rb_define_method(cSSLContext, "security_level", ossl_sslctx_get_security_level, 0);
rb_define_method(cSSLContext, "security_level=", ossl_sslctx_set_security_level, 1);
Expand Down
12 changes: 5 additions & 7 deletions lib/openssl/ssl.rb
Original file line number Diff line number Diff line change
Expand Up @@ -91,15 +91,17 @@ class SSLContext
DEFAULT_CERT_STORE.set_default_paths
DEFAULT_CERT_STORE.flags = OpenSSL::X509::V_FLAG_CRL_CHECK_ALL

# A callback invoked when DH parameters are required.
# A callback invoked when DH parameters are required for ephemeral DH key
# exchange.
#
# The callback is invoked with the Session for the key exchange, an
# The callback is invoked with the SSLSocket, a
# flag indicating the use of an export cipher and the keylength
# required.
#
# The callback must return an OpenSSL::PKey::DH instance of the correct
# key length.

#
# <b>Deprecated in version 3.0.</b> Use #tmp_dh= instead.
attr_accessor :tmp_dh_callback

# A callback invoked at connect time to distinguish between multiple
Expand Down Expand Up @@ -432,10 +434,6 @@ def tmp_dh_callback
@context.tmp_dh_callback || OpenSSL::SSL::SSLContext::DEFAULT_TMP_DH_CALLBACK
end

def tmp_ecdh_callback
@context.tmp_ecdh_callback
end

def session_new_cb
@context.session_new_cb
end
Expand Down
24 changes: 17 additions & 7 deletions test/openssl/test_ssl.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1583,13 +1583,11 @@ def test_fallback_scsv
end
end

def test_dh_callback
pend "TLS 1.2 is not supported" unless tls12_supported?

def test_tmp_dh_callback
dh = Fixtures.pkey("dh-1")
called = false
ctx_proc = -> ctx {
ctx.ssl_version = :TLSv1_2
ctx.max_version = :TLS1_2
ctx.ciphers = "DH:!NULL"
ctx.tmp_dh_callback = ->(*args) {
called = true
Expand All @@ -1605,10 +1603,8 @@ def test_dh_callback
end

def test_connect_works_when_setting_dh_callback_to_nil
pend "TLS 1.2 is not supported" unless tls12_supported?

ctx_proc = -> ctx {
ctx.ssl_version = :TLSv1_2
ctx.max_version = :TLS1_2
ctx.ciphers = "DH:!NULL" # use DH
ctx.tmp_dh_callback = nil
}
Expand All @@ -1621,6 +1617,20 @@ def test_connect_works_when_setting_dh_callback_to_nil
end
end

def test_tmp_dh
dh = Fixtures.pkey("dh-1")
ctx_proc = -> ctx {
ctx.max_version = :TLS1_2
ctx.ciphers = "DH:!NULL" # use DH
ctx.tmp_dh = dh
}
start_server(ctx_proc: ctx_proc) do |port|
server_connect(port) { |ssl|
assert_equal dh.to_der, ssl.tmp_key.to_der
}
end
end

def test_ecdh_curves_tls12
pend "EC is disabled" unless defined?(OpenSSL::PKey::EC)

Expand Down