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