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 bldtop_dir/; 11use OpenSSL::Test::Utils; 12use TLSProxy::Proxy; 13use File::Temp qw(tempfile); 14 15my $test_name = "test_tlsextms"; 16setup($test_name); 17 18plan skip_all => "TLSProxy isn't usable on $^O" 19 if $^O =~ /^(VMS)$/; 20 21plan skip_all => "$test_name needs the dynamic engine feature enabled" 22 if disabled("engine") || disabled("dynamic-engine"); 23 24plan skip_all => "$test_name needs the sock feature enabled" 25 if disabled("sock"); 26 27plan skip_all => "$test_name needs TLSv1.0, TLSv1.1 or TLSv1.2 enabled" 28 if disabled("tls1") && disabled("tls1_1") && disabled("tls1_2"); 29 30$ENV{OPENSSL_ia32cap} = '~0x200000200000000'; 31 32sub checkmessages($$$$$); 33sub setrmextms($$); 34sub clearall(); 35 36my $crmextms = 0; 37my $srmextms = 0; 38my $cextms = 0; 39my $sextms = 0; 40my $fullhand = 0; 41 42my $proxy = TLSProxy::Proxy->new( 43 \&extms_filter, 44 cmdstr(app(["openssl"]), display => 1), 45 srctop_file("apps", "server.pem"), 46 (!$ENV{HARNESS_ACTIVE} || $ENV{HARNESS_VERBOSE}) 47); 48 49#Note that EXTMS is only relevant for <TLS1.3 50 51#Test 1: By default server and client should send extended master secret 52# extension. 53#Expected result: ClientHello extension seen; ServerHello extension seen 54# Full handshake 55 56setrmextms(0, 0); 57$proxy->clientflags("-no_tls1_3"); 58$proxy->start() or plan skip_all => "Unable to start up Proxy for tests"; 59plan tests => 10; 60checkmessages(1, "Default extended master secret test", 1, 1, 1); 61 62#Test 2: If client omits extended master secret extension, server should too. 63#Expected result: ClientHello extension not seen; ServerHello extension not seen 64# Full handshake 65 66clearall(); 67setrmextms(1, 0); 68$proxy->clientflags("-no_tls1_3"); 69$proxy->start(); 70checkmessages(2, "No client extension extended master secret test", 0, 0, 1); 71 72# Test 3: same as 1 but with session tickets disabled. 73# Expected result: same as test 1. 74 75clearall(); 76$proxy->clientflags("-no_ticket -no_tls1_3"); 77setrmextms(0, 0); 78$proxy->start(); 79checkmessages(3, "No ticket extended master secret test", 1, 1, 1); 80 81# Test 4: same as 2 but with session tickets disabled. 82# Expected result: same as test 2. 83 84clearall(); 85$proxy->clientflags("-no_ticket -no_tls1_3"); 86setrmextms(1, 0); 87$proxy->start(); 88checkmessages(4, "No ticket, no client extension extended master secret test", 0, 0, 1); 89 90#Test 5: Session resumption extended master secret test 91# 92#Expected result: ClientHello extension seen; ServerHello extension seen 93# Abbreviated handshake 94 95clearall(); 96setrmextms(0, 0); 97(undef, my $session) = tempfile(); 98$proxy->serverconnects(2); 99$proxy->clientflags("-no_tls1_3 -sess_out ".$session); 100$proxy->start(); 101$proxy->clearClient(); 102$proxy->clientflags("-no_tls1_3 -sess_in ".$session); 103$proxy->clientstart(); 104checkmessages(5, "Session resumption extended master secret test", 1, 1, 0); 105unlink $session; 106 107#Test 6: Session resumption extended master secret test original session 108# omits extension. Server must not resume session. 109#Expected result: ClientHello extension seen; ServerHello extension seen 110# Full handshake 111 112clearall(); 113setrmextms(1, 0); 114(undef, $session) = tempfile(); 115$proxy->serverconnects(2); 116$proxy->clientflags("-no_tls1_3 -sess_out ".$session); 117$proxy->start(); 118$proxy->clearClient(); 119$proxy->clientflags("-no_tls1_3 -sess_in ".$session); 120setrmextms(0, 0); 121$proxy->clientstart(); 122checkmessages(6, "Session resumption extended master secret test", 1, 1, 1); 123unlink $session; 124 125#Test 7: Session resumption extended master secret test resumed session 126# omits client extension. Server must abort connection. 127#Expected result: aborted connection. 128 129clearall(); 130setrmextms(0, 0); 131(undef, $session) = tempfile(); 132$proxy->serverconnects(2); 133$proxy->clientflags("-no_tls1_3 -sess_out ".$session); 134$proxy->start(); 135$proxy->clearClient(); 136$proxy->clientflags("-no_tls1_3 -sess_in ".$session); 137setrmextms(1, 0); 138$proxy->clientstart(); 139ok(TLSProxy::Message->fail(), "Client inconsistent session resumption"); 140unlink $session; 141 142#Test 8: Session resumption extended master secret test resumed session 143# omits server extension. Client must abort connection. 144#Expected result: aborted connection. 145 146clearall(); 147setrmextms(0, 0); 148(undef, $session) = tempfile(); 149$proxy->serverconnects(2); 150$proxy->clientflags("-no_tls1_3 -sess_out ".$session); 151$proxy->start(); 152$proxy->clearClient(); 153$proxy->clientflags("-no_tls1_3 -sess_in ".$session); 154setrmextms(0, 1); 155$proxy->clientstart(); 156ok(TLSProxy::Message->fail(), "Server inconsistent session resumption 1"); 157unlink $session; 158 159#Test 9: Session resumption extended master secret test initial session 160# omits server extension. Client must abort connection. 161#Expected result: aborted connection. 162 163clearall(); 164setrmextms(0, 1); 165(undef, $session) = tempfile(); 166$proxy->serverconnects(2); 167$proxy->clientflags("-no_tls1_3 -sess_out ".$session); 168$proxy->start(); 169$proxy->clearClient(); 170$proxy->clientflags("-no_tls1_3 -sess_in ".$session); 171setrmextms(0, 0); 172$proxy->clientstart(); 173ok(TLSProxy::Message->fail(), "Server inconsistent session resumption 2"); 174unlink $session; 175 176SKIP: { 177 skip "TLS 1.3 disabled", 1 178 if disabled("tls1_3") || (disabled("ec") && disabled("dh")); 179 180 #Test 10: In TLS1.3 we should not negotiate extended master secret 181 #Expected result: ClientHello extension seen; ServerHello extension not seen 182 # TLS1.3 handshake (will appear as abbreviated handshake 183 # because of no CKE message) 184 clearall(); 185 setrmextms(0, 0); 186 $proxy->start(); 187 checkmessages(10, "TLS1.3 extended master secret test", 1, 0, 0); 188} 189 190 191sub extms_filter 192{ 193 my $proxy = shift; 194 195 foreach my $message (@{$proxy->message_list}) { 196 if ($crmextms && $message->mt == TLSProxy::Message::MT_CLIENT_HELLO) { 197 $message->delete_extension(TLSProxy::Message::EXT_EXTENDED_MASTER_SECRET); 198 $message->repack(); 199 } 200 if ($srmextms && $message->mt == TLSProxy::Message::MT_SERVER_HELLO) { 201 $message->delete_extension(TLSProxy::Message::EXT_EXTENDED_MASTER_SECRET); 202 $message->repack(); 203 } 204 } 205} 206 207sub checkmessages($$$$$) 208{ 209 my ($testno, $testname, $testcextms, $testsextms, $testhand) = @_; 210 211 subtest $testname => sub { 212 213 foreach my $message (@{$proxy->message_list}) { 214 if ($message->mt == TLSProxy::Message::MT_CLIENT_HELLO 215 || $message->mt == TLSProxy::Message::MT_SERVER_HELLO) { 216 #Get the extensions data 217 my %extensions = %{$message->extension_data}; 218 if (defined 219 $extensions{TLSProxy::Message::EXT_EXTENDED_MASTER_SECRET}) { 220 if ($message->mt == TLSProxy::Message::MT_CLIENT_HELLO) { 221 $cextms = 1; 222 } else { 223 $sextms = 1; 224 } 225 } 226 } elsif ($message->mt == TLSProxy::Message::MT_CLIENT_KEY_EXCHANGE) { 227 #Must be doing a full handshake 228 $fullhand = 1; 229 } 230 } 231 232 plan tests => 4; 233 234 ok(TLSProxy::Message->success, "Handshake"); 235 236 ok($testcextms == $cextms, 237 "ClientHello extension extended master secret check"); 238 ok($testsextms == $sextms, 239 "ServerHello extension extended master secret check"); 240 ok($testhand == $fullhand, 241 "Extended master secret full handshake check"); 242 243 } 244} 245 246sub setrmextms($$) 247{ 248 ($crmextms, $srmextms) = @_; 249} 250 251sub clearall() 252{ 253 $cextms = 0; 254 $sextms = 0; 255 $fullhand = 0; 256 $proxy->clear(); 257} 258