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