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