Skip to content

Commit

Permalink
ssl: remove SSL::SSLContext#tmp_ecdh_callback
Browse files Browse the repository at this point in the history
The underlying API SSL_CTX_set_tmp_ecdh_callback() was removed by
LibreSSL >= 2.6.1 and OpenSSL >= 1.1.0, in other words, it is not
supported by any non-EOL versions of OpenSSL.

The wrapper was initially implemented in Ruby 2.3 and has been
deprecated since Ruby/OpenSSL 2.0 (bundled with Ruby 2.4) with explicit
warning with rb_warn().
  • Loading branch information
rhenium committed Aug 13, 2020
1 parent 0cdd377 commit ee037e1
Show file tree
Hide file tree
Showing 3 changed files with 3 additions and 94 deletions.
1 change: 0 additions & 1 deletion ext/openssl/extconf.rb
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,6 @@ def find_openssl_library
have_func("X509_STORE_up_ref")
have_func("SSL_SESSION_up_ref")
have_func("EVP_PKEY_up_ref")
have_func("SSL_CTX_set_tmp_ecdh_callback(NULL, NULL)", "openssl/ssl.h") # removed
have_func("SSL_CTX_set_min_proto_version(NULL, 0)", "openssl/ssl.h")
have_func("SSL_CTX_get_security_level")
have_func("X509_get0_notBefore")
Expand Down
72 changes: 3 additions & 69 deletions ext/openssl/ossl_ssl.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,14 @@ VALUE cSSLSocket;
static VALUE eSSLErrorWaitReadable;
static VALUE eSSLErrorWaitWritable;

static ID id_call, ID_callback_state, id_tmp_dh_callback, id_tmp_ecdh_callback,
static ID id_call, ID_callback_state, id_tmp_dh_callback,
id_npn_protocols_encoded;
static VALUE sym_exception, sym_wait_readable, sym_wait_writable;

static ID id_i_cert_store, id_i_ca_file, id_i_ca_path, id_i_verify_mode,
id_i_verify_depth, id_i_verify_callback, id_i_client_ca,
id_i_renegotiation_cb, id_i_cert, id_i_key, id_i_extra_chain_cert,
id_i_client_cert_cb, id_i_tmp_ecdh_callback, id_i_timeout,
id_i_client_cert_cb, id_i_timeout,
id_i_session_id_context, id_i_session_get_cb, id_i_session_new_cb,
id_i_session_remove_cb, id_i_npn_select_cb, id_i_npn_protocols,
id_i_alpn_select_cb, id_i_alpn_protocols, id_i_servername_cb,
Expand Down Expand Up @@ -231,8 +231,7 @@ ossl_client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey)
return 1;
}

#if !defined(OPENSSL_NO_DH) || \
!defined(OPENSSL_NO_EC) && defined(HAVE_SSL_CTX_SET_TMP_ECDH_CALLBACK)
#if !defined(OPENSSL_NO_DH)
struct tmp_dh_callback_args {
VALUE ssl_obj;
ID id;
Expand Down Expand Up @@ -289,35 +288,6 @@ ossl_tmp_dh_callback(SSL *ssl, int is_export, int keylength)
}
#endif /* OPENSSL_NO_DH */

#if !defined(OPENSSL_NO_EC) && defined(HAVE_SSL_CTX_SET_TMP_ECDH_CALLBACK)
static EC_KEY *
ossl_tmp_ecdh_callback(SSL *ssl, int is_export, int keylength)
{
VALUE rb_ssl;
EVP_PKEY *pkey;
struct tmp_dh_callback_args args;
int state;

rb_ssl = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx);
args.ssl_obj = rb_ssl;
args.id = id_tmp_ecdh_callback;
args.is_export = is_export;
args.keylength = keylength;
args.type = EVP_PKEY_EC;

pkey = (EVP_PKEY *)rb_protect((VALUE (*)(VALUE))ossl_call_tmp_dh_callback,
(VALUE)&args, &state);
if (state) {
rb_ivar_set(rb_ssl, ID_callback_state, INT2NUM(state));
return NULL;
}
if (!pkey)
return NULL;

return EVP_PKEY_get0_EC_KEY(pkey);
}
#endif

