Added an explicit yield (OP_SLEEP) to QUIC testing for cooperative threading.
[openssl.git] / util / perl / checkhandshake.pm
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     CERT_COMP_SRV_HANDSHAKE => 512,
30     CERT_COMP_CLI_HANDSHAKE => 1024,
31     CERT_COMP_BOTH_HANDSHAKE => 2048,
32
33     ALL_HANDSHAKES => 4095
34 };
35
36 use 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
65 our @handmessages = ();
66 our @extensions = ();
67
68 sub 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
237 1;