]>
Commit | Line | Data |
---|---|---|
5a8e54d9 MC |
1 | #! /usr/bin/env perl |
2 | # Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved. | |
3 | # | |
4 | # Licensed under the OpenSSL license (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 | }; | |
29 | ||
30 | use constant { | |
31 | CLIENT_TO_SERVER => 1, | |
32 | SERVER_TO_CLIENT => 2 | |
33 | }; | |
34 | ||
35 | ||
36 | use constant { | |
37 | X25519 => 0x1d, | |
38 | P_256 => 0x17 | |
39 | }; | |
40 | ||
41 | my $testtype; | |
42 | my $direction; | |
43 | my $selectedgroupid; | |
44 | ||
45 | my $test_name = "test_key_share"; | |
46 | setup($test_name); | |
47 | ||
48 | plan skip_all => "TLSProxy isn't usable on $^O" | |
49 | if $^O =~ /^(VMS|MSWin32)$/; | |
50 | ||
51 | plan skip_all => "$test_name needs the dynamic engine feature enabled" | |
52 | if disabled("engine") || disabled("dynamic-engine"); | |
53 | ||
54 | plan skip_all => "$test_name needs the sock feature enabled" | |
55 | if disabled("sock"); | |
56 | ||
57 | plan skip_all => "$test_name needs TLS1.3 enabled" | |
58 | if disabled("tls1_3"); | |
59 | ||
60 | $ENV{OPENSSL_ia32cap} = '~0x200000200000000'; | |
61 | ||
62 | my $proxy = TLSProxy::Proxy->new( | |
63 | undef, | |
64 | cmdstr(app(["openssl"]), display => 1), | |
65 | srctop_file("apps", "server.pem"), | |
66 | (!$ENV{HARNESS_ACTIVE} || $ENV{HARNESS_VERBOSE}) | |
67 | ); | |
68 | ||
69 | #We assume that test_ssl_new and friends will test the happy path for this, | |
70 | #so we concentrate on the less common scenarios | |
71 | ||
72 | #Test 1: An empty key_shares extension should not succeed | |
73 | $testtype = EMPTY_EXTENSION; | |
74 | $direction = CLIENT_TO_SERVER; | |
75 | $proxy->filter(\&modify_key_shares_filter); | |
76 | $proxy->start() or plan skip_all => "Unable to start up Proxy for tests"; | |
7caf619f | 77 | plan tests => 19; |
5a8e54d9 MC |
78 | #TODO(TLS1.3): Actually this should succeed after a HelloRetryRequest - but |
79 | #we've not implemented that yet, so for now we look for a fail | |
80 | ok(TLSProxy::Message->fail(), "Empty key_shares"); | |
81 | ||
82 | #Test 2: A missing key_shares extension should not succeed | |
83 | $proxy->clear(); | |
84 | $testtype = MISSING_EXTENSION; | |
85 | $proxy->start(); | |
86 | #TODO(TLS1.3): As above this should really succeed after a HelloRetryRequest, | |
87 | #but we look for fail for now | |
88 | ok(TLSProxy::Message->fail(), "Missing key_shares extension"); | |
89 | ||
90 | #Test 3: No acceptable key_shares should fail | |
91 | $proxy->clear(); | |
92 | $testtype = NO_ACCEPTABLE_KEY_SHARES; | |
93 | $proxy->start(); | |
94 | #TODO(TLS1.3): Again this should go around the loop of a HelloRetryRequest but | |
95 | #we fail for now | |
96 | ok(TLSProxy::Message->fail(), "No acceptable key_shares"); | |
97 | ||
98 | #Test 4: A non preferred but acceptable key_share should succeed | |
99 | $proxy->clear(); | |
100 | $proxy->filter(undef); | |
101 | $proxy->clientflags("-curves P-256"); | |
102 | $proxy->start(); | |
103 | ok(TLSProxy::Message->success(), "Non preferred key_share"); | |
104 | $proxy->filter(\&modify_key_shares_filter); | |
105 | ||
106 | #Test 5: An acceptable key_share after a list of non-acceptable ones should | |
107 | #succeed | |
108 | $proxy->clear(); | |
109 | $testtype = ACCEPTABLE_AT_END; | |
110 | $proxy->start(); | |
111 | ok(TLSProxy::Message->success(), "Acceptable key_share at end of list"); | |
112 | ||
113 | #Test 6: An acceptable key_share but for a group not in supported_groups should | |
114 | #fail | |
115 | $proxy->clear(); | |
116 | $testtype = NOT_IN_SUPPORTED_GROUPS; | |
117 | $proxy->start(); | |
118 | ok(TLSProxy::Message->fail(), "Acceptable key_share not in supported_groups"); | |
119 | ||
120 | #Test 7: Too short group_id should fail | |
121 | $proxy->clear(); | |
122 | $testtype = GROUP_ID_TOO_SHORT; | |
123 | $proxy->start(); | |
124 | ok(TLSProxy::Message->fail(), "Group id too short"); | |
125 | ||
126 | #Test 8: key_exchange length mismatch should fail | |
127 | $proxy->clear(); | |
128 | $testtype = KEX_LEN_MISMATCH; | |
129 | $proxy->start(); | |
130 | ok(TLSProxy::Message->fail(), "key_exchange length mismatch"); | |
131 | ||
132 | #Test 9: Zero length key_exchange should fail | |
133 | $proxy->clear(); | |
134 | $testtype = ZERO_LEN_KEX_DATA; | |
135 | $proxy->start(); | |
136 | ok(TLSProxy::Message->fail(), "zero length key_exchange data"); | |
137 | ||
138 | #Test 10: Trailing data on key_share list should fail | |
139 | $proxy->clear(); | |
140 | $testtype = TRAILING_DATA; | |
141 | $proxy->start(); | |
142 | ok(TLSProxy::Message->fail(), "key_share list trailing data"); | |
143 | ||
144 | #Test 11: Multiple acceptable key_shares - we choose the first one | |
145 | $proxy->clear(); | |
146 | $direction = SERVER_TO_CLIENT; | |
147 | $testtype = LOOK_ONLY; | |
148 | $proxy->clientflags("-curves P-256:X25519"); | |
149 | $proxy->start(); | |
150 | ok(TLSProxy::Message->success() && ($selectedgroupid == P_256), | |
151 | "Multiple acceptable key_shares"); | |
152 | ||
153 | #Test 12: Multiple acceptable key_shares - we choose the first one (part 2) | |
154 | $proxy->clear(); | |
155 | $proxy->clientflags("-curves X25519:P-256"); | |
156 | $proxy->start(); | |
157 | ok(TLSProxy::Message->success() && ($selectedgroupid == X25519), | |
158 | "Multiple acceptable key_shares (part 2)"); | |
159 | ||
160 | #Test 13: Server sends key_share that wasn't offerred should fail | |
161 | $proxy->clear(); | |
162 | $testtype = SELECT_X25519; | |
163 | $proxy->clientflags("-curves P-256"); | |
164 | $proxy->start(); | |
165 | ok(TLSProxy::Message->fail(), "Non offered key_share"); | |
166 | ||
167 | #Test 14: Too short group_id in ServerHello should fail | |
168 | $proxy->clear(); | |
169 | $testtype = GROUP_ID_TOO_SHORT; | |
170 | $proxy->start(); | |
171 | ok(TLSProxy::Message->fail(), "Group id too short in ServerHello"); | |
172 | ||
173 | #Test 15: key_exchange length mismatch in ServerHello should fail | |
174 | $proxy->clear(); | |
175 | $testtype = KEX_LEN_MISMATCH; | |
176 | $proxy->start(); | |
177 | ok(TLSProxy::Message->fail(), "key_exchange length mismatch in ServerHello"); | |
178 | ||
179 | #Test 16: Zero length key_exchange in ServerHello should fail | |
180 | $proxy->clear(); | |
181 | $testtype = ZERO_LEN_KEX_DATA; | |
182 | $proxy->start(); | |
183 | ok(TLSProxy::Message->fail(), "zero length key_exchange data in ServerHello"); | |
184 | ||
185 | #Test 17: Trailing data on key_share in ServerHello should fail | |
186 | $proxy->clear(); | |
187 | $testtype = TRAILING_DATA; | |
188 | $proxy->start(); | |
189 | ok(TLSProxy::Message->fail(), "key_share trailing data in ServerHello"); | |
190 | ||
7caf619f MC |
191 | #Test 18: key_share should not be sent if the client is not capable of |
192 | # negotiating TLSv1.3 | |
193 | $proxy->clear(); | |
194 | $proxy->filter(undef); | |
195 | $proxy->clientflags("-no_tls1_3"); | |
196 | $proxy->start(); | |
197 | my $clienthello = ${$proxy->message_list}[0]; | |
198 | ok(TLSProxy::Message->success() | |
199 | && !defined ${$clienthello->extension_data}{TLSProxy::Message::EXT_KEY_SHARE}, | |
200 | "No key_share for TLS<=1.2 client"); | |
201 | $proxy->filter(\&modify_key_shares_filter); | |
202 | ||
203 | #Test 19: A server not capable of negotiating TLSv1.3 should not attempt to | |
204 | # process a key_share | |
205 | $proxy->clear(); | |
206 | $direction = CLIENT_TO_SERVER; | |
207 | $testtype = NO_ACCEPTABLE_KEY_SHARES; | |
208 | $proxy->serverflags("-no_tls1_3"); | |
209 | $proxy->start(); | |
210 | ok(TLSProxy::Message->success(), "Ignore key_share for TLS<=1.2 server"); | |
5a8e54d9 MC |
211 | |
212 | sub modify_key_shares_filter | |
213 | { | |
214 | my $proxy = shift; | |
215 | ||
216 | # We're only interested in the initial ClientHello | |
217 | if (($direction == CLIENT_TO_SERVER && $proxy->flight != 0) | |
218 | || ($direction == SERVER_TO_CLIENT && $proxy->flight != 1)) { | |
219 | return; | |
220 | } | |
221 | ||
222 | foreach my $message (@{$proxy->message_list}) { | |
223 | if ($message->mt == TLSProxy::Message::MT_CLIENT_HELLO | |
224 | && $direction == CLIENT_TO_SERVER) { | |
225 | my $ext; | |
226 | my $suppgroups; | |
227 | ||
228 | #Setup supported groups to include some unrecognised groups | |
229 | $suppgroups = pack "C8", | |
230 | 0x00, 0x06, #List Length | |
231 | 0xff, 0xfe, #Non existing group 1 | |
232 | 0xff, 0xff, #Non existing group 2 | |
233 | 0x00, 0x1d; #x25519 | |
234 | ||
235 | if ($testtype == EMPTY_EXTENSION) { | |
236 | $ext = pack "C2", | |
237 | 0x00, 0x00; | |
238 | } elsif ($testtype == NO_ACCEPTABLE_KEY_SHARES) { | |
239 | $ext = pack "C12", | |
240 | 0x00, 0x0a, #List Length | |
241 | 0xff, 0xfe, #Non existing group 1 | |
242 | 0x00, 0x01, 0xff, #key_exchange data | |
243 | 0xff, 0xff, #Non existing group 2 | |
244 | 0x00, 0x01, 0xff; #key_exchange data | |
245 | } elsif ($testtype == ACCEPTABLE_AT_END) { | |
246 | $ext = pack "C11H64", | |
247 | 0x00, 0x29, #List Length | |
248 | 0xff, 0xfe, #Non existing group 1 | |
249 | 0x00, 0x01, 0xff, #key_exchange data | |
250 | 0x00, 0x1d, #x25519 | |
251 | 0x00, 0x20, #key_exchange data length | |
252 | "155155B95269ED5C87EAA99C2EF5A593". | |
253 | "EDF83495E80380089F831B94D14B1421"; #key_exchange data | |
254 | } elsif ($testtype == NOT_IN_SUPPORTED_GROUPS) { | |
255 | $suppgroups = pack "C4", | |
256 | 0x00, 0x02, #List Length | |
257 | 0x00, 0xfe; #Non existing group 1 | |
258 | } elsif ($testtype == GROUP_ID_TOO_SHORT) { | |
259 | $ext = pack "C6H64C1", | |
260 | 0x00, 0x25, #List Length | |
261 | 0x00, 0x1d, #x25519 | |
262 | 0x00, 0x20, #key_exchange data length | |
263 | "155155B95269ED5C87EAA99C2EF5A593". | |
264 | "EDF83495E80380089F831B94D14B1421"; #key_exchange data | |
265 | 0x00; #Group id too short | |
266 | } elsif ($testtype == KEX_LEN_MISMATCH) { | |
267 | $ext = pack "C8", | |
268 | 0x00, 0x06, #List Length | |
269 | 0x00, 0x1d, #x25519 | |
270 | 0x00, 0x20, #key_exchange data length | |
271 | 0x15, 0x51; #Only two bytes of data, but length should be 32 | |
272 | } elsif ($testtype == ZERO_LEN_KEX_DATA) { | |
273 | $ext = pack "C10H64", | |
274 | 0x00, 0x28, #List Length | |
275 | 0xff, 0xfe, #Non existing group 1 | |
276 | 0x00, 0x00, #zero length key_exchange data is invalid | |
277 | 0x00, 0x1d, #x25519 | |
278 | 0x00, 0x20, #key_exchange data length | |
279 | "155155B95269ED5C87EAA99C2EF5A593". | |
280 | "EDF83495E80380089F831B94D14B1421"; #key_exchange data | |
281 | } elsif ($testtype == TRAILING_DATA) { | |
282 | $ext = pack "C6H64C1", | |
283 | 0x00, 0x24, #List Length | |
284 | 0x00, 0x1d, #x25519 | |
285 | 0x00, 0x20, #key_exchange data length | |
286 | "155155B95269ED5C87EAA99C2EF5A593". | |
287 | "EDF83495E80380089F831B94D14B1421", #key_exchange data | |
288 | 0x00; #Trailing garbage | |
289 | } | |
290 | ||
291 | $message->set_extension( | |
292 | TLSProxy::Message::EXT_SUPPORTED_GROUPS, $suppgroups); | |
293 | ||
294 | if ($testtype == MISSING_EXTENSION) { | |
295 | $message->delete_extension( | |
296 | TLSProxy::Message::EXT_KEY_SHARE); | |
297 | } elsif ($testtype != NOT_IN_SUPPORTED_GROUPS) { | |
298 | $message->set_extension( | |
299 | TLSProxy::Message::EXT_KEY_SHARE, $ext); | |
300 | } | |
301 | ||
302 | $message->repack(); | |
303 | } elsif ($message->mt == TLSProxy::Message::MT_SERVER_HELLO | |
304 | && $direction == SERVER_TO_CLIENT) { | |
305 | my $ext; | |
306 | my $key_share = | |
307 | ${$message->extension_data}{TLSProxy::Message::EXT_KEY_SHARE}; | |
308 | $selectedgroupid = unpack("n", $key_share); | |
309 | ||
310 | if ($testtype == LOOK_ONLY) { | |
311 | return; | |
312 | } | |
313 | if ($testtype == SELECT_X25519) { | |
314 | $ext = pack "C4H64", | |
315 | 0x00, 0x1d, #x25519 | |
316 | 0x00, 0x20, #key_exchange data length | |
317 | "155155B95269ED5C87EAA99C2EF5A593". | |
318 | "EDF83495E80380089F831B94D14B1421"; #key_exchange data | |
319 | } elsif ($testtype == GROUP_ID_TOO_SHORT) { | |
320 | $ext = pack "C1", | |
321 | 0x00; | |
322 | } elsif ($testtype == KEX_LEN_MISMATCH) { | |
323 | $ext = pack "C6", | |
324 | 0x00, 0x1d, #x25519 | |
325 | 0x00, 0x20, #key_exchange data length | |
326 | 0x15, 0x51; #Only two bytes of data, but length should be 32 | |
327 | } elsif ($testtype == ZERO_LEN_KEX_DATA) { | |
328 | $ext = pack "C4", | |
329 | 0x00, 0x1d, #x25519 | |
330 | 0x00, 0x00, #zero length key_exchange data is invalid | |
331 | } elsif ($testtype == TRAILING_DATA) { | |
332 | $ext = pack "C4H64C1", | |
333 | 0x00, 0x1d, #x25519 | |
334 | 0x00, 0x20, #key_exchange data length | |
335 | "155155B95269ED5C87EAA99C2EF5A593". | |
336 | "EDF83495E80380089F831B94D14B1421", #key_exchange data | |
337 | 0x00; #Trailing garbage | |
338 | } | |
339 | $message->set_extension( TLSProxy::Message::EXT_KEY_SHARE, $ext); | |
340 | ||
341 | $message->repack(); | |
342 | } | |
343 | } | |
344 | } | |
345 | ||
346 |