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-behaviour(ct_suite).
26
27-include_lib("common_test/include/ct.hrl").
28-include_lib("public_key/include/public_key.hrl").
29
30
31%% Common test
32-export([all/0,
33         groups/0,
34         init_per_suite/1,
35         init_per_group/2,
36         init_per_testcase/2,
37         end_per_suite/1,
38         end_per_group/2,
39         end_per_testcase/2
40        ]).
41
42%% Test cases
43-export([ecc_default_order/1,
44         ecc_default_order_custom_curves/1,
45         ecc_client_order/1,
46         ecc_client_order_custom_curves/1,
47         ecc_unknown_curve/1,
48         client_ecdh_rsa_server_ecdhe_ecdsa_server_custom/1,
49         client_ecdh_rsa_server_ecdhe_rsa_server_custom/1,
50         client_ecdhe_rsa_server_ecdhe_ecdsa_server_custom/1,
51         client_ecdhe_rsa_server_ecdhe_rsa_server_custom/1,
52         client_ecdhe_rsa_server_ecdh_rsa_server_custom/1,
53         client_ecdhe_ecdsa_server_ecdhe_ecdsa_server_custom/1,
54         client_ecdhe_ecdsa_server_ecdhe_rsa_server_custom/1,
55         client_ecdhe_ecdsa_server_ecdhe_ecdsa_client_custom/1,
56         client_ecdhe_rsa_server_ecdhe_ecdsa_client_custom/1,
57         client_ecdsa_server_ecdsa_with_raw_key/1,
58         mix_sign/1
59        ]).
60
61%%--------------------------------------------------------------------
62%% Common Test interface functions -----------------------------------
63%%--------------------------------------------------------------------
64
65all() ->
66    [
67     {group, 'tlsv1.2'},
68     {group, 'tlsv1.1'},
69     {group, 'tlsv1'},
70     {group, 'dtlsv1.2'},
71     {group, 'dtlsv1'}
72    ].
73
74groups() ->
75    [
76     {'tlsv1.2', [], [mix_sign | test_cases()]},
77     {'tlsv1.1', [], test_cases()},
78     {'tlsv1', [], test_cases()},
79     {'dtlsv1.2', [], [mix_sign | test_cases()]},
80     {'dtlsv1', [], test_cases()}
81    ].
82
83test_cases()->
84    misc() ++ ecc_negotiation().
85
86misc()->
87    [client_ecdsa_server_ecdsa_with_raw_key].
88
89ecc_negotiation() ->
90    [ecc_default_order,
91     ecc_default_order_custom_curves,
92     ecc_client_order,
93     ecc_client_order_custom_curves,
94     ecc_unknown_curve,
95     client_ecdh_rsa_server_ecdhe_ecdsa_server_custom,
96     client_ecdh_rsa_server_ecdhe_rsa_server_custom,
97     client_ecdhe_rsa_server_ecdhe_ecdsa_server_custom,
98     client_ecdhe_rsa_server_ecdhe_rsa_server_custom,
99     client_ecdhe_rsa_server_ecdh_rsa_server_custom,
100     client_ecdhe_ecdsa_server_ecdhe_ecdsa_server_custom,
101     client_ecdhe_ecdsa_server_ecdhe_rsa_server_custom,
102     client_ecdhe_ecdsa_server_ecdhe_ecdsa_client_custom,
103     client_ecdhe_rsa_server_ecdhe_ecdsa_client_custom
104    ].
105
106%%--------------------------------------------------------------------
107init_per_suite(Config0) ->
108    end_per_suite(Config0),
109    try crypto:start() of
110	ok ->
111            case ssl_test_lib:sufficient_crypto_support(cipher_ec) of
112                true ->
113                    Config0;
114                false ->
115                    {skip, "Crypto does not support ECC"}
116            end
117    catch _:_ ->
118            {skip, "Crypto did not start"}
119    end.
120
121end_per_suite(_Config) ->
122    application:stop(ssl),
123    application:stop(crypto).
124
125%%--------------------------------------------------------------------
126init_per_group(GroupName, Config) ->
127    case ssl_test_lib:is_protocol_version(GroupName) of
128	true ->
129            ct:log("Ciphers: ~p~n ", [ssl:cipher_suites(default, GroupName)]),
130            ssl_test_lib:init_per_group(GroupName,
131                                        [{client_type, erlang},
132                                         {server_type, erlang},
133                                         {version, GroupName} | Config]);
134        false ->
135            Config
136    end.
137
138end_per_group(GroupName, Config) ->
139    ssl_test_lib:end_per_group(GroupName, Config).
140
141%%--------------------------------------------------------------------
142
143init_per_testcase(TestCase, Config) ->
144    ssl_test_lib:ct_log_supported_protocol_versions(Config),
145    Version = proplists:get_value(version, Config),
146    ct:log("Ciphers: ~p~n ", [ssl:cipher_suites(default, Version)]),
147    end_per_testcase(TestCase, Config),
148    ssl:start(),
149    ct:timetrap({seconds, 15}),
150    Config.
151
152end_per_testcase(_TestCase, Config) ->
153    application:stop(ssl),
154    Config.
155
156%%--------------------------------------------------------------------
157%% Test Cases --------------------------------------------------------
158%%--------------------------------------------------------------------
159%% Test diffrent certificate chain types, note that it is the servers
160%% chain that affect what cipher suite that will be choosen
161
162client_ecdsa_server_ecdsa_with_raw_key(Config)  when is_list(Config) ->
163     Default = ssl_test_lib:default_cert_chain_conf(),
164    {COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
165                                                       {client_chain, Default}]
166                                                     , ecdhe_ecdsa, ecdhe_ecdsa, Config),
167    COpts = ssl_test_lib:ssl_options(COpts0, Config),
168    SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
169    ServerKeyFile = proplists:get_value(keyfile, SOpts),
170    {ok, PemBin} = file:read_file(ServerKeyFile),
171    PemEntries = public_key:pem_decode(PemBin),
172     {'ECPrivateKey', Key, not_encrypted} = proplists:lookup('ECPrivateKey', PemEntries),
173    ServerKey = {'ECPrivateKey', Key},
174    SType = proplists:get_value(server_type, Config),
175    CType = proplists:get_value(client_type, Config),
176    {Server, Port} = ssl_test_lib:start_server_with_raw_key(SType,
177                                                            [{key, ServerKey} | proplists:delete(keyfile, SOpts)],
178                                                            Config),
179    Client = ssl_test_lib:start_client(CType, Port, COpts, Config),
180    ssl_test_lib:gen_check_result(Server, SType, Client, CType),
181    ssl_test_lib:stop(Server, Client).
182
183ecc_default_order(Config) ->
184    Default = ssl_test_lib:default_cert_chain_conf(),
185    DefaultCurve = pubkey_cert_records:namedCurves(hd(tls_v1:ecc_curves(1))),
186    {COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
187                                                         {client_chain, Default}],
188                                                        ecdhe_ecdsa, ecdhe_ecdsa,
189                                                        Config, DefaultCurve),
190    COpts = ssl_test_lib:ssl_options(COpts0, Config),
191    SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
192    ECCOpts = [],
193    case ssl_test_lib:supported_eccs([{eccs, [DefaultCurve]}]) of
194        true ->  ssl_test_lib:ecc_test(DefaultCurve, COpts, SOpts, [], ECCOpts, Config);
195        false -> {skip, "unsupported named curves"}
196     end.
197
198ecc_default_order_custom_curves(Config) ->
199    Default = ssl_test_lib:default_cert_chain_conf(),
200    DefaultCurve = pubkey_cert_records:namedCurves(hd(tls_v1:ecc_curves(1))),
201    {COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
202                                                         {client_chain, Default}],
203                                                        ecdhe_ecdsa, ecdhe_ecdsa,
204                                                        Config, DefaultCurve),
205    COpts = ssl_test_lib:ssl_options(COpts0, Config),
206    SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
207    ECCOpts = [{eccs, [secp256r1, DefaultCurve]}],
208    case ssl_test_lib:supported_eccs(ECCOpts) of
209         true ->  ssl_test_lib:ecc_test(DefaultCurve, COpts, SOpts, [], ECCOpts, Config);
210        false -> {skip, "unsupported named curves"}
211    end.
212
213ecc_client_order(Config) ->
214    Default = ssl_test_lib:default_cert_chain_conf(),
215    DefaultCurve = pubkey_cert_records:namedCurves(hd(tls_v1:ecc_curves(1))),
216    {COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
217                                                         {client_chain, Default}],
218                                                        ecdhe_ecdsa, ecdhe_ecdsa,
219                                                        Config, DefaultCurve),
220    COpts = ssl_test_lib:ssl_options(COpts0, Config),
221    SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
222    ECCOpts = [{honor_ecc_order, false}],
223    case ssl_test_lib:supported_eccs([{eccs, [DefaultCurve]}]) of
224         true -> ssl_test_lib:ecc_test(DefaultCurve, COpts, SOpts, [], ECCOpts, Config);
225        false -> {skip, "unsupported named curves"}
226    end.
227
228ecc_client_order_custom_curves(Config) ->
229    Default = ssl_test_lib:default_cert_chain_conf(),
230    DefaultCurve = pubkey_cert_records:namedCurves(hd(tls_v1:ecc_curves(1))),
231    {COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
232                                                        {client_chain, Default}],
233                                                        ecdhe_ecdsa, ecdhe_ecdsa,
234                                                        Config, DefaultCurve),
235    COpts = ssl_test_lib:ssl_options(COpts0, Config),
236    SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
237    ECCOpts = [{honor_ecc_order, false}, {eccs, [secp256r1, DefaultCurve]}],
238    case ssl_test_lib:supported_eccs(ECCOpts) of
239        true -> ssl_test_lib:ecc_test(DefaultCurve, COpts, SOpts, [], ECCOpts, Config);
240        false -> {skip, "unsupported named curves"}
241    end.
242
243ecc_unknown_curve(Config) ->
244    Default = ssl_test_lib:default_cert_chain_conf(),
245    {COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
246                                                       {client_chain, Default}],
247                                                      ecdhe_ecdsa, ecdhe_ecdsa, Config),
248    COpts = ssl_test_lib:ssl_options(COpts0, Config),
249    SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
250    ECCOpts = [{eccs, ['123_fake_curve']}],
251    ssl_test_lib:ecc_test_error(COpts, SOpts, [], ECCOpts, Config).
252
253client_ecdh_rsa_server_ecdhe_ecdsa_server_custom(Config) ->
254    Default = ssl_test_lib:default_cert_chain_conf(),
255    DefaultCurve = pubkey_cert_records:namedCurves(hd(tls_v1:ecc_curves(1))),
256    {COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
257                                                       {client_chain, Default}],
258                                                        ecdh_rsa, ecdhe_ecdsa, Config),
259    COpts = ssl_test_lib:ssl_options(COpts0, Config),
260    SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
261    ECCOpts = [{honor_ecc_order, true}, {eccs, [secp256r1, DefaultCurve]}],
262     case ssl_test_lib:supported_eccs(ECCOpts) of
263         true -> ssl_test_lib:ecc_test(secp256r1, COpts, SOpts, [], ECCOpts, Config);
264         false -> {skip, "unsupported named curves"}
265     end.
266
267client_ecdh_rsa_server_ecdhe_rsa_server_custom(Config) ->
268    Default = ssl_test_lib:default_cert_chain_conf(),
269    DefaultCurve = pubkey_cert_records:namedCurves(hd(tls_v1:ecc_curves(1))),
270    {COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
271                                                         {client_chain, Default}],
272                                                        ecdh_rsa, ecdhe_rsa, Config),
273    COpts = ssl_test_lib:ssl_options(COpts0, Config),
274    SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
275    ECCOpts = [{honor_ecc_order, true}, {eccs, [secp256r1, DefaultCurve]}],
276
277    case ssl_test_lib:supported_eccs(ECCOpts) of
278        true -> ssl_test_lib:ecc_test(secp256r1, COpts, SOpts, [], ECCOpts, Config);
279        false -> {skip, "unsupported named curves"}
280    end.
281
282client_ecdhe_rsa_server_ecdhe_ecdsa_server_custom(Config) ->
283    Default = ssl_test_lib:default_cert_chain_conf(),
284    DefaultCurve = pubkey_cert_records:namedCurves(hd(tls_v1:ecc_curves(1))),
285    {COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
286                                                         {client_chain, Default}],
287                                                        ecdhe_rsa, ecdhe_ecdsa, Config),
288    COpts = ssl_test_lib:ssl_options(COpts0, Config),
289    SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
290    ECCOpts = [{honor_ecc_order, true}, {eccs, [secp256r1, DefaultCurve]}],
291    case ssl_test_lib:supported_eccs(ECCOpts) of
292         true -> ssl_test_lib:ecc_test(secp256r1, COpts, SOpts, [], ECCOpts, Config);
293        false -> {skip, "unsupported named curves"}
294    end.
295
296client_ecdhe_rsa_server_ecdhe_rsa_server_custom(Config) ->
297    Default = ssl_test_lib:default_cert_chain_conf(),
298    DefaultCurve = pubkey_cert_records:namedCurves(hd(tls_v1:ecc_curves(1))),
299    {COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
300                                                         {client_chain, Default}],
301                                                        ecdhe_rsa, ecdhe_rsa, Config),
302
303    COpts = ssl_test_lib:ssl_options(COpts0, Config),
304    SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
305    ECCOpts = [{honor_ecc_order, true}, {eccs, [secp256r1, DefaultCurve]}],
306    case ssl_test_lib:supported_eccs(ECCOpts) of
307        true -> ssl_test_lib:ecc_test(secp256r1, COpts, SOpts, [], ECCOpts, Config);
308        false -> {skip, "unsupported named curves"}
309     end.
310client_ecdhe_rsa_server_ecdh_rsa_server_custom(Config) ->
311    Default = ssl_test_lib:default_cert_chain_conf(),
312    DefaultCurve = pubkey_cert_records:namedCurves(hd(tls_v1:ecc_curves(1))),
313    Ext = x509_test:extensions([{key_usage, [keyEncipherment]}]),
314    {COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, [[], [], [{extensions, Ext}]]},
315                                                         {client_chain, Default}],
316                                                        ecdhe_rsa, ecdh_rsa, Config),
317
318    COpts = ssl_test_lib:ssl_options(COpts0, Config),
319    SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
320    ECCOpts = [{honor_ecc_order, true}, {eccs, [secp256r1, DefaultCurve]}],
321    Expected = secp256r1, %% The certificate curve
322
323    case ssl_test_lib:supported_eccs(ECCOpts) of
324        true -> ssl_test_lib:ecc_test(Expected, COpts, SOpts, [], ECCOpts, Config);
325        false -> {skip, "unsupported named curves"}
326    end.
327
328client_ecdhe_ecdsa_server_ecdhe_ecdsa_server_custom(Config) ->
329    Default = ssl_test_lib:default_cert_chain_conf(),
330    DefaultCurve = pubkey_cert_records:namedCurves(hd(tls_v1:ecc_curves(1))),
331    {COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
332                                                       {client_chain, Default}],
333                                                        ecdhe_ecdsa, ecdhe_ecdsa, Config),
334    COpts = ssl_test_lib:ssl_options(COpts0, Config),
335    SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
336    ECCOpts = [{honor_ecc_order, true}, {eccs, [secp256r1, DefaultCurve]}],
337    case ssl_test_lib:supported_eccs(ECCOpts) of
338        true -> ssl_test_lib:ecc_test(secp256r1, COpts, SOpts, [], ECCOpts, Config);
339        false -> {skip, "unsupported named curves"}
340    end.
341
342client_ecdhe_ecdsa_server_ecdhe_rsa_server_custom(Config) ->
343    Default = ssl_test_lib:default_cert_chain_conf(),
344    DefaultCurve = pubkey_cert_records:namedCurves(hd(tls_v1:ecc_curves(1))),
345    {COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
346                                                         {client_chain, Default}],
347                                                        ecdhe_ecdsa, ecdhe_rsa, Config),
348    COpts = ssl_test_lib:ssl_options(COpts0, Config),
349    SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
350    ECCOpts = [{honor_ecc_order, true}, {eccs, [secp256r1, DefaultCurve]}],
351    case ssl_test_lib:supported_eccs(ECCOpts) of
352        true -> ssl_test_lib:ecc_test(secp256r1, COpts, SOpts, [], ECCOpts, Config);
353        false -> {skip, "unsupported named curves"}
354    end.
355
356client_ecdhe_ecdsa_server_ecdhe_ecdsa_client_custom(Config) ->
357    Default = ssl_test_lib:default_cert_chain_conf(),
358    DefaultCurve = pubkey_cert_records:namedCurves(hd(tls_v1:ecc_curves(1))),
359    {COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
360                                                       {client_chain, Default}],
361                                                        ecdhe_ecdsa, ecdhe_ecdsa, Config),
362    COpts = ssl_test_lib:ssl_options(COpts0, Config),
363    SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
364    ECCOpts = [{eccs, [secp256r1, DefaultCurve]}],
365    case ssl_test_lib:supported_eccs(ECCOpts) of
366        true -> ssl_test_lib:ecc_test(secp256r1, COpts, SOpts, ECCOpts, [], Config);
367        false -> {skip, "unsupported named curves"}
368    end.
369
370client_ecdhe_rsa_server_ecdhe_ecdsa_client_custom(Config) ->
371    Default = ssl_test_lib:default_cert_chain_conf(),
372    DefaultCurve = pubkey_cert_records:namedCurves(hd(tls_v1:ecc_curves(1))),
373    {COpts0, SOpts0} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default},
374                                                         {client_chain, Default}],
375                                                         ecdhe_rsa, ecdhe_ecdsa, Config),
376    COpts = ssl_test_lib:ssl_options(COpts0, Config),
377    SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
378    ECCOpts = [{eccs, [secp256r1, DefaultCurve]}],
379    case ssl_test_lib:supported_eccs(ECCOpts) of
380        true -> ssl_test_lib:ecc_test(secp256r1, COpts, SOpts, ECCOpts, [], Config);
381        false -> {skip, "unsupported named curves"}
382    end.
383
384mix_sign(Config) ->
385    mix_sign_rsa_peer(Config),
386    mix_sign_ecdsa_peer(Config).
387
388mix_sign_ecdsa_peer(Config) ->
389    {COpts0, SOpts0} = ssl_test_lib:make_mix_cert([{mix, peer_ecc} |Config]),
390    COpts = ssl_test_lib:ssl_options(COpts0, Config),
391    SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
392    ECDHE_ECDSA =
393        ssl:filter_cipher_suites(ssl:cipher_suites(default, 'tlsv1.2'),
394                                 [{key_exchange, fun(ecdhe_ecdsa) -> true; (_) -> false end}]),
395    ssl_test_lib:basic_test(COpts, [{ciphers, ECDHE_ECDSA} | SOpts], Config).
396
397
398mix_sign_rsa_peer(Config) ->
399    {COpts0, SOpts0} = ssl_test_lib:make_mix_cert([{mix, peer_rsa} |Config]),
400    COpts = ssl_test_lib:ssl_options(COpts0, Config),
401    SOpts = ssl_test_lib:ssl_options(SOpts0, Config),
402    ECDHE_RSA =
403        ssl:filter_cipher_suites(ssl:cipher_suites(default, 'tlsv1.2'),
404                                 [{key_exchange, fun(ecdhe_rsa) -> true; (_) -> false end}]),
405    ssl_test_lib:basic_test(COpts, [{ciphers, ECDHE_RSA} | SOpts], Config).
406
407