113d40330Schristos#! /usr/bin/env perl 2*b0d17251Schristos# Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved. 313d40330Schristos# 4*b0d17251Schristos# Licensed under the Apache License 2.0 (the "License"). You may not use 513d40330Schristos# this file except in compliance with the License. You can obtain a copy 613d40330Schristos# in the file LICENSE in the source distribution or at 713d40330Schristos# https://www.openssl.org/source/license.html 813d40330Schristos 913d40330Schristospackage checkhandshake; 1013d40330Schristos 1113d40330Schristosuse OpenSSL::Test qw/:DEFAULT cmdstr srctop_file srctop_dir bldtop_dir/; 1213d40330Schristosuse OpenSSL::Test::Utils; 1313d40330Schristosuse TLSProxy::Proxy; 1413d40330Schristos 1513d40330Schristosuse Exporter; 1613d40330Schristosour @ISA = 'Exporter'; 1713d40330Schristosour @EXPORT = qw(@handmessages @extensions checkhandshake); 1813d40330Schristos 1913d40330Schristosuse constant { 2013d40330Schristos DEFAULT_HANDSHAKE => 1, 2113d40330Schristos OCSP_HANDSHAKE => 2, 2213d40330Schristos RESUME_HANDSHAKE => 4, 2313d40330Schristos CLIENT_AUTH_HANDSHAKE => 8, 2413d40330Schristos RENEG_HANDSHAKE => 16, 2513d40330Schristos NPN_HANDSHAKE => 32, 2613d40330Schristos EC_HANDSHAKE => 64, 2713d40330Schristos HRR_HANDSHAKE => 128, 2813d40330Schristos HRR_RESUME_HANDSHAKE => 256, 2913d40330Schristos 3013d40330Schristos ALL_HANDSHAKES => 511 3113d40330Schristos}; 3213d40330Schristos 3313d40330Schristosuse constant { 3413d40330Schristos #DEFAULT also includes SESSION_TICKET_SRV_EXTENSION and SERVER_NAME_CLI 3513d40330Schristos DEFAULT_EXTENSIONS => 0x00000007, 3613d40330Schristos SESSION_TICKET_SRV_EXTENSION => 0x00000002, 3713d40330Schristos SERVER_NAME_CLI_EXTENSION => 0x00000004, 3813d40330Schristos SERVER_NAME_SRV_EXTENSION => 0x00000008, 3913d40330Schristos STATUS_REQUEST_CLI_EXTENSION => 0x00000010, 4013d40330Schristos STATUS_REQUEST_SRV_EXTENSION => 0x00000020, 4113d40330Schristos ALPN_CLI_EXTENSION => 0x00000040, 4213d40330Schristos ALPN_SRV_EXTENSION => 0x00000080, 4313d40330Schristos SCT_CLI_EXTENSION => 0x00000100, 4413d40330Schristos SCT_SRV_EXTENSION => 0x00000200, 4513d40330Schristos RENEGOTIATE_CLI_EXTENSION => 0x00000400, 4613d40330Schristos NPN_CLI_EXTENSION => 0x00000800, 4713d40330Schristos NPN_SRV_EXTENSION => 0x00001000, 4813d40330Schristos SRP_CLI_EXTENSION => 0x00002000, 4913d40330Schristos #Client side for ec point formats is a default extension 5013d40330Schristos EC_POINT_FORMAT_SRV_EXTENSION => 0x00004000, 5113d40330Schristos PSK_CLI_EXTENSION => 0x00008000, 5213d40330Schristos PSK_SRV_EXTENSION => 0x00010000, 5313d40330Schristos KEY_SHARE_SRV_EXTENSION => 0x00020000, 5413d40330Schristos PSK_KEX_MODES_EXTENSION => 0x00040000, 5513d40330Schristos KEY_SHARE_HRR_EXTENSION => 0x00080000, 5613d40330Schristos SUPPORTED_GROUPS_SRV_EXTENSION => 0x00100000, 5713d40330Schristos POST_HANDSHAKE_AUTH_CLI_EXTENSION => 0x00200000 5813d40330Schristos}; 5913d40330Schristos 6013d40330Schristosour @handmessages = (); 6113d40330Schristosour @extensions = (); 6213d40330Schristos 6313d40330Schristossub checkhandshake($$$$) 6413d40330Schristos{ 6513d40330Schristos my ($proxy, $handtype, $exttype, $testname) = @_; 6613d40330Schristos 6713d40330Schristos subtest $testname => sub { 6813d40330Schristos my $loop = 0; 6913d40330Schristos my $numtests; 7013d40330Schristos my $extcount; 7113d40330Schristos my $clienthelloseen = 0; 7213d40330Schristos 7313d40330Schristos my $lastmt = 0; 7413d40330Schristos my $numsh = 0; 7513d40330Schristos if (TLSProxy::Proxy::is_tls13()) { 7613d40330Schristos #How many ServerHellos are we expecting? 7713d40330Schristos for ($numtests = 0; $handmessages[$loop][1] != 0; $loop++) { 7813d40330Schristos next if (($handmessages[$loop][1] & $handtype) == 0); 7913d40330Schristos $numsh++ if ($lastmt != TLSProxy::Message::MT_SERVER_HELLO 8013d40330Schristos && $handmessages[$loop][0] == TLSProxy::Message::MT_SERVER_HELLO); 8113d40330Schristos $lastmt = $handmessages[$loop][0]; 8213d40330Schristos } 8313d40330Schristos } 8413d40330Schristos 8513d40330Schristos #First count the number of tests 8613d40330Schristos my $nextmess = 0; 8713d40330Schristos my $message = undef; 8813d40330Schristos my $chnum = 0; 8913d40330Schristos my $shnum = 0; 9013d40330Schristos if (!TLSProxy::Proxy::is_tls13()) { 9113d40330Schristos # In non-TLSv1.3 we always treat reneg CH and SH like the first CH 9213d40330Schristos # and SH 9313d40330Schristos $chnum = 1; 9413d40330Schristos $shnum = 1; 9513d40330Schristos } 9613d40330Schristos #If we're only expecting one ServerHello out of two then we skip the 9713d40330Schristos #first ServerHello in the list completely 9813d40330Schristos $shnum++ if ($numsh == 1 && TLSProxy::Proxy::is_tls13()); 9913d40330Schristos $loop = 0; 10013d40330Schristos for ($numtests = 0; $handmessages[$loop][1] != 0; $loop++) { 10113d40330Schristos next if (($handmessages[$loop][1] & $handtype) == 0); 10213d40330Schristos if (scalar @{$proxy->message_list} > $nextmess) { 10313d40330Schristos $message = ${$proxy->message_list}[$nextmess]; 10413d40330Schristos $nextmess++; 10513d40330Schristos } else { 10613d40330Schristos $message = undef; 10713d40330Schristos } 10813d40330Schristos $numtests++; 10913d40330Schristos 11013d40330Schristos next if (!defined $message); 11113d40330Schristos if (TLSProxy::Proxy::is_tls13()) { 11213d40330Schristos $chnum++ if $message->mt() == TLSProxy::Message::MT_CLIENT_HELLO; 11313d40330Schristos $shnum++ if $message->mt() == TLSProxy::Message::MT_SERVER_HELLO; 11413d40330Schristos } 11513d40330Schristos next if ($message->mt() != TLSProxy::Message::MT_CLIENT_HELLO 11613d40330Schristos && $message->mt() != TLSProxy::Message::MT_SERVER_HELLO 11713d40330Schristos && $message->mt() != 11813d40330Schristos TLSProxy::Message::MT_ENCRYPTED_EXTENSIONS 1194ce06407Schristos && $message->mt() != TLSProxy::Message::MT_CERTIFICATE 1204ce06407Schristos && $message->mt() != TLSProxy::Message::MT_CERTIFICATE_REQUEST); 12113d40330Schristos 12213d40330Schristos next if $message->mt() == TLSProxy::Message::MT_CERTIFICATE 12313d40330Schristos && !TLSProxy::Proxy::is_tls13(); 12413d40330Schristos 12513d40330Schristos my $extchnum = 1; 12613d40330Schristos my $extshnum = 1; 12713d40330Schristos for (my $extloop = 0; 1284ce06407Schristos $extensions[$extloop][3] != 0; 12913d40330Schristos $extloop++) { 13013d40330Schristos $extchnum = 2 if $extensions[$extloop][0] != TLSProxy::Message::MT_CLIENT_HELLO 13113d40330Schristos && TLSProxy::Proxy::is_tls13(); 13213d40330Schristos $extshnum = 2 if $extensions[$extloop][0] != TLSProxy::Message::MT_SERVER_HELLO 13313d40330Schristos && $extchnum == 2; 13413d40330Schristos next if $extensions[$extloop][0] == TLSProxy::Message::MT_CLIENT_HELLO 13513d40330Schristos && $extchnum != $chnum; 13613d40330Schristos next if $extensions[$extloop][0] == TLSProxy::Message::MT_SERVER_HELLO 13713d40330Schristos && $extshnum != $shnum; 13813d40330Schristos next if ($message->mt() != $extensions[$extloop][0]); 1394ce06407Schristos next if ($message->server() != $extensions[$extloop][2]); 14013d40330Schristos $numtests++; 14113d40330Schristos } 14213d40330Schristos $numtests++; 14313d40330Schristos } 14413d40330Schristos 14513d40330Schristos plan tests => $numtests; 14613d40330Schristos 14713d40330Schristos $nextmess = 0; 14813d40330Schristos $message = undef; 14913d40330Schristos if (TLSProxy::Proxy::is_tls13()) { 15013d40330Schristos $chnum = 0; 15113d40330Schristos $shnum = 0; 15213d40330Schristos } else { 15313d40330Schristos # In non-TLSv1.3 we always treat reneg CH and SH like the first CH 15413d40330Schristos # and SH 15513d40330Schristos $chnum = 1; 15613d40330Schristos $shnum = 1; 15713d40330Schristos } 15813d40330Schristos #If we're only expecting one ServerHello out of two then we skip the 15913d40330Schristos #first ServerHello in the list completely 16013d40330Schristos $shnum++ if ($numsh == 1 && TLSProxy::Proxy::is_tls13()); 16113d40330Schristos for ($loop = 0; $handmessages[$loop][1] != 0; $loop++) { 16213d40330Schristos next if (($handmessages[$loop][1] & $handtype) == 0); 16313d40330Schristos if (scalar @{$proxy->message_list} > $nextmess) { 16413d40330Schristos $message = ${$proxy->message_list}[$nextmess]; 16513d40330Schristos $nextmess++; 16613d40330Schristos } else { 16713d40330Schristos $message = undef; 16813d40330Schristos } 16913d40330Schristos if (!defined $message) { 17013d40330Schristos fail("Message type check. Got nothing, expected " 17113d40330Schristos .$handmessages[$loop][0]); 17213d40330Schristos next; 17313d40330Schristos } else { 17413d40330Schristos ok($message->mt == $handmessages[$loop][0], 17513d40330Schristos "Message type check. Got ".$message->mt 17613d40330Schristos .", expected ".$handmessages[$loop][0]); 17713d40330Schristos } 17813d40330Schristos if (TLSProxy::Proxy::is_tls13()) { 17913d40330Schristos $chnum++ if $message->mt() == TLSProxy::Message::MT_CLIENT_HELLO; 18013d40330Schristos $shnum++ if $message->mt() == TLSProxy::Message::MT_SERVER_HELLO; 18113d40330Schristos } 18213d40330Schristos 18313d40330Schristos next if ($message->mt() != TLSProxy::Message::MT_CLIENT_HELLO 18413d40330Schristos && $message->mt() != TLSProxy::Message::MT_SERVER_HELLO 18513d40330Schristos && $message->mt() != 18613d40330Schristos TLSProxy::Message::MT_ENCRYPTED_EXTENSIONS 1874ce06407Schristos && $message->mt() != TLSProxy::Message::MT_CERTIFICATE 1884ce06407Schristos && $message->mt() != TLSProxy::Message::MT_CERTIFICATE_REQUEST); 18913d40330Schristos 19013d40330Schristos next if $message->mt() == TLSProxy::Message::MT_CERTIFICATE 19113d40330Schristos && !TLSProxy::Proxy::is_tls13(); 19213d40330Schristos 19313d40330Schristos if ($message->mt() == TLSProxy::Message::MT_CLIENT_HELLO) { 19413d40330Schristos #Add renegotiate extension we will expect if renegotiating 19513d40330Schristos $exttype |= RENEGOTIATE_CLI_EXTENSION 19613d40330Schristos if ($clienthelloseen && !TLSProxy::Proxy::is_tls13()); 19713d40330Schristos $clienthelloseen = 1; 19813d40330Schristos } 19913d40330Schristos #Now check that we saw the extensions we expected 20013d40330Schristos my $msgexts = $message->extension_data(); 20113d40330Schristos my $extchnum = 1; 20213d40330Schristos my $extshnum = 1; 2034ce06407Schristos for (my $extloop = 0, $extcount = 0; $extensions[$extloop][3] != 0; 20413d40330Schristos $extloop++) { 20513d40330Schristos #In TLSv1.3 we can have two ClientHellos if there has been a 20613d40330Schristos #HelloRetryRequest, and they may have different extensions. Skip 20713d40330Schristos #if these are extensions for a different ClientHello 20813d40330Schristos $extchnum = 2 if $extensions[$extloop][0] != TLSProxy::Message::MT_CLIENT_HELLO 20913d40330Schristos && TLSProxy::Proxy::is_tls13(); 21013d40330Schristos $extshnum = 2 if $extensions[$extloop][0] != TLSProxy::Message::MT_SERVER_HELLO 21113d40330Schristos && $extchnum == 2; 21213d40330Schristos next if $extensions[$extloop][0] == TLSProxy::Message::MT_CLIENT_HELLO 21313d40330Schristos && $extchnum != $chnum; 21413d40330Schristos next if $extensions[$extloop][0] == TLSProxy::Message::MT_SERVER_HELLO 21513d40330Schristos && $extshnum != $shnum; 21613d40330Schristos next if ($message->mt() != $extensions[$extloop][0]); 2174ce06407Schristos next if ($message->server() != $extensions[$extloop][2]); 2184ce06407Schristos ok (($extensions[$extloop][3] & $exttype) == 0 21913d40330Schristos || defined ($msgexts->{$extensions[$extloop][1]}), 22013d40330Schristos "Extension presence check (Message: ".$message->mt() 2214ce06407Schristos ." Extension: ".($extensions[$extloop][3] & $exttype).", " 22213d40330Schristos .$extloop.")"); 2234ce06407Schristos $extcount++ if (($extensions[$extloop][3] & $exttype) != 0); 22413d40330Schristos } 22513d40330Schristos ok($extcount == keys %$msgexts, "Extensions count mismatch (" 22613d40330Schristos .$extcount.", ".(keys %$msgexts) 22713d40330Schristos .")"); 22813d40330Schristos } 22913d40330Schristos } 23013d40330Schristos} 23113d40330Schristos 23213d40330Schristos1; 233