From c0c09a13112f21cde05f2c4b0fff641addd15bb6 Mon Sep 17 00:00:00 2001 From: Klaus Trainer Date: Wed, 17 Jul 2013 22:15:31 +0200 Subject: Work around broken elliptic-curve cipher suites Unfortunately the implementation of elliptic-curve ciphers that has been introduced in R16B01 is incomplete. Depending on the particular client, this can cause the TLS handshake to break during key agreement. As it turns out that most popular browsers (e.g. Firefox, Chromium, and Safari) are affected by this bug, we provide this workaround. This workaround makes sure that only cipher suite implementations that are not known to be broken are supported by default. --- src/ranch_ssl.erl | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/ranch_ssl.erl b/src/ranch_ssl.erl index 512f3b4..98b2f5e 100644 --- a/src/ranch_ssl.erl +++ b/src/ranch_ssl.erl @@ -136,10 +136,11 @@ listen(Opts) -> true = lists:keymember(cert, 1, Opts) orelse lists:keymember(certfile, 1, Opts), Opts2 = ranch:set_option_default(Opts, backlog, 1024), + Opts3 = ranch:set_option_default(Opts2, ciphers, unbroken_cipher_suites()), %% We set the port to 0 because it is given in the Opts directly. %% The port in the options takes precedence over the one in the %% first argument. - ssl:listen(0, ranch:filter_options(Opts2, + ssl:listen(0, ranch:filter_options(Opts3, [backlog, cacertfile, cacerts, cert, certfile, ciphers, fail_if_no_peer_cert, ip, key, keyfile, next_protocols_advertised, nodelay, password, port, raw, reuse_session, reuse_sessions, @@ -269,3 +270,20 @@ ssl_accept(Socket, Timeout) -> {error, Reason} -> {error, {ssl_accept, Reason}} end. + +%% Unfortunately the implementation of elliptic-curve ciphers that has +%% been introduced in R16B01 is incomplete. Depending on the particular +%% client, this can cause the TLS handshake to break during key +%% agreement. Depending on the ssl application version, this function +%% returns a list of all cipher suites that are supported by default, +%% minus the elliptic-curve ones. +-spec unbroken_cipher_suites() -> [ssl:erl_cipher_suite()]. +unbroken_cipher_suites() -> + case proplists:get_value(ssl_app, ssl:versions()) of + "5.3" -> + lists:filter(fun(Suite) -> + string:left(atom_to_list(element(1, Suite)), 4) =/= "ecdh" + end, ssl:cipher_suites()); + _ -> + ssl:cipher_suites() + end. -- cgit v1.2.3