1#! /usr/bin/env perl
2# Copyright 2015-2019 The OpenSSL Project Authors. All Rights Reserved.
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
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$ENV{CTLOG_FILE} = srctop_file("test", "ct", "log_list.conf");
34
35my $proxy = TLSProxy::Proxy->new(
36    undef,
37    cmdstr(app(["openssl"]), display => 1),
38    srctop_file("apps", "server.pem"),
39    (!$ENV{HARNESS_ACTIVE} || $ENV{HARNESS_VERBOSE})
40);
41
42@handmessages = (
43    [TLSProxy::Message::MT_CLIENT_HELLO,
44        checkhandshake::ALL_HANDSHAKES],
45    [TLSProxy::Message::MT_SERVER_HELLO,
46        checkhandshake::ALL_HANDSHAKES],
47    [TLSProxy::Message::MT_CERTIFICATE,
48        checkhandshake::ALL_HANDSHAKES
49        & ~checkhandshake::RESUME_HANDSHAKE],
50    (disabled("ec") ? () :
51                      [TLSProxy::Message::MT_SERVER_KEY_EXCHANGE,
52                          checkhandshake::EC_HANDSHAKE]),
53    [TLSProxy::Message::MT_CERTIFICATE_STATUS,
54        checkhandshake::OCSP_HANDSHAKE],
55    #ServerKeyExchange handshakes not currently supported by TLSProxy
56    [TLSProxy::Message::MT_CERTIFICATE_REQUEST,
57        checkhandshake::CLIENT_AUTH_HANDSHAKE],
58    [TLSProxy::Message::MT_SERVER_HELLO_DONE,
59        checkhandshake::ALL_HANDSHAKES
60        & ~checkhandshake::RESUME_HANDSHAKE],
61    [TLSProxy::Message::MT_CERTIFICATE,
62        checkhandshake::CLIENT_AUTH_HANDSHAKE],
63    [TLSProxy::Message::MT_CLIENT_KEY_EXCHANGE,
64        checkhandshake::ALL_HANDSHAKES
65        & ~checkhandshake::RESUME_HANDSHAKE],
66    [TLSProxy::Message::MT_CERTIFICATE_VERIFY,
67        checkhandshake::CLIENT_AUTH_HANDSHAKE],
68    [TLSProxy::Message::MT_NEXT_PROTO,
69        checkhandshake::NPN_HANDSHAKE],
70    [TLSProxy::Message::MT_FINISHED,
71        checkhandshake::ALL_HANDSHAKES],
72    [TLSProxy::Message::MT_NEW_SESSION_TICKET,
73        checkhandshake::ALL_HANDSHAKES
74        & ~checkhandshake::RESUME_HANDSHAKE],
75    [TLSProxy::Message::MT_FINISHED,
76        checkhandshake::ALL_HANDSHAKES],
77    [TLSProxy::Message::MT_CLIENT_HELLO,
78        checkhandshake::RENEG_HANDSHAKE],
79    [TLSProxy::Message::MT_SERVER_HELLO,
80        checkhandshake::RENEG_HANDSHAKE],
81    [TLSProxy::Message::MT_CERTIFICATE,
82        checkhandshake::RENEG_HANDSHAKE],
83    [TLSProxy::Message::MT_SERVER_HELLO_DONE,
84        checkhandshake::RENEG_HANDSHAKE],
85    [TLSProxy::Message::MT_CLIENT_KEY_EXCHANGE,
86        checkhandshake::RENEG_HANDSHAKE],
87    [TLSProxy::Message::MT_FINISHED,
88        checkhandshake::RENEG_HANDSHAKE],
89    [TLSProxy::Message::MT_NEW_SESSION_TICKET,
90        checkhandshake::RENEG_HANDSHAKE],
91    [TLSProxy::Message::MT_FINISHED,
92        checkhandshake::RENEG_HANDSHAKE],
93    [0, 0]
94);
95
96@extensions = (
97    [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_SERVER_NAME,
98        TLSProxy::Message::CLIENT,
99        checkhandshake::SERVER_NAME_CLI_EXTENSION],
100    [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_STATUS_REQUEST,
101        TLSProxy::Message::CLIENT,
102        checkhandshake::STATUS_REQUEST_CLI_EXTENSION],
103    (disabled("ec") ? () :
104                      [TLSProxy::Message::MT_CLIENT_HELLO,
105                       TLSProxy::Message::EXT_SUPPORTED_GROUPS,
106                       TLSProxy::Message::CLIENT,
107                       checkhandshake::DEFAULT_EXTENSIONS]),
108    (disabled("ec") ? () :
109                      [TLSProxy::Message::MT_CLIENT_HELLO,
110                       TLSProxy::Message::EXT_EC_POINT_FORMATS,
111                       TLSProxy::Message::CLIENT,
112                       checkhandshake::DEFAULT_EXTENSIONS]),
113    (disabled("tls1_2") ? () :
114     [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_SIG_ALGS,
115        TLSProxy::Message::CLIENT,
116         checkhandshake::DEFAULT_EXTENSIONS]),
117    [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_ALPN,
118        TLSProxy::Message::CLIENT,
119        checkhandshake::ALPN_CLI_EXTENSION],
120    [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_SCT,
121        TLSProxy::Message::CLIENT,
122        checkhandshake::SCT_CLI_EXTENSION],
123    [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_ENCRYPT_THEN_MAC,
124        TLSProxy::Message::CLIENT,
125        checkhandshake::DEFAULT_EXTENSIONS],
126    [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_EXTENDED_MASTER_SECRET,
127        TLSProxy::Message::CLIENT,
128        checkhandshake::DEFAULT_EXTENSIONS],
129    [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_SESSION_TICKET,
130        TLSProxy::Message::CLIENT,
131        checkhandshake::DEFAULT_EXTENSIONS],
132    [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_RENEGOTIATE,
133        TLSProxy::Message::CLIENT,
134        checkhandshake::RENEGOTIATE_CLI_EXTENSION],
135    [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_NPN,
136        TLSProxy::Message::CLIENT,
137        checkhandshake::NPN_CLI_EXTENSION],
138    [TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_SRP,
139        TLSProxy::Message::CLIENT,
140        checkhandshake::SRP_CLI_EXTENSION],
141
142    [TLSProxy::Message::MT_SERVER_HELLO, TLSProxy::Message::EXT_RENEGOTIATE,
143        TLSProxy::Message::SERVER,
144        checkhandshake::DEFAULT_EXTENSIONS],
145    [TLSProxy::Message::MT_SERVER_HELLO, TLSProxy::Message::EXT_ENCRYPT_THEN_MAC,
146        TLSProxy::Message::SERVER,
147        checkhandshake::DEFAULT_EXTENSIONS],
148    [TLSProxy::Message::MT_SERVER_HELLO, TLSProxy::Message::EXT_EXTENDED_MASTER_SECRET,
149        TLSProxy::Message::SERVER,
150        checkhandshake::DEFAULT_EXTENSIONS],
151    [TLSProxy::Message::MT_SERVER_HELLO, TLSProxy::Message::EXT_SESSION_TICKET,
152        TLSProxy::Message::SERVER,
153        checkhandshake::SESSION_TICKET_SRV_EXTENSION],
154    [TLSProxy::Message::MT_SERVER_HELLO, TLSProxy::Message::EXT_SERVER_NAME,
155        TLSProxy::Message::SERVER,
156        checkhandshake::SERVER_NAME_SRV_EXTENSION],
157    [TLSProxy::Message::MT_SERVER_HELLO, TLSProxy::Message::EXT_STATUS_REQUEST,
158        TLSProxy::Message::SERVER,
159        checkhandshake::STATUS_REQUEST_SRV_EXTENSION],
160    [TLSProxy::Message::MT_SERVER_HELLO, TLSProxy::Message::EXT_ALPN,
161        TLSProxy::Message::SERVER,
162        checkhandshake::ALPN_SRV_EXTENSION],
163    [TLSProxy::Message::MT_SERVER_HELLO, TLSProxy::Message::EXT_SCT,
164        TLSProxy::Message::SERVER,
165        checkhandshake::SCT_SRV_EXTENSION],
166    [TLSProxy::Message::MT_SERVER_HELLO, TLSProxy::Message::EXT_NPN,
167        TLSProxy::Message::SERVER,
168        checkhandshake::NPN_SRV_EXTENSION],
169    [TLSProxy::Message::MT_SERVER_HELLO, TLSProxy::Message::EXT_EC_POINT_FORMATS,
170        TLSProxy::Message::SERVER,
171        checkhandshake::EC_POINT_FORMAT_SRV_EXTENSION],
172    [0,0,0,0]
173);
174
175#Test 1: Check we get all the right messages for a default handshake
176(undef, my $session) = tempfile();
177$proxy->serverconnects(2);
178$proxy->clientflags("-no_tls1_3 -sess_out ".$session);
179$proxy->start() or plan skip_all => "Unable to start up Proxy for tests";
180plan tests => 21;
181checkhandshake($proxy, checkhandshake::DEFAULT_HANDSHAKE,
182               checkhandshake::DEFAULT_EXTENSIONS,
183               "Default handshake test");
184
185#Test 2: Resumption handshake
186$proxy->clearClient();
187$proxy->clientflags("-no_tls1_3 -sess_in ".$session);
188$proxy->clientstart();
189checkhandshake($proxy, checkhandshake::RESUME_HANDSHAKE,
190               checkhandshake::DEFAULT_EXTENSIONS
191               & ~checkhandshake::SESSION_TICKET_SRV_EXTENSION,
192               "Resumption handshake test");
193unlink $session;
194
195SKIP: {
196    skip "No OCSP support in this OpenSSL build", 3
197        if disabled("ocsp");
198
199    #Test 3: A status_request handshake (client request only)
200    $proxy->clear();
201    $proxy->clientflags("-no_tls1_3 -status");
202    $proxy->start();
203    checkhandshake($proxy, checkhandshake::DEFAULT_HANDSHAKE,
204                   checkhandshake::DEFAULT_EXTENSIONS
205                   | checkhandshake::STATUS_REQUEST_CLI_EXTENSION,
206                   "status_request handshake test (client)");
207
208    #Test 4: A status_request handshake (server support only)
209    $proxy->clear();
210    $proxy->clientflags("-no_tls1_3");
211    $proxy->serverflags("-status_file "
212                        .srctop_file("test", "recipes", "ocsp-response.der"));
213    $proxy->start();
214    checkhandshake($proxy, checkhandshake::DEFAULT_HANDSHAKE,
215                   checkhandshake::DEFAULT_EXTENSIONS,
216                   "status_request handshake test (server)");
217
218    #Test 5: A status_request handshake (client and server)
219    $proxy->clear();
220    $proxy->clientflags("-no_tls1_3 -status");
221    $proxy->serverflags("-status_file "
222                        .srctop_file("test", "recipes", "ocsp-response.der"));
223    $proxy->start();
224    checkhandshake($proxy, checkhandshake::OCSP_HANDSHAKE,
225                   checkhandshake::DEFAULT_EXTENSIONS
226                   | checkhandshake::STATUS_REQUEST_CLI_EXTENSION
227                   | checkhandshake::STATUS_REQUEST_SRV_EXTENSION,
228                   "status_request handshake test");
229}
230
231#Test 6: A client auth handshake
232$proxy->clear();
233$proxy->clientflags("-no_tls1_3 -cert ".srctop_file("apps", "server.pem"));
234$proxy->serverflags("-Verify 5");
235$proxy->start();
236checkhandshake($proxy, checkhandshake::CLIENT_AUTH_HANDSHAKE,
237               checkhandshake::DEFAULT_EXTENSIONS,
238               "Client auth handshake test");
239
240#Test 7: A handshake with a renegotiation
241$proxy->clear();
242$proxy->clientflags("-no_tls1_3");
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