aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIngela Anderton Andin <[email protected]>2013-09-10 17:43:40 +0200
committerIngela Anderton Andin <[email protected]>2013-12-02 09:44:49 +0100
commit810c34a7991f2b6edd5e9f41e3c667958a5b2bc8 (patch)
tree650dfd13ab00533b8a1cc8f3f63986c672558667
parent2bc1b1c962adf7849abb5a8399706aad708c5969 (diff)
downloadotp-810c34a7991f2b6edd5e9f41e3c667958a5b2bc8.tar.gz
otp-810c34a7991f2b6edd5e9f41e3c667958a5b2bc8.tar.bz2
otp-810c34a7991f2b6edd5e9f41e3c667958a5b2bc8.zip
ssl: Refactor handshake and record handling
-rw-r--r--lib/ssl/src/dtls_handshake.erl10
-rw-r--r--lib/ssl/src/dtls_record.erl123
-rw-r--r--lib/ssl/src/ssl_cipher.erl2
-rw-r--r--lib/ssl/src/ssl_record.erl38
-rw-r--r--lib/ssl/src/tls_handshake.erl2
-rw-r--r--lib/ssl/src/tls_record.erl82
6 files changed, 113 insertions, 144 deletions
diff --git a/lib/ssl/src/dtls_handshake.erl b/lib/ssl/src/dtls_handshake.erl
index d0f9649f9f..d898da65fb 100644
--- a/lib/ssl/src/dtls_handshake.erl
+++ b/lib/ssl/src/dtls_handshake.erl
@@ -87,11 +87,6 @@ hello(Address, Port,
{reply, HelloVerifyRequest}
end.
-address_to_bin({A,B,C,D}, Port) ->
- <<0:80,16#ffff:16,A,B,C,D,Port:16>>;
-address_to_bin({A,B,C,D,E,F,G,H}, Port) ->
- <<A:16,B:16,C:16,D:16,E:16,F:16,G:16,H:16,Port:16>>.
-
%%--------------------------------------------------------------------
encode_handshake(Package, Version, MsgSeq, Mss) ->
{MsgType, Bin} = enc_hs(Package, Version),
@@ -426,3 +421,8 @@ decode_handshake(_Version, ?HELLO_VERIFY_REQUEST, <<?BYTE(Major), ?BYTE(Minor),
cookie = Cookie};
decode_handshake(Version, Tag, Msg) ->
ssl_handshake:decode_handshake(Version, Tag, Msg).
+
+address_to_bin({A,B,C,D}, Port) ->
+ <<0:80,16#ffff:16,A,B,C,D,Port:16>>;
+address_to_bin({A,B,C,D,E,F,G,H}, Port) ->
+ <<A:16,B:16,C:16,D:16,E:16,F:16,G:16,H:16,Port:16>>.
diff --git a/lib/ssl/src/dtls_record.erl b/lib/ssl/src/dtls_record.erl
index f667458a10..7959c4d860 100644
--- a/lib/ssl/src/dtls_record.erl
+++ b/lib/ssl/src/dtls_record.erl
@@ -40,8 +40,9 @@
%% Protocol version handling
-export([protocol_version/1, lowest_protocol_version/2,
highest_protocol_version/1, supported_protocol_versions/0,
- is_acceptable_version/2, cipher/4, decipher/2]).
+ is_acceptable_version/2]).
+%% DTLS Epoch handling
-export([init_connection_state_seq/2, current_connection_state_epoch/2,
set_connection_state_by_epoch/3, connection_state_by_epoch/3]).
@@ -114,35 +115,44 @@ get_dtls_records_aux(Data, Acc) ->
end.
encode_plain_text(Type, Version, Data,
- #connection_state{
- compression_state = CompS0,
- epoch = Epoch,
- sequence_number = Seq,
- security_parameters=
- #security_parameters{compression_algorithm = CompAlg}
- }= CS0) ->
+ #connection_states{current_write=#connection_state{
+ epoch = Epoch,
+ sequence_number = Seq,
+ compression_state=CompS0,
+ security_parameters=
+ #security_parameters{compression_algorithm=CompAlg}
+ }= WriteState0} = ConnectionStates) ->
{Comp, CompS1} = ssl_record: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, Epoch, Seq, CipherText),
- {CTBin, CS2}.
-
-decode_cipher_text(CipherText, ConnnectionStates0) ->
- ReadState0 = ConnnectionStates0#connection_states.current_read,
- #connection_state{compression_state = CompressionS0,
- security_parameters = SecParams} = ReadState0,
+ WriteState1 = WriteState0#connection_state{compression_state = CompS1},
+ MacHash = calc_mac_hash(WriteState1, Type, Version, Epoch, Seq, Comp),
+ {CipherFragment, WriteState} = ssl_record:cipher(Version, Comp, WriteState1, MacHash),
+ CipherText = encode_tls_cipher_text(Type, Version, Epoch, Seq, CipherFragment),
+ {CipherText, ConnectionStates#connection_states{current_write =
+ WriteState#connection_state{sequence_number = Seq +1}}}.
+
+decode_cipher_text(#ssl_tls{type = Type, version = Version,
+ epoch = Epoch,
+ record_seq = Seq,
+ fragment = CipherFragment} = CipherText,
+ #connection_states{current_read =
+ #connection_state{compression_state = CompressionS0,
+ security_parameters = SecParams} = ReadState0}
+ = ConnnectionStates0) ->
CompressAlg = SecParams#security_parameters.compression_algorithm,
- case decipher(CipherText, ReadState0) of
- {Compressed, ReadState1} ->
- {Plain, CompressionS1} = ssl_record:uncompress(CompressAlg,
- Compressed, CompressionS0),
- ConnnectionStates = ConnnectionStates0#connection_states{
- current_read = ReadState1#connection_state{
- compression_state = CompressionS1}},
- {Plain, ConnnectionStates};
- #alert{} = Alert ->
- Alert
- end.
+ {PlainFragment, Mac, ReadState1} = ssl_record:decipher(dtls_v1:corresponding_tls_version(Version),
+ CipherFragment, ReadState0),
+ MacHash = calc_mac_hash(Type, Version, Epoch, Seq, PlainFragment, ReadState1),
+ case ssl_record:is_correct_mac(Mac, MacHash) of
+ true ->
+ {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};
+ false ->
+ ?ALERT_REC(?FATAL, ?BAD_RECORD_MAC)
+ end.
%%--------------------------------------------------------------------
-spec protocol_version(tls_atom_version() | tls_version()) ->
@@ -323,62 +333,13 @@ encode_tls_cipher_text(Type, {MajVer, MinVer}, Epoch, Seq, Fragment) ->
[<<?BYTE(Type), ?BYTE(MajVer), ?BYTE(MinVer), ?UINT16(Epoch),
?UINT48(Seq), ?UINT16(Length)>>, Fragment].
-cipher(Type, Version, Fragment, CS0) ->
+calc_mac_hash(#connection_state{mac_secret = MacSecret,
+ security_parameters = #security_parameters{mac_algorithm = MacAlg}},
+ Type, Version, Epoch, SeqNo, Fragment) ->
Length = erlang:iolist_size(Fragment),
- {MacHash, CS1=#connection_state{cipher_state = CipherS0,
- 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={254, _},
- epoch = Epoch, record_seq = SeqNo,
- fragment=Fragment}, CS0) ->
- SP = CS0#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 = hash_with_seqno(CS1, Type, Version, Epoch, SeqNo, TLength, T),
- case ssl_record:is_correct_mac(Mac, MacHash) of
- true ->
- {TLS#ssl_tls{fragment = T}, CS1};
- false ->
- ?ALERT_REC(?FATAL, ?BAD_RECORD_MAC)
- end;
- #alert{} = Alert ->
- Alert
- end.
-
-hash_with_seqno(#connection_state{mac_secret = MacSecret,
- security_parameters =
- SecPars},
- Type, Version = {254, _},
- Epoch, SeqNo, Length, Fragment) ->
- mac_hash(Version,
- SecPars#security_parameters.mac_algorithm,
- MacSecret, (Epoch bsl 48) + SeqNo, Type,
+ mac_hash(Version, MacAlg, MacSecret, (Epoch bsl 48) + SeqNo, Type,
Length, Fragment).
-hash_and_bump_seqno(#connection_state{epoch = Epoch,
- sequence_number = SeqNo,
- mac_secret = MacSecret,
- security_parameters =
- SecPars} = CS0,
- Type, Version = {254, _}, Length, Fragment) ->
- Hash = mac_hash(Version,
- SecPars#security_parameters.mac_algorithm,
- MacSecret, (Epoch bsl 48) + SeqNo, Type,
- Length, Fragment),
- {Hash, CS0#connection_state{sequence_number = SeqNo+1}}.
-
mac_hash(Version, MacAlg, MacSecret, SeqNo, Type, Length, Fragment) ->
dtls_v1:mac_hash(MacAlg, MacSecret, SeqNo, Type, Version,
Length, Fragment).
diff --git a/lib/ssl/src/ssl_cipher.erl b/lib/ssl/src/ssl_cipher.erl
index e6ed0d8626..b2077c662a 100644
--- a/lib/ssl/src/ssl_cipher.erl
+++ b/lib/ssl/src/ssl_cipher.erl
@@ -72,7 +72,7 @@ security_parameters(Version, CipherSuite, SecParams) ->
hash_size = hash_size(Hash)}.
%%--------------------------------------------------------------------
--spec cipher(cipher_enum(), #cipher_state{}, binary(), binary(), tls_version()) ->
+-spec cipher(cipher_enum(), #cipher_state{}, binary(), iolist(), tls_version()) ->
{binary(), #cipher_state{}}.
%%
%% Description: Encrypts the data and the MAC using chipher described
diff --git a/lib/ssl/src/ssl_record.erl b/lib/ssl/src/ssl_record.erl
index 50a45dc16b..018c8befe0 100644
--- a/lib/ssl/src/ssl_record.erl
+++ b/lib/ssl/src/ssl_record.erl
@@ -47,7 +47,8 @@
%% Compression
-export([compress/3, uncompress/3, compressions/0]).
--export([is_correct_mac/2]).
+%% Payload encryption/decryption
+-export([cipher/4, decipher/3, is_correct_mac/2]).
%%====================================================================
%% Internal application API
@@ -355,6 +356,41 @@ compressions() ->
[?byte(?NULL)].
%%--------------------------------------------------------------------
+-spec cipher(tls_version(), iolist(), #connection_state{}, MacHash::binary()) ->
+ {CipherFragment::binary(), #connection_state{}}.
+%%
+%% Description: Payload encryption
+%%--------------------------------------------------------------------
+cipher(Version, Fragment,
+ #connection_state{cipher_state = CipherS0,
+ security_parameters=
+ #security_parameters{bulk_cipher_algorithm =
+ BulkCipherAlgo}
+ } = WriteState0, MacHash) ->
+
+ {CipherFragment, CipherS1} =
+ ssl_cipher:cipher(BulkCipherAlgo, CipherS0, MacHash, Fragment, Version),
+ {CipherFragment, WriteState0#connection_state{cipher_state = CipherS1}}.
+%%--------------------------------------------------------------------
+-spec decipher(tls_version(), binary(), #connection_state{}) -> {binary(), binary(), #connection_state{}}.
+%%
+%% Description: Payload decryption
+%%--------------------------------------------------------------------
+decipher(Version, CipherFragment,
+ #connection_state{security_parameters =
+ #security_parameters{bulk_cipher_algorithm =
+ BulkCipherAlgo,
+ hash_size = HashSz},
+ cipher_state = CipherS0
+ } = ReadState) ->
+ case ssl_cipher:decipher(BulkCipherAlgo, HashSz, CipherS0, CipherFragment, Version) of
+ {PlainFragment, Mac, CipherS1} ->
+ CS1 = ReadState#connection_state{cipher_state = CipherS1},
+ {PlainFragment, Mac, CS1};
+ #alert{} = Alert ->
+ Alert
+ end.
+%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
empty_connection_state(ConnectionEnd) ->
diff --git a/lib/ssl/src/tls_handshake.erl b/lib/ssl/src/tls_handshake.erl
index 262f2d929f..f783bacff6 100644
--- a/lib/ssl/src/tls_handshake.erl
+++ b/lib/ssl/src/tls_handshake.erl
@@ -26,10 +26,8 @@
-include("tls_handshake.hrl").
-include("tls_record.hrl").
--include("ssl_cipher.hrl").
-include("ssl_alert.hrl").
-include("ssl_internal.hrl").
--include("ssl_srp.hrl").
-include_lib("public_key/include/public_key.hrl").
-export([client_hello/8, server_hello/4, hello/4,
diff --git a/lib/ssl/src/tls_record.erl b/lib/ssl/src/tls_record.erl
index 54cf8d0b80..88107557a0 100644
--- a/lib/ssl/src/tls_record.erl
+++ b/lib/ssl/src/tls_record.erl
@@ -121,17 +121,20 @@ get_tls_records_aux(Data, Acc) ->
?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,
+encode_plain_text(Type, Version, Data,
+ #connection_states{current_write =
+ #connection_state{
+ sequence_number = Seq,
+ compression_state=CompS0,
+ security_parameters=
+ #security_parameters{compression_algorithm=CompAlg}
+ }= WriteState0} = 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}}.
+ WriteState1 = WriteState0#connection_state{compression_state = CompS1},
+ MacHash = calc_mac_hash(Type, Version, Comp, WriteState1),
+ {CipherFragment, WriteState} = ssl_record:cipher(Version, Comp, WriteState1, MacHash),
+ CipherText = encode_tls_cipher_text(Type, Version, CipherFragment),
+ {CipherText, ConnectionStates#connection_states{current_write = WriteState#connection_state{sequence_number = Seq +1}}}.
%%--------------------------------------------------------------------
-spec decode_cipher_text(#ssl_tls{}, #connection_states{}) ->
@@ -143,19 +146,23 @@ decode_cipher_text(#ssl_tls{type = Type, version = Version,
fragment = CipherFragment} = CipherText, ConnnectionStates0) ->
ReadState0 = ConnnectionStates0#connection_states.current_read,
#connection_state{compression_state = CompressionS0,
+ sequence_number = Seq,
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.
+ {PlainFragment, Mac, ReadState1} = ssl_record:decipher(Version, CipherFragment, ReadState0),
+ MacHash = calc_mac_hash(Type, Version, PlainFragment, ReadState1),
+ case ssl_record:is_correct_mac(Mac, MacHash) of
+ true ->
+ {Plain, CompressionS1} = ssl_record:uncompress(CompressAlg,
+ PlainFragment, CompressionS0),
+ ConnnectionStates = ConnnectionStates0#connection_states{
+ current_read = ReadState1#connection_state{
+ sequence_number = Seq + 1,
+ compression_state = CompressionS1}},
+ {CipherText#ssl_tls{fragment = Plain}, ConnnectionStates};
+ false ->
+ ?ALERT_REC(?FATAL, ?BAD_RECORD_MAC)
+ end.
%%--------------------------------------------------------------------
-spec protocol_version(tls_atom_version() | tls_version()) ->
@@ -280,39 +287,6 @@ 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,
- #connection_state{cipher_state = CipherS0,
- sequence_number = SeqNo,
- security_parameters=
- #security_parameters{bulk_cipher_algorithm =
- BCA}
- } = 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 = 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 ->
- {PlainFragment,
- CS1#connection_state{sequence_number = SeqNo+1}};
- false ->
- ?ALERT_REC(?FATAL, ?BAD_RECORD_MAC)
- end;
- #alert{} = Alert ->
- Alert
- end.
mac_hash({_,_}, ?NULL, _MacSecret, _SeqNo, _Type,
_Length, _Fragment) ->