Skip to content

Commit

Permalink
TLS Fallback Signaling Cipher Suite Value
Browse files Browse the repository at this point in the history
Support for fallback SCSV [RFC 7507](https://tools.ietf.org/html/rfc7507).

Expected behaviour is to refuse connection if the client signals a protocol with
the fallback flag but the server supports a better one (downgrade attack detection).
  • Loading branch information
aeris committed Nov 3, 2017
1 parent d834e86 commit 7c4028a
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 0 deletions.
23 changes: 23 additions & 0 deletions ext/openssl/ossl_ssl.c
Original file line number Diff line number Diff line change
Expand Up @@ -1193,6 +1193,26 @@ ossl_sslctx_set_security_level(VALUE self, VALUE value)
return value;
}

#ifdef SSL_MODE_SEND_FALLBACK_SCSV
/*
* call-seq:
* ctx.enable_fallback_scsv() => nil
*
* Activate TLS_FALLBACK_SCSV for this context.
* See RFC 7507.
*/
static VALUE
ossl_sslctx_enable_fallback_scsv(VALUE self)
{
SSL_CTX *ctx;

GetSSLCTX(self, ctx);
SSL_CTX_set_mode(ctx, SSL_MODE_SEND_FALLBACK_SCSV);

return Qnil;
}
#endif

/*
* call-seq:
* ctx.session_add(session) -> true | false
Expand Down Expand Up @@ -2558,6 +2578,9 @@ Init_ossl_ssl(void)
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);
#ifdef SSL_MODE_SEND_FALLBACK_SCSV
rb_define_method(cSSLContext, "enable_fallback_scsv", ossl_sslctx_enable_fallback_scsv, 0);
#endif

rb_define_method(cSSLContext, "setup", ossl_sslctx_setup, 0);
rb_define_alias(cSSLContext, "freeze", "setup");
Expand Down
53 changes: 53 additions & 0 deletions test/test_ssl.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1222,6 +1222,59 @@ def test_get_ephemeral_key
end
end

def test_fallback_scsv
pend "Fallback SCSV is not supported" unless OpenSSL::SSL::SSLContext.method_defined?( :enable_fallback_scsv)

start_server do |port|
ctx = OpenSSL::SSL::SSLContext.new
ctx.max_version = OpenSSL::SSL::TLS1_2_VERSION
# Here is OK
# TLS1.2 supported and this is what we ask the first time
server_connect(port, ctx)
end

ctx_proc = proc { |ctx|
ctx.max_version = OpenSSL::SSL::TLS1_1_VERSION
}
start_server(ctx_proc: ctx_proc) do |port|
ctx = OpenSSL::SSL::SSLContext.new
ctx.enable_fallback_scsv
ctx.max_version = OpenSSL::SSL::TLS1_1_VERSION
# Here is OK too
# TLS1.2 not supported, fallback to TLS1.1 and signaling the fallback
# Server doesn't support better, so connection OK
server_connect(port, ctx)
end

# Here is not OK
# TLS1.2 is supported, fallback to TLS1.1 (downgrade attack) and signaling the fallback
# Server support better, so refuse the connection
sock1, sock2 = socketpair
begin
ctx1 = OpenSSL::SSL::SSLContext.new
s1 = OpenSSL::SSL::SSLSocket.new(sock1, ctx1)

ctx2 = OpenSSL::SSL::SSLContext.new
ctx2.enable_fallback_scsv
ctx2.max_version = OpenSSL::SSL::TLS1_1_VERSION
s2 = OpenSSL::SSL::SSLSocket.new(sock2, ctx2)
t = Thread.new {
assert_raise_with_message(OpenSSL::SSL::SSLError, /inappropriate fallback/) {
s2.connect
}
}

assert_raise_with_message(OpenSSL::SSL::SSLError, /inappropriate fallback/) {
s1.accept
}

assert t.join
ensure
sock1.close
sock2.close
end
end

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

Expand Down

0 comments on commit 7c4028a

Please sign in to comment.