1*4724848cSchristos#! /usr/bin/env perl 2*4724848cSchristos# Copyright 2015-2019 The OpenSSL Project Authors. All Rights Reserved. 3*4724848cSchristos# 4*4724848cSchristos# Licensed under the OpenSSL license (the "License"). You may not use 5*4724848cSchristos# this file except in compliance with the License. You can obtain a copy 6*4724848cSchristos# in the file LICENSE in the source distribution or at 7*4724848cSchristos# https://www.openssl.org/source/license.html 8*4724848cSchristos 9*4724848cSchristospackage checkhandshake; 10*4724848cSchristos 11*4724848cSchristosuse OpenSSL::Test qw/:DEFAULT cmdstr srctop_file srctop_dir bldtop_dir/; 12*4724848cSchristosuse OpenSSL::Test::Utils; 13*4724848cSchristosuse TLSProxy::Proxy; 14*4724848cSchristos 15*4724848cSchristosuse Exporter; 16*4724848cSchristosour @ISA = 'Exporter'; 17*4724848cSchristosour @EXPORT = qw(@handmessages @extensions checkhandshake); 18*4724848cSchristos 19*4724848cSchristosuse constant { 20*4724848cSchristos DEFAULT_HANDSHAKE => 1, 21*4724848cSchristos OCSP_HANDSHAKE => 2, 22*4724848cSchristos RESUME_HANDSHAKE => 4, 23*4724848cSchristos CLIENT_AUTH_HANDSHAKE => 8, 24*4724848cSchristos RENEG_HANDSHAKE => 16, 25*4724848cSchristos NPN_HANDSHAKE => 32, 26*4724848cSchristos EC_HANDSHAKE => 64, 27*4724848cSchristos HRR_HANDSHAKE => 128, 28*4724848cSchristos HRR_RESUME_HANDSHAKE => 256, 29*4724848cSchristos 30*4724848cSchristos ALL_HANDSHAKES => 511 31*4724848cSchristos}; 32*4724848cSchristos 33*4724848cSchristosuse constant { 34*4724848cSchristos #DEFAULT also includes SESSION_TICKET_SRV_EXTENSION and SERVER_NAME_CLI 35*4724848cSchristos DEFAULT_EXTENSIONS => 0x00000007, 36*4724848cSchristos SESSION_TICKET_SRV_EXTENSION => 0x00000002, 37*4724848cSchristos SERVER_NAME_CLI_EXTENSION => 0x00000004, 38*4724848cSchristos SERVER_NAME_SRV_EXTENSION => 0x00000008, 39*4724848cSchristos STATUS_REQUEST_CLI_EXTENSION => 0x00000010, 40*4724848cSchristos STATUS_REQUEST_SRV_EXTENSION => 0x00000020, 41*4724848cSchristos ALPN_CLI_EXTENSION => 0x00000040, 42*4724848cSchristos ALPN_SRV_EXTENSION => 0x00000080, 43*4724848cSchristos SCT_CLI_EXTENSION => 0x00000100, 44*4724848cSchristos SCT_SRV_EXTENSION => 0x00000200, 45*4724848cSchristos RENEGOTIATE_CLI_EXTENSION => 0x00000400, 46*4724848cSchristos NPN_CLI_EXTENSION => 0x00000800, 47*4724848cSchristos NPN_SRV_EXTENSION => 0x00001000, 48*4724848cSchristos SRP_CLI_EXTENSION => 0x00002000, 49*4724848cSchristos #Client side for ec point formats is a default extension 50*4724848cSchristos EC_POINT_FORMAT_SRV_EXTENSION => 0x00004000, 51*4724848cSchristos PSK_CLI_EXTENSION => 0x00008000, 52*4724848cSchristos PSK_SRV_EXTENSION => 0x00010000, 53*4724848cSchristos KEY_SHARE_SRV_EXTENSION => 0x00020000, 54*4724848cSchristos PSK_KEX_MODES_EXTENSION => 0x00040000, 55*4724848cSchristos KEY_SHARE_HRR_EXTENSION => 0x00080000, 56*4724848cSchristos SUPPORTED_GROUPS_SRV_EXTENSION => 0x00100000, 57*4724848cSchristos POST_HANDSHAKE_AUTH_CLI_EXTENSION => 0x00200000 58*4724848cSchristos}; 59*4724848cSchristos 60*4724848cSchristosour @handmessages = (); 61*4724848cSchristosour @extensions = (); 62*4724848cSchristos 63*4724848cSchristossub checkhandshake($$$$) 64*4724848cSchristos{ 65*4724848cSchristos my ($proxy, $handtype, $exttype, $testname) = @_; 66*4724848cSchristos 67*4724848cSchristos subtest $testname => sub { 68*4724848cSchristos my $loop = 0; 69*4724848cSchristos my $numtests; 70*4724848cSchristos my $extcount; 71*4724848cSchristos my $clienthelloseen = 0; 72*4724848cSchristos 73*4724848cSchristos my $lastmt = 0; 74*4724848cSchristos my $numsh = 0; 75*4724848cSchristos if (TLSProxy::Proxy::is_tls13()) { 76*4724848cSchristos #How many ServerHellos are we expecting? 77*4724848cSchristos for ($numtests = 0; $handmessages[$loop][1] != 0; $loop++) { 78*4724848cSchristos next if (($handmessages[$loop][1] & $handtype) == 0); 79*4724848cSchristos $numsh++ if ($lastmt != TLSProxy::Message::MT_SERVER_HELLO 80*4724848cSchristos && $handmessages[$loop][0] == TLSProxy::Message::MT_SERVER_HELLO); 81*4724848cSchristos $lastmt = $handmessages[$loop][0]; 82*4724848cSchristos } 83*4724848cSchristos } 84*4724848cSchristos 85*4724848cSchristos #First count the number of tests 86*4724848cSchristos my $nextmess = 0; 87*4724848cSchristos my $message = undef; 88*4724848cSchristos my $chnum = 0; 89*4724848cSchristos my $shnum = 0; 90*4724848cSchristos if (!TLSProxy::Proxy::is_tls13()) { 91*4724848cSchristos # In non-TLSv1.3 we always treat reneg CH and SH like the first CH 92*4724848cSchristos # and SH 93*4724848cSchristos $chnum = 1; 94*4724848cSchristos $shnum = 1; 95*4724848cSchristos } 96*4724848cSchristos #If we're only expecting one ServerHello out of two then we skip the 97*4724848cSchristos #first ServerHello in the list completely 98*4724848cSchristos $shnum++ if ($numsh == 1 && TLSProxy::Proxy::is_tls13()); 99*4724848cSchristos $loop = 0; 100*4724848cSchristos for ($numtests = 0; $handmessages[$loop][1] != 0; $loop++) { 101*4724848cSchristos next if (($handmessages[$loop][1] & $handtype) == 0); 102*4724848cSchristos if (scalar @{$proxy->message_list} > $nextmess) { 103*4724848cSchristos $message = ${$proxy->message_list}[$nextmess]; 104*4724848cSchristos $nextmess++; 105*4724848cSchristos } else { 106*4724848cSchristos $message = undef; 107*4724848cSchristos } 108*4724848cSchristos $numtests++; 109*4724848cSchristos 110*4724848cSchristos next if (!defined $message); 111*4724848cSchristos if (TLSProxy::Proxy::is_tls13()) { 112*4724848cSchristos $chnum++ if $message->mt() == TLSProxy::Message::MT_CLIENT_HELLO; 113*4724848cSchristos $shnum++ if $message->mt() == TLSProxy::Message::MT_SERVER_HELLO; 114*4724848cSchristos } 115*4724848cSchristos next if ($message->mt() != TLSProxy::Message::MT_CLIENT_HELLO 116*4724848cSchristos && $message->mt() != TLSProxy::Message::MT_SERVER_HELLO 117*4724848cSchristos && $message->mt() != 118*4724848cSchristos TLSProxy::Message::MT_ENCRYPTED_EXTENSIONS 119*4724848cSchristos && $message->mt() != TLSProxy::Message::MT_CERTIFICATE 120*4724848cSchristos && $message->mt() != TLSProxy::Message::MT_CERTIFICATE_REQUEST); 121*4724848cSchristos 122*4724848cSchristos next if $message->mt() == TLSProxy::Message::MT_CERTIFICATE 123*4724848cSchristos && !TLSProxy::Proxy::is_tls13(); 124*4724848cSchristos 125*4724848cSchristos my $extchnum = 1; 126*4724848cSchristos my $extshnum = 1; 127*4724848cSchristos for (my $extloop = 0; 128*4724848cSchristos $extensions[$extloop][3] != 0; 129*4724848cSchristos $extloop++) { 130*4724848cSchristos $extchnum = 2 if $extensions[$extloop][0] != TLSProxy::Message::MT_CLIENT_HELLO 131*4724848cSchristos && TLSProxy::Proxy::is_tls13(); 132*4724848cSchristos $extshnum = 2 if $extensions[$extloop][0] != TLSProxy::Message::MT_SERVER_HELLO 133*4724848cSchristos && $extchnum == 2; 134*4724848cSchristos next if $extensions[$extloop][0] == TLSProxy::Message::MT_CLIENT_HELLO 135*4724848cSchristos && $extchnum != $chnum; 136*4724848cSchristos next if $extensions[$extloop][0] == TLSProxy::Message::MT_SERVER_HELLO 137*4724848cSchristos && $extshnum != $shnum; 138*4724848cSchristos next if ($message->mt() != $extensions[$extloop][0]); 139*4724848cSchristos next if ($message->server() != $extensions[$extloop][2]); 140*4724848cSchristos $numtests++; 141*4724848cSchristos } 142*4724848cSchristos $numtests++; 143*4724848cSchristos } 144*4724848cSchristos 145*4724848cSchristos plan tests => $numtests; 146*4724848cSchristos 147*4724848cSchristos $nextmess = 0; 148*4724848cSchristos $message = undef; 149*4724848cSchristos if (TLSProxy::Proxy::is_tls13()) { 150*4724848cSchristos $chnum = 0; 151*4724848cSchristos $shnum = 0; 152*4724848cSchristos } else { 153*4724848cSchristos # In non-TLSv1.3 we always treat reneg CH and SH like the first CH 154*4724848cSchristos # and SH 155*4724848cSchristos $chnum = 1; 156*4724848cSchristos $shnum = 1; 157*4724848cSchristos } 158*4724848cSchristos #If we're only expecting one ServerHello out of two then we skip the 159*4724848cSchristos #first ServerHello in the list completely 160*4724848cSchristos $shnum++ if ($numsh == 1 && TLSProxy::Proxy::is_tls13()); 161*4724848cSchristos for ($loop = 0; $handmessages[$loop][1] != 0; $loop++) { 162*4724848cSchristos next if (($handmessages[$loop][1] & $handtype) == 0); 163*4724848cSchristos if (scalar @{$proxy->message_list} > $nextmess) { 164*4724848cSchristos $message = ${$proxy->message_list}[$nextmess]; 165*4724848cSchristos $nextmess++; 166*4724848cSchristos } else { 167*4724848cSchristos $message = undef; 168*4724848cSchristos } 169*4724848cSchristos if (!defined $message) { 170*4724848cSchristos fail("Message type check. Got nothing, expected " 171*4724848cSchristos .$handmessages[$loop][0]); 172*4724848cSchristos next; 173*4724848cSchristos } else { 174*4724848cSchristos ok($message->mt == $handmessages[$loop][0], 175*4724848cSchristos "Message type check. Got ".$message->mt 176*4724848cSchristos .", expected ".$handmessages[$loop][0]); 177*4724848cSchristos } 178*4724848cSchristos if (TLSProxy::Proxy::is_tls13()) { 179*4724848cSchristos $chnum++ if $message->mt() == TLSProxy::Message::MT_CLIENT_HELLO; 180*4724848cSchristos $shnum++ if $message->mt() == TLSProxy::Message::MT_SERVER_HELLO; 181*4724848cSchristos } 182*4724848cSchristos 183*4724848cSchristos next if ($message->mt() != TLSProxy::Message::MT_CLIENT_HELLO 184*4724848cSchristos && $message->mt() != TLSProxy::Message::MT_SERVER_HELLO 185*4724848cSchristos && $message->mt() != 186*4724848cSchristos TLSProxy::Message::MT_ENCRYPTED_EXTENSIONS 187*4724848cSchristos && $message->mt() != TLSProxy::Message::MT_CERTIFICATE 188*4724848cSchristos && $message->mt() != TLSProxy::Message::MT_CERTIFICATE_REQUEST); 189*4724848cSchristos 190*4724848cSchristos next if $message->mt() == TLSProxy::Message::MT_CERTIFICATE 191*4724848cSchristos && !TLSProxy::Proxy::is_tls13(); 192*4724848cSchristos 193*4724848cSchristos if ($message->mt() == TLSProxy::Message::MT_CLIENT_HELLO) { 194*4724848cSchristos #Add renegotiate extension we will expect if renegotiating 195*4724848cSchristos $exttype |= RENEGOTIATE_CLI_EXTENSION 196*4724848cSchristos if ($clienthelloseen && !TLSProxy::Proxy::is_tls13()); 197*4724848cSchristos $clienthelloseen = 1; 198*4724848cSchristos } 199*4724848cSchristos #Now check that we saw the extensions we expected 200*4724848cSchristos my $msgexts = $message->extension_data(); 201*4724848cSchristos my $extchnum = 1; 202*4724848cSchristos my $extshnum = 1; 203*4724848cSchristos for (my $extloop = 0, $extcount = 0; $extensions[$extloop][3] != 0; 204*4724848cSchristos $extloop++) { 205*4724848cSchristos #In TLSv1.3 we can have two ClientHellos if there has been a 206*4724848cSchristos #HelloRetryRequest, and they may have different extensions. Skip 207*4724848cSchristos #if these are extensions for a different ClientHello 208*4724848cSchristos $extchnum = 2 if $extensions[$extloop][0] != TLSProxy::Message::MT_CLIENT_HELLO 209*4724848cSchristos && TLSProxy::Proxy::is_tls13(); 210*4724848cSchristos $extshnum = 2 if $extensions[$extloop][0] != TLSProxy::Message::MT_SERVER_HELLO 211*4724848cSchristos && $extchnum == 2; 212*4724848cSchristos next if $extensions[$extloop][0] == TLSProxy::Message::MT_CLIENT_HELLO 213*4724848cSchristos && $extchnum != $chnum; 214*4724848cSchristos next if $extensions[$extloop][0] == TLSProxy::Message::MT_SERVER_HELLO 215*4724848cSchristos && $extshnum != $shnum; 216*4724848cSchristos next if ($message->mt() != $extensions[$extloop][0]); 217*4724848cSchristos next if ($message->server() != $extensions[$extloop][2]); 218*4724848cSchristos ok (($extensions[$extloop][3] & $exttype) == 0 219*4724848cSchristos || defined ($msgexts->{$extensions[$extloop][1]}), 220*4724848cSchristos "Extension presence check (Message: ".$message->mt() 221*4724848cSchristos ." Extension: ".($extensions[$extloop][3] & $exttype).", " 222*4724848cSchristos .$extloop.")"); 223*4724848cSchristos $extcount++ if (($extensions[$extloop][3] & $exttype) != 0); 224*4724848cSchristos } 225*4724848cSchristos ok($extcount == keys %$msgexts, "Extensions count mismatch (" 226*4724848cSchristos .$extcount.", ".(keys %$msgexts) 227*4724848cSchristos .")"); 228*4724848cSchristos } 229*4724848cSchristos } 230*4724848cSchristos} 231*4724848cSchristos 232*4724848cSchristos1; 233