Skip to content

Commit bd6a495

Browse files
noburhenium
authored andcommitted
openssl: Access to ephemeral TLS session key
* ext/openssl/ossl_ssl.c (ossl_ssl_tmp_key): Access to ephemeral TLS session key in case of forward secrecy cipher. Only available since OpenSSL 1.0.2. [Fix GH-1318] * ext/openssl/extconf.rb: Check for SSL_get_server_tmp_key. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@54485 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
1 parent b0996b8 commit bd6a495

4 files changed

Lines changed: 47 additions & 0 deletions

File tree

ext/openssl/extconf.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@
111111
have_func("TLSv1_2_client_method")
112112
have_func("SSL_CTX_set_alpn_select_cb")
113113
have_func("SSL_CTX_set_next_proto_select_cb")
114+
have_macro("SSL_get_server_tmp_key", ['openssl/ssl.h']) && $defs.push("-DHAVE_SSL_GET_SERVER_TMP_KEY")
114115
unless have_func("SSL_set_tlsext_host_name", ['openssl/ssl.h'])
115116
have_macro("SSL_set_tlsext_host_name", ['openssl/ssl.h']) && $defs.push("-DHAVE_SSL_SET_TLSEXT_HOST_NAME")
116117
end

ext/openssl/ossl_ssl.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1912,6 +1912,25 @@ ossl_ssl_alpn_protocol(VALUE self)
19121912
return rb_str_new((const char *) out, outlen);
19131913
}
19141914
# endif
1915+
1916+
# ifdef HAVE_SSL_GET_SERVER_TMP_KEY
1917+
/*
1918+
* call-seq:
1919+
* ssl.tmp_key => PKey or nil
1920+
*
1921+
* Returns the ephemeral key used in case of forward secrecy cipher
1922+
*/
1923+
static VALUE
1924+
ossl_ssl_tmp_key(VALUE self)
1925+
{
1926+
SSL *ssl;
1927+
EVP_PKEY *key;
1928+
ossl_ssl_data_get_struct(self, ssl);
1929+
if (!SSL_get_server_tmp_key(ssl, &key))
1930+
return Qnil;
1931+
return ossl_pkey_new(key);
1932+
}
1933+
# endif /* defined(HAVE_SSL_GET_SERVER_TMP_KEY) */
19151934
#endif /* !defined(OPENSSL_NO_SOCK) */
19161935

19171936
void
@@ -2306,6 +2325,9 @@ Init_ossl_ssl(void)
23062325
rb_define_method(cSSLSocket, "session=", ossl_ssl_set_session, 1);
23072326
rb_define_method(cSSLSocket, "verify_result", ossl_ssl_get_verify_result, 0);
23082327
rb_define_method(cSSLSocket, "client_ca", ossl_ssl_get_client_ca_list, 0);
2328+
# ifdef HAVE_SSL_GET_SERVER_TMP_KEY
2329+
rb_define_method(cSSLSocket, "tmp_key", ossl_ssl_tmp_key, 0);
2330+
# endif
23092331
# ifdef HAVE_SSL_CTX_SET_ALPN_SELECT_CB
23102332
rb_define_method(cSSLSocket, "alpn_protocol", ossl_ssl_alpn_protocol, 0);
23112333
# endif

test/test_ssl.rb

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1169,6 +1169,29 @@ def test_sync_close_without_connect
11691169
}
11701170
end
11711171

1172+
def test_get_ephemeral_key
1173+
return unless OpenSSL::SSL::SSLSocket.method_defined?(:tmp_key)
1174+
ciphers = {
1175+
'ECDHE-RSA-AES128-SHA' => OpenSSL::PKey::EC,
1176+
'DHE-RSA-AES128-SHA' => OpenSSL::PKey::DH,
1177+
'AES128-SHA' => nil
1178+
}
1179+
conf_proc = Proc.new { |ctx| ctx.ciphers = 'ALL' }
1180+
start_server(OpenSSL::SSL::VERIFY_NONE, true, :ctx_proc => conf_proc) do |server, port|
1181+
ciphers.each do |cipher, ephemeral|
1182+
ctx = OpenSSL::SSL::SSLContext.new
1183+
ctx.ciphers = cipher
1184+
server_connect(port, ctx) do |ssl|
1185+
if ephemeral
1186+
assert_equal(ephemeral, ssl.tmp_key.class)
1187+
else
1188+
assert_nil(ssl.tmp_key)
1189+
end
1190+
end
1191+
end
1192+
end
1193+
end
1194+
11721195
private
11731196

11741197
def start_server_version(version, ctx_proc=nil, server_proc=nil, &blk)

test/utils.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,7 @@ def start_server(verify_mode, start_immediately, args = {}, &block)
278278
ctx.cert = @svr_cert
279279
ctx.key = @svr_key
280280
ctx.tmp_dh_callback = proc { OpenSSL::TestUtils::TEST_KEY_DH1024 }
281+
ctx.tmp_ecdh_callback = proc { OpenSSL::TestUtils::TEST_KEY_EC_P256V1 }
281282
ctx.verify_mode = verify_mode
282283
ctx_proc.call(ctx) if ctx_proc
283284

0 commit comments

Comments
 (0)