From 8dd9c18629be297b0ed5178630076882dd8b8880 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Dimitrov?= Date: Thu, 24 Jan 2019 16:58:01 +0100 Subject: ssl: Add 'Finished' Implement Finished message on the server side. Change-Id: Ie0d054ac80f7eb47797273e1878990335112e923 --- lib/ssl/src/tls_handshake_1_3.erl | 30 ++++++++++++++++++++++++++---- lib/ssl/src/tls_v1.erl | 21 ++++++++++++++++++++- 2 files changed, 46 insertions(+), 5 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 8ff58b841d..453894e8b3 100644 --- a/lib/ssl/src/tls_handshake_1_3.erl +++ b/lib/ssl/src/tls_handshake_1_3.erl @@ -139,6 +139,23 @@ certificate_verify(PrivateKey, SignatureScheme, signature = Signature }. +finished(#state{connection_states = ConnectionStates, + handshake_env = + #handshake_env{ + tls_handshake_history = {Messages, _}}}) -> + #{security_parameters := SecParamsR} = + ssl_record:current_connection_state(ConnectionStates, write), + #security_parameters{prf_algorithm = HKDFAlgo, + master_secret = SHTS} = SecParamsR, + + FinishedKey = tls_v1:finished_key(SHTS, HKDFAlgo), + VerifyData = tls_v1:finished_verify_data(FinishedKey, HKDFAlgo, Messages), + + #finished{ + verify_data = VerifyData + }. + + %%==================================================================== %% Encode handshake %%==================================================================== @@ -464,10 +481,14 @@ do_negotiated(#{client_share := ClientKey, %% Create CertificateVerify CertificateVerify = certificate_verify(CertPrivateKey, SignatureScheme, State5, server), - %% Encode CertificateVerify - %% Send Certificate, CertifricateVerify - {_State6, _} = tls_connection:send_handshake(CertificateVerify, State5), + State6 = tls_connection:queue_handshake(CertificateVerify, State5), + + %% Create Finished + Finished = finished(State6), + + %% Encode Certificate, CertifricateVerify + {_State7, _} = tls_connection:send_handshake(Finished, State6), %% Send finished @@ -532,7 +553,8 @@ calculate_security_parameters(ClientKey, SelectedGroup, KeyShare, {ReadKey, ReadIV} = tls_v1:calculate_traffic_keys(HKDFAlgo, Cipher, ClientHSTrafficSecret), {WriteKey, WriteIV} = tls_v1:calculate_traffic_keys(HKDFAlgo, Cipher, ServerHSTrafficSecret), - {HandshakeSecret, ReadKey, ReadIV, WriteKey, WriteIV}. + %% TODO: store all relevant secrets in state! + {ServerHSTrafficSecret, ReadKey, ReadIV, WriteKey, WriteIV}. %% %% Update pending connection state %% PendingRead0 = ssl_record:pending_connection_state(ConnectionStates, read), diff --git a/lib/ssl/src/tls_v1.erl b/lib/ssl/src/tls_v1.erl index d1a62696cc..5c023bd2d8 100644 --- a/lib/ssl/src/tls_v1.erl +++ b/lib/ssl/src/tls_v1.erl @@ -44,7 +44,7 @@ client_application_traffic_secret_0/3, server_application_traffic_secret_0/3, exporter_master_secret/3, resumption_master_secret/3, update_traffic_secret/2, calculate_traffic_keys/3, - transcript_hash/2]). + transcript_hash/2, finished_key/2, finished_verify_data/3]). -type named_curve() :: sect571r1 | sect571k1 | secp521r1 | brainpoolP512r1 | sect409k1 | sect409r1 | brainpoolP384r1 | secp384r1 | @@ -374,6 +374,25 @@ exporter_master_secret(Algo, {master_secret, Secret}, M) -> resumption_master_secret(Algo, {master_secret, Secret}, M) -> derive_secret(Secret, <<"res master">>, M, Algo). +-spec finished_key(binary(), atom()) -> binary(). +finished_key(BaseKey, Algo) -> + %% finished_key = + %% HKDF-Expand-Label(BaseKey, "finished", "", Hash.length) + ssl_cipher:hash_size(Algo), + hkdf_expand_label(BaseKey, <<"finished">>, <<>>, ssl_cipher:hash_size(Algo), Algo). + +-spec finished_verify_data(binary(), atom(), iodata()) -> binary(). +finished_verify_data(FinishedKey, HKDFAlgo, Messages) -> + %% The verify_data value is computed as follows: + %% + %% verify_data = + %% HMAC(finished_key, + %% Transcript-Hash(Handshake Context, + %% Certificate*, CertificateVerify*)) + Context = lists:reverse(Messages), + THash = tls_v1:transcript_hash(Context, HKDFAlgo), + tls_v1:hmac_hash(HKDFAlgo, FinishedKey, THash). + %% The next-generation application_traffic_secret is computed as: %% %% application_traffic_secret_N+1 = -- cgit v1.2.3