summaryrefslogtreecommitdiff
path: root/lib/ssl/src/tls_connection_1_3.erl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ssl/src/tls_connection_1_3.erl')
-rw-r--r--lib/ssl/src/tls_connection_1_3.erl56
1 files changed, 41 insertions, 15 deletions
diff --git a/lib/ssl/src/tls_connection_1_3.erl b/lib/ssl/src/tls_connection_1_3.erl
index fc4b4f673f..6c81933c23 100644
--- a/lib/ssl/src/tls_connection_1_3.erl
+++ b/lib/ssl/src/tls_connection_1_3.erl
@@ -132,6 +132,7 @@
wait_sh/3,
wait_ee/3,
wait_cert_cr/3,
+ wait_eoed/3,
connection/3,
downgrade/3
]).
@@ -168,8 +169,8 @@ update_cipher_key(ConnStateName, CS0) ->
ApplicationTrafficSecret = tls_v1:update_traffic_secret(HKDF, ApplicationTrafficSecret0),
%% Calculate traffic keys
- #{cipher := Cipher} = ssl_cipher_format:suite_bin_to_map(CipherSuite),
- {Key, IV} = tls_v1:calculate_traffic_keys(HKDF, Cipher, ApplicationTrafficSecret),
+ KeyLength = tls_v1:key_length(CipherSuite),
+ {Key, IV} = tls_v1:calculate_traffic_keys(HKDF, KeyLength, ApplicationTrafficSecret),
SecParams = SecParams0#security_parameters{application_traffic_secret = ApplicationTrafficSecret},
CipherState = CipherState0#cipher_state{key = Key, iv = IV},
@@ -307,8 +308,8 @@ negotiated(internal, Message, State0) ->
negotiated(info, Msg, State) ->
tls_gen_connection:handle_info(Msg, ?FUNCTION_NAME, State).
-wait_cert(internal, #change_cipher_spec{}, State) ->
- tls_gen_connection:next_event(?FUNCTION_NAME, no_record, State);
+wait_cert(internal, #change_cipher_spec{}, State0) ->
+ tls_gen_connection:next_event(?FUNCTION_NAME, no_record, State0);
wait_cert(internal,
#certificate_1_3{} = Certificate, State0) ->
case tls_handshake_1_3:do_wait_cert(Certificate, State0) of
@@ -337,9 +338,8 @@ wait_cv(info, Msg, State) ->
wait_cv(Type, Msg, State) ->
ssl_gen_statem:handle_common_event(Type, Msg, ?FUNCTION_NAME, State).
-
-wait_finished(internal, #change_cipher_spec{}, State) ->
- tls_gen_connection:next_event(?FUNCTION_NAME, no_record, State);
+wait_finished(internal, #change_cipher_spec{}, State0) ->
+ tls_gen_connection:next_event(?FUNCTION_NAME, no_record, State0);
wait_finished(internal,
#finished{} = Finished, State0) ->
case tls_handshake_1_3:do_wait_finished(Finished, State0) of
@@ -417,6 +417,20 @@ wait_cert_cr(info, Msg, State) ->
wait_cert_cr(Type, Msg, State) ->
ssl_gen_statem:handle_common_event(Type, Msg, ?FUNCTION_NAME, State).
+wait_eoed(internal, #change_cipher_spec{}, State) ->
+ tls_gen_connection:next_event(?FUNCTION_NAME, no_record, State);
+wait_eoed(internal, #end_of_early_data{} = EOED, State0) ->
+ case tls_handshake_1_3:do_wait_eoed(EOED, State0) of
+ {#alert{} = Alert, State} ->
+ ssl_gen_statem:handle_own_alert(Alert, {3,4}, wait_eoed, State);
+ {State1, NextState} ->
+ tls_gen_connection:next_event(NextState, no_record, State1)
+ end;
+wait_eoed(info, Msg, State) ->
+ tls_gen_connection:handle_info(Msg, ?FUNCTION_NAME, State);
+wait_eoed(Type, Msg, State) ->
+ ssl_gen_statem:handle_common_event(Type, Msg, ?FUNCTION_NAME, State).
+
connection(internal, #new_session_ticket{} = NewSessionTicket, State) ->
handle_new_session_ticket(NewSessionTicket, State),
tls_gen_connection:next_event(?FUNCTION_NAME, no_record, State);
@@ -450,7 +464,8 @@ initial_state(Role, Sender, Host, Port, Socket, {SSLOptions, SocketOptions, Trac
{CbModule, DataTag, CloseTag, ErrorTag, PassiveTag}) ->
#{erl_dist := IsErlDist,
client_renegotiation := ClientRenegotiation} = SSLOptions,
- ConnectionStates = tls_record:init_connection_states(Role, disabled),
+ MaxEarlyDataSize = init_max_early_data_size(Role),
+ ConnectionStates = tls_record:init_connection_states(Role, disabled, MaxEarlyDataSize),
InternalActiveN = case application:get_env(ssl, internal_active_n) of
{ok, N} when is_integer(N) andalso (not IsErlDist) ->
N;
@@ -504,10 +519,12 @@ handle_new_session_ticket(#new_session_ticket{ticket_nonce = Nonce} = NewSession
when SessionTickets =:= manual ->
#{security_parameters := SecParams} =
ssl_record:current_connection_state(ConnectionStates, read),
+ CipherSuite = SecParams#security_parameters.cipher_suite,
+ #{cipher := Cipher} = ssl_cipher_format:suite_bin_to_map(CipherSuite),
HKDF = SecParams#security_parameters.prf_algorithm,
RMS = SecParams#security_parameters.resumption_master_secret,
PSK = tls_v1:pre_shared_key(RMS, Nonce, HKDF),
- send_ticket_data(User, NewSessionTicket, HKDF, SNI, PSK);
+ send_ticket_data(User, NewSessionTicket, {Cipher, HKDF}, SNI, PSK);
handle_new_session_ticket(#new_session_ticket{ticket_nonce = Nonce} = NewSessionTicket,
#state{connection_states = ConnectionStates,
ssl_options = #{session_tickets := SessionTickets,
@@ -515,21 +532,21 @@ handle_new_session_ticket(#new_session_ticket{ticket_nonce = Nonce} = NewSession
when SessionTickets =:= auto ->
#{security_parameters := SecParams} =
ssl_record:current_connection_state(ConnectionStates, read),
+ CipherSuite = SecParams#security_parameters.cipher_suite,
+ #{cipher := Cipher} = ssl_cipher_format:suite_bin_to_map(CipherSuite),
HKDF = SecParams#security_parameters.prf_algorithm,
RMS = SecParams#security_parameters.resumption_master_secret,
PSK = tls_v1:pre_shared_key(RMS, Nonce, HKDF),
- tls_client_ticket_store:store_ticket(NewSessionTicket, HKDF, SNI, PSK).
-
+ tls_client_ticket_store:store_ticket(NewSessionTicket, {Cipher, HKDF}, SNI, PSK).
-%% Send ticket data to user as opaque binary
-send_ticket_data(User, NewSessionTicket, HKDF, SNI, PSK) ->
+send_ticket_data(User, NewSessionTicket, CipherSuite, SNI, PSK) ->
Timestamp = erlang:system_time(seconds),
- TicketData = #{hkdf => HKDF,
+ TicketData = #{cipher_suite => CipherSuite,
sni => SNI,
psk => PSK,
timestamp => Timestamp,
ticket => NewSessionTicket},
- User ! {ssl, session_ticket, {SNI, erlang:term_to_binary(TicketData)}}.
+ User ! {ssl, session_ticket, TicketData}.
handle_key_update(#key_update{request_update = update_not_requested}, State0) ->
%% Update read key in connection
@@ -545,3 +562,12 @@ handle_key_update(#key_update{request_update = update_requested},
{error, Reason} ->
{error, State1, ?ALERT_REC(?FATAL, ?INTERNAL_ERROR, Reason)}
end.
+
+init_max_early_data_size(client) ->
+ %% Disable trial decryption on the client side
+ %% Servers do trial decryption of max_early_data bytes of plain text.
+ %% Setting it to 0 means that a decryption error will result in an Alert.
+ 0;
+init_max_early_data_size(server) ->
+ ssl_config:get_max_early_data_size().
+