xref: /freebsd/crypto/openssl/test/recipes/70-test_sslsessiontick.t (revision e0c4386e7e71d93b0edc0c8fa156263fc4a8b0b6)
1*e0c4386eSCy Schubert#! /usr/bin/env perl
2*e0c4386eSCy Schubert# Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved.
3*e0c4386eSCy Schubert#
4*e0c4386eSCy Schubert# Licensed under the Apache License 2.0 (the "License").  You may not use
5*e0c4386eSCy Schubert# this file except in compliance with the License.  You can obtain a copy
6*e0c4386eSCy Schubert# in the file LICENSE in the source distribution or at
7*e0c4386eSCy Schubert# https://www.openssl.org/source/license.html
8*e0c4386eSCy Schubert
9*e0c4386eSCy Schubertuse strict;
10*e0c4386eSCy Schubertuse OpenSSL::Test qw/:DEFAULT cmdstr srctop_file bldtop_dir/;
11*e0c4386eSCy Schubertuse OpenSSL::Test::Utils;
12*e0c4386eSCy Schubertuse TLSProxy::Proxy;
13*e0c4386eSCy Schubertuse File::Temp qw(tempfile);
14*e0c4386eSCy Schubert
15*e0c4386eSCy Schubertmy $test_name = "test_sslsessiontick";
16*e0c4386eSCy Schubertsetup($test_name);
17*e0c4386eSCy Schubert
18*e0c4386eSCy Schubertplan skip_all => "TLSProxy isn't usable on $^O"
19*e0c4386eSCy Schubert    if $^O =~ /^(VMS)$/;
20*e0c4386eSCy Schubert
21*e0c4386eSCy Schubertplan skip_all => "$test_name needs the dynamic engine feature enabled"
22*e0c4386eSCy Schubert    if disabled("engine") || disabled("dynamic-engine");
23*e0c4386eSCy Schubert
24*e0c4386eSCy Schubertplan skip_all => "$test_name needs the sock feature enabled"
25*e0c4386eSCy Schubert    if disabled("sock");
26*e0c4386eSCy Schubert
27*e0c4386eSCy Schubertplan skip_all => "$test_name needs SSLv3, TLSv1, TLSv1.1 or TLSv1.2 enabled"
28*e0c4386eSCy Schubert    if alldisabled(("ssl3", "tls1", "tls1_1", "tls1_2"));
29*e0c4386eSCy Schubert
30*e0c4386eSCy Schubert$ENV{OPENSSL_ia32cap} = '~0x200000200000000';
31*e0c4386eSCy Schubert
32*e0c4386eSCy Schubertsub checkmessages($$$$$$);
33*e0c4386eSCy Schubertsub clearclient();
34*e0c4386eSCy Schubertsub clearall();
35*e0c4386eSCy Schubert
36*e0c4386eSCy Schubertmy $chellotickext = 0;
37*e0c4386eSCy Schubertmy $shellotickext = 0;
38*e0c4386eSCy Schubertmy $fullhand = 0;
39*e0c4386eSCy Schubertmy $ticketseen = 0;
40*e0c4386eSCy Schubert
41*e0c4386eSCy Schubertmy $proxy = TLSProxy::Proxy->new(
42*e0c4386eSCy Schubert    undef,
43*e0c4386eSCy Schubert    cmdstr(app(["openssl"]), display => 1),
44*e0c4386eSCy Schubert    srctop_file("apps", "server.pem"),
45*e0c4386eSCy Schubert    (!$ENV{HARNESS_ACTIVE} || $ENV{HARNESS_VERBOSE})
46*e0c4386eSCy Schubert);
47*e0c4386eSCy Schubert
48*e0c4386eSCy Schubert#Test 1: By default with no existing session we should get a session ticket
49*e0c4386eSCy Schubert#Expected result: ClientHello extension seen; ServerHello extension seen
50*e0c4386eSCy Schubert#                 NewSessionTicket message seen; Full handshake
51*e0c4386eSCy Schubert$proxy->clientflags("-no_tls1_3");
52*e0c4386eSCy Schubert$proxy->start() or plan skip_all => "Unable to start up Proxy for tests";
53*e0c4386eSCy Schubertplan tests => 10;
54*e0c4386eSCy Schubertcheckmessages(1, "Default session ticket test", 1, 1, 1, 1);
55*e0c4386eSCy Schubert
56*e0c4386eSCy Schubert#Test 2: If the server does not accept tickets we should get a normal handshake
57*e0c4386eSCy Schubert#with no session tickets
58*e0c4386eSCy Schubert#Expected result: ClientHello extension seen; ServerHello extension not seen
59*e0c4386eSCy Schubert#                 NewSessionTicket message not seen; Full handshake
60*e0c4386eSCy Schubertclearall();
61*e0c4386eSCy Schubert$proxy->clientflags("-no_tls1_3");
62*e0c4386eSCy Schubert$proxy->serverflags("-no_ticket");
63*e0c4386eSCy Schubert$proxy->start();
64*e0c4386eSCy Schubertcheckmessages(2, "No server support session ticket test", 1, 0, 0, 1);
65*e0c4386eSCy Schubert
66*e0c4386eSCy Schubert#Test 3: If the client does not accept tickets we should get a normal handshake
67*e0c4386eSCy Schubert#with no session tickets
68*e0c4386eSCy Schubert#Expected result: ClientHello extension not seen; ServerHello extension not seen
69*e0c4386eSCy Schubert#                 NewSessionTicket message not seen; Full handshake
70*e0c4386eSCy Schubertclearall();
71*e0c4386eSCy Schubert$proxy->clientflags("-no_tls1_3 -no_ticket");
72*e0c4386eSCy Schubert$proxy->start();
73*e0c4386eSCy Schubertcheckmessages(3, "No client support session ticket test", 0, 0, 0, 1);
74*e0c4386eSCy Schubert
75*e0c4386eSCy Schubert#Test 4: Test session resumption with session ticket
76*e0c4386eSCy Schubert#Expected result: ClientHello extension seen; ServerHello extension not seen
77*e0c4386eSCy Schubert#                 NewSessionTicket message not seen; Abbreviated handshake
78*e0c4386eSCy Schubertclearall();
79*e0c4386eSCy Schubert(undef, my $session) = tempfile();
80*e0c4386eSCy Schubert$proxy->serverconnects(2);
81*e0c4386eSCy Schubert$proxy->clientflags("-no_tls1_3 -sess_out ".$session);
82*e0c4386eSCy Schubert$proxy->start();
83*e0c4386eSCy Schubert$proxy->clearClient();
84*e0c4386eSCy Schubert$proxy->clientflags("-no_tls1_3 -sess_in ".$session);
85*e0c4386eSCy Schubert$proxy->clientstart();
86*e0c4386eSCy Schubertcheckmessages(4, "Session resumption session ticket test", 1, 0, 0, 0);
87*e0c4386eSCy Schubertunlink $session;
88*e0c4386eSCy Schubert
89*e0c4386eSCy Schubert#Test 5: Test session resumption with ticket capable client without a ticket
90*e0c4386eSCy Schubert#Expected result: ClientHello extension seen; ServerHello extension seen
91*e0c4386eSCy Schubert#                 NewSessionTicket message seen; Abbreviated handshake
92*e0c4386eSCy Schubertclearall();
93*e0c4386eSCy Schubert(undef, $session) = tempfile();
94*e0c4386eSCy Schubert$proxy->serverconnects(2);
95*e0c4386eSCy Schubert$proxy->clientflags("-no_tls1_3 -sess_out ".$session." -no_ticket");
96*e0c4386eSCy Schubert$proxy->start();
97*e0c4386eSCy Schubert$proxy->clearClient();
98*e0c4386eSCy Schubert$proxy->clientflags("-no_tls1_3 -sess_in ".$session);
99*e0c4386eSCy Schubert$proxy->clientstart();
100*e0c4386eSCy Schubertcheckmessages(5, "Session resumption with ticket capable client without a "
101*e0c4386eSCy Schubert                 ."ticket", 1, 1, 1, 0);
102*e0c4386eSCy Schubertunlink $session;
103*e0c4386eSCy Schubert
104*e0c4386eSCy Schubert#Test 6: Client accepts empty ticket.
105*e0c4386eSCy Schubert#Expected result: ClientHello extension seen; ServerHello extension seen;
106*e0c4386eSCy Schubert#                 NewSessionTicket message seen; Full handshake.
107*e0c4386eSCy Schubertclearall();
108*e0c4386eSCy Schubert$proxy->filter(\&ticket_filter);
109*e0c4386eSCy Schubert$proxy->clientflags("-no_tls1_3");
110*e0c4386eSCy Schubert$proxy->start();
111*e0c4386eSCy Schubertcheckmessages(6, "Empty ticket test",  1, 1, 1, 1);
112*e0c4386eSCy Schubert
113*e0c4386eSCy Schubert#Test 7-8: Client keeps existing ticket on empty ticket.
114*e0c4386eSCy Schubertclearall();
115*e0c4386eSCy Schubert(undef, $session) = tempfile();
116*e0c4386eSCy Schubert$proxy->serverconnects(3);
117*e0c4386eSCy Schubert$proxy->filter(undef);
118*e0c4386eSCy Schubert$proxy->clientflags("-no_tls1_3 -sess_out ".$session);
119*e0c4386eSCy Schubert$proxy->start();
120*e0c4386eSCy Schubert$proxy->clearClient();
121*e0c4386eSCy Schubert$proxy->clientflags("-no_tls1_3 -sess_in ".$session." -sess_out ".$session);
122*e0c4386eSCy Schubert$proxy->filter(\&inject_empty_ticket_filter);
123*e0c4386eSCy Schubert$proxy->clientstart();
124*e0c4386eSCy Schubert#Expected result: ClientHello extension seen; ServerHello extension seen;
125*e0c4386eSCy Schubert#                 NewSessionTicket message seen; Abbreviated handshake.
126*e0c4386eSCy Schubertcheckmessages(7, "Empty ticket resumption test",  1, 1, 1, 0);
127*e0c4386eSCy Schubertclearclient();
128*e0c4386eSCy Schubert$proxy->clientflags("-no_tls1_3 -sess_in ".$session);
129*e0c4386eSCy Schubert$proxy->filter(undef);
130*e0c4386eSCy Schubert$proxy->clientstart();
131*e0c4386eSCy Schubert#Expected result: ClientHello extension seen; ServerHello extension not seen;
132*e0c4386eSCy Schubert#                 NewSessionTicket message not seen; Abbreviated handshake.
133*e0c4386eSCy Schubertcheckmessages(8, "Empty ticket resumption test",  1, 0, 0, 0);
134*e0c4386eSCy Schubertunlink $session;
135*e0c4386eSCy Schubert
136*e0c4386eSCy Schubert#Test 9: Bad server sends the ServerHello extension but does not send a
137*e0c4386eSCy Schubert#NewSessionTicket
138*e0c4386eSCy Schubert#Expected result: Connection failure
139*e0c4386eSCy Schubertclearall();
140*e0c4386eSCy Schubert$proxy->clientflags("-no_tls1_3");
141*e0c4386eSCy Schubert$proxy->serverflags("-no_ticket");
142*e0c4386eSCy Schubert$proxy->filter(\&inject_ticket_extension_filter);
143*e0c4386eSCy Schubert$proxy->start();
144*e0c4386eSCy Schubertok(TLSProxy::Message->fail, "Server sends ticket extension but no ticket test");
145*e0c4386eSCy Schubert
146*e0c4386eSCy Schubert#Test10: Bad server does not send the ServerHello extension but does send a
147*e0c4386eSCy Schubert#NewSessionTicket
148*e0c4386eSCy Schubert#Expected result: Connection failure
149*e0c4386eSCy Schubertclearall();
150*e0c4386eSCy Schubert$proxy->clientflags("-no_tls1_3");
151*e0c4386eSCy Schubert$proxy->serverflags("-no_ticket");
152*e0c4386eSCy Schubert$proxy->filter(\&inject_empty_ticket_filter);
153*e0c4386eSCy Schubert$proxy->start();
154*e0c4386eSCy Schubertok(TLSProxy::Message->fail, "No server ticket extension but ticket sent test");
155*e0c4386eSCy Schubert
156*e0c4386eSCy Schubertsub ticket_filter
157*e0c4386eSCy Schubert{
158*e0c4386eSCy Schubert    my $proxy = shift;
159*e0c4386eSCy Schubert
160*e0c4386eSCy Schubert    foreach my $message (@{$proxy->message_list}) {
161*e0c4386eSCy Schubert        if ($message->mt == TLSProxy::Message::MT_NEW_SESSION_TICKET) {
162*e0c4386eSCy Schubert            $message->ticket("");
163*e0c4386eSCy Schubert            $message->repack();
164*e0c4386eSCy Schubert        }
165*e0c4386eSCy Schubert    }
166*e0c4386eSCy Schubert}
167*e0c4386eSCy Schubert
168*e0c4386eSCy Schubertsub inject_empty_ticket_filter {
169*e0c4386eSCy Schubert    my $proxy = shift;
170*e0c4386eSCy Schubert
171*e0c4386eSCy Schubert    foreach my $message (@{$proxy->message_list}) {
172*e0c4386eSCy Schubert        if ($message->mt == TLSProxy::Message::MT_NEW_SESSION_TICKET) {
173*e0c4386eSCy Schubert            # Only inject the message first time we're called.
174*e0c4386eSCy Schubert            return;
175*e0c4386eSCy Schubert        }
176*e0c4386eSCy Schubert    }
177*e0c4386eSCy Schubert
178*e0c4386eSCy Schubert    my @new_message_list = ();
179*e0c4386eSCy Schubert    foreach my $message (@{$proxy->message_list}) {
180*e0c4386eSCy Schubert        push @new_message_list, $message;
181*e0c4386eSCy Schubert        if ($message->mt == TLSProxy::Message::MT_SERVER_HELLO) {
182*e0c4386eSCy Schubert            $message->set_extension(TLSProxy::Message::EXT_SESSION_TICKET, "");
183*e0c4386eSCy Schubert            $message->repack();
184*e0c4386eSCy Schubert            # Tack NewSessionTicket onto the ServerHello record.
185*e0c4386eSCy Schubert            # This only works if the ServerHello is exactly one record.
186*e0c4386eSCy Schubert            my $record = ${$message->records}[0];
187*e0c4386eSCy Schubert
188*e0c4386eSCy Schubert            my $offset = $message->startoffset + $message->encoded_length;
189*e0c4386eSCy Schubert            my $newsessionticket = TLSProxy::NewSessionTicket->new(
190*e0c4386eSCy Schubert                1, "", [$record], $offset, []);
191*e0c4386eSCy Schubert            $newsessionticket->repack();
192*e0c4386eSCy Schubert            push @new_message_list, $newsessionticket;
193*e0c4386eSCy Schubert        }
194*e0c4386eSCy Schubert    }
195*e0c4386eSCy Schubert    $proxy->message_list([@new_message_list]);
196*e0c4386eSCy Schubert}
197*e0c4386eSCy Schubert
198*e0c4386eSCy Schubertsub inject_ticket_extension_filter
199*e0c4386eSCy Schubert{
200*e0c4386eSCy Schubert    my $proxy = shift;
201*e0c4386eSCy Schubert
202*e0c4386eSCy Schubert    # We're only interested in the initial ServerHello
203*e0c4386eSCy Schubert    if ($proxy->flight != 1) {
204*e0c4386eSCy Schubert        return;
205*e0c4386eSCy Schubert    }
206*e0c4386eSCy Schubert
207*e0c4386eSCy Schubert    foreach my $message (@{$proxy->message_list}) {
208*e0c4386eSCy Schubert        if ($message->mt == TLSProxy::Message::MT_SERVER_HELLO) {
209*e0c4386eSCy Schubert            #Add the session ticket extension to the ServerHello even though
210*e0c4386eSCy Schubert            #we are not going to send a NewSessionTicket message
211*e0c4386eSCy Schubert            $message->set_extension(TLSProxy::Message::EXT_SESSION_TICKET, "");
212*e0c4386eSCy Schubert
213*e0c4386eSCy Schubert            $message->repack();
214*e0c4386eSCy Schubert        }
215*e0c4386eSCy Schubert    }
216*e0c4386eSCy Schubert}
217*e0c4386eSCy Schubert
218*e0c4386eSCy Schubertsub checkmessages($$$$$$)
219*e0c4386eSCy Schubert{
220*e0c4386eSCy Schubert    my ($testno, $testname, $testch, $testsh, $testtickseen, $testhand) = @_;
221*e0c4386eSCy Schubert
222*e0c4386eSCy Schubert    subtest $testname => sub {
223*e0c4386eSCy Schubert
224*e0c4386eSCy Schubert        foreach my $message (@{$proxy->message_list}) {
225*e0c4386eSCy Schubert            if ($message->mt == TLSProxy::Message::MT_CLIENT_HELLO
226*e0c4386eSCy Schubert                || $message->mt == TLSProxy::Message::MT_SERVER_HELLO) {
227*e0c4386eSCy Schubert                #Get the extensions data
228*e0c4386eSCy Schubert                my %extensions = %{$message->extension_data};
229*e0c4386eSCy Schubert                if (defined
230*e0c4386eSCy Schubert                    $extensions{TLSProxy::Message::EXT_SESSION_TICKET}) {
231*e0c4386eSCy Schubert                    if ($message->mt == TLSProxy::Message::MT_CLIENT_HELLO) {
232*e0c4386eSCy Schubert                        $chellotickext = 1;
233*e0c4386eSCy Schubert                    } else {
234*e0c4386eSCy Schubert                        $shellotickext = 1;
235*e0c4386eSCy Schubert                    }
236*e0c4386eSCy Schubert                }
237*e0c4386eSCy Schubert            } elsif ($message->mt == TLSProxy::Message::MT_CERTIFICATE) {
238*e0c4386eSCy Schubert                #Must be doing a full handshake
239*e0c4386eSCy Schubert                $fullhand = 1;
240*e0c4386eSCy Schubert            } elsif ($message->mt == TLSProxy::Message::MT_NEW_SESSION_TICKET) {
241*e0c4386eSCy Schubert                $ticketseen = 1;
242*e0c4386eSCy Schubert            }
243*e0c4386eSCy Schubert        }
244*e0c4386eSCy Schubert
245*e0c4386eSCy Schubert        plan tests => 5;
246*e0c4386eSCy Schubert
247*e0c4386eSCy Schubert        ok(TLSProxy::Message->success, "Handshake");
248*e0c4386eSCy Schubert        ok(($testch && $chellotickext) || (!$testch && !$chellotickext),
249*e0c4386eSCy Schubert           "ClientHello extension Session Ticket check");
250*e0c4386eSCy Schubert        ok(($testsh && $shellotickext) || (!$testsh && !$shellotickext),
251*e0c4386eSCy Schubert           "ServerHello extension Session Ticket check");
252*e0c4386eSCy Schubert        ok(($testtickseen && $ticketseen) || (!$testtickseen && !$ticketseen),
253*e0c4386eSCy Schubert           "Session Ticket message presence check");
254*e0c4386eSCy Schubert        ok(($testhand && $fullhand) || (!$testhand && !$fullhand),
255*e0c4386eSCy Schubert           "Session Ticket full handshake check");
256*e0c4386eSCy Schubert    }
257*e0c4386eSCy Schubert}
258*e0c4386eSCy Schubert
259*e0c4386eSCy Schubert
260*e0c4386eSCy Schubertsub clearclient()
261*e0c4386eSCy Schubert{
262*e0c4386eSCy Schubert    $chellotickext = 0;
263*e0c4386eSCy Schubert    $shellotickext = 0;
264*e0c4386eSCy Schubert    $fullhand = 0;
265*e0c4386eSCy Schubert    $ticketseen = 0;
266*e0c4386eSCy Schubert    $proxy->clearClient();
267*e0c4386eSCy Schubert}
268*e0c4386eSCy Schubert
269*e0c4386eSCy Schubertsub clearall()
270*e0c4386eSCy Schubert{
271*e0c4386eSCy Schubert    clearclient();
272*e0c4386eSCy Schubert    $proxy->clear();
273*e0c4386eSCy Schubert}
274