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