static VALUE
call_verify_certificate_identity(VALUE ctx_v)
{
Expand Down Expand Up @@ -797,26 +767,6 @@ ossl_sslctx_setup(VALUE self)
SSL_CTX_set_tmp_dh_callback(ctx, ossl_tmp_dh_callback);
#endif

#if !defined(OPENSSL_NO_EC)
/* We added SSLContext#tmp_ecdh_callback= in Ruby 2.3.0,
* but SSL_CTX_set_tmp_ecdh_callback() was removed in OpenSSL 1.1.0. */
if (RTEST(rb_attr_get(self, id_i_tmp_ecdh_callback))) {
# if defined(HAVE_SSL_CTX_SET_TMP_ECDH_CALLBACK)
rb_warn("#tmp_ecdh_callback= is deprecated; use #ecdh_curves= instead");
SSL_CTX_set_tmp_ecdh_callback(ctx, ossl_tmp_ecdh_callback);
# if defined(HAVE_SSL_CTX_SET_ECDH_AUTO)
/* tmp_ecdh_callback and ecdh_auto conflict; OpenSSL ignores
* tmp_ecdh_callback. So disable ecdh_auto. */
if (!SSL_CTX_set_ecdh_auto(ctx, 0))
ossl_raise(eSSLError, "SSL_CTX_set_ecdh_auto");
# endif
# else
ossl_raise(eSSLError, "OpenSSL does not support tmp_ecdh_callback; "
"use #ecdh_curves= instead");
# endif
}
#endif /* OPENSSL_NO_EC */

#ifdef HAVE_SSL_CTX_SET_POST_HANDSHAKE_AUTH
SSL_CTX_set_post_handshake_auth(ctx, 1);
#endif
Expand Down Expand Up @@ -2632,20 +2582,6 @@ Init_ossl_ssl(void)
*/
rb_attr(cSSLContext, rb_intern("client_cert_cb"), 1, 1, Qfalse);

#if !defined(OPENSSL_NO_EC) && defined(HAVE_SSL_CTX_SET_TMP_ECDH_CALLBACK)
/*
* A callback invoked when ECDH parameters are required.
*
* The callback is invoked with the Session for the key exchange, an
* flag indicating the use of an export cipher and the keylength
* required.
*
* The callback is deprecated. This does not work with recent versions of
* OpenSSL. Use OpenSSL::SSL::SSLContext#ecdh_curves= instead.
*/
rb_attr(cSSLContext, rb_intern("tmp_ecdh_callback"), 1, 1, Qfalse);
#endif

/*
* Sets the context in which a session can be reused. This allows
* sessions for multiple applications to be distinguished, for example, by
Expand Down Expand Up @@ -2997,7 +2933,6 @@ Init_ossl_ssl(void)
sym_wait_writable = ID2SYM(rb_intern("wait_writable"));

id_tmp_dh_callback = rb_intern("tmp_dh_callback");
id_tmp_ecdh_callback = rb_intern("tmp_ecdh_callback");
id_npn_protocols_encoded = rb_intern("npn_protocols_encoded");

#define DefIVarID(name) do \
Expand All @@ -3015,7 +2950,6 @@ Init_ossl_ssl(void)
DefIVarID(key);
DefIVarID(extra_chain_cert);
DefIVarID(client_cert_cb);
DefIVarID(tmp_ecdh_callback);
DefIVarID(timeout);
DefIVarID(session_id_context);
DefIVarID(session_get_cb);
Expand Down
24 changes: 0 additions & 24 deletions test/openssl/test_ssl.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1603,30 +1603,6 @@ def test_connect_works_when_setting_dh_callback_to_nil
end
end

def test_tmp_ecdh_callback
pend "EC is disabled" unless defined?(OpenSSL::PKey::EC)
pend "tmp_ecdh_callback is not supported" unless \
OpenSSL::SSL::SSLContext.method_defined?(:tmp_ecdh_callback)
pend "LibreSSL 2.6 has broken SSL_CTX_set_tmp_ecdh_callback()" \
if libressl?(2, 6, 1)

EnvUtil.suppress_warning do # tmp_ecdh_callback is deprecated (2016-05)
called = false
ctx_proc = -> ctx {
ctx.ciphers = "DEFAULT:!kRSA:!kEDH"
ctx.tmp_ecdh_callback = -> (*args) {
called = true
OpenSSL::PKey::EC.new "prime256v1"
}
}
start_server(ctx_proc: ctx_proc) do |port|
server_connect(port) { |s|
assert called, "tmp_ecdh_callback should be called"
}
end
end
end

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

Expand Down

0 comments on commit ee037e1

Please sign in to comment.