diff options
Diffstat (limited to 'lib/ssl/src/tls_connection_1_3.erl')
-rw-r--r-- | lib/ssl/src/tls_connection_1_3.erl | 56 |
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(). + |