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