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