]>
Commit | Line | Data |
---|---|---|
5a8e54d9 | 1 | #! /usr/bin/env perl |
6738bf14 | 2 | # Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved. |
5a8e54d9 | 3 | # |
909f1a2e | 4 | # Licensed under the Apache License 2.0 (the "License"). You may not use |
5a8e54d9 MC |
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, | |
5e3766e2 MC |
27 | SELECT_X25519 => 11, |
28 | NO_KEY_SHARES_IN_HRR => 12 | |
5a8e54d9 MC |
29 | }; |
30 | ||
31 | use constant { | |
32 | CLIENT_TO_SERVER => 1, | |
33 | SERVER_TO_CLIENT => 2 | |
34 | }; | |
35 | ||
36 | ||
37 | use constant { | |
38 | X25519 => 0x1d, | |
dbc6268f MC |
39 | P_256 => 0x17, |
40 | FFDHE2048 => 0x0100, | |
41 | FFDHE3072 => 0x0101 | |
5a8e54d9 MC |
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" | |
c5856878 | 52 | if $^O =~ /^(VMS)$/; |
5a8e54d9 MC |
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 | ||
a763ca11 MC |
63 | plan skip_all => "$test_name needs EC or DH enabled" |
64 | if disabled("ec") && disabled("dh"); | |
65 | ||
5a8e54d9 MC |
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 | ||
38f5c30b | 78 | #Test 1: An empty key_shares extension should succeed after a HelloRetryRequest |
5a8e54d9 MC |
79 | $testtype = EMPTY_EXTENSION; |
80 | $direction = CLIENT_TO_SERVER; | |
81 | $proxy->filter(\&modify_key_shares_filter); | |
dbc6268f MC |
82 | if (disabled("ec")) { |
83 | $proxy->serverflags("-groups ffdhe3072"); | |
84 | } else { | |
85 | $proxy->serverflags("-groups P-256"); | |
86 | } | |
5a8e54d9 | 87 | $proxy->start() or plan skip_all => "Unable to start up Proxy for tests"; |
5e3766e2 | 88 | plan tests => 22; |
38f5c30b | 89 | ok(TLSProxy::Message->success(), "Success after HRR"); |
5a8e54d9 | 90 | |
38f5c30b MC |
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 | |
5a8e54d9 MC |
98 | $proxy->clear(); |
99 | $testtype = MISSING_EXTENSION; | |
100 | $proxy->start(); | |
5a8e54d9 MC |
101 | ok(TLSProxy::Message->fail(), "Missing key_shares extension"); |
102 | ||
38f5c30b MC |
103 | #Test 4: No initial acceptable key_shares should succeed after a |
104 | # HelloRetryRequest | |
5a8e54d9 | 105 | $proxy->clear(); |
38f5c30b | 106 | $proxy->filter(undef); |
dbc6268f MC |
107 | if (disabled("ec")) { |
108 | $proxy->serverflags("-groups ffdhe3072"); | |
109 | } else { | |
110 | $proxy->serverflags("-groups P-256"); | |
111 | } | |
5a8e54d9 | 112 | $proxy->start(); |
38f5c30b | 113 | ok(TLSProxy::Message->success(), "No initial acceptable key_shares"); |
5a8e54d9 | 114 | |
38f5c30b | 115 | #Test 5: No acceptable key_shares and no shared groups should fail |
5a8e54d9 MC |
116 | $proxy->clear(); |
117 | $proxy->filter(undef); | |
dbc6268f MC |
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 | } | |
38f5c30b MC |
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(); | |
5a8e54d9 | 133 | $proxy->clientflags("-curves P-256"); |
dbc6268f MC |
134 | if (disabled("ec")) { |
135 | $proxy->clientflags("-groups ffdhe3072"); | |
136 | } else { | |
137 | $proxy->clientflags("-groups P-256"); | |
138 | } | |
5a8e54d9 MC |
139 | $proxy->start(); |
140 | ok(TLSProxy::Message->success(), "Non preferred key_share"); | |
141 | $proxy->filter(\&modify_key_shares_filter); | |
142 | ||
dbc6268f MC |
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 | } | |
5a8e54d9 | 153 | |
38f5c30b | 154 | #Test 8: An acceptable key_share but for a group not in supported_groups should |
5a8e54d9 MC |
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 | ||
38f5c30b | 161 | #Test 9: Too short group_id should fail |
5a8e54d9 MC |
162 | $proxy->clear(); |
163 | $testtype = GROUP_ID_TOO_SHORT; | |
164 | $proxy->start(); | |
165 | ok(TLSProxy::Message->fail(), "Group id too short"); | |
166 | ||
38f5c30b | 167 | #Test 10: key_exchange length mismatch should fail |
5a8e54d9 MC |
168 | $proxy->clear(); |
169 | $testtype = KEX_LEN_MISMATCH; | |
170 | $proxy->start(); | |
171 | ok(TLSProxy::Message->fail(), "key_exchange length mismatch"); | |
172 | ||
38f5c30b | 173 | #Test 11: Zero length key_exchange should fail |
5a8e54d9 MC |
174 | $proxy->clear(); |
175 | $testtype = ZERO_LEN_KEX_DATA; | |
176 | $proxy->start(); | |
177 | ok(TLSProxy::Message->fail(), "zero length key_exchange data"); | |
178 | ||
38f5c30b | 179 | #Test 12: Trailing data on key_share list should fail |
5a8e54d9 MC |
180 | $proxy->clear(); |
181 | $testtype = TRAILING_DATA; | |
182 | $proxy->start(); | |
183 | ok(TLSProxy::Message->fail(), "key_share list trailing data"); | |
184 | ||
38f5c30b | 185 | #Test 13: Multiple acceptable key_shares - we choose the first one |
5a8e54d9 MC |
186 | $proxy->clear(); |
187 | $direction = SERVER_TO_CLIENT; | |
188 | $testtype = LOOK_ONLY; | |
dbc6268f MC |
189 | $selectedgroupid = 0; |
190 | if (disabled("ec")) { | |
191 | $proxy->clientflags("-groups ffdhe3072:ffdhe2048"); | |
192 | } else { | |
193 | $proxy->clientflags("-groups P-256:X25519"); | |
194 | } | |
5a8e54d9 | 195 | $proxy->start(); |
dbc6268f MC |
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 | } | |
5a8e54d9 | 203 | |
38f5c30b | 204 | #Test 14: Multiple acceptable key_shares - we choose the first one (part 2) |
5a8e54d9 | 205 | $proxy->clear(); |
dbc6268f MC |
206 | if (disabled("ec")) { |
207 | $proxy->clientflags("-curves ffdhe2048:ffdhe3072"); | |
208 | } else { | |
209 | $proxy->clientflags("-curves X25519:P-256"); | |
210 | } | |
5a8e54d9 | 211 | $proxy->start(); |
dbc6268f MC |
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 | } | |
5a8e54d9 | 219 | |
46f4e1be | 220 | #Test 15: Server sends key_share that wasn't offered should fail |
5a8e54d9 MC |
221 | $proxy->clear(); |
222 | $testtype = SELECT_X25519; | |
dbc6268f MC |
223 | if (disabled("ec")) { |
224 | $proxy->clientflags("-groups ffdhe3072"); | |
225 | } else { | |
226 | $proxy->clientflags("-groups P-256"); | |
227 | } | |
5a8e54d9 MC |
228 | $proxy->start(); |
229 | ok(TLSProxy::Message->fail(), "Non offered key_share"); | |
230 | ||
38f5c30b | 231 | #Test 16: Too short group_id in ServerHello should fail |
5a8e54d9 MC |
232 | $proxy->clear(); |
233 | $testtype = GROUP_ID_TOO_SHORT; | |
234 | $proxy->start(); | |
235 | ok(TLSProxy::Message->fail(), "Group id too short in ServerHello"); | |
236 | ||
38f5c30b | 237 | #Test 17: key_exchange length mismatch in ServerHello should fail |
5a8e54d9 MC |
238 | $proxy->clear(); |
239 | $testtype = KEX_LEN_MISMATCH; | |
240 | $proxy->start(); | |
241 | ok(TLSProxy::Message->fail(), "key_exchange length mismatch in ServerHello"); | |
242 | ||
38f5c30b | 243 | #Test 18: Zero length key_exchange in ServerHello should fail |
5a8e54d9 MC |
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 | ||
38f5c30b | 249 | #Test 19: Trailing data on key_share in ServerHello should fail |
5a8e54d9 MC |
250 | $proxy->clear(); |
251 | $testtype = TRAILING_DATA; | |
252 | $proxy->start(); | |
253 | ok(TLSProxy::Message->fail(), "key_share trailing data in ServerHello"); | |
254 | ||
c423ecaa MC |
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 | } | |
5a8e54d9 | 279 | |
5e3766e2 MC |
280 | #Test 22: The server sending an HRR but not requesting a new key_share should |
281 | # fail | |
282 | $proxy->clear(); | |
597c51bc | 283 | $direction = SERVER_TO_CLIENT; |
5e3766e2 | 284 | $testtype = NO_KEY_SHARES_IN_HRR; |
dbc6268f MC |
285 | if (disabled("ec")) { |
286 | $proxy->serverflags("-groups ffdhe2048"); | |
287 | } else { | |
288 | $proxy->serverflags("-groups X25519"); | |
289 | } | |
5e3766e2 MC |
290 | $proxy->start(); |
291 | ok(TLSProxy::Message->fail(), "Server sends HRR with no key_shares"); | |
292 | ||
5a8e54d9 MC |
293 | sub modify_key_shares_filter |
294 | { | |
295 | my $proxy = shift; | |
296 | ||
297 | # We're only interested in the initial ClientHello | |
5e3766e2 MC |
298 | if (($direction == CLIENT_TO_SERVER && $proxy->flight != 0 |
299 | && ($proxy->flight != 1 || $testtype != NO_KEY_SHARES_IN_HRR)) | |
5a8e54d9 MC |
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 | |
5e3766e2 MC |
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 | |
5a8e54d9 MC |
379 | } |
380 | ||
5e3766e2 MC |
381 | if ($testtype != EMPTY_EXTENSION |
382 | && $testtype != NO_KEY_SHARES_IN_HRR) { | |
38f5c30b MC |
383 | $message->set_extension( |
384 | TLSProxy::Message::EXT_SUPPORTED_GROUPS, $suppgroups); | |
385 | } | |
5a8e54d9 MC |
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 = | |
ecc2f938 | 400 | $message->extension_data->{TLSProxy::Message::EXT_KEY_SHARE}; |
5a8e54d9 MC |
401 | $selectedgroupid = unpack("n", $key_share); |
402 | ||
403 | if ($testtype == LOOK_ONLY) { | |
404 | return; | |
405 | } | |
597c51bc MC |
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 | } | |
5a8e54d9 MC |
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 | } | |
ecc2f938 | 438 | $message->set_extension(TLSProxy::Message::EXT_KEY_SHARE, $ext); |
5a8e54d9 MC |
439 | |
440 | $message->repack(); | |
597c51bc | 441 | } |
5a8e54d9 MC |
442 | } |
443 | } | |
444 | ||
445 |