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