1%%
2%% %CopyrightBegin%
3%%
4%% Copyright Ericsson AB 2007-2018. All Rights Reserved.
5%%
6%% Licensed under the Apache License, Version 2.0 (the "License");
7%% you may not use this file except in compliance with the License.
8%% You may obtain a copy of the License at
9%%
10%%     http://www.apache.org/licenses/LICENSE-2.0
11%%
12%% Unless required by applicable law or agreed to in writing, software
13%% distributed under the License is distributed on an "AS IS" BASIS,
14%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15%% See the License for the specific language governing permissions and
16%% limitations under the License.
17%%
18%% %CopyrightEnd%
19%%
20
21%%
22%%----------------------------------------------------------------------
23%% Purpose: Handles sslv3 encryption.
24%%----------------------------------------------------------------------
25
26-module(ssl_v3).
27
28-include("ssl_cipher.hrl").
29-include("ssl_internal.hrl").
30-include("ssl_record.hrl"). 			% MD5 and SHA
31
32-export([master_secret/3, finished/3, certificate_verify/3,
33	 mac_hash/6, setup_keys/7,
34	 suites/0]).
35-compile(inline).
36
37%%====================================================================
38%% Internal application API
39%%====================================================================
40
41-spec master_secret(binary(), binary(), binary()) -> binary().
42
43master_secret(PremasterSecret, ClientRandom, ServerRandom) ->
44    %%  draft-ietf-tls-ssl-version3-00 - 6.2.2
45    %% key_block =
46    %%   MD5(master_secret + SHA(`A' + master_secret +
47    %%                           ServerHello.random +
48    %%                           ClientHello.random)) +
49    %%   MD5(master_secret + SHA(`BB' + master_secret +
50    %%                           ServerHello.random +
51    %%                           ClientHello.random)) +
52    %%   MD5(master_secret + SHA(`CCC' + master_secret +
53    %%                           ServerHello.random +
54    %%                           ClientHello.random)) + [...];
55    Block = generate_keyblock(PremasterSecret, ClientRandom, ServerRandom, 48),
56    Block.
57
58-spec finished(client | server, binary(), [binary()]) -> binary().
59
60finished(Role, MasterSecret, Handshake) ->
61   %%  draft-ietf-tls-ssl-version3-00 - 5.6.9 Finished
62   %%     struct {
63   %%      opaque md5_hash[16];
64   %%      opaque sha_hash[20];
65   %%  } Finished;
66   %%
67   %%   md5_hash       MD5(master_secret + pad2 +
68   %%                     MD5(handshake_messages + Sender +
69   %%                         master_secret + pad1));
70   %%  sha_hash        SHA(master_secret + pad2 +
71   %%                      SHA(handshake_messages + Sender +
72   %%                          master_secret + pad1));
73    Sender = get_sender(Role),
74    MD5 = handshake_hash(?MD5, MasterSecret, Sender, Handshake),
75    SHA = handshake_hash(?SHA, MasterSecret, Sender, Handshake),
76    <<MD5/binary, SHA/binary>>.
77
78-spec certificate_verify(md5sha | sha, binary(), [binary()]) -> binary().
79
80certificate_verify(md5sha, MasterSecret, Handshake) ->
81     %% md5_hash
82     %%           MD5(master_secret + pad_2 +
83     %%               MD5(handshake_messages + master_secret + pad_1));
84     %% sha_hash
85     %%           SHA(master_secret + pad_2 +
86     %%               SHA(handshake_messages + master_secret + pad_1));
87
88    MD5 = handshake_hash(?MD5, MasterSecret, undefined, Handshake),
89    SHA = handshake_hash(?SHA, MasterSecret, undefined, Handshake),
90    <<MD5/binary, SHA/binary>>;
91
92certificate_verify(sha, MasterSecret, Handshake) ->
93     %% sha_hash
94     %%           SHA(master_secret + pad_2 +
95     %%               SHA(handshake_messages + master_secret + pad_1));
96
97    handshake_hash(?SHA, MasterSecret, undefined, Handshake).
98
99-spec mac_hash(integer(), binary(), integer(), integer(), integer(), binary()) -> binary().
100
101mac_hash(Method, Mac_write_secret, Seq_num, Type, Length, Fragment) ->
102    %% draft-ietf-tls-ssl-version3-00 - 5.2.3.1
103    %% hash(MAC_write_secret + pad_2 +
104    %%      hash(MAC_write_secret + pad_1 + seq_num +
105    %%           SSLCompressed.type + SSLCompressed.length +
106    %%           SSLCompressed.fragment));
107    Mac = mac_hash(Method, Mac_write_secret,
108		   [<<?UINT64(Seq_num), ?BYTE(Type),
109		     ?UINT16(Length)>>, Fragment]),
110    Mac.
111
112-spec setup_keys(binary(), binary(), binary(),
113		 integer(), integer(), term(), integer()) ->
114			{binary(), binary(), binary(),
115			 binary(), binary(), binary()}.
116
117setup_keys(MasterSecret, ServerRandom, ClientRandom, HS, KML, _EKML, IVS) ->
118    KeyBlock = generate_keyblock(MasterSecret, ServerRandom, ClientRandom,
119				 2*(HS+KML+IVS)),
120    %%  draft-ietf-tls-ssl-version3-00 - 6.2.2
121    %% The key_block is partitioned as follows.
122    %% client_write_MAC_secret[CipherSpec.hash_size]
123    %% server_write_MAC_secret[CipherSpec.hash_size]
124    %% client_write_key[CipherSpec.key_material]
125    %% server_write_key[CipherSpec.key_material]
126    %% client_write_IV[CipherSpec.IV_size] /* non-export ciphers */
127    %% server_write_IV[CipherSpec.IV_size] /* non-export ciphers */
128    <<ClientWriteMacSecret:HS/binary, ServerWriteMacSecret:HS/binary,
129     ClientWriteKey:KML/binary, ServerWriteKey:KML/binary,
130     ClientIV:IVS/binary, ServerIV:IVS/binary>> = KeyBlock,
131    {ClientWriteMacSecret, ServerWriteMacSecret, ClientWriteKey,
132     ServerWriteKey, ClientIV, ServerIV}.
133
134-spec suites() -> [ssl_cipher_format:cipher_suite()].
135
136suites() ->
137    [
138      ?TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
139      ?TLS_DHE_DSS_WITH_AES_256_CBC_SHA,
140      ?TLS_RSA_WITH_AES_256_CBC_SHA,
141      ?TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA,
142      ?TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA,
143      ?TLS_RSA_WITH_3DES_EDE_CBC_SHA,
144      ?TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
145      ?TLS_DHE_DSS_WITH_AES_128_CBC_SHA,
146      ?TLS_RSA_WITH_AES_128_CBC_SHA
147     ].
148
149%%--------------------------------------------------------------------
150%%% Internal functions
151%%--------------------------------------------------------------------
152
153hash(?MD5, Data) ->
154    crypto:hash(md5, Data);
155hash(?SHA, Data) ->
156    crypto:hash(sha, Data).
157
158%%pad_1(?NULL) ->
159%%    "";
160pad_1(?MD5) ->
161    <<"666666666666666666666666666666666666666666666666">>;
162pad_1(?SHA) ->
163    <<"6666666666666666666666666666666666666666">>.
164%%pad_2(?NULL) ->
165%%    "";
166pad_2(?MD5) ->
167    <<"\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"
168     "\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\">>;
169pad_2(?SHA) ->
170    <<"\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"
171     "\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\">>.
172
173mac_hash(?NULL, _Secret, _Data) ->
174    <<>>;
175mac_hash(Method, Secret, Data) ->
176    InnerHash = hash(Method, [Secret, pad_1(Method), Data]),
177    hash(Method, [Secret, pad_2(Method), InnerHash]).
178
179handshake_hash(Method, MasterSecret, undefined, Handshake) ->
180    InnerHash = hash(Method, [Handshake, MasterSecret, pad_1(Method)]),
181    hash(Method, [MasterSecret, pad_2(Method), InnerHash]);
182handshake_hash(Method, MasterSecret, Sender, Handshake) ->
183    InnerHash = hash(Method, [Handshake, Sender, MasterSecret, pad_1(Method)]),
184    hash(Method, [MasterSecret, pad_2(Method), InnerHash]).
185
186get_sender(client) -> "CLNT";
187get_sender(server) -> "SRVR".
188
189generate_keyblock(MasterSecret, ServerRandom, ClientRandom, WantedLength) ->
190    gen(MasterSecret, [MasterSecret, ServerRandom, ClientRandom],
191	WantedLength, 0, $A, 1, []).
192
193gen(_Secret, _All, Wanted, Len, _C, _N, Acc) when Wanted =< Len ->
194    <<Block:Wanted/binary, _/binary>> = list_to_binary(lists:reverse(Acc)),
195    Block;
196gen(Secret, All, Wanted, Len, C, N, Acc) ->
197    Prefix = lists:duplicate(N, C),
198    SHA = crypto:hash(sha, [Prefix, All]),
199    MD5 = crypto:hash(md5, [Secret, SHA]),
200    gen(Secret, All, Wanted, Len + 16, C+1, N+1, [MD5 | Acc]).
201