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_sslmessages";
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 TLS enabled"
29    if alldisabled(available_protocols("tls"))
30       || (!disabled("tls1_3") && disabled("tls1_2"));
31
32my $proxy = TLSProxy::Proxy->new(
33    undef,
34    cmdstr(app(["openssl"]), display => 1),
35    srctop_file("apps", "server.pem"),
36    (!$ENV{HARNESS_ACTIVE} || $ENV{HARNESS_VERBOSE})
37);
38
39@handmessages = (
40    [TLSProxy::Message::MT_CLIENT_HELLO,
41        checkhandshake::ALL_HANDSHAKES],
42    [TLSProxy::Message::MT_SERVER_HELLO,
43        checkhandshake::ALL_HANDSHAKES],
44    [TLSProxy::Message::MT_CERTIFICATE,
45        checkhandshake::ALL_HANDSHAKES
46        & ~checkhandshake::RESUME_HANDSHAKE],
47    (disabled("ec") ? () :
48                      [TLSProxy::Message::MT_SERVER_KEY_EXCHANGE,
49                          checkhandshake::EC_HANDSHAKE]),
50    [TLSProxy::Message::MT_CERTIFICATE_STATUS,
51        checkhandshake::OCSP_HANDSHAKE],
52    #ServerKeyExchange handshakes not currently supported by TLSProxy
53    [TLSProxy::Message::MT_CERTIFICATE_REQUEST,
54        checkhandshake::CLIENT_AUTH_HANDSHAKE],
55    [TLSProxy::Message::MT_SERVER_HELLO_DONE,
56        checkhandshake::ALL_HANDSHAKES
57        & ~checkhandshake::RESUME_HANDSHAKE],
58    [TLSProxy::Message::MT_CERTIFICATE,
59        checkhandshake::CLIENT_AUTH_HANDSHAKE],
60    [TLSProxy::Message::MT_CLIENT_KEY_EXCHANGE,
61        checkhandshake::ALL_HANDSHAKES
62        & ~checkhandshake::RESUME_HANDSHAKE],
63    [TLSProxy::Message::MT_CERTIFICATE_VERIFY,
64        checkhandshake::CLIENT_AUTH_HANDSHAKE],
65    [TLSProxy::Message::MT_NEXT_PROTO,
66        checkhandshake::NPN_HANDSHAKE],
67    [TLSProxy::Message::MT_FINISHED,
68        checkhandshake::ALL_HANDSHAKES],
69    [TLSProxy::Message::MT_NEW_SESSION_TICKET,
70        checkhandshake::ALL_HANDSHAKES
71        & ~checkhandshake::RESUME_HANDSHAKE],
72    [TLSProxy::Message::MT_FINISHED,
73        checkhandshake::ALL_HANDSHAKES],
74    [TLSProxy::Message::MT_CLIENT_HELLO,
75        checkhandshake::RENEG_HANDSHAKE],
76    [TLSProxy::Message::MT_SERVER_HELLO,
77        checkhandshake::RENEG_HANDSHAKE],
78    [TLSProxy::Message::MT_CERTIFICATE,
79        checkhandshake::RENEG_HANDSHAKE],
80    [TLSProxy::Message::MT_SERVER_HELLO_DONE,
81        checkhandshake::RENEG_HANDSHAKE],
82    [TLSProxy::Message::MT_CLIENT_KEY_EXCHANGE,
83        checkhandshake::RENEG_HANDSHAKE],
84    [TLSProxy::Message::MT_FINISHED,
85        checkhandshake::RENEG_HANDSHAKE],
86    [TLSProxy::Message::MT_NEW_SESSION_TICKET,
87        checkhandshake::RENEG_HANDSHAKE],
88    [TLSProxy::Message::MT_FINISHED,
89        checkhandshake::RENEG_HANDSHAKE],
90    [0, 0]
91);
92
93@extensions = (
94    [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_SERVER_NAME,
95        TLSProxy::Message::CLIENT,
96        checkhandshake::SERVER_NAME_CLI_EXTENSION],
97    [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_STATUS_REQUEST,
98        TLSProxy::Message::CLIENT,
99        checkhandshake::STATUS_REQUEST_CLI_EXTENSION],
100    (disabled("ec") ? () :
101                      [TLSProxy::Message::MT_CLIENT_HELLO,
102                       TLSProxy::Message::EXT_SUPPORTED_GROUPS,
103                       TLSProxy::Message::CLIENT,
104                       checkhandshake::DEFAULT_EXTENSIONS]),
105    (disabled("ec") ? () :
106                      [TLSProxy::Message::MT_CLIENT_HELLO,
107                       TLSProxy::Message::EXT_EC_POINT_FORMATS,
108                       TLSProxy::Message::CLIENT,
109                       checkhandshake::DEFAULT_EXTENSIONS]),
110    (disabled("tls1_2") ? () :
111     [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_SIG_ALGS,
112        TLSProxy::Message::CLIENT,
113         checkhandshake::DEFAULT_EXTENSIONS]),
114    [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_ALPN,
115        TLSProxy::Message::CLIENT,
116        checkhandshake::ALPN_CLI_EXTENSION],
117    [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_SCT,
118        TLSProxy::Message::CLIENT,
119        checkhandshake::SCT_CLI_EXTENSION],
120    [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_ENCRYPT_THEN_MAC,
121        TLSProxy::Message::CLIENT,
122        checkhandshake::DEFAULT_EXTENSIONS],
123    [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_EXTENDED_MASTER_SECRET,
124        TLSProxy::Message::CLIENT,
125        checkhandshake::DEFAULT_EXTENSIONS],
126    [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_SESSION_TICKET,
127        TLSProxy::Message::CLIENT,
128        checkhandshake::DEFAULT_EXTENSIONS],
129    [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_RENEGOTIATE,
130        TLSProxy::Message::CLIENT,
131        checkhandshake::DEFAULT_EXTENSIONS],
132    [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_NPN,
133        TLSProxy::Message::CLIENT,
134        checkhandshake::NPN_CLI_EXTENSION],
135    [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_SRP,
136        TLSProxy::Message::CLIENT,
137        checkhandshake::SRP_CLI_EXTENSION],
138
139    [TLSProxy::Message::MT_SERVER_HELLO, TLSProxy::Message::EXT_RENEGOTIATE,
140        TLSProxy::Message::SERVER,
141        checkhandshake::DEFAULT_EXTENSIONS],
142    [TLSProxy::Message::MT_SERVER_HELLO, TLSProxy::Message::EXT_ENCRYPT_THEN_MAC,
143        TLSProxy::Message::SERVER,
144        checkhandshake::DEFAULT_EXTENSIONS],
145    [TLSProxy::Message::MT_SERVER_HELLO, TLSProxy::Message::EXT_EXTENDED_MASTER_SECRET,
146        TLSProxy::Message::SERVER,
147        checkhandshake::DEFAULT_EXTENSIONS],
148    [TLSProxy::Message::MT_SERVER_HELLO, TLSProxy::Message::EXT_SESSION_TICKET,
149        TLSProxy::Message::SERVER,
150        checkhandshake::SESSION_TICKET_SRV_EXTENSION],
151    [TLSProxy::Message::MT_SERVER_HELLO, TLSProxy::Message::EXT_SERVER_NAME,
152        TLSProxy::Message::SERVER,
153        checkhandshake::SERVER_NAME_SRV_EXTENSION],
154    [TLSProxy::Message::MT_SERVER_HELLO, TLSProxy::Message::EXT_STATUS_REQUEST,
155        TLSProxy::Message::SERVER,
156        checkhandshake::STATUS_REQUEST_SRV_EXTENSION],
157    [TLSProxy::Message::MT_SERVER_HELLO, TLSProxy::Message::EXT_ALPN,
158        TLSProxy::Message::SERVER,
159        checkhandshake::ALPN_SRV_EXTENSION],
160    [TLSProxy::Message::MT_SERVER_HELLO, TLSProxy::Message::EXT_SCT,
161        TLSProxy::Message::SERVER,
162        checkhandshake::SCT_SRV_EXTENSION],
163    [TLSProxy::Message::MT_SERVER_HELLO, TLSProxy::Message::EXT_NPN,
164        TLSProxy::Message::SERVER,
165        checkhandshake::NPN_SRV_EXTENSION],
166    [TLSProxy::Message::MT_SERVER_HELLO, TLSProxy::Message::EXT_EC_POINT_FORMATS,
167        TLSProxy::Message::SERVER,
168        checkhandshake::EC_POINT_FORMAT_SRV_EXTENSION],
169    [0,0,0,0]
170);
171
172#Test 1: Check we get all the right messages for a default handshake
173(undef, my $session) = tempfile();
174$proxy->serverconnects(2);
175$proxy->clientflags("-no_tls1_3 -sess_out ".$session);
176$proxy->start() or plan skip_all => "Unable to start up Proxy for tests";
177plan tests => 21;
178checkhandshake($proxy, checkhandshake::DEFAULT_HANDSHAKE,
179               checkhandshake::DEFAULT_EXTENSIONS,
180               "Default handshake test");
181
182#Test 2: Resumption handshake
183$proxy->clearClient();
184$proxy->clientflags("-no_tls1_3 -sess_in ".$session);
185$proxy->clientstart();
186checkhandshake($proxy, checkhandshake::RESUME_HANDSHAKE,
187               checkhandshake::DEFAULT_EXTENSIONS
188               & ~checkhandshake::SESSION_TICKET_SRV_EXTENSION,
189               "Resumption handshake test");
190unlink $session;
191
192SKIP: {
193    skip "No OCSP support in this OpenSSL build", 3
194        if disabled("ocsp");
195
196    #Test 3: A status_request handshake (client request only)
197    $proxy->clear();
198    $proxy->clientflags("-no_tls1_3 -status");
199    $proxy->start();
200    checkhandshake($proxy, checkhandshake::DEFAULT_HANDSHAKE,
201                   checkhandshake::DEFAULT_EXTENSIONS
202                   | checkhandshake::STATUS_REQUEST_CLI_EXTENSION,
203                   "status_request handshake test (client)");
204
205    #Test 4: A status_request handshake (server support only)
206    $proxy->clear();
207    $proxy->clientflags("-no_tls1_3");
208    $proxy->serverflags("-status_file "
209                        .srctop_file("test", "recipes", "ocsp-response.der"));
210    $proxy->start();
211    checkhandshake($proxy, checkhandshake::DEFAULT_HANDSHAKE,
212                   checkhandshake::DEFAULT_EXTENSIONS,
213                   "status_request handshake test (server)");
214
215    #Test 5: A status_request handshake (client and server)
216    $proxy->clear();
217    $proxy->clientflags("-no_tls1_3 -status");
218    $proxy->serverflags("-status_file "
219                        .srctop_file("test", "recipes", "ocsp-response.der"));
220    $proxy->start();
221    checkhandshake($proxy, checkhandshake::OCSP_HANDSHAKE,
222                   checkhandshake::DEFAULT_EXTENSIONS
223                   | checkhandshake::STATUS_REQUEST_CLI_EXTENSION
224                   | checkhandshake::STATUS_REQUEST_SRV_EXTENSION,
225                   "status_request handshake test");
226}
227
228#Test 6: A client auth handshake
229$proxy->clear();
230$proxy->clientflags("-no_tls1_3 -cert ".srctop_file("apps", "server.pem"));
231$proxy->serverflags("-Verify 5");
232$proxy->start();
233checkhandshake($proxy, checkhandshake::CLIENT_AUTH_HANDSHAKE,
234               checkhandshake::DEFAULT_EXTENSIONS,
235               "Client auth handshake test");
236
237#Test 7: A handshake with a renegotiation
238$proxy->clear();
239$proxy->clientflags("-no_tls1_3");
240$proxy->serverflags("-client_renegotiation");
241$proxy->reneg(1);
242$proxy->start();
243checkhandshake($proxy, checkhandshake::RENEG_HANDSHAKE,
244               checkhandshake::DEFAULT_EXTENSIONS,
245               "Renegotiation handshake test");
246
247#Test 8: Server name handshake (no client request)
248$proxy->clear();
249$proxy->clientflags("-no_tls1_3 -noservername");
250$proxy->start();
251checkhandshake($proxy, checkhandshake::DEFAULT_HANDSHAKE,
252               checkhandshake::DEFAULT_EXTENSIONS
253               & ~checkhandshake::SERVER_NAME_CLI_EXTENSION,
254               "Server name handshake test (client)");
255
256#Test 9: Server name handshake (server support only)
257$proxy->clear();
258$proxy->clientflags("-no_tls1_3 -noservername");
259$proxy->serverflags("-servername testhost");
260$proxy->start();
261checkhandshake($proxy, checkhandshake::DEFAULT_HANDSHAKE,
262               checkhandshake::DEFAULT_EXTENSIONS
263               & ~checkhandshake::SERVER_NAME_CLI_EXTENSION,
264               "Server name handshake test (server)");
265
266#Test 10: Server name handshake (client and server)
267$proxy->clear();
268$proxy->clientflags("-no_tls1_3 -servername testhost");
269$proxy->serverflags("-servername testhost");
270$proxy->start();
271checkhandshake($proxy, checkhandshake::DEFAULT_HANDSHAKE,
272               checkhandshake::DEFAULT_EXTENSIONS
273               | checkhandshake::SERVER_NAME_SRV_EXTENSION,
274               "Server name handshake test");
275
276#Test 11: ALPN handshake (client request only)
277$proxy->clear();
278$proxy->clientflags("-no_tls1_3 -alpn test");
279$proxy->start();
280checkhandshake($proxy, checkhandshake::DEFAULT_HANDSHAKE,
281               checkhandshake::DEFAULT_EXTENSIONS
282               | checkhandshake::ALPN_CLI_EXTENSION,
283               "ALPN handshake test (client)");
284
285#Test 12: ALPN handshake (server support only)
286$proxy->clear();
287$proxy->clientflags("-no_tls1_3");
288$proxy->serverflags("-alpn test");
289$proxy->start();
290checkhandshake($proxy, checkhandshake::DEFAULT_HANDSHAKE,
291               checkhandshake::DEFAULT_EXTENSIONS,
292               "ALPN handshake test (server)");
293
294#Test 13: ALPN handshake (client and server)
295$proxy->clear();
296$proxy->clientflags("-no_tls1_3 -alpn test");
297$proxy->serverflags("-alpn test");
298$proxy->start();
299checkhandshake($proxy, checkhandshake::DEFAULT_HANDSHAKE,
300               checkhandshake::DEFAULT_EXTENSIONS
301               | checkhandshake::ALPN_CLI_EXTENSION
302               | checkhandshake::ALPN_SRV_EXTENSION,
303               "ALPN handshake test");
304
305SKIP: {
306    skip "No CT, EC or OCSP support in this OpenSSL build", 1
307        if disabled("ct") || disabled("ec") || disabled("ocsp");
308
309    #Test 14: SCT handshake (client request only)
310    $proxy->clear();
311    #Note: -ct also sends status_request
312    $proxy->clientflags("-no_tls1_3 -ct");
313    $proxy->serverflags("-status_file "
314                        .srctop_file("test", "recipes", "ocsp-response.der"));
315    $proxy->start();
316    checkhandshake($proxy, checkhandshake::OCSP_HANDSHAKE,
317                   checkhandshake::DEFAULT_EXTENSIONS
318                   | checkhandshake::SCT_CLI_EXTENSION
319                   | checkhandshake::STATUS_REQUEST_CLI_EXTENSION
320                   | checkhandshake::STATUS_REQUEST_SRV_EXTENSION,
321                   "SCT handshake test (client)");
322}
323
324SKIP: {
325    skip "No OCSP support in this OpenSSL build", 1
326        if disabled("ocsp");
327
328    #Test 15: SCT handshake (server support only)
329    $proxy->clear();
330    #Note: -ct also sends status_request
331    $proxy->clientflags("-no_tls1_3");
332    $proxy->serverflags("-status_file "
333                        .srctop_file("test", "recipes", "ocsp-response.der"));
334    $proxy->start();
335    checkhandshake($proxy, checkhandshake::DEFAULT_HANDSHAKE,
336                   checkhandshake::DEFAULT_EXTENSIONS,
337                   "SCT handshake test (server)");
338}
339
340SKIP: {
341    skip "No CT, EC or OCSP support in this OpenSSL build", 1
342        if disabled("ct") || disabled("ec") || disabled("ocsp");
343
344    #Test 16: SCT handshake (client and server)
345    #There is no built-in server side support for this so we are actually also
346    #testing custom extensions here
347    $proxy->clear();
348    #Note: -ct also sends status_request
349    $proxy->clientflags("-no_tls1_3 -ct");
350    $proxy->serverflags("-status_file "
351                        .srctop_file("test", "recipes", "ocsp-response.der")
352                        ." -serverinfo ".srctop_file("test", "serverinfo.pem"));
353    $proxy->start();
354    checkhandshake($proxy, checkhandshake::OCSP_HANDSHAKE,
355                   checkhandshake::DEFAULT_EXTENSIONS
356                   | checkhandshake::SCT_CLI_EXTENSION
357                   | checkhandshake::SCT_SRV_EXTENSION
358                   | checkhandshake::STATUS_REQUEST_CLI_EXTENSION
359                   | checkhandshake::STATUS_REQUEST_SRV_EXTENSION,
360                   "SCT handshake test");
361}
362
363
364SKIP: {
365    skip "No NPN support in this OpenSSL build", 3
366        if disabled("nextprotoneg");
367
368    #Test 17: NPN handshake (client request only)
369    $proxy->clear();
370    $proxy->clientflags("-no_tls1_3 -nextprotoneg test");
371    $proxy->start();
372    checkhandshake($proxy, checkhandshake::DEFAULT_HANDSHAKE,
373                   checkhandshake::DEFAULT_EXTENSIONS
374                   | checkhandshake::NPN_CLI_EXTENSION,
375                   "NPN handshake test (client)");
376
377    #Test 18: NPN handshake (server support only)
378    $proxy->clear();
379    $proxy->clientflags("-no_tls1_3");
380    $proxy->serverflags("-nextprotoneg test");
381    $proxy->start();
382    checkhandshake($proxy, checkhandshake::DEFAULT_HANDSHAKE,
383                   checkhandshake::DEFAULT_EXTENSIONS,
384                   "NPN handshake test (server)");
385
386    #Test 19: NPN handshake (client and server)
387    $proxy->clear();
388    $proxy->clientflags("-no_tls1_3 -nextprotoneg test");
389    $proxy->serverflags("-nextprotoneg test");
390    $proxy->start();
391    checkhandshake($proxy, checkhandshake::NPN_HANDSHAKE,
392                   checkhandshake::DEFAULT_EXTENSIONS
393                   | checkhandshake::NPN_CLI_EXTENSION
394                   | checkhandshake::NPN_SRV_EXTENSION,
395                   "NPN handshake test");
396}
397
398SKIP: {
399    skip "No SRP support in this OpenSSL build", 1
400        if disabled("srp");
401
402    #Test 20: SRP extension
403    #Note: We are not actually going to perform an SRP handshake (TLSProxy
404    #does not support it). However it is sufficient for us to check that the
405    #SRP extension gets added on the client side. There is no SRP extension
406    #generated on the server side anyway.
407    $proxy->clear();
408    $proxy->clientflags("-no_tls1_3 -srpuser user -srppass pass:pass");
409    $proxy->start();
410    checkhandshake($proxy, checkhandshake::DEFAULT_HANDSHAKE,
411                   checkhandshake::DEFAULT_EXTENSIONS
412                   | checkhandshake::SRP_CLI_EXTENSION,
413                   "SRP extension test");
414}
415
416#Test 21: EC handshake
417SKIP: {
418    skip "No EC support in this OpenSSL build", 1 if disabled("ec");
419    $proxy->clear();
420    $proxy->clientflags("-no_tls1_3");
421    $proxy->serverflags("-no_tls1_3");
422    $proxy->ciphers("ECDHE-RSA-AES128-SHA");
423    $proxy->start();
424    checkhandshake($proxy, checkhandshake::EC_HANDSHAKE,
425                   checkhandshake::DEFAULT_EXTENSIONS
426                   | checkhandshake::EC_POINT_FORMAT_SRV_EXTENSION,
427                   "EC handshake test");
428}
429