]> git.ipfire.org Git - thirdparty/openssl.git/blame - test/recipes/70-test_sslrecords.t
Fail if an unrecognised record type is received
[thirdparty/openssl.git] / test / recipes / 70-test_sslrecords.t
CommitLineData
4f0c4757
MC
1#! /usr/bin/env perl
2# Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
3#
4# Licensed under the OpenSSL license (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
9use strict;
10use OpenSSL::Test qw/:DEFAULT cmdstr srctop_file bldtop_dir/;
11use OpenSSL::Test::Utils;
12use TLSProxy::Proxy;
13
14my $test_name = "test_sslrecords";
15setup($test_name);
16
17plan skip_all => "TLSProxy isn't usable on $^O"
18 if $^O =~ /^(VMS|MSWin32)$/;
19
20plan skip_all => "$test_name needs the dynamic engine feature enabled"
21 if disabled("engine") || disabled("dynamic-engine");
22
23plan skip_all => "$test_name needs the sock feature enabled"
24 if disabled("sock");
25
80f397e2
MC
26plan skip_all => "$test_name needs TLSv1.2 enabled"
27 if disabled("tls1_2");
4f0c4757
MC
28
29$ENV{OPENSSL_ia32cap} = '~0x200000200000000';
30my $proxy = TLSProxy::Proxy->new(
31 \&add_empty_recs_filter,
32 cmdstr(app(["openssl"]), display => 1),
33 srctop_file("apps", "server.pem"),
34 (!$ENV{HARNESS_ACTIVE} || $ENV{HARNESS_VERBOSE})
35);
36
4f0c4757
MC
37#Test 1: Injecting out of context empty records should fail
38my $content_type = TLSProxy::Record::RT_APPLICATION_DATA;
39my $inject_recs_num = 1;
837e591d 40$proxy->serverflags("-tls1_2");
b02b5743 41$proxy->start() or plan skip_all => "Unable to start up Proxy for tests";
a2a0c86b 42plan tests => 9;
4f0c4757
MC
43ok(TLSProxy::Message->fail(), "Out of context empty records test");
44
45#Test 2: Injecting in context empty records should succeed
46$proxy->clear();
47$content_type = TLSProxy::Record::RT_HANDSHAKE;
837e591d 48$proxy->serverflags("-tls1_2");
4f0c4757
MC
49$proxy->start();
50ok(TLSProxy::Message->success(), "In context empty records test");
51
52#Test 3: Injecting too many in context empty records should fail
53$proxy->clear();
54#We allow 32 consecutive in context empty records
55$inject_recs_num = 33;
837e591d 56$proxy->serverflags("-tls1_2");
4f0c4757
MC
57$proxy->start();
58ok(TLSProxy::Message->fail(), "Too many in context empty records test");
59
c3fd55d4
MC
60#Test 4: Injecting a fragmented fatal alert should fail. We actually expect no
61# alerts to be sent from either side because *we* injected the fatal
62# alert, i.e. this will look like a disorderly close
63$proxy->clear();
64$proxy->filter(\&add_frag_alert_filter);
837e591d 65$proxy->serverflags("-tls1_2");
c3fd55d4
MC
66$proxy->start();
67ok(!TLSProxy::Message->end(), "Fragmented alert records test");
68
a2a0c86b
MC
69#Run some SSLv2 ClientHello tests
70
71use constant {
72 TLSV1_2_IN_SSLV2 => 0,
73 SSLV2_IN_SSLV2 => 1,
74 FRAGMENTED_IN_TLSV1_2 => 2,
75 FRAGMENTED_IN_SSLV2 => 3,
76 ALERT_BEFORE_SSLV2 => 4
77};
78#Test 5: Inject an SSLv2 style record format for a TLSv1.2 ClientHello
a2a0c86b
MC
79my $sslv2testtype = TLSV1_2_IN_SSLV2;
80$proxy->clear();
81$proxy->filter(\&add_sslv2_filter);
837e591d 82$proxy->serverflags("-tls1_2");
a2a0c86b
MC
83$proxy->start();
84ok(TLSProxy::Message->success(), "TLSv1.2 in SSLv2 ClientHello test");
85
86#Test 6: Inject an SSLv2 style record format for an SSLv2 ClientHello. We don't
87# support this so it should fail. We actually treat it as an unknown
88# protocol so we don't even send an alert in this case.
89$sslv2testtype = SSLV2_IN_SSLV2;
90$proxy->clear();
837e591d 91$proxy->serverflags("-tls1_2");
a2a0c86b
MC
92$proxy->start();
93ok(!TLSProxy::Message->end(), "SSLv2 in SSLv2 ClientHello test");
94
95#Test 7: Sanity check ClientHello fragmentation. This isn't really an SSLv2 test
96# at all, but it gives us confidence that Test 8 fails for the right
97# reasons
98$sslv2testtype = FRAGMENTED_IN_TLSV1_2;
99$proxy->clear();
837e591d 100$proxy->serverflags("-tls1_2");
a2a0c86b
MC
101$proxy->start();
102ok(TLSProxy::Message->success(), "Fragmented ClientHello in TLSv1.2 test");
103
104#Test 8: Fragment a TLSv1.2 ClientHello across a TLS1.2 record; an SSLv2
105# record; and another TLS1.2 record. This isn't allowed so should fail
106$sslv2testtype = FRAGMENTED_IN_SSLV2;
107$proxy->clear();
837e591d 108$proxy->serverflags("-tls1_2");
a2a0c86b
MC
109$proxy->start();
110ok(TLSProxy::Message->fail(), "Fragmented ClientHello in TLSv1.2/SSLv2 test");
111
112#Test 9: Send a TLS warning alert before an SSLv2 ClientHello. This should
113# fail because an SSLv2 ClientHello must be the first record.
114$sslv2testtype = ALERT_BEFORE_SSLV2;
115$proxy->clear();
837e591d 116$proxy->serverflags("-tls1_2");
a2a0c86b
MC
117$proxy->start();
118ok(TLSProxy::Message->fail(), "Alert before SSLv2 ClientHello test");
4f0c4757
MC
119sub add_empty_recs_filter
120{
121 my $proxy = shift;
122
123 # We're only interested in the initial ClientHello
124 if ($proxy->flight != 0) {
125 return;
126 }
127
128 for (my $i = 0; $i < $inject_recs_num; $i++) {
129 my $record = TLSProxy::Record->new(
130 0,
131 $content_type,
132 TLSProxy::Record::VERS_TLS_1_2,
133 0,
134 0,
135 0,
a2a0c86b 136 0,
4f0c4757
MC
137 "",
138 ""
139 );
140
141 push @{$proxy->record_list}, $record;
142 }
143}
c3fd55d4
MC
144
145sub add_frag_alert_filter
146{
147 my $proxy = shift;
148 my $byte;
149
150 # We're only interested in the initial ClientHello
151 if ($proxy->flight != 0) {
152 return;
153 }
154
155 # Add a zero length fragment first
156 #my $record = TLSProxy::Record->new(
157 # 0,
158 # TLSProxy::Record::RT_ALERT,
159 # TLSProxy::Record::VERS_TLS_1_2,
160 # 0,
161 # 0,
162 # 0,
163 # "",
164 # ""
165 #);
166 #push @{$proxy->record_list}, $record;
167
60250017 168 # Now add the alert level (Fatal) as a separate record
c3fd55d4
MC
169 $byte = pack('C', TLSProxy::Message::AL_LEVEL_FATAL);
170 my $record = TLSProxy::Record->new(
171 0,
172 TLSProxy::Record::RT_ALERT,
173 TLSProxy::Record::VERS_TLS_1_2,
174 1,
a2a0c86b 175 0,
c3fd55d4
MC
176 1,
177 1,
178 $byte,
179 $byte
180 );
181 push @{$proxy->record_list}, $record;
182
183 # And finally the description (Unexpected message) in a third record
184 $byte = pack('C', TLSProxy::Message::AL_DESC_UNEXPECTED_MESSAGE);
185 $record = TLSProxy::Record->new(
186 0,
187 TLSProxy::Record::RT_ALERT,
188 TLSProxy::Record::VERS_TLS_1_2,
189 1,
a2a0c86b 190 0,
c3fd55d4
MC
191 1,
192 1,
193 $byte,
194 $byte
195 );
196 push @{$proxy->record_list}, $record;
197}
a2a0c86b
MC
198
199sub add_sslv2_filter
200{
201 my $proxy = shift;
202 my $clienthello;
203 my $record;
204
205 # We're only interested in the initial ClientHello
206 if ($proxy->flight != 0) {
207 return;
208 }
209
210 # Ditch the real ClientHello - we're going to replace it with our own
211 shift @{$proxy->record_list};
212
213 if ($sslv2testtype == ALERT_BEFORE_SSLV2) {
214 my $alert = pack('CC', TLSProxy::Message::AL_LEVEL_FATAL,
215 TLSProxy::Message::AL_DESC_NO_RENEGOTIATION);
216 my $alertlen = length $alert;
217 $record = TLSProxy::Record->new(
218 0,
219 TLSProxy::Record::RT_ALERT,
220 TLSProxy::Record::VERS_TLS_1_2,
221 $alertlen,
222 0,
223 $alertlen,
224 $alertlen,
225 $alert,
226 $alert
227 );
228
229 push @{$proxy->record_list}, $record;
230 }
231
232 if ($sslv2testtype == ALERT_BEFORE_SSLV2
233 || $sslv2testtype == TLSV1_2_IN_SSLV2
234 || $sslv2testtype == SSLV2_IN_SSLV2) {
235 # This is an SSLv2 format ClientHello
236 $clienthello =
237 pack "C44",
238 0x01, # ClientHello
239 0x03, 0x03, #TLSv1.2
240 0x00, 0x03, # Ciphersuites len
241 0x00, 0x00, # Session id len
242 0x00, 0x20, # Challenge len
243 0x00, 0x00, 0x2f, #AES128-SHA
244 0x01, 0x18, 0x9F, 0x76, 0xEC, 0x57, 0xCE, 0xE5, 0xB3, 0xAB, 0x79, 0x90,
245 0xAD, 0xAC, 0x6E, 0xD1, 0x58, 0x35, 0x03, 0x97, 0x16, 0x10, 0x82, 0x56,
246 0xD8, 0x55, 0xFF, 0xE1, 0x8A, 0xA3, 0x2E, 0xF6; # Challenge
247
248 if ($sslv2testtype == SSLV2_IN_SSLV2) {
249 # Set the version to "real" SSLv2
250 vec($clienthello, 1, 8) = 0x00;
251 vec($clienthello, 2, 8) = 0x02;
252 }
253
254 my $chlen = length $clienthello;
255
256 $record = TLSProxy::Record->new(
257 0,
258 TLSProxy::Record::RT_HANDSHAKE,
259 TLSProxy::Record::VERS_TLS_1_2,
260 $chlen,
261 1, #SSLv2
262 $chlen,
263 $chlen,
264 $clienthello,
265 $clienthello
266 );
267
268 push @{$proxy->record_list}, $record;
269 } else {
270 # For this test we're using a real TLS ClientHello
271 $clienthello =
272 pack "C49",
273 0x01, # ClientHello
274 0x00, 0x00, 0x2D, # Message length
275 0x03, 0x03, # TLSv1.2
276 0x01, 0x18, 0x9F, 0x76, 0xEC, 0x57, 0xCE, 0xE5, 0xB3, 0xAB, 0x79, 0x90,
277 0xAD, 0xAC, 0x6E, 0xD1, 0x58, 0x35, 0x03, 0x97, 0x16, 0x10, 0x82, 0x56,
278 0xD8, 0x55, 0xFF, 0xE1, 0x8A, 0xA3, 0x2E, 0xF6, # Random
279 0x00, # Session id len
280 0x00, 0x04, # Ciphersuites len
281 0x00, 0x2f, # AES128-SHA
282 0x00, 0xff, # Empty reneg info SCSV
283 0x01, # Compression methods len
284 0x00, # Null compression
285 0x00, 0x00; # Extensions len
286
287 # Split this into 3: A TLS record; a SSLv2 record and a TLS record.
288 # We deliberately split the second record prior to the Challenge/Random
289 # and set the first byte of the random to 1. This makes the second SSLv2
290 # record look like an SSLv2 ClientHello
291 my $frag1 = substr $clienthello, 0, 6;
292 my $frag2 = substr $clienthello, 6, 32;
293 my $frag3 = substr $clienthello, 38;
294
295 my $fraglen = length $frag1;
296 $record = TLSProxy::Record->new(
297 0,
298 TLSProxy::Record::RT_HANDSHAKE,
299 TLSProxy::Record::VERS_TLS_1_2,
300 $fraglen,
301 0,
302 $fraglen,
303 $fraglen,
304 $frag1,
305 $frag1
306 );
307 push @{$proxy->record_list}, $record;
308
309 $fraglen = length $frag2;
310 my $recvers;
311 if ($sslv2testtype == FRAGMENTED_IN_SSLV2) {
312 $recvers = 1;
313 } else {
314 $recvers = 0;
315 }
316 $record = TLSProxy::Record->new(
317 0,
318 TLSProxy::Record::RT_HANDSHAKE,
319 TLSProxy::Record::VERS_TLS_1_2,
320 $fraglen,
321 $recvers,
322 $fraglen,
323 $fraglen,
324 $frag2,
325 $frag2
326 );
327 push @{$proxy->record_list}, $record;
328
329 $fraglen = length $frag3;
330 $record = TLSProxy::Record->new(
331 0,
332 TLSProxy::Record::RT_HANDSHAKE,
333 TLSProxy::Record::VERS_TLS_1_2,
334 $fraglen,
335 0,
336 $fraglen,
337 $fraglen,
338 $frag3,
339 $frag3
340 );
341 push @{$proxy->record_list}, $record;
342 }
343
344}