1%% 2%% %CopyrightBegin% 3%% 4%% Copyright Ericsson AB 2013-2019. 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: Common handling of a TLS/SSL/DTLS connection, see also 24%% tls_connection.erl and dtls_connection.erl 25%%---------------------------------------------------------------------- 26 27-module(ssl_connection). 28 29-include("ssl_api.hrl"). 30-include("ssl_connection.hrl"). 31-include("ssl_handshake.hrl"). 32-include("ssl_alert.hrl"). 33-include("ssl_record.hrl"). 34-include("ssl_cipher.hrl"). 35-include("ssl_internal.hrl"). 36-include("ssl_srp.hrl"). 37-include_lib("public_key/include/public_key.hrl"). 38 39%% Setup 40 41-export([connect/8, handshake/7, handshake/2, handshake/3, 42 handshake_continue/3, handshake_cancel/1, 43 socket_control/4, socket_control/5]). 44 45%% User Events 46-export([send/2, recv/3, close/2, shutdown/2, 47 new_user/2, get_opts/2, set_opts/2, 48 peer_certificate/1, renegotiation/1, negotiated_protocol/1, prf/5, 49 connection_information/2 50 ]). 51 52%% Alert and close handling 53-export([handle_own_alert/4, handle_alert/3, 54 handle_normal_shutdown/3, 55 handle_trusted_certs_db/1]). 56 57%% Data handling 58-export([read_application_data/2, internal_renegotiation/2]). 59 60%% Help functions for tls|dtls_connection.erl 61-export([handle_session/7, ssl_config/3, 62 prepare_connection/2, hibernate_after/3, map_extensions/1]). 63 64%% General gen_statem state functions with extra callback argument 65%% to determine if it is an SSL/TLS or DTLS gen_statem machine 66-export([init/4, error/4, hello/4, user_hello/4, abbreviated/4, certify/4, cipher/4, 67 connection/4, downgrade/4]). 68 69%% gen_statem callbacks 70-export([terminate/3, format_status/2]). 71 72%% Erlang Distribution export 73-export([dist_handshake_complete/2]). 74 75%%==================================================================== 76%% Setup 77%%==================================================================== 78%%-------------------------------------------------------------------- 79-spec connect(tls_connection | dtls_connection, 80 ssl:host(), inet:port_number(), 81 port() | {tuple(), port()}, %% TLS | DTLS 82 {#ssl_options{}, #socket_options{}, 83 %% Tracker only needed on server side 84 undefined}, 85 pid(), tuple(), timeout()) -> 86 {ok, #sslsocket{}} | {error, reason()}. 87%% 88%% Description: Connect to an ssl server. 89%%-------------------------------------------------------------------- 90connect(Connection, Host, Port, Socket, Options, User, CbInfo, Timeout) -> 91 try Connection:start_fsm(client, Host, Port, Socket, Options, User, CbInfo, 92 Timeout) 93 catch 94 exit:{noproc, _} -> 95 {error, ssl_not_started} 96 end. 97%%-------------------------------------------------------------------- 98-spec handshake(tls_connection | dtls_connection, 99 inet:port_number(), port(), 100 {#ssl_options{}, #socket_options{}, undefined | pid()}, 101 pid(), tuple(), timeout()) -> 102 {ok, #sslsocket{}} | {error, reason()}. 103%% 104%% Description: Performs accept on an ssl listen socket. e.i. performs 105%% ssl handshake. 106%%-------------------------------------------------------------------- 107handshake(Connection, Port, Socket, Opts, User, CbInfo, Timeout) -> 108 try Connection:start_fsm(server, "localhost", Port, Socket, Opts, User, 109 CbInfo, Timeout) 110 catch 111 exit:{noproc, _} -> 112 {error, ssl_not_started} 113 end. 114 115%%-------------------------------------------------------------------- 116-spec handshake(#sslsocket{}, timeout()) -> {ok, #sslsocket{}} | 117 {ok, #sslsocket{}, map()}| {error, reason()}. 118%% 119%% Description: Starts ssl handshake. 120%%-------------------------------------------------------------------- 121handshake(#sslsocket{pid = [Pid|_]} = Socket, Timeout) -> 122 case call(Pid, {start, Timeout}) of 123 connected -> 124 {ok, Socket}; 125 {ok, Ext} -> 126 {ok, Socket, Ext}; 127 Error -> 128 Error 129 end. 130 131%%-------------------------------------------------------------------- 132-spec handshake(#sslsocket{}, {#ssl_options{},#socket_options{}}, timeout()) -> 133 {ok, #sslsocket{}} | {ok, #sslsocket{}, map()} | {error, reason()}. 134%% 135%% Description: Starts ssl handshake with some new options 136%%-------------------------------------------------------------------- 137handshake(#sslsocket{pid = [Pid|_]} = Socket, SslOptions, Timeout) -> 138 case call(Pid, {start, SslOptions, Timeout}) of 139 connected -> 140 {ok, Socket}; 141 Error -> 142 Error 143 end. 144 145%%-------------------------------------------------------------------- 146-spec handshake_continue(#sslsocket{}, [ssl:tls_server_option()], 147 timeout()) -> {ok, #sslsocket{}}| {error, reason()}. 148%% 149%% Description: Continues handshake with new options 150%%-------------------------------------------------------------------- 151handshake_continue(#sslsocket{pid = [Pid|_]} = Socket, SslOptions, Timeout) -> 152 case call(Pid, {handshake_continue, SslOptions, Timeout}) of 153 connected -> 154 {ok, Socket}; 155 Error -> 156 Error 157 end. 158%%-------------------------------------------------------------------- 159-spec handshake_cancel(#sslsocket{}) -> ok | {error, reason()}. 160%% 161%% Description: Cancels connection 162%%-------------------------------------------------------------------- 163handshake_cancel(#sslsocket{pid = [Pid|_]}) -> 164 case call(Pid, cancel) of 165 closed -> 166 ok; 167 Error -> 168 Error 169 end. 170%-------------------------------------------------------------------- 171-spec socket_control(tls_connection | dtls_connection, port(), [pid()], atom()) -> 172 {ok, #sslsocket{}} | {error, reason()}. 173%% 174%% Description: Set the ssl process to own the accept socket 175%%-------------------------------------------------------------------- 176socket_control(Connection, Socket, Pid, Transport) -> 177 socket_control(Connection, Socket, Pid, Transport, undefined). 178 179%-------------------------------------------------------------------- 180-spec socket_control(tls_connection | dtls_connection, port(), [pid()], atom(), pid()| atom()) -> 181 {ok, #sslsocket{}} | {error, reason()}. 182%%-------------------------------------------------------------------- 183socket_control(Connection, Socket, Pids, Transport, udp_listener) -> 184 %% dtls listener process must have the socket control 185 {ok, Connection:socket(Pids, Transport, Socket, undefined)}; 186 187socket_control(tls_connection = Connection, Socket, [Pid|_] = Pids, Transport, ListenTracker) -> 188 case Transport:controlling_process(Socket, Pid) of 189 ok -> 190 {ok, Connection:socket(Pids, Transport, Socket, ListenTracker)}; 191 {error, Reason} -> 192 {error, Reason} 193 end; 194socket_control(dtls_connection = Connection, {_, Socket}, [Pid|_] = Pids, Transport, ListenTracker) -> 195 case Transport:controlling_process(Socket, Pid) of 196 ok -> 197 {ok, Connection:socket(Pids, Transport, Socket, ListenTracker)}; 198 {error, Reason} -> 199 {error, Reason} 200 end. 201 202 203%%==================================================================== 204%% User events 205%%==================================================================== 206 207%%-------------------------------------------------------------------- 208-spec send(pid(), iodata()) -> ok | {error, reason()}. 209%% 210%% Description: Sends data over the ssl connection 211%%-------------------------------------------------------------------- 212send(Pid, Data) -> 213 call(Pid, {application_data, 214 %% iolist_to_iovec should really 215 %% be called iodata_to_iovec() 216 erlang:iolist_to_iovec(Data)}). 217 218%%-------------------------------------------------------------------- 219-spec recv(pid(), integer(), timeout()) -> 220 {ok, binary() | list()} | {error, reason()}. 221%% 222%% Description: Receives data when active = false 223%%-------------------------------------------------------------------- 224recv(Pid, Length, Timeout) -> 225 call(Pid, {recv, Length, Timeout}). 226 227%%-------------------------------------------------------------------- 228-spec connection_information(pid(), boolean()) -> {ok, list()} | {error, reason()}. 229%% 230%% Description: Get the SNI hostname 231%%-------------------------------------------------------------------- 232connection_information(Pid, IncludeSecrityInfo) when is_pid(Pid) -> 233 call(Pid, {connection_information, IncludeSecrityInfo}). 234 235%%-------------------------------------------------------------------- 236-spec close(pid(), {close, Timeout::integer() | 237 {NewController::pid(), Timeout::integer()}}) -> 238 ok | {ok, port()} | {error, reason()}. 239%% 240%% Description: Close an ssl connection 241%%-------------------------------------------------------------------- 242close(ConnectionPid, How) -> 243 case call(ConnectionPid, How) of 244 {error, closed} -> 245 ok; 246 Other -> 247 Other 248 end. 249%%-------------------------------------------------------------------- 250-spec shutdown(pid(), atom()) -> ok | {error, reason()}. 251%% 252%% Description: Same as gen_tcp:shutdown/2 253%%-------------------------------------------------------------------- 254shutdown(ConnectionPid, How) -> 255 call(ConnectionPid, {shutdown, How}). 256 257%%-------------------------------------------------------------------- 258-spec new_user(pid(), pid()) -> ok | {error, reason()}. 259%% 260%% Description: Changes process that receives the messages when active = true 261%% or once. 262%%-------------------------------------------------------------------- 263new_user(ConnectionPid, User) -> 264 call(ConnectionPid, {new_user, User}). 265 266%%-------------------------------------------------------------------- 267-spec negotiated_protocol(pid()) -> {ok, binary()} | {error, reason()}. 268%% 269%% Description: Returns the negotiated protocol 270%%-------------------------------------------------------------------- 271negotiated_protocol(ConnectionPid) -> 272 call(ConnectionPid, negotiated_protocol). 273 274%%-------------------------------------------------------------------- 275-spec get_opts(pid(), list()) -> {ok, list()} | {error, reason()}. 276%% 277%% Description: Same as inet:getopts/2 278%%-------------------------------------------------------------------- 279get_opts(ConnectionPid, OptTags) -> 280 call(ConnectionPid, {get_opts, OptTags}). 281%%-------------------------------------------------------------------- 282-spec set_opts(pid(), list()) -> ok | {error, reason()}. 283%% 284%% Description: Same as inet:setopts/2 285%%-------------------------------------------------------------------- 286set_opts(ConnectionPid, Options) -> 287 call(ConnectionPid, {set_opts, Options}). 288 289%%-------------------------------------------------------------------- 290-spec peer_certificate(pid()) -> {ok, binary()| undefined} | {error, reason()}. 291%% 292%% Description: Returns the peer cert 293%%-------------------------------------------------------------------- 294peer_certificate(ConnectionPid) -> 295 call(ConnectionPid, peer_certificate). 296 297%%-------------------------------------------------------------------- 298-spec renegotiation(pid()) -> ok | {error, reason()}. 299%% 300%% Description: Starts a renegotiation of the ssl session. 301%%-------------------------------------------------------------------- 302renegotiation(ConnectionPid) -> 303 call(ConnectionPid, renegotiate). 304 305%%-------------------------------------------------------------------- 306-spec internal_renegotiation(pid(), ssl_record:connection_states()) -> 307 ok. 308%% 309%% Description: Starts a renegotiation of the ssl session. 310%%-------------------------------------------------------------------- 311internal_renegotiation(ConnectionPid, #{current_write := WriteState}) -> 312 gen_statem:cast(ConnectionPid, {internal_renegotiate, WriteState}). 313 314dist_handshake_complete(ConnectionPid, DHandle) -> 315 gen_statem:cast(ConnectionPid, {dist_handshake_complete, DHandle}). 316 317%%-------------------------------------------------------------------- 318-spec prf(pid(), binary() | 'master_secret', binary(), 319 [binary() | ssl:prf_random()], non_neg_integer()) -> 320 {ok, binary()} | {error, reason()} | {'EXIT', term()}. 321%% 322%% Description: use a ssl sessions TLS PRF to generate key material 323%%-------------------------------------------------------------------- 324prf(ConnectionPid, Secret, Label, Seed, WantedLength) -> 325 call(ConnectionPid, {prf, Secret, Label, Seed, WantedLength}). 326 327%%==================================================================== 328%% Alert and close handling 329%%==================================================================== 330handle_own_alert(Alert0, _, StateName, 331 #state{static_env = #static_env{role = Role, 332 protocol_cb = Connection}, 333 ssl_options = SslOpts} = State) -> 334 try %% Try to tell the other side 335 send_alert(Alert0, StateName, State) 336 catch _:_ -> %% Can crash if we are in a uninitialized state 337 ignore 338 end, 339 try %% Try to tell the local user 340 Alert = Alert0#alert{role = Role}, 341 log_alert(SslOpts#ssl_options.log_alert, Role, Connection:protocol_name(), StateName, Alert), 342 handle_normal_shutdown(Alert,StateName, State) 343 catch _:_ -> 344 ok 345 end, 346 {stop, {shutdown, own_alert}, State}. 347 348handle_normal_shutdown(Alert, StateName, #state{static_env = #static_env{role = Role, 349 socket = Socket, 350 transport_cb = Transport, 351 protocol_cb = Connection, 352 tracker = Tracker}, 353 handshake_env = #handshake_env{renegotiation = {false, first}}, 354 start_or_recv_from = StartFrom} = State) -> 355 Pids = Connection:pids(State), 356 alert_user(Pids, Transport, Tracker,Socket, StartFrom, Alert, Role, StateName, Connection); 357 358handle_normal_shutdown(Alert, StateName, #state{static_env = #static_env{role = Role, 359 socket = Socket, 360 transport_cb = Transport, 361 protocol_cb = Connection, 362 tracker = Tracker}, 363 connection_env = #connection_env{user_application = {_Mon, Pid}}, 364 socket_options = Opts, 365 start_or_recv_from = RecvFrom} = State) -> 366 Pids = Connection:pids(State), 367 alert_user(Pids, Transport, Tracker, Socket, StateName, Opts, Pid, RecvFrom, Alert, Role, StateName, Connection). 368 369handle_alert(#alert{level = ?FATAL} = Alert0, StateName, 370 #state{static_env = #static_env{role = Role, 371 socket = Socket, 372 host = Host, 373 port = Port, 374 tracker = Tracker, 375 transport_cb = Transport, 376 protocol_cb = Connection}, 377 connection_env = #connection_env{user_application = {_Mon, Pid}}, 378 ssl_options = SslOpts, 379 start_or_recv_from = From, 380 session = Session, 381 socket_options = Opts} = State) -> 382 invalidate_session(Role, Host, Port, Session), 383 Alert = Alert0#alert{role = opposite_role(Role)}, 384 log_alert(SslOpts#ssl_options.log_alert, Role, Connection:protocol_name(), 385 StateName, Alert), 386 Pids = Connection:pids(State), 387 alert_user(Pids, Transport, Tracker, Socket, StateName, Opts, Pid, From, Alert, Role, StateName, Connection), 388 {stop, {shutdown, normal}, State}; 389 390handle_alert(#alert{level = ?WARNING, description = ?CLOSE_NOTIFY} = Alert, 391 downgrade= StateName, State) -> 392 {next_state, StateName, State, [{next_event, internal, Alert}]}; 393handle_alert(#alert{level = ?WARNING, description = ?CLOSE_NOTIFY} = Alert, 394 StateName, State) -> 395 handle_normal_shutdown(Alert, StateName, State), 396 {stop,{shutdown, peer_close}, State}; 397handle_alert(#alert{level = ?WARNING, description = ?NO_RENEGOTIATION} = Alert0, StateName, 398 #state{static_env = #static_env{role = Role, 399 protocol_cb = Connection}, 400 handshake_env = #handshake_env{renegotiation = {true, internal}}, 401 ssl_options = SslOpts} = State) -> 402 Alert = Alert0#alert{role = opposite_role(Role)}, 403 log_alert(SslOpts#ssl_options.log_alert, Role, 404 Connection:protocol_name(), StateName, Alert), 405 handle_normal_shutdown(Alert, StateName, State), 406 {stop,{shutdown, peer_close}, State}; 407 408handle_alert(#alert{level = ?WARNING, description = ?NO_RENEGOTIATION} = Alert, connection = StateName, 409 #state{static_env = #static_env{role = Role, 410 protocol_cb = Connection}, 411 handshake_env = #handshake_env{renegotiation = {true, From}} = HsEnv, 412 ssl_options = SslOpts 413 } = State0) -> 414 log_alert(SslOpts#ssl_options.log_alert, Role, 415 Connection:protocol_name(), StateName, Alert#alert{role = opposite_role(Role)}), 416 gen_statem:reply(From, {error, renegotiation_rejected}), 417 State = Connection:reinit_handshake_data(State0), 418 Connection:next_event(connection, no_record, State#state{handshake_env = HsEnv#handshake_env{renegotiation = undefined}}); 419 420handle_alert(#alert{level = ?WARNING, description = ?NO_RENEGOTIATION} = Alert, StateName, 421 #state{static_env = #static_env{role = Role, 422 protocol_cb = Connection}, 423 handshake_env = #handshake_env{renegotiation = {true, From}} = HsEnv, 424 ssl_options = SslOpts 425 } = State0) -> 426 log_alert(SslOpts#ssl_options.log_alert, Role, 427 Connection:protocol_name(), StateName, Alert#alert{role = opposite_role(Role)}), 428 gen_statem:reply(From, {error, renegotiation_rejected}), 429 %% Go back to connection! 430 State = Connection:reinit(State0#state{handshake_env = HsEnv#handshake_env{renegotiation = undefined}}), 431 Connection:next_event(connection, no_record, State); 432 433%% Gracefully log and ignore all other warning alerts 434handle_alert(#alert{level = ?WARNING} = Alert, StateName, 435 #state{static_env = #static_env{role = Role, 436 protocol_cb = Connection}, 437 ssl_options = SslOpts} = State) -> 438 log_alert(SslOpts#ssl_options.log_alert, Role, 439 Connection:protocol_name(), StateName, Alert#alert{role = opposite_role(Role)}), 440 Connection:next_event(StateName, no_record, State). 441 442%%==================================================================== 443%% Data handling 444%%==================================================================== 445passive_receive(State0 = #state{user_data_buffer = {_,BufferSize,_}}, StateName, Connection, StartTimerAction) -> 446 case BufferSize of 447 0 -> 448 Connection:next_event(StateName, no_record, State0, StartTimerAction); 449 _ -> 450 case read_application_data(<<>>, State0) of 451 {stop, _, _} = ShutdownError -> 452 ShutdownError; 453 {Record, State} -> 454 case State#state.start_or_recv_from of 455 undefined -> 456 %% Cancel recv timeout as data has been delivered 457 Connection:next_event(StateName, Record, State, 458 [{{timeout, recv}, infinity, timeout}]); 459 _ -> 460 Connection:next_event(StateName, Record, State, StartTimerAction) 461 end 462 end 463 end. 464 465read_application_data( 466 Data, 467 #state{ 468 user_data_buffer = {Front0,BufferSize0,Rear0}, 469 connection_env = #connection_env{erl_dist_handle = DHandle}} = State) -> 470 %% 471 Front = Front0, 472 BufferSize = BufferSize0 + byte_size(Data), 473 Rear = [Data|Rear0], 474 case DHandle of 475 undefined -> 476 read_application_data(State, Front, BufferSize, Rear); 477 _ -> 478 try read_application_dist_data(DHandle, Front, BufferSize, Rear) of 479 Buffer -> 480 {no_record, State#state{user_data_buffer = Buffer}} 481 catch error:_ -> 482 {stop,disconnect, 483 State#state{user_data_buffer = {Front,BufferSize,Rear}}} 484 end 485 end. 486 487 488read_application_data(#state{ 489 socket_options = SocketOpts, 490 bytes_to_read = BytesToRead, 491 start_or_recv_from = RecvFrom} = State, Front, BufferSize, Rear) -> 492 read_application_data(State, Front, BufferSize, Rear, SocketOpts, RecvFrom, BytesToRead). 493 494%% Pick binary from queue front, if empty wait for more data 495read_application_data(State, [Bin|Front], BufferSize, Rear, SocketOpts, RecvFrom, BytesToRead) -> 496 read_application_data_bin(State, Front, BufferSize, Rear, SocketOpts, RecvFrom, BytesToRead, Bin); 497read_application_data(State, [] = Front, BufferSize, [] = Rear, SocketOpts, RecvFrom, BytesToRead) -> 498 0 = BufferSize, % Assert 499 {no_record, State#state{socket_options = SocketOpts, 500 bytes_to_read = BytesToRead, 501 start_or_recv_from = RecvFrom, 502 user_data_buffer = {Front,BufferSize,Rear}}}; 503read_application_data(State, [], BufferSize, Rear, SocketOpts, RecvFrom, BytesToRead) -> 504 [Bin|Front] = lists:reverse(Rear), 505 read_application_data_bin(State, Front, BufferSize, [], SocketOpts, RecvFrom, BytesToRead, Bin). 506 507read_application_data_bin(State, Front, BufferSize, Rear, SocketOpts, RecvFrom, BytesToRead, <<>>) -> 508 %% Done with this binary - get next 509 read_application_data(State, Front, BufferSize, Rear, SocketOpts, RecvFrom, BytesToRead); 510read_application_data_bin(State, Front0, BufferSize0, Rear0, SocketOpts0, RecvFrom, BytesToRead, Bin0) -> 511 %% Decode one packet from a binary 512 case get_data(SocketOpts0, BytesToRead, Bin0) of 513 {ok, Data, Bin} -> % Send data 514 BufferSize = BufferSize0 - (byte_size(Bin0) - byte_size(Bin)), 515 read_application_data_deliver( 516 State, [Bin|Front0], BufferSize, Rear0, SocketOpts0, RecvFrom, Data); 517 {more, undefined} -> 518 %% We need more data, do not know how much 519 if 520 byte_size(Bin0) < BufferSize0 -> 521 %% We have more data in the buffer besides the first binary - concatenate all and retry 522 Bin = iolist_to_binary([Bin0,Front0|lists:reverse(Rear0)]), 523 read_application_data_bin( 524 State, [], BufferSize0, [], SocketOpts0, RecvFrom, BytesToRead, Bin); 525 true -> 526 %% All data is in the first binary, no use to retry - wait for more 527 {no_record, State#state{socket_options = SocketOpts0, 528 bytes_to_read = BytesToRead, 529 start_or_recv_from = RecvFrom, 530 user_data_buffer = {[Bin0|Front0],BufferSize0,Rear0}}} 531 end; 532 {more, Size} when Size =< BufferSize0 -> 533 %% We have a packet in the buffer - collect it in a binary and decode 534 {Data,Front,Rear} = iovec_from_front(Size - byte_size(Bin0), Front0, Rear0, [Bin0]), 535 Bin = iolist_to_binary(Data), 536 read_application_data_bin( 537 State, Front, BufferSize0, Rear, SocketOpts0, RecvFrom, BytesToRead, Bin); 538 {more, _Size} -> 539 %% We do not have a packet in the buffer - wait for more 540 {no_record, State#state{socket_options = SocketOpts0, 541 bytes_to_read = BytesToRead, 542 start_or_recv_from = RecvFrom, 543 user_data_buffer = {[Bin0|Front0],BufferSize0,Rear0}}}; 544 passive -> 545 {no_record, State#state{socket_options = SocketOpts0, 546 bytes_to_read = BytesToRead, 547 start_or_recv_from = RecvFrom, 548 user_data_buffer = {[Bin0|Front0],BufferSize0,Rear0}}}; 549 {error,_Reason} -> 550 %% Invalid packet in packet mode 551 #state{ 552 static_env = 553 #static_env{ 554 socket = Socket, 555 protocol_cb = Connection, 556 transport_cb = Transport, 557 tracker = Tracker}, 558 connection_env = 559 #connection_env{user_application = {_Mon, Pid}}} = State, 560 Buffer = iolist_to_binary([Bin0,Front0|lists:reverse(Rear0)]), 561 deliver_packet_error( 562 Connection:pids(State), Transport, Socket, SocketOpts0, 563 Buffer, Pid, RecvFrom, Tracker, Connection), 564 {stop, {shutdown, normal}, State#state{socket_options = SocketOpts0, 565 bytes_to_read = BytesToRead, 566 start_or_recv_from = RecvFrom, 567 user_data_buffer = {[Buffer],BufferSize0,[]}}} 568 end. 569 570read_application_data_deliver(State, Front, BufferSize, Rear, SocketOpts0, RecvFrom, Data) -> 571 #state{ 572 static_env = 573 #static_env{ 574 socket = Socket, 575 protocol_cb = Connection, 576 transport_cb = Transport, 577 tracker = Tracker}, 578 connection_env = 579 #connection_env{user_application = {_Mon, Pid}}} = State, 580 SocketOpts = 581 deliver_app_data( 582 Connection:pids(State), Transport, Socket, SocketOpts0, Data, Pid, RecvFrom, Tracker, Connection), 583 if 584 SocketOpts#socket_options.active =:= false -> 585 %% Passive mode, wait for active once or recv 586 {no_record, 587 State#state{ 588 user_data_buffer = {Front,BufferSize,Rear}, 589 start_or_recv_from = undefined, 590 bytes_to_read = undefined, 591 socket_options = SocketOpts 592 }}; 593 true -> %% Try to deliver more data 594 read_application_data(State, Front, BufferSize, Rear, SocketOpts, undefined, undefined) 595 end. 596 597 598read_application_dist_data(DHandle, [Bin|Front], BufferSize, Rear) -> 599 read_application_dist_data(DHandle, Front, BufferSize, Rear, Bin); 600read_application_dist_data(_DHandle, [] = Front, BufferSize, [] = Rear) -> 601 BufferSize = 0, 602 {Front,BufferSize,Rear}; 603read_application_dist_data(DHandle, [], BufferSize, Rear) -> 604 [Bin|Front] = lists:reverse(Rear), 605 read_application_dist_data(DHandle, Front, BufferSize, [], Bin). 606%% 607read_application_dist_data(DHandle, Front0, BufferSize, Rear0, Bin0) -> 608 case Bin0 of 609 %% 610 %% START Optimization 611 %% It is cheaper to match out several packets in one match operation than to loop for each 612 <<SizeA:32, DataA:SizeA/binary, 613 SizeB:32, DataB:SizeB/binary, 614 SizeC:32, DataC:SizeC/binary, 615 SizeD:32, DataD:SizeD/binary, Rest/binary>> 616 when 0 < SizeA, 0 < SizeB, 0 < SizeC, 0 < SizeD -> 617 %% We have 4 complete packets in the first binary 618 erlang:dist_ctrl_put_data(DHandle, DataA), 619 erlang:dist_ctrl_put_data(DHandle, DataB), 620 erlang:dist_ctrl_put_data(DHandle, DataC), 621 erlang:dist_ctrl_put_data(DHandle, DataD), 622 read_application_dist_data( 623 DHandle, Front0, BufferSize - (4*4+SizeA+SizeB+SizeC+SizeD), Rear0, Rest); 624 <<SizeA:32, DataA:SizeA/binary, 625 SizeB:32, DataB:SizeB/binary, 626 SizeC:32, DataC:SizeC/binary, Rest/binary>> 627 when 0 < SizeA, 0 < SizeB, 0 < SizeC -> 628 %% We have 3 complete packets in the first binary 629 erlang:dist_ctrl_put_data(DHandle, DataA), 630 erlang:dist_ctrl_put_data(DHandle, DataB), 631 erlang:dist_ctrl_put_data(DHandle, DataC), 632 read_application_dist_data( 633 DHandle, Front0, BufferSize - (3*4+SizeA+SizeB+SizeC), Rear0, Rest); 634 <<SizeA:32, DataA:SizeA/binary, 635 SizeB:32, DataB:SizeB/binary, Rest/binary>> 636 when 0 < SizeA, 0 < SizeB -> 637 %% We have 2 complete packets in the first binary 638 erlang:dist_ctrl_put_data(DHandle, DataA), 639 erlang:dist_ctrl_put_data(DHandle, DataB), 640 read_application_dist_data( 641 DHandle, Front0, BufferSize - (2*4+SizeA+SizeB), Rear0, Rest); 642 %% END Optimization 643 %% 644 %% Basic one packet code path 645 <<Size:32, Data:Size/binary, Rest/binary>> -> 646 %% We have a complete packet in the first binary 647 0 < Size andalso erlang:dist_ctrl_put_data(DHandle, Data), 648 read_application_dist_data(DHandle, Front0, BufferSize - (4+Size), Rear0, Rest); 649 <<Size:32, FirstData/binary>> when 4+Size =< BufferSize -> 650 %% We have a complete packet in the buffer 651 %% - fetch the missing content from the buffer front 652 {Data,Front,Rear} = iovec_from_front(Size - byte_size(FirstData), Front0, Rear0, [FirstData]), 653 0 < Size andalso erlang:dist_ctrl_put_data(DHandle, Data), 654 read_application_dist_data(DHandle, Front, BufferSize - (4+Size), Rear); 655 <<Bin/binary>> -> 656 %% In OTP-21 the match context reuse optimization fails if we use Bin0 in recursion, so here we 657 %% match out the whole binary which will trick the optimization into keeping the match context 658 %% for the first binary contains complete packet code above 659 case Bin of 660 <<_Size:32, _InsufficientData/binary>> -> 661 %% We have a length field in the first binary but there is not enough data 662 %% in the buffer to form a complete packet - await more data 663 {[Bin|Front0],BufferSize,Rear0}; 664 <<IncompleteLengthField/binary>> when 4 < BufferSize -> 665 %% We do not have a length field in the first binary but the buffer 666 %% contains enough data to maybe form a packet 667 %% - fetch a tiny binary from the buffer front to complete the length field 668 {LengthField,Front,Rear} = 669 case IncompleteLengthField of 670 <<>> -> 671 iovec_from_front(4, Front0, Rear0, []); 672 _ -> 673 iovec_from_front( 674 4 - byte_size(IncompleteLengthField), Front0, Rear0, [IncompleteLengthField]) 675 end, 676 LengthBin = iolist_to_binary(LengthField), 677 read_application_dist_data(DHandle, Front, BufferSize, Rear, LengthBin); 678 <<IncompleteLengthField/binary>> -> 679 %% We do not have enough data in the buffer to even form a length field - await more data 680 case IncompleteLengthField of 681 <<>> -> 682 {Front0,BufferSize,Rear0}; 683 _ -> 684 {[IncompleteLengthField|Front0],BufferSize,Rear0} 685 end 686 end 687 end. 688 689iovec_from_front(0, Front, Rear, Acc) -> 690 {lists:reverse(Acc),Front,Rear}; 691iovec_from_front(Size, [], Rear, Acc) -> 692 case Rear of 693 %% Avoid lists:reverse/1 for simple cases. 694 %% Case clause for [] to avoid infinite loop. 695 [_] -> 696 iovec_from_front(Size, Rear, [], Acc); 697 [Bin2,Bin1] -> 698 iovec_from_front(Size, [Bin1,Bin2], [], Acc); 699 [Bin3,Bin2,Bin1] -> 700 iovec_from_front(Size, [Bin1,Bin2,Bin3], [], Acc); 701 [_,_,_|_] = Rear -> 702 iovec_from_front(Size, lists:reverse(Rear), [], Acc) 703 end; 704iovec_from_front(Size, [Bin|Front], Rear, []) -> 705 case Bin of 706 <<Last:Size/binary>> -> % Just enough 707 {[Last],Front,Rear}; 708 <<Last:Size/binary, Rest/binary>> -> % More than enough, split here 709 {[Last],[Rest|Front],Rear}; 710 <<>> -> % Not enough, skip empty binaries 711 iovec_from_front(Size, Front, Rear, []); 712 <<_/binary>> -> % Not enough 713 BinSize = byte_size(Bin), 714 iovec_from_front(Size - BinSize, Front, Rear, [Bin]) 715 end; 716iovec_from_front(Size, [Bin|Front], Rear, Acc) -> 717 case Bin of 718 <<Last:Size/binary>> -> % Just enough 719 {lists:reverse(Acc, [Last]),Front,Rear}; 720 <<Last:Size/binary, Rest/binary>> -> % More than enough, split here 721 {lists:reverse(Acc, [Last]),[Rest|Front],Rear}; 722 <<>> -> % Not enough, skip empty binaries 723 iovec_from_front(Size, Front, Rear, Acc); 724 <<_/binary>> -> % Not enough 725 BinSize = byte_size(Bin), 726 iovec_from_front(Size - BinSize, Front, Rear, [Bin|Acc]) 727 end. 728 729 730%%==================================================================== 731%% Help functions for tls|dtls_connection.erl 732%%==================================================================== 733%%-------------------------------------------------------------------- 734-spec handle_session(#server_hello{}, ssl_record:ssl_version(), 735 binary(), ssl_record:connection_states(), _,_, #state{}) -> 736 gen_statem:state_function_result(). 737%%-------------------------------------------------------------------- 738handle_session(#server_hello{cipher_suite = CipherSuite, 739 compression_method = Compression}, 740 Version, NewId, ConnectionStates, ProtoExt, Protocol0, 741 #state{session = #session{session_id = OldId}, 742 handshake_env = #handshake_env{negotiated_protocol = CurrentProtocol} = HsEnv, 743 connection_env = #connection_env{negotiated_version = ReqVersion} = CEnv} = State0) -> 744 #{key_exchange := KeyAlgorithm} = 745 ssl_cipher_format:suite_definition(CipherSuite), 746 747 PremasterSecret = make_premaster_secret(ReqVersion, KeyAlgorithm), 748 749 {ExpectNPN, Protocol} = case Protocol0 of 750 undefined -> 751 {false, CurrentProtocol}; 752 _ -> 753 {ProtoExt =:= npn, Protocol0} 754 end, 755 756 State = State0#state{connection_states = ConnectionStates, 757 handshake_env = HsEnv#handshake_env{kex_algorithm = KeyAlgorithm, 758 premaster_secret = PremasterSecret, 759 expecting_next_protocol_negotiation = ExpectNPN, 760 negotiated_protocol = Protocol}, 761 connection_env = CEnv#connection_env{negotiated_version = Version}}, 762 763 case ssl_session:is_new(OldId, NewId) of 764 true -> 765 handle_new_session(NewId, CipherSuite, Compression, 766 State#state{connection_states = ConnectionStates}); 767 false -> 768 handle_resumed_session(NewId, 769 State#state{connection_states = ConnectionStates}) 770 end. 771 772%%-------------------------------------------------------------------- 773-spec ssl_config(#ssl_options{}, client | server, #state{}) -> #state{}. 774%%-------------------------------------------------------------------- 775ssl_config(Opts, Role, #state{static_env = InitStatEnv0, 776 handshake_env = HsEnv, 777 connection_env = CEnv} = State0) -> 778 {ok, #{cert_db_ref := Ref, 779 cert_db_handle := CertDbHandle, 780 fileref_db_handle := FileRefHandle, 781 session_cache := CacheHandle, 782 crl_db_info := CRLDbHandle, 783 private_key := Key, 784 dh_params := DHParams, 785 own_certificate := OwnCert}} = 786 ssl_config:init(Opts, Role), 787 TimeStamp = erlang:monotonic_time(), 788 Session = State0#state.session, 789 790 State0#state{session = Session#session{own_certificate = OwnCert, 791 time_stamp = TimeStamp}, 792 static_env = InitStatEnv0#static_env{ 793 file_ref_db = FileRefHandle, 794 cert_db_ref = Ref, 795 cert_db = CertDbHandle, 796 crl_db = CRLDbHandle, 797 session_cache = CacheHandle 798 }, 799 handshake_env = HsEnv#handshake_env{diffie_hellman_params = DHParams}, 800 connection_env = CEnv#connection_env{private_key = Key}, 801 ssl_options = Opts}. 802 803%%==================================================================== 804%% gen_statem general state functions with connection cb argument 805%%==================================================================== 806%%-------------------------------------------------------------------- 807-spec init(gen_statem:event_type(), 808 {start, timeout()} | {start, {list(), list()}, timeout()}| term(), 809 #state{}, tls_connection | dtls_connection) -> 810 gen_statem:state_function_result(). 811%%-------------------------------------------------------------------- 812 813init({call, From}, {start, Timeout}, State0, Connection) -> 814 Connection:next_event(hello, no_record, State0#state{start_or_recv_from = From}, 815 [{{timeout, handshake}, Timeout, close}]); 816init({call, From}, {start, {Opts, EmOpts}, Timeout}, 817 #state{static_env = #static_env{role = Role}, 818 ssl_options = OrigSSLOptions, 819 socket_options = SockOpts} = State0, Connection) -> 820 try 821 SslOpts = ssl:handle_options(Opts, OrigSSLOptions), 822 State = ssl_config(SslOpts, Role, State0), 823 init({call, From}, {start, Timeout}, 824 State#state{ssl_options = SslOpts, 825 socket_options = new_emulated(EmOpts, SockOpts)}, Connection) 826 catch throw:Error -> 827 {stop_and_reply, {shutdown, normal}, {reply, From, {error, Error}}, State0} 828 end; 829init({call, From}, {new_user, _} = Msg, State, Connection) -> 830 handle_call(Msg, From, ?FUNCTION_NAME, State, Connection); 831init({call, From}, _Msg, _State, _Connection) -> 832 {keep_state_and_data, [{reply, From, {error, notsup_on_transport_accept_socket}}]}; 833init(_Type, _Event, _State, _Connection) -> 834 {keep_state_and_data, [postpone]}. 835 836%%-------------------------------------------------------------------- 837-spec error(gen_statem:event_type(), 838 {start, timeout()} | term(), #state{}, 839 tls_connection | dtls_connection) -> 840 gen_statem:state_function_result(). 841%%-------------------------------------------------------------------- 842error({call, From}, {close, _}, State, _Connection) -> 843 {stop_and_reply, {shutdown, normal}, {reply, From, ok}, State}; 844error({call, From}, _Msg, State, _Connection) -> 845 {next_state, ?FUNCTION_NAME, State, [{reply, From, {error, closed}}]}. 846 847%%-------------------------------------------------------------------- 848-spec hello(gen_statem:event_type(), 849 #hello_request{} | #server_hello{} | term(), 850 #state{}, tls_connection | dtls_connection) -> 851 gen_statem:state_function_result(). 852%%-------------------------------------------------------------------- 853hello({call, From}, Msg, State, Connection) -> 854 handle_call(Msg, From, ?FUNCTION_NAME, State, Connection); 855hello(internal, {common_client_hello, Type, ServerHelloExt}, State, Connection) -> 856 do_server_hello(Type, ServerHelloExt, State, Connection); 857hello(info, Msg, State, _) -> 858 handle_info(Msg, ?FUNCTION_NAME, State); 859hello(Type, Msg, State, Connection) -> 860 handle_common_event(Type, Msg, ?FUNCTION_NAME, State, Connection). 861 862user_hello({call, From}, cancel, #state{connection_env = #connection_env{negotiated_version = Version}} = State, _) -> 863 gen_statem:reply(From, ok), 864 handle_own_alert(?ALERT_REC(?FATAL, ?USER_CANCELED, user_canceled), 865 Version, ?FUNCTION_NAME, State); 866user_hello({call, From}, {handshake_continue, NewOptions, Timeout}, 867 #state{static_env = #static_env{role = Role}, 868 handshake_env = #handshake_env{hello = Hello}, 869 ssl_options = Options0} = State0, _Connection) -> 870 Options = ssl:handle_options(NewOptions, Options0#ssl_options{handshake = full}), 871 State = ssl_config(Options, Role, State0), 872 {next_state, hello, State#state{start_or_recv_from = From}, 873 [{next_event, internal, Hello}, {{timeout, handshake}, Timeout, close}]}; 874user_hello(_, _, _, _) -> 875 {keep_state_and_data, [postpone]}. 876 877%%-------------------------------------------------------------------- 878-spec abbreviated(gen_statem:event_type(), 879 #hello_request{} | #finished{} | term(), 880 #state{}, tls_connection | dtls_connection) -> 881 gen_statem:state_function_result(). 882%%-------------------------------------------------------------------- 883abbreviated({call, From}, Msg, State, Connection) -> 884 handle_call(Msg, From, ?FUNCTION_NAME, State, Connection); 885abbreviated(internal, #finished{verify_data = Data} = Finished, 886 #state{static_env = #static_env{role = server}, 887 handshake_env = #handshake_env{tls_handshake_history = Hist, 888 expecting_finished = true} = HsEnv, 889 connection_env = #connection_env{negotiated_version = Version}, 890 session = #session{master_secret = MasterSecret}, 891 connection_states = ConnectionStates0} = 892 State0, Connection) -> 893 case ssl_handshake:verify_connection(ssl:tls_version(Version), Finished, client, 894 get_current_prf(ConnectionStates0, write), 895 MasterSecret, Hist) of 896 verified -> 897 ConnectionStates = 898 ssl_record:set_client_verify_data(current_both, Data, ConnectionStates0), 899 {Record, State} = prepare_connection(State0#state{connection_states = ConnectionStates, 900 handshake_env = HsEnv#handshake_env{expecting_finished = false}}, Connection), 901 Connection:next_event(connection, Record, State, [{{timeout, handshake}, infinity, close}]); 902 #alert{} = Alert -> 903 handle_own_alert(Alert, Version, ?FUNCTION_NAME, State0) 904 end; 905abbreviated(internal, #finished{verify_data = Data} = Finished, 906 #state{static_env = #static_env{role = client}, 907 handshake_env = #handshake_env{tls_handshake_history = Hist0}, 908 connection_env = #connection_env{negotiated_version = Version}, 909 session = #session{master_secret = MasterSecret}, 910 connection_states = ConnectionStates0} = State0, Connection) -> 911 case ssl_handshake:verify_connection(ssl:tls_version(Version), Finished, server, 912 get_pending_prf(ConnectionStates0, write), 913 MasterSecret, Hist0) of 914 verified -> 915 ConnectionStates1 = 916 ssl_record:set_server_verify_data(current_read, Data, ConnectionStates0), 917 {#state{handshake_env = HsEnv} = State1, Actions} = 918 finalize_handshake(State0#state{connection_states = ConnectionStates1}, 919 ?FUNCTION_NAME, Connection), 920 {Record, State} = prepare_connection(State1#state{handshake_env = HsEnv#handshake_env{expecting_finished = false}}, Connection), 921 Connection:next_event(connection, Record, State, [{{timeout, handshake}, infinity, close} | Actions]); 922 #alert{} = Alert -> 923 handle_own_alert(Alert, Version, ?FUNCTION_NAME, State0) 924 end; 925%% only allowed to send next_protocol message after change cipher spec 926%% & before finished message and it is not allowed during renegotiation 927abbreviated(internal, #next_protocol{selected_protocol = SelectedProtocol}, 928 #state{static_env = #static_env{role = server}, 929 handshake_env = #handshake_env{expecting_next_protocol_negotiation = true} = HsEnv} = State, 930 Connection) -> 931 Connection:next_event(?FUNCTION_NAME, no_record, 932 State#state{handshake_env = HsEnv#handshake_env{negotiated_protocol = SelectedProtocol, 933 expecting_next_protocol_negotiation = false}}); 934abbreviated(internal, 935 #change_cipher_spec{type = <<1>>}, 936 #state{connection_states = ConnectionStates0, 937 handshake_env = HsEnv} = State, Connection) -> 938 ConnectionStates1 = 939 ssl_record:activate_pending_connection_state(ConnectionStates0, read, Connection), 940 Connection:next_event(?FUNCTION_NAME, no_record, State#state{connection_states = 941 ConnectionStates1, 942 handshake_env = HsEnv#handshake_env{expecting_finished = true}}); 943abbreviated(info, Msg, State, _) -> 944 handle_info(Msg, ?FUNCTION_NAME, State); 945abbreviated(Type, Msg, State, Connection) -> 946 handle_common_event(Type, Msg, ?FUNCTION_NAME, State, Connection). 947 948%%-------------------------------------------------------------------- 949-spec certify(gen_statem:event_type(), 950 #hello_request{} | #certificate{} | #server_key_exchange{} | 951 #certificate_request{} | #server_hello_done{} | #client_key_exchange{} | term(), 952 #state{}, tls_connection | dtls_connection) -> 953 gen_statem:state_function_result(). 954%%-------------------------------------------------------------------- 955certify({call, From}, Msg, State, Connection) -> 956 handle_call(Msg, From, ?FUNCTION_NAME, State, Connection); 957certify(info, Msg, State, _) -> 958 handle_info(Msg, ?FUNCTION_NAME, State); 959certify(internal, #certificate{asn1_certificates = []}, 960 #state{static_env = #static_env{role = server}, 961 connection_env = #connection_env{negotiated_version = Version}, 962 ssl_options = #ssl_options{verify = verify_peer, 963 fail_if_no_peer_cert = true}} = 964 State, _) -> 965 Alert = ?ALERT_REC(?FATAL,?HANDSHAKE_FAILURE), 966 handle_own_alert(Alert, Version, ?FUNCTION_NAME, State); 967certify(internal, #certificate{asn1_certificates = []}, 968 #state{static_env = #static_env{role = server}, 969 ssl_options = #ssl_options{verify = verify_peer, 970 fail_if_no_peer_cert = false}} = 971 State0, Connection) -> 972 Connection:next_event(?FUNCTION_NAME, no_record, State0#state{client_certificate_requested = false}); 973certify(internal, #certificate{}, 974 #state{static_env = #static_env{role = server}, 975 connection_env = #connection_env{negotiated_version = Version}, 976 ssl_options = #ssl_options{verify = verify_none}} = 977 State, _) -> 978 Alert = ?ALERT_REC(?FATAL,?UNEXPECTED_MESSAGE, unrequested_certificate), 979 handle_own_alert(Alert, Version, ?FUNCTION_NAME, State); 980certify(internal, #certificate{} = Cert, 981 #state{static_env = #static_env{ 982 role = Role, 983 host = Host, 984 cert_db = CertDbHandle, 985 cert_db_ref = CertDbRef, 986 crl_db = CRLDbInfo}, 987 connection_env = #connection_env{negotiated_version = Version}, 988 ssl_options = Opts} = State, Connection) -> 989 case ssl_handshake:certify(Cert, CertDbHandle, CertDbRef, 990 Opts, CRLDbInfo, Role, Host) of 991 {PeerCert, PublicKeyInfo} -> 992 handle_peer_cert(Role, PeerCert, PublicKeyInfo, 993 State#state{client_certificate_requested = false}, Connection); 994 #alert{} = Alert -> 995 handle_own_alert(Alert, Version, ?FUNCTION_NAME, State) 996 end; 997certify(internal, #server_key_exchange{exchange_keys = Keys}, 998 #state{static_env = #static_env{role = client}, 999 handshake_env = #handshake_env{kex_algorithm = KexAlg, 1000 public_key_info = PubKeyInfo} = HsEnv, 1001 connection_env = #connection_env{negotiated_version = Version}, 1002 session = Session, 1003 connection_states = ConnectionStates} = State, Connection) 1004 when KexAlg == dhe_dss; 1005 KexAlg == dhe_rsa; 1006 KexAlg == ecdhe_rsa; 1007 KexAlg == ecdhe_ecdsa; 1008 KexAlg == dh_anon; 1009 KexAlg == ecdh_anon; 1010 KexAlg == psk; 1011 KexAlg == dhe_psk; 1012 KexAlg == ecdhe_psk; 1013 KexAlg == rsa_psk; 1014 KexAlg == srp_dss; 1015 KexAlg == srp_rsa; 1016 KexAlg == srp_anon -> 1017 1018 Params = ssl_handshake:decode_server_key(Keys, KexAlg, ssl:tls_version(Version)), 1019 1020 %% Use negotiated value if TLS-1.2 otherwhise return default 1021 HashSign = negotiated_hashsign(Params#server_key_params.hashsign, KexAlg, PubKeyInfo, ssl:tls_version(Version)), 1022 1023 case is_anonymous(KexAlg) of 1024 true -> 1025 calculate_secret(Params#server_key_params.params, 1026 State#state{handshake_env = HsEnv#handshake_env{hashsign_algorithm = HashSign}}, Connection); 1027 false -> 1028 case ssl_handshake:verify_server_key(Params, HashSign, 1029 ConnectionStates, ssl:tls_version(Version), PubKeyInfo) of 1030 true -> 1031 calculate_secret(Params#server_key_params.params, 1032 State#state{handshake_env = HsEnv#handshake_env{hashsign_algorithm = HashSign}, 1033 session = session_handle_params(Params#server_key_params.params, Session)}, 1034 Connection); 1035 false -> 1036 handle_own_alert(?ALERT_REC(?FATAL, ?DECRYPT_ERROR), 1037 Version, ?FUNCTION_NAME, State) 1038 end 1039 end; 1040certify(internal, #certificate_request{}, 1041 #state{static_env = #static_env{role = client}, 1042 handshake_env = #handshake_env{kex_algorithm = KexAlg}, 1043 connection_env = #connection_env{negotiated_version = Version}} = State, _) 1044 when KexAlg == dh_anon; 1045 KexAlg == ecdh_anon; 1046 KexAlg == psk; 1047 KexAlg == dhe_psk; 1048 KexAlg == ecdhe_psk; 1049 KexAlg == rsa_psk; 1050 KexAlg == srp_dss; 1051 KexAlg == srp_rsa; 1052 KexAlg == srp_anon -> 1053 handle_own_alert(?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE), 1054 Version, ?FUNCTION_NAME, State); 1055certify(internal, #certificate_request{}, 1056 #state{static_env = #static_env{role = client}, 1057 session = #session{own_certificate = undefined}} = State, Connection) -> 1058 %% The client does not have a certificate and will send an empty reply, the server may fail 1059 %% or accept the connection by its own preference. No signature algorihms needed as there is 1060 %% no certificate to verify. 1061 Connection:next_event(?FUNCTION_NAME, no_record, State#state{client_certificate_requested = true}); 1062certify(internal, #certificate_request{} = CertRequest, 1063 #state{static_env = #static_env{role = client}, 1064 handshake_env = HsEnv, 1065 connection_env = #connection_env{negotiated_version = Version}, 1066 session = #session{own_certificate = Cert}, 1067 ssl_options = #ssl_options{signature_algs = SupportedHashSigns}} = State, Connection) -> 1068 case ssl_handshake:select_hashsign(CertRequest, Cert, SupportedHashSigns, ssl:tls_version(Version)) of 1069 #alert {} = Alert -> 1070 handle_own_alert(Alert, Version, ?FUNCTION_NAME, State); 1071 NegotiatedHashSign -> 1072 Connection:next_event(?FUNCTION_NAME, no_record, 1073 State#state{client_certificate_requested = true, 1074 handshake_env = HsEnv#handshake_env{cert_hashsign_algorithm = NegotiatedHashSign}}) 1075 end; 1076%% PSK and RSA_PSK might bypass the Server-Key-Exchange 1077certify(internal, #server_hello_done{}, 1078 #state{static_env = #static_env{role = client}, 1079 session = #session{master_secret = undefined}, 1080 connection_env = #connection_env{negotiated_version = Version}, 1081 handshake_env = #handshake_env{kex_algorithm = KexAlg, 1082 premaster_secret = undefined, 1083 server_psk_identity = PSKIdentity} = HsEnv, 1084 ssl_options = #ssl_options{user_lookup_fun = PSKLookup}} = State0, Connection) 1085 when KexAlg == psk -> 1086 case ssl_handshake:premaster_secret({KexAlg, PSKIdentity}, PSKLookup) of 1087 #alert{} = Alert -> 1088 handle_own_alert(Alert, Version, ?FUNCTION_NAME, State0); 1089 PremasterSecret -> 1090 State = master_secret(PremasterSecret, 1091 State0#state{handshake_env = 1092 HsEnv#handshake_env{premaster_secret = PremasterSecret}}), 1093 client_certify_and_key_exchange(State, Connection) 1094 end; 1095certify(internal, #server_hello_done{}, 1096 #state{static_env = #static_env{role = client}, 1097 connection_env = #connection_env{negotiated_version = {Major, Minor}} = Version, 1098 handshake_env = #handshake_env{kex_algorithm = KexAlg, 1099 premaster_secret = undefined, 1100 server_psk_identity = PSKIdentity} = HsEnv, 1101 session = #session{master_secret = undefined}, 1102 ssl_options = #ssl_options{user_lookup_fun = PSKLookup}} = State0, Connection) 1103 when KexAlg == rsa_psk -> 1104 Rand = ssl_cipher:random_bytes(?NUM_OF_PREMASTERSECRET_BYTES-2), 1105 RSAPremasterSecret = <<?BYTE(Major), ?BYTE(Minor), Rand/binary>>, 1106 case ssl_handshake:premaster_secret({KexAlg, PSKIdentity}, PSKLookup, 1107 RSAPremasterSecret) of 1108 #alert{} = Alert -> 1109 handle_own_alert(Alert, Version, ?FUNCTION_NAME, State0); 1110 PremasterSecret -> 1111 State = master_secret(PremasterSecret, 1112 State0#state{handshake_env = 1113 HsEnv#handshake_env{premaster_secret = RSAPremasterSecret}}), 1114 client_certify_and_key_exchange(State, Connection) 1115 end; 1116%% Master secret was determined with help of server-key exchange msg 1117certify(internal, #server_hello_done{}, 1118 #state{static_env = #static_env{role = client}, 1119 connection_env = #connection_env{negotiated_version = Version}, 1120 handshake_env = #handshake_env{premaster_secret = undefined}, 1121 session = #session{master_secret = MasterSecret} = Session, 1122 connection_states = ConnectionStates0} = State0, Connection) -> 1123 case ssl_handshake:master_secret(ssl:tls_version(Version), Session, 1124 ConnectionStates0, client) of 1125 {MasterSecret, ConnectionStates} -> 1126 State = State0#state{connection_states = ConnectionStates}, 1127 client_certify_and_key_exchange(State, Connection); 1128 #alert{} = Alert -> 1129 handle_own_alert(Alert, Version, ?FUNCTION_NAME, State0) 1130 end; 1131%% Master secret is calculated from premaster_secret 1132certify(internal, #server_hello_done{}, 1133 #state{static_env = #static_env{role = client}, 1134 connection_env = #connection_env{negotiated_version = Version}, 1135 handshake_env = #handshake_env{premaster_secret = PremasterSecret}, 1136 session = Session0, 1137 connection_states = ConnectionStates0} = State0, Connection) -> 1138 case ssl_handshake:master_secret(ssl:tls_version(Version), PremasterSecret, 1139 ConnectionStates0, client) of 1140 {MasterSecret, ConnectionStates} -> 1141 Session = Session0#session{master_secret = MasterSecret}, 1142 State = State0#state{connection_states = ConnectionStates, 1143 session = Session}, 1144 client_certify_and_key_exchange(State, Connection); 1145 #alert{} = Alert -> 1146 handle_own_alert(Alert, Version, ?FUNCTION_NAME, State0) 1147 end; 1148certify(internal = Type, #client_key_exchange{} = Msg, 1149 #state{static_env = #static_env{role = server}, 1150 client_certificate_requested = true, 1151 ssl_options = #ssl_options{fail_if_no_peer_cert = true}} = State, 1152 Connection) -> 1153 %% We expect a certificate here 1154 handle_common_event(Type, Msg, ?FUNCTION_NAME, State, Connection); 1155certify(internal, #client_key_exchange{exchange_keys = Keys}, 1156 State = #state{handshake_env = #handshake_env{kex_algorithm = KeyAlg}, 1157 connection_env = #connection_env{negotiated_version = Version}}, Connection) -> 1158 try 1159 certify_client_key_exchange(ssl_handshake:decode_client_key(Keys, KeyAlg, ssl:tls_version(Version)), 1160 State, Connection) 1161 catch 1162 #alert{} = Alert -> 1163 handle_own_alert(Alert, Version, ?FUNCTION_NAME, State) 1164 end; 1165certify(Type, Msg, State, Connection) -> 1166 handle_common_event(Type, Msg, ?FUNCTION_NAME, State, Connection). 1167 1168%%-------------------------------------------------------------------- 1169-spec cipher(gen_statem:event_type(), 1170 #hello_request{} | #certificate_verify{} | #finished{} | term(), 1171 #state{}, tls_connection | dtls_connection) -> 1172 gen_statem:state_function_result(). 1173%%-------------------------------------------------------------------- 1174cipher({call, From}, Msg, State, Connection) -> 1175 handle_call(Msg, From, ?FUNCTION_NAME, State, Connection); 1176cipher(info, Msg, State, _) -> 1177 handle_info(Msg, ?FUNCTION_NAME, State); 1178cipher(internal, #certificate_verify{signature = Signature, 1179 hashsign_algorithm = CertHashSign}, 1180 #state{static_env = #static_env{role = server}, 1181 handshake_env = #handshake_env{tls_handshake_history = Hist, 1182 kex_algorithm = KexAlg, 1183 public_key_info = PubKeyInfo} = HsEnv, 1184 connection_env = #connection_env{negotiated_version = Version}, 1185 session = #session{master_secret = MasterSecret} 1186 } = State, Connection) -> 1187 1188 TLSVersion = ssl:tls_version(Version), 1189 %% Use negotiated value if TLS-1.2 otherwhise return default 1190 HashSign = negotiated_hashsign(CertHashSign, KexAlg, PubKeyInfo, TLSVersion), 1191 case ssl_handshake:certificate_verify(Signature, PubKeyInfo, 1192 TLSVersion, HashSign, MasterSecret, Hist) of 1193 valid -> 1194 Connection:next_event(?FUNCTION_NAME, no_record, 1195 State#state{handshake_env = HsEnv#handshake_env{cert_hashsign_algorithm = HashSign}}); 1196 #alert{} = Alert -> 1197 handle_own_alert(Alert, Version, ?FUNCTION_NAME, State) 1198 end; 1199%% client must send a next protocol message if we are expecting it 1200cipher(internal, #finished{}, 1201 #state{static_env = #static_env{role = server}, 1202 handshake_env = #handshake_env{expecting_next_protocol_negotiation = true, 1203 negotiated_protocol = undefined}, 1204 connection_env = #connection_env{negotiated_version = Version}} = State0, 1205 _Connection) -> 1206 handle_own_alert(?ALERT_REC(?FATAL,?UNEXPECTED_MESSAGE), Version, ?FUNCTION_NAME, State0); 1207cipher(internal, #finished{verify_data = Data} = Finished, 1208 #state{static_env = #static_env{role = Role, 1209 host = Host, 1210 port = Port}, 1211 handshake_env = #handshake_env{tls_handshake_history = Hist, 1212 expecting_finished = true} = HsEnv, 1213 connection_env = #connection_env{negotiated_version = Version}, 1214 session = #session{master_secret = MasterSecret} 1215 = Session0, 1216 ssl_options = SslOpts, 1217 connection_states = ConnectionStates0} = State, Connection) -> 1218 case ssl_handshake:verify_connection(ssl:tls_version(Version), Finished, 1219 opposite_role(Role), 1220 get_current_prf(ConnectionStates0, read), 1221 MasterSecret, Hist) of 1222 verified -> 1223 Session = handle_session(Role, SslOpts, Host, Port, Session0), 1224 cipher_role(Role, Data, Session, 1225 State#state{handshake_env = HsEnv#handshake_env{expecting_finished = false}}, Connection); 1226 #alert{} = Alert -> 1227 handle_own_alert(Alert, Version, ?FUNCTION_NAME, State) 1228 end; 1229%% only allowed to send next_protocol message after change cipher spec 1230%% & before finished message and it is not allowed during renegotiation 1231cipher(internal, #next_protocol{selected_protocol = SelectedProtocol}, 1232 #state{static_env = #static_env{role = server}, 1233 handshake_env = #handshake_env{expecting_finished = true, 1234 expecting_next_protocol_negotiation = true} = HsEnv} = State, Connection) -> 1235 Connection:next_event(?FUNCTION_NAME, no_record, 1236 State#state{handshake_env = HsEnv#handshake_env{negotiated_protocol = SelectedProtocol, 1237 expecting_next_protocol_negotiation = false}}); 1238cipher(internal, #change_cipher_spec{type = <<1>>}, #state{handshake_env = HsEnv, connection_states = ConnectionStates0} = 1239 State, Connection) -> 1240 ConnectionStates = 1241 ssl_record:activate_pending_connection_state(ConnectionStates0, read, Connection), 1242 Connection:next_event(?FUNCTION_NAME, no_record, State#state{handshake_env = HsEnv#handshake_env{expecting_finished = true}, 1243 connection_states = ConnectionStates}); 1244cipher(Type, Msg, State, Connection) -> 1245 handle_common_event(Type, Msg, ?FUNCTION_NAME, State, Connection). 1246 1247%%-------------------------------------------------------------------- 1248-spec connection(gen_statem:event_type(), term(), 1249 #state{}, tls_connection | dtls_connection) -> 1250 gen_statem:state_function_result(). 1251%%-------------------------------------------------------------------- 1252connection({call, RecvFrom}, {recv, N, Timeout}, 1253 #state{static_env = #static_env{protocol_cb = Connection}, 1254 socket_options = 1255 #socket_options{active = false}} = State0, Connection) -> 1256 passive_receive(State0#state{bytes_to_read = N, 1257 start_or_recv_from = RecvFrom}, ?FUNCTION_NAME, Connection, 1258 [{{timeout, recv}, Timeout, timeout}]); 1259 1260connection({call, From}, renegotiate, #state{static_env = #static_env{protocol_cb = Connection}, 1261 handshake_env = HsEnv} = State, 1262 Connection) -> 1263 Connection:renegotiate(State#state{handshake_env = HsEnv#handshake_env{renegotiation = {true, From}}}, []); 1264connection({call, From}, peer_certificate, 1265 #state{session = #session{peer_certificate = Cert}} = State, _) -> 1266 hibernate_after(?FUNCTION_NAME, State, [{reply, From, {ok, Cert}}]); 1267connection({call, From}, {connection_information, true}, State, _) -> 1268 Info = connection_info(State) ++ security_info(State), 1269 hibernate_after(?FUNCTION_NAME, State, [{reply, From, {ok, Info}}]); 1270connection({call, From}, {connection_information, false}, State, _) -> 1271 Info = connection_info(State), 1272 hibernate_after(?FUNCTION_NAME, State, [{reply, From, {ok, Info}}]); 1273connection({call, From}, negotiated_protocol, 1274 #state{handshake_env = #handshake_env{negotiated_protocol = undefined}} = State, _) -> 1275 hibernate_after(?FUNCTION_NAME, State, [{reply, From, {error, protocol_not_negotiated}}]); 1276connection({call, From}, negotiated_protocol, 1277 #state{handshake_env = #handshake_env{negotiated_protocol = SelectedProtocol}} = State, _) -> 1278 hibernate_after(?FUNCTION_NAME, State, 1279 [{reply, From, {ok, SelectedProtocol}}]); 1280connection({call, From}, Msg, State, Connection) -> 1281 handle_call(Msg, From, ?FUNCTION_NAME, State, Connection); 1282connection(cast, {internal_renegotiate, WriteState}, #state{static_env = #static_env{protocol_cb = Connection}, 1283 handshake_env = HsEnv, 1284 connection_states = ConnectionStates} 1285 = State, Connection) -> 1286 Connection:renegotiate(State#state{handshake_env = HsEnv#handshake_env{renegotiation = {true, internal}}, 1287 connection_states = ConnectionStates#{current_write => WriteState}}, []); 1288connection(cast, {dist_handshake_complete, DHandle}, 1289 #state{ssl_options = #ssl_options{erl_dist = true}, 1290 connection_env = CEnv, 1291 socket_options = SockOpts} = State0, Connection) -> 1292 process_flag(priority, normal), 1293 State1 = 1294 State0#state{ 1295 socket_options = SockOpts#socket_options{active = true}, 1296 connection_env = CEnv#connection_env{erl_dist_handle = DHandle}, 1297 bytes_to_read = undefined}, 1298 {Record, State} = read_application_data(<<>>, State1), 1299 Connection:next_event(connection, Record, State); 1300connection(info, Msg, State, _) -> 1301 handle_info(Msg, ?FUNCTION_NAME, State); 1302connection(internal, {recv, Timeout}, State, Connection) -> 1303 passive_receive(State, ?FUNCTION_NAME, Connection, [{{timeout, recv}, Timeout, timeout}]); 1304connection(Type, Msg, State, Connection) -> 1305 handle_common_event(Type, Msg, ?FUNCTION_NAME, State, Connection). 1306 1307%%-------------------------------------------------------------------- 1308-spec downgrade(gen_statem:event_type(), term(), 1309 #state{}, tls_connection | dtls_connection) -> 1310 gen_statem:state_function_result(). 1311%%-------------------------------------------------------------------- 1312downgrade(Type, Event, State, Connection) -> 1313 handle_common_event(Type, Event, ?FUNCTION_NAME, State, Connection). 1314 1315%%-------------------------------------------------------------------- 1316%% Event handling functions called by state functions to handle 1317%% common or unexpected events for the state. 1318%%-------------------------------------------------------------------- 1319handle_common_event(internal, {handshake, {#hello_request{} = Handshake, _}}, connection = StateName, 1320 #state{static_env = #static_env{role = client}, 1321 handshake_env = HsEnv} = State, _) -> 1322 %% Should not be included in handshake history 1323 {next_state, StateName, State#state{handshake_env = HsEnv#handshake_env{renegotiation = {true, peer}}}, 1324 [{next_event, internal, Handshake}]}; 1325handle_common_event(internal, {handshake, {#hello_request{}, _}}, StateName, 1326 #state{static_env = #static_env{role = client}}, _) 1327 when StateName =/= connection -> 1328 keep_state_and_data; 1329handle_common_event(internal, {handshake, {Handshake, Raw}}, StateName, 1330 #state{handshake_env = #handshake_env{tls_handshake_history = Hist0}} = State0, 1331 Connection) -> 1332 1333 PossibleSNI = Connection:select_sni_extension(Handshake), 1334 %% This function handles client SNI hello extension when Handshake is 1335 %% a client_hello, which needs to be determined by the connection callback. 1336 %% In other cases this is a noop 1337 State = #state{handshake_env = HsEnv} = handle_sni_extension(PossibleSNI, State0), 1338 1339 Hist = ssl_handshake:update_handshake_history(Hist0, Raw), 1340 {next_state, StateName, State#state{handshake_env = HsEnv#handshake_env{tls_handshake_history = Hist}}, 1341 [{next_event, internal, Handshake}]}; 1342handle_common_event(internal, {protocol_record, TLSorDTLSRecord}, StateName, State, Connection) -> 1343 Connection:handle_protocol_record(TLSorDTLSRecord, StateName, State); 1344handle_common_event(timeout, hibernate, _, _, _) -> 1345 {keep_state_and_data, [hibernate]}; 1346handle_common_event(internal, #change_cipher_spec{type = <<1>>}, StateName, 1347 #state{connection_env = #connection_env{negotiated_version = Version}} = State, _) -> 1348 handle_own_alert(?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE), Version, 1349 StateName, State); 1350handle_common_event({timeout, handshake}, close, _StateName, #state{start_or_recv_from = StartFrom} = State, _) -> 1351 {stop_and_reply, 1352 {shutdown, user_timeout}, 1353 {reply, StartFrom, {error, timeout}}, State#state{start_or_recv_from = undefined}}; 1354handle_common_event({timeout, recv}, timeout, StateName, #state{start_or_recv_from = RecvFrom} = State, _) -> 1355 {next_state, StateName, State#state{start_or_recv_from = undefined, 1356 bytes_to_read = undefined}, [{reply, RecvFrom, {error, timeout}}]}; 1357handle_common_event(_Type, Msg, StateName, #state{connection_env = 1358 #connection_env{negotiated_version = Version}} = State, 1359 _) -> 1360 Alert = ?ALERT_REC(?FATAL,?UNEXPECTED_MESSAGE, {unexpected_msg, Msg}), 1361 handle_own_alert(Alert, Version, StateName, State). 1362 1363handle_call({application_data, _Data}, _, _, _, _) -> 1364 %% In renegotiation priorities handshake, send data when handshake is finished 1365 {keep_state_and_data, [postpone]}; 1366handle_call({close, _} = Close, From, StateName, #state{connection_env = CEnv} = State, _Connection) -> 1367 %% Run terminate before returning so that the reuseaddr 1368 %% inet-option works properly 1369 Result = terminate(Close, StateName, State), 1370 {stop_and_reply, 1371 {shutdown, normal}, 1372 {reply, From, Result}, State#state{connection_env = CEnv#connection_env{terminated = true}}}; 1373handle_call({shutdown, read_write = How}, From, StateName, 1374 #state{static_env = #static_env{transport_cb = Transport, 1375 socket = Socket}, 1376 connection_env = CEnv} = State, _) -> 1377 try send_alert(?ALERT_REC(?WARNING, ?CLOSE_NOTIFY), 1378 StateName, State) of 1379 _ -> 1380 case Transport:shutdown(Socket, How) of 1381 ok -> 1382 {next_state, StateName, State#state{connection_env = 1383 CEnv#connection_env{terminated = true}}, 1384 [{reply, From, ok}]}; 1385 Error -> 1386 {stop_and_reply, {shutdown, normal}, {reply, From, Error}, 1387 State#state{connection_env = CEnv#connection_env{terminated = true}}} 1388 end 1389 catch 1390 throw:Return -> 1391 Return 1392 end; 1393handle_call({shutdown, How0}, From, StateName, 1394 #state{static_env = #static_env{transport_cb = Transport, 1395 socket = Socket}} = State, _) -> 1396 case Transport:shutdown(Socket, How0) of 1397 ok -> 1398 {next_state, StateName, State, [{reply, From, ok}]}; 1399 Error -> 1400 {stop_and_reply, {shutdown, normal}, {reply, From, Error}, State} 1401 end; 1402handle_call({recv, _N, _Timeout}, From, _, 1403 #state{socket_options = 1404 #socket_options{active = Active}}, _) when Active =/= false -> 1405 {keep_state_and_data, [{reply, From, {error, einval}}]}; 1406handle_call({recv, N, Timeout}, RecvFrom, StateName, State, _) -> 1407 %% Doing renegotiate wait with handling request until renegotiate is 1408 %% finished. 1409 {next_state, StateName, State#state{bytes_to_read = N, start_or_recv_from = RecvFrom}, 1410 [{next_event, internal, {recv, RecvFrom}} , {{timeout, recv}, Timeout, timeout}]}; 1411handle_call({new_user, User}, From, StateName, 1412 State = #state{connection_env = #connection_env{user_application = {OldMon, _}} = CEnv}, _) -> 1413 NewMon = erlang:monitor(process, User), 1414 erlang:demonitor(OldMon, [flush]), 1415 {next_state, StateName, State#state{connection_env = CEnv#connection_env{user_application = {NewMon, User}}}, 1416 [{reply, From, ok}]}; 1417handle_call({get_opts, OptTags}, From, _, 1418 #state{static_env = #static_env{socket = Socket, 1419 transport_cb = Transport}, 1420 socket_options = SockOpts}, Connection) -> 1421 OptsReply = get_socket_opts(Connection, Transport, Socket, OptTags, SockOpts, []), 1422 {keep_state_and_data, [{reply, From, OptsReply}]}; 1423handle_call({set_opts, Opts0}, From, StateName, 1424 #state{static_env = #static_env{socket = Socket, 1425 transport_cb = Transport, 1426 tracker = Tracker}, 1427 connection_env = 1428 #connection_env{user_application = {_Mon, Pid}}, 1429 socket_options = Opts1 1430 } = State0, Connection) -> 1431 {Reply, Opts} = set_socket_opts(Connection, Transport, Socket, Opts0, Opts1, []), 1432 case {proplists:lookup(active, Opts0), Opts} of 1433 {{_, N}, #socket_options{active=false}} when is_integer(N) -> 1434 send_user( 1435 Pid, 1436 format_passive( 1437 Connection:pids(State0), Transport, Socket, Tracker, Connection)); 1438 _ -> 1439 ok 1440 end, 1441 State = State0#state{socket_options = Opts}, 1442 handle_active_option(Opts#socket_options.active, StateName, From, Reply, State); 1443 1444handle_call(renegotiate, From, StateName, _, _) when StateName =/= connection -> 1445 {keep_state_and_data, [{reply, From, {error, already_renegotiating}}]}; 1446 1447handle_call({prf, Secret, Label, Seed, WantedLength}, From, _, 1448 #state{connection_states = ConnectionStates, 1449 connection_env = #connection_env{negotiated_version = Version}}, _) -> 1450 #{security_parameters := SecParams} = 1451 ssl_record:current_connection_state(ConnectionStates, read), 1452 #security_parameters{master_secret = MasterSecret, 1453 client_random = ClientRandom, 1454 server_random = ServerRandom, 1455 prf_algorithm = PRFAlgorithm} = SecParams, 1456 Reply = try 1457 SecretToUse = case Secret of 1458 _ when is_binary(Secret) -> Secret; 1459 master_secret -> MasterSecret 1460 end, 1461 SeedToUse = lists:reverse( 1462 lists:foldl(fun(X, Acc) when is_binary(X) -> [X|Acc]; 1463 (client_random, Acc) -> [ClientRandom|Acc]; 1464 (server_random, Acc) -> [ServerRandom|Acc] 1465 end, [], Seed)), 1466 ssl_handshake:prf(ssl:tls_version(Version), PRFAlgorithm, SecretToUse, Label, SeedToUse, WantedLength) 1467 catch 1468 exit:_ -> {error, badarg}; 1469 error:Reason -> {error, Reason} 1470 end, 1471 {keep_state_and_data, [{reply, From, Reply}]}; 1472handle_call(_,_,_,_,_) -> 1473 {keep_state_and_data, [postpone]}. 1474 1475handle_info({ErrorTag, Socket, econnaborted}, StateName, 1476 #state{static_env = #static_env{role = Role, 1477 socket = Socket, 1478 transport_cb = Transport, 1479 error_tag = ErrorTag, 1480 tracker = Tracker, 1481 protocol_cb = Connection}, 1482 start_or_recv_from = StartFrom 1483 } = State) when StateName =/= connection -> 1484 Pids = Connection:pids(State), 1485 alert_user(Pids, Transport, Tracker,Socket, 1486 StartFrom, ?ALERT_REC(?FATAL, ?CLOSE_NOTIFY), Role, StateName, Connection), 1487 {stop, {shutdown, normal}, State}; 1488 1489handle_info({ErrorTag, Socket, Reason}, StateName, #state{static_env = #static_env{socket = Socket, 1490 error_tag = ErrorTag}} = State) -> 1491 Report = io_lib:format("SSL: Socket error: ~p ~n", [Reason]), 1492 error_logger:error_report(Report), 1493 handle_normal_shutdown(?ALERT_REC(?FATAL, ?CLOSE_NOTIFY), StateName, State), 1494 {stop, {shutdown,normal}, State}; 1495 1496handle_info({'DOWN', MonitorRef, _, _, Reason}, _, 1497 #state{connection_env = #connection_env{user_application = {MonitorRef, _Pid}}, 1498 ssl_options = #ssl_options{erl_dist = true}}) -> 1499 {stop, {shutdown, Reason}}; 1500handle_info({'DOWN', MonitorRef, _, _, _}, _, 1501 #state{connection_env = #connection_env{user_application = {MonitorRef, _Pid}}}) -> 1502 {stop, {shutdown, normal}}; 1503handle_info({'EXIT', Pid, _Reason}, StateName, 1504 #state{connection_env = #connection_env{user_application = {_MonitorRef, Pid}}} = State) -> 1505 %% It seems the user application has linked to us 1506 %% - ignore that and let the monitor handle this 1507 {next_state, StateName, State}; 1508%%% So that terminate will be run when supervisor issues shutdown 1509handle_info({'EXIT', _Sup, shutdown}, _StateName, State) -> 1510 {stop, shutdown, State}; 1511handle_info({'EXIT', Socket, normal}, _StateName, #state{static_env = #static_env{socket = Socket}} = State) -> 1512 %% Handle as transport close" 1513 {stop,{shutdown, transport_closed}, State}; 1514handle_info({'EXIT', Socket, Reason}, _StateName, #state{static_env = #static_env{socket = Socket}} = State) -> 1515 {stop,{shutdown, Reason}, State}; 1516 1517handle_info(allow_renegotiate, StateName, #state{handshake_env = HsEnv} = State) -> 1518 {next_state, StateName, State#state{handshake_env = HsEnv#handshake_env{allow_renegotiate = true}}}; 1519 1520handle_info(Msg, StateName, #state{static_env = #static_env{socket = Socket, error_tag = Tag}} = State) -> 1521 Report = io_lib:format("SSL: Got unexpected info: ~p ~n", [{Msg, Tag, Socket}]), 1522 error_logger:info_report(Report), 1523 {next_state, StateName, State}. 1524 1525%%==================================================================== 1526%% general gen_statem callbacks 1527%%==================================================================== 1528terminate(_, _, #state{connection_env = #connection_env{terminated = true}}) -> 1529 %% Happens when user closes the connection using ssl:close/1 1530 %% we want to guarantee that Transport:close has been called 1531 %% when ssl:close/1 returns unless it is a downgrade where 1532 %% we want to guarantee that close alert is received before 1533 %% returning. In both cases terminate has been run manually 1534 %% before run by gen_statem which will end up here 1535 ok; 1536terminate({shutdown, transport_closed} = Reason, 1537 _StateName, #state{static_env = #static_env{protocol_cb = Connection, 1538 socket = Socket, 1539 transport_cb = Transport}} = State) -> 1540 handle_trusted_certs_db(State), 1541 Connection:close(Reason, Socket, Transport, undefined, undefined); 1542terminate({shutdown, own_alert}, _StateName, #state{ 1543 static_env = #static_env{protocol_cb = Connection, 1544 socket = Socket, 1545 transport_cb = Transport}} = State) -> 1546 handle_trusted_certs_db(State), 1547 case application:get_env(ssl, alert_timeout) of 1548 {ok, Timeout} when is_integer(Timeout) -> 1549 Connection:close({timeout, Timeout}, Socket, Transport, undefined, undefined); 1550 _ -> 1551 Connection:close({timeout, ?DEFAULT_TIMEOUT}, Socket, Transport, undefined, undefined) 1552 end; 1553terminate({shutdown, downgrade = Reason}, downgrade, #state{static_env = #static_env{protocol_cb = Connection, 1554 transport_cb = Transport, 1555 socket = Socket} 1556 } = State) -> 1557 handle_trusted_certs_db(State), 1558 Connection:close(Reason, Socket, Transport, undefined, undefined); 1559terminate(Reason, connection, #state{static_env = #static_env{ 1560 protocol_cb = Connection, 1561 transport_cb = Transport, 1562 socket = Socket}, 1563 connection_states = ConnectionStates, 1564 ssl_options = #ssl_options{padding_check = Check} 1565 } = State) -> 1566 handle_trusted_certs_db(State), 1567 Alert = terminate_alert(Reason), 1568 %% Send the termination ALERT if possible 1569 catch (ok = Connection:send_alert_in_connection(Alert, State)), 1570 Connection:close({timeout, ?DEFAULT_TIMEOUT}, Socket, Transport, ConnectionStates, Check); 1571terminate(Reason, _StateName, #state{static_env = #static_env{transport_cb = Transport, 1572 protocol_cb = Connection, 1573 socket = Socket} 1574 } = State) -> 1575 handle_trusted_certs_db(State), 1576 Connection:close(Reason, Socket, Transport, undefined, undefined). 1577 1578format_status(normal, [_, StateName, State]) -> 1579 [{data, [{"State", {StateName, State}}]}]; 1580format_status(terminate, [_, StateName, State]) -> 1581 SslOptions = (State#state.ssl_options), 1582 NewOptions = SslOptions#ssl_options{password = ?SECRET_PRINTOUT, 1583 cert = ?SECRET_PRINTOUT, 1584 cacerts = ?SECRET_PRINTOUT, 1585 key = ?SECRET_PRINTOUT, 1586 dh = ?SECRET_PRINTOUT, 1587 psk_identity = ?SECRET_PRINTOUT, 1588 srp_identity = ?SECRET_PRINTOUT}, 1589 [{data, [{"State", {StateName, State#state{connection_states = ?SECRET_PRINTOUT, 1590 protocol_buffers = ?SECRET_PRINTOUT, 1591 user_data_buffer = ?SECRET_PRINTOUT, 1592 handshake_env = ?SECRET_PRINTOUT, 1593 connection_env = ?SECRET_PRINTOUT, 1594 session = ?SECRET_PRINTOUT, 1595 ssl_options = NewOptions, 1596 flight_buffer = ?SECRET_PRINTOUT} 1597 }}]}]. 1598 1599%%-------------------------------------------------------------------- 1600%%% Internal functions 1601%%-------------------------------------------------------------------- 1602send_alert(Alert, connection, #state{static_env = #static_env{protocol_cb = Connection}} = State) -> 1603 Connection:send_alert_in_connection(Alert, State); 1604send_alert(Alert, _, #state{static_env = #static_env{protocol_cb = Connection}} = State) -> 1605 Connection:send_alert(Alert, State). 1606 1607connection_info(#state{static_env = #static_env{protocol_cb = Connection}, 1608 handshake_env = #handshake_env{sni_hostname = SNIHostname}, 1609 session = #session{session_id = SessionId, 1610 cipher_suite = CipherSuite, ecc = ECCCurve}, 1611 connection_env = #connection_env{negotiated_version = {_,_} = Version}, 1612 ssl_options = Opts}) -> 1613 RecordCB = record_cb(Connection), 1614 CipherSuiteDef = #{key_exchange := KexAlg} = ssl_cipher_format:suite_definition(CipherSuite), 1615 IsNamedCurveSuite = lists:member(KexAlg, 1616 [ecdh_ecdsa, ecdhe_ecdsa, ecdh_rsa, ecdhe_rsa, ecdh_anon]), 1617 CurveInfo = case ECCCurve of 1618 {namedCurve, Curve} when IsNamedCurveSuite -> 1619 [{ecc, {named_curve, pubkey_cert_records:namedCurves(Curve)}}]; 1620 _ -> 1621 [] 1622 end, 1623 [{protocol, RecordCB:protocol_version(Version)}, 1624 {session_id, SessionId}, 1625 {cipher_suite, ssl_cipher_format:erl_suite_definition(CipherSuiteDef)}, 1626 {selected_cipher_suite, CipherSuiteDef}, 1627 {sni_hostname, SNIHostname} | CurveInfo] ++ ssl_options_list(Opts). 1628 1629security_info(#state{connection_states = ConnectionStates}) -> 1630 #{security_parameters := 1631 #security_parameters{client_random = ClientRand, 1632 server_random = ServerRand, 1633 master_secret = MasterSecret}} = 1634 ssl_record:current_connection_state(ConnectionStates, read), 1635 [{client_random, ClientRand}, {server_random, ServerRand}, {master_secret, MasterSecret}]. 1636 1637do_server_hello(Type, #hello_extensions{next_protocol_negotiation = NextProtocols} = 1638 ServerHelloExt, 1639 #state{connection_env = #connection_env{negotiated_version = Version}, 1640 handshake_env = HsEnv, 1641 session = #session{session_id = SessId}, 1642 connection_states = ConnectionStates0} 1643 = State0, Connection) when is_atom(Type) -> 1644 1645 ServerHello = 1646 ssl_handshake:server_hello(SessId, ssl:tls_version(Version), ConnectionStates0, ServerHelloExt), 1647 State = server_hello(ServerHello, 1648 State0#state{handshake_env = HsEnv#handshake_env{expecting_next_protocol_negotiation = 1649 NextProtocols =/= undefined}}, Connection), 1650 case Type of 1651 new -> 1652 new_server_hello(ServerHello, State, Connection); 1653 resumed -> 1654 resumed_server_hello(State, Connection) 1655 end. 1656 1657new_server_hello(#server_hello{cipher_suite = CipherSuite, 1658 compression_method = Compression, 1659 session_id = SessionId}, 1660 #state{session = Session0, 1661 connection_env = #connection_env{negotiated_version = Version}} = State0, Connection) -> 1662 try server_certify_and_key_exchange(State0, Connection) of 1663 #state{} = State1 -> 1664 {State, Actions} = server_hello_done(State1, Connection), 1665 Session = 1666 Session0#session{session_id = SessionId, 1667 cipher_suite = CipherSuite, 1668 compression_method = Compression}, 1669 Connection:next_event(certify, no_record, State#state{session = Session}, Actions) 1670 catch 1671 #alert{} = Alert -> 1672 handle_own_alert(Alert, Version, hello, State0) 1673 end. 1674 1675resumed_server_hello(#state{session = Session, 1676 connection_states = ConnectionStates0, 1677 connection_env = #connection_env{negotiated_version = Version}} = State0, Connection) -> 1678 1679 case ssl_handshake:master_secret(ssl:tls_version(Version), Session, 1680 ConnectionStates0, server) of 1681 {_, ConnectionStates1} -> 1682 State1 = State0#state{connection_states = ConnectionStates1, 1683 session = Session}, 1684 {State, Actions} = 1685 finalize_handshake(State1, abbreviated, Connection), 1686 Connection:next_event(abbreviated, no_record, State, Actions); 1687 #alert{} = Alert -> 1688 handle_own_alert(Alert, Version, hello, State0) 1689 end. 1690 1691server_hello(ServerHello, State0, Connection) -> 1692 CipherSuite = ServerHello#server_hello.cipher_suite, 1693 #{key_exchange := KeyAlgorithm} = ssl_cipher_format:suite_definition(CipherSuite), 1694 #state{handshake_env = HsEnv} = State = Connection:queue_handshake(ServerHello, State0), 1695 State#state{handshake_env = HsEnv#handshake_env{kex_algorithm = KeyAlgorithm}}. 1696 1697server_hello_done(State, Connection) -> 1698 HelloDone = ssl_handshake:server_hello_done(), 1699 Connection:send_handshake(HelloDone, State). 1700 1701handle_peer_cert(Role, PeerCert, PublicKeyInfo, 1702 #state{handshake_env = HsEnv, 1703 session = #session{cipher_suite = CipherSuite} = Session} = State0, 1704 Connection) -> 1705 State1 = State0#state{handshake_env = HsEnv#handshake_env{public_key_info = PublicKeyInfo}, 1706 session = 1707 Session#session{peer_certificate = PeerCert}}, 1708 #{key_exchange := KeyAlgorithm} = ssl_cipher_format:suite_definition(CipherSuite), 1709 State = handle_peer_cert_key(Role, PeerCert, PublicKeyInfo, KeyAlgorithm, State1), 1710 Connection:next_event(certify, no_record, State). 1711 1712handle_peer_cert_key(client, _, 1713 {?'id-ecPublicKey', #'ECPoint'{point = _ECPoint} = PublicKey, 1714 PublicKeyParams}, 1715 KeyAlg, #state{handshake_env = HsEnv, 1716 session = Session} = State) when KeyAlg == ecdh_rsa; 1717 KeyAlg == ecdh_ecdsa -> 1718 ECDHKey = public_key:generate_key(PublicKeyParams), 1719 PremasterSecret = ssl_handshake:premaster_secret(PublicKey, ECDHKey), 1720 master_secret(PremasterSecret, State#state{handshake_env = HsEnv#handshake_env{kex_keys = ECDHKey}, 1721 session = Session#session{ecc = PublicKeyParams}}); 1722handle_peer_cert_key(_, _, _, _, State) -> 1723 State. 1724 1725certify_client(#state{static_env = #static_env{role = client, 1726 cert_db = CertDbHandle, 1727 cert_db_ref = CertDbRef}, 1728 client_certificate_requested = true, 1729 session = #session{own_certificate = OwnCert}} 1730 = State, Connection) -> 1731 Certificate = ssl_handshake:certificate(OwnCert, CertDbHandle, CertDbRef, client), 1732 Connection:queue_handshake(Certificate, State); 1733certify_client(#state{client_certificate_requested = false} = State, _) -> 1734 State. 1735 1736verify_client_cert(#state{static_env = #static_env{role = client}, 1737 handshake_env = #handshake_env{tls_handshake_history = Hist, 1738 cert_hashsign_algorithm = HashSign}, 1739 connection_env = #connection_env{negotiated_version = Version, 1740 private_key = PrivateKey}, 1741 client_certificate_requested = true, 1742 session = #session{master_secret = MasterSecret, 1743 own_certificate = OwnCert}} = State, Connection) -> 1744 1745 case ssl_handshake:client_certificate_verify(OwnCert, MasterSecret, 1746 ssl:tls_version(Version), HashSign, PrivateKey, Hist) of 1747 #certificate_verify{} = Verified -> 1748 Connection:queue_handshake(Verified, State); 1749 ignore -> 1750 State; 1751 #alert{} = Alert -> 1752 throw(Alert) 1753 end; 1754verify_client_cert(#state{client_certificate_requested = false} = State, _) -> 1755 State. 1756 1757client_certify_and_key_exchange(#state{connection_env = #connection_env{negotiated_version = Version}} = 1758 State0, Connection) -> 1759 try do_client_certify_and_key_exchange(State0, Connection) of 1760 State1 = #state{} -> 1761 {State2, Actions} = finalize_handshake(State1, certify, Connection), 1762 State = State2#state{ 1763 %% Reinitialize 1764 client_certificate_requested = false}, 1765 Connection:next_event(cipher, no_record, State, Actions) 1766 catch 1767 throw:#alert{} = Alert -> 1768 handle_own_alert(Alert, Version, certify, State0) 1769 end. 1770 1771do_client_certify_and_key_exchange(State0, Connection) -> 1772 State1 = certify_client(State0, Connection), 1773 State2 = key_exchange(State1, Connection), 1774 verify_client_cert(State2, Connection). 1775 1776server_certify_and_key_exchange(State0, Connection) -> 1777 State1 = certify_server(State0, Connection), 1778 State2 = key_exchange(State1, Connection), 1779 request_client_cert(State2, Connection). 1780 1781certify_client_key_exchange(#encrypted_premaster_secret{premaster_secret= EncPMS}, 1782 #state{connection_env = #connection_env{private_key = Key}, 1783 handshake_env = #handshake_env{client_hello_version = {Major, Minor} = Version}} 1784 = State, Connection) -> 1785 FakeSecret = make_premaster_secret(Version, rsa), 1786 %% Countermeasure for Bleichenbacher attack always provide some kind of premaster secret 1787 %% and fail handshake later.RFC 5246 section 7.4.7.1. 1788 PremasterSecret = 1789 try ssl_handshake:premaster_secret(EncPMS, Key) of 1790 Secret when erlang:byte_size(Secret) == ?NUM_OF_PREMASTERSECRET_BYTES -> 1791 case Secret of 1792 <<?BYTE(Major), ?BYTE(Minor), Rest/binary>> -> %% Correct 1793 <<?BYTE(Major), ?BYTE(Minor), Rest/binary>>; 1794 <<?BYTE(_), ?BYTE(_), Rest/binary>> -> %% Version mismatch 1795 <<?BYTE(Major), ?BYTE(Minor), Rest/binary>> 1796 end; 1797 _ -> %% erlang:byte_size(Secret) =/= ?NUM_OF_PREMASTERSECRET_BYTES 1798 FakeSecret 1799 catch 1800 #alert{description = ?DECRYPT_ERROR} -> 1801 FakeSecret 1802 end, 1803 calculate_master_secret(PremasterSecret, State, Connection, certify, cipher); 1804certify_client_key_exchange(#client_diffie_hellman_public{dh_public = ClientPublicDhKey}, 1805 #state{handshake_env = #handshake_env{diffie_hellman_params = #'DHParameter'{} = Params, 1806 kex_keys = {_, ServerDhPrivateKey}} 1807 } = State, 1808 Connection) -> 1809 PremasterSecret = ssl_handshake:premaster_secret(ClientPublicDhKey, ServerDhPrivateKey, Params), 1810 calculate_master_secret(PremasterSecret, State, Connection, certify, cipher); 1811 1812certify_client_key_exchange(#client_ec_diffie_hellman_public{dh_public = ClientPublicEcDhPoint}, 1813 #state{handshake_env = #handshake_env{kex_keys = ECDHKey}} = State, Connection) -> 1814 PremasterSecret = ssl_handshake:premaster_secret(#'ECPoint'{point = ClientPublicEcDhPoint}, ECDHKey), 1815 calculate_master_secret(PremasterSecret, State, Connection, certify, cipher); 1816certify_client_key_exchange(#client_psk_identity{} = ClientKey, 1817 #state{ssl_options = 1818 #ssl_options{user_lookup_fun = PSKLookup}} = State0, 1819 Connection) -> 1820 PremasterSecret = ssl_handshake:premaster_secret(ClientKey, PSKLookup), 1821 calculate_master_secret(PremasterSecret, State0, Connection, certify, cipher); 1822certify_client_key_exchange(#client_dhe_psk_identity{} = ClientKey, 1823 #state{handshake_env = #handshake_env{diffie_hellman_params = #'DHParameter'{} = Params, 1824 kex_keys = {_, ServerDhPrivateKey}}, 1825 ssl_options = 1826 #ssl_options{user_lookup_fun = PSKLookup}} = State0, 1827 Connection) -> 1828 PremasterSecret = 1829 ssl_handshake:premaster_secret(ClientKey, ServerDhPrivateKey, Params, PSKLookup), 1830 calculate_master_secret(PremasterSecret, State0, Connection, certify, cipher); 1831certify_client_key_exchange(#client_ecdhe_psk_identity{} = ClientKey, 1832 #state{handshake_env = #handshake_env{kex_keys = ServerEcDhPrivateKey}, 1833 ssl_options = 1834 #ssl_options{user_lookup_fun = PSKLookup}} = State, 1835 Connection) -> 1836 PremasterSecret = 1837 ssl_handshake:premaster_secret(ClientKey, ServerEcDhPrivateKey, PSKLookup), 1838 calculate_master_secret(PremasterSecret, State, Connection, certify, cipher); 1839certify_client_key_exchange(#client_rsa_psk_identity{} = ClientKey, 1840 #state{connection_env = #connection_env{private_key = Key}, 1841 ssl_options = 1842 #ssl_options{user_lookup_fun = PSKLookup}} = State0, 1843 Connection) -> 1844 PremasterSecret = ssl_handshake:premaster_secret(ClientKey, Key, PSKLookup), 1845 calculate_master_secret(PremasterSecret, State0, Connection, certify, cipher); 1846certify_client_key_exchange(#client_srp_public{} = ClientKey, 1847 #state{handshake_env = #handshake_env{srp_params = Params, 1848 kex_keys = Key} 1849 } = State0, Connection) -> 1850 PremasterSecret = ssl_handshake:premaster_secret(ClientKey, Key, Params), 1851 calculate_master_secret(PremasterSecret, State0, Connection, certify, cipher). 1852 1853certify_server(#state{handshake_env = #handshake_env{kex_algorithm = KexAlg}} = 1854 State, _) when KexAlg == dh_anon; 1855 KexAlg == ecdh_anon; 1856 KexAlg == psk; 1857 KexAlg == dhe_psk; 1858 KexAlg == ecdhe_psk; 1859 KexAlg == srp_anon -> 1860 State; 1861certify_server(#state{static_env = #static_env{cert_db = CertDbHandle, 1862 cert_db_ref = CertDbRef}, 1863 session = #session{own_certificate = OwnCert}} = State, Connection) -> 1864 case ssl_handshake:certificate(OwnCert, CertDbHandle, CertDbRef, server) of 1865 Cert = #certificate{} -> 1866 Connection:queue_handshake(Cert, State); 1867 Alert = #alert{} -> 1868 throw(Alert) 1869 end. 1870 1871key_exchange(#state{static_env = #static_env{role = server}, 1872 handshake_env = #handshake_env{kex_algorithm = rsa}} = State,_) -> 1873 State; 1874key_exchange(#state{static_env = #static_env{role = server}, 1875 handshake_env = #handshake_env{kex_algorithm = KexAlg, 1876 diffie_hellman_params = #'DHParameter'{} = Params, 1877 hashsign_algorithm = HashSignAlgo}, 1878 connection_env = #connection_env{negotiated_version = Version, 1879 private_key = PrivateKey}, 1880 connection_states = ConnectionStates0} = State0, Connection) 1881 when KexAlg == dhe_dss; 1882 KexAlg == dhe_rsa; 1883 KexAlg == dh_anon -> 1884 DHKeys = public_key:generate_key(Params), 1885 #{security_parameters := SecParams} = 1886 ssl_record:pending_connection_state(ConnectionStates0, read), 1887 #security_parameters{client_random = ClientRandom, 1888 server_random = ServerRandom} = SecParams, 1889 Msg = ssl_handshake:key_exchange(server, ssl:tls_version(Version), {dh, DHKeys, Params, 1890 HashSignAlgo, ClientRandom, 1891 ServerRandom, 1892 PrivateKey}), 1893 #state{handshake_env = HsEnv} = State = Connection:queue_handshake(Msg, State0), 1894 State#state{handshake_env = HsEnv#handshake_env{kex_keys = DHKeys}}; 1895key_exchange(#state{static_env = #static_env{role = server}, 1896 handshake_env = #handshake_env{kex_algorithm = KexAlg} = HsEnv, 1897 connection_env = #connection_env{private_key = #'ECPrivateKey'{parameters = ECCurve} = Key}, 1898 session = Session} = State, _) 1899 when KexAlg == ecdh_ecdsa; 1900 KexAlg == ecdh_rsa -> 1901 State#state{handshake_env = HsEnv#handshake_env{kex_keys = Key}, 1902 session = Session#session{ecc = ECCurve}}; 1903key_exchange(#state{static_env = #static_env{role = server}, 1904 handshake_env = #handshake_env{kex_algorithm = KexAlg, 1905 hashsign_algorithm = HashSignAlgo}, 1906 connection_env = #connection_env{negotiated_version = Version, 1907 private_key = PrivateKey}, 1908 session = #session{ecc = ECCCurve}, 1909 connection_states = ConnectionStates0} = State0, Connection) 1910 when KexAlg == ecdhe_ecdsa; 1911 KexAlg == ecdhe_rsa; 1912 KexAlg == ecdh_anon -> 1913 1914 ECDHKeys = public_key:generate_key(ECCCurve), 1915 #{security_parameters := SecParams} = 1916 ssl_record:pending_connection_state(ConnectionStates0, read), 1917 #security_parameters{client_random = ClientRandom, 1918 server_random = ServerRandom} = SecParams, 1919 Msg = ssl_handshake:key_exchange(server, ssl:tls_version(Version), 1920 {ecdh, ECDHKeys, 1921 HashSignAlgo, ClientRandom, 1922 ServerRandom, 1923 PrivateKey}), 1924 #state{handshake_env = HsEnv} = State = Connection:queue_handshake(Msg, State0), 1925 State#state{handshake_env = HsEnv#handshake_env{kex_keys = ECDHKeys}}; 1926key_exchange(#state{static_env = #static_env{role = server}, 1927 handshake_env = #handshake_env{kex_algorithm = psk}, 1928 ssl_options = #ssl_options{psk_identity = undefined}} = State, _) -> 1929 State; 1930key_exchange(#state{static_env = #static_env{role = server}, 1931 ssl_options = #ssl_options{psk_identity = PskIdentityHint}, 1932 handshake_env = #handshake_env{kex_algorithm = psk, 1933 hashsign_algorithm = HashSignAlgo}, 1934 connection_env = #connection_env{negotiated_version = Version, 1935 private_key = PrivateKey}, 1936 connection_states = ConnectionStates0} = State0, Connection) -> 1937 #{security_parameters := SecParams} = 1938 ssl_record:pending_connection_state(ConnectionStates0, read), 1939 #security_parameters{client_random = ClientRandom, 1940 server_random = ServerRandom} = SecParams, 1941 Msg = ssl_handshake:key_exchange(server, ssl:tls_version(Version), 1942 {psk, PskIdentityHint, 1943 HashSignAlgo, ClientRandom, 1944 ServerRandom, 1945 PrivateKey}), 1946 Connection:queue_handshake(Msg, State0); 1947key_exchange(#state{static_env = #static_env{role = server}, 1948 ssl_options = #ssl_options{psk_identity = PskIdentityHint}, 1949 handshake_env = #handshake_env{kex_algorithm = dhe_psk, 1950 diffie_hellman_params = #'DHParameter'{} = Params, 1951 hashsign_algorithm = HashSignAlgo}, 1952 connection_env = #connection_env{negotiated_version = Version, 1953 private_key = PrivateKey}, 1954 connection_states = ConnectionStates0 1955 } = State0, Connection) -> 1956 DHKeys = public_key:generate_key(Params), 1957 #{security_parameters := SecParams} = 1958 ssl_record:pending_connection_state(ConnectionStates0, read), 1959 #security_parameters{client_random = ClientRandom, 1960 server_random = ServerRandom} = SecParams, 1961 Msg = ssl_handshake:key_exchange(server, ssl:tls_version(Version), 1962 {dhe_psk, 1963 PskIdentityHint, DHKeys, Params, 1964 HashSignAlgo, ClientRandom, 1965 ServerRandom, 1966 PrivateKey}), 1967 #state{handshake_env = HsEnv} = State = Connection:queue_handshake(Msg, State0), 1968 State#state{handshake_env = HsEnv#handshake_env{kex_keys = DHKeys}}; 1969key_exchange(#state{static_env = #static_env{role = server}, 1970 ssl_options = #ssl_options{psk_identity = PskIdentityHint}, 1971 handshake_env = #handshake_env{kex_algorithm = ecdhe_psk, 1972 hashsign_algorithm = HashSignAlgo}, 1973 connection_env = #connection_env{negotiated_version = Version, 1974 private_key = PrivateKey}, 1975 session = #session{ecc = ECCCurve}, 1976 connection_states = ConnectionStates0 1977 } = State0, Connection) -> 1978 ECDHKeys = public_key:generate_key(ECCCurve), 1979 #{security_parameters := SecParams} = 1980 ssl_record:pending_connection_state(ConnectionStates0, read), 1981 #security_parameters{client_random = ClientRandom, 1982 server_random = ServerRandom} = SecParams, 1983 Msg = ssl_handshake:key_exchange(server, ssl:tls_version(Version), 1984 {ecdhe_psk, 1985 PskIdentityHint, ECDHKeys, 1986 HashSignAlgo, ClientRandom, 1987 ServerRandom, 1988 PrivateKey}), 1989 #state{handshake_env = HsEnv} = State = Connection:queue_handshake(Msg, State0), 1990 State#state{handshake_env = HsEnv#handshake_env{kex_keys = ECDHKeys}}; 1991key_exchange(#state{static_env = #static_env{role = server}, 1992 handshake_env = #handshake_env{kex_algorithm = rsa_psk}, 1993 ssl_options = #ssl_options{psk_identity = undefined}} = State, _) -> 1994 State; 1995key_exchange(#state{static_env = #static_env{role = server}, 1996 ssl_options = #ssl_options{psk_identity = PskIdentityHint}, 1997 handshake_env = #handshake_env{kex_algorithm = rsa_psk, 1998 hashsign_algorithm = HashSignAlgo}, 1999 connection_env = #connection_env{negotiated_version = Version, 2000 private_key = PrivateKey}, 2001 connection_states = ConnectionStates0 2002 } = State0, Connection) -> 2003 #{security_parameters := SecParams} = 2004 ssl_record:pending_connection_state(ConnectionStates0, read), 2005 #security_parameters{client_random = ClientRandom, 2006 server_random = ServerRandom} = SecParams, 2007 Msg = ssl_handshake:key_exchange(server, ssl:tls_version(Version), 2008 {psk, PskIdentityHint, 2009 HashSignAlgo, ClientRandom, 2010 ServerRandom, 2011 PrivateKey}), 2012 Connection:queue_handshake(Msg, State0); 2013key_exchange(#state{static_env = #static_env{role = server}, 2014 ssl_options = #ssl_options{user_lookup_fun = LookupFun}, 2015 handshake_env = #handshake_env{kex_algorithm = KexAlg, 2016 hashsign_algorithm = HashSignAlgo}, 2017 connection_env = #connection_env{negotiated_version = Version, 2018 private_key = PrivateKey}, 2019 session = #session{srp_username = Username}, 2020 connection_states = ConnectionStates0 2021 } = State0, Connection) 2022 when KexAlg == srp_dss; 2023 KexAlg == srp_rsa; 2024 KexAlg == srp_anon -> 2025 SrpParams = handle_srp_identity(Username, LookupFun), 2026 Keys = case generate_srp_server_keys(SrpParams, 0) of 2027 Alert = #alert{} -> 2028 throw(Alert); 2029 Keys0 = {_,_} -> 2030 Keys0 2031 end, 2032 #{security_parameters := SecParams} = 2033 ssl_record:pending_connection_state(ConnectionStates0, read), 2034 #security_parameters{client_random = ClientRandom, 2035 server_random = ServerRandom} = SecParams, 2036 Msg = ssl_handshake:key_exchange(server, ssl:tls_version(Version), 2037 {srp, Keys, SrpParams, 2038 HashSignAlgo, ClientRandom, 2039 ServerRandom, 2040 PrivateKey}), 2041 #state{handshake_env = HsEnv} = State = Connection:queue_handshake(Msg, State0), 2042 State#state{handshake_env = HsEnv#handshake_env{srp_params = SrpParams, 2043 kex_keys = Keys}}; 2044key_exchange(#state{static_env = #static_env{role = client}, 2045 handshake_env = #handshake_env{kex_algorithm = rsa, 2046 public_key_info = PublicKeyInfo, 2047 premaster_secret = PremasterSecret}, 2048 connection_env = #connection_env{negotiated_version = Version} 2049 } = State0, Connection) -> 2050 Msg = rsa_key_exchange(ssl:tls_version(Version), PremasterSecret, PublicKeyInfo), 2051 Connection:queue_handshake(Msg, State0); 2052key_exchange(#state{static_env = #static_env{role = client}, 2053 handshake_env = #handshake_env{kex_algorithm = KexAlg, 2054 kex_keys = {DhPubKey, _}}, 2055 connection_env = #connection_env{negotiated_version = Version} 2056 } = State0, Connection) 2057 when KexAlg == dhe_dss; 2058 KexAlg == dhe_rsa; 2059 KexAlg == dh_anon -> 2060 Msg = ssl_handshake:key_exchange(client, ssl:tls_version(Version), {dh, DhPubKey}), 2061 Connection:queue_handshake(Msg, State0); 2062 2063key_exchange(#state{static_env = #static_env{role = client}, 2064 handshake_env = #handshake_env{kex_algorithm = KexAlg, 2065 kex_keys = #'ECPrivateKey'{parameters = ECCurve} = Key}, 2066 connection_env = #connection_env{negotiated_version = Version}, 2067 session = Session 2068 } = State0, Connection) 2069 when KexAlg == ecdhe_ecdsa; 2070 KexAlg == ecdhe_rsa; 2071 KexAlg == ecdh_ecdsa; 2072 KexAlg == ecdh_rsa; 2073 KexAlg == ecdh_anon -> 2074 Msg = ssl_handshake:key_exchange(client, ssl:tls_version(Version), {ecdh, Key}), 2075 Connection:queue_handshake(Msg, State0#state{session = Session#session{ecc = ECCurve}}); 2076key_exchange(#state{static_env = #static_env{role = client}, 2077 handshake_env = #handshake_env{kex_algorithm = psk}, 2078 connection_env = #connection_env{negotiated_version = Version}, 2079 ssl_options = SslOpts} = State0, Connection) -> 2080 Msg = ssl_handshake:key_exchange(client, ssl:tls_version(Version), 2081 {psk, SslOpts#ssl_options.psk_identity}), 2082 Connection:queue_handshake(Msg, State0); 2083key_exchange(#state{static_env = #static_env{role = client}, 2084 handshake_env = #handshake_env{kex_algorithm = dhe_psk, 2085 kex_keys = {DhPubKey, _}}, 2086 connection_env = #connection_env{negotiated_version = Version}, 2087 ssl_options = SslOpts} = State0, Connection) -> 2088 Msg = ssl_handshake:key_exchange(client, ssl:tls_version(Version), 2089 {dhe_psk, 2090 SslOpts#ssl_options.psk_identity, DhPubKey}), 2091 Connection:queue_handshake(Msg, State0); 2092 2093key_exchange(#state{static_env = #static_env{role = client}, 2094 handshake_env = #handshake_env{kex_algorithm = ecdhe_psk, 2095 kex_keys = ECDHKeys}, 2096 connection_env = #connection_env{negotiated_version = Version}, 2097 ssl_options = SslOpts} = State0, Connection) -> 2098 Msg = ssl_handshake:key_exchange(client, ssl:tls_version(Version), 2099 {ecdhe_psk, 2100 SslOpts#ssl_options.psk_identity, ECDHKeys}), 2101 Connection:queue_handshake(Msg, State0); 2102 2103key_exchange(#state{static_env = #static_env{role = client}, 2104 handshake_env = #handshake_env{kex_algorithm = rsa_psk, 2105 public_key_info = PublicKeyInfo, 2106 premaster_secret = PremasterSecret}, 2107 connection_env = #connection_env{negotiated_version = Version}, 2108 ssl_options = SslOpts} 2109 = State0, Connection) -> 2110 Msg = rsa_psk_key_exchange(ssl:tls_version(Version), SslOpts#ssl_options.psk_identity, 2111 PremasterSecret, PublicKeyInfo), 2112 Connection:queue_handshake(Msg, State0); 2113key_exchange(#state{static_env = #static_env{role = client}, 2114 handshake_env = #handshake_env{kex_algorithm = KexAlg, 2115 kex_keys = {ClientPubKey, _}}, 2116 connection_env = #connection_env{negotiated_version = Version}} 2117 = State0, Connection) 2118 when KexAlg == srp_dss; 2119 KexAlg == srp_rsa; 2120 KexAlg == srp_anon -> 2121 Msg = ssl_handshake:key_exchange(client, ssl:tls_version(Version), {srp, ClientPubKey}), 2122 Connection:queue_handshake(Msg, State0). 2123 2124rsa_key_exchange(Version, PremasterSecret, PublicKeyInfo = {Algorithm, _, _}) 2125 when Algorithm == ?rsaEncryption; 2126 Algorithm == ?md2WithRSAEncryption; 2127 Algorithm == ?md5WithRSAEncryption; 2128 Algorithm == ?sha1WithRSAEncryption; 2129 Algorithm == ?sha224WithRSAEncryption; 2130 Algorithm == ?sha256WithRSAEncryption; 2131 Algorithm == ?sha384WithRSAEncryption; 2132 Algorithm == ?sha512WithRSAEncryption 2133 -> 2134 ssl_handshake:key_exchange(client, ssl:tls_version(Version), 2135 {premaster_secret, PremasterSecret, 2136 PublicKeyInfo}); 2137rsa_key_exchange(_, _, _) -> 2138 throw (?ALERT_REC(?FATAL,?HANDSHAKE_FAILURE, pub_key_is_not_rsa)). 2139 2140rsa_psk_key_exchange(Version, PskIdentity, PremasterSecret, 2141 PublicKeyInfo = {Algorithm, _, _}) 2142 when Algorithm == ?rsaEncryption; 2143 Algorithm == ?md2WithRSAEncryption; 2144 Algorithm == ?md5WithRSAEncryption; 2145 Algorithm == ?sha1WithRSAEncryption; 2146 Algorithm == ?sha224WithRSAEncryption; 2147 Algorithm == ?sha256WithRSAEncryption; 2148 Algorithm == ?sha384WithRSAEncryption; 2149 Algorithm == ?sha512WithRSAEncryption 2150 -> 2151 ssl_handshake:key_exchange(client, ssl:tls_version(Version), 2152 {psk_premaster_secret, PskIdentity, PremasterSecret, 2153 PublicKeyInfo}); 2154rsa_psk_key_exchange(_, _, _, _) -> 2155 throw (?ALERT_REC(?FATAL,?HANDSHAKE_FAILURE, pub_key_is_not_rsa)). 2156 2157request_client_cert(#state{handshake_env = #handshake_env{kex_algorithm = Alg}} = State, _) 2158 when Alg == dh_anon; 2159 Alg == ecdh_anon; 2160 Alg == psk; 2161 Alg == dhe_psk; 2162 Alg == ecdhe_psk; 2163 Alg == rsa_psk; 2164 Alg == srp_dss; 2165 Alg == srp_rsa; 2166 Alg == srp_anon -> 2167 State; 2168 2169request_client_cert(#state{static_env = #static_env{cert_db = CertDbHandle, 2170 cert_db_ref = CertDbRef}, 2171 connection_env = #connection_env{negotiated_version = Version}, 2172 ssl_options = #ssl_options{verify = verify_peer, 2173 signature_algs = SupportedHashSigns}, 2174 connection_states = ConnectionStates0} = State0, Connection) -> 2175 #{security_parameters := 2176 #security_parameters{cipher_suite = CipherSuite}} = 2177 ssl_record:pending_connection_state(ConnectionStates0, read), 2178 TLSVersion = ssl:tls_version(Version), 2179 HashSigns = ssl_handshake:available_signature_algs(SupportedHashSigns, 2180 TLSVersion), 2181 Msg = ssl_handshake:certificate_request(CipherSuite, CertDbHandle, CertDbRef, 2182 HashSigns, TLSVersion), 2183 State = Connection:queue_handshake(Msg, State0), 2184 State#state{client_certificate_requested = true}; 2185 2186request_client_cert(#state{ssl_options = #ssl_options{verify = verify_none}} = 2187 State, _) -> 2188 State. 2189 2190calculate_master_secret(PremasterSecret, 2191 #state{connection_env = #connection_env{negotiated_version = Version}, 2192 connection_states = ConnectionStates0, 2193 session = Session0} = State0, Connection, 2194 _Current, Next) -> 2195 case ssl_handshake:master_secret(ssl:tls_version(Version), PremasterSecret, 2196 ConnectionStates0, server) of 2197 {MasterSecret, ConnectionStates} -> 2198 Session = Session0#session{master_secret = MasterSecret}, 2199 State = State0#state{connection_states = ConnectionStates, 2200 session = Session}, 2201 Connection:next_event(Next, no_record, State); 2202 #alert{} = Alert -> 2203 handle_own_alert(Alert, Version, certify, State0) 2204 end. 2205 2206finalize_handshake(State0, StateName, Connection) -> 2207 #state{connection_states = ConnectionStates0} = 2208 State1 = cipher_protocol(State0, Connection), 2209 2210 ConnectionStates = 2211 ssl_record:activate_pending_connection_state(ConnectionStates0, 2212 write, Connection), 2213 2214 State2 = State1#state{connection_states = ConnectionStates}, 2215 State = next_protocol(State2, Connection), 2216 finished(State, StateName, Connection). 2217 2218next_protocol(#state{static_env = #static_env{role = server}} = State, _) -> 2219 State; 2220next_protocol(#state{handshake_env = #handshake_env{negotiated_protocol = undefined}} = State, _) -> 2221 State; 2222next_protocol(#state{handshake_env = #handshake_env{expecting_next_protocol_negotiation = false}} = State, _) -> 2223 State; 2224next_protocol(#state{handshake_env = #handshake_env{negotiated_protocol = NextProtocol}} = State0, Connection) -> 2225 NextProtocolMessage = ssl_handshake:next_protocol(NextProtocol), 2226 Connection:queue_handshake(NextProtocolMessage, State0). 2227 2228cipher_protocol(State, Connection) -> 2229 Connection:queue_change_cipher(#change_cipher_spec{}, State). 2230 2231finished(#state{static_env = #static_env{role = Role}, 2232 handshake_env = #handshake_env{tls_handshake_history = Hist}, 2233 connection_env = #connection_env{negotiated_version = Version}, 2234 session = Session, 2235 connection_states = ConnectionStates0} = State0, 2236 StateName, Connection) -> 2237 MasterSecret = Session#session.master_secret, 2238 Finished = ssl_handshake:finished(ssl:tls_version(Version), Role, 2239 get_current_prf(ConnectionStates0, write), 2240 MasterSecret, Hist), 2241 ConnectionStates = save_verify_data(Role, Finished, ConnectionStates0, StateName), 2242 Connection:send_handshake(Finished, State0#state{connection_states = 2243 ConnectionStates}). 2244 2245save_verify_data(client, #finished{verify_data = Data}, ConnectionStates, certify) -> 2246 ssl_record:set_client_verify_data(current_write, Data, ConnectionStates); 2247save_verify_data(server, #finished{verify_data = Data}, ConnectionStates, cipher) -> 2248 ssl_record:set_server_verify_data(current_both, Data, ConnectionStates); 2249save_verify_data(client, #finished{verify_data = Data}, ConnectionStates, abbreviated) -> 2250 ssl_record:set_client_verify_data(current_both, Data, ConnectionStates); 2251save_verify_data(server, #finished{verify_data = Data}, ConnectionStates, abbreviated) -> 2252 ssl_record:set_server_verify_data(current_write, Data, ConnectionStates). 2253 2254calculate_secret(#server_dh_params{dh_p = Prime, dh_g = Base, 2255 dh_y = ServerPublicDhKey} = Params, 2256 #state{handshake_env = HsEnv} = State, Connection) -> 2257 Keys = {_, PrivateDhKey} = crypto:generate_key(dh, [Prime, Base]), 2258 PremasterSecret = 2259 ssl_handshake:premaster_secret(ServerPublicDhKey, PrivateDhKey, Params), 2260 calculate_master_secret(PremasterSecret, 2261 State#state{handshake_env = HsEnv#handshake_env{kex_keys = Keys}}, 2262 Connection, certify, certify); 2263 2264calculate_secret(#server_ecdh_params{curve = ECCurve, public = ECServerPubKey}, 2265 #state{handshake_env = HsEnv, 2266 session = Session} = State, Connection) -> 2267 ECDHKeys = public_key:generate_key(ECCurve), 2268 PremasterSecret = 2269 ssl_handshake:premaster_secret(#'ECPoint'{point = ECServerPubKey}, ECDHKeys), 2270 calculate_master_secret(PremasterSecret, 2271 State#state{handshake_env = HsEnv#handshake_env{kex_keys = ECDHKeys}, 2272 session = Session#session{ecc = ECCurve}}, 2273 Connection, certify, certify); 2274 2275calculate_secret(#server_psk_params{ 2276 hint = IdentityHint}, 2277 #state{handshake_env = HsEnv} = State, Connection) -> 2278 %% store for later use 2279 Connection:next_event(certify, no_record, 2280 State#state{handshake_env = 2281 HsEnv#handshake_env{server_psk_identity = IdentityHint}}); 2282 2283calculate_secret(#server_dhe_psk_params{ 2284 dh_params = #server_dh_params{dh_p = Prime, dh_g = Base}} = ServerKey, 2285 #state{handshake_env = HsEnv, 2286 ssl_options = #ssl_options{user_lookup_fun = PSKLookup}} = 2287 State, Connection) -> 2288 Keys = {_, PrivateDhKey} = 2289 crypto:generate_key(dh, [Prime, Base]), 2290 PremasterSecret = ssl_handshake:premaster_secret(ServerKey, PrivateDhKey, PSKLookup), 2291 calculate_master_secret(PremasterSecret, State#state{handshake_env = HsEnv#handshake_env{kex_keys = Keys}}, 2292 Connection, certify, certify); 2293 2294calculate_secret(#server_ecdhe_psk_params{ 2295 dh_params = #server_ecdh_params{curve = ECCurve}} = ServerKey, 2296 #state{ssl_options = #ssl_options{user_lookup_fun = PSKLookup}} = 2297 #state{handshake_env = HsEnv, 2298 session = Session} = State, Connection) -> 2299 ECDHKeys = public_key:generate_key(ECCurve), 2300 2301 PremasterSecret = ssl_handshake:premaster_secret(ServerKey, ECDHKeys, PSKLookup), 2302 calculate_master_secret(PremasterSecret, 2303 State#state{handshake_env = HsEnv#handshake_env{kex_keys = ECDHKeys}, 2304 session = Session#session{ecc = ECCurve}}, 2305 Connection, certify, certify); 2306 2307calculate_secret(#server_srp_params{srp_n = Prime, srp_g = Generator} = ServerKey, 2308 #state{handshake_env = HsEnv, 2309 ssl_options = #ssl_options{srp_identity = SRPId}} = State, 2310 Connection) -> 2311 Keys = generate_srp_client_keys(Generator, Prime, 0), 2312 PremasterSecret = ssl_handshake:premaster_secret(ServerKey, Keys, SRPId), 2313 calculate_master_secret(PremasterSecret, State#state{handshake_env = HsEnv#handshake_env{kex_keys = Keys}}, Connection, 2314 certify, certify). 2315 2316master_secret(#alert{} = Alert, _) -> 2317 Alert; 2318master_secret(PremasterSecret, #state{static_env = #static_env{role = Role}, 2319 connection_env = #connection_env{negotiated_version = Version}, 2320 session = Session, 2321 connection_states = ConnectionStates0} = State) -> 2322 case ssl_handshake:master_secret(ssl:tls_version(Version), PremasterSecret, 2323 ConnectionStates0, Role) of 2324 {MasterSecret, ConnectionStates} -> 2325 State#state{ 2326 session = 2327 Session#session{master_secret = MasterSecret}, 2328 connection_states = ConnectionStates}; 2329 #alert{} = Alert -> 2330 Alert 2331 end. 2332 2333generate_srp_server_keys(_SrpParams, 10) -> 2334 ?ALERT_REC(?FATAL, ?ILLEGAL_PARAMETER); 2335generate_srp_server_keys(SrpParams = 2336 #srp_user{generator = Generator, prime = Prime, 2337 verifier = Verifier}, N) -> 2338 try crypto:generate_key(srp, {host, [Verifier, Generator, Prime, '6a']}) of 2339 Keys -> 2340 Keys 2341 catch 2342 error:_ -> 2343 generate_srp_server_keys(SrpParams, N+1) 2344 end. 2345 2346generate_srp_client_keys(_Generator, _Prime, 10) -> 2347 ?ALERT_REC(?FATAL, ?ILLEGAL_PARAMETER); 2348generate_srp_client_keys(Generator, Prime, N) -> 2349 2350 try crypto:generate_key(srp, {user, [Generator, Prime, '6a']}) of 2351 Keys -> 2352 Keys 2353 catch 2354 error:_ -> 2355 generate_srp_client_keys(Generator, Prime, N+1) 2356 end. 2357 2358handle_srp_identity(Username, {Fun, UserState}) -> 2359 case Fun(srp, Username, UserState) of 2360 {ok, {SRPParams, Salt, DerivedKey}} 2361 when is_atom(SRPParams), is_binary(Salt), is_binary(DerivedKey) -> 2362 {Generator, Prime} = ssl_srp_primes:get_srp_params(SRPParams), 2363 Verifier = crypto:mod_pow(Generator, DerivedKey, Prime), 2364 #srp_user{generator = Generator, prime = Prime, 2365 salt = Salt, verifier = Verifier}; 2366 #alert{} = Alert -> 2367 throw(Alert); 2368 _ -> 2369 throw(?ALERT_REC(?FATAL, ?ILLEGAL_PARAMETER)) 2370 end. 2371 2372 2373cipher_role(client, Data, Session, #state{connection_states = ConnectionStates0} = State0, 2374 Connection) -> 2375 ConnectionStates = ssl_record:set_server_verify_data(current_both, Data, 2376 ConnectionStates0), 2377 {Record, State} = prepare_connection(State0#state{session = Session, 2378 connection_states = ConnectionStates}, 2379 Connection), 2380 Connection:next_event(connection, Record, State, [{{timeout, handshake}, infinity, close}]); 2381cipher_role(server, Data, Session, #state{connection_states = ConnectionStates0} = State0, 2382 Connection) -> 2383 ConnectionStates1 = ssl_record:set_client_verify_data(current_read, Data, 2384 ConnectionStates0), 2385 {State1, Actions} = 2386 finalize_handshake(State0#state{connection_states = ConnectionStates1, 2387 session = Session}, cipher, Connection), 2388 {Record, State} = prepare_connection(State1, Connection), 2389 Connection:next_event(connection, Record, State, [{{timeout, handshake}, infinity, close} | Actions]). 2390 2391is_anonymous(KexAlg) when KexAlg == dh_anon; 2392 KexAlg == ecdh_anon; 2393 KexAlg == psk; 2394 KexAlg == dhe_psk; 2395 KexAlg == ecdhe_psk; 2396 KexAlg == rsa_psk; 2397 KexAlg == srp_anon -> 2398 true; 2399is_anonymous(_) -> 2400 false. 2401 2402get_current_prf(CStates, Direction) -> 2403 #{security_parameters := SecParams} = ssl_record:current_connection_state(CStates, Direction), 2404 SecParams#security_parameters.prf_algorithm. 2405get_pending_prf(CStates, Direction) -> 2406 #{security_parameters := SecParams} = ssl_record:pending_connection_state(CStates, Direction), 2407 SecParams#security_parameters.prf_algorithm. 2408 2409opposite_role(client) -> 2410 server; 2411opposite_role(server) -> 2412 client. 2413 2414record_cb(tls_connection) -> 2415 tls_record; 2416record_cb(dtls_connection) -> 2417 dtls_record. 2418 2419call(FsmPid, Event) -> 2420 try gen_statem:call(FsmPid, Event) 2421 catch 2422 exit:{noproc, _} -> 2423 {error, closed}; 2424 exit:{normal, _} -> 2425 {error, closed}; 2426 exit:{{shutdown, _},_} -> 2427 {error, closed} 2428 end. 2429 2430get_socket_opts(_, _,_,[], _, Acc) -> 2431 {ok, Acc}; 2432get_socket_opts(Connection, Transport, Socket, [mode | Tags], SockOpts, Acc) -> 2433 get_socket_opts(Connection, Transport, Socket, Tags, SockOpts, 2434 [{mode, SockOpts#socket_options.mode} | Acc]); 2435get_socket_opts(Connection, Transport, Socket, [packet | Tags], SockOpts, Acc) -> 2436 case SockOpts#socket_options.packet of 2437 {Type, headers} -> 2438 get_socket_opts(Connection, Transport, Socket, Tags, SockOpts, [{packet, Type} | Acc]); 2439 Type -> 2440 get_socket_opts(Connection, Transport, Socket, Tags, SockOpts, [{packet, Type} | Acc]) 2441 end; 2442get_socket_opts(Connection, Transport, Socket, [header | Tags], SockOpts, Acc) -> 2443 get_socket_opts(Connection, Transport, Socket, Tags, SockOpts, 2444 [{header, SockOpts#socket_options.header} | Acc]); 2445get_socket_opts(Connection, Transport, Socket, [active | Tags], SockOpts, Acc) -> 2446 get_socket_opts(Connection, Transport, Socket, Tags, SockOpts, 2447 [{active, SockOpts#socket_options.active} | Acc]); 2448get_socket_opts(Connection, Transport, Socket, [Tag | Tags], SockOpts, Acc) -> 2449 case Connection:getopts(Transport, Socket, [Tag]) of 2450 {ok, [Opt]} -> 2451 get_socket_opts(Connection, Transport, Socket, Tags, SockOpts, [Opt | Acc]); 2452 {error, Reason} -> 2453 {error, {options, {socket_options, Tag, Reason}}} 2454 end; 2455get_socket_opts(_,_, _,Opts, _,_) -> 2456 {error, {options, {socket_options, Opts, function_clause}}}. 2457 2458set_socket_opts(_,_,_, [], SockOpts, []) -> 2459 {ok, SockOpts}; 2460set_socket_opts(ConnectionCb, Transport, Socket, [], SockOpts, Other) -> 2461 %% Set non emulated options 2462 try ConnectionCb:setopts(Transport, Socket, Other) of 2463 ok -> 2464 {ok, SockOpts}; 2465 {error, InetError} -> 2466 {{error, {options, {socket_options, Other, InetError}}}, SockOpts} 2467 catch 2468 _:Error -> 2469 %% So that inet behavior does not crash our process 2470 {{error, {options, {socket_options, Other, Error}}}, SockOpts} 2471 end; 2472 2473set_socket_opts(ConnectionCb, Transport,Socket, [{mode, Mode}| Opts], SockOpts, Other) 2474 when Mode == list; Mode == binary -> 2475 set_socket_opts(ConnectionCb, Transport, Socket, Opts, 2476 SockOpts#socket_options{mode = Mode}, Other); 2477set_socket_opts(_, _, _, [{mode, _} = Opt| _], SockOpts, _) -> 2478 {{error, {options, {socket_options, Opt}}}, SockOpts}; 2479set_socket_opts(ConnectionCb, Transport,Socket, [{packet, Packet}| Opts], SockOpts, Other) 2480 when Packet == raw; 2481 Packet == 0; 2482 Packet == 1; 2483 Packet == 2; 2484 Packet == 4; 2485 Packet == asn1; 2486 Packet == cdr; 2487 Packet == sunrm; 2488 Packet == fcgi; 2489 Packet == tpkt; 2490 Packet == line; 2491 Packet == http; 2492 Packet == httph; 2493 Packet == http_bin; 2494 Packet == httph_bin -> 2495 set_socket_opts(ConnectionCb, Transport, Socket, Opts, 2496 SockOpts#socket_options{packet = Packet}, Other); 2497set_socket_opts(_, _, _, [{packet, _} = Opt| _], SockOpts, _) -> 2498 {{error, {options, {socket_options, Opt}}}, SockOpts}; 2499set_socket_opts(ConnectionCb, Transport, Socket, [{header, Header}| Opts], SockOpts, Other) 2500 when is_integer(Header) -> 2501 set_socket_opts(ConnectionCb, Transport, Socket, Opts, 2502 SockOpts#socket_options{header = Header}, Other); 2503set_socket_opts(_, _, _, [{header, _} = Opt| _], SockOpts, _) -> 2504 {{error,{options, {socket_options, Opt}}}, SockOpts}; 2505set_socket_opts(ConnectionCb, Transport, Socket, [{active, Active}| Opts], SockOpts, Other) 2506 when Active == once; 2507 Active == true; 2508 Active == false -> 2509 set_socket_opts(ConnectionCb, Transport, Socket, Opts, 2510 SockOpts#socket_options{active = Active}, Other); 2511set_socket_opts(ConnectionCb, Transport, Socket, [{active, Active1} = Opt| Opts], 2512 SockOpts=#socket_options{active = Active0}, Other) 2513 when Active1 >= -32768, Active1 =< 32767 -> 2514 Active = if 2515 is_integer(Active0), Active0 + Active1 < -32768 -> 2516 error; 2517 is_integer(Active0), Active0 + Active1 =< 0 -> 2518 false; 2519 is_integer(Active0), Active0 + Active1 > 32767 -> 2520 error; 2521 Active1 =< 0 -> 2522 false; 2523 is_integer(Active0) -> 2524 Active0 + Active1; 2525 true -> 2526 Active1 2527 end, 2528 case Active of 2529 error -> 2530 {{error, {options, {socket_options, Opt}} }, SockOpts}; 2531 _ -> 2532 set_socket_opts(ConnectionCb, Transport, Socket, Opts, 2533 SockOpts#socket_options{active = Active}, Other) 2534 end; 2535set_socket_opts(_,_, _, [{active, _} = Opt| _], SockOpts, _) -> 2536 {{error, {options, {socket_options, Opt}} }, SockOpts}; 2537set_socket_opts(ConnectionCb, Transport, Socket, [Opt | Opts], SockOpts, Other) -> 2538 set_socket_opts(ConnectionCb, Transport, Socket, Opts, SockOpts, [Opt | Other]). 2539 2540 2541 2542hibernate_after(connection = StateName, 2543 #state{ssl_options=#ssl_options{hibernate_after = HibernateAfter}} = State, 2544 Actions) -> 2545 {next_state, StateName, State, [{timeout, HibernateAfter, hibernate} | Actions]}; 2546hibernate_after(StateName, State, Actions) -> 2547 {next_state, StateName, State, Actions}. 2548 2549map_extensions(#hello_extensions{renegotiation_info = RenegotiationInfo, 2550 signature_algs = SigAlg, 2551 alpn = Alpn, 2552 next_protocol_negotiation = Next, 2553 srp = SRP, 2554 ec_point_formats = ECPointFmt, 2555 elliptic_curves = ECCCurves, 2556 sni = SNI}) -> 2557 #{renegotiation_info => ssl_handshake:extension_value(RenegotiationInfo), 2558 signature_algs => ssl_handshake:extension_value(SigAlg), 2559 alpn => ssl_handshake:extension_value(Alpn), 2560 srp => ssl_handshake:extension_value(SRP), 2561 next_protocol => ssl_handshake:extension_value(Next), 2562 ec_point_formats => ssl_handshake:extension_value(ECPointFmt), 2563 elliptic_curves => ssl_handshake:extension_value(ECCCurves), 2564 sni => ssl_handshake:extension_value(SNI)}. 2565 2566terminate_alert(normal) -> 2567 ?ALERT_REC(?WARNING, ?CLOSE_NOTIFY); 2568terminate_alert({Reason, _}) when Reason == close; 2569 Reason == shutdown -> 2570 ?ALERT_REC(?WARNING, ?CLOSE_NOTIFY); 2571terminate_alert(_) -> 2572 ?ALERT_REC(?FATAL, ?INTERNAL_ERROR). 2573 2574handle_trusted_certs_db(#state{ssl_options = 2575 #ssl_options{cacertfile = <<>>, cacerts = []}}) -> 2576 %% No trusted certs specified 2577 ok; 2578handle_trusted_certs_db(#state{static_env = #static_env{cert_db_ref = Ref, 2579 cert_db = CertDb}, 2580 ssl_options = #ssl_options{cacertfile = <<>>}}) when CertDb =/= undefined -> 2581 %% Certs provided as DER directly can not be shared 2582 %% with other connections and it is safe to delete them when the connection ends. 2583 ssl_pkix_db:remove_trusted_certs(Ref, CertDb); 2584handle_trusted_certs_db(#state{static_env = #static_env{file_ref_db = undefined}}) -> 2585 %% Something went wrong early (typically cacertfile does not 2586 %% exist) so there is nothing to handle 2587 ok; 2588handle_trusted_certs_db(#state{static_env = #static_env{cert_db_ref = Ref, 2589 file_ref_db = RefDb}, 2590 ssl_options = #ssl_options{cacertfile = File}}) -> 2591 case ssl_pkix_db:ref_count(Ref, RefDb, -1) of 2592 0 -> 2593 ssl_manager:clean_cert_db(Ref, File); 2594 _ -> 2595 ok 2596 end. 2597 2598prepare_connection(#state{handshake_env = #handshake_env{renegotiation = Renegotiate}, 2599 start_or_recv_from = RecvFrom} = State0, Connection) 2600 when Renegotiate =/= {false, first}, 2601 RecvFrom =/= undefined -> 2602 State = Connection:reinit(State0), 2603 {no_record, ack_connection(State)}; 2604prepare_connection(State0, Connection) -> 2605 State = Connection:reinit(State0), 2606 {no_record, ack_connection(State)}. 2607 2608ack_connection(#state{handshake_env = #handshake_env{renegotiation = {true, Initiater}} = HsEnv} = State) when Initiater == peer; 2609 Initiater == internal -> 2610 State#state{handshake_env = HsEnv#handshake_env{renegotiation = undefined}}; 2611ack_connection(#state{handshake_env = #handshake_env{renegotiation = {true, From}} = HsEnv} = State) -> 2612 gen_statem:reply(From, ok), 2613 State#state{handshake_env = HsEnv#handshake_env{renegotiation = undefined}}; 2614ack_connection(#state{handshake_env = #handshake_env{renegotiation = {false, first}} = HsEnv, 2615 start_or_recv_from = StartFrom} = State) when StartFrom =/= undefined -> 2616 gen_statem:reply(StartFrom, connected), 2617 State#state{handshake_env = HsEnv#handshake_env{renegotiation = undefined}, 2618 start_or_recv_from = undefined}; 2619ack_connection(State) -> 2620 State. 2621 2622session_handle_params(#server_ecdh_params{curve = ECCurve}, Session) -> 2623 Session#session{ecc = ECCurve}; 2624session_handle_params(_, Session) -> 2625 Session. 2626 2627handle_session(Role = server, #ssl_options{reuse_sessions = true} = SslOpts, 2628 Host, Port, Session0) -> 2629 register_session(Role, host_id(Role, Host, SslOpts), Port, Session0, true); 2630handle_session(Role = client, #ssl_options{verify = verify_peer, 2631 reuse_sessions = Reuse} = SslOpts, 2632 Host, Port, Session0) when Reuse =/= false -> 2633 register_session(Role, host_id(Role, Host, SslOpts), Port, Session0, reg_type(Reuse)); 2634handle_session(server, _, Host, Port, Session) -> 2635 %% Remove "session of type new" entry from session DB 2636 ssl_manager:invalidate_session(Host, Port, Session), 2637 Session; 2638handle_session(client, _,_,_, Session) -> 2639 %% In client case there is no entry yet, so nothing to remove 2640 Session. 2641 2642reg_type(save) -> 2643 true; 2644reg_type(true) -> 2645 unique. 2646 2647register_session(client, Host, Port, #session{is_resumable = new} = Session0, Save) -> 2648 Session = Session0#session{is_resumable = true}, 2649 ssl_manager:register_session(Host, Port, Session, Save), 2650 Session; 2651register_session(server, _, Port, #session{is_resumable = new} = Session0, _) -> 2652 Session = Session0#session{is_resumable = true}, 2653 ssl_manager:register_session(Port, Session), 2654 Session; 2655register_session(_, _, _, Session, _) -> 2656 Session. %% Already registered 2657 2658host_id(client, _Host, #ssl_options{server_name_indication = Hostname}) when is_list(Hostname) -> 2659 Hostname; 2660host_id(_, Host, _) -> 2661 Host. 2662 2663handle_new_session(NewId, CipherSuite, Compression, 2664 #state{static_env = #static_env{protocol_cb = Connection}, 2665 session = Session0 2666 } = State0) -> 2667 Session = Session0#session{session_id = NewId, 2668 cipher_suite = CipherSuite, 2669 compression_method = Compression}, 2670 Connection:next_event(certify, no_record, State0#state{session = Session}). 2671 2672handle_resumed_session(SessId, #state{static_env = #static_env{host = Host, 2673 port = Port, 2674 protocol_cb = Connection, 2675 session_cache = Cache, 2676 session_cache_cb = CacheCb}, 2677 connection_env = #connection_env{negotiated_version = Version}, 2678 connection_states = ConnectionStates0} = State) -> 2679 Session = CacheCb:lookup(Cache, {{Host, Port}, SessId}), 2680 case ssl_handshake:master_secret(ssl:tls_version(Version), Session, 2681 ConnectionStates0, client) of 2682 {_, ConnectionStates} -> 2683 Connection:next_event(abbreviated, no_record, State#state{ 2684 connection_states = ConnectionStates, 2685 session = Session}); 2686 #alert{} = Alert -> 2687 handle_own_alert(Alert, Version, hello, State) 2688 end. 2689 2690make_premaster_secret({MajVer, MinVer}, rsa) -> 2691 Rand = ssl_cipher:random_bytes(?NUM_OF_PREMASTERSECRET_BYTES-2), 2692 <<?BYTE(MajVer), ?BYTE(MinVer), Rand/binary>>; 2693make_premaster_secret(_, _) -> 2694 undefined. 2695 2696negotiated_hashsign(undefined, KexAlg, PubKeyInfo, Version) -> 2697 %% Not negotiated choose default 2698 case is_anonymous(KexAlg) of 2699 true -> 2700 {null, anon}; 2701 false -> 2702 {PubAlg, _, _} = PubKeyInfo, 2703 ssl_handshake:select_hashsign_algs(undefined, PubAlg, Version) 2704 end; 2705negotiated_hashsign(HashSign = {_, _}, _, _, _) -> 2706 HashSign. 2707 2708ssl_options_list(SslOptions) -> 2709 Fileds = record_info(fields, ssl_options), 2710 Values = tl(tuple_to_list(SslOptions)), 2711 ssl_options_list(Fileds, Values, []). 2712 2713ssl_options_list([],[], Acc) -> 2714 lists:reverse(Acc); 2715%% Skip internal options, only return user options 2716ssl_options_list([protocol | Keys], [_ | Values], Acc) -> 2717 ssl_options_list(Keys, Values, Acc); 2718ssl_options_list([erl_dist | Keys], [_ | Values], Acc) -> 2719 ssl_options_list(Keys, Values, Acc); 2720ssl_options_list([renegotiate_at | Keys], [_ | Values], Acc) -> 2721 ssl_options_list(Keys, Values, Acc); 2722ssl_options_list([ciphers = Key | Keys], [Value | Values], Acc) -> 2723 ssl_options_list(Keys, Values, 2724 [{Key, lists:map( 2725 fun(Suite) -> 2726 ssl_cipher_format:suite_definition(Suite) 2727 end, Value)} 2728 | Acc]); 2729ssl_options_list([Key | Keys], [Value | Values], Acc) -> 2730 ssl_options_list(Keys, Values, [{Key, Value} | Acc]). 2731 2732handle_active_option(false, connection = StateName, To, Reply, State) -> 2733 hibernate_after(StateName, State, [{reply, To, Reply}]); 2734 2735handle_active_option(_, connection = StateName, To, _Reply, #state{connection_env = #connection_env{terminated = true}, 2736 user_data_buffer = {_,0,_}} = State) -> 2737 handle_normal_shutdown(?ALERT_REC(?FATAL, ?CLOSE_NOTIFY, all_data_deliverd), StateName, 2738 State#state{start_or_recv_from = To}), 2739 {stop,{shutdown, peer_close}, State}; 2740handle_active_option(_, connection = StateName0, To, Reply, #state{static_env = #static_env{protocol_cb = Connection}, 2741 user_data_buffer = {_,0,_}} = State0) -> 2742 case Connection:next_event(StateName0, no_record, State0) of 2743 {next_state, StateName, State} -> 2744 hibernate_after(StateName, State, [{reply, To, Reply}]); 2745 {next_state, StateName, State, Actions} -> 2746 hibernate_after(StateName, State, [{reply, To, Reply} | Actions]); 2747 {stop, _, _} = Stop -> 2748 Stop 2749 end; 2750handle_active_option(_, StateName, To, Reply, #state{user_data_buffer = {_,0,_}} = State) -> 2751 %% Active once already set 2752 {next_state, StateName, State, [{reply, To, Reply}]}; 2753 2754%% user_data_buffer nonempty 2755handle_active_option(_, StateName0, To, Reply, 2756 #state{static_env = #static_env{protocol_cb = Connection}} = State0) -> 2757 case read_application_data(<<>>, State0) of 2758 {stop, _, _} = Stop -> 2759 Stop; 2760 {Record, State1} -> 2761 %% Note: Renogotiation may cause StateName0 =/= StateName 2762 case Connection:next_event(StateName0, Record, State1) of 2763 {next_state, StateName, State} -> 2764 hibernate_after(StateName, State, [{reply, To, Reply}]); 2765 {next_state, StateName, State, Actions} -> 2766 hibernate_after(StateName, State, [{reply, To, Reply} | Actions]); 2767 {stop, _, _} = Stop -> 2768 Stop 2769 end 2770 end. 2771 2772 2773%% Picks ClientData 2774get_data(#socket_options{active=false}, undefined, _Bin) -> 2775 %% Recv timed out save buffer data until next recv 2776 passive; 2777get_data(#socket_options{active=Active, packet=Raw}, BytesToRead, Bin) 2778 when Raw =:= raw; Raw =:= 0 -> %% Raw Mode 2779 case Bin of 2780 <<_/binary>> when Active =/= false orelse BytesToRead =:= 0 -> 2781 %% Active true or once, or passive mode recv(0) 2782 {ok, Bin, <<>>}; 2783 <<Data:BytesToRead/binary, Rest/binary>> -> 2784 %% Passive Mode, recv(Bytes) 2785 {ok, Data, Rest}; 2786 <<_/binary>> -> 2787 %% Passive Mode not enough data 2788 {more, BytesToRead} 2789 end; 2790get_data(#socket_options{packet=Type, packet_size=Size}, _, Bin) -> 2791 PacketOpts = [{packet_size, Size}], 2792 decode_packet(Type, Bin, PacketOpts). 2793 2794decode_packet({http, headers}, Buffer, PacketOpts) -> 2795 decode_packet(httph, Buffer, PacketOpts); 2796decode_packet({http_bin, headers}, Buffer, PacketOpts) -> 2797 decode_packet(httph_bin, Buffer, PacketOpts); 2798decode_packet(Type, Buffer, PacketOpts) -> 2799 erlang:decode_packet(Type, Buffer, PacketOpts). 2800 2801%% Just like with gen_tcp sockets, an ssl socket that has been configured with 2802%% {packet, http} (or {packet, http_bin}) will automatically switch to expect 2803%% HTTP headers after it sees a HTTP Request or HTTP Response line. We 2804%% represent the current state as follows: 2805%% #socket_options.packet =:= http: Expect a HTTP Request/Response line 2806%% #socket_options.packet =:= {http, headers}: Expect HTTP Headers 2807%% Note that if the user has explicitly configured the socket to expect 2808%% HTTP headers using the {packet, httph} option, we don't do any automatic 2809%% switching of states. 2810deliver_app_data( 2811 CPids, Transport, Socket, 2812 #socket_options{active=Active, packet=Type} = SOpts, 2813 Data, Pid, From, Tracker, Connection) -> 2814 %% 2815 send_or_reply( 2816 Active, Pid, From, 2817 format_reply( 2818 CPids, Transport, Socket, SOpts, Data, Tracker, Connection)), 2819 SO = 2820 case Data of 2821 {P, _, _, _} 2822 when ((P =:= http_request) or (P =:= http_response)), 2823 ((Type =:= http) or (Type =:= http_bin)) -> 2824 SOpts#socket_options{packet={Type, headers}}; 2825 http_eoh when tuple_size(Type) =:= 2 -> 2826 %% End of headers - expect another Request/Response line 2827 {Type1, headers} = Type, 2828 SOpts#socket_options{packet=Type1}; 2829 _ -> 2830 SOpts 2831 end, 2832 case Active of 2833 once -> 2834 SO#socket_options{active=false}; 2835 1 -> 2836 send_user( 2837 Pid, 2838 format_passive( 2839 CPids, Transport, Socket, Tracker, Connection)), 2840 SO#socket_options{active=false}; 2841 N when is_integer(N) -> 2842 SO#socket_options{active=N - 1}; 2843 _ -> 2844 SO 2845 end. 2846 2847format_reply(_, _, _,#socket_options{active = false, mode = Mode, packet = Packet, 2848 header = Header}, Data, _, _) -> 2849 {ok, do_format_reply(Mode, Packet, Header, Data)}; 2850format_reply(CPids, Transport, Socket, #socket_options{active = _, mode = Mode, packet = Packet, 2851 header = Header}, Data, Tracker, Connection) -> 2852 {ssl, Connection:socket(CPids, Transport, Socket, Tracker), 2853 do_format_reply(Mode, Packet, Header, Data)}. 2854 2855deliver_packet_error(CPids, Transport, Socket, 2856 SO= #socket_options{active = Active}, Data, Pid, From, Tracker, Connection) -> 2857 send_or_reply(Active, Pid, From, format_packet_error(CPids, 2858 Transport, Socket, SO, Data, Tracker, Connection)). 2859 2860format_packet_error(_, _, _,#socket_options{active = false, mode = Mode}, Data, _, _) -> 2861 {error, {invalid_packet, do_format_reply(Mode, raw, 0, Data)}}; 2862format_packet_error(CPids, Transport, Socket, #socket_options{active = _, mode = Mode}, 2863 Data, Tracker, Connection) -> 2864 {ssl_error, Connection:socket(CPids, Transport, Socket, Tracker), 2865 {invalid_packet, do_format_reply(Mode, raw, 0, Data)}}. 2866 2867do_format_reply(binary, _, N, Data) when N > 0 -> % Header mode 2868 header(N, Data); 2869do_format_reply(binary, _, _, Data) -> 2870 Data; 2871do_format_reply(list, Packet, _, Data) 2872 when Packet == http; Packet == {http, headers}; 2873 Packet == http_bin; Packet == {http_bin, headers}; 2874 Packet == httph; Packet == httph_bin -> 2875 Data; 2876do_format_reply(list, _,_, Data) -> 2877 binary_to_list(Data). 2878 2879format_passive(CPids, Transport, Socket, Tracker, Connection) -> 2880 {ssl_passive, Connection:socket(CPids, Transport, Socket, Tracker)}. 2881 2882header(0, <<>>) -> 2883 <<>>; 2884header(_, <<>>) -> 2885 []; 2886header(0, Binary) -> 2887 Binary; 2888header(N, Binary) -> 2889 <<?BYTE(ByteN), NewBinary/binary>> = Binary, 2890 [ByteN | header(N-1, NewBinary)]. 2891 2892send_or_reply(false, _Pid, From, Data) when From =/= undefined -> 2893 gen_statem:reply(From, Data); 2894%% Can happen when handling own alert or tcp error/close and there is 2895%% no outstanding gen_fsm sync events 2896send_or_reply(false, no_pid, _, _) -> 2897 ok; 2898send_or_reply(_, Pid, _From, Data) -> 2899 send_user(Pid, Data). 2900 2901send_user(Pid, Msg) -> 2902 Pid ! Msg, 2903 ok. 2904 2905alert_user(Pids, Transport, Tracker, Socket, connection, Opts, Pid, From, Alert, Role, StateName, Connection) -> 2906 alert_user(Pids, Transport, Tracker, Socket, Opts#socket_options.active, Pid, From, Alert, Role, StateName, Connection); 2907alert_user(Pids, Transport, Tracker, Socket,_, _, _, From, Alert, Role, StateName, Connection) -> 2908 alert_user(Pids, Transport, Tracker, Socket, From, Alert, Role, StateName, Connection). 2909 2910alert_user(Pids, Transport, Tracker, Socket, From, Alert, Role, StateName, Connection) -> 2911 alert_user(Pids, Transport, Tracker, Socket, false, no_pid, From, Alert, Role, StateName, Connection). 2912 2913alert_user(_, _, _, _, false = Active, Pid, From, Alert, Role, StateName, Connection) when From =/= undefined -> 2914 %% If there is an outstanding ssl_accept | recv 2915 %% From will be defined and send_or_reply will 2916 %% send the appropriate error message. 2917 ReasonCode = ssl_alert:reason_code(Alert, Role, Connection:protocol_name(), StateName), 2918 send_or_reply(Active, Pid, From, {error, ReasonCode}); 2919alert_user(Pids, Transport, Tracker, Socket, Active, Pid, From, Alert, Role, StateName, Connection) -> 2920 case ssl_alert:reason_code(Alert, Role, Connection:protocol_name(), StateName) of 2921 closed -> 2922 send_or_reply(Active, Pid, From, 2923 {ssl_closed, Connection:socket(Pids, Transport, Socket, Tracker)}); 2924 ReasonCode -> 2925 send_or_reply(Active, Pid, From, 2926 {ssl_error, Connection:socket(Pids, Transport, Socket, Tracker), ReasonCode}) 2927 end. 2928 2929log_alert(true, Role, ProtocolName, StateName, #alert{role = Role} = Alert) -> 2930 Txt = ssl_alert:own_alert_txt(Alert), 2931 error_logger:info_report(ssl_alert:alert_txt(ProtocolName, Role, StateName, Txt)); 2932log_alert(true, Role, ProtocolName, StateName, Alert) -> 2933 Txt = ssl_alert:alert_txt(Alert), 2934 error_logger:info_report(ssl_alert:alert_txt(ProtocolName, Role, StateName, Txt)); 2935log_alert(false, _, _, _, _) -> 2936 ok. 2937 2938invalidate_session(client, Host, Port, Session) -> 2939 ssl_manager:invalidate_session(Host, Port, Session); 2940invalidate_session(server, _, Port, Session) -> 2941 ssl_manager:invalidate_session(Port, Session). 2942 2943handle_sni_extension(undefined, State) -> 2944 State; 2945handle_sni_extension(#sni{hostname = Hostname}, #state{static_env = #static_env{role = Role} = InitStatEnv0, 2946 handshake_env = HsEnv, 2947 connection_env = CEnv} = State0) -> 2948 NewOptions = update_ssl_options_from_sni(State0#state.ssl_options, Hostname), 2949 case NewOptions of 2950 undefined -> 2951 State0; 2952 _ -> 2953 {ok, #{cert_db_ref := Ref, 2954 cert_db_handle := CertDbHandle, 2955 fileref_db_handle := FileRefHandle, 2956 session_cache := CacheHandle, 2957 crl_db_info := CRLDbHandle, 2958 private_key := Key, 2959 dh_params := DHParams, 2960 own_certificate := OwnCert}} = 2961 ssl_config:init(NewOptions, Role), 2962 State0#state{ 2963 session = State0#state.session#session{own_certificate = OwnCert}, 2964 static_env = InitStatEnv0#static_env{ 2965 file_ref_db = FileRefHandle, 2966 cert_db_ref = Ref, 2967 cert_db = CertDbHandle, 2968 crl_db = CRLDbHandle, 2969 session_cache = CacheHandle 2970 }, 2971 connection_env = CEnv#connection_env{private_key = Key}, 2972 ssl_options = NewOptions, 2973 handshake_env = HsEnv#handshake_env{sni_hostname = Hostname, 2974 diffie_hellman_params = DHParams} 2975 } 2976 end. 2977 2978update_ssl_options_from_sni(OrigSSLOptions, SNIHostname) -> 2979 SSLOption = 2980 case OrigSSLOptions#ssl_options.sni_fun of 2981 undefined -> 2982 proplists:get_value(SNIHostname, 2983 OrigSSLOptions#ssl_options.sni_hosts); 2984 SNIFun -> 2985 SNIFun(SNIHostname) 2986 end, 2987 case SSLOption of 2988 undefined -> 2989 undefined; 2990 _ -> 2991 ssl:handle_options(SSLOption, OrigSSLOptions) 2992 end. 2993 2994new_emulated([], EmOpts) -> 2995 EmOpts; 2996new_emulated(NewEmOpts, _) -> 2997 NewEmOpts. 2998