aboutsummaryrefslogtreecommitdiffstats
path: root/lib/ssl
diff options
context:
space:
mode:
authorPéter Dimitrov <[email protected]>2019-02-19 13:04:17 +0100
committerPéter Dimitrov <[email protected]>2019-02-19 13:04:17 +0100
commita7c2d09f1f3e2aa1db6c2b83baf5267655507ce1 (patch)
tree5b32b8f35bdd7096abf13368dc053512e5df59f1 /lib/ssl
parent6c0c1f69353b14bb9cec8d6d2ae134b54bf3b2d7 (diff)
downloadotp-a7c2d09f1f3e2aa1db6c2b83baf5267655507ce1.tar.gz
otp-a7c2d09f1f3e2aa1db6c2b83baf5267655507ce1.tar.bz2
otp-a7c2d09f1f3e2aa1db6c2b83baf5267655507ce1.zip
ssl: Validate Client Finished
Validate Client Finished message. If validation fails, send decrypt_error alert. Change-Id: I1da7be3505ca6df2b3d50282f0500b988ef8b488
Diffstat (limited to 'lib/ssl')
-rw-r--r--lib/ssl/src/tls_handshake_1_3.erl36
1 files changed, 32 insertions, 4 deletions
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 =