ruby-changes:42411
From: nobu <ko1@a...>
Date: Mon, 4 Apr 2016 23:10:09 +0900 (JST)
Subject: [ruby-changes:42411] nobu:r54485 (trunk): openssl: Access to ephemeral TLS session key
nobu 2016-04-05 00:06:46 +0900 (Tue, 05 Apr 2016) New Revision: 54485 https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=54485 Log: 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. Modified files: trunk/ChangeLog trunk/ext/openssl/extconf.rb trunk/ext/openssl/ossl_ssl.c trunk/test/openssl/test_ssl.rb trunk/test/openssl/utils.rb Index: test/openssl/utils.rb =================================================================== --- test/openssl/utils.rb (revision 54484) +++ test/openssl/utils.rb (revision 54485) @@ -277,6 +277,7 @@ AQjjxMXhwULlmuR/K+WwlaZPiLIBYalLAZQ7ZbOP https://github.com/ruby/ruby/blob/trunk/test/openssl/utils.rb#L277 ctx.cert = @svr_cert ctx.key = @svr_key ctx.tmp_dh_callback = proc { OpenSSL::TestUtils::TEST_KEY_DH1024 } + ctx.tmp_ecdh_callback = proc { OpenSSL::TestUtils::TEST_KEY_EC_P256V1 } ctx.verify_mode = verify_mode ctx_proc.call(ctx) if ctx_proc Index: test/openssl/test_ssl.rb =================================================================== --- test/openssl/test_ssl.rb (revision 54484) +++ test/openssl/test_ssl.rb (revision 54485) @@ -1169,6 +1169,29 @@ end https://github.com/ruby/ruby/blob/trunk/test/openssl/test_ssl.rb#L1169 } end + def test_get_ephemeral_key + return unless OpenSSL::SSL::SSLSocket.method_defined?(:tmp_key) + ciphers = { + 'ECDHE-RSA-AES128-SHA' => OpenSSL::PKey::EC, + 'DHE-RSA-AES128-SHA' => OpenSSL::PKey::DH, + 'AES128-SHA' => nil + } + conf_proc = Proc.new { |ctx| ctx.ciphers = 'ALL' } + start_server(OpenSSL::SSL::VERIFY_NONE, true, :ctx_proc => conf_proc) do |server, port| + ciphers.each do |cipher, ephemeral| + ctx = OpenSSL::SSL::SSLContext.new + ctx.ciphers = cipher + server_connect(port, ctx) do |ssl| + if ephemeral + assert_equal(ephemeral, ssl.tmp_key.class) + else + assert_nil(ssl.tmp_key) + end + end + end + end + end + private def start_server_version(version, ctx_proc=nil, server_proc=nil, &blk) Index: ext/openssl/extconf.rb =================================================================== --- ext/openssl/extconf.rb (revision 54484) +++ ext/openssl/extconf.rb (revision 54485) @@ -111,6 +111,7 @@ have_func("TLSv1_2_server_method") https://github.com/ruby/ruby/blob/trunk/ext/openssl/extconf.rb#L111 have_func("TLSv1_2_client_method") have_func("SSL_CTX_set_alpn_select_cb") have_func("SSL_CTX_set_next_proto_select_cb") +have_macro("SSL_get_server_tmp_key", ['openssl/ssl.h']) && $defs.push("-DHAVE_SSL_GET_SERVER_TMP_KEY") unless have_func("SSL_set_tlsext_host_name", ['openssl/ssl.h']) have_macro("SSL_set_tlsext_host_name", ['openssl/ssl.h']) && $defs.push("-DHAVE_SSL_SET_TLSEXT_HOST_NAME") end Index: ext/openssl/ossl_ssl.c =================================================================== --- ext/openssl/ossl_ssl.c (revision 54484) +++ ext/openssl/ossl_ssl.c (revision 54485) @@ -1912,6 +1912,25 @@ ossl_ssl_alpn_protocol(VALUE self) https://github.com/ruby/ruby/blob/trunk/ext/openssl/ossl_ssl.c#L1912 return rb_str_new((const char *) out, outlen); } # endif + +# ifdef HAVE_SSL_GET_SERVER_TMP_KEY +/* + * call-seq: + * ssl.tmp_key => PKey or nil + * + * Returns the ephemeral key used in case of forward secrecy cipher + */ +static VALUE +ossl_ssl_tmp_key(VALUE self) +{ + SSL *ssl; + EVP_PKEY *key; + ossl_ssl_data_get_struct(self, ssl); + if (!SSL_get_server_tmp_key(ssl, &key)) + return Qnil; + return ossl_pkey_new(key); +} +# endif /* defined(HAVE_SSL_GET_SERVER_TMP_KEY) */ #endif /* !defined(OPENSSL_NO_SOCK) */ void @@ -2306,6 +2325,9 @@ Init_ossl_ssl(void) https://github.com/ruby/ruby/blob/trunk/ext/openssl/ossl_ssl.c#L2325 rb_define_method(cSSLSocket, "session=", ossl_ssl_set_session, 1); rb_define_method(cSSLSocket, "verify_result", ossl_ssl_get_verify_result, 0); rb_define_method(cSSLSocket, "client_ca", ossl_ssl_get_client_ca_list, 0); +# ifdef HAVE_SSL_GET_SERVER_TMP_KEY + rb_define_method(cSSLSocket, "tmp_key", ossl_ssl_tmp_key, 0); +# endif # ifdef HAVE_SSL_CTX_SET_ALPN_SELECT_CB rb_define_method(cSSLSocket, "alpn_protocol", ossl_ssl_alpn_protocol, 0); # endif Index: ChangeLog =================================================================== --- ChangeLog (revision 54484) +++ ChangeLog (revision 54485) @@ -1,3 +1,11 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1 +Tue Apr 5 00:06:44 2016 Aeris <aeris@i...> + + * 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. + Mon Apr 4 23:37:05 2016 Nobuyoshi Nakada <nobu@r...> * vm_core.h (rb_vm_struct): make at_exit a single linked list but -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/