diff options
author | Ingela Anderton Andin <ingela@erlang.org> | 2020-01-23 17:32:34 +0100 |
---|---|---|
committer | Ingela Anderton Andin <ingela@erlang.org> | 2020-01-24 15:47:20 +0100 |
commit | 33f13c107c694e472ffb878d600503b05067c944 (patch) | |
tree | 05325259ddee80c3036306d0055c1112110158ce /lib | |
parent | 2ca0df73606da118b945a3a87d4d3f5397da9f48 (diff) | |
download | erlang-33f13c107c694e472ffb878d600503b05067c944.tar.gz |
ssl: Application data optimization must be done differently for TLS-1.3 and previous versions
TLS-1.3 encrypts the real packet type and uses APPLICATION_DATA
as external type. The optimization will disregard the last
decryption if next packet is not APPLICATION_DATA. This however
will not work for pre TLS-1.3 and stream cipher RC4, after the
optimization to stream ciphers making the crypto API pure
functional. In TLS-1.3 no stream ciphers are supported. In
previous TLS versions we can look at the external packet type
with out decryption.
Diffstat (limited to 'lib')
-rw-r--r-- | lib/ssl/src/tls_connection.erl | 33 |
1 files changed, 32 insertions, 1 deletions
diff --git a/lib/ssl/src/tls_connection.erl b/lib/ssl/src/tls_connection.erl index b4754e9f55..cfd1ca3932 100644 --- a/lib/ssl/src/tls_connection.erl +++ b/lib/ssl/src/tls_connection.erl @@ -221,7 +221,7 @@ activate_socket(#state{protocol_specific = #{active_n_toggle := true, active_n : next_record(State, CipherTexts, ConnectionStates, Check) -> next_record(State, CipherTexts, ConnectionStates, Check, []). %% -next_record(#state{connection_env = #connection_env{negotiated_version = Version}} = State, +next_record(#state{connection_env = #connection_env{negotiated_version = {3,4} = Version}} = State, [CT|CipherTexts], ConnectionStates0, Check, Acc) -> case tls_record:decode_cipher_text(Version, CT, ConnectionStates0, Check) of {#ssl_tls{type = ?APPLICATION_DATA, fragment = Fragment}, ConnectionStates} -> @@ -242,10 +242,41 @@ next_record(#state{connection_env = #connection_env{negotiated_version = Version %% Not ?APPLICATION_DATA but we have accumulated fragments %% -> build an ?APPLICATION_DATA record with concatenated fragments %% and forget about decrypting this record - we'll decrypt it again next time + %% Will not work for stream ciphers next_record_done(State, [CT|CipherTexts], ConnectionStates0, #ssl_tls{type = ?APPLICATION_DATA, fragment = iolist_to_binary(lists:reverse(Acc))}); #alert{} = Alert -> Alert + end; +next_record(#state{connection_env = #connection_env{negotiated_version = Version}} = State, + [#ssl_tls{type = ?APPLICATION_DATA} = CT |CipherTexts], ConnectionStates0, Check, Acc) -> + case tls_record:decode_cipher_text(Version, CT, ConnectionStates0, Check) of + {#ssl_tls{type = ?APPLICATION_DATA, fragment = Fragment}, ConnectionStates} -> + case CipherTexts of + [] -> + %% End of cipher texts - build and deliver an ?APPLICATION_DATA record + %% from the accumulated fragments + next_record_done(State, [], ConnectionStates, + #ssl_tls{type = ?APPLICATION_DATA, + fragment = iolist_to_binary(lists:reverse(Acc, [Fragment]))}); + [_|_] -> + next_record(State, CipherTexts, ConnectionStates, Check, [Fragment|Acc]) + end; + #alert{} = Alert -> + Alert + end; +next_record(State, CipherTexts, ConnectionStates, _, [_|_] = Acc) -> + next_record_done(State, CipherTexts, ConnectionStates, + #ssl_tls{type = ?APPLICATION_DATA, + fragment = iolist_to_binary(lists:reverse(Acc))}); +next_record(#state{connection_env = #connection_env{negotiated_version = Version}} = State, + [CT|CipherTexts], ConnectionStates0, Check, []) -> + case tls_record:decode_cipher_text(Version, CT, ConnectionStates0, Check) of + {Record, ConnectionStates} -> + %% Singelton non-?APPLICATION_DATA record - deliver + next_record_done(State, CipherTexts, ConnectionStates, Record); + #alert{} = Alert -> + Alert end. next_record_done(#state{protocol_buffers = Buffers} = State, CipherTexts, ConnectionStates, Record) -> |