1#! /usr/bin/env perl 2# Copyright 2015-2018 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 bldtop_dir/; 11use OpenSSL::Test::Utils; 12use File::Temp qw(tempfile); 13use TLSProxy::Proxy; 14my $test_name = "test_tls13messages"; 15setup($test_name); 16 17plan skip_all => "TLSProxy isn't usable on $^O" 18 if $^O =~ /^(VMS)$/; 19 20plan skip_all => "$test_name needs the dynamic engine feature enabled" 21 if disabled("engine") || disabled("dynamic-engine"); 22 23plan skip_all => "$test_name needs the sock feature enabled" 24 if disabled("sock"); 25 26plan skip_all => "$test_name needs TLS enabled" 27 if alldisabled(available_protocols("tls")); 28 29$ENV{OPENSSL_ia32cap} = '~0x200000200000000'; 30 31use constant { 32 DEFAULT_HANDSHAKE => 1, 33 OCSP_HANDSHAKE => 2, 34 RESUME_HANDSHAKE => 4, 35 CLIENT_AUTH_HANDSHAKE => 8, 36 RENEG_HANDSHAKE => 16, 37 38 ALL_HANDSHAKES => 31 39}; 40 41my @handmessages = ( 42 [TLSProxy::Message::MT_CLIENT_HELLO, ALL_HANDSHAKES], 43 [TLSProxy::Message::MT_SERVER_HELLO, ALL_HANDSHAKES], 44 [TLSProxy::Message::MT_CERTIFICATE, ALL_HANDSHAKES & ~RESUME_HANDSHAKE], 45 [TLSProxy::Message::MT_CERTIFICATE_STATUS, OCSP_HANDSHAKE], 46 #ServerKeyExchange handshakes not currently supported by TLSProxy 47 [TLSProxy::Message::MT_CERTIFICATE_REQUEST, CLIENT_AUTH_HANDSHAKE], 48 [TLSProxy::Message::MT_SERVER_HELLO_DONE, ALL_HANDSHAKES & ~RESUME_HANDSHAKE], 49 [TLSProxy::Message::MT_CERTIFICATE, CLIENT_AUTH_HANDSHAKE], 50 [TLSProxy::Message::MT_CLIENT_KEY_EXCHANGE, ALL_HANDSHAKES & ~RESUME_HANDSHAKE], 51 [TLSProxy::Message::MT_CERTIFICATE_VERIFY, CLIENT_AUTH_HANDSHAKE], 52 [TLSProxy::Message::MT_FINISHED, ALL_HANDSHAKES], 53 [TLSProxy::Message::MT_NEW_SESSION_TICKET, ALL_HANDSHAKES & ~RESUME_HANDSHAKE], 54 [TLSProxy::Message::MT_FINISHED, ALL_HANDSHAKES], 55 [TLSProxy::Message::MT_CLIENT_HELLO, RENEG_HANDSHAKE], 56 [TLSProxy::Message::MT_SERVER_HELLO, RENEG_HANDSHAKE], 57 [TLSProxy::Message::MT_CERTIFICATE, RENEG_HANDSHAKE], 58 [TLSProxy::Message::MT_SERVER_HELLO_DONE, RENEG_HANDSHAKE], 59 [TLSProxy::Message::MT_CLIENT_KEY_EXCHANGE, RENEG_HANDSHAKE], 60 [TLSProxy::Message::MT_FINISHED, RENEG_HANDSHAKE], 61 [TLSProxy::Message::MT_NEW_SESSION_TICKET, RENEG_HANDSHAKE], 62 [TLSProxy::Message::MT_FINISHED, RENEG_HANDSHAKE], 63 [0, 0] 64); 65 66my $proxy = TLSProxy::Proxy->new( 67 undef, 68 cmdstr(app(["openssl"]), display => 1), 69 srctop_file("apps", "server.pem"), 70 (!$ENV{HARNESS_ACTIVE} || $ENV{HARNESS_VERBOSE}) 71); 72 73sub checkmessages($$); 74 75#Test 1: Check we get all the right messages for a default handshake 76(undef, my $session) = tempfile(); 77$proxy->serverconnects(2); 78$proxy->clientflags("-sess_out ".$session); 79$proxy->start() or plan skip_all => "Unable to start up Proxy for tests"; 80plan tests => 5; 81checkmessages(DEFAULT_HANDSHAKE, "Default handshake test"); 82 83#Test 2: Resumption handshake 84$proxy->clearClient(); 85$proxy->clientflags("-sess_in ".$session); 86$proxy->clientstart(); 87checkmessages(RESUME_HANDSHAKE, "Resumption handshake test"); 88unlink $session; 89 90#Test 3: A client auth handshake 91$proxy->clear(); 92$proxy->clientflags("-cert ".srctop_file("apps", "server.pem")); 93$proxy->serverflags("-Verify 5"); 94$proxy->start(); 95checkmessages(CLIENT_AUTH_HANDSHAKE, "Client auth handshake test"); 96 97#Test 4: A handshake with a renegotiation 98$proxy->clear(); 99$proxy->reneg(1); 100$proxy->start(); 101checkmessages(RENEG_HANDSHAKE, "Renegotiation handshake test"); 102 103#Test 5: A handshake with a renegotiation and client auth 104$proxy->clear(); 105$proxy->clientflags("-cert ".srctop_file("apps", "server.pem")); 106$proxy->serverflags("-Verify 5"); 107$proxy->reneg(1); 108$proxy->start(); 109checkmessages(RENEG_HANDSHAKE | CLIENT_AUTH_HANDSHAKE, 110 "Renogitation and client auth handshake test"); 111 112sub checkmessages($$) 113{ 114 my ($handtype, $testname) = @_; 115 116 subtest $testname => sub { 117 my $loop = 0; 118 my $numtests; 119 120 #First count the number of tests 121 for ($numtests = 0; $handmessages[$loop][1] != 0; $loop++) { 122 $numtests++ if (($handmessages[$loop][1] & $handtype) != 0); 123 } 124 125 plan tests => $numtests; 126 127 my $nextmess = 0; 128 my $message = undef; 129 for ($loop = 0; $handmessages[$loop][1] != 0; $loop++) { 130 next if (($handmessages[$loop][1] & $handtype) == 0); 131 if (scalar @{$proxy->message_list} > $nextmess) { 132 $message = ${$proxy->message_list}[$nextmess]; 133 $nextmess++; 134 } else { 135 $message = undef; 136 } 137 if (!defined $message) { 138 fail("Message type check. Got nothing, expected " 139 .$handmessages[$loop][0]); 140 } else { 141 ok($message->mt == $handmessages[$loop][0], 142 "Message type check. Got ".$message->mt 143 .", expected ".$handmessages[$loop][0]); 144 } 145 } 146 } 147} 148