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