From a7c2d09f1f3e2aa1db6c2b83baf5267655507ce1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Dimitrov?= Date: Tue, 19 Feb 2019 13:04:17 +0100 Subject: ssl: Validate Client Finished Validate Client Finished message. If validation fails, send decrypt_error alert. Change-Id: I1da7be3505ca6df2b3d50282f0500b988ef8b488 --- lib/ssl/src/tls_handshake_1_3.erl | 36 ++++++++++++++++++++++++++++++++---- 1 file changed, 32 insertions(+), 4 deletions(-) (limited to 'lib/ssl/src') diff --git a/lib/ssl/src/tls_handshake_1_3.erl b/lib/ssl/src/tls_handshake_1_3.erl index c099e3f276..6a6de4b988 100644 --- a/lib/ssl/src/tls_handshake_1_3.erl +++ b/lib/ssl/src/tls_handshake_1_3.erl @@ -532,7 +532,7 @@ do_wait_finished(#change_cipher_spec{}, {_Ref, {state_not_implemented, State}} -> ?ALERT_REC(?FATAL, ?INTERNAL_ERROR, {state_not_implemented, State}) end; -do_wait_finished(#finished{}, +do_wait_finished(#finished{verify_data = VerifyData}, #state{connection_states = _ConnectionStates0, session = #session{session_id = _SessionId, own_certificate = _OwnCert}, @@ -546,10 +546,10 @@ do_wait_finished(#finished{}, transport_cb = _Transport} } = State0) -> - %% {Ref,Maybe} = maybe(), + {Ref,Maybe} = maybe(), try - %% TODO: validate client Finished + Maybe(validate_client_finished(State0, VerifyData)), State1 = calculate_traffic_secrets(State0), @@ -558,7 +558,9 @@ do_wait_finished(#finished{}, catch - {_Ref, {state_not_implemented, State}} -> + {Ref, decrypt_error} -> + ?ALERT_REC(?FATAL, ?DECRYPT_ERROR, decrypt_error); + {_, {state_not_implemented, State}} -> %% TODO ?ALERT_REC(?FATAL, ?INTERNAL_ERROR, {state_not_implemented, State}) end. @@ -569,6 +571,32 @@ do_wait_finished(#finished{}, %% {error, {state_not_implemented, State}}. +%% Recipients of Finished messages MUST verify that the contents are +%% correct and if incorrect MUST terminate the connection with a +%% "decrypt_error" alert. +validate_client_finished(#state{connection_states = ConnectionStates, + handshake_env = + #handshake_env{ + tls_handshake_history = {Messages0, _}}}, VerifyData) -> + #{security_parameters := SecParamsR, + cipher_state := #cipher_state{finished_key = FinishedKey}} = + ssl_record:current_connection_state(ConnectionStates, read), + #security_parameters{prf_algorithm = HKDFAlgo} = SecParamsR, + + %% Drop the client's finished message, it is not part of the handshake context + %% when the client calculates its finished message. + [_|Messages] = Messages0, + + ControlData = tls_v1:finished_verify_data(FinishedKey, HKDFAlgo, Messages), + compare_verify_data(ControlData, VerifyData). + + +compare_verify_data(Data, Data) -> + ok; +compare_verify_data(_, _) -> + {error, decrypt_error}. + + calculate_handshake_secrets(ClientKey, SelectedGroup, KeyShare, #state{connection_states = ConnectionStates, handshake_env = -- cgit v1.2.3