aboutsummaryrefslogtreecommitdiffstats
path: root/lib/ssl
diff options
context:
space:
mode:
authorIngela Anderton Andin <ingela@erlang.org>2013-06-18 12:30:38 +0200
committerIngela Anderton Andin <ingela@erlang.org>2013-09-10 09:37:29 +0200
commitb9a31f24053c84d9a7ffa4281bc11f47b3be5905 (patch)
treee0698a95d56b1fd6070d916033cd07f098d3b5ed /lib/ssl
parentfb6ac178ac437fcc04f1675df75b0583c1d24ad7 (diff)
downloadotp-b9a31f24053c84d9a7ffa4281bc11f47b3be5905.tar.gz
otp-b9a31f24053c84d9a7ffa4281bc11f47b3be5905.tar.bz2
otp-b9a31f24053c84d9a7ffa4281bc11f47b3be5905.zip
ssl: DTLS record handling
Also refactor so that TLS and DTLS can have common functions when possible.
Diffstat (limited to 'lib/ssl')
-rw-r--r--lib/ssl/src/Makefile7
-rw-r--r--lib/ssl/src/dtls_record.erl51
-rw-r--r--lib/ssl/src/dtls_record.hrl10
-rw-r--r--lib/ssl/src/dtls_v1.erl2
-rw-r--r--lib/ssl/src/ssl.app.src8
-rw-r--r--lib/ssl/src/ssl_cipher.erl4
-rw-r--r--lib/ssl/src/ssl_handshake.erl12
-rw-r--r--lib/ssl/src/ssl_record.erl89
-rw-r--r--lib/ssl/src/ssl_record.hrl7
-rw-r--r--lib/ssl/src/ssl_v2.erl (renamed from lib/ssl/src/ssl_ssl2.erl)16
-rw-r--r--lib/ssl/src/ssl_v3.erl (renamed from lib/ssl/src/ssl_ssl3.erl)28
-rw-r--r--lib/ssl/src/tls_handshake.erl19
-rw-r--r--lib/ssl/src/tls_record.erl31
-rw-r--r--lib/ssl/src/tls_record.hrl7
-rw-r--r--lib/ssl/src/tls_v1.erl (renamed from lib/ssl/src/ssl_tls1.erl)42
15 files changed, 193 insertions, 140 deletions
diff --git a/lib/ssl/src/Makefile b/lib/ssl/src/Makefile
index a467b3f608..a5af451244 100644
--- a/lib/ssl/src/Makefile
+++ b/lib/ssl/src/Makefile
@@ -65,9 +65,10 @@ MODULES= \
ssl_socket \
tls_record \
dtls_record \
- ssl_ssl2 \
- ssl_ssl3 \
- ssl_tls1 \
+ ssl_record \
+ ssl_v2 \
+ ssl_v3 \
+ tls_v1 \
ssl_tls_dist_proxy
INTERNAL_HRL_FILES = \
diff --git a/lib/ssl/src/dtls_record.erl b/lib/ssl/src/dtls_record.erl
index 98c60f599c..daadae0725 100644
--- a/lib/ssl/src/dtls_record.erl
+++ b/lib/ssl/src/dtls_record.erl
@@ -30,7 +30,7 @@
%% Misc.
-export([protocol_version/1, lowest_protocol_version/2,
highest_protocol_version/1, supported_protocol_versions/0,
- is_acceptable_version/2]).
+ is_acceptable_version/2, cipher/4, decipher/2]).
%%--------------------------------------------------------------------
-spec init_connection_state_seq(tls_version(), #connection_states{}) ->
@@ -71,25 +71,18 @@ current_connection_state_epoch(#connection_states{current_write = Current},
%% Description: Returns the instance of the connection_state record
%% that is defined by the Epoch.
%%--------------------------------------------------------------------
-connection_state_by_epoch(#connection_states{previous_read = CS}, Epoch, read)
- when CS#connection_state.epoch == Epoch ->
- CS;
connection_state_by_epoch(#connection_states{current_read = CS}, Epoch, read)
when CS#connection_state.epoch == Epoch ->
CS;
connection_state_by_epoch(#connection_states{pending_read = CS}, Epoch, read)
when CS#connection_state.epoch == Epoch ->
CS;
-connection_state_by_epoch(#connection_states{previous_write = CS}, Epoch, write)
- when CS#connection_state.epoch == Epoch ->
- CS;
connection_state_by_epoch(#connection_states{current_write = CS}, Epoch, write)
when CS#connection_state.epoch == Epoch ->
CS;
connection_state_by_epoch(#connection_states{pending_write = CS}, Epoch, write)
when CS#connection_state.epoch == Epoch ->
CS.
-
%%--------------------------------------------------------------------
-spec set_connection_state_by_epoch(#connection_states{},
#connection_state{}, read | write) -> ok.
@@ -98,12 +91,6 @@ connection_state_by_epoch(#connection_states{pending_write = CS}, Epoch, write)
%% that is defined by the Epoch.
%%--------------------------------------------------------------------
set_connection_state_by_epoch(ConnectionStates0 =
- #connection_states{previous_read = CS},
- NewCS = #connection_state{epoch = Epoch}, read)
- when CS#connection_state.epoch == Epoch ->
- ConnectionStates0#connection_states{previous_read = NewCS};
-
-set_connection_state_by_epoch(ConnectionStates0 =
#connection_states{current_read = CS},
NewCS = #connection_state{epoch = Epoch}, read)
when CS#connection_state.epoch == Epoch ->
@@ -116,12 +103,6 @@ set_connection_state_by_epoch(ConnectionStates0 =
ConnectionStates0#connection_states{pending_read = NewCS};
set_connection_state_by_epoch(ConnectionStates0 =
- #connection_states{previous_write = CS},
- NewCS = #connection_state{epoch = Epoch}, write)
- when CS#connection_state.epoch == Epoch ->
- ConnectionStates0#connection_states{previous_write = NewCS};
-
-set_connection_state_by_epoch(ConnectionStates0 =
#connection_states{current_write = CS},
NewCS = #connection_state{epoch = Epoch}, write)
when CS#connection_state.epoch == Epoch ->
@@ -133,7 +114,6 @@ set_connection_state_by_epoch(ConnectionStates0 =
when CS#connection_state.epoch == Epoch ->
ConnectionStates0#connection_states{pending_write = NewCS}.
-
%%--------------------------------------------------------------------
-spec protocol_version(tls_atom_version() | tls_version()) ->
tls_version() | tls_atom_version().
@@ -283,20 +263,21 @@ supported_connection_protocol_versions([]) ->
is_acceptable_version(Version, Versions) ->
lists:member(Version, Versions).
-%%--------------------------------------------------------------------
--spec clear_previous_epoch(#connection_states{}) ->
- #connection_states{}.
-%%
-%% Description: Advance to min_read_epoch to the current read epoch.
-%%--------------------------------------------------------------------
-clear_previous_epoch(States =
- #connection_states{current_read = Current}) ->
- States#connection_states{min_read_epoch = Current#connection_state.epoch}.
-
+cipher(Type, Version, Fragment, CS0) ->
+ 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, sequence = SeqNo,
+ epoch = Epoch, record_seq = SeqNo,
fragment=Fragment}, CS0) ->
SP = CS0#connection_state.security_parameters,
BCA = SP#security_parameters.bulk_cipher_algorithm,
@@ -307,7 +288,7 @@ decipher(TLS=#ssl_tls{type=Type, version=Version={254, _},
CS1 = CS0#connection_state{cipher_state = CipherS1},
TLength = size(T),
MacHash = hash_with_seqno(CS1, Type, Version, Epoch, SeqNo, TLength, T),
- case is_correct_mac(Mac, MacHash) of
+ case ssl_record:is_correct_mac(Mac, MacHash) of
true ->
{TLS#ssl_tls{fragment = T}, CS1};
false ->
@@ -338,3 +319,7 @@ hash_and_bump_seqno(#connection_state{epoch = Epoch,
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/dtls_record.hrl b/lib/ssl/src/dtls_record.hrl
index c50550cc28..b72c14c2d7 100644
--- a/lib/ssl/src/dtls_record.hrl
+++ b/lib/ssl/src/dtls_record.hrl
@@ -30,16 +30,6 @@
-define(INITIAL_BYTES, 5).
--record(connection_states, {
- min_read_epoch,
- previous_read,
- current_read,
- pending_read,
- previous_write,
- current_write,
- pending_write
- }).
-
%% Used to handle tls_plain_text, tls_compressed and tls_cipher_text
-record(ssl_tls, {
diff --git a/lib/ssl/src/dtls_v1.erl b/lib/ssl/src/dtls_v1.erl
index 930998b460..a9fcf575af 100644
--- a/lib/ssl/src/dtls_v1.erl
+++ b/lib/ssl/src/dtls_v1.erl
@@ -25,7 +25,7 @@
-spec suites(Minor:: 253|255) -> [cipher_suite()].
suites(Minor) ->
- tls_v1:suites(corresponding_minor_tls_version(Minor));
+ tls_v1:suites(corresponding_minor_tls_version(Minor)).
mac_hash(Version, MacAlg, MacSecret, SeqNo, Type, Length, Fragment) ->
tls_v1:mac_hash(MacAlg, MacSecret, SeqNo, Type, Version,
diff --git a/lib/ssl/src/ssl.app.src b/lib/ssl/src/ssl.app.src
index 0a2ae92e9d..677f5fdd07 100644
--- a/lib/ssl/src/ssl.app.src
+++ b/lib/ssl/src/ssl.app.src
@@ -20,14 +20,14 @@
inet_tls_dist,
ssl_tls_dist_proxy,
ssl_dist_sup,
- ssl_tls1,
- ssl_ssl3,
- ssl_ssl2,
+ tls_v1,
+ ssl_v3,
+ ssl_v2,
ssl_session,
ssl_session_cache_api,
ssl_session_cache,
ssl_socket,
- %%ssl_record,
+ ssl_record,
ssl_manager,
ssl_handshake,
ssl_connection_sup,
diff --git a/lib/ssl/src/ssl_cipher.erl b/lib/ssl/src/ssl_cipher.erl
index 09aad8e414..d958b74e9f 100644
--- a/lib/ssl/src/ssl_cipher.erl
+++ b/lib/ssl/src/ssl_cipher.erl
@@ -195,9 +195,9 @@ block_decipher(Fun, #cipher_state{key=Key, iv=IV} = CipherState0,
%% Description: Returns a list of supported cipher suites.
%%--------------------------------------------------------------------
suites({3, 0}) ->
- ssl_ssl3:suites();
+ ssl_v3:suites();
suites({3, N}) ->
- ssl_tls1:suites(N).
+ tls_v1:suites(N).
%%--------------------------------------------------------------------
-spec anonymous_suites() -> [cipher_suite()].
diff --git a/lib/ssl/src/ssl_handshake.erl b/lib/ssl/src/ssl_handshake.erl
index 0f5d5def48..5084c46571 100644
--- a/lib/ssl/src/ssl_handshake.erl
+++ b/lib/ssl/src/ssl_handshake.erl
@@ -575,6 +575,7 @@ encode_hello_extensions([#renegotiation_info{renegotiated_connection = Info} | R
encode_hello_extensions(Rest, <<?UINT16(?RENEGOTIATION_EXT), ?UINT16(Len), ?BYTE(InfoLen),
Info/binary, Acc/binary>>);
encode_hello_extensions([#elliptic_curves{elliptic_curve_list = EllipticCurves} | Rest], Acc) ->
+
EllipticCurveList = << <<(tls_v1:oid_to_enum(X)):16>> || X <- EllipticCurves>>,
ListLen = byte_size(EllipticCurveList),
Len = ListLen + 2,
@@ -752,7 +753,7 @@ dec_server_key(<<?BYTE(?NAMED_CURVE), ?UINT16(CurveID),
?BYTE(PointLen), ECPoint:PointLen/binary,
_/binary>> = KeyStruct,
?KEY_EXCHANGE_EC_DIFFIE_HELLMAN, Version) ->
- Params = #server_ecdh_params{curve = {namedCurve, ssl_tls1:enum_to_oid(CurveID)},
+ Params = #server_ecdh_params{curve = {namedCurve, tls_v1:enum_to_oid(CurveID)},
public = ECPoint},
{BinMsg, HashSign, Signature} = dec_server_key_params(PointLen + 4, KeyStruct, Version),
#server_key_params{params = Params,
@@ -1445,10 +1446,11 @@ dec_hello_extensions(<<?UINT16(?ELLIPTIC_CURVES_EXT), ?UINT16(Len),
EllipticCurveListLen = Len - 2,
<<?UINT16(EllipticCurveListLen), EllipticCurveList/binary>> = ExtData,
EllipticCurves = [tls_v1:enum_to_oid(X) || <<X:16>> <= EllipticCurveList],
- dec_hello_extensions(Rest, Acc#hello_extensions{elliptic_curves =
- #elliptic_curves{elliptic_curve_list =
- EllipticCurves}});
-dec_hello_extensions(<<?UINT16(?EC_POINT_FORMATS_EXT), ?UINT16(Len), ?BYTE(_),
+
+ dec_hello_extensions(Rest, [{elliptic_curves,
+ #elliptic_curves{elliptic_curve_list = EllipticCurves}} | Acc]);
+
+dec_hello_extensions(<<?UINT16(?EC_POINT_FORMATS_EXT), ?UINT16(Len),
ExtData:Len/binary, Rest/binary>>, Acc) ->
%%ECPointFormatListLen = Len - 1,
<<?BYTE(_), ECPointFormatList/binary>> = ExtData,
diff --git a/lib/ssl/src/ssl_record.erl b/lib/ssl/src/ssl_record.erl
new file mode 100644
index 0000000000..ac56e3ab29
--- /dev/null
+++ b/lib/ssl/src/ssl_record.erl
@@ -0,0 +1,89 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2013-2013. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+
+-module(ssl_record).
+
+-include("ssl_internal.hrl").
+-include("ssl_record.hrl").
+
+-export([empty_connection_state/1, activate_pending_connection_state/2, is_correct_mac/2]).
+
+empty_connection_state(ConnectionEnd) ->
+ SecParams = empty_security_params(ConnectionEnd),
+ #connection_state{security_parameters = SecParams}.
+
+empty_security_params(ConnectionEnd = ?CLIENT) ->
+ #security_parameters{connection_end = ConnectionEnd,
+ client_random = random()};
+empty_security_params(ConnectionEnd = ?SERVER) ->
+ #security_parameters{connection_end = ConnectionEnd,
+ server_random = random()}.
+random() ->
+ Secs_since_1970 = calendar:datetime_to_gregorian_seconds(
+ calendar:universal_time()) - 62167219200,
+ Random_28_bytes = crypto:rand_bytes(28),
+ <<?UINT32(Secs_since_1970), Random_28_bytes/binary>>.
+
+%%--------------------------------------------------------------------
+-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{current_read = Current,
+ pending_read = Pending},
+ read) ->
+ %% Next epoch is a noop for SSL/TLS only uesed by DTLS
+ NewCurrent = Pending#connection_state{epoch = connection_state_next_epoch(Current),
+ sequence_number = 0},
+ SecParams = Pending#connection_state.security_parameters,
+ ConnectionEnd = SecParams#security_parameters.connection_end,
+ EmptyPending = 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{current_write = Current,
+ pending_write = Pending},
+ write) ->
+ %% Next epoch is a noop for SSL/TLS only uesed by DTLS
+ NewCurrent = Pending#connection_state{epoch = connection_state_next_epoch(Current),
+ sequence_number = 0},
+ SecParams = Pending#connection_state.security_parameters,
+ ConnectionEnd = SecParams#security_parameters.connection_end,
+ EmptyPending = 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
+ }.
+
+connection_state_next_epoch(#connection_state{epoch = undefined}) ->
+ undefined;
+connection_state_next_epoch(State) ->
+ State#connection_state.epoch + 1.
+
+is_correct_mac(Mac, Mac) ->
+ true;
+is_correct_mac(_M,_H) ->
+ false.
diff --git a/lib/ssl/src/ssl_record.hrl b/lib/ssl/src/ssl_record.hrl
index 8a6a211553..34893ce699 100644
--- a/lib/ssl/src/ssl_record.hrl
+++ b/lib/ssl/src/ssl_record.hrl
@@ -42,6 +42,13 @@
server_verify_data
}).
+-record(connection_states, {
+ current_read,
+ pending_read,
+ current_write,
+ pending_write
+ }).
+
-record(security_parameters, {
cipher_suite,
connection_end,
diff --git a/lib/ssl/src/ssl_ssl2.erl b/lib/ssl/src/ssl_v2.erl
index a9ab6a2678..07876366f1 100644
--- a/lib/ssl/src/ssl_ssl2.erl
+++ b/lib/ssl/src/ssl_v2.erl
@@ -1,30 +1,30 @@
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2007-2011. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 2007-2013. All Rights Reserved.
+%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
%% compliance with the License. You should have received a copy of the
%% Erlang Public License along with this software. If not, it can be
%% retrieved online at http://www.erlang.org/.
-%%
+%%
%% Software distributed under the License is distributed on an "AS IS"
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
%% the License for the specific language governing rights and limitations
%% under the License.
-%%
+%%
%% %CopyrightEnd%
%%
%%
%%----------------------------------------------------------------------
-%% Purpose: Handles sslv2 hello as clients supporting sslv2 and higher
+%% Purpose: Handles sslv2 hello as clients supporting sslv2 and higher
%% will send an sslv2 hello.
%%----------------------------------------------------------------------
--module(ssl_ssl2).
-
+-module(ssl_v2).
+
-export([client_random/2]).
client_random(ChallengeData, 32) ->
diff --git a/lib/ssl/src/ssl_ssl3.erl b/lib/ssl/src/ssl_v3.erl
index 013c27ebb5..d477b3df81 100644
--- a/lib/ssl/src/ssl_ssl3.erl
+++ b/lib/ssl/src/ssl_v3.erl
@@ -22,14 +22,14 @@
%% Purpose: Handles sslv3 encryption.
%%----------------------------------------------------------------------
--module(ssl_ssl3).
+-module(ssl_v3).
-include("ssl_cipher.hrl").
-include("ssl_internal.hrl").
-include("ssl_record.hrl"). % MD5 and SHA
-export([master_secret/3, finished/3, certificate_verify/3,
- mac_hash/6, setup_keys/7,
+ mac_hash/6, setup_keys/7,
suites/0]).
-compile(inline).
@@ -40,7 +40,7 @@
-spec master_secret(binary(), binary(), binary()) -> binary().
master_secret(PremasterSecret, ClientRandom, ServerRandom) ->
- %% draft-ietf-tls-ssl-version3-00 - 6.2.2
+ %% draft-ietf-tls-ssl-version3-00 - 6.2.2
%% key_block =
%% MD5(master_secret + SHA(`A' + master_secret +
%% ServerHello.random +
@@ -62,7 +62,7 @@ finished(Role, MasterSecret, Handshake) ->
%% opaque md5_hash[16];
%% opaque sha_hash[20];
%% } Finished;
- %%
+ %%
%% md5_hash MD5(master_secret + pad2 +
%% MD5(handshake_messages + Sender +
%% master_secret + pad1));
@@ -95,23 +95,23 @@ certificate_verify(sha, MasterSecret, Handshake) ->
handshake_hash(?SHA, MasterSecret, undefined, Handshake).
--spec mac_hash(integer(), binary(), integer(), integer(), integer(), binary()) -> binary().
+-spec mac_hash(integer(), binary(), integer(), integer(), integer(), binary()) -> binary().
mac_hash(Method, Mac_write_secret, Seq_num, Type, Length, Fragment) ->
- %% draft-ietf-tls-ssl-version3-00 - 5.2.3.1
+ %% draft-ietf-tls-ssl-version3-00 - 5.2.3.1
%% hash(MAC_write_secret + pad_2 +
%% hash(MAC_write_secret + pad_1 + seq_num +
%% SSLCompressed.type + SSLCompressed.length +
%% SSLCompressed.fragment));
- Mac = mac_hash(Method, Mac_write_secret,
- [<<?UINT64(Seq_num), ?BYTE(Type),
+ Mac = mac_hash(Method, Mac_write_secret,
+ [<<?UINT64(Seq_num), ?BYTE(Type),
?UINT16(Length)>>, Fragment]),
Mac.
--spec setup_keys(binary(), binary(), binary(),
- integer(), integer(), term(), integer()) ->
- {binary(), binary(), binary(),
- binary(), binary(), binary()}.
+-spec setup_keys(binary(), binary(), binary(),
+ integer(), integer(), term(), integer()) ->
+ {binary(), binary(), binary(),
+ binary(), binary(), binary()}.
setup_keys(MasterSecret, ServerRandom, ClientRandom, HS, KML, _EKML, IVS) ->
KeyBlock = generate_keyblock(MasterSecret, ServerRandom, ClientRandom,
@@ -133,7 +133,7 @@ setup_keys(MasterSecret, ServerRandom, ClientRandom, HS, KML, _EKML, IVS) ->
-spec suites() -> [cipher_suite()].
suites() ->
- [
+ [
?TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
?TLS_DHE_DSS_WITH_AES_256_CBC_SHA,
?TLS_RSA_WITH_AES_256_CBC_SHA,
@@ -143,7 +143,7 @@ suites() ->
?TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
?TLS_DHE_DSS_WITH_AES_128_CBC_SHA,
?TLS_RSA_WITH_AES_128_CBC_SHA,
- %%?TLS_RSA_WITH_IDEA_CBC_SHA,
+ %%?TLS_RSA_WITH_IDEA_CBC_SHA,
?TLS_RSA_WITH_RC4_128_SHA,
?TLS_RSA_WITH_RC4_128_MD5,
?TLS_RSA_WITH_DES_CBC_SHA
diff --git a/lib/ssl/src/tls_handshake.erl b/lib/ssl/src/tls_handshake.erl
index 066590afb1..fef1464c64 100644
--- a/lib/ssl/src/tls_handshake.erl
+++ b/lib/ssl/src/tls_handshake.erl
@@ -33,7 +33,7 @@
-include_lib("public_key/include/public_key.hrl").
-export([client_hello/8, server_hello/4, hello/4,
- get_tls_handshake/3, encode_handshake/2,
+ get_tls_handshake/3, encode_handshake/2, decode_handshake/3,
init_handshake_history/0, update_handshake_history/2]).
%%====================================================================
@@ -197,17 +197,22 @@ update_handshake_history(Handshake, % special-case SSL2 client hello
update_handshake_history({Handshake0, _Prev}, Data) ->
{[Data|Handshake0], Handshake0}.
-%%--------------------------------------------------------------------
-%%% Internal functions
-%%--------------------------------------------------------------------
+
get_tls_handshake_aux(Version, <<?BYTE(Type), ?UINT24(Length),
Body:Length/binary,Rest/binary>>, Acc) ->
Raw = <<?BYTE(Type), ?UINT24(Length), Body/binary>>,
- H = decode_handshake(Version, Type, Body),
- get_tls_handshake_aux(Version, Rest, [{H,Raw} | Acc]);
+ Handshake = decode_handshake(Version, Type, Body),
+ get_tls_handshake_aux(Version, Rest, [{Handshake,Raw} | Acc]);
get_tls_handshake_aux(_Version, Data, Acc) ->
{lists:reverse(Acc), Data}.
+%%--------------------------------------------------------------------
+%%% Internal functions
+%%--------------------------------------------------------------------
+
+decode_handshake(_, ?HELLO_REQUEST, <<>>) ->
+ #hello_request{};
+
%% Client hello v2.
%% The server must be able to receive such messages, from clients that
%% are willing to use ssl v3 or higher, but have ssl v2 compatibility.
@@ -217,7 +222,7 @@ decode_handshake(_Version, ?CLIENT_HELLO, <<?BYTE(Major), ?BYTE(Minor),
CipherSuites:CSLength/binary,
ChallengeData:CDLength/binary>>) ->
#client_hello{client_version = {Major, Minor},
- random = ssl_ssl2:client_random(ChallengeData, CDLength),
+ random = ssl_v2:client_random(ChallengeData, CDLength),
session_id = 0,
cipher_suites = ssl_handshake:decode_suites('3_bytes', CipherSuites),
compression_methods = [?NULL],
diff --git a/lib/ssl/src/tls_record.erl b/lib/ssl/src/tls_record.erl
index 1409a04763..9ab512f334 100644
--- a/lib/ssl/src/tls_record.erl
+++ b/lib/ssl/src/tls_record.erl
@@ -77,7 +77,7 @@
init_connection_states(Role) ->
ConnectionEnd = record_protocol_role(Role),
Current = initial_connection_state(ConnectionEnd),
- Pending = empty_connection_state(ConnectionEnd),
+ Pending = ssl_record:empty_connection_state(ConnectionEnd),
#connection_states{current_read = Current,
pending_read = Pending,
current_write = Current,
@@ -265,7 +265,7 @@ activate_pending_connection_state(States =
NewCurrent = Pending#connection_state{sequence_number = 0},
SecParams = Pending#connection_state.security_parameters,
ConnectionEnd = SecParams#security_parameters.connection_end,
- EmptyPending = empty_connection_state(ConnectionEnd),
+ 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,
@@ -278,7 +278,7 @@ activate_pending_connection_state(States =
NewCurrent = Pending#connection_state{sequence_number = 0},
SecParams = Pending#connection_state.security_parameters,
ConnectionEnd = SecParams#security_parameters.connection_end,
- EmptyPending = empty_connection_state(ConnectionEnd),
+ 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,
@@ -591,21 +591,6 @@ initial_security_params(ConnectionEnd) ->
ssl_cipher:security_parameters(highest_protocol_version(), ?TLS_NULL_WITH_NULL_NULL,
SecParams).
-empty_connection_state(ConnectionEnd) ->
- SecParams = empty_security_params(ConnectionEnd),
- #connection_state{security_parameters = SecParams}.
-
-empty_security_params(ConnectionEnd = ?CLIENT) ->
- #security_parameters{connection_end = ConnectionEnd,
- client_random = random()};
-empty_security_params(ConnectionEnd = ?SERVER) ->
- #security_parameters{connection_end = ConnectionEnd,
- server_random = random()}.
-random() ->
- Secs_since_1970 = calendar:datetime_to_gregorian_seconds(
- calendar:universal_time()) - 62167219200,
- Random_28_bytes = crypto:rand_bytes(28),
- <<?UINT32(Secs_since_1970), Random_28_bytes/binary>>.
record_protocol_role(client) ->
?CLIENT;
@@ -667,7 +652,7 @@ decipher(TLS=#ssl_tls{type=Type, version=Version, fragment=Fragment}, CS0) ->
CS1 = CS0#connection_state{cipher_state = CipherS1},
TLength = size(T),
{MacHash, CS2} = hash_and_bump_seqno(CS1, Type, Version, TLength, T),
- case is_correct_mac(Mac, MacHash) of
+ case ssl_record:is_correct_mac(Mac, MacHash) of
true ->
{TLS#ssl_tls{fragment = T}, CS2};
false ->
@@ -696,19 +681,15 @@ hash_and_bump_seqno(#connection_state{sequence_number = SeqNo,
Length, Fragment),
{Hash, CS0#connection_state{sequence_number = SeqNo+1}}.
-is_correct_mac(Mac, Mac) ->
- true;
-is_correct_mac(_M,_H) ->
- false.
mac_hash({_,_}, ?NULL, _MacSecret, _SeqNo, _Type,
_Length, _Fragment) ->
<<>>;
mac_hash({3, 0}, MacAlg, MacSecret, SeqNo, Type, Length, Fragment) ->
- ssl_ssl3:mac_hash(MacAlg, MacSecret, SeqNo, Type, Length, Fragment);
+ ssl_v3:mac_hash(MacAlg, MacSecret, SeqNo, Type, Length, Fragment);
mac_hash({3, N} = Version, MacAlg, MacSecret, SeqNo, Type, Length, Fragment)
when N =:= 1; N =:= 2; N =:= 3 ->
- ssl_tls1:mac_hash(MacAlg, MacSecret, SeqNo, Type, Version,
+ tls_v1:mac_hash(MacAlg, MacSecret, SeqNo, Type, Version,
Length, Fragment).
sufficient_tlsv1_2_crypto_support() ->
diff --git a/lib/ssl/src/tls_record.hrl b/lib/ssl/src/tls_record.hrl
index 0e3552bafa..0be1e35458 100644
--- a/lib/ssl/src/tls_record.hrl
+++ b/lib/ssl/src/tls_record.hrl
@@ -27,13 +27,6 @@
-define(tls_record, true).
-include("ssl_record.hrl"). %% Common TLS and DTLS records and Constantes
--record(connection_states, {
- current_read,
- pending_read,
- current_write,
- pending_write
- }).
-
%% Used to handle tls_plain_text, tls_compressed and tls_cipher_text
-record(ssl_tls, {
diff --git a/lib/ssl/src/ssl_tls1.erl b/lib/ssl/src/tls_v1.erl
index 8ab66d0627..2395e98642 100644
--- a/lib/ssl/src/ssl_tls1.erl
+++ b/lib/ssl/src/tls_v1.erl
@@ -22,7 +22,7 @@
%% Purpose: Handles tls1 encryption.
%%----------------------------------------------------------------------
--module(ssl_tls1).
+-module(tls_v1).
-include("ssl_cipher.hrl").
-include("ssl_internal.hrl").
@@ -86,7 +86,7 @@ certificate_verify(HashAlgo, _Version, Handshake) ->
-spec setup_keys(integer(), integer(), binary(), binary(), binary(), integer(),
integer(), integer()) -> {binary(), binary(), binary(),
- binary(), binary(), binary()}.
+ binary(), binary(), binary()}.
setup_keys(Version, _PrfAlgo, MasterSecret, ServerRandom, ClientRandom, HashSize,
KeyMatLen, IVSize)
@@ -106,7 +106,7 @@ setup_keys(Version, _PrfAlgo, MasterSecret, ServerRandom, ClientRandom, HashSize
WantedLength = 2 * (HashSize + KeyMatLen + IVSize),
KeyBlock = prf(?MD5SHA, MasterSecret, "key expansion",
[ServerRandom, ClientRandom], WantedLength),
- <<ClientWriteMacSecret:HashSize/binary,
+ <<ClientWriteMacSecret:HashSize/binary,
ServerWriteMacSecret:HashSize/binary,
ClientWriteKey:KeyMatLen/binary, ServerWriteKey:KeyMatLen/binary,
ClientIV:IVSize/binary, ServerIV:IVSize/binary>> = KeyBlock,
@@ -167,22 +167,22 @@ setup_keys(Version, PrfAlgo, MasterSecret, ServerRandom, ClientRandom, HashSize,
ServerWriteKey, ClientIV, ServerIV}.
-spec mac_hash(integer(), binary(), integer(), integer(), tls_version(),
- integer(), binary()) -> binary().
+ integer(), binary()) -> binary().
-mac_hash(Method, Mac_write_secret, Seq_num, Type, {Major, Minor},
+mac_hash(Method, Mac_write_secret, Seq_num, Type, {Major, Minor},
Length, Fragment) ->
%% RFC 2246 & 4346 - 6.2.3.1.
%% HMAC_hash(MAC_write_secret, seq_num + TLSCompressed.type +
%% TLSCompressed.version + TLSCompressed.length +
%% TLSCompressed.fragment));
- Mac = hmac_hash(Method, Mac_write_secret,
- [<<?UINT64(Seq_num), ?BYTE(Type),
- ?BYTE(Major), ?BYTE(Minor), ?UINT16(Length)>>,
+ Mac = hmac_hash(Method, Mac_write_secret,
+ [<<?UINT64(Seq_num), ?BYTE(Type),
+ ?BYTE(Major), ?BYTE(Minor), ?UINT16(Length)>>,
Fragment]),
Mac.
-spec suites(1|2|3) -> [cipher_suite()].
-
+
suites(Minor) when Minor == 1; Minor == 2->
case sufficent_ec_support() of
true ->
@@ -199,8 +199,8 @@ suites(Minor) when Minor == 3 ->
no_ec_suites(3) ++ no_ec_suites(2)
end.
-all_suites(Minor) when Minor == 1; Minor == 2->
- [
+all_suites(Minor) when Minor == 1; Minor == 2->
+ [
?TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
?TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
?TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
@@ -224,7 +224,7 @@ all_suites(Minor) when Minor == 1; Minor == 2->
?TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA,
?TLS_ECDH_RSA_WITH_AES_128_CBC_SHA,
?TLS_RSA_WITH_AES_128_CBC_SHA,
-
+
?TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
?TLS_ECDHE_RSA_WITH_RC4_128_SHA,
?TLS_RSA_WITH_RC4_128_SHA,
@@ -232,32 +232,32 @@ all_suites(Minor) when Minor == 1; Minor == 2->
?TLS_DHE_RSA_WITH_DES_CBC_SHA,
?TLS_ECDH_ECDSA_WITH_RC4_128_SHA,
?TLS_ECDH_RSA_WITH_RC4_128_SHA,
-
+
?TLS_RSA_WITH_DES_CBC_SHA
];
-all_suites(3) ->
+all_suites(3) ->
[
?TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,
?TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,
?TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384,
?TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384,
-
+
?TLS_DHE_RSA_WITH_AES_256_CBC_SHA256,
?TLS_DHE_DSS_WITH_AES_256_CBC_SHA256,
?TLS_RSA_WITH_AES_256_CBC_SHA256,
-
+
?TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
?TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
?TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256,
?TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256,
-
+
?TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,
?TLS_DHE_DSS_WITH_AES_128_CBC_SHA256,
?TLS_RSA_WITH_AES_128_CBC_SHA256
].
-no_ec_suites(Minor) when Minor == 1; Minor == 2->
- [
+no_ec_suites(Minor) when Minor == 1; Minor == 2->
+ [
?TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
?TLS_DHE_DSS_WITH_AES_256_CBC_SHA,
?TLS_RSA_WITH_AES_256_CBC_SHA,
@@ -272,7 +272,7 @@ no_ec_suites(Minor) when Minor == 1; Minor == 2->
?TLS_DHE_RSA_WITH_DES_CBC_SHA,
?TLS_RSA_WITH_DES_CBC_SHA
];
-no_ec_suites(3) ->
+no_ec_suites(3) ->
[
?TLS_DHE_RSA_WITH_AES_256_CBC_SHA256,
?TLS_DHE_DSS_WITH_AES_256_CBC_SHA256,
@@ -323,7 +323,7 @@ p_hash(Secret, Seed, WantedLength, Method, N, Acc) ->
%% ... Where A(0) = seed
%% A(i) = HMAC_hash(secret, A(i-1))
-%% a(0, _Secret, Seed, _Method) ->
+%% a(0, _Secret, Seed, _Method) ->
%% Seed.
%% a(N, Secret, Seed, Method) ->
%% hmac_hash(Method, Secret, a(N-1, Secret, Seed, Method)).