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