summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorIngela Anderton Andin <ingela@erlang.org>2020-01-23 17:32:34 +0100
committerIngela Anderton Andin <ingela@erlang.org>2020-01-24 15:47:20 +0100
commit33f13c107c694e472ffb878d600503b05067c944 (patch)
tree05325259ddee80c3036306d0055c1112110158ce /lib
parent2ca0df73606da118b945a3a87d4d3f5397da9f48 (diff)
downloaderlang-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.erl33
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) ->