1%% 2%% %CopyrightBegin% 3%% 4%% Copyright Ericsson AB 2019-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_renegotiate_SUITE). 24 25-behaviour(ct_suite). 26 27-include_lib("common_test/include/ct.hrl"). 28-include_lib("public_key/include/public_key.hrl"). 29 30%% Common test 31-export([all/0, 32 groups/0, 33 init_per_suite/1, 34 init_per_group/2, 35 init_per_testcase/2, 36 end_per_suite/1, 37 end_per_group/2, 38 end_per_testcase/2 39 ]). 40 41%% Test cases 42-export([client_renegotiate/0, 43 client_renegotiate/1, 44 server_renegotiate/0, 45 server_renegotiate/1, 46 client_secure_renegotiate/0, 47 client_secure_renegotiate/1, 48 client_secure_renegotiate_fallback/0, 49 client_secure_renegotiate_fallback/1, 50 client_renegotiate_reused_session/0, 51 client_renegotiate_reused_session/1, 52 server_renegotiate_reused_session/0, 53 server_renegotiate_reused_session/1, 54 client_no_wrap_sequence_number/0, 55 client_no_wrap_sequence_number/1, 56 server_no_wrap_sequence_number/0, 57 server_no_wrap_sequence_number/1, 58 renegotiate_dos_mitigate_active/0, 59 renegotiate_dos_mitigate_active/1, 60 renegotiate_dos_mitigate_passive/0, 61 renegotiate_dos_mitigate_passive/1, 62 renegotiate_dos_mitigate_absolute/0, 63 renegotiate_dos_mitigate_absolute/1 64 ]). 65 66%% Apply export 67-export([renegotiate/2, 68 renegotiate_reuse_session/2, 69 renegotiate_immediately/1, 70 renegotiate_rejected/1, 71 erlang_ssl_receive/2]). 72 73-define(SLEEP, 500). 74-define(RENEGOTIATION_DISABLE_TIME, 12000). 75 76%%-------------------------------------------------------------------- 77%% Common Test interface functions ----------------------------------- 78%%-------------------------------------------------------------------- 79all() -> 80 [ 81 {group, 'tlsv1.2'}, 82 {group, 'tlsv1.1'}, 83 {group, 'tlsv1'}, 84 {group, 'dtlsv1.2'}, 85 {group, 'dtlsv1'} 86 ]. 87 88groups() -> 89 [{'dtlsv1.2', [], renegotiate_tests()}, 90 {'dtlsv1', [], renegotiate_tests()}, 91 {'tlsv1.3', [], renegotiate_tests()}, 92 {'tlsv1.2', [], renegotiate_tests()}, 93 {'tlsv1.1', [], renegotiate_tests()}, 94 {'tlsv1', [], renegotiate_tests()} 95 ]. 96 97renegotiate_tests() -> 98 [client_renegotiate, 99 server_renegotiate, 100 client_secure_renegotiate, 101 client_secure_renegotiate_fallback, 102 client_renegotiate_reused_session, 103 server_renegotiate_reused_session, 104 client_no_wrap_sequence_number, 105 server_no_wrap_sequence_number, 106 renegotiate_dos_mitigate_active, 107 renegotiate_dos_mitigate_passive, 108 renegotiate_dos_mitigate_absolute]. 109 110ssl3_renegotiate_tests() -> 111 [client_renegotiate, 112 server_renegotiate, 113 client_renegotiate_reused_session, 114 server_renegotiate_reused_session, 115 client_no_wrap_sequence_number, 116 server_no_wrap_sequence_number, 117 renegotiate_dos_mitigate_active, 118 renegotiate_dos_mitigate_passive, 119 renegotiate_dos_mitigate_absolute]. 120 121init_per_suite(Config) -> 122 catch crypto:stop(), 123 try crypto:start() of 124 ok -> 125 ssl_test_lib:clean_start(), 126 ssl_test_lib:make_rsa_cert(Config) 127 catch _:_ -> 128 {skip, "Crypto did not start"} 129 end. 130 131end_per_suite(_Config) -> 132 ssl:stop(), 133 application:stop(crypto). 134 135init_per_group(GroupName, Config) -> 136 ssl_test_lib:init_per_group(GroupName, Config). 137 138end_per_group(GroupName, Config) -> 139 ssl_test_lib:end_per_group(GroupName, Config). 140 141init_per_testcase(TestCase, Config) when TestCase == renegotiate_dos_mitigate_active; 142 TestCase == renegotiate_dos_mitigate_passive; 143 TestCase == renegotiate_dos_mitigate_absolute -> 144 ct:timetrap({seconds, 160}), 145 Config; 146init_per_testcase(_, Config) -> 147 ct:timetrap({seconds, 15}), 148 Config. 149 150end_per_testcase(_, Config) -> 151 Config. 152 153%%-------------------------------------------------------------------- 154%% Test Cases -------------------------------------------------------- 155%%-------------------------------------------------------------------- 156client_renegotiate() -> 157 [{doc,"Test ssl:renegotiate/1 on client."}]. 158client_renegotiate(Config) when is_list(Config) -> 159 ServerOpts = ssl_test_lib:ssl_options(server_rsa_verify_opts, Config), 160 ClientOpts = ssl_test_lib:ssl_options(client_rsa_verify_opts, Config), 161 162 {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), 163 164 Data = "From erlang to erlang", 165 166 Server = 167 ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, 168 {from, self()}, 169 {mfa, {?MODULE, erlang_ssl_receive, [Data]}}, 170 {options, ServerOpts}]), 171 Port = ssl_test_lib:inet_port(Server), 172 173 Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, 174 {host, Hostname}, 175 {from, self()}, 176 {mfa, {?MODULE, 177 renegotiate, [Data]}}, 178 {options, [{reuse_sessions, false} | ClientOpts]}]), 179 180 ssl_test_lib:check_result(Client, ok, Server, ok), 181 ssl_test_lib:close(Server), 182 ssl_test_lib:close(Client). 183 184%%-------------------------------------------------------------------- 185client_secure_renegotiate() -> 186 [{doc,"Test ssl:renegotiate/1 on client."}]. 187client_secure_renegotiate(Config) when is_list(Config) -> 188 ServerOpts = ssl_test_lib:ssl_options(server_rsa_verify_opts, Config), 189 ClientOpts = ssl_test_lib:ssl_options(client_rsa_verify_opts, Config), 190 191 {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), 192 193 Data = "From erlang to erlang", 194 195 Server = 196 ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, 197 {from, self()}, 198 {mfa, {?MODULE, erlang_ssl_receive, [Data]}}, 199 {options, [{secure_renegotiate, true} | ServerOpts]}]), 200 Port = ssl_test_lib:inet_port(Server), 201 202 Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, 203 {host, Hostname}, 204 {from, self()}, 205 {mfa, {?MODULE, 206 renegotiate, [Data]}}, 207 {options, [{reuse_sessions, false}, 208 {secure_renegotiate, true}| ClientOpts]}]), 209 210 ssl_test_lib:check_result(Client, ok, Server, ok), 211 ssl_test_lib:close(Server), 212 ssl_test_lib:close(Client). 213 214%%-------------------------------------------------------------------- 215client_secure_renegotiate_fallback() -> 216 [{doc,"Test that we can set secure_renegotiate to false that is " 217 "fallback option, we however do not have a insecure server to test against!"}]. 218client_secure_renegotiate_fallback(Config) when is_list(Config) -> 219 ServerOpts = ssl_test_lib:ssl_options(server_rsa_verify_opts, Config), 220 ClientOpts = ssl_test_lib:ssl_options(client_rsa_verify_opts, Config), 221 222 {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), 223 224 Data = "From erlang to erlang", 225 226 Server = 227 ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, 228 {from, self()}, 229 {mfa, {?MODULE, erlang_ssl_receive, [Data]}}, 230 {options, [{secure_renegotiate, false} | ServerOpts]}]), 231 Port = ssl_test_lib:inet_port(Server), 232 233 Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, 234 {host, Hostname}, 235 {from, self()}, 236 {mfa, {?MODULE, 237 renegotiate, [Data]}}, 238 {options, [{reuse_sessions, false}, 239 {secure_renegotiate, false}| ClientOpts]}]), 240 241 ssl_test_lib:check_result(Client, ok, Server, ok), 242 ssl_test_lib:close(Server), 243 ssl_test_lib:close(Client). 244 245%%-------------------------------------------------------------------- 246server_renegotiate() -> 247 [{doc,"Test ssl:renegotiate/1 on server."}]. 248server_renegotiate(Config) when is_list(Config) -> 249 ServerOpts = ssl_test_lib:ssl_options(server_rsa_verify_opts, Config), 250 ClientOpts = ssl_test_lib:ssl_options(client_rsa_verify_opts, Config), 251 252 {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), 253 254 Data = "From erlang to erlang", 255 256 Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, 257 {from, self()}, 258 {mfa, {?MODULE, 259 renegotiate, [Data]}}, 260 {options, ServerOpts}]), 261 Port = ssl_test_lib:inet_port(Server), 262 263 Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, 264 {host, Hostname}, 265 {from, self()}, 266 {mfa, {?MODULE, erlang_ssl_receive, [Data]}}, 267 {options, [{reuse_sessions, false} | ClientOpts]}]), 268 269 ssl_test_lib:check_result(Server, ok, Client, ok), 270 ssl_test_lib:close(Server), 271 ssl_test_lib:close(Client). 272 273%%-------------------------------------------------------------------- 274client_renegotiate_reused_session() -> 275 [{doc,"Test ssl:renegotiate/1 on client when the ssl session will be reused."}]. 276client_renegotiate_reused_session(Config) when is_list(Config) -> 277 ServerOpts = ssl_test_lib:ssl_options(server_rsa_verify_opts, Config), 278 ClientOpts = ssl_test_lib:ssl_options(client_rsa_verify_opts, Config), 279 280 {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), 281 282 Data = "From erlang to erlang", 283 284 Server = 285 ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, 286 {from, self()}, 287 {mfa, {?MODULE, erlang_ssl_receive, [Data]}}, 288 {options, ServerOpts}]), 289 Port = ssl_test_lib:inet_port(Server), 290 291 Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, 292 {host, Hostname}, 293 {from, self()}, 294 {mfa, {?MODULE, 295 renegotiate_reuse_session, [Data]}}, 296 {options, [{reuse_sessions, true} | ClientOpts]}]), 297 298 ssl_test_lib:check_result(Client, ok, Server, ok), 299 ssl_test_lib:close(Server), 300 ssl_test_lib:close(Client). 301%%-------------------------------------------------------------------- 302server_renegotiate_reused_session() -> 303 [{doc,"Test ssl:renegotiate/1 on server when the ssl session will be reused."}]. 304server_renegotiate_reused_session(Config) when is_list(Config) -> 305 ServerOpts = ssl_test_lib:ssl_options(server_rsa_verify_opts, Config), 306 ClientOpts = ssl_test_lib:ssl_options(client_rsa_verify_opts, Config), 307 308 {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), 309 310 Data = "From erlang to erlang", 311 312 Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, 313 {from, self()}, 314 {mfa, {?MODULE, 315 renegotiate_reuse_session, [Data]}}, 316 {options, ServerOpts}]), 317 Port = ssl_test_lib:inet_port(Server), 318 319 Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, 320 {host, Hostname}, 321 {from, self()}, 322 {mfa, {?MODULE, erlang_ssl_receive, [Data]}}, 323 {options, [{reuse_sessions, true} | ClientOpts]}]), 324 325 ssl_test_lib:check_result(Server, ok, Client, ok), 326 ssl_test_lib:close(Server), 327 ssl_test_lib:close(Client). 328%%-------------------------------------------------------------------- 329client_no_wrap_sequence_number() -> 330 [{doc,"Test that erlang client will renegotiate session when", 331 "max sequence number celing is about to be reached. Although" 332 "in the testcase we use the test option renegotiate_at" 333 " to lower treashold substantially."}]. 334 335client_no_wrap_sequence_number(Config) when is_list(Config) -> 336 ServerOpts = ssl_test_lib:ssl_options(server_rsa_verify_opts, Config), 337 ClientOpts = ssl_test_lib:ssl_options(client_rsa_verify_opts, Config), 338 339 {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), 340 341 ErlData = "From erlang to erlang", 342 N = 12, 343 344 Server = 345 ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, 346 {from, self()}, 347 {mfa, {ssl_test_lib, no_result, []}}, 348 {options, ServerOpts}]), 349 Port = ssl_test_lib:inet_port(Server), 350 351 Version = ssl_test_lib:protocol_version(Config, tuple), 352 353 Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, 354 {host, Hostname}, 355 {from, self()}, 356 {mfa, {ssl_test_lib, 357 trigger_renegotiate, [[ErlData, treashold(N, Version)]]}}, 358 {options, [{reuse_sessions, false}, 359 {renegotiate_at, N} | ClientOpts]}]), 360 361 ssl_test_lib:check_result(Client, ok), 362 ssl_test_lib:close(Server), 363 ssl_test_lib:close(Client). 364 365%%-------------------------------------------------------------------- 366server_no_wrap_sequence_number() -> 367 [{doc, "Test that erlang server will renegotiate session when", 368 "max sequence number celing is about to be reached. Although" 369 "in the testcase we use the test option renegotiate_at" 370 " to lower treashold substantially."}]. 371 372server_no_wrap_sequence_number(Config) when is_list(Config) -> 373 ServerOpts = ssl_test_lib:ssl_options(server_rsa_verify_opts, Config), 374 ClientOpts = ssl_test_lib:ssl_options(client_rsa_verify_opts, Config), 375 376 {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), 377 378 Data = "From erlang to erlang", 379 N = 12, 380 381 Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, 382 {from, self()}, 383 {mfa, {ssl_test_lib, 384 trigger_renegotiate, [[Data, N+2]]}}, 385 {options, [{renegotiate_at, N} | ServerOpts]}]), 386 Port = ssl_test_lib:inet_port(Server), 387 388 Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, 389 {host, Hostname}, 390 {from, self()}, 391 {mfa, {ssl_test_lib, no_result, []}}, 392 {options, [{reuse_sessions, false} | ClientOpts]}]), 393 394 ssl_test_lib:check_result(Server, ok), 395 ssl_test_lib:close(Server), 396 ssl_test_lib:close(Client). 397renegotiate_dos_mitigate_active() -> 398 [{doc, "Mitigate DOS computational attack by not allowing client to renegotiate many times in a row", 399 "immediately after each other"}]. 400renegotiate_dos_mitigate_active(Config) when is_list(Config) -> 401 ServerOpts = ssl_test_lib:ssl_options(server_rsa_verify_opts, Config), 402 ClientOpts = ssl_test_lib:ssl_options(client_rsa_verify_opts, Config), 403 404 {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), 405 406 Server = 407 ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, 408 {from, self()}, 409 {mfa, {ssl_test_lib, send_recv_result_active, []}}, 410 {options, ServerOpts}]), 411 Port = ssl_test_lib:inet_port(Server), 412 413 Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, 414 {host, Hostname}, 415 {from, self()}, 416 {mfa, {?MODULE, 417 renegotiate_immediately, []}}, 418 {options, ClientOpts}]), 419 420 ssl_test_lib:check_result(Client, ok, Server, ok), 421 ssl_test_lib:close(Server), 422 ssl_test_lib:close(Client). 423 424%%-------------------------------------------------------------------- 425renegotiate_dos_mitigate_passive() -> 426 [{doc, "Mitigate DOS computational attack by not allowing client to renegotiate many times in a row", 427 "immediately after each other"}]. 428renegotiate_dos_mitigate_passive(Config) when is_list(Config) -> 429 ServerOpts = ssl_test_lib:ssl_options(server_rsa_verify_opts, Config), 430 ClientOpts = ssl_test_lib:ssl_options(client_rsa_verify_opts, Config), 431 432 {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), 433 434 Server = 435 ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, 436 {from, self()}, 437 {mfa, {ssl_test_lib, send_recv_result, []}}, 438 {options, [{active, false} | ServerOpts]}]), 439 Port = ssl_test_lib:inet_port(Server), 440 441 Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, 442 {host, Hostname}, 443 {from, self()}, 444 {mfa, {?MODULE, 445 renegotiate_immediately, []}}, 446 {options, ClientOpts}]), 447 448 ssl_test_lib:check_result(Client, ok, Server, ok), 449 ssl_test_lib:close(Server), 450 ssl_test_lib:close(Client). 451 452%%-------------------------------------------------------------------- 453renegotiate_dos_mitigate_absolute() -> 454 [{doc, "Mitigate DOS computational attack by not allowing client to initiate renegotiation"}]. 455renegotiate_dos_mitigate_absolute(Config) when is_list(Config) -> 456 ServerOpts = ssl_test_lib:ssl_options(server_rsa_verify_opts, Config), 457 ClientOpts = ssl_test_lib:ssl_options(client_rsa_verify_opts, Config), 458 459 {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), 460 461 Server = 462 ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, 463 {from, self()}, 464 {mfa, {ssl_test_lib, send_recv_result_active, []}}, 465 {options, [{client_renegotiation, false} | ServerOpts]}]), 466 Port = ssl_test_lib:inet_port(Server), 467 468 Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, 469 {host, Hostname}, 470 {from, self()}, 471 {mfa, {?MODULE, 472 renegotiate_rejected, 473 []}}, 474 {options, ClientOpts}]), 475 476 ssl_test_lib:check_result(Client, ok, Server, ok), 477 ssl_test_lib:close(Server), 478 ssl_test_lib:close(Client). 479 480%%-------------------------------------------------------------------- 481%% Internal functions ------------------------------------------------ 482%%-------------------------------------------------------------------- 483renegotiate(Socket, Data) -> 484 ct:log("Renegotiating ~n", []), 485 Result = ssl:renegotiate(Socket), 486 ct:log("Result ~p~n", [Result]), 487 ssl:send(Socket, Data), 488 case Result of 489 ok -> 490 ok; 491 Other -> 492 Other 493 end. 494 495renegotiate_reuse_session(Socket, Data) -> 496 %% Make sure session is registered 497 ct:sleep(?SLEEP), 498 renegotiate(Socket, Data). 499 500renegotiate_immediately(Socket) -> 501 _ = ssl_test_lib:active_recv(Socket, 11), 502 ok = ssl:renegotiate(Socket), 503 {error, renegotiation_rejected} = ssl:renegotiate(Socket), 504 ct:sleep(?RENEGOTIATION_DISABLE_TIME + ?SLEEP), 505 ok = ssl:renegotiate(Socket), 506 ct:log("Renegotiated again"), 507 ssl:send(Socket, "Hello world"), 508 ok. 509 510renegotiate_rejected(Socket) -> 511 _ = ssl_test_lib:active_recv(Socket, 11), 512 {error, renegotiation_rejected} = ssl:renegotiate(Socket), 513 {error, renegotiation_rejected} = ssl:renegotiate(Socket), 514 ct:sleep(?RENEGOTIATION_DISABLE_TIME +1), 515 {error, renegotiation_rejected} = ssl:renegotiate(Socket), 516 ct:log("Failed to renegotiate again"), 517 ssl:send(Socket, "Hello world"), 518 ok. 519 520%% First two clauses handles 1/n-1 splitting countermeasure Rizzo/Duong-Beast 521treashold(N, {3,0}) -> 522 (N div 2) + 1; 523treashold(N, {3,1}) -> 524 (N div 2) + 1; 525treashold(N, _) -> 526 N + 1. 527 528erlang_ssl_receive(Socket, Data) -> 529 case ssl_test_lib:active_recv(Socket, length(Data)) of 530 Data -> 531 ok; 532 Other -> 533 ct:fail({{expected, Data}, {got, Other}}) 534 end. 535