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