1%%
2%% %CopyrightBegin%
3%%
4%% Copyright Ericsson AB 2008-2020. All Rights Reserved.
5%%
6%% Licensed under the Apache License, Version 2.0 (the "License");
7%% you may not use this file except in compliance with the License.
8%% You may obtain a copy of the License at
9%%
10%%     http://www.apache.org/licenses/LICENSE-2.0
11%%
12%% Unless required by applicable law or agreed to in writing, software
13%% distributed under the License is distributed on an "AS IS" BASIS,
14%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15%% See the License for the specific language governing permissions and
16%% limitations under the License.
17%%
18%% %CopyrightEnd%
19%%
20
21%%
22-module(ssl_test_lib).
23
24-behaviour(ct_suite).
25
26-include_lib("common_test/include/ct.hrl").
27-include_lib("public_key/include/public_key.hrl").
28-include_lib("ssl/src/tls_handshake_1_3.hrl").
29
30-export([clean_start/0,
31         clean_start/1,
32         clean_env/0,
33         init_per_group/2,
34         init_per_group_openssl/2,
35         end_per_group/2,
36         ct_log_supported_protocol_versions/1,
37         ssl_options/2,
38         run_where/1,
39         run_where/2,
40         inet_port/1,
41         default_tls_version/1,
42         check_sane_openssl_renegotiate/2,
43         check_openssl_npn_support/1,
44         start_server/1,
45         start_server/2,
46         start_client/1,
47         start_client/2,
48         start_server/3,
49         start_client/3,
50         start_client/4,
51         start_upgrade_server/1,
52         start_upgrade_server_error/1,
53         start_upgrade_client/1,
54         start_client_error/1,
55         start_server_error/1,
56         start_server_transport_abuse_socket/1,
57         start_server_transport_control/1,
58         start_server_with_raw_key/3,
59         start_openssl_client/2,
60         run_server/1,
61         run_server/3,
62         run_server_error/1,
63         ecc_test/6,
64         ecc_test_error/5,
65         transport_accept_abuse/1,
66         transport_switch_control/1,
67         init_openssl_server/3,
68         init_openssl_client/1,
69         run_client_init/1,
70         run_upgrade_server/1,
71         run_upgrade_client/1,
72         run_upgrade_server_error/1,
73         run_client_error/1,
74         send_recv_result_active/3,
75         wait_for_result/2,
76         wait_for_result/4,
77         wait_for_openssl_server/2,
78         send_recv_result/1,
79         send_recv_result_active/1,
80         send_recv_result_active/2,
81         send_recv_result_active_once/1,
82         active_recv/2,
83         active_recv_loop/3,
84         active_once_recv/2,
85         recv_disregard/2,
86         active_disregard/2,
87         active_once_disregard/2,
88         send/2,
89         close/1,
90         close/2,
91         check_active_receive/2,
92         check_client_alert/2,
93         check_client_alert/3,
94         check_server_alert/2,
95         check_server_alert/3,
96         check_tickets/1,
97         check_ecc/3,
98         check_key_exchange_send_active/2,
99         verify_active_session_resumption/2,
100         verify_active_session_resumption/3,
101         verify_active_session_resumption/4,
102         verify_active_session_resumption/5,
103         verify_server_early_data/3,
104         verify_session_ticket_extension/2,
105         update_session_ticket_extension/2,
106         check_sane_openssl_version/1,
107         check_ok/1,
108         check_result/4,
109         check_result/2,
110         gen_check_result/4,
111         basic_alert/4,
112         session_id/1,
113         update_keys/2,
114         sanity_check/2,
115         oscp_responder/6,
116         supported_eccs/1,
117         no_result/1,
118         receive_tickets/1,
119         set_protocol_versions/1,
120         user_lookup/3,
121         digest/0,
122         accepters/1,
123         client_msg/2,
124         server_msg/2,
125         hardcode_rsa_key/1,
126         bigger_buffers/0,
127         stop/2,
128         working_openssl_client/0
129        ]).
130
131-export([basic_test/3,
132         erlang_ssl_receive_and_assert_negotiated_protocol/3,
133         cipher_result/2,
134         assert_mfl/2,
135         trigger_renegotiate/4,
136         trigger_renegotiate/2,
137         session_info_result/1,
138         reuse_session/3,
139         test_ciphers/3,
140         test_cipher/2,
141         openssl_ciphers/0,
142         openssl_support_rsa_kex/0
143        ]).
144
145-export([tls_version/1,
146         is_protocol_version/1,
147         is_dtls_version/1,
148         protocol_version/1,
149         protocol_version/2,
150         protocol_options/2,
151         public_key/1,
152         state/1,
153         new_config/2,
154         node_to_hostip/2
155       ]).
156
157-export([make_rsa_cert/1,
158         make_dsa_cert/1,
159         make_ecdsa_cert/1,
160         make_ecdh_rsa_cert/1,
161         make_rsa_ecdsa_cert/2,
162         make_rsa_cert_chains/3,
163         make_dsa_cert_chains/3,
164         make_ecc_cert_chains/3,
165         make_cert_chains_der/2,
166         make_cert_chains_pem/4,
167         make_ec_cert_chains/4,
168         make_ec_cert_chains/5,
169         make_rsa_1024_cert/1,
170         make_rsa_pss_pem/4,
171         gen_conf/4,
172         make_mix_cert/1,
173         default_cert_chain_conf/0,
174         cert_options/1,
175         rsa_non_signed_suites/1,
176         ecdh_dh_anonymous_suites/1,
177         ecdsa_suites/1,
178         der_to_pem/2,
179         pem_to_der/1,
180         appropriate_sha/1,
181         format_certs/1,
182         format_cert/1
183        ]).
184
185-export([maybe_force_ipv4/1,
186         openssl_sane_dtls/0,
187         kill_openssl/0,
188         openssl_allows_server_renegotiate/1,
189         openssl_dtls_maxfraglen_support/0,
190         openssl_maxfraglen_support/0,
191         is_sane_oppenssl_pss/1,
192         consume_port_exit/1,
193         is_sane_oppenssl_client/0,
194         openssl_sane_dtls_session_reuse/0,
195         sufficient_crypto_support/1,
196         openssl_sane_dtls_alpn/0,
197         openssl_ecdsa_suites/0,
198         openssl_dsa_suites/0,
199         enough_openssl_crl_support/1,
200         openssl_ocsp_support/0,
201         openssl_allows_client_renegotiate/1,
202         version_flag/1,
203         portable_cmd/2,
204         portable_open_port/2,
205         close_port/1,
206         verify_early_data/1
207        ]).
208
209-record(sslsocket, { fd = nil, pid = nil}).
210-define(SLEEP, 1000).
211-define(DEFAULT_CURVE, secp256r1).
212-define(PRINT_DEPTH, 100).
213
214%%====================================================================
215%% API
216%%====================================================================
217start_client(erlang, Options, Config) ->
218    start_client(Options, Config);
219start_client(openssl, Options, Config) ->
220    start_openssl_client(Options, Config);
221start_client(Type, _Args, _Config) ->
222    {error, unsupported_client_type, Type}.
223
224start_server(erlang, Options, Config) ->
225    start_server(Options, Config);
226start_server(openssl, Options, Config) ->
227    start_openssl_server(openssl, Options, Config);
228start_server(openssl_ocsp, Options, Config) ->
229    start_openssl_server(openssl_ocsp, Options, Config);
230start_server(openssl_ocsp_revoked, Options, Config) ->
231    start_openssl_server(openssl_ocsp_revoked, Options, Config);
232start_server(Type, _Args, _Config) ->
233    {error, unsupported_server_type, Type}.
234
235
236%% Test
237send_recv_result_active(Peer1, Peer2, Data) ->
238    ok = send(Peer1, Data),
239    Data = check_active_receive(Peer2, Data),
240    ok = send(Peer2, Data),
241    Data = check_active_receive(Peer1, Data).
242
243
244%% Options
245get_server_opts(Config) ->
246    get_server_opts(openssl, Config).
247    %% DSOpts = proplists:get_value(server_ecdsa_opts, Config),
248    %% SOpts = proplists:get_value(server_opts, Config, DSOpts),
249    %% ssl_test_lib:ssl_options(SOpts, Config).
250%%
251get_server_opts(openssl, Config) ->
252    DSOpts = proplists:get_value(server_ecdsa_opts, Config),
253    SOpts = proplists:get_value(server_opts, Config, DSOpts),
254    ssl_options(SOpts, Config);
255get_server_opts(openssl_ocsp, Config) ->
256    PrivDir = proplists:get_value(priv_dir, Config),
257    Cert = filename:join(PrivDir, "a.server/cert.pem"),
258    Key = filename:join(PrivDir, "a.server/key.pem"),
259    CACerts = filename:join(PrivDir, "a.server/cacerts.pem"),
260    SOpts = [{reuseaddr, true},
261             {cacertfile, CACerts},
262             {certfile, Cert},
263             {keyfile, Key}],
264    ssl_options(SOpts, Config);
265get_server_opts(openssl_ocsp_revoked, Config) ->
266    PrivDir = proplists:get_value(priv_dir, Config),
267    Cert = filename:join(PrivDir, "revoked/cert.pem"),
268    Key = filename:join(PrivDir, "revoked/key.pem"),
269    CACerts = filename:join(PrivDir, "revoked/cacerts.pem"),
270    SOpts = [{reuseaddr, true},
271             {cacertfile, CACerts},
272             {certfile, Cert},
273             {keyfile, Key}],
274    ssl_options(SOpts, Config).
275
276
277get_client_opts(Config) ->
278    DCOpts = proplists:get_value(client_ecdsa_opts, Config),
279    COpts = proplists:get_value(client_opts, Config, DCOpts),
280    ssl_options(COpts, Config).
281
282%% Default callback functions
283init_per_group(GroupName, Config0) ->
284    case is_protocol_version(GroupName) andalso sufficient_crypto_support(GroupName) of
285	true ->
286            Config = clean_protocol_version(Config0),
287	    [{version, GroupName}|init_protocol_version(GroupName, Config)];
288	_ ->
289	    case sufficient_crypto_support(GroupName) of
290		true ->
291		    ssl:start(),
292		    Config0;
293		false ->
294		    {skip, "Missing crypto support"}
295	    end
296    end.
297
298working_openssl_client() ->
299    case portable_cmd("openssl", ["version"]) of
300        %% Theses versions of OpenSSL has a client that
301        %% can not handle hello extensions. And will
302        %% fail with bad packet length if they are present
303        %% in ServerHello
304        "OpenSSL 0.9.8h" ++ _ ->
305            false;
306        "OpenSSL 0.9.8k" ++ _ ->
307            false;
308        _  ->
309            true
310    end.
311
312init_per_group_openssl(GroupName, Config0) ->
313    case is_tls_version(GroupName) andalso sufficient_crypto_support(GroupName) of
314	true ->
315            Config = clean_protocol_version(Config0),
316	    case openssl_tls_version_support(GroupName, Config)
317            of
318		true ->
319		    [{version, GroupName}|init_protocol_version(GroupName, Config)];
320		false ->
321		    {skip, "Missing openssl support"}
322	    end;
323	_ ->
324            case sufficient_crypto_support(GroupName) of
325		true ->
326		    ssl:start(),
327		    Config0;
328		false ->
329		    {skip, "Missing crypto support"}
330	    end
331    end.
332
333end_per_group(GroupName, Config) ->
334  case is_tls_version(GroupName) of
335      true ->
336          clean_protocol_version(Config);
337      false ->
338          Config
339  end.
340
341openssl_ocsp_support() ->
342    case portable_cmd("openssl", ["version"]) of
343        "OpenSSL 1.1.1" ++ _Rest ->
344            true;
345        _ ->
346            false
347    end.
348
349openssl_ciphers() ->
350    Str = portable_cmd("openssl", ["ciphers"]),
351    Ciphers = string:split(string:strip(Str, right, $\n), ":", all),
352    case portable_cmd("openssl", ["version"]) of
353	"LibreSSL 3." ++ _ ->
354            Ciphers -- ["DES-CBC3-SHA","AES128-SHA", "AES256-SHA", "RC4-SHA", "RC4-MD5"];
355        _ ->
356            Ciphers
357    end.
358
359openssl_support_rsa_kex() ->
360    case portable_cmd("openssl", ["version"]) of
361        "OpenSSL 1.1.1" ++ _Rest ->
362            false;
363        _ ->
364            true
365    end.
366
367%%====================================================================
368%% Internal functions
369%%====================================================================
370
371%% For now always run locally
372run_where(_) ->
373    ClientNode = node(),
374    ServerNode = node(),
375    Host = rpc:call(ServerNode, net_adm, localhost, []),
376    {ClientNode, ServerNode, Host}.
377
378run_where(_, ipv6) ->
379    ClientNode = node(),
380    ServerNode = node(),
381    Host = rpc:call(ServerNode, net_adm, localhost, []),
382    {ClientNode, ServerNode, Host}.
383
384node_to_hostip(Node, Role) ->
385    [_ , Host] = string:tokens(atom_to_list(Node), "@"),
386    {ok, Address} = inet:getaddr(Host, inet),
387    %% Convert client addresses in 127.0.0.0/24 subnet to the atom 'localhost'.
388    %% This is a workaround for testcase problems caused by the fact that
389    %% inet:peername/1 and inet:getaddr/2 return different addresses when
390    %% running on localhost.
391    normalize_loopback(Address, Role).
392
393normalize_loopback({127,_,_,_}, client) ->
394    localhost;
395normalize_loopback(Address, _) ->
396    Address.
397
398
399start_server(Args0, Config) ->
400    {_, ServerNode, _} = run_where(Config),
401    ServerOpts = get_server_opts(Config),
402    Node = proplists:get_value(node, Args0, ServerNode),
403    Port = proplists:get_value(port, Args0, 0),
404    Args = [{from, self()},
405            {node, Node},
406            {port, Port},
407            {options, ServerOpts} | Args0],
408    start_server(Args).
409%%
410start_server(Args) ->
411    Node = proplists:get_value(node, Args),
412    Result = spawn_link(Node, ?MODULE, run_server, [Args]),
413    receive
414	{listen, up} ->
415	    Result;
416        {error, Error} ->
417            Error
418    end.
419
420run_server(Opts) ->
421    Port = proplists:get_value(port, Opts),
422    Options = proplists:get_value(options, Opts),
423    Pid = proplists:get_value(from, Opts),
424    Transport =  proplists:get_value(transport, Opts, ssl),
425    ct:log("~p:~p~nssl:listen(~p, ~p)~n", [?MODULE,?LINE, Port, format_options(Options)]),
426    %% {ok, ListenSocket} = Transport:listen(Port, Options),
427    case Transport:listen(Port, Options) of
428        {ok, ListenSocket} ->
429            Pid ! {listen, up},
430            send_selected_port(Pid, Port, ListenSocket),
431            run_server(ListenSocket, Opts);
432        Error ->
433            Pid ! Error
434    end.
435
436run_server(ListenSocket, Opts) ->
437    Accepters = proplists:get_value(accepters, Opts, 1),
438    run_server(ListenSocket, Opts, Accepters).
439
440run_server(ListenSocket, Opts, 1) ->
441    do_run_server(ListenSocket, connect(ListenSocket, Opts), Opts);
442run_server(ListenSocket, Opts, N) ->
443    Pid = proplists:get_value(from, Opts),
444    Server = spawn(?MODULE, run_server, [ListenSocket, Opts, 1]),
445    Pid ! {accepter, N, Server},
446    run_server(ListenSocket, Opts, N-1).
447
448do_run_server(_, {error, _} = Result, Opts)  ->
449    ct:log("Server error result ~p~n", [Result]),
450    Pid = proplists:get_value(from, Opts),
451    Pid ! {self(), Result};
452do_run_server(_, ok = Result, Opts) ->
453    ct:log("Server cancel result ~p~n", [Result]),
454    Pid = proplists:get_value(from, Opts),
455    Pid ! {self(), Result};
456do_run_server(ListenSocket, AcceptSocket, Opts) ->
457    Pid = proplists:get_value(from, Opts),
458    Transport = proplists:get_value(transport, Opts, ssl),
459    MFA = proplists:get_value(mfa, Opts),
460    case server_apply_mfa(AcceptSocket, MFA) of
461	no_result_msg ->
462	    ok;
463	Msg ->
464	    ct:log("~p:~p~nServer Msg: ~p ~n", [?MODULE,?LINE, Msg]),
465	    Pid ! {self(), Msg}
466    end,
467    do_run_server_core(ListenSocket, AcceptSocket, Opts, Transport, Pid).
468
469server_apply_mfa(_, undefined) ->
470    no_result_msg;
471server_apply_mfa(AcceptSocket, {Module, Function, Args}) ->
472    ct:log("~p:~p~nServer: apply(~p,~p,~p)~n",
473           [?MODULE,?LINE, Module, Function, [AcceptSocket | Args]]),
474    apply(Module, Function, [AcceptSocket | Args]).
475
476client_apply_mfa(_, undefined) ->
477    no_result_msg;
478client_apply_mfa(AcceptSocket, {Module, Function, Args}) ->
479    ct:log("~p:~p~nClient: apply(~p,~p,~p)~n",
480           [?MODULE,?LINE, Module, Function, [AcceptSocket | Args]]),
481    apply(Module, Function, [AcceptSocket | Args]).
482
483
484do_run_server_core(ListenSocket, AcceptSocket, Opts, Transport, Pid) ->
485    receive
486        {data, Data} ->
487            ct:log("[server] Send: ~p~n", [Data]),
488            case Transport:send(AcceptSocket, Data) of
489                ok ->
490                    Pid ! {self(), ok};
491                {error, Reason} ->
492                    Pid ! {self(), Reason}
493            end,
494            do_run_server_core(ListenSocket, AcceptSocket, Opts, Transport, Pid);
495        {active_receive, Data} ->
496            case active_recv(AcceptSocket, length(Data)) of
497                ReceivedData ->
498                    ct:log("[server] Received: ~p~n", [Data]),
499                    Pid ! {self(), ReceivedData}
500            end,
501            do_run_server_core(ListenSocket, AcceptSocket, Opts, Transport, Pid);
502        {update_keys, Type} ->
503            case ssl:update_keys(AcceptSocket, Type) of
504                ok ->
505                    ct:log("[server] Update keys: ~p", [Type]),
506                    Pid ! {self(), ok};
507                {error, Reason} ->
508                    ct:log("[server] Update keys failed: ~p", [Type]),
509                    Pid ! {self(), Reason}
510            end,
511            do_run_server_core(ListenSocket, AcceptSocket, Opts, Transport, Pid);
512        get_socket ->
513            Pid ! {self(), {socket, AcceptSocket}},
514            do_run_server_core(ListenSocket, AcceptSocket, Opts, Transport, Pid);
515	listen ->
516	    run_server(ListenSocket, Opts);
517	{listen, MFA} ->
518	    run_server(ListenSocket, [MFA | proplists:delete(mfa, Opts)]);
519	close ->
520	    ct:log("~p:~p~nServer closing  ~p ~n", [?MODULE,?LINE, self()]),
521	    Result = Transport:close(AcceptSocket),
522	    Result1 = Transport:close(ListenSocket),
523	    ct:log("~p:~p~nResult ~p : ~p ~n", [?MODULE,?LINE, Result, Result1])
524    end.
525
526%%% To enable to test with s_client -reconnect
527connect(#sslsocket{} = ListenSocket, Opts) ->
528    Node = proplists:get_value(node, Opts),
529    ReconnectTimes =  proplists:get_value(reconnect_times, Opts, 0),
530    Timeout = proplists:get_value(timeout, Opts, infinity),
531    SslOpts = proplists:get_value(ssl_extra_opts, Opts, []),
532    ContOpts = proplists:get_value(continue_options, Opts, []),
533    AcceptSocket = connect(ListenSocket, Node, 1 + ReconnectTimes, dummy, Timeout, SslOpts, ContOpts),
534    case ReconnectTimes of
535	0 ->
536	    AcceptSocket;
537	_ ->
538	  remove_close_msg(ReconnectTimes),
539	  AcceptSocket
540    end;
541connect(ListenSocket, _Opts) ->
542    ct:log("~p:~p~ngen_tcp:accept(~p)~n", [?MODULE,?LINE, ListenSocket]),
543    {ok, AcceptSocket} = gen_tcp:accept(ListenSocket),
544    AcceptSocket.
545
546connect(_, _, 0, AcceptSocket, _, _, _) ->
547    AcceptSocket;
548connect(ListenSocket, Node, _N, _, Timeout, SslOpts, cancel) ->
549    ct:log("ssl:transport_accept(~P)~n", [ListenSocket, ?PRINT_DEPTH]),
550    {ok, AcceptSocket} = ssl:transport_accept(ListenSocket),
551    ct:log("~p:~p~nssl:handshake(~p,~p,~p)~n", [?MODULE,?LINE, AcceptSocket, format_options(SslOpts),Timeout]),
552
553    case ssl:handshake(AcceptSocket, SslOpts, Timeout) of
554	{ok, Socket0, Ext} ->
555            ct:log("Ext ~p:~n", [Ext]),
556            ct:log("~p:~p~nssl:handshake_cancel(~p)~n", [?MODULE,?LINE, Socket0]),
557            ssl:handshake_cancel(Socket0);
558        Result ->
559	    ct:log("~p:~p~nssl:handshake@~p ret ~p",[?MODULE,?LINE, Node,Result]),
560	    Result
561    end;
562connect(ListenSocket, Node, N, _, Timeout, SslOpts, [_|_] =ContOpts0) ->
563    ct:log("ssl:transport_accept(~P)~n", [ListenSocket, ?PRINT_DEPTH]),
564    {ok, AcceptSocket} = ssl:transport_accept(ListenSocket),
565    ct:log("~p:~p~nssl:handshake(~p,~p,~p)~n", [?MODULE,?LINE, AcceptSocket, SslOpts,Timeout]),
566
567    case ssl:handshake(AcceptSocket, SslOpts, Timeout) of
568	{ok, Socket0, Ext} ->
569            [_|_] = maps:get(sni, Ext),
570            ct:log("Ext ~p:~n", [Ext]),
571            ContOpts = case lists:keytake(want_ext, 1, ContOpts0) of
572                           {value, {_, WantExt}, ContOpts1} ->
573                               if is_pid(WantExt) ->
574                                       WantExt ! {self(), {ext, Ext}};
575                                  true ->
576                                       ignore
577                               end,
578                               ContOpts1;
579                           _ ->
580                               ContOpts0
581                       end,
582            ct:log("~p:~p~nssl:handshake_continue(~p,~p,~p)~n", [?MODULE,?LINE, Socket0, ContOpts,Timeout]),
583            case ssl:handshake_continue(Socket0, ContOpts, Timeout) of
584                {ok, Socket} ->
585                    connect(ListenSocket, Node, N-1, Socket, Timeout, SslOpts, ContOpts0);
586                Error ->
587                    ct:log("~p:~p~nssl:handshake_continue@~p ret ~p",[?MODULE,?LINE, Node,Error]),
588                    Error
589            end;
590	Result ->
591	    ct:log("~p:~p~nssl:handshake@~p ret ~p",[?MODULE,?LINE, Node,Result]),
592	    Result
593    end;
594connect(ListenSocket, Node, N, _, Timeout, [], ContOpts) ->
595    ct:log("ssl:transport_accept(~P)~n", [ListenSocket, ?PRINT_DEPTH]),
596    {ok, AcceptSocket} = ssl:transport_accept(ListenSocket),
597    ct:log("~p:~p~nssl:ssl_accept(~p, ~p)~n", [?MODULE,?LINE, AcceptSocket, Timeout]),
598
599    case ssl:handshake(AcceptSocket, Timeout) of
600	{ok, Socket} ->
601	    connect(ListenSocket, Node, N-1, Socket, Timeout, [], ContOpts);
602	Result ->
603	    ct:log("~p:~p~nssl:handshake@~p ret ~p",[?MODULE,?LINE, Node,Result]),
604	    Result
605    end;
606connect(ListenSocket, _Node, _, _, Timeout, Opts, _) ->
607    ct:log("ssl:transport_accept(~P)~n", [ListenSocket, ?PRINT_DEPTH]),
608    {ok, AcceptSocket} = ssl:transport_accept(ListenSocket),
609    ct:log("ssl:handshake(~p,~p, ~p)~n", [AcceptSocket, Opts, Timeout]),
610    ssl:handshake(AcceptSocket, Opts, Timeout),
611    AcceptSocket.
612
613
614start_server_transport_abuse_socket(Args) ->
615    Node = proplists:get_value(node, Args),
616    Result = spawn_link(Node, ?MODULE, transport_accept_abuse, [Args]),
617    receive
618	{listen, up} ->
619	    Result
620    end.
621
622start_server_transport_control(Args) ->
623    Node = proplists:get_value(node, Args),
624    Result = spawn_link(Node, ?MODULE, transport_switch_control, [Args]),
625    receive
626	{listen, up} ->
627	    Result
628    end.
629
630transport_accept_abuse(Opts) ->
631    Port = proplists:get_value(port, Opts),
632    Options = proplists:get_value(options, Opts),
633    Pid = proplists:get_value(from, Opts),
634    Transport =  proplists:get_value(transport, Opts, ssl),
635    ct:log("~p:~p~nssl:listen(~p, ~p)~n", [?MODULE,?LINE, Port, Options]),
636    {ok, ListenSocket} = Transport:listen(Port, Options),
637    Pid ! {listen, up},
638    send_selected_port(Pid, Port, ListenSocket),
639    {ok, AcceptSocket} = ssl:transport_accept(ListenSocket),
640    {error, _} = ssl:connection_information(AcceptSocket),
641    _ = ssl:handshake(AcceptSocket, infinity),
642    Pid ! {self(), ok}.
643
644transport_switch_control(Opts) ->
645    Port = proplists:get_value(port, Opts),
646    Options = proplists:get_value(options, Opts),
647    Pid = proplists:get_value(from, Opts),
648    Transport =  proplists:get_value(transport, Opts, ssl),
649    ct:log("~p:~p~nssl:listen(~p, ~p)~n", [?MODULE,?LINE, Port, Options]),
650    {ok, ListenSocket} = Transport:listen(Port, Options),
651    Pid ! {listen, up},
652    send_selected_port(Pid, Port, ListenSocket),
653    {ok, AcceptSocket} = ssl:transport_accept(ListenSocket),
654    ok = ssl:controlling_process(AcceptSocket, self()),
655    Pid ! {self(), ok}.
656
657
658remove_close_msg(0) ->
659    ok;
660remove_close_msg(ReconnectTimes) ->
661    receive
662	{ssl_closed, _} ->
663	   remove_close_msg(ReconnectTimes -1)
664    end.
665
666
667start_openssl_server(Mode, Args0, Config) ->
668    {_, ServerNode, _} = run_where(Config),
669    ServerOpts = get_server_opts(Mode, Config),
670    Node = proplists:get_value(node, Args0, ServerNode),
671    Port = proplists:get_value(port, Args0, 0),
672    ResponderPort = proplists:get_value(responder_port, Config, 0),
673    PrivDir = proplists:get_value(priv_dir, Config),
674    Args = [{from, self()}, {port, Port}] ++ ServerOpts ++ Args0 ++ [{priv_dir, PrivDir}],
675    Result = spawn_link(Node, ?MODULE, init_openssl_server,
676                        [Mode, ResponderPort,lists:delete(return_port, Args)]),
677    receive
678	{started, OpenSSLPort} ->
679	    case lists:member(return_port, Args) of
680		true -> {Result, OpenSSLPort};
681		false -> Result
682	    end;
683	{start_failed, Reason} ->
684	    {start_failed, Reason}
685    end.
686
687init_openssl_server(openssl, _, Options) ->
688    DefaultVersions = default_tls_version(Options),
689    [Version | _] = proplists:get_value(versions, Options, DefaultVersions),
690    Port = inet_port(node()),
691    Pid = proplists:get_value(from, Options),
692
693    Exe = "openssl",
694    Ciphers = proplists:get_value(ciphers, Options, default_ciphers(Version)),
695    Groups0 = proplists:get_value(groups, Options),
696    EarlyData = proplists:get_value(early_data, Options, undefined),
697    PrivDir = proplists:get_value(priv_dir, Options),
698    CertArgs = openssl_cert_options(Options, server),
699    AlpnArgs = openssl_alpn_options(proplists:get_value(alpn, Options, undefined)),
700    NpnArgs =  openssl_npn_options(proplists:get_value(np, Options, undefined)),
701    Debug = openssl_debug_options(PrivDir),
702
703    Args0 =  case Groups0 of
704                undefined ->
705                    ["s_server", "-accept", integer_to_list(Port), cipher_flag(Version),
706                     ciphers(Ciphers, Version),
707                     version_flag(Version)] ++ AlpnArgs ++ NpnArgs ++ CertArgs ++ Debug;
708                Group ->
709                       ["s_server", "-accept", integer_to_list(Port), cipher_flag(Version),
710                        ciphers(Ciphers, Version), "-groups", Group,
711                        version_flag(Version)] ++ AlpnArgs ++ NpnArgs ++ CertArgs ++ Debug
712            end,
713    Args1 = case EarlyData of
714               undefined ->
715                   Args0;
716               MaxSize ->
717                   Args0 ++ ["-early_data", "-no_anti_replay", "-max_early_data",
718                             integer_to_list(MaxSize)]
719           end,
720    Args = maybe_force_ipv4(Args1),
721    SslPort = portable_open_port(Exe, Args),
722    wait_for_openssl_server(Port, proplists:get_value(protocol, Options, tls)),
723    Pid ! {started, SslPort},
724    Pid ! {self(), {port, Port}},
725    openssl_server_loop(Pid, SslPort, Args);
726
727init_openssl_server(Mode, ResponderPort, Options) when Mode == openssl_ocsp orelse
728                                                       Mode == openssl_ocsp_revoked ->
729    DefaultVersions = default_tls_version(Options),
730    [Version | _] = proplists:get_value(versions, Options, DefaultVersions),
731    Port = inet_port(node()),
732    Pid = proplists:get_value(from, Options),
733    GroupName = proplists:get_value(group, Options),
734
735    Exe = "openssl",
736    Ciphers = proplists:get_value(ciphers, Options, ssl:cipher_suites(default,Version)),
737    CertArgs = openssl_cert_options(Options, server),
738    Exe = "openssl",
739
740    Args = ["s_server", "-accept", integer_to_list(Port), cipher_flag(Version),
741            ciphers(Ciphers, Version),
742            "-status_verbose",
743            "-status_url",
744            "http://127.0.0.1:" ++ erlang:integer_to_list(ResponderPort),
745            version_flag(Version)] ++ CertArgs ++ ["-msg", "-debug"]
746            ++ openssl_dtls_opt(GroupName),
747
748    SslPort = portable_open_port(Exe, Args),
749    wait_for_openssl_server(Port, proplists:get_value(protocol, Options, tls)),
750    Pid ! {started, Port},
751    Pid ! {self(), {port, Port}},
752    openssl_server_loop(Pid, SslPort, Args).
753
754oscp_responder(Port, Index, CACerts, Cert, Key, Starter) ->
755    Args = ["ocsp", "-index", Index, "-CA", CACerts, "-rsigner", Cert,
756            "-rkey", Key, "-port",  erlang:integer_to_list(Port)],
757    Responder = portable_open_port("openssl", Args),
758    wait_for_openssl_server(Port, tls),
759
760    openssl_server_loop(Starter, Responder, []).
761
762
763openssl_dtls_opt('dtlsv1.2') ->
764    ["-dtls"];
765openssl_dtls_opt(_Other) ->
766    [].
767
768openssl_server_loop(Pid, SslPort, Args) ->
769    receive
770        {data, Data} ->
771            case port_command(SslPort, Data, [nosuspend]) of
772                true ->
773                    ct:log("(~p) [openssl server] Send data: ~p~n",
774                           [self(), Data]),
775                    Pid ! {self(), ok};
776                _Else ->
777                    ct:log("(~p) [openssl server] Send failed, data: ~p~n",
778                           [self(), Data]),
779                    Pid ! {self(), {error, port_command_failed}}
780            end,
781            openssl_server_loop(Pid, SslPort, Args);
782        {active_receive, Data} ->
783            case active_recv(SslPort, length(Data)) of
784                ReceivedData ->
785                    ct:log("(~p) [openssl server] Received: ~p~n", [self(), Data]),
786                    Pid ! {self(), ReceivedData}
787            end,
788            openssl_server_loop(Pid, SslPort, Args);
789        {update_keys, Type} ->
790            case Type of
791                write ->
792                    ct:log("[openssl server] Update keys: ~p", [Type]),
793                    true = port_command(SslPort, "k", [nosuspend]),
794                    Pid ! {self(), ok};
795                read_write ->
796                    ct:log("[openssl server] Update keys: ~p", [Type]),
797                    true = port_command(SslPort, "K", [nosuspend]),
798                    Pid ! {self(), ok}
799            end,
800            openssl_server_loop(Pid, SslPort, Args);
801        close ->
802            ct:log("~p:~p~n[openssl server] Server closing~n", [?MODULE,?LINE]),
803            catch port_close(SslPort);
804        {ssl_closed, _Socket} ->
805            %% TODO
806            ok
807    end.
808
809start_openssl_client(Args0, Config) ->
810    {ClientNode, _, Hostname} = run_where(Config),
811    ClientOpts = get_client_opts(Config),
812    DefaultVersions = default_tls_version(ClientOpts),
813    [Version | _] = proplists:get_value(versions, ClientOpts, DefaultVersions),
814    Node = proplists:get_value(node, Args0, ClientNode),
815    Args = [{from, self()},
816            {host, Hostname},
817            {options, ClientOpts} | Args0],
818
819    Result = spawn_link(Node, ?MODULE, init_openssl_client, [[{version, Version} | lists:delete(return_port, Args)]]),
820    receive
821	{connected, OpenSSLPort} ->
822	    case lists:member(return_port, Args) of
823		true -> {Result, OpenSSLPort};
824		false -> Result
825	    end;
826	{connect_failed, Reason} ->
827	    {connect_failed, Reason}
828    end.
829
830init_openssl_client(Options) ->
831    Version = proplists:get_value(version, Options),
832    Port = proplists:get_value(port, Options),
833    Pid = proplists:get_value(from, Options),
834    SslPort = start_client(openssl, Port, Options, [{version, Version}]),
835    openssl_client_loop(Pid, SslPort, []).
836
837
838openssl_client_loop(Pid, SslPort, Args) ->
839    Pid ! {connected, SslPort},
840    openssl_client_loop_core(Pid, SslPort, Args).
841
842openssl_client_loop_core(Pid, SslPort, Args) ->
843    receive
844        {data, Data} ->
845            case port_command(SslPort, Data, [nosuspend]) of
846                true ->
847                    ct:log("(~p) [openssl client] Send data: ~p~n",
848                           [self(), Data]),
849                    Pid ! {self(), ok};
850                _Else ->
851                    ct:log("(~p) [openssl client] Send failed, data: ~p~n",
852                           [self(), Data]),
853                    Pid ! {self(), {error, port_command_failed}}
854            end,
855            openssl_client_loop_core(Pid, SslPort, Args);
856        {active_receive, Data} ->
857            case active_recv(SslPort, length(Data)) of
858                ReceivedData ->
859                    ct:log("(~p) [openssl client] Received: ~p~n   (forward to PID=~p)~n",
860                           [self(), Data, Pid]),
861                    Pid ! {self(), ReceivedData}
862            end,
863            openssl_client_loop_core(Pid, SslPort, Args);
864        {update_keys, Type} ->
865            case Type of
866                write ->
867                    ct:log("[openssl client] Update keys: ~p", [Type]),
868                    true = port_command(SslPort, "k", [nosuspend]),
869                    Pid ! {self(), ok};
870                read_write ->
871                    ct:log("[openssl client] Update keys: ~p", [Type]),
872                    true = port_command(SslPort, "K", [nosuspend]),
873                    Pid ! {self(), ok}
874            end,
875            openssl_client_loop_core(Pid, SslPort, Args);
876        close ->
877            ct:log("~p:~p~nClient closing~n", [?MODULE,?LINE]),
878            catch port_close(SslPort);
879        {ssl_closed, _Socket} ->
880            %% TODO
881            ok
882    end.
883
884start_client(Args0, Config) ->
885    {_, ServerNode, Hostname} = run_where(Config),
886    ClientOpts = get_client_opts(Config),
887    ClientOpts1 = proplists:get_value(options, Args0, []),
888    Node = proplists:get_value(node, Args0, ServerNode),
889    Args1 = proplists:delete(options, Args0),
890    Args = [{from, self()},
891            {host, Hostname},
892            {node, Node},
893            {options, ClientOpts ++ ClientOpts1} | Args1],
894    start_client(Args).
895%%
896start_client(Args) ->
897    Node = proplists:get_value(node, Args),
898    Result = spawn_link(Node, ?MODULE, run_client_init, [lists:delete(return_socket, Args)]),
899    receive
900	{connected, Socket} ->
901	    case lists:member(return_socket, Args) of
902		true -> {Result, Socket};
903		false -> Result
904	    end;
905	{connect_failed, Reason} ->
906	    {connect_failed, Reason}
907    end.
908
909run_client_init(Opts) ->
910    put(retries, 0),
911    run_client(Opts).
912
913run_client(Opts) ->
914    Node = proplists:get_value(node, Opts),
915    Host = proplists:get_value(host, Opts),
916    Port = proplists:get_value(port, Opts),
917    Pid = proplists:get_value(from, Opts),
918    Transport =  proplists:get_value(transport, Opts, ssl),
919    Options = proplists:get_value(options, Opts),
920    ContOpts = proplists:get_value(continue_options, Opts, []),
921    ct:log("~p:~p~n~p:connect(~p, ~p)@~p~n", [?MODULE,?LINE, Transport, Host, Port, Node]),
922    ct:log("SSLOpts: ~p", [format_options(Options)]),
923    case ContOpts of
924        [] ->
925            client_loop(Node, Host, Port, Pid, Transport, Options, Opts);
926        _ ->
927            client_cont_loop(Node, Host, Port, Pid, Transport, Options, ContOpts, Opts)
928    end.
929
930client_loop(_Node, Host, Port, Pid, Transport, Options, Opts) ->
931    case Transport:connect(Host, Port, Options) of
932	{ok, Socket} ->
933	    Pid ! {connected, Socket},
934	    ct:log("~p:~p~nClient: connected~n", [?MODULE,?LINE]),
935	    %% In special cases we want to know the client port, it will
936	    %% be indicated by sending {port, 0} in options list!
937	    send_selected_port(Pid,  proplists:get_value(port, Options), Socket),
938	    MFA = proplists:get_value(mfa, Opts),
939	    case client_apply_mfa(Socket, MFA) of
940		no_result_msg ->
941		    ok;
942		Msg ->
943		    ct:log("~p:~p~nClient Msg: ~p ~n", [?MODULE,?LINE, Msg]),
944		    Pid ! {self(), Msg}
945	    end,
946            client_loop_core(Socket, Pid, Transport);
947	{error, econnrefused = Reason} ->
948            case proplists:get_value(return_error, Opts, undefined) of
949                econnrefused ->
950                    Pid ! {connect_failed, Reason};
951                _ ->
952                    case get(retries) of
953                        N when N < 5 ->
954                            ct:log("~p:~p~neconnrefused retries=~p sleep ~p",[?MODULE,?LINE, N,?SLEEP]),
955                            put(retries, N+1),
956                            ct:sleep(?SLEEP),
957                            run_client(Opts);
958                        _ ->
959                            ct:log("~p:~p~nClient faild several times: connection failed: ~p ~n", [?MODULE,?LINE, Reason]),
960                            Pid ! {self(), {error, Reason}}
961                    end
962            end;
963	{error, econnreset = Reason} ->
964	      case get(retries) of
965		N when N < 5 ->
966		    ct:log("~p:~p~neconnreset retries=~p sleep ~p",[?MODULE,?LINE, N,?SLEEP]),
967		    put(retries, N+1),
968		    ct:sleep(?SLEEP),
969		    run_client(Opts);
970	       _ ->
971		    ct:log("~p:~p~nClient faild several times: connection failed: ~p ~n", [?MODULE,?LINE, Reason]),
972		    Pid ! {self(), {error, Reason}}
973	    end;
974	{error, Reason} ->
975	    ct:log("~p:~p~nClient: connection failed: ~p ~n", [?MODULE,?LINE, Reason]),
976	    Pid ! {connect_failed, Reason}
977    end.
978
979client_loop_core(Socket, Pid, Transport) ->
980    receive
981        {data, Data} ->
982            ct:log("[client] Send: ~p~n", [Data]),
983            case Transport:send(Socket, Data) of
984                ok ->
985                    Pid ! {self(), ok};
986                {error, Reason} ->
987                    Pid ! {self(), Reason}
988            end,
989            client_loop_core(Socket, Pid, Transport);
990        {active_receive, Data} ->
991            case active_recv(Socket, length(Data)) of
992                ReceivedData ->
993                    ct:log("[client] Received: ~p~n", [Data]),
994                    Pid ! {self(), ReceivedData}
995            end,
996            client_loop_core(Socket, Pid, Transport);
997        {update_keys, Type} ->
998            case ssl:update_keys(Socket, Type) of
999                ok ->
1000                    ct:log("[client] Update keys: ~p", [Type]),
1001                    Pid ! {self(), ok};
1002                {error, Reason} ->
1003                    ct:log("[client] Update keys failed: ~p", [Type]),
1004                    Pid ! {self(), Reason}
1005            end,
1006            client_loop_core(Socket, Pid, Transport);
1007        get_socket ->
1008            Pid ! {self(), {socket, Socket}},
1009            client_loop_core(Socket, Pid, Transport);
1010        close ->
1011            ct:log("~p:~p~nClient closing~n", [?MODULE,?LINE]),
1012            Transport:close(Socket);
1013        {ssl_closed, Socket} ->
1014            ok;
1015        {gen_tcp, closed} ->
1016            ok
1017    end.
1018
1019client_cont_loop(_Node, Host, Port, Pid, Transport, Options, cancel, _Opts) ->
1020    case Transport:connect(Host, Port, Options) of
1021        {ok, Socket, _} ->
1022           Result = Transport:handshake_cancel(Socket),
1023            ct:log("~p:~p~nClient: Cancel: ~p ~n", [?MODULE,?LINE, Result]),
1024            Pid ! {connect_failed, Result};
1025        {error, Reason} ->
1026	    ct:log("~p:~p~nClient: connection failed: ~p ~n", [?MODULE,?LINE, Reason]),
1027	    Pid ! {connect_failed, Reason}
1028    end;
1029
1030client_cont_loop(_Node, Host, Port, Pid, Transport, Options, ContOpts0, Opts) ->
1031    case Transport:connect(Host, Port, Options) of
1032        {ok, Socket0, Ext} ->
1033            ContOpts = case lists:keytake(want_ext, 1, ContOpts0) of
1034                           {value, {_, WantExt}, ContOpts1} ->
1035                               if is_pid(WantExt) ->
1036                                       WantExt ! {self(), {ext, Ext}};
1037                                  true ->
1038                                       ignore
1039                               end,
1040                               ContOpts1;
1041                           _ ->
1042                               ContOpts0
1043                       end,
1044            ct:log("~p:~p~nClient: handshake_continue(~p, ~p, infinity) ~n", [?MODULE, ?LINE, Socket0, ContOpts]),
1045            case Transport:handshake_continue(Socket0, ContOpts) of
1046                {ok, Socket} ->
1047                    Pid ! {connected, Socket},
1048                    {Module, Function, Args} = proplists:get_value(mfa, Opts),
1049                    ct:log("~p:~p~nClient: apply(~p,~p,~p)~n",
1050                           [?MODULE,?LINE, Module, Function, [Socket | Args]]),
1051                    case apply(Module, Function, [Socket | Args]) of
1052                        no_result_msg ->
1053                            ok;
1054                        Msg ->
1055                            ct:log("~p:~p~nClient Msg: ~p ~n", [?MODULE,?LINE, Msg]),
1056                            Pid ! {self(), Msg}
1057                    end
1058	    end;
1059        {error, Reason} ->
1060            ct:log("~p:~p~nClient: connection failed: ~p ~n", [?MODULE,?LINE, Reason]),
1061            Pid ! {connect_failed, Reason}
1062    end.
1063
1064close(Pid) ->
1065    ct:log("~p:~p~nClose ~p ~n", [?MODULE,?LINE, Pid]),
1066    Monitor = erlang:monitor(process, Pid),
1067    Pid ! close,
1068    receive
1069	{'DOWN', Monitor, process, Pid, Reason} ->
1070	    erlang:demonitor(Monitor),
1071	    ct:log("~p:~p~nPid: ~p down due to:~p ~n", [?MODULE,?LINE, Pid, Reason])
1072
1073    end.
1074
1075close(Pid, Timeout) ->
1076    ct:log("~p:~p~n Close ~p ~n", [?MODULE,?LINE, Pid]),
1077    Monitor = erlang:monitor(process, Pid),
1078    Pid ! close,
1079    receive
1080	{'DOWN', Monitor, process, Pid, Reason} ->
1081	    erlang:demonitor(Monitor),
1082	    ct:log("~p:~p~nPid: ~p down due to:~p ~n", [?MODULE,?LINE, Pid, Reason])
1083    after
1084	Timeout ->
1085	    exit(Pid, kill)
1086    end.
1087
1088check_result(Server, ServerMsg, Client, ClientMsg) ->
1089    {ClientIP, ClientPort} = get_ip_port(ServerMsg),
1090    receive
1091	{Server, ServerMsg} ->
1092	    check_result(Client, ClientMsg);
1093        %% Workaround to accept local addresses (127.0.0.0/24)
1094        {Server, {ok, {{127,_,_,_}, ClientPort}}} when ClientIP =:= localhost  ->
1095            check_result(Client, ClientMsg);
1096	{Client, ClientMsg} ->
1097	    check_result(Server, ServerMsg);
1098	{Port, {data,Debug}} when is_port(Port) ->
1099	    ct:log("~p:~p~n Openssl ~s~n",[?MODULE,?LINE, Debug]),
1100	    check_result(Server, ServerMsg, Client, ClientMsg);
1101        {Port,closed} when is_port(Port) ->
1102            ct:log("~p:~p~n Openssl port closed ~n",[?MODULE,?LINE]),
1103            check_result(Server, ServerMsg, Client, ClientMsg);
1104        {'EXIT', epipe} ->
1105            ct:log("~p:~p~n Openssl port died ~n",[?MODULE,?LINE]),
1106            check_result(Server, ServerMsg, Client, ClientMsg);
1107	Unexpected ->
1108	    Reason = {{expected, {Client, ClientMsg}},
1109		      {expected, {Server, ServerMsg}}, {got, Unexpected}},
1110	    ct:fail(Reason)
1111    end.
1112
1113check_result(Pid, Msg) ->
1114    {ClientIP, ClientPort} = get_ip_port(Msg),
1115    receive
1116	{Pid, Msg} ->
1117	    ok;
1118        %% Workaround to accept local addresses (127.0.0.0/24)
1119        {Pid, {ok, {{127,_,_,_}, ClientPort}}} when ClientIP =:= localhost ->
1120            ok;
1121	{Port, {data,Debug}} when is_port(Port) ->
1122	    ct:log("~p:~p~n Openssl ~s~n",[?MODULE,?LINE, Debug]),
1123	    check_result(Pid,Msg);
1124        {Port,closed} when is_port(Port)->
1125            ct:log("~p:~p Openssl port closed ~n",[?MODULE,?LINE]),
1126            check_result(Pid, Msg);
1127	Unexpected ->
1128	    Reason = {{expected, {Pid, Msg}},
1129		      {got, Unexpected}},
1130	    ct:fail(Reason)
1131    end.
1132
1133
1134get_ip_port({ok,{ClientIP, ClientPort}}) ->
1135    {ClientIP, ClientPort};
1136get_ip_port(_) ->
1137    {undefined, undefined}.
1138
1139
1140check_server_alert(Pid, Alert) ->
1141    receive
1142	{Pid, {error, {tls_alert, {Alert, STxt}}}} ->
1143            check_server_txt(STxt),
1144            ok;
1145        {Pid, {error, {tls_alert, {OtherAlert, STxt}}}} ->
1146            ct:fail("Unexpected alert during negative test: ~p - ~p", [OtherAlert, STxt]);
1147        {Pid, {error, closed}} ->
1148            ok;
1149        {Pid, {ok, _}} ->
1150            ct:fail("Successful connection during negative test.")
1151    end.
1152
1153check_server_alert(Server, Client, Alert) ->
1154    receive
1155	{Server, {error, {tls_alert, {Alert, STxt}}}} ->
1156            check_server_txt(STxt),
1157            check_client_alert(Client, Alert);
1158        {Server, {ok, _}} ->
1159            ct:fail("Successful connection during negative test.")
1160    end.
1161
1162check_client_alert(Pid, Alert) ->
1163    receive
1164	{Pid, {error, {tls_alert, {Alert, CTxt}}}} ->
1165            check_client_txt(CTxt),
1166            ok;
1167        {Pid, {error, {tls_alert, {OtherAlert, CTxt}}}} ->
1168            ct:fail("Unexpected alert during negative test: ~p - ~p", [OtherAlert, CTxt]);
1169        {Pid, {ssl_error, _, {tls_alert, {Alert, CTxt}}}} ->
1170            check_client_txt(CTxt),
1171            ok;
1172        {Pid, {ssl_error, _, {tls_alert, {OtherAlert, CTxt}}}} ->
1173            ct:fail("Unexpected alert during negative test: ~p - ~p", [OtherAlert, CTxt]);
1174        {Pid, {error, closed}} ->
1175            ok;
1176        {Pid, {ok, _}} ->
1177            ct:fail("Successful connection during negative test.")
1178    end.
1179check_client_alert(Server, Client, Alert) ->
1180    receive
1181	{Client, {error, {tls_alert, {Alert, CTxt}}}} ->
1182            check_client_txt(CTxt),
1183            check_server_alert(Server, Alert);
1184        {Client, {ssl_error, _, {tls_alert, {Alert, CTxt}}}} ->
1185            check_client_txt(CTxt),
1186            ok;
1187        {Client, {error, closed}} ->
1188            ok;
1189        {Client, {ok, _}} ->
1190            ct:fail("Successful connection during negative test.")
1191    end.
1192check_server_txt("TLS server" ++ _) ->
1193    ok;
1194check_server_txt("DTLS server" ++ _) ->
1195    ok;
1196check_server_txt(Txt) ->
1197    ct:fail({expected_server, {got, Txt}}).
1198
1199check_client_txt("TLS client" ++ _) ->
1200    ok;
1201check_client_txt("DTLS client" ++ _) ->
1202    ok;
1203check_client_txt(Txt) ->
1204    ct:fail({expected_server, {got, Txt}}).
1205
1206wait_for_result(Server, ServerMsg, Client, ClientMsg) ->
1207    receive
1208	{Server, ServerMsg} ->
1209	    receive
1210		{Client, ClientMsg} ->
1211		    ok
1212		%% Unexpected ->
1213		%%     Unexpected
1214	    end;
1215	{Client, ClientMsg} ->
1216	    receive
1217		{Server, ServerMsg} ->
1218		    ok
1219		%% Unexpected ->
1220		%%     Unexpected
1221	    end;
1222	{Port, {data,Debug}} when is_port(Port) ->
1223	    ct:log("~p:~p~nopenssl ~s~n",[?MODULE,?LINE, Debug]),
1224	    wait_for_result(Server, ServerMsg, Client, ClientMsg)
1225	%% Unexpected ->
1226	%%     Unexpected
1227    end.
1228
1229check_ok([]) ->
1230    ok;
1231check_ok(Pids) ->
1232    receive
1233	{Pid, ok} ->
1234	    check_ok(lists:delete(Pid, Pids));
1235	Other ->
1236	    ct:fail({expected, {"pid()", ok}, got, Other})
1237    end.
1238
1239wait_for_result(Pid, Msg) ->
1240    receive
1241	{Pid, Msg} ->
1242	    ok;
1243	{Port, {data,Debug}} when is_port(Port) ->
1244	    ct:log("~p:~p~nopenssl ~s~n",[?MODULE,?LINE, Debug]),
1245	    wait_for_result(Pid,Msg)
1246	%% Unexpected ->
1247	%%     Unexpected
1248    end.
1249
1250format_options([{cacerts, Certs}|R]) ->
1251    [{cacerts, format_certs(Certs)} | format_options(R)];
1252format_options([{cert, Certs}|R]) ->
1253    [{cert, format_certs(Certs)} | format_options(R)];
1254format_options([{key, Key}|R]) ->
1255    [{key, lists:flatten(io_lib:format("~W",[Key, ?PRINT_DEPTH]))} | format_options(R)];
1256format_options([Opt|R]) ->
1257    [Opt | format_options(R)];
1258format_options([]) ->
1259    [].
1260
1261format_certs(Certs) when is_list(Certs) ->
1262    [lists:flatten(format_cert(C)) || C <- Certs];
1263format_certs(Cert) when is_binary(Cert) ->
1264    lists:flatten(format_cert(Cert)).
1265
1266format_cert(BinCert) when is_binary(BinCert) ->
1267    OtpCert = #'OTPCertificate'{tbsCertificate = Cert} = public_key:pkix_decode_cert(BinCert, otp),
1268    #'OTPTBSCertificate'{subject = Subject, serialNumber = Nr, issuer = Issuer} = Cert,
1269    case public_key:pkix_is_self_signed(OtpCert) of
1270        true ->
1271            io_lib:format("~.3w: ~s ->   selfsigned", [Nr, format_subject(Subject)]);
1272        false ->
1273            case public_key:pkix_issuer_id(OtpCert, other) of
1274                {ok, {IsNr, Issuer0}} ->
1275                    io_lib:format("~.3w:~s -> ~.3w:~s", [Nr, format_subject(Subject), IsNr, format_subject(Issuer0)]);
1276                {error, _} ->
1277                    io_lib:format("~.3w:~s ->    :~s", [Nr, format_subject(Subject), format_subject(Issuer)])
1278            end
1279    end.
1280
1281format_subject({rdnSequence, Seq}) ->
1282    format_subject(Seq);
1283format_subject([[{'AttributeTypeAndValue', ?'id-at-commonName', {_, String}}]|_]) ->
1284    String;
1285format_subject([_|R]) ->
1286    format_subject(R).
1287
1288cert_options(Config) ->
1289    ClientCaCertFile = filename:join([proplists:get_value(priv_dir, Config),
1290				      "client", "cacerts.pem"]),
1291    ClientCertFile = filename:join([proplists:get_value(priv_dir, Config),
1292				    "client", "cert.pem"]),
1293    ClientCertFileDigitalSignatureOnly = filename:join([proplists:get_value(priv_dir, Config),
1294				    "client", "digital_signature_only_cert.pem"]),
1295    ServerCaCertFile = filename:join([proplists:get_value(priv_dir, Config),
1296				      "server", "cacerts.pem"]),
1297    ServerCertFile = filename:join([proplists:get_value(priv_dir, Config),
1298				    "server", "cert.pem"]),
1299    ServerKeyFile = filename:join([proplists:get_value(priv_dir, Config),
1300			     "server", "key.pem"]),
1301    ClientKeyFile = filename:join([proplists:get_value(priv_dir, Config),
1302			     "client", "key.pem"]),
1303    ServerKeyCertFile = filename:join([proplists:get_value(priv_dir, Config),
1304				       "server", "keycert.pem"]),
1305    ClientKeyCertFile = filename:join([proplists:get_value(priv_dir, Config),
1306				       "client", "keycert.pem"]),
1307
1308    BadCaCertFile = filename:join([proplists:get_value(priv_dir, Config),
1309				   "badcacert.pem"]),
1310    BadCertFile = filename:join([proplists:get_value(priv_dir, Config),
1311				   "badcert.pem"]),
1312    BadKeyFile = filename:join([proplists:get_value(priv_dir, Config),
1313			      "badkey.pem"]),
1314
1315    [{client_opts, [{cacertfile, ClientCaCertFile},
1316		    {certfile, ClientCertFile},
1317		    {keyfile, ClientKeyFile}]},
1318     {client_verification_opts, [{cacertfile, ServerCaCertFile},
1319				{certfile, ClientCertFile},
1320				{keyfile, ClientKeyFile},
1321				{verify, verify_peer}]},
1322     {client_verification_opts_digital_signature_only, [{cacertfile, ServerCaCertFile},
1323				{certfile, ClientCertFileDigitalSignatureOnly},
1324				{keyfile, ClientKeyFile},
1325				{ssl_imp, new}]},
1326     {server_opts, [{ssl_imp, new},{reuseaddr, true}, {cacertfile, ServerCaCertFile},
1327		    {certfile, ServerCertFile}, {keyfile, ServerKeyFile}]},
1328     {server_verification_opts, [{ssl_imp, new},{reuseaddr, true},
1329		    {cacertfile, ClientCaCertFile},
1330		    {certfile, ServerCertFile}, {keyfile, ServerKeyFile}]},
1331     {client_kc_opts, [{certfile, ClientKeyCertFile},  {ssl_imp, new}]},
1332     {server_kc_opts, [{ssl_imp, new},{reuseaddr, true},
1333		       {certfile, ServerKeyCertFile}]},
1334     {client_bad_ca, [{cacertfile, BadCaCertFile},
1335		      {certfile, ClientCertFile},
1336		      {keyfile, ClientKeyFile},
1337		      {ssl_imp, new}]},
1338     {client_bad_cert, [{cacertfile, ClientCaCertFile},
1339			{certfile, BadCertFile},
1340			{keyfile, ClientKeyFile},
1341			{ssl_imp, new}]},
1342     {server_bad_ca, [{ssl_imp, new},{cacertfile, BadCaCertFile},
1343		      {certfile, ServerCertFile},
1344		      {keyfile, ServerKeyFile}]},
1345     {server_bad_cert, [{ssl_imp, new},{cacertfile, ServerCaCertFile},
1346			{certfile, BadCertFile}, {keyfile, ServerKeyFile}]},
1347     {server_bad_key, [{ssl_imp, new},{cacertfile, ServerCaCertFile},
1348		       {certfile, ServerCertFile}, {keyfile, BadKeyFile}]}
1349     | Config].
1350
1351make_dsa_cert(Config) ->
1352    CryptoSupport = crypto:supports(),
1353    case proplists:get_bool(dss, proplists:get_value(public_keys, CryptoSupport)) of
1354        true ->
1355            ClientChain = proplists:get_value(client_chain, Config, default_cert_chain_conf()),
1356            ServerChain = proplists:get_value(server_chain, Config, default_cert_chain_conf()),
1357            CertChainConf = gen_conf(dsa, dsa, ClientChain, ServerChain),
1358            ClientFileBase = filename:join([proplists:get_value(priv_dir, Config), "dsa"]),
1359            ServerFileBase = filename:join([proplists:get_value(priv_dir, Config), "dsa"]),
1360            GenCertData = public_key:pkix_test_data(CertChainConf),
1361            [{server_config, ServerConf},
1362             {client_config, ClientConf}] =
1363                x509_test:gen_pem_config_files(GenCertData, ClientFileBase, ServerFileBase),
1364
1365          [{server_dsa_opts, ServerConf},
1366           {server_dsa_verify_opts, [{verify, verify_peer} | ServerConf]},
1367           {client_dsa_opts, ClientConf}
1368           | Config];
1369      false ->
1370          Config
1371  end.
1372
1373
1374make_cert_chains_der(Alg, UserConf) ->
1375    ClientChain = proplists:get_value(client_chain, UserConf, default_cert_chain_conf()),
1376    ServerChain = proplists:get_value(server_chain, UserConf, default_cert_chain_conf()),
1377    CertChainConf = gen_conf(Alg, Alg, ClientChain, ServerChain),
1378    public_key:pkix_test_data(CertChainConf).
1379
1380make_cert_chains_pem(Alg, UserConf, Config, Suffix) ->
1381    ClientChain = proplists:get_value(client_chain, UserConf, default_cert_chain_conf()),
1382    ServerChain = proplists:get_value(server_chain, UserConf, default_cert_chain_conf()),
1383    CertChainConf = gen_conf(Alg, Alg, ClientChain, ServerChain),
1384    ClientFileBase = filename:join([proplists:get_value(priv_dir, Config), atom_to_list(Alg) ++ Suffix]),
1385    ServerFileBase = filename:join([proplists:get_value(priv_dir, Config), atom_to_list(Alg) ++ Suffix]),
1386    GenCertData = public_key:pkix_test_data(CertChainConf),
1387    Conf = x509_test:gen_pem_config_files(GenCertData, ClientFileBase, ServerFileBase),
1388    CConf = proplists:get_value(client_config, Conf),
1389    SConf = proplists:get_value(server_config, Conf),
1390    #{server_config => SConf,
1391      client_config => CConf}.
1392
1393make_rsa_cert_chains(UserConf, Config, Suffix) ->
1394    ClientChain = proplists:get_value(client_chain, UserConf, default_cert_chain_conf()),
1395    ServerChain = proplists:get_value(server_chain, UserConf, default_cert_chain_conf()),
1396    CertChainConf = gen_conf(rsa, rsa, ClientChain, ServerChain),
1397    ClientFileBase = filename:join([proplists:get_value(priv_dir, Config), "rsa" ++ Suffix]),
1398    ServerFileBase = filename:join([proplists:get_value(priv_dir, Config), "rsa" ++ Suffix]),
1399    GenCertData = public_key:pkix_test_data(CertChainConf),
1400    [{server_config, ServerConf},
1401     {client_config, ClientConf}] =
1402        x509_test:gen_pem_config_files(GenCertData, ClientFileBase, ServerFileBase),
1403    {[{verify, verify_peer} | ClientConf],
1404     [{reuseaddr, true}, {verify, verify_peer} | ServerConf]
1405    }.
1406
1407make_ecc_cert_chains(UserConf, Config, Suffix) ->
1408    ClientChain = proplists:get_value(client_chain, UserConf, default_cert_chain_conf()),
1409    ServerChain = proplists:get_value(server_chain, UserConf, default_cert_chain_conf()),
1410    CertChainConf = gen_conf(ecdsa, ecdsa, ClientChain, ServerChain),
1411    ClientFileBase = filename:join([proplists:get_value(priv_dir, Config), "ecdsa" ++ Suffix]),
1412    ServerFileBase = filename:join([proplists:get_value(priv_dir, Config), "ecdsa" ++ Suffix]),
1413    GenCertData = public_key:pkix_test_data(CertChainConf),
1414    [{server_config, ServerConf},
1415     {client_config, ClientConf}] =
1416        x509_test:gen_pem_config_files(GenCertData, ClientFileBase, ServerFileBase),
1417    {[{verify, verify_peer} | ClientConf],
1418     [{reuseaddr, true}, {verify, verify_peer} | ServerConf]
1419    }.
1420
1421
1422make_dsa_cert_chains(UserConf, Config, Suffix) ->
1423    CryptoSupport = crypto:supports(),
1424    case proplists:get_bool(dss, proplists:get_value(public_keys, CryptoSupport)) of
1425        true ->
1426            ClientChain = proplists:get_value(client_chain, UserConf, default_cert_chain_conf()),
1427            ServerChain = proplists:get_value(server_chain, UserConf, default_cert_chain_conf()),
1428            CertChainConf = gen_conf(dsa, dsa, ClientChain, ServerChain),
1429            ClientFileBase = filename:join([proplists:get_value(priv_dir, Config), "dsa" ++ Suffix]),
1430            ServerFileBase = filename:join([proplists:get_value(priv_dir, Config), "dsa" ++ Suffix]),
1431            GenCertData = public_key:pkix_test_data(CertChainConf),
1432            [{server_config, ServerConf},
1433             {client_config, ClientConf}] =
1434                x509_test:gen_pem_config_files(GenCertData, ClientFileBase, ServerFileBase),
1435            {[{verify, verify_peer} | ClientConf],
1436             [{reuseaddr, true}, {verify, verify_peer} | ServerConf]};
1437      false ->
1438          Config
1439  end.
1440
1441make_ec_cert_chains(UserConf, ClientChainType, ServerChainType, Config) ->
1442    make_ec_cert_chains(UserConf, ClientChainType, ServerChainType, Config, ?DEFAULT_CURVE).
1443%%
1444make_ec_cert_chains(UserConf, ClientChainType, ServerChainType, Config, Curve) ->
1445    ClientChain = proplists:get_value(client_chain, UserConf, default_cert_chain_conf()),
1446    ServerChain = proplists:get_value(server_chain, UserConf, default_cert_chain_conf()),
1447    CertChainConf = gen_conf(ClientChainType, ServerChainType, ClientChain, ServerChain, Curve),
1448    ClientFileBase = filename:join([proplists:get_value(priv_dir, Config), atom_to_list(ClientChainType)]),
1449    ServerFileBase = filename:join([proplists:get_value(priv_dir, Config), atom_to_list(ServerChainType)]),
1450    GenCertData = public_key:pkix_test_data(CertChainConf),
1451    [{server_config, ServerConf},
1452     {client_config, ClientConf}] =
1453        x509_test:gen_pem_config_files(GenCertData, ClientFileBase, ServerFileBase),
1454    {[{verify, verify_peer} | ClientConf],
1455     [{reuseaddr, true}, {verify, verify_peer} | ServerConf]
1456    }.
1457
1458default_cert_chain_conf() ->
1459    %% Use only default options
1460    [[],[],[]].
1461
1462make_rsa_pss_pem(Alg, _UserConf, Config, Suffix) ->
1463    DefClientConf = chain_spec(client, Alg, []),
1464    DefServerConf = chain_spec(server, Alg, []),
1465    CertChainConf = new_format([{client_chain, DefClientConf}, {server_chain, DefServerConf}]),
1466    ClientFileBase = filename:join([proplists:get_value(priv_dir, Config), atom_to_list(Alg) ++ Suffix]),
1467    ServerFileBase = filename:join([proplists:get_value(priv_dir, Config), atom_to_list(Alg) ++ Suffix]),
1468    GenCertData = public_key:pkix_test_data(CertChainConf),
1469    Conf = x509_test:gen_pem_config_files(GenCertData, ClientFileBase, ServerFileBase),
1470    CConf = proplists:get_value(client_config, Conf),
1471    SConf = proplists:get_value(server_config, Conf),
1472    #{server_config => SConf,
1473      client_config => CConf}.
1474
1475gen_conf(ClientChainType, ServerChainType, UserClient, UserServer) ->
1476    gen_conf(ClientChainType, ServerChainType, UserClient, UserServer, ?DEFAULT_CURVE).
1477%%
1478gen_conf(mix, mix, UserClient, UserServer, _) ->
1479    ClientTag = conf_tag("client"),
1480    ServerTag = conf_tag("server"),
1481
1482    DefaultClient = default_cert_chain_conf(),
1483    DefaultServer = default_cert_chain_conf(),
1484
1485    ClientConf = merge_chain_spec(UserClient, DefaultClient, []),
1486    ServerConf = merge_chain_spec(UserServer, DefaultServer, []),
1487
1488    new_format([{ClientTag, ClientConf}, {ServerTag, ServerConf}]);
1489gen_conf(ClientChainType, ServerChainType, UserClient, UserServer, Curve) ->
1490    ClientTag = conf_tag("client"),
1491    ServerTag = conf_tag("server"),
1492
1493    DefaultClient = chain_spec(client, ClientChainType, Curve),
1494    DefaultServer = chain_spec(server, ServerChainType, Curve),
1495
1496    ClientConf = merge_chain_spec(UserClient, DefaultClient, []),
1497    ServerConf = merge_chain_spec(UserServer, DefaultServer, []),
1498
1499    new_format([{ClientTag, ClientConf}, {ServerTag, ServerConf}]).
1500
1501new_format(Conf) ->
1502    CConf = proplists:get_value(client_chain, Conf),
1503    SConf = proplists:get_value(server_chain, Conf),
1504    #{server_chain => proplist_to_map(SConf),
1505      client_chain => proplist_to_map(CConf)}.
1506
1507proplist_to_map([Head | Rest]) ->
1508    [Last | Tail] = lists:reverse(Rest),
1509    #{root => Head,
1510      intermediates => lists:reverse(Tail),
1511      peer => Last}.
1512
1513conf_tag(Role) ->
1514    list_to_atom(Role ++ "_chain").
1515
1516chain_spec(_Role, ecdh_rsa, Curve) ->
1517    Digest = {digest, appropriate_sha(crypto:supports())},
1518    CurveOid = pubkey_cert_records:namedCurves(Curve),
1519     [[Digest, {key, {namedCurve, CurveOid}}],
1520      [Digest, {key, hardcode_rsa_key(1)}],
1521      [Digest, {key, {namedCurve, CurveOid}}]];
1522
1523chain_spec(_Role, ecdhe_ecdsa, Curve) ->
1524    Digest = {digest, appropriate_sha(crypto:supports())},
1525    CurveOid = pubkey_cert_records:namedCurves(Curve),
1526    [[Digest, {key, {namedCurve, CurveOid}}],
1527     [Digest, {key, {namedCurve, CurveOid}}],
1528     [Digest, {key, {namedCurve, CurveOid}}]];
1529
1530chain_spec(_Role, ecdh_ecdsa, Curve) ->
1531    Digest = {digest, appropriate_sha(crypto:supports())},
1532    CurveOid = pubkey_cert_records:namedCurves(Curve),
1533    [[Digest, {key, {namedCurve, CurveOid}}],
1534     [Digest, {key, {namedCurve, CurveOid}}],
1535     [Digest, {key, {namedCurve, CurveOid}}]];
1536chain_spec(_Role, ecdhe_rsa, _) ->
1537    Digest = {digest, appropriate_sha(crypto:supports())},
1538    [[Digest, {key, hardcode_rsa_key(1)}],
1539     [Digest, {key, hardcode_rsa_key(2)}],
1540     [Digest, {key, hardcode_rsa_key(3)}]];
1541chain_spec(_Role, ecdsa, Curve) ->
1542    Digest = {digest, appropriate_sha(crypto:supports())},
1543    CurveOid = pubkey_cert_records:namedCurves(Curve),
1544    [[Digest, {key, {namedCurve, CurveOid}}],
1545     [Digest, {key, {namedCurve, CurveOid}}],
1546     [Digest, {key, {namedCurve, CurveOid}}]];
1547chain_spec(_Role, rsa, _) ->
1548    Digest = {digest, appropriate_sha(crypto:supports())},
1549    [[Digest, {key, hardcode_rsa_key(1)}],
1550     [Digest, {key, hardcode_rsa_key(2)}],
1551     [Digest, {key, hardcode_rsa_key(3)}]];
1552chain_spec(_Role, 'rsa-1024', _) ->
1553    Digest = {digest, appropriate_sha(crypto:supports())},
1554    [[Digest, {key, hardcode_rsa_1024_key(1)}],
1555     [Digest, {key, hardcode_rsa_1024_key(2)}],
1556     [Digest, {key, hardcode_rsa_1024_key(3)}]];
1557chain_spec(client, rsa_pss_rsae, _) ->
1558    Digest = {digest, sha256},
1559    [[Digest,  {rsa_padding, rsa_pss_rsae}, {key, hardcode_rsa_key(1)}],
1560     [Digest,  {rsa_padding, rsa_pss_rsae}, {key, hardcode_rsa_key(2)}],
1561     [Digest,  {rsa_padding, rsa_pss_rsae}, {key, hardcode_rsa_key(3)}]];
1562chain_spec(server, rsa_pss_rsae, _) ->
1563    Digest = {digest, sha256},
1564    [[Digest,  {rsa_padding, rsa_pss_rsae}, {key, hardcode_rsa_key(4)}],
1565     [Digest,  {rsa_padding, rsa_pss_rsae}, {key, hardcode_rsa_key(5)}],
1566     [Digest,  {rsa_padding, rsa_pss_rsae}, {key, hardcode_rsa_key(6)}]];
1567chain_spec(client, rsa_pss_pss, _) ->
1568    Digest = {digest, sha256},
1569    [[Digest, {rsa_padding, rsa_pss_pss}, {key, {hardcode_rsa_key(1), pss_params(sha256)}}],
1570     [Digest, {rsa_padding, rsa_pss_pss}, {key, {hardcode_rsa_key(2), pss_params(sha256)}}],
1571     [Digest, {rsa_padding, rsa_pss_pss}, {key, {hardcode_rsa_key(3), pss_params(sha256)}}]];
1572chain_spec(server, rsa_pss_pss, _) ->
1573    Digest = {digest, sha256},
1574    [[Digest, {rsa_padding, rsa_pss_pss}, {key, {hardcode_rsa_key(4), pss_params(sha256)}}],
1575     [Digest, {rsa_padding, rsa_pss_pss}, {key, {hardcode_rsa_key(5),  pss_params(sha256)}}],
1576     [Digest, {rsa_padding, rsa_pss_pss}, {key, {hardcode_rsa_key(6),  pss_params(sha256)}}]];
1577chain_spec(_Role, dsa, _) ->
1578    Digest = {digest, appropriate_sha(crypto:supports())},
1579    [[Digest, {key, hardcode_dsa_key(1)}],
1580     [Digest, {key, hardcode_dsa_key(2)}],
1581     [Digest, {key, hardcode_dsa_key(3)}]].
1582
1583merge_chain_spec([], [], Acc)->
1584    lists:reverse(Acc);
1585merge_chain_spec([User| UserRest], [Default | DefaultRest], Acc) ->
1586    Merge = merge_spec(User, Default, confs(), []),
1587    merge_chain_spec(UserRest, DefaultRest, [Merge | Acc]).
1588
1589confs() ->
1590    [key, digest, validity, extensions].
1591
1592merge_spec(_, _, [], Acc) ->
1593    Acc;
1594merge_spec(User, Default, [Conf | Rest], Acc) ->
1595    case proplists:get_value(Conf, User, undefined) of
1596        undefined ->
1597            case proplists:get_value(Conf, Default, undefined) of
1598                undefined ->
1599                    merge_spec(User, Default, Rest, Acc);
1600                Value  ->
1601                    merge_spec(User, Default, Rest, [{Conf, Value} | Acc])
1602            end;
1603        Value ->
1604                merge_spec(User, Default, Rest, [{Conf, Value} | Acc])
1605    end.
1606
1607make_mix_cert(Config) ->
1608    Ext = x509_test:extensions([{key_usage, [digitalSignature]}]),
1609    Digest = {digest, appropriate_sha(crypto:supports())},
1610    CurveOid = pubkey_cert_records:namedCurves(?DEFAULT_CURVE),
1611    Mix = proplists:get_value(mix, Config, peer_ecc),
1612    ClientChainType =ServerChainType = mix,
1613    {ClientChain, ServerChain} = mix(Mix, Digest, CurveOid, Ext),
1614    CertChainConf = gen_conf(ClientChainType, ServerChainType, ClientChain, ServerChain),
1615    ClientFileBase = filename:join([proplists:get_value(priv_dir, Config), "mix" ++ atom_to_list(Mix)]),
1616    ServerFileBase = filename:join([proplists:get_value(priv_dir, Config), "mix" ++ atom_to_list(Mix)]),
1617    GenCertData = public_key:pkix_test_data(CertChainConf),
1618    [{server_config, ServerConf},
1619     {client_config, ClientConf}] =
1620        x509_test:gen_pem_config_files(GenCertData, ClientFileBase, ServerFileBase),
1621    {[{verify, verify_peer} | ClientConf],
1622     [{reuseaddr, true}, {verify, verify_peer} | ServerConf]
1623    }.
1624
1625mix(peer_ecc, Digest, CurveOid, Ext) ->
1626    ClientChain =  [[Digest, {key, {namedCurve, CurveOid}}],
1627                    [Digest, {key, hardcode_rsa_key(1)}],
1628                    [Digest, {key, {namedCurve, CurveOid}}, {extensions, Ext}]
1629                   ],
1630    ServerChain =  [[Digest, {key, {namedCurve, CurveOid}}],
1631                    [Digest, {key,  hardcode_rsa_key(2)}],
1632                    [Digest, {key, {namedCurve, CurveOid}},{extensions, Ext}]
1633                   ],
1634    {ClientChain, ServerChain};
1635
1636mix(peer_rsa, Digest, CurveOid, Ext) ->
1637    ClientChain =  [[Digest, {key, {namedCurve, CurveOid}}],
1638                    [Digest, {key, {namedCurve, CurveOid}}],
1639                    [Digest, {key, hardcode_rsa_key(1)}, {extensions, Ext}]
1640                   ],
1641    ServerChain =  [[Digest, {key, {namedCurve, CurveOid}}],
1642                    [Digest, {key, {namedCurve, CurveOid}}],
1643                    [Digest, {key,  hardcode_rsa_key(2)},{extensions, Ext}]
1644                   ],
1645    {ClientChain, ServerChain}.
1646
1647make_ecdsa_cert(Config) ->
1648    CryptoSupport = crypto:supports(),
1649    case proplists:get_bool(ecdsa, proplists:get_value(public_keys, CryptoSupport)) of
1650        true ->
1651            ClientFileBase = filename:join([proplists:get_value(priv_dir, Config), "ecdsa"]),
1652            ServerFileBase = filename:join([proplists:get_value(priv_dir, Config), "ecdsa"]),
1653            ClientChain = proplists:get_value(client_chain, Config, default_cert_chain_conf()),
1654            ServerChain = proplists:get_value(server_chain, Config, default_cert_chain_conf()),
1655            CertChainConf = gen_conf(ecdsa, ecdsa, ClientChain, ServerChain),
1656            GenCertData = public_key:pkix_test_data(CertChainConf),
1657            [{server_config, ServerConf},
1658             {client_config, ClientConf}] =
1659                x509_test:gen_pem_config_files(GenCertData, ClientFileBase, ServerFileBase),
1660	    [{server_ecdsa_opts, [{ssl_imp, new},{reuseaddr, true} | ServerConf]},
1661
1662	     {server_ecdsa_verify_opts, [{ssl_imp, new}, {reuseaddr, true},
1663					 {verify, verify_peer} | ServerConf]},
1664	     {client_ecdsa_opts, ClientConf}
1665	     | Config];
1666	false ->
1667	    Config
1668    end.
1669make_rsa_cert(Config) ->
1670    CryptoSupport = crypto:supports(),
1671    case proplists:get_bool(rsa, proplists:get_value(public_keys, CryptoSupport)) of
1672        true ->
1673            ClientFileBase = filename:join([proplists:get_value(priv_dir, Config), "rsa"]),
1674            ServerFileBase = filename:join([proplists:get_value(priv_dir, Config), "rsa"]),
1675            ClientChain = proplists:get_value(client_chain, Config, default_cert_chain_conf()),
1676            ServerChain = proplists:get_value(server_chain, Config, default_cert_chain_conf()),
1677            CertChainConf = gen_conf(rsa, rsa, ClientChain, ServerChain),
1678            GenCertData = public_key:pkix_test_data(CertChainConf),
1679            [{server_config, ServerConf},
1680             {client_config, ClientConf}] =
1681                x509_test:gen_pem_config_files(GenCertData, ClientFileBase, ServerFileBase),
1682	    [{server_rsa_opts, [{reuseaddr, true} | ServerConf]},
1683
1684	     {server_rsa_verify_opts, [{reuseaddr, true},
1685                                       {verify, verify_peer} | ServerConf]},
1686	     {client_rsa_opts, ClientConf},
1687             {client_rsa_verify_opts,  [{verify, verify_peer} |ClientConf]}
1688	     | Config];
1689	false ->
1690	    Config
1691    end.
1692
1693make_rsa_1024_cert(Config) ->
1694    CryptoSupport = crypto:supports(),
1695    case proplists:get_bool(rsa, proplists:get_value(public_keys, CryptoSupport)) of
1696        true ->
1697            ClientFileBase = filename:join([proplists:get_value(priv_dir, Config), "rsa-1024"]),
1698            ServerFileBase = filename:join([proplists:get_value(priv_dir, Config), "rsa-1024"]),
1699            ClientChain = proplists:get_value(client_chain, Config, default_cert_chain_conf()),
1700            ServerChain = proplists:get_value(server_chain, Config, default_cert_chain_conf()),
1701            CertChainConf = gen_conf('rsa-1024', 'rsa-1024', ClientChain, ServerChain),
1702            GenCertData = public_key:pkix_test_data(CertChainConf),
1703            [{server_config, ServerConf},
1704             {client_config, ClientConf}] =
1705                x509_test:gen_pem_config_files(GenCertData, ClientFileBase, ServerFileBase),
1706	    [{server_rsa_1024_opts, [{ssl_imp, new},{reuseaddr, true} | ServerConf]},
1707
1708	     {server_rsa_1024_verify_opts, [{ssl_imp, new}, {reuseaddr, true},
1709					 {verify, verify_peer} | ServerConf]},
1710	     {client_rsa_1024_opts, ClientConf},
1711             {client_rsa_1024_verify_opts,  [{verify, verify_peer} |ClientConf]}
1712	     | Config];
1713	false ->
1714	    Config
1715    end.
1716
1717appropriate_sha(CryptoSupport) ->
1718    Hashes = proplists:get_value(hashs, CryptoSupport),
1719    case portable_cmd("openssl", ["version"]) of
1720        "OpenSSL 0.9.8" ++  _ ->
1721            sha;
1722        _ ->
1723            case lists:member(sha256, Hashes) of
1724                true ->
1725                    sha256;
1726                false ->
1727                    sha
1728            end
1729    end.
1730
1731%% RFC 4492, Sect. 2.3.  ECDH_RSA
1732%%
1733%%    This key exchange algorithm is the same as ECDH_ECDSA except that the
1734%%    server's certificate MUST be signed with RSA rather than ECDSA.
1735make_ecdh_rsa_cert(Config) ->
1736    CryptoSupport = crypto:supports(),
1737    case proplists:get_bool(ecdh, proplists:get_value(public_keys, CryptoSupport)) of
1738	true ->
1739            ClientFileBase = filename:join([proplists:get_value(priv_dir, Config), "ecdh_rsa"]),
1740            ServerFileBase = filename:join([proplists:get_value(priv_dir, Config), "ecdh_rsa"]),
1741            ClientChain = proplists:get_value(client_chain, Config, default_cert_chain_conf()),
1742            ServerChain = proplists:get_value(server_chain, Config, default_cert_chain_conf()),
1743            CertChainConf = gen_conf(ecdh_rsa, ecdh_rsa, ClientChain, ServerChain),
1744            GenCertData = public_key:pkix_test_data(CertChainConf),
1745            [{server_config, ServerConf},
1746             {client_config, ClientConf}] =
1747                x509_test:gen_pem_config_files(GenCertData, ClientFileBase, ServerFileBase),
1748
1749	    [{server_ecdh_rsa_opts, [{ssl_imp, new},{reuseaddr, true} | ServerConf]},
1750
1751	     {server_ecdh_rsa_verify_opts, [{ssl_imp, new},{reuseaddr, true},
1752                                            {verify, verify_peer} | ServerConf]},
1753
1754	     {client_ecdh_rsa_opts, ClientConf}
1755
1756             | Config];
1757	_ ->
1758	    Config
1759    end.
1760
1761make_rsa_ecdsa_cert(Config, Curve) ->
1762    CryptoSupport = crypto:supports(),
1763    case proplists:get_bool(ecdh, proplists:get_value(public_keys, CryptoSupport)) of
1764	true ->
1765            ClientFileBase = filename:join([proplists:get_value(priv_dir, Config),
1766                                            "rsa_ecdsa_" ++ atom_to_list(Curve)]),
1767            ServerFileBase = filename:join([proplists:get_value(priv_dir, Config),
1768                                            "rsa_ecdsa_" ++ atom_to_list(Curve)]),
1769            ClientChain = proplists:get_value(client_chain, Config, default_cert_chain_conf()),
1770            ServerChain = proplists:get_value(server_chain, Config, default_cert_chain_conf()),
1771            CertChainConf = gen_conf(ecdh_rsa, ecdh_rsa, ClientChain, ServerChain, Curve),
1772            GenCertData = public_key:pkix_test_data(CertChainConf),
1773            [{server_config, ServerConf},
1774             {client_config, ClientConf}] =
1775                x509_test:gen_pem_config_files(GenCertData, ClientFileBase, ServerFileBase),
1776
1777	    [{server_rsa_ecdsa_opts, [{ssl_imp, new},{reuseaddr, true} | ServerConf]},
1778	     {server_rsa_ecdsa_verify_opts, [{ssl_imp, new},{reuseaddr, true},
1779                                            {verify, verify_peer} | ServerConf]},
1780	     {client_rsa_ecdsa_opts, ClientConf} | Config];
1781	_ ->
1782	    Config
1783    end.
1784
1785
1786start_upgrade_server(Args) ->
1787    Node = proplists:get_value(node, Args),
1788    Result = spawn_link(Node, ?MODULE, run_upgrade_server, [Args]),
1789    receive
1790	{listen, up} ->
1791	    Result
1792    end.
1793
1794run_upgrade_server(Opts) ->
1795    Port = proplists:get_value(port, Opts),
1796    TimeOut = proplists:get_value(timeout, Opts, infinity),
1797    TcpOptions = proplists:get_value(tcp_options, Opts),
1798    SslOptions = proplists:get_value(ssl_options, Opts),
1799    Pid = proplists:get_value(from, Opts),
1800
1801    ct:log("~p:~p~ngen_tcp:listen(~p, ~p)~n", [?MODULE,?LINE, Port, TcpOptions]),
1802    {ok, ListenSocket} = gen_tcp:listen(Port, TcpOptions),
1803    Pid ! {listen, up},
1804    send_selected_port(Pid, Port, ListenSocket),
1805    ct:log("~p:~p~ngen_tcp:accept(~p)~n", [?MODULE,?LINE, ListenSocket]),
1806    {ok, AcceptSocket} = gen_tcp:accept(ListenSocket),
1807
1808    try
1809	{ok, SslAcceptSocket} = case TimeOut of
1810				    infinity ->
1811					ct:log("~p:~p~nssl:handshake(~p, ~p)~n",
1812							   [?MODULE,?LINE, AcceptSocket, SslOptions]),
1813					ssl:handshake(AcceptSocket, SslOptions);
1814				    _ ->
1815					ct:log("~p:~p~nssl:handshake(~p, ~p, ~p)~n",
1816							   [?MODULE,?LINE, AcceptSocket, SslOptions, TimeOut]),
1817					ssl:handshake(AcceptSocket, SslOptions, TimeOut)
1818				end,
1819	{Module, Function, Args} = proplists:get_value(mfa, Opts),
1820	Msg = apply(Module, Function, [SslAcceptSocket | Args]),
1821	ct:log("~p:~p~nUpgrade Server Msg: ~p ~n", [?MODULE,?LINE, Msg]),
1822	Pid ! {self(), Msg},
1823	receive
1824	    close ->
1825		ct:log("~p:~p~nUpgrade Server closing~n", [?MODULE,?LINE]),
1826		ssl:close(SslAcceptSocket)
1827	end
1828    catch error:{badmatch, Error} ->
1829	    Pid ! {self(), Error}
1830    end.
1831
1832start_upgrade_client(Args) ->
1833    Node = proplists:get_value(node, Args),
1834    spawn_link(Node, ?MODULE, run_upgrade_client, [Args]).
1835
1836run_upgrade_client(Opts) ->
1837    Host = proplists:get_value(host, Opts),
1838    Port = proplists:get_value(port, Opts),
1839    Pid = proplists:get_value(from, Opts),
1840    TcpOptions = proplists:get_value(tcp_options, Opts),
1841    SslOptions = proplists:get_value(ssl_options, Opts),
1842
1843    ct:log("~p:~p~ngen_tcp:connect(~p, ~p, ~p)~n",
1844		       [?MODULE,?LINE, Host, Port, TcpOptions]),
1845    {ok, Socket} = gen_tcp:connect(Host, Port, TcpOptions),
1846
1847    send_selected_port(Pid, Port, Socket),
1848
1849    ct:log("~p:~p~nssl:connect(~p, ~p)~n", [?MODULE,?LINE, Socket, SslOptions]),
1850    {ok, SslSocket} = ssl:connect(Socket, SslOptions),
1851
1852    {Module, Function, Args} = proplists:get_value(mfa, Opts),
1853    ct:log("~p:~p~napply(~p, ~p, ~p)~n",
1854		       [?MODULE,?LINE, Module, Function, [SslSocket | Args]]),
1855    Msg = apply(Module, Function, [SslSocket | Args]),
1856    ct:log("~p:~p~nUpgrade Client Msg: ~p ~n", [?MODULE,?LINE, Msg]),
1857    Pid ! {self(), Msg},
1858    receive
1859	close ->
1860	    ct:log("~p:~p~nUpgrade Client closing~n", [?MODULE,?LINE]),
1861	    ssl:close(SslSocket)
1862    end.
1863
1864start_upgrade_server_error(Args) ->
1865    Node = proplists:get_value(node, Args),
1866    Result = spawn_link(Node,?MODULE, run_upgrade_server_error, [Args]),
1867    receive
1868	{listen, up} ->
1869	    Result
1870    end.
1871
1872run_upgrade_server_error(Opts) ->
1873    Port = proplists:get_value(port, Opts),
1874    TimeOut = proplists:get_value(timeout, Opts, infinity),
1875    TcpOptions = proplists:get_value(tcp_options, Opts),
1876    SslOptions = proplists:get_value(ssl_options, Opts),
1877    Pid = proplists:get_value(from, Opts),
1878
1879    ct:log("~p:~p~ngen_tcp:listen(~p, ~p)~n", [?MODULE,?LINE, Port, TcpOptions]),
1880    {ok, ListenSocket} = gen_tcp:listen(Port, TcpOptions),
1881    Pid ! {listen, up},
1882    send_selected_port(Pid, Port, ListenSocket),
1883    ct:log("~p:~p~ngen_tcp:accept(~p)~n", [?MODULE,?LINE, ListenSocket]),
1884    {ok, AcceptSocket} = gen_tcp:accept(ListenSocket),
1885    Error = case TimeOut of
1886		infinity ->
1887		    ct:log("~p:~p~nssl:handshake(~p, ~p)~n",
1888				       [?MODULE,?LINE, AcceptSocket, SslOptions]),
1889		    ssl:handshake(AcceptSocket, SslOptions);
1890		_ ->
1891		    ct:log("~p:~p~nssl:ssl_handshake(~p, ~p, ~p)~n",
1892				       [?MODULE,?LINE, AcceptSocket, SslOptions, TimeOut]),
1893		    ssl:handshake(AcceptSocket, SslOptions, TimeOut)
1894	    end,
1895    Pid ! {self(), Error}.
1896
1897start_server_error(Args) ->
1898    Result = spawn_link(?MODULE, run_server_error, [Args]),
1899    receive
1900	{listen, up} ->
1901	    Result
1902    end.
1903
1904run_server_error(Opts) ->
1905    Port = proplists:get_value(port, Opts),
1906    Options = proplists:get_value(options, Opts),
1907    Pid = proplists:get_value(from, Opts),
1908    Transport =  proplists:get_value(transport, Opts, ssl),
1909    ct:log("~p:~p~nssl:listen(~p, ~p)~n", [?MODULE,?LINE, Port, Options]),
1910    case Transport:listen(Port, Options) of
1911	{ok, #sslsocket{} = ListenSocket} ->
1912	    %% To make sure error_client will
1913	    %% get {error, closed} and not {error, connection_refused}
1914	    Pid ! {listen, up},
1915	    send_selected_port(Pid, Port, ListenSocket),
1916	    ct:log("~p:~p~nssl:transport_accept(~p)~n", [?MODULE,?LINE, ListenSocket]),
1917	    case Transport:transport_accept(ListenSocket) of
1918		{error, _} = Error ->
1919		    Pid ! {self(), Error};
1920		{ok, AcceptSocket} ->
1921		    ct:log("~p:~p~nssl:ssl_accept(~p)~n", [?MODULE,?LINE, AcceptSocket]),
1922		    Error = ssl:handshake(AcceptSocket),
1923		    Pid ! {self(), Error}
1924	    end;
1925	{ok, ListenSocket} ->
1926	    Pid ! {listen, up},
1927	    send_selected_port(Pid, Port, ListenSocket),
1928	    ct:log("~p:~p~n~p:accept(~p)~n", [?MODULE,?LINE, Transport, ListenSocket]),
1929	     case Transport:accept(ListenSocket) of
1930		{error, _} = Error ->
1931		     Pid ! {self(), Error}
1932	     end;
1933	Error ->
1934	    %% Not really true but as this is an error test
1935	    %% this is what we want.
1936	    Pid ! {listen, up},
1937	    Pid ! {self(), Error}
1938    end.
1939
1940start_client_error(Args) ->
1941    Node = proplists:get_value(node, Args),
1942    spawn_link(Node, ?MODULE, run_client_error, [Args]).
1943
1944run_client_error(Opts) ->
1945    Host = proplists:get_value(host, Opts),
1946    Port = proplists:get_value(port, Opts),
1947    Pid = proplists:get_value(from, Opts),
1948    Transport = proplists:get_value(transport, Opts, ssl),
1949    Options = proplists:get_value(options, Opts),
1950    ct:log("~p:~p~nssl:connect(~p, ~p, ~p)~n", [?MODULE,?LINE, Host, Port, Options]),
1951    Error = Transport:connect(Host, Port, Options),
1952    case Error of
1953        {error, _} ->
1954            Pid ! {self(), Error};
1955        {ok, _Socket} ->
1956            receive
1957                {ssl_error, _, {tls_alert, _}} = SslError ->
1958                                Pid ! {self(), SslError}
1959            end;
1960        {ok, Socket, _Ext} ->
1961            ContOpts = proplists:get_value(continue_options, Opts, []),
1962            Result = Transport:handshake_continue(Socket, ContOpts),
1963            Pid ! {self(), Result}
1964    end.
1965
1966accepters(N) ->
1967    accepters([], N).
1968
1969accepters(Acc, 0) ->
1970    Acc;
1971accepters(Acc, N) ->
1972    receive
1973	{accepter, _, Server} ->
1974	    accepters([Server| Acc], N-1)
1975    end.
1976
1977
1978basic_test(COpts, SOpts, Config) ->
1979    SType = proplists:get_value(server_type, Config, erlang),
1980    CType = proplists:get_value(client_type, Config, erlang),
1981    {Server, Port} = start_server(SType, COpts, SOpts, Config),
1982    Client = start_client(CType, Port, COpts, Config),
1983    gen_check_result(Server, SType, Client, CType),
1984    stop(Server, Client).
1985
1986basic_alert(ClientOpts, ServerOpts, Config, Alert) ->
1987    SType = proplists:get_value(server_type, Config),
1988    CType = proplists:get_value(client_type, Config),
1989    run_basic_alert(SType, CType, ClientOpts, ServerOpts, Config, Alert).
1990
1991run_basic_alert(erlang, erlang, ClientOpts, ServerOpts, Config, Alert) ->
1992    {ClientNode, ServerNode, Hostname} = run_where(Config),
1993
1994    Server = start_server_error([{node, ServerNode}, {port, 0},
1995                                 {from, self()},
1996                                 {mfa, {ssl_test_lib, no_result, []}},
1997                                 {options, ServerOpts}]),
1998
1999    Port  = inet_port(Server),
2000
2001    Client = start_client_error([{node, ClientNode}, {port, Port},
2002                                 {host, Hostname},
2003                                 {from, self()},
2004                                 {mfa, {ssl_test_lib, no_result, []}},
2005                                 {options, ClientOpts}]),
2006
2007    check_server_alert(Server, Client, Alert);
2008run_basic_alert(openssl = SType, erlang, ClientOpts, ServerOpts, Config, Alert) ->
2009    {ClientNode, _, Hostname} = run_where(Config),
2010    {_Server, Port} = start_server(SType, ClientOpts, ServerOpts, Config),
2011    wait_for_openssl_server(Port, proplists:get_value(protocol, Config)),
2012    Client = start_client_error([{node, ClientNode}, {port, Port},
2013                                 {host, Hostname},
2014                                 {from, self()},
2015                                 {mfa, {ssl_test_lib, no_result, []}},
2016					      {options, ClientOpts}]),
2017
2018    check_client_alert(Client, Alert);
2019run_basic_alert(erlang, openssl = CType, ClientOpts, ServerOpts, Config, Alert) ->
2020    {_, ServerNode, Hostname} = run_where(Config),
2021    Server = start_server_error([{node, ServerNode}, {port, 0},
2022                                 {host, Hostname},
2023                                 {from, self()},
2024                                 {mfa, {ssl_test_lib, no_result, []}},
2025                                 {options, ServerOpts}]),
2026    Port  = inet_port(Server),
2027    start_client(CType, Port, ClientOpts, Config),
2028
2029    check_server_alert(Server, Alert).
2030
2031
2032ecc_test(Expect, COpts, SOpts, CECCOpts, SECCOpts, Config) ->
2033    {Server, Port} = start_server_ecc(erlang, SOpts, Expect, SECCOpts, Config),
2034    Client = start_client_ecc(erlang, Port, COpts, Expect, CECCOpts, Config),
2035    check_result(Server, ok, Client, ok),
2036    stop(Server, Client).
2037
2038ecc_test_error(COpts, SOpts, CECCOpts, SECCOpts, Config) ->
2039    {Server, Port} = start_server_ecc_error(erlang, SOpts, SECCOpts, Config),
2040    Client = start_client_ecc_error(erlang, Port, COpts, CECCOpts, Config),
2041    check_server_alert(Server, Client, insufficient_security).
2042
2043start_client(openssl, Port, ClientOpts, Config) ->
2044    Version = protocol_version(Config),
2045    Exe = "openssl",
2046    Ciphers = proplists:get_value(ciphers, ClientOpts, ssl:cipher_suites(default,Version)),
2047    Groups0 = proplists:get_value(groups, ClientOpts),
2048    CertArgs = openssl_cert_options(ClientOpts, client),
2049    AlpnArgs = openssl_alpn_options(proplists:get_value(alpn, ClientOpts, undefined)),
2050    NpnArgs =  openssl_npn_options(proplists:get_value(np, ClientOpts, undefined)),
2051    Reconnect = openssl_reconect_option(proplists:get_value(reconnect, ClientOpts, false)),
2052    MaxFragLen = openssl_maxfag_option(proplists:get_value(maxfrag, ClientOpts, false)),
2053    SessionArgs =  proplists:get_value(session_args, ClientOpts, []),
2054    HostName = proplists:get_value(hostname, ClientOpts, net_adm:localhost()),
2055    Debug = openssl_debug_options(),
2056
2057    Exe = "openssl",
2058    Args0 =  case Groups0 of
2059                undefined ->
2060                     ["s_client",
2061                      "-verify", "2",
2062                      "-connect", hostname_format(HostName) ++ ":" ++ integer_to_list(Port), cipher_flag(Version),
2063                      ciphers(Ciphers, Version),
2064                      version_flag(Version)]
2065                         ++ CertArgs ++ AlpnArgs ++ NpnArgs ++ Reconnect ++ MaxFragLen ++ SessionArgs
2066                         ++ Debug;
2067                 Group ->
2068                     ["s_client",
2069                      "-verify", "2",
2070                      "-connect", hostname_format(HostName) ++ ":" ++ integer_to_list(Port), cipher_flag(Version),
2071                      ciphers(Ciphers, Version), "-groups", Group,
2072                      version_flag(Version)]
2073                         ++ CertArgs ++ AlpnArgs ++ NpnArgs ++ Reconnect ++ MaxFragLen ++ SessionArgs
2074                         ++ Debug
2075                 end,
2076    Args = maybe_force_ipv4(Args0),
2077    OpenSslPort = portable_open_port(Exe, Args),
2078    true = port_command(OpenSslPort, "Hello world"),
2079    OpenSslPort;
2080
2081start_client(erlang, Port, ClientOpts, Config) ->
2082    {ClientNode, _, Hostname} = run_where(Config),
2083    KeyEx = proplists:get_value(check_keyex, Config, false),
2084    start_client([{node, ClientNode}, {port, Port},
2085			       {host, Hostname},
2086			       {from, self()},
2087			       {mfa, {ssl_test_lib, check_key_exchange_send_active, [KeyEx]}},
2088			       {options, ClientOpts}]).
2089
2090%% Workaround for running tests on machines where openssl
2091%% s_client would use an IPv6 address with localhost. As
2092%% this test suite and the ssl application is not prepared
2093%% for that we have to force s_client to use IPv4 if
2094%% OpenSSL supports IPv6.
2095maybe_force_ipv4(Args0) ->
2096    case is_ipv6_supported() of
2097        true ->
2098            Args0 ++ ["-4"];
2099        false ->
2100            Args0
2101    end.
2102
2103start_client_ecc(erlang, Port, ClientOpts, Expect, ECCOpts, Config) ->
2104    {ClientNode, _, Hostname} = run_where(Config),
2105    ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
2106                               {host, Hostname},
2107                               {from, self()},
2108                               {mfa, {?MODULE, check_ecc, [client, Expect]}},
2109                               {options,
2110                                ECCOpts ++
2111                                [{verify, verify_peer} | ClientOpts]}]).
2112
2113start_client_ecc_error(erlang, Port, ClientOpts, ECCOpts, Config) ->
2114    {ClientNode, _, Hostname} = run_where(Config),
2115    ssl_test_lib:start_client_error([{node, ClientNode}, {port, Port},
2116                                     {host, Hostname},
2117                                     {from, self()},
2118                                     {options,
2119                                      ECCOpts ++
2120                                      [{verify, verify_peer} | ClientOpts]}]).
2121
2122
2123start_server(openssl, ClientOpts, ServerOpts, Config) ->
2124    Port = inet_port(node()),
2125    Version = protocol_version(Config),
2126    Exe = "openssl",
2127    CertArgs = openssl_cert_options(ServerOpts, server),
2128    Ciphers = proplists:get_value(ciphers, ClientOpts, ssl:cipher_suites(default,Version)),
2129    Groups0 = proplists:get_value(groups, ServerOpts),
2130    SigAlgs = proplists:get_value(openssl_sigalgs, Config, undefined),
2131    SessionArgs = proplists:get_value(session_args, Config, []),
2132    Debug = openssl_debug_options(),
2133
2134    Args =  case Groups0 of
2135                undefined ->
2136                    ["s_server", "-accept", integer_to_list(Port), cipher_flag(Version),
2137                     ciphers(Ciphers, Version),
2138                     version_flag(Version)] ++ sig_algs(SigAlgs) ++ CertArgs ++ SessionArgs ++ Debug;
2139                Group ->
2140                       ["s_server", "-accept", integer_to_list(Port), cipher_flag(Version),
2141                        ciphers(Ciphers, Version), "-groups", Group,
2142                        version_flag(Version)] ++ sig_algs(SigAlgs) ++ CertArgs ++ SessionArgs ++ Debug
2143            end,
2144    OpenSslPort = portable_open_port(Exe, Args),
2145    true = port_command(OpenSslPort, "Hello world"),
2146    {OpenSslPort, Port};
2147start_server(erlang, _, ServerOpts, Config) ->
2148    {_, ServerNode, _} = run_where(Config),
2149    KeyEx = proplists:get_value(check_keyex, Config, false),
2150    Server = start_server([{node, ServerNode}, {port, 0},
2151                           {from, self()},
2152                           {mfa, {ssl_test_lib,
2153                                  check_key_exchange_send_active,
2154                                  [KeyEx]}},
2155                           {options, [{verify, verify_peer} | ServerOpts]}]),
2156    {Server, inet_port(Server)}.
2157
2158sig_algs(undefined) ->
2159    [];
2160sig_algs(SigAlgs) ->
2161    ["-sigalgs " ++ SigAlgs].
2162
2163cipher_flag('tlsv1.3') ->
2164     "-ciphersuites";
2165cipher_flag(_) ->
2166    "-cipher".
2167
2168ciphers([#{}| _] = Ciphers, Version) ->
2169    Strs = [ssl_cipher_format:suite_map_to_openssl_str(Cipher) || Cipher <- Ciphers],
2170    ciphers_concat(Version, Strs, "");
2171ciphers(Ciphers, Version) ->
2172    ciphers_concat(Version, Ciphers, "").
2173
2174ciphers_concat(_, [], [":" | Acc]) ->
2175    lists:append(lists:reverse(Acc));
2176ciphers_concat('tlsv1.3' = Version, [Head| Tail], Acc) ->
2177    case Head of
2178        "TLS" ++ _ ->
2179            ciphers_concat(Version, Tail, [":", Head | Acc]);
2180        _ ->
2181            ciphers_concat(Version, Tail, Acc)
2182    end;
2183ciphers_concat(Version,  [Head| Tail], Acc) ->
2184    ciphers_concat(Version, Tail, [":", Head | Acc]).
2185
2186openssl_alpn_options(undefined) ->
2187    [];
2188openssl_alpn_options(Alpn) ->
2189    ["-alpn", Alpn].
2190
2191openssl_npn_options(undefined) ->
2192    [];
2193openssl_npn_options(Npn) ->
2194    ["-nextprotoneg", Npn].
2195
2196openssl_reconect_option(false) ->
2197    [];
2198openssl_reconect_option(true) ->
2199    ["-reconnect"].
2200openssl_maxfag_option(false) ->
2201    [];
2202openssl_maxfag_option(Int) ->
2203    ["-maxfraglen", integer_to_list(Int)].
2204
2205openssl_debug_options() ->
2206    ["-msg", "-debug"].
2207%%
2208openssl_debug_options(PrivDir) ->
2209    case is_keylogfile_supported() of
2210        true ->
2211            ["-msg", "-debug","-keylogfile", PrivDir ++ "keylog"];
2212        false ->
2213            ["-msg", "-debug"]
2214    end.
2215
2216is_keylogfile_supported() ->
2217    [{_,_, Bin}]  = crypto:info_lib(),
2218    case binary_to_list(Bin) of
2219	"OpenSSL 1.1.1" ++ _ ->
2220	    true;
2221	_ ->
2222	    false
2223    end.
2224
2225start_server_with_raw_key(erlang, ServerOpts, Config) ->
2226    {_, ServerNode, _} = run_where(Config),
2227    Server = start_server([{node, ServerNode}, {port, 0},
2228                           {from, self()},
2229                           {mfa, {ssl_test_lib,
2230                                  send_recv_result_active,
2231                                  []}},
2232                           {options,
2233                            [{verify, verify_peer} | ServerOpts]}]),
2234    {Server, inet_port(Server)}.
2235
2236start_server_ecc(erlang, ServerOpts, Expect, ECCOpts, Config) ->
2237    {_, ServerNode, _} = run_where(Config),
2238    Server = start_server([{node, ServerNode}, {port, 0},
2239                                        {from, self()},
2240                                        {mfa, {?MODULE, check_ecc, [server, Expect]}},
2241                                        {options,
2242                                         ECCOpts ++
2243                                         [{verify, verify_peer} | ServerOpts]}]),
2244    {Server, inet_port(Server)}.
2245
2246start_server_ecc_error(erlang, ServerOpts, ECCOpts, Config) ->
2247    {_, ServerNode, _} = run_where(Config),
2248    Server = start_server_error([{node, ServerNode}, {port, 0},
2249                                              {from, self()},
2250                                              {options,
2251                                               ECCOpts ++
2252                                               [{verify, verify_peer} | ServerOpts]}]),
2253    {Server, inet_port(Server)}.
2254
2255gen_check_result(Server, erlang, Client, erlang) ->
2256    check_result(Server, ok, Client, ok);
2257gen_check_result(Server, erlang, _, _) ->
2258    check_result(Server, ok);
2259gen_check_result(_, _, Client, erlang) ->
2260    check_result(Client, ok);
2261gen_check_result(_,openssl, _, openssl) ->
2262    ok.
2263
2264stop(Port1, Port2) when is_port(Port1), is_port(Port2) ->
2265    close_port(Port1),
2266    close_port(Port2);
2267stop(Port, Pid) when is_port(Port) ->
2268    close_port(Port),
2269    close(Pid);
2270stop(Pid, Port) when is_port(Port) ->
2271    close_port(Port),
2272    close(Pid);
2273stop(Client, Server)  ->
2274    close(Server),
2275    close(Client).
2276
2277
2278openssl_cert_options(Opts, Role) ->
2279    Cert = proplists:get_value(certfile, Opts, undefined),
2280    Key = proplists:get_value(keyfile, Opts, undefined),
2281    CA = proplists:get_value(cacertfile, Opts, undefined),
2282    case CA of
2283        undefined ->
2284            case cert_option("-cert", Cert) ++ cert_option("-key", Key) of
2285                [] when Role == server ->
2286                    ["-nocert"];
2287                Other ->
2288                    Other
2289            end;
2290        _ ->
2291            cert_option("-cert", Cert) ++  cert_option("-CAfile", CA)
2292                ++ cert_option("-cert_chain", CA) ++
2293                cert_option("-key", Key) ++ openssl_verify(Opts) ++ ["2"]
2294    end.
2295
2296openssl_verify(Opts) ->
2297      case proplists:get_value(fail_if_no_peer_cert, Opts, undefined) of
2298          true ->
2299              ["-Verify"];
2300          _ ->
2301              ["-verify"]
2302      end.
2303
2304cert_option(_, undefined) ->
2305    [];
2306cert_option("-cert_chain", Value) ->
2307    case portable_cmd("openssl", ["version"]) of
2308	"OpenSSL 1.1.1" ++ _ ->
2309	    ["-cert_chain", Value];
2310        _ ->
2311            ""
2312     end;
2313cert_option(Opt, Value) ->
2314    [Opt, Value].
2315
2316supported_eccs(Opts) ->
2317    ToCheck = proplists:get_value(eccs, Opts, []),
2318    Supported = ssl:eccs(),
2319    lists:all(fun(Curve) -> lists:member(Curve, Supported) end, ToCheck).
2320
2321check_ecc(SSL, Role, Expect) ->
2322    {ok, Data} = ssl:connection_information(SSL),
2323    case lists:keyfind(ecc, 1, Data) of
2324        {ecc, {named_curve, Expect}} -> ok;
2325        Other -> {error, Role, Expect, Other}
2326    end.
2327
2328inet_port(Pid) when is_pid(Pid)->
2329    receive
2330	{Pid, {port, Port}} ->
2331	    Port
2332    end;
2333
2334inet_port(Node) ->
2335    {Port, Socket} = do_inet_port(Node),
2336     rpc:call(Node, gen_tcp, close, [Socket]),
2337     Port.
2338
2339do_inet_port(Node) ->
2340    {ok, Socket} = rpc:call(Node, gen_tcp, listen, [0, [{reuseaddr, true}]]),
2341    {ok, Port} = rpc:call(Node, inet, port, [Socket]),
2342    {Port, Socket}.
2343
2344no_result(_) ->
2345    no_result_msg.
2346
2347trigger_renegotiate(Socket, [ErlData, N]) ->
2348     {ok, [{session_id, Id}]} = ssl:connection_information(Socket,  [session_id]),
2349    trigger_renegotiate(Socket, ErlData, N, Id).
2350
2351trigger_renegotiate(Socket, _, 0, Id) ->
2352    ct:sleep(1000),
2353    case ssl:connection_information(Socket,  [session_id]) of
2354        {ok, [{session_id, Id}]} ->
2355	    fail_session_not_renegotiated;
2356	%% Tests that uses this function will not reuse
2357	%% sessions so if we get a new session id the
2358	%% renegotiation has succeeded.
2359        {ok, [{session_id, _}]} ->
2360	    ok;
2361	{error, closed} ->
2362	    fail_session_fatal_alert_during_renegotiation;
2363	{error, timeout} ->
2364	    fail_timeout
2365    end;
2366
2367trigger_renegotiate(Socket, ErlData, N, Id) ->
2368    ssl:send(Socket, ErlData),
2369    trigger_renegotiate(Socket, ErlData, N-1, Id).
2370
2371
2372send_selected_port(Pid, 0, #sslsocket{} = Socket) ->
2373    {ok, {_, NewPort}} = ssl:sockname(Socket),
2374    Pid ! {self(), {port, NewPort}};
2375send_selected_port(Pid, 0, Socket) ->
2376    {ok, {_, NewPort}} = inet:sockname(Socket),
2377    Pid ! {self(), {port, NewPort}};
2378send_selected_port(_,_,_) ->
2379    ok.
2380
2381
2382available_suites(Version) ->
2383    [ssl_cipher_format:suite_bin_to_map(Suite) ||
2384	Suite  <-  ssl_cipher:filter_suites(ssl_cipher:suites(Version))].
2385
2386
2387rsa_non_signed_suites(Version) ->
2388    lists:filter(fun({rsa, _, _}) ->
2389			 false;
2390		    (_) ->
2391			 true
2392		 end,
2393		 available_suites(Version)).
2394
2395ecdsa_suites(Version) ->
2396     lists:filter(fun({ecdhe_ecdsa, _, _}) ->
2397                        true;
2398                   (_) ->
2399                        false
2400                end,
2401                available_suites(Version)).
2402
2403openssl_dsa_suites() ->
2404    Ciphers = ssl:cipher_suites(openssl),
2405    lists:filter(fun(Str) -> string_regex_filter(Str, "DSS")
2406		 end, Ciphers).
2407
2408openssl_ecdsa_suites() ->
2409    Ciphers = ssl:cipher_suites(openssl),
2410    lists:filter(fun(Str) -> string_regex_filter(Str, "ECDHE-ECDSA")
2411		 end, Ciphers).
2412
2413
2414openssl_filter(FilterStr) ->
2415    Ciphers = string:tokens(portable_cmd("openssl", ["ciphers"]), ":"),
2416    lists:filter(fun(Str) -> string_regex_filter(Str, FilterStr)
2417		 end, Ciphers).
2418
2419
2420string_regex_filter(Str, Search) when is_list(Str) ->
2421    case re:run(Str, Search, []) of
2422	nomatch ->
2423	    false;
2424	_ ->
2425	    true
2426    end;
2427string_regex_filter(_Str, _Search) ->
2428    false.
2429
2430ecdh_dh_anonymous_suites(Version) ->
2431    ssl:filter_cipher_suites([ssl_cipher_format:suite_bin_to_map(S) || S <- ssl_cipher:anonymous_suites(Version)],
2432                             [{key_exchange,
2433                               fun(dh_anon) ->
2434                                       true;
2435                                  (ecdh_anon) ->
2436                                       true;
2437                                  (_) ->
2438                                       false
2439                               end}]).
2440
2441pem_to_der(File) ->
2442    {ok, PemBin} = file:read_file(File),
2443    public_key:pem_decode(PemBin).
2444
2445der_to_pem(File, Entries) ->
2446    PemBin = public_key:pem_encode(Entries),
2447    file:write_file(File, PemBin).
2448
2449cipher_result(Socket, Result) ->
2450    {ok, Info} = ssl:connection_information(Socket),
2451    Result = {ok, {proplists:get_value(protocol, Info), proplists:get_value(selected_cipher_suite, Info)}},
2452    ct:log("~p:~p~nSuccessfull connect: ~p~n", [?MODULE,?LINE, Result]),
2453    %% Importante to send two packets here
2454    %% to properly test "cipher state" handling
2455    Hello = "Hello\n",
2456    World = " world\n",
2457    ssl:send(Socket, Hello),
2458    ct:sleep(500),
2459    ssl:send(Socket, World),
2460    Expected = Hello ++ World,
2461    Expected = active_recv(Socket, length(Expected)),
2462    ok.
2463
2464session_info_result(Socket) ->
2465    {ok, Info} = ssl:connection_information(Socket,  [session_id, cipher_suite]),
2466    Info.
2467
2468public_key(#'PrivateKeyInfo'{privateKeyAlgorithm =
2469				 #'PrivateKeyInfo_privateKeyAlgorithm'{algorithm = ?rsaEncryption},
2470			     privateKey = Key}) ->
2471    public_key:der_decode('RSAPrivateKey', iolist_to_binary(Key));
2472
2473public_key(#'PrivateKeyInfo'{privateKeyAlgorithm =
2474				 #'PrivateKeyInfo_privateKeyAlgorithm'{algorithm = ?'id-dsa'},
2475			     privateKey = Key}) ->
2476    public_key:der_decode('DSAPrivateKey', iolist_to_binary(Key));
2477public_key(Key) ->
2478    Key.
2479
2480state([{data,[{"State", {_StateName, StateData}}]} | _]) -> %% gen_statem
2481    StateData;
2482state([{data,[{"State", State}]} | _]) -> %% gen_server
2483    State;
2484state([{data,[{"StateData", State}]} | _]) -> %% gen_fsm
2485     State;
2486state([_ | Rest]) ->
2487    state(Rest).
2488
2489is_protocol_version(Ver) ->
2490    is_tls_version(Ver) orelse
2491        is_dtls_version(Ver).
2492
2493is_tls_version('tlsv1.3') ->
2494    true;
2495is_tls_version('tlsv1.2') ->
2496    true;
2497is_tls_version('tlsv1.1') ->
2498    true;
2499is_tls_version('tlsv1') ->
2500    true;
2501is_tls_version(_) ->
2502    false.
2503
2504is_dtls_version('dtlsv1.2') ->
2505    true;
2506is_dtls_version('dtlsv1') ->
2507    true;
2508is_dtls_version(_) ->
2509    false.
2510
2511openssl_tls_version_support(Version, Config0) ->
2512    %% Check if version is supported
2513    Config = make_rsa_cert(Config0),
2514    ServerOpts = proplists:get_value(server_rsa_opts, Config),
2515    Port = inet_port(node()),
2516    CaCertFile = proplists:get_value(cacertfile, ServerOpts),
2517    CertFile = proplists:get_value(certfile, ServerOpts),
2518    KeyFile = proplists:get_value(keyfile, ServerOpts),
2519    Exe = "openssl",
2520    Args0 = ["s_server", "-accept",
2521            integer_to_list(Port), "-CAfile", CaCertFile,
2522            "-cert", CertFile,"-key", KeyFile],
2523    Args = maybe_force_ipv4(Args0),
2524    OpensslPort = portable_open_port(Exe, Args),
2525
2526    try wait_for_openssl_server(Port, tls) of
2527        ok ->
2528            case  ssl:connect("localhost", Port, [{versions, [Version]}]) of
2529                {ok, Socket} ->
2530                    ssl:close(Socket),
2531                    close_port(OpensslPort),
2532                    true;
2533                {error, {tls_alert, {protocol_version, _}}} ->
2534                    ct:pal("Openssl does not support ~p", [Version]),
2535                    close_port(OpensslPort),
2536                    false;
2537                {error, {tls_alert, Alert}} ->
2538                    ct:pal("Openssl returned alert ~p", [Alert]),
2539                    close_port(OpensslPort),
2540                    false
2541            end
2542    catch
2543        _:_ ->
2544            ct:pal("Openssl does not support ~p", [Version]),
2545            close_port(OpensslPort),
2546            false
2547    end.
2548
2549init_protocol_version(Version, Config)
2550  when Version == 'dtlsv1.2'; Version == 'dtlsv1' ->
2551    ssl:stop(),
2552    application:load(ssl),
2553    application:set_env(ssl, dtls_protocol_version, [Version]),
2554    ssl:start(),
2555    NewConfig = proplists:delete(protocol_opts, proplists:delete(protocol, Config)),
2556    [{protocol, dtls}, {protocol_opts, [{protocol, dtls}]} | NewConfig];
2557
2558init_protocol_version(Version, Config) ->
2559    ssl:stop(),
2560    application:load(ssl),
2561    application:set_env(ssl, protocol_version, [Version]),
2562    ssl:start(),
2563    NewConfig = proplists:delete(protocol_opts, proplists:delete(protocol, Config)),
2564    [{protocol, tls} | NewConfig].
2565
2566clean_protocol_version(Config) ->
2567    proplists:delete(version, proplists:delete(protocol_opts, proplists:delete(protocol, Config))).
2568
2569sufficient_crypto_support(Version)
2570  when Version == 'tlsv1.3' ->
2571    CryptoSupport = crypto:supports(),
2572    lists:member(rsa_pkcs1_pss_padding, proplists:get_value(rsa_opts, CryptoSupport)) andalso
2573    lists:member(x448, proplists:get_value(curves, CryptoSupport));
2574sufficient_crypto_support(Version)
2575  when Version == 'tlsv1.2'; Version == 'dtlsv1.2' ->
2576    CryptoSupport = crypto:supports(),
2577    proplists:get_bool(sha256, proplists:get_value(hashs, CryptoSupport));
2578sufficient_crypto_support(cipher_ec) ->
2579    CryptoSupport = crypto:supports(),
2580    proplists:get_bool(ecdh, proplists:get_value(public_keys, CryptoSupport));
2581sufficient_crypto_support(_) ->
2582    true.
2583
2584check_key_exchange_send_active(Socket, false) ->
2585    send_recv_result_active(Socket);
2586check_key_exchange_send_active(Socket, KeyEx) ->
2587    {ok, Info} =
2588        ssl:connection_information(Socket, [cipher_suite, protocol]),
2589    Suite = proplists:get_value(cipher_suite, Info),
2590    Version = proplists:get_value(protocol, Info),
2591    true = check_key_exchange(Suite, KeyEx, Version),
2592    send_recv_result_active(Socket).
2593
2594check_key_exchange({KeyEx,_, _}, KeyEx, _) ->
2595    ct:pal("Kex: ~p", [KeyEx]),
2596    true;
2597check_key_exchange({KeyEx,_,_,_}, KeyEx, _) ->
2598    ct:pal("Kex: ~p", [KeyEx]),
2599    true;
2600check_key_exchange(KeyEx1, KeyEx2, Version) ->
2601    ct:pal("Kex: ~p ~p", [KeyEx1, KeyEx2]),
2602    case Version of
2603        'tlsv1.2' ->
2604            v_1_2_check(element(1, KeyEx1), KeyEx2);
2605        'dtlsv1.2' ->
2606            v_1_2_check(element(1, KeyEx1), KeyEx2);
2607        _ ->
2608            ct:pal("Negotiated ~p  Expected ~p", [KeyEx1, KeyEx2]),
2609            false
2610    end.
2611
2612v_1_2_check(ecdh_ecdsa, ecdh_rsa) ->
2613    true;
2614v_1_2_check(ecdh_rsa, ecdh_ecdsa) ->
2615    true;
2616v_1_2_check(_, _) ->
2617    false.
2618
2619send_recv_result(Socket) ->
2620    Data =  "Hello world",
2621    ssl:send(Socket, Data),
2622    {ok, Data} = ssl:recv(Socket, length(Data)),
2623    ok.
2624
2625send_recv_result_active(Socket) ->
2626    Data =  "Hello world",
2627    ssl:send(Socket, Data),
2628    Data = active_recv(Socket, length(Data)),
2629    ok.
2630
2631send_recv_result_active(Socket, Data) ->
2632    ssl:send(Socket, Data),
2633    Data = active_recv(Socket, length(Data)),
2634    ok.
2635
2636send(Pid, Data) ->
2637    Pid ! {data, Data},
2638    receive
2639        {Pid, ok} ->
2640            ok;
2641        {Pid, Reason} ->
2642            {error, Reason}
2643    end.
2644
2645check_active_receive(Pid, Data) ->
2646    Pid ! {active_receive, Data},
2647    check_active_receive_loop(Pid, Data).
2648
2649check_active_receive_loop(Pid, Data) ->
2650    receive
2651        {Pid, Data} ->
2652            ct:log("(~p) Received: ~p~n   (from ~p)~n", [self(), Data, Pid]),
2653            Data;
2654        {Pid, Data2} ->
2655            ct:log("(~p) Received unexpected message: ~p~n   (from ~p)~n",
2656                   [self(), Data2, Pid]),
2657            check_active_receive_loop(Pid, Data)
2658    end.
2659
2660update_keys(Pid, Type) ->
2661    Pid ! {update_keys, Type},
2662    receive
2663        {Pid, ok} ->
2664            ok;
2665        {Pid, Reason} ->
2666            {error, Reason}
2667    end.
2668
2669send_recv_result_active_once(Socket) ->
2670    Data = "Hello world",
2671    ssl:send(Socket, Data),
2672    active_once_recv_list(Socket, length(Data)).
2673
2674%% This function can verify the following functionalities in clients:
2675%% - session resumption, sending/receiving application data, receiving session tickets
2676%% - verifying if client early data is accepted/rejected
2677verify_active_session_resumption(Socket, SessionResumption) ->
2678    verify_active_session_resumption(Socket, SessionResumption, wait_reply, no_tickets, no_early_data).
2679%%
2680verify_active_session_resumption(Socket, SessionResumption, WaitReply) ->
2681    verify_active_session_resumption(Socket, SessionResumption, WaitReply, no_tickets, no_early_data).
2682%%
2683verify_active_session_resumption(Socket, SessionResumption, WaitReply, TicketOption) ->
2684    verify_active_session_resumption(Socket, SessionResumption, WaitReply, TicketOption, no_early_data).
2685%%
2686verify_active_session_resumption(Socket, SessionResumption, WaitForReply, TicketOption, EarlyData) ->
2687    case ssl:connection_information(Socket, [session_resumption]) of
2688        {ok, [{session_resumption, SessionResumption}]} ->
2689            Msg = boolean_to_log_msg(SessionResumption),
2690            ct:log("~p:~p~nSession resumption verified! (expected ~p, got ~p)!",
2691                   [?MODULE, ?LINE, Msg, Msg]);
2692        {ok, [{session_resumption, Got0}]} ->
2693            Expected = boolean_to_log_msg(SessionResumption),
2694            Got = boolean_to_log_msg(Got0),
2695            ct:fail("~p:~p~nFailed to verify session resumption! (expected ~p, got ~p)",
2696                    [?MODULE, ?LINE, Expected, Got]);
2697        {error, Reason} ->
2698            ct:fail("~p:~p~nFailed to verify session resumption! Reason: ~p",
2699                    [?MODULE, ?LINE, Reason])
2700    end,
2701
2702    Data =  "Hello world",
2703    ssl:send(Socket, Data),
2704    case WaitForReply of
2705        wait_reply ->
2706            Data = active_recv(Socket, length(Data));
2707        no_reply ->
2708            ok;
2709        Else1 ->
2710            ct:fail("~p:~p~nFaulty parameter: ~p", [?MODULE, ?LINE, Else1])
2711    end,
2712    Tickets =
2713        case TicketOption of
2714            {tickets, N} ->
2715                receive_tickets(N);
2716            no_tickets ->
2717                ok;
2718            Else2 ->
2719                ct:fail("~p:~p~nFaulty parameter: ~p", [?MODULE, ?LINE, Else2])
2720        end,
2721    case EarlyData of
2722        {verify_early_data, Atom} ->
2723            case verify_early_data(Atom) of
2724                ok ->
2725                    Tickets;
2726                Else ->
2727                    ct:fail("~p:~p~nFailed to verify early_data! (expected ~p, got ~p)",
2728                            [?MODULE, ?LINE, Atom, Else])
2729            end;
2730        no_early_data ->
2731            Tickets;
2732        Else3 ->
2733            ct:fail("~p:~p~nFaulty parameter: ~p", [?MODULE, ?LINE, Else3])
2734    end.
2735
2736verify_server_early_data(Socket, WaitForReply, EarlyData) ->
2737    case ssl:connection_information(Socket, [session_resumption]) of
2738        {ok, [{session_resumption, true}]} ->
2739            Msg = boolean_to_log_msg(true),
2740            ct:log("~p:~p~nSession resumption verified! (expected ~p, got ~p)!",
2741                   [?MODULE, ?LINE, Msg, Msg]);
2742        {ok, [{session_resumption, Got0}]} ->
2743            Expected = boolean_to_log_msg(true),
2744            Got = boolean_to_log_msg(Got0),
2745            ct:fail("~p:~p~nFailed to verify session resumption! (expected ~p, got ~p)",
2746                    [?MODULE, ?LINE, Expected, Got]);
2747        {error, Reason} ->
2748            ct:fail("~p:~p~nFailed to verify session resumption! Reason: ~p",
2749                    [?MODULE, ?LINE, Reason])
2750    end,
2751    Data =  "Hello world",
2752    ssl:send(Socket, Data),
2753    Reply =
2754        case EarlyData of
2755            no_early_data ->
2756                Data;
2757            _ ->
2758                binary_to_list(EarlyData) ++ Data
2759        end,
2760    ct:log("Expected Reply: ~p~n", [Reply]),
2761    case WaitForReply of
2762        wait_reply ->
2763            Reply = active_recv(Socket, length(Reply));
2764        no_reply ->
2765            ok;
2766        Else1 ->
2767            ct:fail("~p:~p~nFaulty parameter: ~p", [?MODULE, ?LINE, Else1])
2768    end,
2769    ok.
2770
2771verify_session_ticket_extension([Ticket0|_], MaxEarlyDataSize) ->
2772    #{ticket := #new_session_ticket{
2773                   extensions = #{early_data :=
2774                                      #early_data_indication_nst{
2775                                         indication = Size}}}} = Ticket0,
2776      case Size of
2777          MaxEarlyDataSize ->
2778              ct:log("~p:~p~nmax_early_data_size verified! (expected ~p, got ~p)!",
2779                     [?MODULE, ?LINE, MaxEarlyDataSize, Size]);
2780          Else ->
2781              ct:log("~p:~p~nFailed to verify max_early_data_size! (expected ~p, got ~p)!",
2782                     [?MODULE, ?LINE, MaxEarlyDataSize, Else])
2783      end.
2784
2785update_session_ticket_extension([Ticket|_], MaxEarlyDataSize) ->
2786    #{ticket := #new_session_ticket{
2787                   extensions = #{early_data :=
2788                                      #early_data_indication_nst{
2789                                         indication = Size}}}} = Ticket,
2790    ct:log("~p:~p~nOverwrite max_early_data_size (from ~p to ~p)!",
2791                     [?MODULE, ?LINE, Size, MaxEarlyDataSize]),
2792    #{ticket := #new_session_ticket{
2793                   extensions = #{early_data := Extensions0}} = NST0} = Ticket,
2794    Extensions = #{early_data => #early_data_indication_nst{
2795                                    indication = MaxEarlyDataSize}},
2796    NST = NST0#new_session_ticket{extensions = Extensions},
2797    [Ticket#{ticket => NST}].
2798
2799boolean_to_log_msg(true) ->
2800    "OK";
2801boolean_to_log_msg(false) ->
2802    "FAIL".
2803
2804receive_tickets(N) ->
2805    receive_tickets(N, []).
2806%%
2807receive_tickets(0, Acc) ->
2808    Acc;
2809receive_tickets(N, Acc) ->
2810    receive
2811        {ssl, session_ticket, Ticket} ->
2812            receive_tickets(N - 1, [Ticket|Acc])
2813    end.
2814
2815check_tickets(Client) ->
2816    receive
2817        {Client, Tickets} ->
2818            Tickets
2819    after
2820        5000 ->
2821            ct:fail("~p:~p~nNo tickets received!", [?MODULE, ?LINE])
2822    end.
2823
2824active_recv_loop(Pid, SslPort, Data) ->
2825    case active_recv(SslPort, length(Data)) of
2826        Data ->
2827            ct:log("(~p) [openssl server] Received: ~p~n   (forward to PID=~p)~n",
2828                   [self(), Data, Pid]),
2829            Pid ! {self(), Data};
2830        Unexpected ->
2831            ct:log("(~p) [openssl server] Received unexpected: ~p~n   (dropping message)~n", [self(), Unexpected]),
2832            active_recv_loop(Pid, SslPort, Data)
2833    end.
2834
2835active_recv(Socket, N) ->
2836    active_recv(Socket, N, []).
2837
2838active_recv(_Socket, 0, Acc) ->
2839    Acc;
2840active_recv(_Socket, N, Acc) when N < 0 ->
2841    {_, T} = lists:split(0 - N, Acc),
2842    T;
2843active_recv(Socket, N, Acc) ->
2844    receive
2845        %% Filter {ssl, Socket, {early_data, Atom}} messages
2846	{ssl, Socket, Bytes} when not is_tuple(Bytes) ->
2847            active_recv(Socket, N-data_length(Bytes),  Acc ++ Bytes);
2848        {Socket, {data, Bytes0}} ->
2849            Bytes = filter_openssl_debug_data(Bytes0),
2850            active_recv(Socket, N-data_length(Bytes),  Acc ++ Bytes)
2851    end.
2852
2853
2854data_length(Bytes) when is_list(Bytes) ->
2855    length(Bytes);
2856data_length(Bytes) when is_binary(Bytes)->
2857    size(Bytes).
2858
2859filter_openssl_debug_data(Bytes) ->
2860    re:replace(Bytes,
2861               "(read.*\n|write to.*\n|[\\dabcdefABCDEF]{4,4} -.*\n|>>> .*\n|<<< .*\n|    \\d\\d.*\n|KEYUPDATE\n|.*Read BLOCK\n)*",
2862               "", [global,{return, list}]).
2863
2864active_once_recv(_Socket, 0) ->
2865    ok;
2866active_once_recv(Socket, N) ->
2867    receive
2868	{ssl, Socket, Bytes} ->
2869            ssl:setopts(Socket, [{active, once}]),
2870            active_once_recv(Socket, N-byte_size(Bytes))
2871    end.
2872
2873active_once_recv_list(_Socket, 0) ->
2874    ok;
2875active_once_recv_list(Socket, N) ->
2876    receive
2877	{ssl, Socket, Bytes} ->
2878            ssl:setopts(Socket, [{active, once}]),
2879            active_once_recv_list(Socket, N-length(Bytes))
2880    end.
2881recv_disregard(_Socket, 0) ->
2882    ok;
2883recv_disregard(Socket, N) ->
2884    {ok, Bytes} = ssl:recv(Socket, 0),
2885    recv_disregard(Socket, N-byte_size(Bytes)).
2886
2887active_disregard(_Socket, 0) ->
2888    ok;
2889active_disregard(Socket, N) ->
2890    receive
2891	{ssl, Socket, Bytes} ->
2892            active_disregard(Socket, N-byte_size(Bytes))
2893    end.
2894active_once_disregard(_Socket, 0) ->
2895    ok;
2896active_once_disregard(Socket, N) ->
2897    receive
2898	{ssl, Socket, Bytes} ->
2899            ssl:setopts(Socket, [{active, once}]),
2900            active_once_disregard(Socket, N-byte_size(Bytes))
2901    end.
2902
2903is_ipv6_supported() ->
2904    case portable_cmd("openssl", ["version"]) of
2905        "OpenSSL 0.9.8" ++ _ -> % Does not support IPv6
2906            false;
2907        "OpenSSL 1.0" ++ _ ->   % Does not support IPv6
2908            false;
2909        "LibreSSL 3" ++ _->
2910            false;
2911        _ ->
2912            true
2913    end.
2914
2915
2916is_sane_oppenssl_client() ->
2917    [{_,_, Bin}]  = crypto:info_lib(),
2918    case binary_to_list(Bin) of
2919	"OpenSSL 0.9" ++ _ ->
2920	    false;
2921	_ ->
2922	    true
2923    end.
2924
2925is_sane_oppenssl_pss(rsa_pss_pss) ->
2926    case portable_cmd("openssl",["version"]) of
2927        "OpenSSL 1.1.1" ++ Rest ->
2928            hd(Rest) >= $c;
2929        _ ->
2930            false
2931    end;
2932is_sane_oppenssl_pss(rsa_pss_rsae) ->
2933    case portable_cmd("openssl",["version"]) of
2934        "OpenSSL 1.1.1" ++ _ ->
2935            true;
2936        _ ->
2937            false
2938    end.
2939
2940is_fips(openssl) ->
2941    VersionStr = portable_cmd("openssl",["version"]),
2942    case re:split(VersionStr, "fips") of
2943	[_] ->
2944	    false;
2945	_ ->
2946	    true
2947    end;
2948is_fips(crypto) ->
2949    [{_,_, Bin}]  = crypto:info_lib(),
2950    case re:split(Bin, <<"fips">>) of
2951	[_] ->
2952	    false;
2953	_ ->
2954	    true
2955    end;
2956is_fips(_) ->
2957    false.
2958
2959%% Acctual support is tested elsewhere, this is to exclude some LibreSSL and OpenSSL versions
2960openssl_sane_dtls() ->
2961    case portable_cmd("openssl", ["version"]) of
2962        "OpenSSL 0." ++ _ ->
2963            false;
2964        "OpenSSL 1.0.1s-freebsd" ++ _ ->
2965            false;
2966        "OpenSSL 1.0.2k-freebsd" ++ _ ->
2967            false;
2968        "OpenSSL 1.0.2" ++ _ ->
2969            false;
2970        "OpenSSL 1.0.0" ++ _ ->
2971            false;
2972        "OpenSSL" ++ _ ->
2973            true;
2974        "LibreSSL 2.7" ++ _ ->
2975            true;
2976        _ ->
2977            false
2978        end.
2979
2980check_sane_openssl_version(Version) ->
2981    case supports_ssl_tls_version(Version) of
2982	true ->
2983	    case {Version, portable_cmd("openssl",["version"])} of
2984                {'dtlsv1', "OpenSSL 0" ++ _} ->
2985		    false;
2986		{'dtlsv1.2', "OpenSSL 0" ++ _} ->
2987		    false;
2988                {'dtlsv1.2', "OpenSSL 1.0.2" ++ _} ->
2989		    false;
2990		{'dtlsv1',  "OpenSSL 1.0.0" ++ _} ->
2991		    false;
2992                {'dtlsv1', _} ->
2993		    not is_fips(openssl);
2994		{'dtlsv1.2', _} ->
2995		    not is_fips(openssl);
2996		{_, "OpenSSL 1.0.2" ++ _} ->
2997		    true;
2998		{_, "OpenSSL 1.0.1" ++ _} ->
2999		    true;
3000		{'tlsv1.2', "OpenSSL 1.0.0" ++ _} ->
3001		    false;
3002		{'tlsv1.1', "OpenSSL 1.0.0" ++ _} ->
3003		    false;
3004		{'tlsv1.2', "OpenSSL 0" ++ _} ->
3005		    false;
3006		{'tlsv1.1', "OpenSSL 0" ++ _} ->
3007		    false;
3008                {'tlsv1', "OpenSSL 0" ++ _} ->
3009		    false;
3010		{_, _} ->
3011		    true
3012	    end;
3013	false ->
3014	    false
3015    end.
3016check_sane_openssl_renegotiate(Config, Version) when  Version == 'tlsv1';
3017                                                      Version == 'tlsv1.1';
3018                                                      Version == 'tlsv1.2' ->
3019    case portable_cmd("openssl", ["version"]) of
3020	"OpenSSL 1.0.1c" ++ _ ->
3021	    {skip, "Known renegotiation bug in OpenSSL"};
3022	"OpenSSL 1.0.1b" ++ _ ->
3023	    {skip, "Known renegotiation bug in OpenSSL"};
3024	"OpenSSL 1.0.1a" ++ _ ->
3025	    {skip, "Known renegotiation bug in OpenSSL"};
3026	"OpenSSL 1.0.1 " ++ _ ->
3027	    {skip, "Known renegotiation bug in OpenSSL"};
3028        "LibreSSL 3.0.2" ++ _ ->
3029	    {skip, "Known renegotiation bug in LibreSSL"};
3030        "LibreSSL 3.1" ++ _ ->
3031	    {skip, "Known renegotiation bug in LibreSSL"};
3032        _ ->
3033	    check_sane_openssl_renegotiate(Config)
3034    end;
3035check_sane_openssl_renegotiate(Config, _) ->
3036    check_sane_openssl_renegotiate(Config).
3037
3038check_sane_openssl_renegotiate(Config) ->
3039    case portable_cmd("openssl", ["version"]) of
3040	"OpenSSL 1.0.0" ++ _ ->
3041	    {skip, "Known renegotiation bug in OpenSSL"};
3042	"OpenSSL 0.9.8" ++ _ ->
3043	    {skip, "Known renegotiation bug in OpenSSL"};
3044	"OpenSSL 0.9.7" ++ _ ->
3045	    {skip, "Known renegotiation bug in OpenSSL"};
3046        "LibreSSL 2." ++ _ ->
3047	    {skip, "Known renegotiation bug in LibreSSL"};
3048        "LibreSSL 3." ++ _ ->
3049	    {skip, "Known renegotiation bug in LibreSSL"};
3050	_ ->
3051	    Config
3052    end.
3053
3054openssl_allows_client_renegotiate(Config) ->
3055     case portable_cmd("openssl", ["version"]) of
3056	"OpenSSL 1.1" ++ _ ->
3057	    {skip, "OpenSSL does not allow client renegotiation"};
3058	"LibreSSL" ++ _ ->
3059	    {skip, "LibreSSL does not allow client renegotiation"};
3060         _ ->
3061             Config
3062     end.
3063
3064openssl_allows_server_renegotiate(Config) ->
3065     case portable_cmd("openssl", ["version"]) of
3066	"LibreSSL 3.1" ++ _ ->
3067	    {skip, "LibreSSL 3.1 does not allow server renegotiation"};
3068         _ ->
3069             Config
3070     end.
3071
3072
3073enough_openssl_crl_support("OpenSSL 0." ++ _) -> false;
3074enough_openssl_crl_support(_) -> true.
3075
3076wait_for_openssl_server(Port, tls) ->
3077    do_wait_for_openssl_tls_server(Port, 10);
3078wait_for_openssl_server(_Port, dtls) ->
3079    ok. %% No need to wait for DTLS over UDP server
3080        %% client will retransmitt until it is up.
3081
3082do_wait_for_openssl_tls_server(_, 0) ->
3083    exit(failed_to_connect_to_openssl);
3084do_wait_for_openssl_tls_server(Port, N) ->
3085    case gen_tcp:connect("localhost", Port, []) of
3086	{ok, S} ->
3087	    gen_tcp:close(S),
3088            ok;
3089	_  ->
3090	    ct:sleep(?SLEEP),
3091	    do_wait_for_openssl_tls_server(Port, N-1)
3092    end.
3093
3094version_flag(tlsv1) ->
3095    "-tls1";
3096version_flag('tlsv1.1') ->
3097    "-tls1_1";
3098version_flag('tlsv1.2') ->
3099    "-tls1_2";
3100version_flag('tlsv1.3') ->
3101    "-tls1_3";
3102version_flag(sslv3) ->
3103    "-ssl3";
3104version_flag(sslv2) ->
3105    "-ssl2";
3106version_flag('dtlsv1.2') ->
3107    "-dtls1_2";
3108version_flag('dtlsv1') ->
3109    "-dtls1".
3110
3111-define(OPENSSL_QUIT, "Q\n").
3112close_port(Port) ->
3113    catch port_command(Port, ?OPENSSL_QUIT),
3114    close_loop(Port, 500, false).
3115
3116close_loop(Port, Time, SentClose) ->
3117    receive
3118	{Port, {data,Debug}} when is_port(Port) ->
3119	    ct:log("openssl ~s~n",[Debug]),
3120	    close_loop(Port, Time, SentClose);
3121	{ssl,_,Msg} ->
3122	    ct:log("ssl Msg ~s~n",[Msg]),
3123	    close_loop(Port, Time, SentClose);
3124	{Port, closed} ->
3125	    ct:log("Port Closed~n",[]),
3126	    ok;
3127	{'EXIT', Port, Reason} ->
3128	    ct:log("Port Closed ~p~n",[Reason]),
3129	    ok;
3130	Msg ->
3131	    ct:log("Port Msg ~p~n",[Msg]),
3132	    close_loop(Port, Time, SentClose)
3133    after Time ->
3134	    case SentClose of
3135		false ->
3136		    ct:log("Closing port ~n",[]),
3137		    catch erlang:port_close(Port),
3138		    close_loop(Port, Time, true);
3139		true ->
3140		    ct:log("Timeout~n",[])
3141	    end
3142    end.
3143
3144portable_open_port("openssl" = Exe, Args0) ->
3145    IsWindows = case os:type() of
3146                    {win32, _} -> true;
3147                    _ -> false
3148                end,
3149    case IsWindows andalso os:getenv("WSLENV") of
3150        false ->
3151            AbsPath = os:find_executable(Exe),
3152            ct:pal("open_port({spawn_executable, ~p}, [{args, ~p}, stderr_to_stdout]).",
3153                   [AbsPath, Args0]),
3154            open_port({spawn_executable, AbsPath},
3155                      [{args, Args0}, stderr_to_stdout]);
3156	_ ->
3157	    %% I can't get the new windows version of openssl.exe to be stable
3158	    %% certain server tests are failing for no reason.
3159	    %% This is using "linux" openssl via wslenv
3160
3161	    Translate = fun([_Drive|":/" ++ _ ]= Path) ->
3162				string:trim(os:cmd("wsl wslpath -u " ++ Path));
3163			   (Arg) ->
3164				Arg
3165			end,
3166	    Args1 = [Translate(Arg) || Arg <- Args0],
3167	    Args = ["/C","wsl","openssl"| Args1] ++ ["2>&1"],
3168	    Cmd =  os:find_executable("cmd"),
3169	    ct:pal("open_port({spawn_executable, ~p}, [{args, ~p}, stderr_to_stdout]).", [Cmd,Args]),
3170	    open_port({spawn_executable, Cmd},
3171		      [{args, Args}, stderr_to_stdout, hide])
3172    end;
3173portable_open_port(Exe, Args) ->
3174    AbsPath = os:find_executable(Exe),
3175    ct:pal("open_port({spawn_executable, ~p}, [{args, ~p}, stderr_to_stdout]).", [AbsPath, Args]),
3176    open_port({spawn_executable, AbsPath},
3177	      [{args, Args}, stderr_to_stdout]).
3178
3179portable_cmd(Exe, Args) ->
3180    Port = portable_open_port(Exe, Args),
3181    receive
3182         {Port, {data, Data}} ->
3183            catch erlang:port_close(Port),
3184            Data
3185    end.
3186
3187supports_ssl_tls_version(Version) when Version == sslv2;
3188                                       Version == sslv3 ->
3189
3190    case ubuntu_legacy_support() of
3191        true ->
3192            case portable_cmd("openssl", ["version"]) of
3193                "OpenSSL 1.0.1" ++ _ ->
3194                    Version =/= sslv2;
3195                "OpenSSL 1" ++ _ ->
3196                    false;
3197                %% Appears to be broken
3198                "OpenSSL 0.9.8.o" ++ _ ->
3199                    false;
3200                _ ->
3201                    VersionFlag = version_flag(Version),
3202                    Exe = "openssl",
3203                    Args = ["s_client", VersionFlag],
3204                    [{trap_exit, Trap}] = process_info(self(), [trap_exit]),
3205                    process_flag(trap_exit, true),
3206                    Port = portable_open_port(Exe, Args),
3207                    Bool = do_supports_ssl_tls_version(Port, ""),
3208                    consume_port_exit(Port),
3209                    process_flag(trap_exit, Trap),
3210                    Bool
3211            end;
3212        false ->
3213            false
3214    end;
3215supports_ssl_tls_version(Version) ->
3216    VersionFlag = version_flag(Version),
3217    Exe = "openssl",
3218    Args = ["s_client", VersionFlag],
3219    Port = portable_open_port(Exe, Args),
3220    do_supports_ssl_tls_version(Port, "").
3221
3222do_supports_ssl_tls_version(Port, Acc) ->
3223    receive
3224        {Port, {data, Data}} ->
3225            case Acc ++ Data of
3226                "unknown option"  ++ _ ->
3227                    false;
3228                "s_client: Option unknown" ++ _->
3229                    false;
3230                Info when length(Info) >= 24 ->
3231                    ct:pal("~p", [Info]),
3232                    true;
3233                _ ->
3234                    do_supports_ssl_tls_version(Port, Acc ++ Data)
3235            end
3236    after 1000 ->
3237            true
3238    end.
3239
3240ubuntu_legacy_support() ->
3241    case os:type() of
3242        {unix, linux} ->
3243            Issue = os:cmd("more /etc/issue"),
3244            case re:run(Issue, "Ubuntu 1[6-9]+", [global]) of
3245                nomatch ->
3246                    true;
3247                _ ->
3248                    false
3249            end;
3250        _ ->
3251            true
3252    end.
3253
3254ssl_options(Option, Config) when is_atom(Option) ->
3255    ProtocolOpts = proplists:get_value(protocol_opts, Config, []),
3256    Opts = proplists:get_value(Option, Config, []),
3257    Opts ++ ProtocolOpts;
3258ssl_options(Options, Config) ->
3259    ProtocolOpts = proplists:get_value(protocol_opts, Config, []),
3260    Options ++ ProtocolOpts.
3261
3262protocol_version(Config) ->
3263   case proplists:get_value(version, Config, undefined) of
3264       undefined ->
3265           protocol_version(Config, atom);
3266       Version ->
3267           Version
3268   end.
3269protocol_version(Config, tuple) ->
3270    case proplists:get_value(protocol, Config) of
3271	dtls ->
3272	    dtls_record:highest_protocol_version(dtls_record:supported_protocol_versions());
3273	_ ->
3274	    tls_record:highest_protocol_version(tls_record:supported_protocol_versions())
3275   end;
3276
3277protocol_version(Config, atom) ->
3278    case proplists:get_value(protocol, Config) of
3279	dtls ->
3280	   dtls_record:protocol_version(protocol_version(Config, tuple));
3281	_ ->
3282           tls_record:protocol_version(protocol_version(Config, tuple))
3283   end.
3284
3285protocol_options(Config, Options) ->
3286    Protocol = proplists:get_value(protocol, Config, tls),
3287    {Protocol, Opts} = lists:keyfind(Protocol, 1, Options),
3288    Opts.
3289
3290ct_log_supported_protocol_versions(Config) ->
3291    case proplists:get_value(protocol, Config) of
3292	dtls ->
3293	    ct:log("DTLS version ~p~n ", [dtls_record:supported_protocol_versions()]);
3294	_ ->
3295	    ct:log("TLS/SSL version ~p~n ", [tls_record:supported_protocol_versions()])
3296    end.
3297
3298clean_env() ->
3299    application:unset_env(ssl, protocol_version),
3300    application:unset_env(ssl, dtls_protocol_version),
3301    application:unset_env(ssl, session_lifetime),
3302    application:unset_env(ssl, session_cb),
3303    application:unset_env(ssl, session_cb_init_args),
3304    application:unset_env(ssl, session_cache_client_max),
3305    application:unset_env(ssl, session_cache_server_max),
3306    application:unset_env(ssl, ssl_pem_cache_clean),
3307    application:unset_env(ssl, bypass_pem_cache),
3308    application:unset_env(ssl, alert_timeout),
3309    application:unset_env(ssl, internal_active_n).
3310%%
3311clean_env(keep_version) ->
3312    application:unset_env(ssl, session_lifetime),
3313    application:unset_env(ssl, session_cb),
3314    application:unset_env(ssl, session_cb_init_args),
3315    application:unset_env(ssl, session_cache_client_max),
3316    application:unset_env(ssl, session_cache_server_max),
3317    application:unset_env(ssl, ssl_pem_cache_clean),
3318    application:unset_env(ssl, bypass_pem_cache),
3319    application:unset_env(ssl, alert_timeout),
3320    application:unset_env(ssl, internal_active_n).
3321
3322clean_start() ->
3323    ssl:stop(),
3324    application:load(ssl),
3325    clean_env(),
3326    ssl:start().
3327%%
3328clean_start(keep_version) ->
3329    ssl:stop(),
3330    application:load(ssl),
3331    clean_env(keep_version),
3332    ssl:start().
3333
3334
3335tls_version('dtlsv1' = Atom) ->
3336    dtls_v1:corresponding_tls_version(dtls_record:protocol_version(Atom));
3337tls_version('dtlsv1.2' = Atom) ->
3338    dtls_v1:corresponding_tls_version(dtls_record:protocol_version(Atom));
3339tls_version(Atom) ->
3340    tls_record:protocol_version(Atom).
3341
3342consume_port_exit(OpenSSLPort) ->
3343    receive
3344        {'EXIT', OpenSSLPort, _} ->
3345            ok
3346    end.
3347
3348hardcode_rsa_key(1) ->
3349    #'RSAPrivateKey'{
3350       version = 'two-prime',
3351       modulus = 23995666614853919027835084074500048897452890537492185072956789802729257783422306095699263934587064480357348855732149402060270996295002843755712064937715826848741191927820899197493902093529581182351132392364214171173881547273475904587683433713767834856230531387991145055273426806331200574039205571401702219159773947658558490957010003143162250693492642996408861265758000254664396313741422909188635443907373976005987612936763564996605457102336549804831742940035613780926178523017685712710473543251580072875247250504243621640157403744718833162626193206685233710319205099867303242759099560438381385658382486042995679707669,
3352       publicExponent = 17,
3353       privateExponent = 11292078406990079542510627799764728892919007311761028269626724613049062486316379339152594792746853873109340637991599718616598115903530750002688030558925094987642913848386305504703012749896273497577003478759630198199473669305165131570674557041773098755873191241407597673069847908861741446606684974777271632545629600685952292605647052193819136445675100211504432575554351515262198132231537860917084269870590492135731720141577986787033006338680118008484613510063003323516659048210893001173583018220214626635609151105287049126443102976056146630518124476470236027123782297108342869049542023328584384300970694412006494684657,
3354       prime1 = 169371138592582642967021557955633494538845517070305333860805485424261447791289944610138334410987654265476540480228705481960508520379619587635662291973699651583489223555422528867090299996446070521801757353675026048850480903160224210802452555900007597342687137394192939372218903554801584969667104937092080815197,
3355       prime2 = 141675062317286527042995673340952251894209529891636708844197799307963834958115010129693036021381525952081167155681637592199810112261679449166276939178032066869788822014115556349519329537177920752776047051833616197615329017439297361972726138285974555338480581117881706656603857310337984049152655480389797687577,
3356       exponent1 = 119556097830058336212015217380447172615655659108450823901745048534772786676204666783627059584226579481512852103690850928442711896738555003036938088452023283470698275450886490965004917644550167427154181661417665446247398284583687678213495921811770068712485038160606780733330990744565824684470897602653233516609,
3357       exponent2 = 41669135975672507953822256864985956439473391144599032012999352737636422046504414744027363535700448809435637398729893409470532385959317485048904982111185902020526124121798693043976273393287623750816484427009887116945685005129205106462566511260580751570141347387612266663707016855981760014456663376585234613993,
3358       coefficient = 76837684977089699359024365285678488693966186052769523357232308621548155587515525857011429902602352279058920284048929101483304120686557782043616693940283344235057989514310975192908256494992960578961614059245280827077951132083993754797053182279229469590276271658395444955906108899267024101096069475145863928441,
3359       otherPrimeInfos = asn1_NOVALUE};
3360
3361hardcode_rsa_key(2) ->
3362    #'RSAPrivateKey'{
3363       version = 'two-prime',
3364       modulus = 21343679768589700771839799834197557895311746244621307033143551583788179817796325695589283169969489517156931770973490560582341832744966317712674900833543896521418422508485833901274928542544381247956820115082240721897193055368570146764204557110415281995205343662628196075590438954399631753508888358737971039058298703003743872818150364935790613286541190842600031570570099801682794056444451081563070538409720109449780410837763602317050353477918147758267825417201591905091231778937606362076129350476690460157227101296599527319242747999737801698427160817755293383890373574621116766934110792127739174475029121017282777887777,
3365       publicExponent = 17,
3366       privateExponent = 18832658619343853622211588088997845201745658451136447382185486691577805721584993260814073385267196632785528033211903435807948675951440868570007265441362261636545666919252206383477878125774454042314841278013741813438699754736973658909592256273895837054592950290554290654932740253882028017801960316533503857992358685308186680144968293076156011747178275038098868263178095174694099811498968993700538293188879611375604635940554394589807673542938082281934965292051746326331046224291377703201248790910007232374006151098976879987912446997911775904329728563222485791845480864283470332826504617837402078265424772379987120023773,
3367       prime1 = 146807662748886761089048448970170315054939768171908279335181627815919052012991509112344782731265837727551849787333310044397991034789843793140419387740928103541736452627413492093463231242466386868459637115999163097726153692593711599245170083315894262154838974616739452594203727376460632750934355508361223110419,
3368       prime2 = 145385325050081892763917667176962991350872697916072592966410309213561884732628046256782356731057378829876640317801978404203665761131810712267778698468684631707642938779964806354584156202882543264893826268426566901882487709510744074274965029453915224310656287149777603803201831202222853023280023478269485417083,
3369       exponent1 = 51814469205489445090252393754177758254684624060673510353593515699736136004585238510239335081623236845018299924941168250963996835808180162284853901555621683602965806809675350150634081614988136541809283687999704622726877773856604093851236499993845033701707873394143336209718962603456693912094478414715725803677,
3370       exponent2 = 51312467664734785681382706062457526359131540440966797517556579722433606376221663384746714140373192528191755406283051201483646739222992016094510128871300458249756331334105225772206172777487956446433115153562317730076172132768497908567634716277852432109643395464627389577600646306666889302334125933506877206029,
3371       coefficient = 30504662229874176232343608562807118278893368758027179776313787938167236952567905398252901545019583024374163153775359371298239336609182249464886717948407152570850677549297935773605431024166978281486607154204888016179709037883348099374995148481968169438302456074511782717758301581202874062062542434218011141540,
3372       otherPrimeInfos = asn1_NOVALUE};
3373hardcode_rsa_key(3) ->
3374    #'RSAPrivateKey'{
3375       version = 'two-prime',
3376       modulus = 25089040456112869869472694987833070928503703615633809313972554887193090845137746668197820419383804666271752525807484521370419854590682661809972833718476098189250708650325307850184923546875260207894844301992963978994451844985784504212035958130279304082438876764367292331581532569155681984449177635856426023931875082020262146075451989132180409962870105455517050416234175675478291534563995772675388370042873175344937421148321291640477650173765084699931690748536036544188863178325887393475703801759010864779559318631816411493486934507417755306337476945299570726975433250753415110141783026008347194577506976486290259135429,
3377       publicExponent = 17,
3378       privateExponent = 8854955455098659953931539407470495621824836570223697404931489960185796768872145882893348383311931058684147950284994536954265831032005645344696294253579799360912014817761873358888796545955974191021709753644575521998041827642041589721895044045980930852625485916835514940558187965584358347452650930302268008446431977397918214293502821599497633970075862760001650736520566952260001423171553461362588848929781360590057040212831994258783694027013289053834376791974167294527043946669963760259975273650548116897900664646809242902841107022557239712438496384819445301703021164043324282687280801738470244471443835900160721870265,
3379       prime1 = 171641816401041100605063917111691927706183918906535463031548413586331728772311589438043965564336865070070922328258143588739626712299625805650832695450270566547004154065267940032684307994238248203186986569945677705100224518137694769557564475390859269797990555863306972197736879644001860925483629009305104925823,
3380       prime2 =146170909759497809922264016492088453282310383272504533061020897155289106805616042710009332510822455269704884883705830985184223718261139908416790475825625309815234508695722132706422885088219618698987115562577878897003573425367881351537506046253616435685549396767356003663417208105346307649599145759863108910523,
3381       exponent1 = 60579464612132153154728441333538327425711971378777222246428851853999433684345266860486105493295364142377972586444050678378691780811632637288529186629507258781295583787741625893888579292084087601124818789392592131211843947578009918667375697196773859928702549128225990187436545756706539150170692591519448797349,
3382       exponent2 = 137572620950115585809189662580789132500998007785886619351549079675566218169991569609420548245479957900898715184664311515467504676010484619686391036071176762179044243478326713135456833024206699951987873470661533079532774988581535389682358631768109586527575902839864474036157372334443583670210960715165278974609,
3383       coefficient = 15068630434698373319269196003209754243798959461311186548759287649485250508074064775263867418602372588394608558985183294561315208336731894947137343239541687540387209051236354318837334154993136528453613256169847839789803932725339395739618592522865156272771578671216082079933457043120923342632744996962853951612,
3384       otherPrimeInfos = asn1_NOVALUE};
3385hardcode_rsa_key(4) ->
3386    #'RSAPrivateKey'{
3387       version ='two-prime',
3388       modulus = 28617237755030755643854803617273584643843067580642149032833640135949799721163782522787597288521902619948688786051081993247908700824196122780349730169173433743054172191054872553484065655968335396052034378669869864779940355219732200954630251223541048434478476115391643898092650304645086338265930608997389611376417609043761464100338332976874588396803891301015812818307951159858145399281035705713082131199940309445719678087542976246147777388465712394062188801177717719764254900022006288880246925156931391594131839991579403409541227225173269459173129377291869028712271737734702830877034334838181789916127814298794576266389,
3389       publicExponent = 17,
3390       privateExponent = 26933870828264240605980991639786903194205240075898493207372837775011576208154148256741268036255908348187001210401018346586267012540419880263858569570986761169933338532757527109161473558558433313931326474042230460969355628442100895016122589386862163232450330461545076609969553227901257730132640573174013751883368376011370428995523268034111482031427024082719896108094847702954695363285832195666458915142143884210891427766607838346722974883433132513540317964796373298134261669479023445911856492129270184781873446960437310543998533283339488055776892320162032014809906169940882070478200435536171854883284366514852906334641,
3391       prime1 = 177342190816702392178883147766999616783253285436834252111702533617098994535049411784501174309695427674025956656849179054202187436663487378682303508229883753383891163725167367039879190685255046547908384208614573353917213168937832054054779266431207529839577747601879940934691505396807977946728204814969824442867,
3392       prime2 = 161367340863680900415977542864139121629424927689088951345472941851682581254789586032968359551717004797621579428672968948552429138154521719743297455351687337112710712475376510559020211584326773715482918387500187602625572442687231345855402020688502483137168684570635690059254866684191216155909970061793538842967,
3393       exponent1 = 62591361464718491357252875682470452982324688977706206627659717747211409835899792394529826226951327414362102349476180842659595565881230839534930649963488383547255704844176717778780890830090016428673547367746320007264898765507470136725216211681602657590439205035957626212244060728285168687080542875871702744541,
3394       exponent2 = 28476589564178982426348978152495139111074987239250991413906989738532220221433456358759122273832412611344984605059935696803369847909621479954699550944415412431654831613301737157474154985469430655673456186029444871051571607533040825739188591886206320553618003159523945304574388238386685203984112363845918619347,
3395       coefficient = 34340318160575773065401929915821192439103777558577109939078671096408836197675640654693301707202885840826672396546056002756167635035389371579540325327619480512374920136684787633921441576901246290213545161954865184290700344352088099063404416346968182170720521708773285279884132629954461545103181082503707725012,
3396       otherPrimeInfos = asn1_NOVALUE};
3397
3398hardcode_rsa_key(5) ->
3399    #'RSAPrivateKey'{
3400       version= 'two-prime',
3401       modulus = 26363170152814518327068346871197765236382539835597898797762992537312221863402655353436079974302838986536256364057947538018476963115004626096654613827403121905035011992899481598437933532388248462251770039307078647864188314916665766359828262009578648593031111569685489178543405615478739906285223620987558499488359880003693226535420421293716164794046859453204135383236667988765227190694994861629971618548127529849059769249520775574008363789050621665120207265361610436965088511042779948238320901918522125988916609088415989475825860046571847719492980547438560049874493788767083330042728150253120940100665370844282489982633,
3402       publicExponent = 17,
3403       privateExponent = 10855423004100095781734025182257903332628104638187370093196526338893267826106975733767797636477639582691399679317978398007608161282648963686857782164224814902073240232370374775827384395689278778574258251479385325591136364965685903795223402003944149420659869469870495544106108194608892902588033255700759382142132115013969680562678811046675523365751498355532768935784747314021422035957153013494814430893022253205880275287307995039363642554998244274484818208792520243113824379110193356010059999642946040953102866271737127640405568982049887176990990501963784502429481034227543991366980671390566584211881030995602076468001,
3404       prime1 =163564135568104310461344551909369650951960301778977149705601170951529791054750122905880591964737953456660497440730575925978769763154927541340839715938951226089095007207042122512586007411328664679011914120351043948122025612160733403945093961374276707993674792189646478659304624413958625254578122842556295400709,
3405       prime2 = 161179405627326572739107057023381254841260287988433675196680483761672455172873134522398837271764104320975746111042211695289319249471386600030523328069395763313848583139553961129874895374324504709512019736703349829576024049432816885712623938437949550266365056310544300920756181033500610331519029869549723159637,
3406       exponent1 = 115457036871603042678596154288966812436677860079277988027483179495197499568058910286503947269226790675289762899339230065396778656344654735064122152427494983121714122734382674714766593466820233891067233496718383963380253373289929461608301619793607087995535147427985749641862087821617853120878674947686796753441,
3407       exponent2 = 142217122612346975946270932667689342506994371754500301644129838613240401623123353990351915239791856753802128921507833848784693455415929352968108818884760967629866396887841730408713142977345151214275311532385308673155315337734838428569962298621720191411498579097539089047726042088382891468987379296661520434973,
3408       coefficient = 40624877259097915043489529504071755460170951428490878553842519165800720914888257733191322215286203357356050737713125202129282154441426952501134581314792133018830748896123382106683994268028624341502298766844710276939303555637478596035491641473828661569958212421472263269629366559343208764012473880251174832392,
3409       otherPrimeInfos = asn1_NOVALUE};
3410hardcode_rsa_key(6) ->
3411    #'RSAPrivateKey'{
3412       version = 'two-prime',
3413       modulus = 22748888494866396715768692484866595111939200209856056370972713870125588774286266397044592487895293134537316190976192161177144143633669641697309689280475257429554879273045671863645233402796222694405634510241820106743648116753479926387434021380537483429927516962909367257212902212159798399531316965145618774905828756510318897899298783143203190245236381440043169622358239226123652592179006905016804587837199618842875361941208299410035232803124113612082221121192550063791073372276763648926636149384299189072950588522522800393261949880796214514243704858378436010975184294077063518776479282353562934591448646412389762167039,
3414       publicExponent = 17,
3415       privateExponent = 6690849557313646092873144848490175032923294179369428344403739373566349639495960705013115437616262686628622409110644753287395336362844012263914614494257428655751435080307550548130951000822418439531068973600535325512837681398082331290421770994275730420566916753796872722709677121223470117509210872101652580854566448661533030419787125312956120661097410038933324613372774190658239039998357548275441758790939430824924502690997433186652165055694361752689819209062683281242276039100201318203707142383491769671330743466041394101421674581185260900666085723130684175548215193875544802254923825103844262661010117443222587769713,
3416       prime1 = 164748737139489923768181260808494855987398781964531448608652166632780898215212977127034263859971474195908846263894581556691971503119888726148555271179103885786024920582830105413607436718060544856016793981261118694063993837665813285582095833772675610567592660039821387740255651489996976698808018635344299728063,
3417       prime2 = 138082323967104548254375818343885141517788525705334488282154811252858957969378263753268344088034079842223206527922445018725900110643394926788280539200323021781309918753249061620424428562366627334409266756720941754364262467100514166396917565961434203543659974860389803369482625510495464845206228470088664021953,
3418       exponent1 = 19382204369351755737433089506881747763223386113474288071606137250915399790025056132592266336467232258342217207517009594904937823896457497193947678962247515974826461245038835931012639613889475865413740468383661022831058098548919210068481862796785365949128548239978986792971253116470232552800943368864035262125,
3419       exponent2 = 48734937870742781736838524121371226418043009072470995864289933383361985165662916618800592031070851709019955245149098241903258862580021738866451955011878713569874088971734962924855680669070574353320917678842685325069739694270769705787147376221682660074232932303666989424523279591939575827719845342384234360689,
3420       coefficient = 81173034184183681160439870161505779100040258708276674532866007896310418779840630960490793104541748007902477778658270784073595697910785917474138815202903114440800310078464142273778315781957021015333260021813037604142367434117205299831740956310682461174553260184078272196958146289378701001596552915990080834227,
3421       otherPrimeInfos = asn1_NOVALUE}.
3422
3423hardcode_rsa_1024_key(1) ->
3424    #'RSAPrivateKey'{version = 'two-prime',
3425                     modulus = 152618920709346576506952607098028299458615405194120516804067302859774798720862572082626851690572130284910454988859007980367926204341637028795420927026111160369130942718840998292351565050537705794496742217762844103737634290634532232714374862322877076125650783658974242305324207239909234718160759907957502819181,
3426                     publicExponent = 17,
3427                     privateExponent = 89775835711380339121736827704722529093303179525953245178863119329279293365213277695662853935630664873476738228740592929628191884906845311056129957074183020957315463095429495020547731127789657232144654051871515007759243605000909583210051114028049068215595185959728886310943042856399988846590947179831354428913,
3428                     prime1 = 13018105310773689694711101111767176661493882304979760063552973933059514785910240943852845097923711145970844208861778343060919395218474310542285865516544653,
3429                     prime2 = 11723589344682921162046319310366118627005968525349821205037572987102618200031016344115630095736447992996683226273798377973464634035204645607416378683745377,
3430                     exponent1 = 7657709006337464526300647712804221565584636649988094155031161137093832227006024084619320645837477144688731887565751966506423173657926065024874038539143913,
3431                     exponent2 = 11033966442054514034867124056815170472476205670917478781211833399625993600029191853285298913634303993408643036492986708680907890856663195865803650525878001,
3432                     coefficient = 7357357483264399363785138527396251818499941660605442417644885251395376792981387533016821796011101917057636813775613592220898054882923958484000235934554630,
3433                     otherPrimeInfos = asn1_NOVALUE};
3434hardcode_rsa_1024_key(2) ->
3435    #'RSAPrivateKey'{version = 'two-prime',
3436                     modulus = 132417984874904377472239436563253515498607309816574784497785056464473431603604973287322746340055062696030016903830406088140534281534301418467490242269156926775506208514027213826501153438861284871625076651352798208559277520683414148048437439635357639033850360133068980157555507518934285770383924814915583919331,
3437                     publicExponent = 17,
3438                     privateExponent = 116839398419033274240211267555811925439947626308742456909810343939241263179651447018225952652989761202379426679850358313065177307236148310412491390237491385620149263549211570156731410125598364338974865883306073709062002620705336269289633237348474049621806833904576124689232282666798030505410189805859996211233,
3439                     prime1 = 12354286715326546399270830019697416039683060665495490476376955068446562229853736822465010796530936501225722243114286822522048306078247961653481711526701259,
3440                     prime2 = 10718383661165041035044708868932433765604392896488115438294667272770655136522450030638962957185192634722652306257889603065114923772949624056219896061512009,
3441                     exponent1 = 5087059235722695576170341772816583075163613215204025490272863851713290329939773985720886798571562088740003276576471044567902243679278572445551292981582871,
3442                     exponent2 = 6304931565391200608849828746430843391531995821463597316643921925159208903836735312140566445403054491013324886034052707685361719866440955327188174153830593,
3443                     coefficient = 6764088858264512915296172980190092445938774052616013205418164952211827027745702759906572599388571087295432259160097016323193144471211837074613329649320009,
3444                     otherPrimeInfos = asn1_NOVALUE};
3445hardcode_rsa_1024_key(3) ->
3446    #'RSAPrivateKey'{version = 'two-prime',
3447                     modulus = 132603582566987335579015215397416921308461253540735107996254563101087328483405996961761145905021132317760270172654141110354018131670337351296871719192630978670273323069438897632586026697023844069174787494970866246368200405578784055149230641370998125414763230872277095376893138420738507940599560410343688278361,
3448                     publicExponent = 17,
3449                     privateExponent = 124803371827752786427308438021098278878551768038338925172945471153964544454970350081657549087078712769656724868380368103862605300395611624749996912181299722918452562565562892031863847812293655197586374503957768862684015202213024002730410420619423541154205461118764880018581745374583581669240937327152309672753,
3450                     prime1 = 12202483472094988277172439292742673588688995751099198683383744575043357099902468606144011463115716181768777309695574163698153032647393450605174909802187971,
3451                     prime2 = 10866934003248540047676291395653788246732743513485317053446021859209870346149779563425451397497222238159656279714782986335807210805023580459325334557063091,
3452                     exponent1 = 3588965727086761257991893909630198114320292867970352553936395463248046205853667237101179842092857700520228620498698283440633244896292191354463208765349403,
3453                     exponent2 = 4474619883690575313749061162916265748654659093788071727889538412615828966061673937881068222498856215712799644588440053197097086802068533130310431876437743,
3454                     coefficient = 6440880395775803235356940314241907933534073137546236980469653455119937607298142560546736915150573386382326185901566797818281064505978928392351326571984856,
3455                     otherPrimeInfos = asn1_NOVALUE}.
3456
3457
3458hardcode_dsa_key(1) ->
3459    {'DSAPrivateKey',0,
3460     99438313664986922963487511141216248076486724382260996073922424025828494981416579966171753999204426907349400798052572573634137057487829150578821328280864500098312146772602202702021153757550650696224643730869835650674962433068943942837519621267815961566259265204876799778977478160416743037274938277357237615491,
3461     1454908511695148818053325447108751926908854531909,
3462     20302424198893709525243209250470907105157816851043773596964076323184805650258390738340248469444700378962907756890306095615785481696522324901068493502141775433048117442554163252381401915027666416630898618301033737438756165023568220631119672502120011809327566543827706483229480417066316015458225612363927682579,
3463     48598545580251057979126570873881530215432219542526130654707948736559463436274835406081281466091739849794036308281564299754438126857606949027748889019480936572605967021944405048011118039171039273602705998112739400664375208228641666852589396502386172780433510070337359132965412405544709871654840859752776060358,
3464     1457508827177594730669011716588605181448418352823};
3465hardcode_dsa_key(2) ->
3466    #'DSAPrivateKey'{
3467       version = 0,
3468       p = 145447354557382582722944332987784622105075065624518040072393858097520305927329240484963764783346271194321683798321743658303478090647837211867389721684646254999291098347011037298359107547264573476540026676832159205689428125157386525591130716464335426605521884822982379206842523670736739023467072341958074788151,
3469       q = 742801637799670234315651916144768554943688916729,
3470       g = 79727684678125120155622004643594683941478642656111969487719464672433839064387954070113655822700268007902716505761008423792735229036965034283173483862273639257533568978482104785033927768441235063983341565088899599358397638308472931049309161811156189887217888328371767967629005149630676763492409067382020352505,
3471       y = 35853727034965131665219275925554159789667905059030049940938124723126925435403746979702929280654735557166864135215989313820464108440192507913554896358611966877432546584986661291483639036057475682547385322659469460385785257933737832719745145778223672383438466035853830832837226950912832515496378486927322864228,
3472       x = 801315110178350279541885862867982846569980443911};
3473hardcode_dsa_key(3) ->
3474    #'DSAPrivateKey'{
3475       version = 0,
3476       p =  99438313664986922963487511141216248076486724382260996073922424025828494981416579966171753999204426907349400798052572573634137057487829150578821328280864500098312146772602202702021153757550650696224643730869835650674962433068943942837519621267815961566259265204876799778977478160416743037274938277357237615491,
3477       q =  1454908511695148818053325447108751926908854531909,
3478       g =  20302424198893709525243209250470907105157816851043773596964076323184805650258390738340248469444700378962907756890306095615785481696522324901068493502141775433048117442554163252381401915027666416630898618301033737438756165023568220631119672502120011809327566543827706483229480417066316015458225612363927682579,
3479       y =  48598545580251057979126570873881530215432219542526130654707948736559463436274835406081281466091739849794036308281564299754438126857606949027748889019480936572605967021944405048011118039171039273602705998112739400664375208228641666852589396502386172780433510070337359132965412405544709871654840859752776060358,
3480       x = 1457508827177594730669011716588605181448418352823}.
3481
3482
3483client_msg(Client, ClientMsg) ->
3484    receive
3485	{Client, ClientMsg} ->
3486	    ok;
3487	{Client, {error,closed}} ->
3488	    ct:log("client got close"),
3489	    ok;
3490	{Client, {error, Reason}} ->
3491	    ct:log("client got econnaborted: ~p", [Reason]),
3492	    ok;
3493	Unexpected ->
3494	    ct:fail(Unexpected)
3495    end.
3496server_msg(Server, ServerMsg) ->
3497    receive
3498	{Server, ServerMsg} ->
3499	    ok;
3500	{Server, {error,closed}} ->
3501	    ct:log("server got close"),
3502	    ok;
3503	{Server, {error, Reason}} ->
3504	    ct:log("server got econnaborted: ~p", [Reason]),
3505	    ok;
3506	Unexpected ->
3507	    ct:fail(Unexpected)
3508    end.
3509
3510session_id(Socket) ->
3511    {ok, [{session_id, ID}]} = ssl:connection_information(Socket, [session_id]),
3512    ID.
3513
3514reuse_session(ClientOpts, ServerOpts, Config) ->
3515    {ClientNode, ServerNode, Hostname} = run_where(Config),
3516
3517    Server0 =
3518	start_server([{node, ServerNode}, {port, 0},
3519				   {from, self()},
3520				   {mfa, {ssl_test_lib, no_result, []}},
3521				   {tcp_options, [{active, false}]},
3522				   {options, ServerOpts}]),
3523    Port0 = inet_port(Server0),
3524
3525    Client0 = start_client([{node, ClientNode},
3526                                         {port, Port0}, {host, Hostname},
3527                                         {mfa, {ssl_test_lib, session_id, []}},
3528                                         {from, self()},  {options, [{reuse_sessions, save} | ClientOpts]}]),
3529    Server0 ! listen,
3530
3531    Client1 = start_client([{node, ClientNode},
3532                                         {port, Port0}, {host, Hostname},
3533                                         {mfa, {ssl_test_lib, session_id, []}},
3534                                         {from, self()},  {options, ClientOpts}]),
3535
3536    SID = receive
3537              {Client0, Id0} ->
3538                  Id0
3539          end,
3540
3541    receive
3542        {Client1, SID} ->
3543            ok
3544    after ?SLEEP ->
3545              ct:fail(session_not_reused)
3546    end,
3547
3548    Server0 ! listen,
3549
3550    Client2 =
3551        start_client([{node, ClientNode},
3552                                   {port, Port0}, {host, Hostname},
3553                                   {mfa, {ssl_test_lib, session_id, []}},
3554                                   {from, self()},  {options, [{reuse_sessions, false}
3555         					  | ClientOpts]}]),
3556    receive
3557         {Client2, SID} ->
3558            ct:fail(session_reused_when_session_reuse_disabled_by_client);
3559         {Client2, _} ->
3560            ok
3561    end,
3562
3563    close(Server0),
3564    close(Client0),
3565    close(Client1),
3566    close(Client2),
3567
3568    Server1 =
3569	start_server([{node, ServerNode}, {port, 0},
3570				   {from, self()},
3571				   {mfa, {ssl_test_lib, no_result, []}},
3572				   {tcp_options, [{active, false}]},
3573				   {options, [{reuse_sessions, false} | ServerOpts]}]),
3574    Port1 = inet_port(Server1),
3575
3576    Client3 = start_client([{node, ClientNode},
3577                            {port, Port1}, {host, Hostname},
3578                            {mfa, {ssl_test_lib, session_id, []}},
3579                            {from, self()},  {options, [{reuse_sessions, save} | ClientOpts]}]),
3580    SID1 = receive
3581               {Client3, Id3} ->
3582                   Id3
3583           end,
3584
3585    Server1 ! listen,
3586
3587    Client4 =
3588        start_client([{node, ClientNode},
3589                      {port, Port1}, {host, Hostname},
3590                      {mfa, {ssl_test_lib, session_id, []}},
3591                      {from, self()},  {options, ClientOpts}]),
3592
3593    receive
3594        {Client4, SID1} ->
3595            ct:fail(session_reused_when_session_reuse_disabled_by_server);
3596        {Client4, _} ->
3597            ok
3598    end,
3599
3600    close(Server1),
3601    close(Client3),
3602    close(Client4).
3603
3604user_lookup(psk, _Identity, UserState) ->
3605    {ok, UserState};
3606user_lookup(srp, Username, _UserState) ->
3607    Salt = ssl_cipher:random_bytes(16),
3608    UserPassHash = crypto:hash(sha, [Salt, crypto:hash(sha, [Username, <<$:>>, <<"secret">>])]),
3609    {ok, {srp_1024, Salt, UserPassHash}}.
3610
3611test_cipher(TestCase, Config) ->
3612    [{name, Group} |_] = proplists:get_value(tc_group_properties, Config),
3613    list_to_atom(re:replace(atom_to_list(TestCase), atom_to_list(Group) ++ "_",  "", [{return, list}])).
3614
3615digest() ->
3616    case application:get_env(ssl, protocol_version, application:get_env(ssl, dtls_protocol_version)) of
3617        Ver when Ver == 'tlsv1.2';
3618                 Ver == 'dtlsv1.2' ->
3619            {digest, sha256};
3620        _ ->
3621            {digest, sha1}
3622    end.
3623
3624kill_openssl() ->
3625    case os:type() of
3626        {win32, _} ->
3627            case os:getenv("WSLENV") of
3628                false -> os:cmd("cmd.exe /C \"taskkill /IM openssl.exe /F\"");
3629                _ -> os:cmd("wsl pkill openssl")
3630            end;
3631        _ ->
3632            os:cmd("pkill openssl")
3633    end.
3634
3635hostname_format(Hostname) ->
3636    case lists:member($., Hostname) of
3637        true ->
3638            Hostname;
3639        false ->
3640            "localhost"
3641    end.
3642
3643erlang_ssl_receive_and_assert_negotiated_protocol(Socket, Protocol, Data) ->
3644    case ssl:negotiated_protocol(Socket) of
3645        {ok, Protocol} ->
3646            active_recv(Socket, length(Data));
3647        Result ->
3648            {error, {{expected, Protocol}, {got, Result}}}
3649    end.
3650
3651check_openssl_npn_support(Config) ->
3652    HelpText = portable_cmd("openssl", ["s_client --help"]),
3653    case string:str(HelpText, "nextprotoneg") of
3654        0 ->
3655            {skip, "Openssl not compiled with nextprotoneg support"};
3656        _ ->
3657            Config
3658    end.
3659
3660new_config(PrivDir, ServerOpts0) ->
3661    CaCertFile = proplists:get_value(cacertfile, ServerOpts0),
3662    CertFile = proplists:get_value(certfile, ServerOpts0),
3663    KeyFile = proplists:get_value(keyfile, ServerOpts0),
3664    NewCaCertFile = filename:join(PrivDir, "new_ca.pem"),
3665    NewCertFile = filename:join(PrivDir, "new_cert.pem"),
3666    NewKeyFile = filename:join(PrivDir, "new_key.pem"),
3667    file:copy(CaCertFile, NewCaCertFile),
3668    file:copy(CertFile, NewCertFile),
3669    file:copy(KeyFile, NewKeyFile),
3670    ServerOpts1 = proplists:delete(cacertfile, ServerOpts0),
3671    ServerOpts2 = proplists:delete(certfile, ServerOpts1),
3672    ServerOpts = proplists:delete(keyfile, ServerOpts2),
3673
3674    {ok, PEM} = file:read_file(NewCaCertFile),
3675    ct:log("CA file content: ~p~n", [public_key:pem_decode(PEM)]),
3676
3677    [{cacertfile, NewCaCertFile}, {certfile, NewCertFile},
3678     {keyfile, NewKeyFile} | ServerOpts].
3679
3680
3681openssl_sane_dtls_alpn() ->
3682    case portable_cmd("openssl", ["version"]) of
3683        "OpenSSL 1.1.0g" ++ _ ->
3684            false;
3685        "OpenSSL 1.1.1 " ++ _ ->
3686            false;
3687        "OpenSSL 1.1.1a" ++ _ ->
3688            false;
3689        "OpenSSL 1.1.1d FIPS" ++ _ ->
3690            false;
3691        "OpenSSL 1.1.1d-freebsd" ++ _ ->
3692            false;
3693        _->
3694            openssl_sane_dtls()
3695    end.
3696
3697openssl_sane_dtls_session_reuse() ->
3698    case portable_cmd("openssl", ["version"]) of
3699        "OpenSSL 1.1.1 " ++ _ ->
3700            false;
3701        "OpenSSL 1.1.1a" ++ _ ->
3702            false;
3703        _->
3704            openssl_sane_dtls()
3705    end.
3706
3707set_protocol_versions(Version) when Version == 'tlsv1';
3708                                    Version == 'tlsv1.1';
3709                                    Version == 'tlsv1.2';
3710                                    Version == 'tlsv1.3'->
3711    set_protocol_versions(protocol_version, [Version]);
3712set_protocol_versions(Version) when Version == 'dtlsv1';
3713                                    Version == 'dtlsv1.2' ->
3714    set_protocol_versions(dtls_protocol_version, [Version]).
3715
3716set_protocol_versions(_, undefined) ->
3717    ok;
3718set_protocol_versions(AppVar, Value) ->
3719    application:set_env(ssl, AppVar, Value).
3720
3721pss_params(sha256) ->
3722    #'RSASSA-PSS-params'{
3723       hashAlgorithm = #'HashAlgorithm'{algorithm = ?'id-sha256'},
3724       maskGenAlgorithm = #'MaskGenAlgorithm'{algorithm = ?'id-mgf1',
3725                                              parameters = #'HashAlgorithm'{algorithm = ?'id-sha256'}
3726                                             },
3727       saltLength = 32,
3728       trailerField = 1}.
3729
3730test_ciphers(Kex, Cipher, Version) ->
3731    ssl:filter_cipher_suites(
3732        ssl:cipher_suites(all, Version) ++ ssl:cipher_suites(anonymous, Version),
3733        [{key_exchange,
3734          fun(K) when K == Kex -> true;
3735             (_) -> false
3736          end},
3737         {cipher,
3738          fun(C) when C == Cipher -> true;
3739             (_) -> false
3740          end}]).
3741
3742sanity_check(ErlangPeer, OpenSSLPort) ->
3743    Data = "OpenSSL to Erlang",
3744    port_command(OpenSSLPort, Data, [nosuspend]),
3745    Data = check_active_receive(ErlangPeer, Data).
3746
3747default_tls_version(Config) ->
3748    case proplists:get_value(protocol, Config, tls) of
3749        tls ->
3750            {ok, Versions} = application:get_env(ssl, protocol_version),
3751            Versions;
3752        dtls ->
3753            {ok, Versions} = application:get_env(ssl, dtls_protocol_version),
3754            Versions
3755    end.
3756
3757openssl_maxfraglen_support() ->
3758    case portable_cmd("openssl", ["version"]) of
3759        %% Max fragmentation support introduced in OpenSSL 1.1.1
3760        "OpenSSL 0" ++ _  ->
3761            false;
3762        "OpenSSL 1.0" ++ _  ->
3763            false;
3764        "OpenSSL 1.1.0" ++ _ ->
3765            false;
3766	"OpenSSL 1.1.1" ++ _ ->
3767            true;
3768        "OpenSSL" ++ _ ->
3769            true;
3770        _  ->
3771            false
3772    end.
3773
3774openssl_dtls_maxfraglen_support() ->
3775    case portable_cmd("openssl", ["version"]) of
3776        "OpenSSL 0" ++ _  ->
3777            false;
3778        "OpenSSL 1.0" ++ _  ->
3779            false;
3780        "OpenSSL 1.1.0" ++ _ ->
3781            false;
3782	"OpenSSL 1.1.1" ++ _ ->
3783            false;
3784        "OpenSSL 1.1" ++ _ ->
3785            false;
3786        "OpenSSL" ++ _ ->
3787            true;
3788        _  ->
3789            false
3790    end.
3791
3792assert_mfl(Socket, undefined) ->
3793    InfoMFL = ssl:connection_information(Socket, [max_fragment_length]),
3794    ct:log("Connection MFL ~p, Expecting: [] ~n", [InfoMFL]),
3795    {ok, []} = InfoMFL;
3796assert_mfl(Socket, MFL) ->
3797    InfoMFL = ssl:connection_information(Socket, [max_fragment_length]),
3798    ct:log("Connection MFL ~p, Expecting: ~p ~n", [InfoMFL, MFL]),
3799    {ok, [{max_fragment_length, ConnMFL}]} = InfoMFL,
3800    ConnMFL = MFL.
3801-define(BIG_BUF, 10000000).
3802%% Workaround data delivery issues on solaris | openbsd  when kernel buffers are small
3803bigger_buffers() ->
3804    case os:type() of
3805        {unix,sunos} ->
3806            [{buffer, ?BIG_BUF}, {recbuf, ?BIG_BUF},{sndbuf, ?BIG_BUF}];
3807        {unix,openbsd} ->
3808            [{buffer, ?BIG_BUF}, {recbuf, ?BIG_BUF},{sndbuf, ?BIG_BUF}];
3809        _ ->
3810            []
3811    end.
3812
3813default_ciphers(Version) ->
3814    OpenSSLCiphers = openssl_ciphers(),
3815    Ciphers =
3816        case portable_cmd("openssl", ["version"]) of
3817            "OpenSSL 0.9" ++ _ ->
3818                ssl:cipher_suites(all,Version);
3819            _ ->
3820                ssl:cipher_suites(default, Version)
3821        end,
3822    [Cipher || Cipher <- Ciphers, lists:member(ssl:suite_to_openssl_str(Cipher), OpenSSLCiphers)].
3823
3824verify_early_data(Atom) ->
3825    receive
3826        {ssl, _Socket, {early_data, Atom}} ->
3827            ok;
3828        {ssl, _Socket, {early_data, Other}} ->
3829            Other
3830    end.
3831
3832