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