]>
Commit | Line | Data |
---|---|---|
3ae6b5f8 | 1 | #! /usr/bin/env perl |
6738bf14 | 2 | # Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved. |
3ae6b5f8 MC |
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 srctop_dir bldtop_dir/; | |
11 | use OpenSSL::Test::Utils; | |
12 | use File::Temp qw(tempfile); | |
13 | use TLSProxy::Proxy; | |
14 | use checkhandshake qw(checkhandshake @handmessages @extensions); | |
15 | ||
16 | my $test_name = "test_tls13kexmodes"; | |
17 | setup($test_name); | |
18 | ||
19 | plan skip_all => "TLSProxy isn't usable on $^O" | |
c5856878 | 20 | if $^O =~ /^(VMS)$/; |
3ae6b5f8 MC |
21 | |
22 | plan skip_all => "$test_name needs the dynamic engine feature enabled" | |
23 | if disabled("engine") || disabled("dynamic-engine"); | |
24 | ||
25 | plan skip_all => "$test_name needs the sock feature enabled" | |
26 | if disabled("sock"); | |
27 | ||
28 | plan skip_all => "$test_name needs TLSv1.3 enabled" | |
29 | if disabled("tls1_3"); | |
30 | ||
31 | $ENV{OPENSSL_ia32cap} = '~0x200000200000000'; | |
32 | $ENV{CTLOG_FILE} = srctop_file("test", "ct", "log_list.conf"); | |
33 | ||
34 | ||
35 | @handmessages = ( | |
36 | [TLSProxy::Message::MT_CLIENT_HELLO, | |
37 | checkhandshake::ALL_HANDSHAKES], | |
597c51bc | 38 | [TLSProxy::Message::MT_SERVER_HELLO, |
d542790b MC |
39 | checkhandshake::HRR_HANDSHAKE | checkhandshake::HRR_RESUME_HANDSHAKE], |
40 | [TLSProxy::Message::MT_CLIENT_HELLO, | |
41 | checkhandshake::HRR_HANDSHAKE | checkhandshake::HRR_RESUME_HANDSHAKE], | |
3ae6b5f8 MC |
42 | [TLSProxy::Message::MT_SERVER_HELLO, |
43 | checkhandshake::ALL_HANDSHAKES], | |
44 | [TLSProxy::Message::MT_ENCRYPTED_EXTENSIONS, | |
45 | checkhandshake::ALL_HANDSHAKES], | |
46 | [TLSProxy::Message::MT_CERTIFICATE_REQUEST, | |
47 | checkhandshake::CLIENT_AUTH_HANDSHAKE], | |
48 | [TLSProxy::Message::MT_CERTIFICATE, | |
d542790b | 49 | checkhandshake::ALL_HANDSHAKES & ~(checkhandshake::RESUME_HANDSHAKE | checkhandshake::HRR_RESUME_HANDSHAKE)], |
3ae6b5f8 | 50 | [TLSProxy::Message::MT_CERTIFICATE_VERIFY, |
d542790b | 51 | checkhandshake::ALL_HANDSHAKES & ~(checkhandshake::RESUME_HANDSHAKE | checkhandshake::HRR_RESUME_HANDSHAKE)], |
3ae6b5f8 MC |
52 | [TLSProxy::Message::MT_FINISHED, |
53 | checkhandshake::ALL_HANDSHAKES], | |
54 | [TLSProxy::Message::MT_CERTIFICATE, | |
55 | checkhandshake::CLIENT_AUTH_HANDSHAKE], | |
56 | [TLSProxy::Message::MT_CERTIFICATE_VERIFY, | |
57 | checkhandshake::CLIENT_AUTH_HANDSHAKE], | |
58 | [TLSProxy::Message::MT_FINISHED, | |
59 | checkhandshake::ALL_HANDSHAKES], | |
60 | [0, 0] | |
61 | ); | |
62 | ||
63 | @extensions = ( | |
64 | [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_SERVER_NAME, | |
65 | checkhandshake::SERVER_NAME_CLI_EXTENSION], | |
66 | [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_STATUS_REQUEST, | |
67 | checkhandshake::STATUS_REQUEST_CLI_EXTENSION], | |
68 | [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_SUPPORTED_GROUPS, | |
69 | checkhandshake::DEFAULT_EXTENSIONS], | |
70 | [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_EC_POINT_FORMATS, | |
71 | checkhandshake::DEFAULT_EXTENSIONS], | |
72 | [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_SIG_ALGS, | |
73 | checkhandshake::DEFAULT_EXTENSIONS], | |
74 | [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_ALPN, | |
75 | checkhandshake::ALPN_CLI_EXTENSION], | |
76 | [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_SCT, | |
77 | checkhandshake::SCT_CLI_EXTENSION], | |
78 | [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_ENCRYPT_THEN_MAC, | |
79 | checkhandshake::DEFAULT_EXTENSIONS], | |
80 | [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_EXTENDED_MASTER_SECRET, | |
81 | checkhandshake::DEFAULT_EXTENSIONS], | |
82 | [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_SESSION_TICKET, | |
83 | checkhandshake::DEFAULT_EXTENSIONS], | |
84 | [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_KEY_SHARE, | |
85 | checkhandshake::DEFAULT_EXTENSIONS], | |
86 | [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_SUPPORTED_VERSIONS, | |
87 | checkhandshake::DEFAULT_EXTENSIONS], | |
88 | [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_PSK_KEX_MODES, | |
89 | checkhandshake::PSK_KEX_MODES_EXTENSION], | |
90 | [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_PSK, | |
91 | checkhandshake::PSK_CLI_EXTENSION], | |
92 | ||
426dfc9f MC |
93 | [TLSProxy::Message::MT_SERVER_HELLO, TLSProxy::Message::EXT_SUPPORTED_VERSIONS, |
94 | checkhandshake::DEFAULT_EXTENSIONS], | |
597c51bc | 95 | [TLSProxy::Message::MT_SERVER_HELLO, TLSProxy::Message::EXT_KEY_SHARE, |
d542790b MC |
96 | checkhandshake::KEY_SHARE_HRR_EXTENSION], |
97 | ||
98 | [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_SERVER_NAME, | |
99 | checkhandshake::SERVER_NAME_CLI_EXTENSION], | |
100 | [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_STATUS_REQUEST, | |
101 | checkhandshake::STATUS_REQUEST_CLI_EXTENSION], | |
102 | [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_SUPPORTED_GROUPS, | |
103 | checkhandshake::DEFAULT_EXTENSIONS], | |
a2b97bdf MC |
104 | [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_EC_POINT_FORMATS, |
105 | checkhandshake::DEFAULT_EXTENSIONS], | |
d542790b MC |
106 | [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_SIG_ALGS, |
107 | checkhandshake::DEFAULT_EXTENSIONS], | |
108 | [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_ALPN, | |
109 | checkhandshake::ALPN_CLI_EXTENSION], | |
110 | [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_SCT, | |
111 | checkhandshake::SCT_CLI_EXTENSION], | |
a2b97bdf MC |
112 | [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_ENCRYPT_THEN_MAC, |
113 | checkhandshake::DEFAULT_EXTENSIONS], | |
114 | [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_EXTENDED_MASTER_SECRET, | |
115 | checkhandshake::DEFAULT_EXTENSIONS], | |
116 | [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_SESSION_TICKET, | |
117 | checkhandshake::DEFAULT_EXTENSIONS], | |
d542790b MC |
118 | [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_KEY_SHARE, |
119 | checkhandshake::DEFAULT_EXTENSIONS], | |
120 | [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_SUPPORTED_VERSIONS, | |
121 | checkhandshake::DEFAULT_EXTENSIONS], | |
122 | [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_PSK_KEX_MODES, | |
123 | checkhandshake::PSK_KEX_MODES_EXTENSION], | |
124 | [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_PSK, | |
125 | checkhandshake::PSK_CLI_EXTENSION], | |
126 | ||
88050dd1 MC |
127 | [TLSProxy::Message::MT_SERVER_HELLO, TLSProxy::Message::EXT_SUPPORTED_VERSIONS, |
128 | checkhandshake::DEFAULT_EXTENSIONS], | |
3ae6b5f8 MC |
129 | [TLSProxy::Message::MT_SERVER_HELLO, TLSProxy::Message::EXT_KEY_SHARE, |
130 | checkhandshake::KEY_SHARE_SRV_EXTENSION], | |
131 | [TLSProxy::Message::MT_SERVER_HELLO, TLSProxy::Message::EXT_PSK, | |
132 | checkhandshake::PSK_SRV_EXTENSION], | |
133 | ||
134 | [TLSProxy::Message::MT_CERTIFICATE, TLSProxy::Message::EXT_STATUS_REQUEST, | |
135 | checkhandshake::STATUS_REQUEST_SRV_EXTENSION], | |
136 | [0,0,0] | |
137 | ); | |
138 | ||
139 | use constant { | |
140 | DELETE_EXTENSION => 0, | |
141 | EMPTY_EXTENSION => 1, | |
142 | NON_DHE_KEX_MODE_ONLY => 2, | |
143 | DHE_KEX_MODE_ONLY => 3, | |
46f4e1be | 144 | UNKNOWN_KEX_MODES => 4, |
3ae6b5f8 MC |
145 | BOTH_KEX_MODES => 5 |
146 | }; | |
147 | ||
148 | my $proxy = TLSProxy::Proxy->new( | |
149 | undef, | |
150 | cmdstr(app(["openssl"]), display => 1), | |
151 | srctop_file("apps", "server.pem"), | |
152 | (!$ENV{HARNESS_ACTIVE} || $ENV{HARNESS_VERBOSE}) | |
153 | ); | |
154 | ||
155 | #Test 1: First get a session | |
156 | (undef, my $session) = tempfile(); | |
157 | $proxy->clientflags("-sess_out ".$session); | |
db919b1e | 158 | $proxy->serverflags("-servername localhost"); |
3ae6b5f8 MC |
159 | $proxy->sessionfile($session); |
160 | $proxy->start() or plan skip_all => "Unable to start up Proxy for tests"; | |
d542790b | 161 | plan tests => 11; |
3ae6b5f8 MC |
162 | ok(TLSProxy::Message->success(), "Initial connection"); |
163 | ||
164 | #Test 2: Attempt a resume with no kex modes extension. Should not resume | |
165 | $proxy->clear(); | |
166 | $proxy->clientflags("-sess_in ".$session); | |
167 | my $testtype = DELETE_EXTENSION; | |
168 | $proxy->filter(\&modify_kex_modes_filter); | |
169 | $proxy->start(); | |
170 | checkhandshake($proxy, checkhandshake::DEFAULT_HANDSHAKE, | |
171 | checkhandshake::DEFAULT_EXTENSIONS | |
172 | | checkhandshake::KEY_SHARE_SRV_EXTENSION | |
173 | | checkhandshake::PSK_CLI_EXTENSION, | |
174 | "Resume with no kex modes"); | |
175 | ||
176 | #Test 3: Attempt a resume with empty kex modes extension. Should fail (empty | |
177 | # extension is invalid) | |
178 | $proxy->clear(); | |
179 | $proxy->clientflags("-sess_in ".$session); | |
180 | $testtype = EMPTY_EXTENSION; | |
181 | $proxy->start(); | |
182 | ok(TLSProxy::Message->fail(), "Resume with empty kex modes"); | |
183 | ||
184 | #Test 4: Attempt a resume with non-dhe kex mode only. Should resume without a | |
185 | # key_share | |
186 | $proxy->clear(); | |
e3c0d76b MC |
187 | $proxy->clientflags("-allow_no_dhe_kex -sess_in ".$session); |
188 | $proxy->serverflags("-allow_no_dhe_kex"); | |
3ae6b5f8 MC |
189 | $testtype = NON_DHE_KEX_MODE_ONLY; |
190 | $proxy->start(); | |
191 | checkhandshake($proxy, checkhandshake::RESUME_HANDSHAKE, | |
192 | checkhandshake::DEFAULT_EXTENSIONS | |
193 | | checkhandshake::PSK_KEX_MODES_EXTENSION | |
194 | | checkhandshake::PSK_CLI_EXTENSION | |
195 | | checkhandshake::PSK_SRV_EXTENSION, | |
196 | "Resume with non-dhe kex mode"); | |
197 | ||
198 | #Test 5: Attempt a resume with dhe kex mode only. Should resume with a key_share | |
199 | $proxy->clear(); | |
200 | $proxy->clientflags("-sess_in ".$session); | |
201 | $testtype = DHE_KEX_MODE_ONLY; | |
202 | $proxy->start(); | |
203 | checkhandshake($proxy, checkhandshake::RESUME_HANDSHAKE, | |
204 | checkhandshake::DEFAULT_EXTENSIONS | |
205 | | checkhandshake::PSK_KEX_MODES_EXTENSION | |
206 | | checkhandshake::KEY_SHARE_SRV_EXTENSION | |
207 | | checkhandshake::PSK_CLI_EXTENSION | |
208 | | checkhandshake::PSK_SRV_EXTENSION, | |
209 | "Resume with non-dhe kex mode"); | |
210 | ||
211 | #Test 6: Attempt a resume with only unrecognised kex modes. Should not resume | |
212 | $proxy->clear(); | |
213 | $proxy->clientflags("-sess_in ".$session); | |
46f4e1be | 214 | $testtype = UNKNOWN_KEX_MODES; |
3ae6b5f8 MC |
215 | $proxy->start(); |
216 | checkhandshake($proxy, checkhandshake::DEFAULT_HANDSHAKE, | |
217 | checkhandshake::DEFAULT_EXTENSIONS | |
218 | | checkhandshake::PSK_KEX_MODES_EXTENSION | |
219 | | checkhandshake::KEY_SHARE_SRV_EXTENSION | |
220 | | checkhandshake::PSK_CLI_EXTENSION, | |
221 | "Resume with empty kex modes"); | |
222 | ||
223 | #Test 7: Attempt a resume with both non-dhe and dhe kex mode. Should resume with | |
224 | # a key_share | |
225 | $proxy->clear(); | |
226 | $proxy->clientflags("-sess_in ".$session); | |
227 | $testtype = BOTH_KEX_MODES; | |
228 | $proxy->start(); | |
229 | checkhandshake($proxy, checkhandshake::RESUME_HANDSHAKE, | |
230 | checkhandshake::DEFAULT_EXTENSIONS | |
231 | | checkhandshake::PSK_KEX_MODES_EXTENSION | |
232 | | checkhandshake::KEY_SHARE_SRV_EXTENSION | |
233 | | checkhandshake::PSK_CLI_EXTENSION | |
234 | | checkhandshake::PSK_SRV_EXTENSION, | |
235 | "Resume with non-dhe kex mode"); | |
236 | ||
d542790b MC |
237 | #Test 8: Attempt a resume with both non-dhe and dhe kex mode, but unacceptable |
238 | # initial key_share. Should resume with a key_share following an HRR | |
239 | $proxy->clear(); | |
240 | $proxy->clientflags("-sess_in ".$session); | |
241 | $proxy->serverflags("-curves P-256"); | |
242 | $testtype = BOTH_KEX_MODES; | |
243 | $proxy->start(); | |
244 | checkhandshake($proxy, checkhandshake::HRR_RESUME_HANDSHAKE, | |
245 | checkhandshake::DEFAULT_EXTENSIONS | |
246 | | checkhandshake::PSK_KEX_MODES_EXTENSION | |
247 | | checkhandshake::KEY_SHARE_SRV_EXTENSION | |
248 | | checkhandshake::KEY_SHARE_HRR_EXTENSION | |
249 | | checkhandshake::PSK_CLI_EXTENSION | |
250 | | checkhandshake::PSK_SRV_EXTENSION, | |
251 | "Resume with both kex modes and HRR"); | |
252 | ||
46f4e1be | 253 | #Test 9: Attempt a resume with dhe kex mode only and an unacceptable initial |
d542790b MC |
254 | # key_share. Should resume with a key_share following an HRR |
255 | $proxy->clear(); | |
256 | $proxy->clientflags("-sess_in ".$session); | |
257 | $proxy->serverflags("-curves P-256"); | |
258 | $testtype = DHE_KEX_MODE_ONLY; | |
259 | $proxy->start(); | |
260 | checkhandshake($proxy, checkhandshake::HRR_RESUME_HANDSHAKE, | |
261 | checkhandshake::DEFAULT_EXTENSIONS | |
262 | | checkhandshake::PSK_KEX_MODES_EXTENSION | |
263 | | checkhandshake::KEY_SHARE_SRV_EXTENSION | |
264 | | checkhandshake::KEY_SHARE_HRR_EXTENSION | |
265 | | checkhandshake::PSK_CLI_EXTENSION | |
266 | | checkhandshake::PSK_SRV_EXTENSION, | |
267 | "Resume with dhe kex mode and HRR"); | |
268 | ||
269 | #Test 10: Attempt a resume with both non-dhe and dhe kex mode, unacceptable | |
270 | # initial key_share and no overlapping groups. Should resume without a | |
271 | # key_share | |
272 | $proxy->clear(); | |
e3c0d76b MC |
273 | $proxy->clientflags("-allow_no_dhe_kex -curves P-384 -sess_in ".$session); |
274 | $proxy->serverflags("-allow_no_dhe_kex -curves P-256"); | |
d542790b MC |
275 | $testtype = BOTH_KEX_MODES; |
276 | $proxy->start(); | |
277 | checkhandshake($proxy, checkhandshake::RESUME_HANDSHAKE, | |
278 | checkhandshake::DEFAULT_EXTENSIONS | |
279 | | checkhandshake::PSK_KEX_MODES_EXTENSION | |
280 | | checkhandshake::PSK_CLI_EXTENSION | |
281 | | checkhandshake::PSK_SRV_EXTENSION, | |
282 | "Resume with both kex modes, no overlapping groups"); | |
283 | ||
284 | #Test 11: Attempt a resume with dhe kex mode only, unacceptable | |
285 | # initial key_share and no overlapping groups. Should fail | |
286 | $proxy->clear(); | |
287 | $proxy->clientflags("-curves P-384 -sess_in ".$session); | |
288 | $proxy->serverflags("-curves P-256"); | |
289 | $testtype = DHE_KEX_MODE_ONLY; | |
290 | $proxy->start(); | |
291 | ok(TLSProxy::Message->fail(), "Resume with dhe kex mode, no overlapping groups"); | |
292 | ||
3ae6b5f8 MC |
293 | unlink $session; |
294 | ||
295 | sub modify_kex_modes_filter | |
296 | { | |
297 | my $proxy = shift; | |
298 | ||
299 | # We're only interested in the initial ClientHello | |
300 | return if ($proxy->flight != 0); | |
301 | ||
302 | foreach my $message (@{$proxy->message_list}) { | |
303 | if ($message->mt == TLSProxy::Message::MT_CLIENT_HELLO) { | |
304 | my $ext; | |
305 | ||
306 | if ($testtype == EMPTY_EXTENSION) { | |
307 | $ext = pack "C", | |
308 | 0x00; #List length | |
309 | } elsif ($testtype == NON_DHE_KEX_MODE_ONLY) { | |
310 | $ext = pack "C2", | |
311 | 0x01, #List length | |
312 | 0x00; #psk_ke | |
313 | } elsif ($testtype == DHE_KEX_MODE_ONLY) { | |
314 | $ext = pack "C2", | |
315 | 0x01, #List length | |
316 | 0x01; #psk_dhe_ke | |
46f4e1be | 317 | } elsif ($testtype == UNKNOWN_KEX_MODES) { |
3ae6b5f8 MC |
318 | $ext = pack "C3", |
319 | 0x02, #List length | |
320 | 0xfe, #unknown | |
321 | 0xff; #unknown | |
322 | } elsif ($testtype == BOTH_KEX_MODES) { | |
323 | #We deliberately list psk_ke first...should still use psk_dhe_ke | |
324 | $ext = pack "C3", | |
325 | 0x02, #List length | |
326 | 0x00, #psk_ke | |
327 | 0x01; #psk_dhe_ke | |
328 | } | |
329 | ||
330 | if ($testtype == DELETE_EXTENSION) { | |
331 | $message->delete_extension( | |
332 | TLSProxy::Message::EXT_PSK_KEX_MODES); | |
333 | } else { | |
334 | $message->set_extension( | |
335 | TLSProxy::Message::EXT_PSK_KEX_MODES, $ext); | |
336 | } | |
337 | ||
338 | $message->repack(); | |
339 | } | |
340 | } | |
341 | } |