chunk 7 of CMP contribution to OpenSSL
[openssl.git] / test / recipes / 70-test_key_share.t
1 #! /usr/bin/env perl
2 # Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved.
3 #
4 # Licensed under the Apache License 2.0 (the "License").  You may not use
5 # this file except in compliance with the License.  You can obtain a copy
6 # in the file LICENSE in the source distribution or at
7 # https://www.openssl.org/source/license.html
8
9 use strict;
10 use OpenSSL::Test qw/:DEFAULT cmdstr srctop_file bldtop_dir/;
11 use OpenSSL::Test::Utils;
12 use TLSProxy::Proxy;
13 use File::Temp qw(tempfile);
14
15 use constant {
16     LOOK_ONLY => 0,
17     EMPTY_EXTENSION => 1,
18     MISSING_EXTENSION => 2,
19     NO_ACCEPTABLE_KEY_SHARES => 3,
20     NON_PREFERRED_KEY_SHARE => 4,
21     ACCEPTABLE_AT_END => 5,
22     NOT_IN_SUPPORTED_GROUPS => 6,
23     GROUP_ID_TOO_SHORT => 7,
24     KEX_LEN_MISMATCH => 8,
25     ZERO_LEN_KEX_DATA => 9,
26     TRAILING_DATA => 10,
27     SELECT_X25519 => 11,
28     NO_KEY_SHARES_IN_HRR => 12
29 };
30
31 use constant {
32     CLIENT_TO_SERVER => 1,
33     SERVER_TO_CLIENT => 2
34 };
35
36
37 use constant {
38     X25519 => 0x1d,
39     P_256 => 0x17,
40     FFDHE2048 => 0x0100,
41     FFDHE3072 => 0x0101
42 };
43
44 my $testtype;
45 my $direction;
46 my $selectedgroupid;
47
48 my $test_name = "test_key_share";
49 setup($test_name);
50
51 plan skip_all => "TLSProxy isn't usable on $^O"
52     if $^O =~ /^(VMS)$/;
53
54 plan skip_all => "$test_name needs the dynamic engine feature enabled"
55     if disabled("engine") || disabled("dynamic-engine");
56
57 plan skip_all => "$test_name needs the sock feature enabled"
58     if disabled("sock");
59
60 plan skip_all => "$test_name needs TLS1.3 enabled"
61     if disabled("tls1_3");
62
63 $ENV{OPENSSL_ia32cap} = '~0x200000200000000';
64
65 my $proxy = TLSProxy::Proxy->new(
66     undef,
67     cmdstr(app(["openssl"]), display => 1),
68     srctop_file("apps", "server.pem"),
69     (!$ENV{HARNESS_ACTIVE} || $ENV{HARNESS_VERBOSE})
70 );
71
72 #We assume that test_ssl_new and friends will test the happy path for this,
73 #so we concentrate on the less common scenarios
74
75 #Test 1: An empty key_shares extension should succeed after a HelloRetryRequest
76 $testtype = EMPTY_EXTENSION;
77 $direction = CLIENT_TO_SERVER;
78 $proxy->filter(\&modify_key_shares_filter);
79 if (disabled("ec")) {
80     $proxy->serverflags("-groups ffdhe3072");
81 } else {
82     $proxy->serverflags("-groups P-256");
83 }
84 $proxy->start() or plan skip_all => "Unable to start up Proxy for tests";
85 plan tests => 22;
86 ok(TLSProxy::Message->success(), "Success after HRR");
87
88 #Test 2: The server sending an HRR requesting a group the client already sent
89 #        should fail
90 $proxy->clear();
91 $proxy->start();
92 ok(TLSProxy::Message->fail(), "Server asks for group already provided");
93
94 #Test 3: A missing key_shares extension should not succeed
95 $proxy->clear();
96 $testtype = MISSING_EXTENSION;
97 $proxy->start();
98 ok(TLSProxy::Message->fail(), "Missing key_shares extension");
99
100 #Test 4: No initial acceptable key_shares should succeed after a
101 #        HelloRetryRequest
102 $proxy->clear();
103 $proxy->filter(undef);
104 if (disabled("ec")) {
105     $proxy->serverflags("-groups ffdhe3072");
106 } else {
107     $proxy->serverflags("-groups P-256");
108 }
109 $proxy->start();
110 ok(TLSProxy::Message->success(), "No initial acceptable key_shares");
111
112 #Test 5: No acceptable key_shares and no shared groups should fail
113 $proxy->clear();
114 $proxy->filter(undef);
115 if (disabled("ec")) {
116     $proxy->serverflags("-groups ffdhe2048");
117 } else {
118     $proxy->serverflags("-groups P-256");
119 }
120 if (disabled("ec")) {
121     $proxy->clientflags("-groups ffdhe3072");
122 } else {
123     $proxy->clientflags("-groups P-384");
124 }
125 $proxy->start();
126 ok(TLSProxy::Message->fail(), "No acceptable key_shares");
127
128 #Test 6: A non preferred but acceptable key_share should succeed
129 $proxy->clear();
130 $proxy->clientflags("-curves P-256");
131 if (disabled("ec")) {
132     $proxy->clientflags("-groups ffdhe3072");
133 } else {
134     $proxy->clientflags("-groups P-256");
135 }
136 $proxy->start();
137 ok(TLSProxy::Message->success(), "Non preferred key_share");
138 $proxy->filter(\&modify_key_shares_filter);
139
140 SKIP: {
141     skip "No ec support in this OpenSSL build", 1 if disabled("ec");
142
143     #Test 7: An acceptable key_share after a list of non-acceptable ones should
144     #succeed
145     $proxy->clear();
146     $testtype = ACCEPTABLE_AT_END;
147     $proxy->start();
148     ok(TLSProxy::Message->success(), "Acceptable key_share at end of list");
149 }
150
151 #Test 8: An acceptable key_share but for a group not in supported_groups should
152 #fail
153 $proxy->clear();
154 $testtype = NOT_IN_SUPPORTED_GROUPS;
155 $proxy->start();
156 ok(TLSProxy::Message->fail(), "Acceptable key_share not in supported_groups");
157
158 #Test 9: Too short group_id should fail
159 $proxy->clear();
160 $testtype = GROUP_ID_TOO_SHORT;
161 $proxy->start();
162 ok(TLSProxy::Message->fail(), "Group id too short");
163
164 #Test 10: key_exchange length mismatch should fail
165 $proxy->clear();
166 $testtype = KEX_LEN_MISMATCH;
167 $proxy->start();
168 ok(TLSProxy::Message->fail(), "key_exchange length mismatch");
169
170 #Test 11: Zero length key_exchange should fail
171 $proxy->clear();
172 $testtype = ZERO_LEN_KEX_DATA;
173 $proxy->start();
174 ok(TLSProxy::Message->fail(), "zero length key_exchange data");
175
176 #Test 12: Trailing data on key_share list should fail
177 $proxy->clear();
178 $testtype = TRAILING_DATA;
179 $proxy->start();
180 ok(TLSProxy::Message->fail(), "key_share list trailing data");
181
182 #Test 13: Multiple acceptable key_shares - we choose the first one
183 $proxy->clear();
184 $direction = SERVER_TO_CLIENT;
185 $testtype = LOOK_ONLY;
186 $selectedgroupid = 0;
187 if (disabled("ec")) {
188     $proxy->clientflags("-groups ffdhe3072:ffdhe2048");
189 } else {
190     $proxy->clientflags("-groups P-256:X25519");
191 }
192 $proxy->start();
193 if (disabled("ec")) {
194     ok(TLSProxy::Message->success() && ($selectedgroupid == FFDHE3072),
195        "Multiple acceptable key_shares");
196 } else {
197     ok(TLSProxy::Message->success() && ($selectedgroupid == P_256),
198        "Multiple acceptable key_shares");
199 }
200
201 #Test 14: Multiple acceptable key_shares - we choose the first one (part 2)
202 $proxy->clear();
203 if (disabled("ec")) {
204     $proxy->clientflags("-curves ffdhe2048:ffdhe3072");
205 } else {
206     $proxy->clientflags("-curves X25519:P-256");
207 }
208 $proxy->start();
209 if (disabled("ec")) {
210     ok(TLSProxy::Message->success() && ($selectedgroupid == FFDHE2048),
211        "Multiple acceptable key_shares (part 2)");
212 } else {
213     ok(TLSProxy::Message->success() && ($selectedgroupid == X25519),
214        "Multiple acceptable key_shares (part 2)");
215 }
216
217 #Test 15: Server sends key_share that wasn't offered should fail
218 $proxy->clear();
219 $testtype = SELECT_X25519;
220 if (disabled("ec")) {
221     $proxy->clientflags("-groups ffdhe3072");
222 } else {
223     $proxy->clientflags("-groups P-256");
224 }
225 $proxy->start();
226 ok(TLSProxy::Message->fail(), "Non offered key_share");
227
228 #Test 16: Too short group_id in ServerHello should fail
229 $proxy->clear();
230 $testtype = GROUP_ID_TOO_SHORT;
231 $proxy->start();
232 ok(TLSProxy::Message->fail(), "Group id too short in ServerHello");
233
234 #Test 17: key_exchange length mismatch in ServerHello should fail
235 $proxy->clear();
236 $testtype = KEX_LEN_MISMATCH;
237 $proxy->start();
238 ok(TLSProxy::Message->fail(), "key_exchange length mismatch in ServerHello");
239
240 #Test 18: Zero length key_exchange in ServerHello should fail
241 $proxy->clear();
242 $testtype = ZERO_LEN_KEX_DATA;
243 $proxy->start();
244 ok(TLSProxy::Message->fail(), "zero length key_exchange data in ServerHello");
245
246 #Test 19: Trailing data on key_share in ServerHello should fail
247 $proxy->clear();
248 $testtype = TRAILING_DATA;
249 $proxy->start();
250 ok(TLSProxy::Message->fail(), "key_share trailing data in ServerHello");
251
252 SKIP: {
253     skip "No TLSv1.2 support in this OpenSSL build", 2 if disabled("tls1_2");
254
255     #Test 20: key_share should not be sent if the client is not capable of
256     #         negotiating TLSv1.3
257     $proxy->clear();
258     $proxy->filter(undef);
259     $proxy->clientflags("-no_tls1_3");
260     $proxy->start();
261     my $clienthello = $proxy->message_list->[0];
262     ok(TLSProxy::Message->success()
263        && !defined $clienthello->extension_data->{TLSProxy::Message::EXT_KEY_SHARE},
264        "No key_share for TLS<=1.2 client");
265     $proxy->filter(\&modify_key_shares_filter);
266
267     #Test 21: A server not capable of negotiating TLSv1.3 should not attempt to
268     #         process a key_share
269     $proxy->clear();
270     $direction = CLIENT_TO_SERVER;
271     $testtype = NO_ACCEPTABLE_KEY_SHARES;
272     $proxy->serverflags("-no_tls1_3");
273     $proxy->start();
274     ok(TLSProxy::Message->success(), "Ignore key_share for TLS<=1.2 server");
275 }
276
277 #Test 22: The server sending an HRR but not requesting a new key_share should
278 #         fail
279 $proxy->clear();
280 $direction = SERVER_TO_CLIENT;
281 $testtype = NO_KEY_SHARES_IN_HRR;
282 if (disabled("ec")) {
283     $proxy->serverflags("-groups ffdhe2048");
284 } else {
285     $proxy->serverflags("-groups X25519");
286 }
287 $proxy->start();
288 ok(TLSProxy::Message->fail(), "Server sends HRR with no key_shares");
289
290 sub modify_key_shares_filter
291 {
292     my $proxy = shift;
293
294     # We're only interested in the initial ClientHello
295     if (($direction == CLIENT_TO_SERVER && $proxy->flight != 0
296                 && ($proxy->flight != 1 || $testtype != NO_KEY_SHARES_IN_HRR))
297             || ($direction == SERVER_TO_CLIENT && $proxy->flight != 1)) {
298         return;
299     }
300
301     foreach my $message (@{$proxy->message_list}) {
302         if ($message->mt == TLSProxy::Message::MT_CLIENT_HELLO
303                 && $direction == CLIENT_TO_SERVER) {
304             my $ext;
305             my $suppgroups;
306
307             #Setup supported groups to include some unrecognised groups
308             $suppgroups = pack "C8",
309                 0x00, 0x06, #List Length
310                 0xff, 0xfe, #Non existing group 1
311                 0xff, 0xff, #Non existing group 2
312                 0x00, 0x1d; #x25519
313
314             if ($testtype == EMPTY_EXTENSION) {
315                 $ext = pack "C2",
316                     0x00, 0x00;
317             } elsif ($testtype == NO_ACCEPTABLE_KEY_SHARES) {
318                 $ext = pack "C12",
319                     0x00, 0x0a, #List Length
320                     0xff, 0xfe, #Non existing group 1
321                     0x00, 0x01, 0xff, #key_exchange data
322                     0xff, 0xff, #Non existing group 2
323                     0x00, 0x01, 0xff; #key_exchange data
324             } elsif ($testtype == ACCEPTABLE_AT_END) {
325                 $ext = pack "C11H64",
326                     0x00, 0x29, #List Length
327                     0xff, 0xfe, #Non existing group 1
328                     0x00, 0x01, 0xff, #key_exchange data
329                     0x00, 0x1d, #x25519
330                     0x00, 0x20, #key_exchange data length
331                     "155155B95269ED5C87EAA99C2EF5A593".
332                     "EDF83495E80380089F831B94D14B1421";  #key_exchange data
333             } elsif ($testtype == NOT_IN_SUPPORTED_GROUPS) {
334                 $suppgroups = pack "C4",
335                     0x00, 0x02, #List Length
336                     0x00, 0xfe; #Non existing group 1
337             } elsif ($testtype == GROUP_ID_TOO_SHORT) {
338                 $ext = pack "C6H64C1",
339                     0x00, 0x25, #List Length
340                     0x00, 0x1d, #x25519
341                     0x00, 0x20, #key_exchange data length
342                     "155155B95269ED5C87EAA99C2EF5A593".
343                     "EDF83495E80380089F831B94D14B1421";  #key_exchange data
344                     0x00;       #Group id too short
345             } elsif ($testtype == KEX_LEN_MISMATCH) {
346                 $ext = pack "C8",
347                     0x00, 0x06, #List Length
348                     0x00, 0x1d, #x25519
349                     0x00, 0x20, #key_exchange data length
350                     0x15, 0x51; #Only two bytes of data, but length should be 32
351             } elsif ($testtype == ZERO_LEN_KEX_DATA) {
352                 $ext = pack "C10H64",
353                     0x00, 0x28, #List Length
354                     0xff, 0xfe, #Non existing group 1
355                     0x00, 0x00, #zero length key_exchange data is invalid
356                     0x00, 0x1d, #x25519
357                     0x00, 0x20, #key_exchange data length
358                     "155155B95269ED5C87EAA99C2EF5A593".
359                     "EDF83495E80380089F831B94D14B1421";  #key_exchange data
360             } elsif ($testtype == TRAILING_DATA) {
361                 $ext = pack "C6H64C1",
362                     0x00, 0x24, #List Length
363                     0x00, 0x1d, #x25519
364                     0x00, 0x20, #key_exchange data length
365                     "155155B95269ED5C87EAA99C2EF5A593".
366                     "EDF83495E80380089F831B94D14B1421", #key_exchange data
367                     0x00; #Trailing garbage
368             } elsif ($testtype == NO_KEY_SHARES_IN_HRR) {
369                 #We trick the server into thinking we sent a P-256 key_share -
370                 #but the client actually sent X25519
371                 $ext = pack "C7",
372                     0x00, 0x05, #List Length
373                     0x00, 0x17, #P-256
374                     0x00, 0x01, #key_exchange data length
375                     0xff;       #Dummy key_share data
376             }
377
378             if ($testtype != EMPTY_EXTENSION
379                     && $testtype != NO_KEY_SHARES_IN_HRR) {
380                 $message->set_extension(
381                     TLSProxy::Message::EXT_SUPPORTED_GROUPS, $suppgroups);
382             }
383
384             if ($testtype == MISSING_EXTENSION) {
385                 $message->delete_extension(
386                     TLSProxy::Message::EXT_KEY_SHARE);
387             } elsif ($testtype != NOT_IN_SUPPORTED_GROUPS) {
388                 $message->set_extension(
389                     TLSProxy::Message::EXT_KEY_SHARE, $ext);
390             }
391
392             $message->repack();
393         } elsif ($message->mt == TLSProxy::Message::MT_SERVER_HELLO
394                      && $direction == SERVER_TO_CLIENT) {
395             my $ext;
396             my $key_share =
397                 $message->extension_data->{TLSProxy::Message::EXT_KEY_SHARE};
398             $selectedgroupid = unpack("n", $key_share);
399
400             if ($testtype == LOOK_ONLY) {
401                 return;
402             }
403             if ($testtype == NO_KEY_SHARES_IN_HRR) {
404                 $message->delete_extension(TLSProxy::Message::EXT_KEY_SHARE);
405                 $message->set_extension(TLSProxy::Message::EXT_UNKNOWN, "");
406                 $message->repack();
407                 return;
408             }
409             if ($testtype == SELECT_X25519) {
410                 $ext = pack "C4H64",
411                     0x00, 0x1d, #x25519
412                     0x00, 0x20, #key_exchange data length
413                     "155155B95269ED5C87EAA99C2EF5A593".
414                     "EDF83495E80380089F831B94D14B1421";  #key_exchange data
415             } elsif ($testtype == GROUP_ID_TOO_SHORT) {
416                 $ext = pack "C1",
417                     0x00;
418             } elsif ($testtype == KEX_LEN_MISMATCH) {
419                 $ext = pack "C6",
420                     0x00, 0x1d, #x25519
421                     0x00, 0x20, #key_exchange data length
422                     0x15, 0x51; #Only two bytes of data, but length should be 32
423             } elsif ($testtype == ZERO_LEN_KEX_DATA) {
424                 $ext = pack "C4",
425                     0x00, 0x1d, #x25519
426                     0x00, 0x00, #zero length key_exchange data is invalid
427             } elsif ($testtype == TRAILING_DATA) {
428                 $ext = pack "C4H64C1",
429                     0x00, 0x1d, #x25519
430                     0x00, 0x20, #key_exchange data length
431                     "155155B95269ED5C87EAA99C2EF5A593".
432                     "EDF83495E80380089F831B94D14B1421", #key_exchange data
433                     0x00; #Trailing garbage
434             }
435             $message->set_extension(TLSProxy::Message::EXT_KEY_SHARE, $ext);
436
437             $message->repack();
438         }
439     }
440 }
441
442