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