aboutsummaryrefslogtreecommitdiffstats
path: root/lib/ssl/src/tls_record.erl
diff options
context:
space:
mode:
authorIngela Anderton Andin <[email protected]>2013-09-05 10:43:31 +0200
committerIngela Anderton Andin <[email protected]>2013-09-10 09:37:30 +0200
commit754b87eb181552d67c61c9a80c31ce52e4b39f19 (patch)
treef6f71c630e6cc22fa9e1c6615f43fc4f7dd5cfb0 /lib/ssl/src/tls_record.erl
parentfa8b8cd60406ddcb2781f27e291949a8698c2886 (diff)
downloadotp-754b87eb181552d67c61c9a80c31ce52e4b39f19.tar.gz
otp-754b87eb181552d67c61c9a80c31ce52e4b39f19.tar.bz2
otp-754b87eb181552d67c61c9a80c31ce52e4b39f19.zip
ssl: Refactor TLS/DTLS record handling
Diffstat (limited to 'lib/ssl/src/tls_record.erl')
-rw-r--r--lib/ssl/src/tls_record.erl511
1 files changed, 78 insertions, 433 deletions
diff --git a/lib/ssl/src/tls_record.erl b/lib/ssl/src/tls_record.erl
index 9ab512f334..54cf8d0b80 100644
--- a/lib/ssl/src/tls_record.erl
+++ b/lib/ssl/src/tls_record.erl
@@ -19,8 +19,7 @@
%%
%%----------------------------------------------------------------------
-%% Purpose: Help functions for handling the SSL-Record protocol
-%%
+%% Purpose: Handle TLS/SSL record protocol. (Parts that are not shared with DTLS)
%%----------------------------------------------------------------------
-module(tls_record).
@@ -31,282 +30,27 @@
-include("tls_handshake.hrl").
-include("ssl_cipher.hrl").
-%% Connection state handling
--export([init_connection_states/1,
- current_connection_state/2, pending_connection_state/2,
- update_security_params/3,
- set_mac_secret/4,
- set_master_secret/2,
- activate_pending_connection_state/2,
- set_pending_cipher_state/4,
- set_renegotiation_flag/2,
- set_client_verify_data/3,
- set_server_verify_data/3]).
-
%% Handling of incoming data
-export([get_tls_records/2]).
-%% Encoding records
--export([encode_handshake/3, encode_alert_record/3,
- encode_change_cipher_spec/2, encode_data/3]).
-
%% Decoding
-export([decode_cipher_text/2]).
-%% Misc.
+%% Encoding
+-export([encode_plain_text/4]).
+
+%% Protocol version handling
-export([protocol_version/1, lowest_protocol_version/2,
highest_protocol_version/1, supported_protocol_versions/0,
is_acceptable_version/1, is_acceptable_version/2]).
--export([compressions/0]).
-
-compile(inline).
--define(INITIAL_BYTES, 5).
-
%%====================================================================
%% Internal application API
%%====================================================================
%%--------------------------------------------------------------------
--spec init_connection_states(client | server) -> #connection_states{}.
-%%
-%% Description: Creates a connection_states record with appropriate
-%% values for the initial SSL connection setup.
-%%--------------------------------------------------------------------
-init_connection_states(Role) ->
- ConnectionEnd = record_protocol_role(Role),
- Current = initial_connection_state(ConnectionEnd),
- Pending = ssl_record:empty_connection_state(ConnectionEnd),
- #connection_states{current_read = Current,
- pending_read = Pending,
- current_write = Current,
- pending_write = Pending
- }.
-
-%%--------------------------------------------------------------------
--spec current_connection_state(#connection_states{}, read | write) ->
- #connection_state{}.
-%%
-%% Description: Returns the instance of the connection_state record
-%% that is currently defined as the current conection state.
-%%--------------------------------------------------------------------
-current_connection_state(#connection_states{current_read = Current},
- read) ->
- Current;
-current_connection_state(#connection_states{current_write = Current},
- write) ->
- Current.
-
-%%--------------------------------------------------------------------
--spec pending_connection_state(#connection_states{}, read | write) ->
- #connection_state{}.
-%%
-%% Description: Returns the instance of the connection_state record
-%% that is currently defined as the pending conection state.
-%%--------------------------------------------------------------------
-pending_connection_state(#connection_states{pending_read = Pending},
- read) ->
- Pending;
-pending_connection_state(#connection_states{pending_write = Pending},
- write) ->
- Pending.
-
-%%--------------------------------------------------------------------
--spec update_security_params(#security_parameters{}, #security_parameters{},
- #connection_states{}) -> #connection_states{}.
-%%
-%% Description: Creates a new instance of the connection_states record
-%% where the pending states gets its security parameters updated.
-%%--------------------------------------------------------------------
-update_security_params(ReadParams, WriteParams, States =
- #connection_states{pending_read = Read,
- pending_write = Write}) ->
- States#connection_states{pending_read =
- Read#connection_state{security_parameters =
- ReadParams},
- pending_write =
- Write#connection_state{security_parameters =
- WriteParams}
- }.
-%%--------------------------------------------------------------------
--spec set_mac_secret(binary(), binary(), client | server,
- #connection_states{}) -> #connection_states{}.
-%%
-%% Description: update the mac_secret field in pending connection states
-%%--------------------------------------------------------------------
-set_mac_secret(ClientWriteMacSecret, ServerWriteMacSecret, client, States) ->
- set_mac_secret(ServerWriteMacSecret, ClientWriteMacSecret, States);
-set_mac_secret(ClientWriteMacSecret, ServerWriteMacSecret, server, States) ->
- set_mac_secret(ClientWriteMacSecret, ServerWriteMacSecret, States).
-
-set_mac_secret(ReadMacSecret, WriteMacSecret,
- States = #connection_states{pending_read = Read,
- pending_write = Write}) ->
- States#connection_states{
- pending_read = Read#connection_state{mac_secret = ReadMacSecret},
- pending_write = Write#connection_state{mac_secret = WriteMacSecret}
- }.
-
-
-%%--------------------------------------------------------------------
--spec set_master_secret(binary(), #connection_states{}) -> #connection_states{}.
-%%
-%% Description: Set master_secret in pending connection states
-%%--------------------------------------------------------------------
-set_master_secret(MasterSecret,
- States = #connection_states{pending_read = Read,
- pending_write = Write}) ->
- ReadSecPar = Read#connection_state.security_parameters,
- Read1 = Read#connection_state{
- security_parameters = ReadSecPar#security_parameters{
- master_secret = MasterSecret}},
- WriteSecPar = Write#connection_state.security_parameters,
- Write1 = Write#connection_state{
- security_parameters = WriteSecPar#security_parameters{
- master_secret = MasterSecret}},
- States#connection_states{pending_read = Read1, pending_write = Write1}.
-
-%%--------------------------------------------------------------------
--spec set_renegotiation_flag(boolean(), #connection_states{}) -> #connection_states{}.
-%%
-%% Description: Set secure_renegotiation in pending connection states
-%%--------------------------------------------------------------------
-set_renegotiation_flag(Flag, #connection_states{
- current_read = CurrentRead0,
- current_write = CurrentWrite0,
- pending_read = PendingRead0,
- pending_write = PendingWrite0}
- = ConnectionStates) ->
- CurrentRead = CurrentRead0#connection_state{secure_renegotiation = Flag},
- CurrentWrite = CurrentWrite0#connection_state{secure_renegotiation = Flag},
- PendingRead = PendingRead0#connection_state{secure_renegotiation = Flag},
- PendingWrite = PendingWrite0#connection_state{secure_renegotiation = Flag},
- ConnectionStates#connection_states{current_read = CurrentRead,
- current_write = CurrentWrite,
- pending_read = PendingRead,
- pending_write = PendingWrite}.
-
-%%--------------------------------------------------------------------
--spec set_client_verify_data(current_read | current_write | current_both,
- binary(), #connection_states{})->
- #connection_states{}.
-%%
-%% Description: Set verify data in connection states.
-%%--------------------------------------------------------------------
-set_client_verify_data(current_read, Data,
- #connection_states{current_read = CurrentRead0,
- pending_write = PendingWrite0}
- = ConnectionStates) ->
- CurrentRead = CurrentRead0#connection_state{client_verify_data = Data},
- PendingWrite = PendingWrite0#connection_state{client_verify_data = Data},
- ConnectionStates#connection_states{current_read = CurrentRead,
- pending_write = PendingWrite};
-set_client_verify_data(current_write, Data,
- #connection_states{pending_read = PendingRead0,
- current_write = CurrentWrite0}
- = ConnectionStates) ->
- PendingRead = PendingRead0#connection_state{client_verify_data = Data},
- CurrentWrite = CurrentWrite0#connection_state{client_verify_data = Data},
- ConnectionStates#connection_states{pending_read = PendingRead,
- current_write = CurrentWrite};
-set_client_verify_data(current_both, Data,
- #connection_states{current_read = CurrentRead0,
- current_write = CurrentWrite0}
- = ConnectionStates) ->
- CurrentRead = CurrentRead0#connection_state{client_verify_data = Data},
- CurrentWrite = CurrentWrite0#connection_state{client_verify_data = Data},
- ConnectionStates#connection_states{current_read = CurrentRead,
- current_write = CurrentWrite}.
-%%--------------------------------------------------------------------
--spec set_server_verify_data(current_read | current_write | current_both,
- binary(), #connection_states{})->
- #connection_states{}.
-%%
-%% Description: Set verify data in pending connection states.
-%%--------------------------------------------------------------------
-set_server_verify_data(current_write, Data,
- #connection_states{pending_read = PendingRead0,
- current_write = CurrentWrite0}
- = ConnectionStates) ->
- PendingRead = PendingRead0#connection_state{server_verify_data = Data},
- CurrentWrite = CurrentWrite0#connection_state{server_verify_data = Data},
- ConnectionStates#connection_states{pending_read = PendingRead,
- current_write = CurrentWrite};
-
-set_server_verify_data(current_read, Data,
- #connection_states{current_read = CurrentRead0,
- pending_write = PendingWrite0}
- = ConnectionStates) ->
- CurrentRead = CurrentRead0#connection_state{server_verify_data = Data},
- PendingWrite = PendingWrite0#connection_state{server_verify_data = Data},
- ConnectionStates#connection_states{current_read = CurrentRead,
- pending_write = PendingWrite};
-
-set_server_verify_data(current_both, Data,
- #connection_states{current_read = CurrentRead0,
- current_write = CurrentWrite0}
- = ConnectionStates) ->
- CurrentRead = CurrentRead0#connection_state{server_verify_data = Data},
- CurrentWrite = CurrentWrite0#connection_state{server_verify_data = Data},
- ConnectionStates#connection_states{current_read = CurrentRead,
- current_write = CurrentWrite}.
-
-%%--------------------------------------------------------------------
--spec activate_pending_connection_state(#connection_states{}, read | write) ->
- #connection_states{}.
-%%
-%% Description: Creates a new instance of the connection_states record
-%% where the pending state of <Type> has been activated.
-%%--------------------------------------------------------------------
-activate_pending_connection_state(States =
- #connection_states{pending_read = Pending},
- read) ->
- NewCurrent = Pending#connection_state{sequence_number = 0},
- SecParams = Pending#connection_state.security_parameters,
- ConnectionEnd = SecParams#security_parameters.connection_end,
- EmptyPending = ssl_record:empty_connection_state(ConnectionEnd),
- SecureRenegotation = NewCurrent#connection_state.secure_renegotiation,
- NewPending = EmptyPending#connection_state{secure_renegotiation = SecureRenegotation},
- States#connection_states{current_read = NewCurrent,
- pending_read = NewPending
- };
-
-activate_pending_connection_state(States =
- #connection_states{pending_write = Pending},
- write) ->
- NewCurrent = Pending#connection_state{sequence_number = 0},
- SecParams = Pending#connection_state.security_parameters,
- ConnectionEnd = SecParams#security_parameters.connection_end,
- EmptyPending = ssl_record:empty_connection_state(ConnectionEnd),
- SecureRenegotation = NewCurrent#connection_state.secure_renegotiation,
- NewPending = EmptyPending#connection_state{secure_renegotiation = SecureRenegotation},
- States#connection_states{current_write = NewCurrent,
- pending_write = NewPending
- }.
-
-%%--------------------------------------------------------------------
--spec set_pending_cipher_state(#connection_states{}, #cipher_state{},
- #cipher_state{}, client | server) ->
- #connection_states{}.
-%%
-%% Description: Set the cipher state in the specified pending connection state.
-%%--------------------------------------------------------------------
-set_pending_cipher_state(#connection_states{pending_read = Read,
- pending_write = Write} = States,
- ClientState, ServerState, server) ->
- States#connection_states{
- pending_read = Read#connection_state{cipher_state = ClientState},
- pending_write = Write#connection_state{cipher_state = ServerState}};
-
-set_pending_cipher_state(#connection_states{pending_read = Read,
- pending_write = Write} = States,
- ClientState, ServerState, client) ->
- States#connection_states{
- pending_read = Read#connection_state{cipher_state = ServerState},
- pending_write = Write#connection_state{cipher_state = ClientState}}.
-
-%%--------------------------------------------------------------------
-spec get_tls_records(binary(), binary()) -> {[binary()], binary()} | #alert{}.
%%
%% Description: Given old buffer and new data from TCP, packs up a records
@@ -376,6 +120,43 @@ get_tls_records_aux(Data, Acc) ->
false ->
?ALERT_REC(?FATAL, ?UNEXPECTED_MESSAGE)
end.
+
+encode_plain_text(Type, Version, Data, ConnectionStates) ->
+ #connection_states{current_write=#connection_state{
+ compression_state=CompS0,
+ security_parameters=
+ #security_parameters{compression_algorithm=CompAlg}
+ }=CS0} = ConnectionStates,
+ {Comp, CompS1} = ssl_record:compress(CompAlg, Data, CompS0),
+ CS1 = CS0#connection_state{compression_state = CompS1},
+ {CipherFragment, CS2} = cipher(Type, Version, Comp, CS1),
+ CTBin = encode_tls_cipher_text(Type, Version, CipherFragment),
+ {CTBin, ConnectionStates#connection_states{current_write = CS2}}.
+
+%%--------------------------------------------------------------------
+-spec decode_cipher_text(#ssl_tls{}, #connection_states{}) ->
+ {#ssl_tls{}, #connection_states{}}| #alert{}.
+%%
+%% Description: Decode cipher text
+%%--------------------------------------------------------------------
+decode_cipher_text(#ssl_tls{type = Type, version = Version,
+ fragment = CipherFragment} = CipherText, ConnnectionStates0) ->
+ ReadState0 = ConnnectionStates0#connection_states.current_read,
+ #connection_state{compression_state = CompressionS0,
+ security_parameters = SecParams} = ReadState0,
+ CompressAlg = SecParams#security_parameters.compression_algorithm,
+ case decipher(Type, Version, CipherFragment, ReadState0) of
+ {PlainFragment, ReadState1} ->
+ {Plain, CompressionS1} = ssl_record:uncompress(CompressAlg,
+ PlainFragment, CompressionS0),
+ ConnnectionStates = ConnnectionStates0#connection_states{
+ current_read = ReadState1#connection_state{
+ compression_state = CompressionS1}},
+ {CipherText#ssl_tls{fragment = Plain}, ConnnectionStates};
+ #alert{} = Alert ->
+ Alert
+ end.
+
%%--------------------------------------------------------------------
-spec protocol_version(tls_atom_version() | tls_version()) ->
tls_version() | tls_atom_version().
@@ -493,168 +274,39 @@ is_acceptable_version(_,_) ->
false.
%%--------------------------------------------------------------------
--spec compressions() -> [binary()].
-%%
-%% Description: return a list of compressions supported (currently none)
-%%--------------------------------------------------------------------
-compressions() ->
- [?byte(?NULL)].
-
-%%--------------------------------------------------------------------
--spec decode_cipher_text(#ssl_tls{}, #connection_states{}) ->
- {#ssl_tls{}, #connection_states{}}| #alert{}.
-%%
-%% Description: Decode cipher text
-%%--------------------------------------------------------------------
-decode_cipher_text(CipherText, ConnnectionStates0) ->
- ReadState0 = ConnnectionStates0#connection_states.current_read,
- #connection_state{compression_state = CompressionS0,
- security_parameters = SecParams} = ReadState0,
- CompressAlg = SecParams#security_parameters.compression_algorithm,
- case decipher(CipherText, ReadState0) of
- {Compressed, ReadState1} ->
- {Plain, CompressionS1} = uncompress(CompressAlg,
- Compressed, CompressionS0),
- ConnnectionStates = ConnnectionStates0#connection_states{
- current_read = ReadState1#connection_state{
- compression_state = CompressionS1}},
- {Plain, ConnnectionStates};
- #alert{} = Alert ->
- Alert
- end.
-%%--------------------------------------------------------------------
--spec encode_data(binary(), tls_version(), #connection_states{}) ->
- {iolist(), #connection_states{}}.
-%%
-%% Description: Encodes data to send on the ssl-socket.
-%%--------------------------------------------------------------------
-encode_data(Frag, Version,
- #connection_states{current_write = #connection_state{
- security_parameters =
- #security_parameters{bulk_cipher_algorithm = BCA}}} =
- ConnectionStates) ->
- Data = split_bin(Frag, ?MAX_PLAIN_TEXT_LENGTH, Version, BCA),
- encode_iolist(?APPLICATION_DATA, Data, Version, ConnectionStates).
-
-%%--------------------------------------------------------------------
--spec encode_handshake(iolist(), tls_version(), #connection_states{}) ->
- {iolist(), #connection_states{}}.
-%%
-%% Description: Encodes a handshake message to send on the ssl-socket.
-%%--------------------------------------------------------------------
-encode_handshake(Frag, Version, ConnectionStates) ->
- encode_plain_text(?HANDSHAKE, Version, Frag, ConnectionStates).
-
-%%--------------------------------------------------------------------
--spec encode_alert_record(#alert{}, tls_version(), #connection_states{}) ->
- {iolist(), #connection_states{}}.
-%%
-%% Description: Encodes an alert message to send on the ssl-socket.
-%%--------------------------------------------------------------------
-encode_alert_record(#alert{level = Level, description = Description},
- Version, ConnectionStates) ->
- encode_plain_text(?ALERT, Version, <<?BYTE(Level), ?BYTE(Description)>>,
- ConnectionStates).
-
-%%--------------------------------------------------------------------
--spec encode_change_cipher_spec(tls_version(), #connection_states{}) ->
- {iolist(), #connection_states{}}.
-%%
-%% Description: Encodes a change_cipher_spec-message to send on the ssl socket.
-%%--------------------------------------------------------------------
-encode_change_cipher_spec(Version, ConnectionStates) ->
- encode_plain_text(?CHANGE_CIPHER_SPEC, Version, <<1:8>>, ConnectionStates).
-
-%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
-encode_iolist(Type, Data, Version, ConnectionStates0) ->
- {ConnectionStates, EncodedMsg} =
- lists:foldl(fun(Text, {CS0, Encoded}) ->
- {Enc, CS1} = encode_plain_text(Type, Version, Text, CS0),
- {CS1, [Enc | Encoded]}
- end, {ConnectionStates0, []}, Data),
- {lists:reverse(EncodedMsg), ConnectionStates}.
-
-highest_protocol_version() ->
- highest_protocol_version(supported_protocol_versions()).
-
-initial_connection_state(ConnectionEnd) ->
- #connection_state{security_parameters =
- initial_security_params(ConnectionEnd),
- sequence_number = 0
- }.
-
-initial_security_params(ConnectionEnd) ->
- SecParams = #security_parameters{connection_end = ConnectionEnd,
- compression_algorithm = ?NULL},
- ssl_cipher:security_parameters(highest_protocol_version(), ?TLS_NULL_WITH_NULL_NULL,
- SecParams).
-
-
-record_protocol_role(client) ->
- ?CLIENT;
-record_protocol_role(server) ->
- ?SERVER.
-
-%% 1/n-1 splitting countermeasure Rizzo/Duong-Beast, RC4 chiphers are not vulnerable to this attack.
-split_bin(<<FirstByte:8, Rest/binary>>, ChunkSize, Version, BCA) when BCA =/= ?RC4 andalso ({3, 1} == Version orelse
- {3, 0} == Version) ->
- do_split_bin(Rest, ChunkSize, [[FirstByte]]);
-split_bin(Bin, ChunkSize, _, _) ->
- do_split_bin(Bin, ChunkSize, []).
-
-do_split_bin(<<>>, _, Acc) ->
- lists:reverse(Acc);
-do_split_bin(Bin, ChunkSize, Acc) ->
- case Bin of
- <<Chunk:ChunkSize/binary, Rest/binary>> ->
- do_split_bin(Rest, ChunkSize, [Chunk | Acc]);
- _ ->
- lists:reverse(Acc, [Bin])
- end.
-
-encode_plain_text(Type, Version, Data, ConnectionStates) ->
- #connection_states{current_write=#connection_state{
- compression_state=CompS0,
- security_parameters=
- #security_parameters{compression_algorithm=CompAlg}
- }=CS0} = ConnectionStates,
- {Comp, CompS1} = compress(CompAlg, Data, CompS0),
- CS1 = CS0#connection_state{compression_state = CompS1},
- {CipherText, CS2} = cipher(Type, Version, Comp, CS1),
- CTBin = encode_tls_cipher_text(Type, Version, CipherText),
- {CTBin, ConnectionStates#connection_states{current_write = CS2}}.
-
encode_tls_cipher_text(Type, {MajVer, MinVer}, Fragment) ->
Length = erlang:iolist_size(Fragment),
[<<?BYTE(Type), ?BYTE(MajVer), ?BYTE(MinVer), ?UINT16(Length)>>, Fragment].
-cipher(Type, Version, Fragment, CS0) ->
- Length = erlang:iolist_size(Fragment),
- {MacHash, CS1=#connection_state{cipher_state = CipherS0,
- security_parameters=
- #security_parameters{bulk_cipher_algorithm =
+cipher(Type, Version, Fragment,
+ #connection_state{cipher_state = CipherS0,
+ sequence_number = SeqNo,
+ security_parameters=
+ #security_parameters{bulk_cipher_algorithm =
BCA}
- }} =
- hash_and_bump_seqno(CS0, Type, Version, Length, Fragment),
- {Ciphered, CipherS1} = ssl_cipher:cipher(BCA, CipherS0, MacHash, Fragment, Version),
- CS2 = CS1#connection_state{cipher_state=CipherS1},
- {Ciphered, CS2}.
-
-decipher(TLS=#ssl_tls{type=Type, version=Version, fragment=Fragment}, CS0) ->
- SP = CS0#connection_state.security_parameters,
+ } = WriteState0) ->
+ MacHash = calc_mac_hash(Type, Version, Fragment, WriteState0),
+ {CipherFragment, CipherS1} =
+ ssl_cipher:cipher(BCA, CipherS0, MacHash, Fragment, Version),
+ WriteState = WriteState0#connection_state{cipher_state=CipherS1},
+ {CipherFragment, WriteState#connection_state{sequence_number = SeqNo+1}}.
+
+decipher(Type, Version, CipherFragment,
+ #connection_state{sequence_number = SeqNo} = ReadState) ->
+ SP = ReadState#connection_state.security_parameters,
BCA = SP#security_parameters.bulk_cipher_algorithm,
HashSz = SP#security_parameters.hash_size,
- CipherS0 = CS0#connection_state.cipher_state,
- case ssl_cipher:decipher(BCA, HashSz, CipherS0, Fragment, Version) of
- {T, Mac, CipherS1} ->
- CS1 = CS0#connection_state{cipher_state = CipherS1},
- TLength = size(T),
- {MacHash, CS2} = hash_and_bump_seqno(CS1, Type, Version, TLength, T),
+ CipherS0 = ReadState#connection_state.cipher_state,
+ case ssl_cipher:decipher(BCA, HashSz, CipherS0, CipherFragment, Version) of
+ {PlainFragment, Mac, CipherS1} ->
+ CS1 = ReadState#connection_state{cipher_state = CipherS1},
+ MacHash = calc_mac_hash(Type, Version, PlainFragment, ReadState),
case ssl_record:is_correct_mac(Mac, MacHash) of
- true ->
- {TLS#ssl_tls{fragment = T}, CS2};
+ true ->
+ {PlainFragment,
+ CS1#connection_state{sequence_number = SeqNo+1}};
false ->
?ALERT_REC(?FATAL, ?BAD_RECORD_MAC)
end;
@@ -662,26 +314,6 @@ decipher(TLS=#ssl_tls{type=Type, version=Version, fragment=Fragment}, CS0) ->
Alert
end.
-uncompress(?NULL, Data = #ssl_tls{type = _Type,
- version = _Version,
- fragment = _Fragment}, CS) ->
- {Data, CS}.
-
-compress(?NULL, Data, CS) ->
- {Data, CS}.
-
-hash_and_bump_seqno(#connection_state{sequence_number = SeqNo,
- mac_secret = MacSecret,
- security_parameters =
- SecPars} = CS0,
- Type, Version, Length, Fragment) ->
- Hash = mac_hash(Version,
- SecPars#security_parameters.mac_algorithm,
- MacSecret, SeqNo, Type,
- Length, Fragment),
- {Hash, CS0#connection_state{sequence_number = SeqNo+1}}.
-
-
mac_hash({_,_}, ?NULL, _MacSecret, _SeqNo, _Type,
_Length, _Fragment) ->
<<>>;
@@ -692,6 +324,19 @@ mac_hash({3, N} = Version, MacAlg, MacSecret, SeqNo, Type, Length, Fragment)
tls_v1:mac_hash(MacAlg, MacSecret, SeqNo, Type, Version,
Length, Fragment).
+highest_protocol_version() ->
+ highest_protocol_version(supported_protocol_versions()).
+
sufficient_tlsv1_2_crypto_support() ->
CryptoSupport = crypto:supports(),
proplists:get_bool(sha256, proplists:get_value(hashs, CryptoSupport)).
+
+calc_mac_hash(Type, Version,
+ PlainFragment, #connection_state{sequence_number = SeqNo,
+ mac_secret = MacSecret,
+ security_parameters =
+ SecPars}) ->
+ Length = erlang:iolist_size(PlainFragment),
+ mac_hash(Version, SecPars#security_parameters.mac_algorithm,
+ MacSecret, SeqNo, Type,
+ Length, PlainFragment).