From kennethlakin@REDACTED Tue May 3 07:18:51 2016 From: kennethlakin@REDACTED (Kenneth Lakin) Date: Mon, 2 May 2016 22:18:51 -0700 Subject: [erlang-patches] ssl: Add BEAST mitigation selection option Message-ID: <572834BB.40305@gmail.com> I'm more than happy to field questions or participate in additional discussion regarding the proposed new feature. The PR is at: https://github.com/erlang/otp/pull/1041 You should be able to fetch with: git fetch git://github.com/kennethlakin/otp.git beast-mitigation-options And compare with: https://github.com/erlang/otp/compare/master...kennethlakin:beast-mitigation-options https://github.com/erlang/otp/compare/master...kennethlakin:beast-mitigation-options.patch Here's the EEP Light describing the new feature: Some legacy TLSv1.0 clients react poorly to certain BEAST mitigation methods. (In particular, every TLSv1.0/PEAP client I have tested fails to function with the 1/n-1 content split method, but works just fine with the 0/n split method.) For greater compatibility, this patch adds a three-way switch to control the BEAST countermeasure used with the given connection, as well as tests and documentation updates. Because the switch defaults to 1/n-1 mode, there are no known incompatibilities. The 1/n-1 content splitting mode was the default for all SSLv3 and TLSv1.0 connections that did not use an RC4 cipher suite. TLSv1.1, TLSv1.2, and connections using an RC4 cipher are not vulnerable to BEAST, and do not need content splitting. It is possible -but unlikely- that I have misunderstood how the 0/n content splitting method works. Every description of the 0/n splitting method that I have read indicates that it will generate an extra Application Data record that is discarded by the receiving side. Packet captures indicate that an extra Application Data record is generated when using either the 1/n-1 or the 0/n splitting method. The unit tests demonstrate that -unlike the 1/n-1 method- the 0/n splitting method does not generate an extra plaintext message. That is to say, given the payload "Hello world" when one uses the 1/n-1 method, the receiver will receive "H" followed by "ello world". If one uses the 0/n method, the receiver receives "Hello world". (Content splitting is done in ssl_record:split_bin/5.) The feature is implemented as an ssloption called 'beast_mitigation' that is valid for both servers and clients. The option has three legal values: 'one_n_minus_one', 'zero_n', and 'disabled'. This option could have also been implemented as an environment variable (see 'protocol' and 'protocol_version'), but 'padding_check' -a similar compatibility option- did not have a corresponding environment variable. The option could have been a simple on/off switch, but that would have been strictly less useful and not significantly easier to implement. -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: OpenPGP digital signature URL: From kennethlakin@REDACTED Tue May 3 09:37:40 2016 From: kennethlakin@REDACTED (Kenneth Lakin) Date: Tue, 3 May 2016 00:37:40 -0700 Subject: [erlang-patches] ssl: Bugfix: Use cypher suite's PRF in prf/5. Message-ID: <57285544.1020906@gmail.com> The PR is at: https://github.com/erlang/otp/pull/1042 You should be able to fetch with: git fetch git://github.com/kennethlakin/otp.git tls-use-negotiated-prf And compare with: https://github.com/erlang/otp/compare/maint-18...kennethlakin:tls-use-negotiated-prf https://github.com/erlang/otp/compare/maint-18...kennethlakin:tls-use-negotiated-prf.patch The remainder of this message is the same as the text in the PR: TLS 1.2 allows the negotiated cipher to specify its own PRF algorithm. ssl:prf/5 currently follows a code path that uses hard-coded PRF algorithms that are always correct for TLS 1.0, always wrong for TLS 1.1, and sometimes correct for TLS 1.2. The TLS handshaking code calls tls_v1:prf/5 through another path, so it does not run into this bug. (Given that ssl:prf/5 was added to support EAP-TLS and friends, I'm probably one of a tiny handful of people who make use of this function. (EAP-TLS and friends use the output of the TLS PRF as keying material. If the authenticating server's keys don't match what the client thinks the keys should be, then the client bails out.)) The patch modifies ssl_handshake:prf to accept a PRF algorithm (rather than using the hard-coded one), and ssl_connection:handle_sync_event({prf ...) to pass the connection's negotiated PRF algorithm along to ssl_handshake:prf. It also adds code to test the output of ssl:prf/5. To demonstrate the bug and the correctness of the fix, run the following in an Erlang shell: dbg:start(). dbg:tracer(). dbg:tpl(tls_v1, prf, []). dbg:p(all, c). ssl:start(). Ciphers={ciphers, [{ecdhe_rsa,aes_256_gcm,null,sha384}, {ecdhe_rsa,aes_256_cbc,sha384,sha384}]}. {ok, S}=ssl:connect("www.google.com", 443, [Ciphers]). ssl:prf(S, <<"">>, <<"">>, [<<"">>], 16). ssl:close(S). f(S). f(Ciphers). (Notice that we're only using ciphers that have a SHA384 PRF.) The buggy code produces the following output. (Random binary data has been elided. The PRF to be used is the first argument to tls_v1:prf. 5 is the SHA384 PRF, 4 is the SHA256 PRF, and both values are defined in ssl_record.hrl.) 7> {ok, S}=ssl:connect("www.google.com", 443, [Ciphers]). (<0.59.0>) call tls_v1:prf(5,...,<<"master secret">>,[...,...],48) (<0.59.0>) call tls_v1:prf(5,...,"key expansion",[...,...],72) (<0.59.0>) call tls_v1:prf(5,...,"key expansion",[...,...],72) (<0.59.0>) call tls_v1:prf(5,...,<<"client finished">>,...,12) (<0.59.0>) call tls_v1:prf(5,...,<<"server finished">>,...,12) {ok,{sslsocket,{gen_tcp,#Port<0.892>,tls_connection, undefined}, <0.59.0>}} 8> ssl:prf(S, <<"">>, <<"">>, [<<"">>], 16). (<0.59.0>) call tls_v1:prf(4,<<>>,<<>>,[<<>>],16) {ok,<<166,249,145,171,43,95,158,232,6,60,17,90,183,180,0, 155>>} Notice how the first argument passed to tls_v1:prf/5 by way of the call to ssl:prf/5 is *not* the same as the first argument passed in during the handshaking process. The fixed code produces the following output: 7> {ok, S}=ssl:connect("www.google.com", 443, [Ciphers]). (<0.59.0>) call tls_v1:prf(5,...,<<"master secret">>,[...,...],48) (<0.59.0>) call tls_v1:prf(5,...,"key expansion",[...,...],72) (<0.59.0>) call tls_v1:prf(5,...,"key expansion",[...,...],72) (<0.59.0>) call tls_v1:prf(5,...,<<"client finished">>,...,12) (<0.59.0>) call tls_v1:prf(5,...,<<"server finished">>,...,12) {ok,{sslsocket,{gen_tcp,#Port<0.892>,tls_connection, undefined}, <0.59.0>}} 8> ssl:prf(S, <<"">>, <<"">>, [<<"">>], 16). (<0.59.0>) call tls_v1:prf(5,<<>>,<<>>,[<<>>],16) {ok,<<153,182,217,96,186,130,105,85,65,103,123,247,146, 91,47,106>>} Notice how the first argument passed to tls_v1:prf/5 by way of the call to ssl:prf/5 is the now same as the first argument passed in during the handshaking process. -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: OpenPGP digital signature URL: