xref: /netbsd-src/crypto/external/bsd/openssl/dist/util/perl/checkhandshake.pm (revision b0d1725196a7921d003d2c66a14f186abda4176b)
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