1%%
2%% %CopyrightBegin%
3%%
4%% Copyright Ericsson AB 2008-2020. 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-module(ssl_handshake_SUITE).
24
25-behaviour(ct_suite).
26
27-include_lib("common_test/include/ct.hrl").
28-include("ssl_alert.hrl").
29-include("ssl_handshake.hrl").
30-include("ssl_internal.hrl").
31-include("ssl_record.hrl").
32-include("tls_handshake.hrl").
33-include_lib("public_key/include/public_key.hrl").
34
35%% Common test
36-export([all/0,
37         init_per_suite/1,
38         init_per_group/2,
39         init_per_testcase/2,
40         end_per_suite/1,
41         end_per_group/2,
42         end_per_testcase/2
43        ]).
44
45%% Test cases
46-export([decode_hello_handshake/1,
47         decode_single_hello_extension_correctly/1,
48         decode_supported_elliptic_curves_hello_extension_correctly/1,
49         decode_unknown_hello_extension_correctly/1,
50         encode_single_hello_sni_extension_correctly/1,
51         decode_single_hello_sni_extension_correctly/1,
52         decode_empty_server_sni_correctly/1,
53         select_proper_tls_1_2_rsa_default_hashsign/1,
54         ignore_hassign_extension_pre_tls_1_2/1,
55         signature_algorithms/1,
56         encode_decode_srp/1]).
57
58%%--------------------------------------------------------------------
59%% Common Test interface functions -----------------------------------
60%%--------------------------------------------------------------------
61all() -> [decode_hello_handshake,
62	  decode_single_hello_extension_correctly,
63	  decode_supported_elliptic_curves_hello_extension_correctly,
64	  decode_unknown_hello_extension_correctly,
65	  encode_single_hello_sni_extension_correctly,
66	  decode_single_hello_sni_extension_correctly,
67	  decode_empty_server_sni_correctly,
68	  select_proper_tls_1_2_rsa_default_hashsign,
69	  ignore_hassign_extension_pre_tls_1_2,
70	  signature_algorithms,
71	  encode_decode_srp].
72
73%%--------------------------------------------------------------------
74init_per_suite(Config) ->
75    Config.
76end_per_suite(Config) ->
77    Config.
78
79init_per_group(_GroupName, Config) ->
80    Config.
81
82end_per_group(_,Config) ->
83    Config.
84
85init_per_testcase(TC, Config0) when
86      TC =:= ignore_hassign_extension_pre_tls_1_2 orelse
87      TC =:= signature_algorithms ->
88    catch crypto:stop(),
89    try crypto:start() of
90	ok ->
91	    case is_supported(sha512) of
92		true ->
93		    ssl_test_lib:clean_start(),
94		    %% make rsa certs using oppenssl
95		    {ok, _} = make_certs:all(proplists:get_value(data_dir, Config0),
96					     proplists:get_value(priv_dir, Config0)),
97		    Config = ssl_test_lib:cert_options(Config0),
98		    ct:timetrap({seconds, 5}),
99		    Config;
100		false ->
101		    {skip, "Crypto did not support sha512"}
102	    end
103    catch _:_ ->
104	    {skip, "Crypto did not start"}
105    end;
106init_per_testcase(_, Config0) ->
107    Config0.
108
109end_per_testcase(ignore_hassign_extension_pre_tls_1_2, _) ->
110    crypto:stop();
111end_per_testcase(_TestCase, Config) ->
112    Config.
113
114%%--------------------------------------------------------------------
115%% Test Cases --------------------------------------------------------
116%%--------------------------------------------------------------------
117decode_hello_handshake(_Config) ->
118    HelloPacket = <<16#02, 16#00, 16#00,
119		    16#44, 16#03, 16#03, 16#4e, 16#7f, 16#c1, 16#03, 16#35,
120		    16#c2, 16#07, 16#b9, 16#4a, 16#58, 16#af, 16#34, 16#07,
121		    16#a6, 16#7e, 16#ef, 16#52, 16#cb, 16#e0, 16#ea, 16#b7,
122		    16#aa, 16#47, 16#c8, 16#c2, 16#2c, 16#66, 16#fa, 16#f8,
123		    16#09, 16#42, 16#cf, 16#00, 16#c0, 16#30, 16#00, 16#00,
124		    16#1c,
125		    16#00, 16#0b, 16#00, 16#04, 16#03, 16#00, 16#01, 16#02, % ec_point_formats
126		    16#ff, 16#01, 16#00, 16#01, 16#00, %% renegotiate
127		    16#00, 16#23,
128		    16#00, 16#00, 16#33, 16#74, 16#00, 16#07, 16#06, 16#73,
129		    16#70, 16#64, 16#79, 16#2f, 16#32>>,
130
131    Version = {3, 0},
132    {Records, _Buffer} = tls_handshake:get_tls_handshake(Version, HelloPacket, <<>>,
133                                                         default_options_map()),
134
135    {Hello, _Data} = hd(Records),
136    Extensions = Hello#server_hello.extensions,
137    #{renegotiation_info := #renegotiation_info{renegotiated_connection = <<0>>}} = Extensions.
138
139decode_single_hello_extension_correctly(_Config) ->
140    Renegotiation = <<?UINT16(?RENEGOTIATION_EXT), ?UINT16(1), 0>>,
141    Extensions = ssl_handshake:decode_extensions(Renegotiation, {3,3}, undefined),
142    #{renegotiation_info := #renegotiation_info{renegotiated_connection = <<0>>}} = Extensions.
143
144decode_supported_elliptic_curves_hello_extension_correctly(_Config) ->
145    % List of supported and unsupported curves (RFC4492:S5.1.1)
146    ClientEllipticCurves = [0, tls_v1:oid_to_enum(?sect233k1), 37, tls_v1:oid_to_enum(?sect193r2), 16#badc],
147    % Construct extension binary - modified version of ssl_handshake:encode_hello_extensions([#elliptic_curves{}], _)
148    EllipticCurveList = << <<X:16>> || X <- ClientEllipticCurves>>,
149    ListLen = byte_size(EllipticCurveList),
150    Len = ListLen + 2,
151    Extension = <<?UINT16(?ELLIPTIC_CURVES_EXT), ?UINT16(Len), ?UINT16(ListLen), EllipticCurveList/binary>>,
152    % after decoding we should see only valid curves
153    Extensions = ssl_handshake:decode_hello_extensions(Extension, {3,2}, {3,2}, client),
154    #{elliptic_curves := #elliptic_curves{elliptic_curve_list = [?sect233k1, ?sect193r2]}} = Extensions.
155
156decode_unknown_hello_extension_correctly(_Config) ->
157    FourByteUnknown = <<16#CA,16#FE, ?UINT16(4), 3, 0, 1, 2>>,
158    Renegotiation = <<?UINT16(?RENEGOTIATION_EXT), ?UINT16(1), 0>>,
159    Extensions = ssl_handshake:decode_hello_extensions(<<FourByteUnknown/binary, Renegotiation/binary>>, {3,2}, {3,2}, client),
160    #{renegotiation_info := #renegotiation_info{renegotiated_connection = <<0>>}} = Extensions.
161
162
163encode_single_hello_sni_extension_correctly(_Config) ->
164    SNI = <<16#00, 16#00, 16#00, 16#0d, 16#00, 16#0b, 16#00, 16#00, 16#08,
165	    $t,    $e,    $s,    $t,    $.,    $c,    $o,    $m>>,
166    ExtSize = byte_size(SNI),
167    HelloExt = <<ExtSize:16/unsigned-big-integer, SNI/binary>>,
168    Encoded = ssl_handshake:encode_extensions([#sni{hostname = "test.com"}]),
169    HelloExt = Encoded.
170
171decode_single_hello_sni_extension_correctly(_Config) ->
172    SNI = <<16#00, 16#00, 16#00, 16#0d, 16#00, 16#0b, 16#00, 16#00, 16#08,
173	    $t,    $e,    $s,    $t,    $.,    $c,    $o,    $m>>,
174    Decoded = ssl_handshake:decode_hello_extensions(SNI, {3,3}, {3,3}, client),
175    #{sni := #sni{hostname = "test.com"}} = Decoded.
176
177decode_empty_server_sni_correctly(_Config) ->
178    SNI = <<?UINT16(?SNI_EXT),?UINT16(0)>>,
179    Decoded = ssl_handshake:decode_hello_extensions(SNI, {3,3}, {3,3}, server),
180    #{sni := #sni{hostname = ""}} = Decoded.
181
182
183select_proper_tls_1_2_rsa_default_hashsign(_Config) ->
184    % RFC 5246 section 7.4.1.4.1 tells to use {sha1,rsa} as default signature_algorithm for RSA key exchanges
185    {sha, rsa} = ssl_handshake:select_hashsign_algs(undefined, ?rsaEncryption, {3,3}),
186    % Older versions use MD5/SHA1 combination
187    {md5sha, rsa} = ssl_handshake:select_hashsign_algs(undefined, ?rsaEncryption, {3,2}),
188    {md5sha, rsa} = ssl_handshake:select_hashsign_algs(undefined, ?rsaEncryption, {3,0}).
189
190
191ignore_hassign_extension_pre_tls_1_2(Config) ->
192    Opts = proplists:get_value(server_opts, Config),
193    CertFile = proplists:get_value(certfile, Opts),
194    [{_, Cert, _}] = ssl_test_lib:pem_to_der(CertFile),
195    HashSigns = #hash_sign_algos{hash_sign_algos = [{sha512, rsa}, {sha, dsa}, {sha256, rsa}]},
196    {sha512, rsa} = ssl_handshake:select_hashsign({HashSigns, undefined}, Cert, ecdhe_rsa, tls_v1:default_signature_algs([{3,3}]), {3,3}),
197    %%% Ignore
198    {md5sha, rsa} = ssl_handshake:select_hashsign({HashSigns, undefined}, Cert, ecdhe_rsa, tls_v1:default_signature_algs([{3,2}]), {3,2}),
199    {md5sha, rsa} = ssl_handshake:select_hashsign({HashSigns, undefined}, Cert, ecdhe_rsa, tls_v1:default_signature_algs([{3,0}]), {3,0}).
200
201encode_decode_srp(_Config) ->
202    Exts = #{srp => #srp{username = <<"foo">>},
203             sni => #sni{hostname = "bar"},
204             renegotiation_info => undefined,
205             signature_algs => undefined,
206             alpn => undefined,
207             next_protocol_negotiation => undefined,
208             ec_point_formats => undefined,
209             elliptic_curves => undefined
210            },
211    EncodedExts0 = <<0,20,          % Length
212                    0,12,          % SRP extension
213                    0,4,           % Length
214                    3,             % srp_I length
215                    102,111,111, % username = "foo"
216                    0,0,           % SNI extension
217                    0,8,           % Length
218                    0,6,           % ServerNameLength
219                    0,             % NameType (host_name)
220                    0,3,           % HostNameLength
221                    98,97,114>>,     % hostname = "bar"
222    EncodedExts0 = <<?UINT16(_),EncodedExts/binary>> =
223        ssl_handshake:encode_hello_extensions(Exts, {3,3}),
224    Exts = ssl_handshake:decode_hello_extensions(EncodedExts, {3,3}, {3,3}, client).
225
226signature_algorithms(Config) ->
227    Opts = proplists:get_value(server_opts, Config),
228    CertFile = proplists:get_value(certfile, Opts),
229    io:format("Cert = ~p~n", [CertFile]),
230    [{_, Cert, _}] = ssl_test_lib:pem_to_der(CertFile),
231    HashSigns0 = #hash_sign_algos{
232                   hash_sign_algos = [{sha512, rsa},
233                                      {sha, dsa},
234                                      {sha256, rsa}]},
235    Schemes0 = #signature_algorithms_cert{
236                 signature_scheme_list = [rsa_pkcs1_sha256,
237                                          ecdsa_sha1]},
238    {sha512, rsa} = ssl_handshake:select_hashsign(
239                      {HashSigns0, Schemes0},
240                      Cert, ecdhe_rsa,
241                      tls_v1:default_signature_algs([{3,3}]),
242                      {3,3}),
243    HashSigns1 = #hash_sign_algos{
244                    hash_sign_algos = [{sha, dsa},
245                                       {sha256, rsa}]},
246    {sha256, rsa} = ssl_handshake:select_hashsign(
247                      {HashSigns1, Schemes0},
248                      Cert, ecdhe_rsa,
249                      tls_v1:default_signature_algs([{3,3}]),
250                      {3,3}),
251    Schemes1 = #signature_algorithms_cert{
252                  signature_scheme_list = [rsa_pkcs1_sha1,
253                                           ecdsa_sha1]},
254    %% Signature not supported
255    #alert{} = ssl_handshake:select_hashsign(
256                 {HashSigns1, Schemes1},
257                 Cert, ecdhe_rsa,
258                 tls_v1:default_signature_algs([{3,3}]),
259                 {3,3}),
260    %% No scheme, hashsign is used
261    {sha256, rsa} = ssl_handshake:select_hashsign(
262                      {HashSigns1, undefined},
263                      Cert, ecdhe_rsa,
264                      tls_v1:default_signature_algs([{3,3}]),
265                      {3,3}),
266    HashSigns2 = #hash_sign_algos{
267                    hash_sign_algos = [{sha, dsa}]},
268    %% Signature not supported
269    #alert{} = ssl_handshake:select_hashsign(
270                 {HashSigns2, Schemes1},
271                 Cert, ecdhe_rsa,
272                 tls_v1:default_signature_algs([{3,3}]),
273                 {3,3}).
274
275%%--------------------------------------------------------------------
276%% Internal functions ------------------------------------------------
277%%--------------------------------------------------------------------
278
279is_supported(Hash) ->
280    Algos = crypto:supports(),
281    Hashs = proplists:get_value(hashs, Algos),
282    lists:member(Hash, Hashs).
283
284default_options_map() ->
285    Fun = fun (_Key, {Default, _}) -> Default end,
286    maps:map(Fun, ?RULES).
287