1%%
2%% %CopyrightBegin%
3%%
4%% Copyright Ericsson AB 2007-2020. All Rights Reserved.
5%%
6%% Licensed under the Apache License, Version 2.0 (the "License");
7%% you may not use this file except in compliance with the License.
8%% You may obtain a copy of the License at
9%%
10%%     http://www.apache.org/licenses/LICENSE-2.0
11%%
12%% Unless required by applicable law or agreed to in writing, software
13%% distributed under the License is distributed on an "AS IS" BASIS,
14%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15%% See the License for the specific language governing permissions and
16%% limitations under the License.
17%%
18%% %CopyrightEnd%
19%%
20
21%%
22
23-module(ssl_ECC_SUITE).
24
25%% Note: This directive should only be used in test suites.
26-compile(export_all).
27
28-include_lib("common_test/include/ct.hrl").
29-include_lib("public_key/include/public_key.hrl").
30
31%%--------------------------------------------------------------------
32%% Common Test interface functions -----------------------------------
33%%--------------------------------------------------------------------
34
35all() ->
36    [
37     {group, 'tlsv1.2'},
38     {group, 'tlsv1.1'},
39     {group, 'tlsv1'},
40     {group, 'dtlsv1.2'},
41     {group, 'dtlsv1'}
42    ].
43
44groups() ->
45    [
46     {'tlsv1.2', [], [mix_sign | test_cases()]},
47     {'tlsv1.1', [], test_cases()},
48     {'tlsv1', [], test_cases()},
49     {'dtlsv1.2', [], [mix_sign | test_cases()]},
50     {'dtlsv1', [], test_cases()}
51    ].
52
53test_cases()->
54    misc() ++ ecc_negotiation().
55
56misc()->
57    [client_ecdsa_server_ecdsa_with_raw_key].
58
59ecc_negotiation() ->
60    [ecc_default_order,
61     ecc_default_order_custom_curves,
62     ecc_client_order,
63     ecc_client_order_custom_curves,
64     ecc_unknown_curve,
65     client_ecdh_rsa_server_ecdhe_ecdsa_server_custom,
66     client_ecdh_rsa_server_ecdhe_rsa_server_custom,
67     client_ecdhe_rsa_server_ecdhe_ecdsa_server_custom,
68     client_ecdhe_rsa_server_ecdhe_rsa_server_custom,
69     client_ecdhe_rsa_server_ecdh_rsa_server_custom,
70     client_ecdhe_ecdsa_server_ecdhe_ecdsa_server_custom,
71     client_ecdhe_ecdsa_server_ecdhe_rsa_server_custom,
72     client_ecdhe_ecdsa_server_ecdhe_ecdsa_client_custom,
73     client_ecdhe_rsa_server_ecdhe_ecdsa_client_custom
74    ].
75
76%%--------------------------------------------------------------------
77init_per_suite(Config0) ->
78    end_per_suite(Config0),
79    try crypto:start() of
80	ok ->
81            case ssl_test_lib:sufficient_crypto_support(cipher_ec) of
82                true ->
83                    Config0;
84                false ->
85                    {skip, "Crypto does not support ECC"}
86            end
87    catch _:_ ->
88            {skip, "Crypto did not start"}
89    end.
90
91end_per_suite(_Config) ->
92    application:stop(ssl),
93    application:stop(crypto).
94
95%%--------------------------------------------------------------------
96init_per_group(GroupName, Config) ->
97    case ssl_test_lib:is_tls_version(GroupName) of
98	true ->
99            [{tls_version, GroupName},
100             {server_type, erlang},
101             {client_type, erlang} | ssl_test_lib:init_tls_version(GroupName, Config)];
102        _ ->
103            Config
104    end.
105
106end_per_group(GroupName, Config0) ->
107  case ssl_test_lib:is_tls_version(GroupName) of
108      true ->
109          Config = ssl_test_lib:clean_tls_version(Config0),
110          proplists:delete(tls_version, Config);
111      false ->
112          Config0
113  end.
114
115%%--------------------------------------------------------------------
116
117init_per_testcase(TestCase, Config) ->
118    ssl_test_lib:ct_log_supported_protocol_versions(Config),
119    ct:log("Ciphers: ~p~n ", [ ssl:cipher_suites()]),
120    end_per_testcase(TestCase, Config),
121    ssl:start(),
122    ct:timetrap({seconds, 15}),
123    Config.
124
125end_per_testcase(_TestCase, Config) ->
126    application:stop(ssl),
127    Config.
128
129%%--------------------------------------------------------------------
130%% Test Cases --------------------------------------------------------
131%%--------------------------------------------------------------------
132%% Test diffrent certificate chain types, note that it is the servers
133%% chain that affect what cipher suit that will be choosen
134
135client_ecdsa_server_ecdsa_with_raw_key(Config)  when is_list(Config) ->
136     Default = ssl_test_lib:default_cert_chain_conf(),
137    {COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
138                                                       {client_chain, Default}]
139                                                     , ecdhe_ecdsa, ecdhe_ecdsa, Config),
140    COpts = ssl_test_lib:ssl_options(COpts0, Config),
141    SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
142    ServerKeyFile = proplists:get_value(keyfile, SOpts),
143    {ok, PemBin} = file:read_file(ServerKeyFile),
144    PemEntries = public_key:pem_decode(PemBin),
145     {'ECPrivateKey', Key, not_encrypted} = proplists:lookup('ECPrivateKey', PemEntries),
146    ServerKey = {'ECPrivateKey', Key},
147    SType = proplists:get_value(server_type, Config),
148    CType = proplists:get_value(client_type, Config),
149    {Server, Port} = ssl_test_lib:start_server_with_raw_key(SType,
150                                                            [{key, ServerKey} | proplists:delete(keyfile, SOpts)],
151                                                            Config),
152    Client = ssl_test_lib:start_client(CType, Port, COpts, Config),
153    ssl_test_lib:gen_check_result(Server, SType, Client, CType),
154    ssl_test_lib:stop(Server, Client).
155
156ecc_default_order(Config) ->
157    Default = ssl_test_lib:default_cert_chain_conf(),
158    DefaultCurve = pubkey_cert_records:namedCurves(hd(tls_v1:ecc_curves(1))),
159    {COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
160                                                         {client_chain, Default}],
161                                                        ecdhe_ecdsa, ecdhe_ecdsa,
162                                                        Config, DefaultCurve),
163    COpts = ssl_test_lib:ssl_options(COpts0, Config),
164    SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
165    ECCOpts = [],
166    case ssl_test_lib:supported_eccs([{eccs, [DefaultCurve]}]) of
167        true ->  ssl_test_lib:ecc_test(DefaultCurve, COpts, SOpts, [], ECCOpts, Config);
168        false -> {skip, "unsupported named curves"}
169     end.
170
171ecc_default_order_custom_curves(Config) ->
172    Default = ssl_test_lib:default_cert_chain_conf(),
173    DefaultCurve = pubkey_cert_records:namedCurves(hd(tls_v1:ecc_curves(1))),
174    {COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
175                                                         {client_chain, Default}],
176                                                        ecdhe_ecdsa, ecdhe_ecdsa,
177                                                        Config, DefaultCurve),
178    COpts = ssl_test_lib:ssl_options(COpts0, Config),
179    SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
180    ECCOpts = [{eccs, [secp256r1, DefaultCurve]}],
181    case ssl_test_lib:supported_eccs(ECCOpts) of
182         true ->  ssl_test_lib:ecc_test(DefaultCurve, COpts, SOpts, [], ECCOpts, Config);
183        false -> {skip, "unsupported named curves"}
184    end.
185
186ecc_client_order(Config) ->
187    Default = ssl_test_lib:default_cert_chain_conf(),
188    DefaultCurve = pubkey_cert_records:namedCurves(hd(tls_v1:ecc_curves(1))),
189    {COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
190                                                         {client_chain, Default}],
191                                                        ecdhe_ecdsa, ecdhe_ecdsa,
192                                                        Config, DefaultCurve),
193    COpts = ssl_test_lib:ssl_options(COpts0, Config),
194    SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
195    ECCOpts = [{honor_ecc_order, false}],
196    case ssl_test_lib:supported_eccs([{eccs, [DefaultCurve]}]) of
197         true -> ssl_test_lib:ecc_test(DefaultCurve, COpts, SOpts, [], ECCOpts, Config);
198        false -> {skip, "unsupported named curves"}
199    end.
200
201ecc_client_order_custom_curves(Config) ->
202    Default = ssl_test_lib:default_cert_chain_conf(),
203    DefaultCurve = pubkey_cert_records:namedCurves(hd(tls_v1:ecc_curves(1))),
204    {COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
205                                                        {client_chain, Default}],
206                                                        ecdhe_ecdsa, ecdhe_ecdsa,
207                                                        Config, DefaultCurve),
208    COpts = ssl_test_lib:ssl_options(COpts0, Config),
209    SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
210    ECCOpts = [{honor_ecc_order, false}, {eccs, [secp256r1, DefaultCurve]}],
211    case ssl_test_lib:supported_eccs(ECCOpts) of
212        true -> ssl_test_lib:ecc_test(DefaultCurve, COpts, SOpts, [], ECCOpts, Config);
213        false -> {skip, "unsupported named curves"}
214    end.
215
216ecc_unknown_curve(Config) ->
217    Default = ssl_test_lib:default_cert_chain_conf(),
218    {COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
219                                                       {client_chain, Default}],
220                                                      ecdhe_ecdsa, ecdhe_ecdsa, Config),
221    COpts = ssl_test_lib:ssl_options(COpts0, Config),
222    SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
223    ECCOpts = [{eccs, ['123_fake_curve']}],
224    ssl_test_lib:ecc_test_error(COpts, SOpts, [], ECCOpts, Config).
225
226client_ecdh_rsa_server_ecdhe_ecdsa_server_custom(Config) ->
227    Default = ssl_test_lib:default_cert_chain_conf(),
228    DefaultCurve = pubkey_cert_records:namedCurves(hd(tls_v1:ecc_curves(1))),
229    {COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
230                                                       {client_chain, Default}],
231                                                        ecdh_rsa, ecdhe_ecdsa, Config),
232    COpts = ssl_test_lib:ssl_options(COpts0, Config),
233    SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
234    ECCOpts = [{honor_ecc_order, true}, {eccs, [secp256r1, DefaultCurve]}],
235     case ssl_test_lib:supported_eccs(ECCOpts) of
236         true -> ssl_test_lib:ecc_test(secp256r1, COpts, SOpts, [], ECCOpts, Config);
237         false -> {skip, "unsupported named curves"}
238     end.
239
240client_ecdh_rsa_server_ecdhe_rsa_server_custom(Config) ->
241    Default = ssl_test_lib:default_cert_chain_conf(),
242    DefaultCurve = pubkey_cert_records:namedCurves(hd(tls_v1:ecc_curves(1))),
243    {COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
244                                                         {client_chain, Default}],
245                                                        ecdh_rsa, ecdhe_rsa, Config),
246    COpts = ssl_test_lib:ssl_options(COpts0, Config),
247    SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
248    ECCOpts = [{honor_ecc_order, true}, {eccs, [secp256r1, DefaultCurve]}],
249
250    case ssl_test_lib:supported_eccs(ECCOpts) of
251        true -> ssl_test_lib:ecc_test(secp256r1, COpts, SOpts, [], ECCOpts, Config);
252        false -> {skip, "unsupported named curves"}
253    end.
254
255client_ecdhe_rsa_server_ecdhe_ecdsa_server_custom(Config) ->
256    Default = ssl_test_lib:default_cert_chain_conf(),
257    DefaultCurve = pubkey_cert_records:namedCurves(hd(tls_v1:ecc_curves(1))),
258    {COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
259                                                         {client_chain, Default}],
260                                                        ecdhe_rsa, ecdhe_ecdsa, Config),
261    COpts = ssl_test_lib:ssl_options(COpts0, Config),
262    SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
263    ECCOpts = [{honor_ecc_order, true}, {eccs, [secp256r1, DefaultCurve]}],
264    case ssl_test_lib:supported_eccs(ECCOpts) of
265         true -> ssl_test_lib:ecc_test(secp256r1, COpts, SOpts, [], ECCOpts, Config);
266        false -> {skip, "unsupported named curves"}
267    end.
268
269client_ecdhe_rsa_server_ecdhe_rsa_server_custom(Config) ->
270    Default = ssl_test_lib:default_cert_chain_conf(),
271    DefaultCurve = pubkey_cert_records:namedCurves(hd(tls_v1:ecc_curves(1))),
272    {COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
273                                                         {client_chain, Default}],
274                                                        ecdhe_rsa, ecdhe_rsa, Config),
275
276    COpts = ssl_test_lib:ssl_options(COpts0, Config),
277    SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
278    ECCOpts = [{honor_ecc_order, true}, {eccs, [secp256r1, DefaultCurve]}],
279    case ssl_test_lib:supported_eccs(ECCOpts) of
280        true -> ssl_test_lib:ecc_test(secp256r1, COpts, SOpts, [], ECCOpts, Config);
281        false -> {skip, "unsupported named curves"}
282     end.
283client_ecdhe_rsa_server_ecdh_rsa_server_custom(Config) ->
284    Default = ssl_test_lib:default_cert_chain_conf(),
285    DefaultCurve = pubkey_cert_records:namedCurves(hd(tls_v1:ecc_curves(1))),
286    Ext = x509_test:extensions([{key_usage, [keyEncipherment]}]),
287    {COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, [[], [], [{extensions, Ext}]]},
288                                                         {client_chain, Default}],
289                                                        ecdhe_rsa, ecdh_rsa, Config),
290
291    COpts = ssl_test_lib:ssl_options(COpts0, Config),
292    SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
293    ECCOpts = [{honor_ecc_order, true}, {eccs, [secp256r1, DefaultCurve]}],
294    Expected = secp256r1, %% The certificate curve
295
296    case ssl_test_lib:supported_eccs(ECCOpts) of
297        true -> ssl_test_lib:ecc_test(Expected, COpts, SOpts, [], ECCOpts, Config);
298        false -> {skip, "unsupported named curves"}
299    end.
300
301client_ecdhe_ecdsa_server_ecdhe_ecdsa_server_custom(Config) ->
302    Default = ssl_test_lib:default_cert_chain_conf(),
303    DefaultCurve = pubkey_cert_records:namedCurves(hd(tls_v1:ecc_curves(1))),
304    {COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
305                                                       {client_chain, Default}],
306                                                        ecdhe_ecdsa, ecdhe_ecdsa, Config),
307    COpts = ssl_test_lib:ssl_options(COpts0, Config),
308    SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
309    ECCOpts = [{honor_ecc_order, true}, {eccs, [secp256r1, DefaultCurve]}],
310    case ssl_test_lib:supported_eccs(ECCOpts) of
311        true -> ssl_test_lib:ecc_test(secp256r1, COpts, SOpts, [], ECCOpts, Config);
312        false -> {skip, "unsupported named curves"}
313    end.
314
315client_ecdhe_ecdsa_server_ecdhe_rsa_server_custom(Config) ->
316    Default = ssl_test_lib:default_cert_chain_conf(),
317    DefaultCurve = pubkey_cert_records:namedCurves(hd(tls_v1:ecc_curves(1))),
318    {COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
319                                                         {client_chain, Default}],
320                                                        ecdhe_ecdsa, ecdhe_rsa, Config),
321    COpts = ssl_test_lib:ssl_options(COpts0, Config),
322    SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
323    ECCOpts = [{honor_ecc_order, true}, {eccs, [secp256r1, DefaultCurve]}],
324    case ssl_test_lib:supported_eccs(ECCOpts) of
325        true -> ssl_test_lib:ecc_test(secp256r1, COpts, SOpts, [], ECCOpts, Config);
326        false -> {skip, "unsupported named curves"}
327    end.
328
329client_ecdhe_ecdsa_server_ecdhe_ecdsa_client_custom(Config) ->
330    Default = ssl_test_lib:default_cert_chain_conf(),
331    DefaultCurve = pubkey_cert_records:namedCurves(hd(tls_v1:ecc_curves(1))),
332    {COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
333                                                       {client_chain, Default}],
334                                                        ecdhe_ecdsa, ecdhe_ecdsa, Config),
335    COpts = ssl_test_lib:ssl_options(COpts0, Config),
336    SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
337    ECCOpts = [{eccs, [secp256r1, DefaultCurve]}],
338    case ssl_test_lib:supported_eccs(ECCOpts) of
339        true -> ssl_test_lib:ecc_test(secp256r1, COpts, SOpts, ECCOpts, [], Config);
340        false -> {skip, "unsupported named curves"}
341    end.
342
343client_ecdhe_rsa_server_ecdhe_ecdsa_client_custom(Config) ->
344    Default = ssl_test_lib:default_cert_chain_conf(),
345    DefaultCurve = pubkey_cert_records:namedCurves(hd(tls_v1:ecc_curves(1))),
346    {COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
347                                                         {client_chain, Default}],
348                                                         ecdhe_rsa, ecdhe_ecdsa, Config),
349    COpts = ssl_test_lib:ssl_options(COpts0, Config),
350    SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
351    ECCOpts = [{eccs, [secp256r1, DefaultCurve]}],
352    case ssl_test_lib:supported_eccs(ECCOpts) of
353        true -> ssl_test_lib:ecc_test(secp256r1, COpts, SOpts, ECCOpts, [], Config);
354        false -> {skip, "unsupported named curves"}
355    end.
356
357mix_sign(Config) ->
358    mix_sign_rsa_peer(Config),
359    mix_sign_ecdsa_peer(Config).
360
361mix_sign_ecdsa_peer(Config) ->
362    {COpts0, SOpts0} = ssl_test_lib:make_mix_cert([{mix, peer_ecc} |Config]),
363    COpts = ssl_test_lib:ssl_options(COpts0, Config),
364    SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
365    ECDHE_ECDSA =
366        ssl:filter_cipher_suites(ssl:cipher_suites(default, 'tlsv1.2'),
367                                 [{key_exchange, fun(ecdhe_ecdsa) -> true; (_) -> false end}]),
368    ssl_test_lib:basic_test(COpts, [{ciphers, ECDHE_ECDSA} | SOpts], Config).
369
370
371mix_sign_rsa_peer(Config) ->
372    {COpts0, SOpts0} = ssl_test_lib:make_mix_cert([{mix, peer_rsa} |Config]),
373    COpts = ssl_test_lib:ssl_options(COpts0, Config),
374    SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
375    ECDHE_RSA =
376        ssl:filter_cipher_suites(ssl:cipher_suites(default, 'tlsv1.2'),
377                                 [{key_exchange, fun(ecdhe_rsa) -> true; (_) -> false end}]),
378    ssl_test_lib:basic_test(COpts, [{ciphers, ECDHE_RSA} | SOpts], Config).
379
380