1#! /usr/bin/env perl
2# Copyright 2015-2024 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
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_tls13messages";
17setup($test_name);
18
19plan skip_all => "TLSProxy isn't usable on $^O"
20    if $^O =~ /^(VMS)$/;
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"
29    if disabled("tls1_3");
30
31plan skip_all => "$test_name needs EC enabled"
32    if disabled("ec");
33
34@handmessages = (
35    [TLSProxy::Message::MT_CLIENT_HELLO,
36        checkhandshake::ALL_HANDSHAKES],
37    [TLSProxy::Message::MT_SERVER_HELLO,
38        checkhandshake::HRR_HANDSHAKE | checkhandshake::HRR_RESUME_HANDSHAKE],
39    [TLSProxy::Message::MT_CLIENT_HELLO,
40        checkhandshake::HRR_HANDSHAKE | checkhandshake::HRR_RESUME_HANDSHAKE],
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,
48        checkhandshake::ALL_HANDSHAKES & ~(checkhandshake::RESUME_HANDSHAKE | checkhandshake::HRR_RESUME_HANDSHAKE)],
49    [TLSProxy::Message::MT_CERTIFICATE_VERIFY,
50        checkhandshake::ALL_HANDSHAKES & ~(checkhandshake::RESUME_HANDSHAKE | checkhandshake::HRR_RESUME_HANDSHAKE)],
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,
64        TLSProxy::Message::CLIENT,
65        checkhandshake::SERVER_NAME_CLI_EXTENSION],
66    [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_STATUS_REQUEST,
67        TLSProxy::Message::CLIENT,
68        checkhandshake::STATUS_REQUEST_CLI_EXTENSION],
69    [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_SUPPORTED_GROUPS,
70        TLSProxy::Message::CLIENT,
71        checkhandshake::DEFAULT_EXTENSIONS],
72    [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_EC_POINT_FORMATS,
73        TLSProxy::Message::CLIENT,
74        checkhandshake::DEFAULT_EXTENSIONS],
75    [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_SIG_ALGS,
76        TLSProxy::Message::CLIENT,
77        checkhandshake::DEFAULT_EXTENSIONS],
78    [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_ALPN,
79        TLSProxy::Message::CLIENT,
80        checkhandshake::ALPN_CLI_EXTENSION],
81    [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_SCT,
82        TLSProxy::Message::CLIENT,
83        checkhandshake::SCT_CLI_EXTENSION],
84    [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_ENCRYPT_THEN_MAC,
85        TLSProxy::Message::CLIENT,
86        checkhandshake::DEFAULT_EXTENSIONS],
87    [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_EXTENDED_MASTER_SECRET,
88        TLSProxy::Message::CLIENT,
89        checkhandshake::DEFAULT_EXTENSIONS],
90    [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_SESSION_TICKET,
91        TLSProxy::Message::CLIENT,
92        checkhandshake::DEFAULT_EXTENSIONS],
93    [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_KEY_SHARE,
94        TLSProxy::Message::CLIENT,
95        checkhandshake::DEFAULT_EXTENSIONS],
96    [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_SUPPORTED_VERSIONS,
97        TLSProxy::Message::CLIENT,
98        checkhandshake::DEFAULT_EXTENSIONS],
99    [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_PSK_KEX_MODES,
100        TLSProxy::Message::CLIENT,
101        checkhandshake::DEFAULT_EXTENSIONS],
102    [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_PSK,
103        TLSProxy::Message::CLIENT,
104        checkhandshake::PSK_CLI_EXTENSION],
105    [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_POST_HANDSHAKE_AUTH,
106        TLSProxy::Message::CLIENT,
107        checkhandshake::POST_HANDSHAKE_AUTH_CLI_EXTENSION],
108    [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_RENEGOTIATE,
109        TLSProxy::Message::CLIENT,
110        checkhandshake::DEFAULT_EXTENSIONS],
111
112    [TLSProxy::Message::MT_SERVER_HELLO, TLSProxy::Message::EXT_SUPPORTED_VERSIONS,
113        TLSProxy::Message::SERVER,
114        checkhandshake::DEFAULT_EXTENSIONS],
115    [TLSProxy::Message::MT_SERVER_HELLO, TLSProxy::Message::EXT_KEY_SHARE,
116        TLSProxy::Message::SERVER,
117        checkhandshake::KEY_SHARE_HRR_EXTENSION],
118
119    [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_SERVER_NAME,
120        TLSProxy::Message::CLIENT,
121        checkhandshake::SERVER_NAME_CLI_EXTENSION],
122    [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_STATUS_REQUEST,
123        TLSProxy::Message::CLIENT,
124        checkhandshake::STATUS_REQUEST_CLI_EXTENSION],
125    [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_SUPPORTED_GROUPS,
126        TLSProxy::Message::CLIENT,
127        checkhandshake::DEFAULT_EXTENSIONS],
128    [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_EC_POINT_FORMATS,
129        TLSProxy::Message::CLIENT,
130        checkhandshake::DEFAULT_EXTENSIONS],
131    [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_SIG_ALGS,
132        TLSProxy::Message::CLIENT,
133        checkhandshake::DEFAULT_EXTENSIONS],
134    [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_ALPN,
135        TLSProxy::Message::CLIENT,
136        checkhandshake::ALPN_CLI_EXTENSION],
137    [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_SCT,
138        TLSProxy::Message::CLIENT,
139        checkhandshake::SCT_CLI_EXTENSION],
140    [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_ENCRYPT_THEN_MAC,
141        TLSProxy::Message::CLIENT,
142        checkhandshake::DEFAULT_EXTENSIONS],
143    [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_EXTENDED_MASTER_SECRET,
144        TLSProxy::Message::CLIENT,
145        checkhandshake::DEFAULT_EXTENSIONS],
146    [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_SESSION_TICKET,
147        TLSProxy::Message::CLIENT,
148        checkhandshake::DEFAULT_EXTENSIONS],
149    [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_KEY_SHARE,
150        TLSProxy::Message::CLIENT,
151        checkhandshake::DEFAULT_EXTENSIONS],
152    [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_SUPPORTED_VERSIONS,
153        TLSProxy::Message::CLIENT,
154        checkhandshake::DEFAULT_EXTENSIONS],
155    [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_PSK_KEX_MODES,
156        TLSProxy::Message::CLIENT,
157        checkhandshake::DEFAULT_EXTENSIONS],
158    [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_PSK,
159        TLSProxy::Message::CLIENT,
160        checkhandshake::PSK_CLI_EXTENSION],
161    [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_POST_HANDSHAKE_AUTH,
162        TLSProxy::Message::CLIENT,
163        checkhandshake::POST_HANDSHAKE_AUTH_CLI_EXTENSION],
164    [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_RENEGOTIATE,
165        TLSProxy::Message::CLIENT,
166        checkhandshake::DEFAULT_EXTENSIONS],
167
168    [TLSProxy::Message::MT_SERVER_HELLO, TLSProxy::Message::EXT_SUPPORTED_VERSIONS,
169        TLSProxy::Message::SERVER,
170        checkhandshake::DEFAULT_EXTENSIONS],
171    [TLSProxy::Message::MT_SERVER_HELLO, TLSProxy::Message::EXT_KEY_SHARE,
172        TLSProxy::Message::SERVER,
173        checkhandshake::DEFAULT_EXTENSIONS],
174    [TLSProxy::Message::MT_SERVER_HELLO, TLSProxy::Message::EXT_PSK,
175        TLSProxy::Message::SERVER,
176        checkhandshake::PSK_SRV_EXTENSION],
177
178    [TLSProxy::Message::MT_ENCRYPTED_EXTENSIONS, TLSProxy::Message::EXT_SERVER_NAME,
179        TLSProxy::Message::SERVER,
180        checkhandshake::SERVER_NAME_SRV_EXTENSION],
181    [TLSProxy::Message::MT_ENCRYPTED_EXTENSIONS, TLSProxy::Message::EXT_ALPN,
182        TLSProxy::Message::SERVER,
183        checkhandshake::ALPN_SRV_EXTENSION],
184    [TLSProxy::Message::MT_ENCRYPTED_EXTENSIONS, TLSProxy::Message::EXT_SUPPORTED_GROUPS,
185        TLSProxy::Message::SERVER,
186        checkhandshake::SUPPORTED_GROUPS_SRV_EXTENSION],
187
188    [TLSProxy::Message::MT_CERTIFICATE_REQUEST, TLSProxy::Message::EXT_SIG_ALGS,
189        TLSProxy::Message::SERVER,
190        checkhandshake::DEFAULT_EXTENSIONS],
191
192    [TLSProxy::Message::MT_CERTIFICATE, TLSProxy::Message::EXT_STATUS_REQUEST,
193        TLSProxy::Message::SERVER,
194        checkhandshake::STATUS_REQUEST_SRV_EXTENSION],
195    [TLSProxy::Message::MT_CERTIFICATE, TLSProxy::Message::EXT_SCT,
196        TLSProxy::Message::SERVER,
197        checkhandshake::SCT_SRV_EXTENSION],
198
199    [0,0,0,0]
200);
201
202my $proxy = TLSProxy::Proxy->new(
203    undef,
204    cmdstr(app(["openssl"]), display => 1),
205    srctop_file("apps", "server.pem"),
206    (!$ENV{HARNESS_ACTIVE} || $ENV{HARNESS_VERBOSE})
207);
208
209#Test 1: Check we get all the right messages for a default handshake
210(undef, my $session) = tempfile();
211$proxy->serverconnects(2);
212$proxy->clientflags("-no_rx_cert_comp -sess_out ".$session);
213$proxy->sessionfile($session);
214$proxy->start() or plan skip_all => "Unable to start up Proxy for tests";
215plan tests => 17;
216checkhandshake($proxy, checkhandshake::DEFAULT_HANDSHAKE,
217               checkhandshake::DEFAULT_EXTENSIONS,
218               "Default handshake test");
219
220#Test 2: Resumption handshake
221$proxy->clearClient();
222$proxy->clientflags("-no_rx_cert_comp -sess_in ".$session);
223$proxy->clientstart();
224checkhandshake($proxy, checkhandshake::RESUME_HANDSHAKE,
225               (checkhandshake::DEFAULT_EXTENSIONS
226                | checkhandshake::PSK_CLI_EXTENSION
227                | checkhandshake::PSK_SRV_EXTENSION),
228               "Resumption handshake test");
229
230SKIP: {
231    skip "No OCSP support in this OpenSSL build", 4
232        if disabled("ct") || disabled("ec") || disabled("ocsp");
233    #Test 3: A status_request handshake (client request only)
234    $proxy->clear();
235    $proxy->clientflags("-no_rx_cert_comp -status");
236    $proxy->start();
237    checkhandshake($proxy, checkhandshake::DEFAULT_HANDSHAKE,
238                   checkhandshake::DEFAULT_EXTENSIONS
239                   | checkhandshake::STATUS_REQUEST_CLI_EXTENSION,
240                   "status_request handshake test (client)");
241
242    #Test 4: A status_request handshake (server support only)
243    $proxy->clear();
244    $proxy->clientflags("-no_rx_cert_comp");
245    $proxy->serverflags("-no_rx_cert_comp -status_file "
246                        .srctop_file("test", "recipes", "ocsp-response.der"));
247    $proxy->start();
248    checkhandshake($proxy, checkhandshake::DEFAULT_HANDSHAKE,
249                   checkhandshake::DEFAULT_EXTENSIONS,
250                   "status_request handshake test (server)");
251
252    #Test 5: A status_request handshake (client and server)
253    $proxy->clear();
254    $proxy->clientflags("-no_rx_cert_comp -status");
255    $proxy->serverflags("-no_rx_cert_comp -status_file "
256                        .srctop_file("test", "recipes", "ocsp-response.der"));
257    $proxy->start();
258    checkhandshake($proxy, checkhandshake::DEFAULT_HANDSHAKE,
259                   checkhandshake::DEFAULT_EXTENSIONS
260                   | checkhandshake::STATUS_REQUEST_CLI_EXTENSION
261                   | checkhandshake::STATUS_REQUEST_SRV_EXTENSION,
262                   "status_request handshake test");
263
264    #Test 6: A status_request handshake (client and server) with client auth
265    $proxy->clear();
266    $proxy->clientflags("-no_rx_cert_comp -status -enable_pha -cert "
267                        .srctop_file("apps", "server.pem"));
268    $proxy->serverflags("-no_rx_cert_comp -Verify 5 -status_file "
269                        .srctop_file("test", "recipes", "ocsp-response.der"));
270    $proxy->start();
271    checkhandshake($proxy, checkhandshake::CLIENT_AUTH_HANDSHAKE,
272                   checkhandshake::DEFAULT_EXTENSIONS
273                   | checkhandshake::STATUS_REQUEST_CLI_EXTENSION
274                   | checkhandshake::STATUS_REQUEST_SRV_EXTENSION
275                   | checkhandshake::POST_HANDSHAKE_AUTH_CLI_EXTENSION,
276                   "status_request handshake with client auth test");
277}
278
279#Test 7: A client auth handshake
280$proxy->clear();
281$proxy->clientflags("-no_rx_cert_comp -enable_pha -cert ".srctop_file("apps", "server.pem"));
282$proxy->serverflags("-no_rx_cert_comp -Verify 5");
283$proxy->start();
284checkhandshake($proxy, checkhandshake::CLIENT_AUTH_HANDSHAKE,
285               checkhandshake::DEFAULT_EXTENSIONS |
286               checkhandshake::POST_HANDSHAKE_AUTH_CLI_EXTENSION,
287               "Client auth handshake test");
288
289#Test 8: Server name handshake (no client request)
290$proxy->clear();
291$proxy->clientflags("-no_rx_cert_comp -noservername");
292$proxy->start();
293checkhandshake($proxy, checkhandshake::DEFAULT_HANDSHAKE,
294               checkhandshake::DEFAULT_EXTENSIONS
295               & ~checkhandshake::SERVER_NAME_CLI_EXTENSION,
296               "Server name handshake test (client)");
297
298#Test 9: Server name handshake (server support only)
299$proxy->clear();
300$proxy->clientflags("-no_rx_cert_comp -noservername");
301$proxy->serverflags("-no_rx_cert_comp -servername testhost");
302$proxy->start();
303checkhandshake($proxy, checkhandshake::DEFAULT_HANDSHAKE,
304               checkhandshake::DEFAULT_EXTENSIONS
305               & ~checkhandshake::SERVER_NAME_CLI_EXTENSION,
306               "Server name handshake test (server)");
307
308#Test 10: Server name handshake (client and server)
309$proxy->clear();
310$proxy->clientflags("-no_rx_cert_comp -servername testhost");
311$proxy->serverflags("-no_rx_cert_comp -servername testhost");
312$proxy->start();
313checkhandshake($proxy, checkhandshake::DEFAULT_HANDSHAKE,
314               checkhandshake::DEFAULT_EXTENSIONS
315               | checkhandshake::SERVER_NAME_SRV_EXTENSION,
316               "Server name handshake test");
317
318#Test 11: ALPN handshake (client request only)
319$proxy->clear();
320$proxy->clientflags("-no_rx_cert_comp -alpn test");
321$proxy->start();
322checkhandshake($proxy, checkhandshake::DEFAULT_HANDSHAKE,
323               checkhandshake::DEFAULT_EXTENSIONS
324               | checkhandshake::ALPN_CLI_EXTENSION,
325               "ALPN handshake test (client)");
326
327#Test 12: ALPN handshake (server support only)
328$proxy->clear();
329$proxy->clientflags("-no_rx_cert_comp");
330$proxy->serverflags("-no_rx_cert_comp -alpn test");
331$proxy->start();
332checkhandshake($proxy, checkhandshake::DEFAULT_HANDSHAKE,
333               checkhandshake::DEFAULT_EXTENSIONS,
334               "ALPN handshake test (server)");
335
336#Test 13: ALPN handshake (client and server)
337$proxy->clear();
338$proxy->clientflags("-no_rx_cert_comp -alpn test");
339$proxy->serverflags("-no_rx_cert_comp -alpn test");
340$proxy->start();
341checkhandshake($proxy, checkhandshake::DEFAULT_HANDSHAKE,
342               checkhandshake::DEFAULT_EXTENSIONS
343               | checkhandshake::ALPN_CLI_EXTENSION
344               | checkhandshake::ALPN_SRV_EXTENSION,
345               "ALPN handshake test");
346
347SKIP: {
348    skip "No CT, EC or OCSP support in this OpenSSL build", 1
349        if disabled("ct") || disabled("ec") || disabled("ocsp");
350
351    #Test 14: SCT handshake (client request only)
352    $proxy->clear();
353    #Note: -ct also sends status_request
354    $proxy->clientflags("-no_rx_cert_comp -ct");
355    $proxy->serverflags("-no_rx_cert_comp -status_file "
356                        .srctop_file("test", "recipes", "ocsp-response.der")
357                        ." -serverinfo ".srctop_file("test", "serverinfo2.pem"));
358    $proxy->start();
359    checkhandshake($proxy, checkhandshake::DEFAULT_HANDSHAKE,
360                   checkhandshake::DEFAULT_EXTENSIONS
361                   | checkhandshake::SCT_CLI_EXTENSION
362                   | checkhandshake::SCT_SRV_EXTENSION
363                   | checkhandshake::STATUS_REQUEST_CLI_EXTENSION
364                   | checkhandshake::STATUS_REQUEST_SRV_EXTENSION,
365                   "SCT handshake test");
366}
367
368#Test 15: HRR Handshake
369$proxy->clear();
370$proxy->clientflags("-no_rx_cert_comp");
371$proxy->serverflags("-no_rx_cert_comp -curves P-384");
372$proxy->start();
373checkhandshake($proxy, checkhandshake::HRR_HANDSHAKE,
374               checkhandshake::DEFAULT_EXTENSIONS
375               | checkhandshake::KEY_SHARE_HRR_EXTENSION,
376               "HRR handshake test");
377
378#Test 16: Resumption handshake with HRR
379$proxy->clear();
380$proxy->clientflags("-no_rx_cert_comp -sess_in ".$session);
381$proxy->serverflags("-no_rx_cert_comp -curves P-384");
382$proxy->start();
383checkhandshake($proxy, checkhandshake::HRR_RESUME_HANDSHAKE,
384               (checkhandshake::DEFAULT_EXTENSIONS
385                | checkhandshake::KEY_SHARE_HRR_EXTENSION
386                | checkhandshake::PSK_CLI_EXTENSION
387                | checkhandshake::PSK_SRV_EXTENSION),
388               "Resumption handshake with HRR test");
389
390#Test 17: Acceptable but non preferred key_share
391$proxy->clear();
392$proxy->clientflags("-no_rx_cert_comp -curves P-384");
393$proxy->start();
394checkhandshake($proxy, checkhandshake::DEFAULT_HANDSHAKE,
395               checkhandshake::DEFAULT_EXTENSIONS
396               | checkhandshake::SUPPORTED_GROUPS_SRV_EXTENSION,
397               "Acceptable but non preferred key_share");
398
399unlink $session;
400