]> git.ipfire.org Git - thirdparty/openssl.git/blob - test/recipes/70-test_sslrecords.t
Update copyright year
[thirdparty/openssl.git] / test / recipes / 70-test_sslrecords.t
1 #! /usr/bin/env perl
2 # Copyright 2016-2022 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 use strict;
10 use feature 'state';
11
12 use OpenSSL::Test qw/:DEFAULT cmdstr srctop_file bldtop_dir/;
13 use OpenSSL::Test::Utils;
14 use TLSProxy::Proxy;
15
16 my $test_name = "test_sslrecords";
17 setup($test_name);
18
19 plan skip_all => "TLSProxy isn't usable on $^O"
20 if $^O =~ /^(VMS)$/;
21
22 plan skip_all => "$test_name needs the dynamic engine feature enabled"
23 if disabled("engine") || disabled("dynamic-engine");
24
25 plan skip_all => "$test_name needs the sock feature enabled"
26 if disabled("sock");
27
28 plan skip_all => "$test_name needs TLSv1.2 enabled"
29 if disabled("tls1_2");
30
31 my $proxy = TLSProxy::Proxy->new(
32 \&add_empty_recs_filter,
33 cmdstr(app(["openssl"]), display => 1),
34 srctop_file("apps", "server.pem"),
35 (!$ENV{HARNESS_ACTIVE} || $ENV{HARNESS_VERBOSE})
36 );
37
38 my $boundary_test_type;
39 my $fatal_alert = 0; # set by filters at expected fatal alerts
40
41 #Test 1: Injecting out of context empty records should fail
42 my $content_type = TLSProxy::Record::RT_APPLICATION_DATA;
43 my $inject_recs_num = 1;
44 $proxy->serverflags("-tls1_2");
45 $proxy->clientflags("-no_tls1_3");
46 $proxy->start() or plan skip_all => "Unable to start up Proxy for tests";
47 plan tests => 20;
48 ok($fatal_alert, "Out of context empty records test");
49
50 #Test 2: Injecting in context empty records should succeed
51 $proxy->clear();
52 $content_type = TLSProxy::Record::RT_HANDSHAKE;
53 $proxy->serverflags("-tls1_2");
54 $proxy->clientflags("-no_tls1_3");
55 $proxy->start();
56 ok(TLSProxy::Message->success(), "In context empty records test");
57
58 #Test 3: Injecting too many in context empty records should fail
59 $fatal_alert = 0;
60 $proxy->clear();
61 #We allow 32 consecutive in context empty records
62 $inject_recs_num = 33;
63 $proxy->serverflags("-tls1_2");
64 $proxy->clientflags("-no_tls1_3");
65 $proxy->start();
66 ok($fatal_alert, "Too many in context empty records test");
67
68 #Test 4: Injecting a fragmented fatal alert should fail. We expect the server to
69 # send back an alert of its own because it cannot handle fragmented
70 # alerts
71 $fatal_alert = 0;
72 $proxy->clear();
73 $proxy->filter(\&add_frag_alert_filter);
74 $proxy->serverflags("-tls1_2");
75 $proxy->clientflags("-no_tls1_3");
76 $proxy->start();
77 ok($fatal_alert, "Fragmented alert records test");
78
79 #Run some SSLv2 ClientHello tests
80
81 use constant {
82 TLSV1_2_IN_SSLV2 => 0,
83 SSLV2_IN_SSLV2 => 1,
84 FRAGMENTED_IN_TLSV1_2 => 2,
85 FRAGMENTED_IN_SSLV2 => 3,
86 ALERT_BEFORE_SSLV2 => 4
87 };
88
89 # The TLSv1.2 in SSLv2 ClientHello need to run at security level 0
90 # because in a SSLv2 ClientHello we can't send extensions to indicate
91 # which signature algorithm we want to use, and the default is SHA1.
92
93 #Test 5: Inject an SSLv2 style record format for a TLSv1.2 ClientHello
94 my $sslv2testtype = TLSV1_2_IN_SSLV2;
95 $proxy->clear();
96 $proxy->filter(\&add_sslv2_filter);
97 $proxy->serverflags("-tls1_2");
98 $proxy->clientflags("-no_tls1_3 -legacy_renegotiation");
99 $proxy->ciphers("AES128-SHA:\@SECLEVEL=0");
100 $proxy->start();
101 ok(TLSProxy::Message->success(), "TLSv1.2 in SSLv2 ClientHello test");
102
103 #Test 6: Inject an SSLv2 style record format for an SSLv2 ClientHello. We don't
104 # support this so it should fail. We actually treat it as an unknown
105 # protocol so we don't even send an alert in this case.
106 $sslv2testtype = SSLV2_IN_SSLV2;
107 $proxy->clear();
108 $proxy->serverflags("-tls1_2");
109 $proxy->clientflags("-no_tls1_3");
110 $proxy->ciphers("AES128-SHA:\@SECLEVEL=0");
111 $proxy->start();
112 ok(TLSProxy::Message->fail(), "SSLv2 in SSLv2 ClientHello test");
113
114 #Test 7: Sanity check ClientHello fragmentation. This isn't really an SSLv2 test
115 # at all, but it gives us confidence that Test 8 fails for the right
116 # reasons
117 $sslv2testtype = FRAGMENTED_IN_TLSV1_2;
118 $proxy->clear();
119 $proxy->serverflags("-tls1_2");
120 $proxy->clientflags("-no_tls1_3");
121 $proxy->ciphers("AES128-SHA:\@SECLEVEL=0");
122 $proxy->start();
123 ok(TLSProxy::Message->success(), "Fragmented ClientHello in TLSv1.2 test");
124
125 #Test 8: Fragment a TLSv1.2 ClientHello across a TLS1.2 record; an SSLv2
126 # record; and another TLS1.2 record. This isn't allowed so should fail
127 $sslv2testtype = FRAGMENTED_IN_SSLV2;
128 $proxy->clear();
129 $proxy->serverflags("-tls1_2");
130 $proxy->clientflags("-no_tls1_3");
131 $proxy->ciphers("AES128-SHA:\@SECLEVEL=0");
132 $proxy->start();
133 ok(TLSProxy::Message->fail(), "Fragmented ClientHello in TLSv1.2/SSLv2 test");
134
135 #Test 9: Send a TLS warning alert before an SSLv2 ClientHello. This should
136 # fail because an SSLv2 ClientHello must be the first record.
137 $sslv2testtype = ALERT_BEFORE_SSLV2;
138 $proxy->clear();
139 $proxy->serverflags("-tls1_2");
140 $proxy->clientflags("-no_tls1_3");
141 $proxy->ciphers("AES128-SHA:\@SECLEVEL=0");
142 $proxy->start();
143 ok(TLSProxy::Message->fail(), "Alert before SSLv2 ClientHello test");
144
145 #Unrecognised record type tests
146
147 #Test 10: Sending an unrecognised record type in TLS1.2 should fail
148 $fatal_alert = 0;
149 $proxy->clear();
150 $proxy->serverflags("-tls1_2");
151 $proxy->clientflags("-no_tls1_3");
152 $proxy->filter(\&add_unknown_record_type);
153 $proxy->start();
154 ok($fatal_alert, "Unrecognised record type in TLS1.2");
155
156 SKIP: {
157 skip "TLSv1.1 disabled", 1 if disabled("tls1_1");
158
159 #Test 11: Sending an unrecognised record type in TLS1.1 should fail
160 $fatal_alert = 0;
161 $proxy->clear();
162 $proxy->clientflags("-tls1_1 -cipher DEFAULT:\@SECLEVEL=0");
163 $proxy->ciphers("AES128-SHA:\@SECLEVEL=0");
164 $proxy->start();
165 ok($fatal_alert, "Unrecognised record type in TLS1.1");
166 }
167
168 #Test 12: Sending a different record version in TLS1.2 should fail
169 $fatal_alert = 0;
170 $proxy->clear();
171 $proxy->clientflags("-tls1_2");
172 $proxy->filter(\&change_version);
173 $proxy->start();
174 ok($fatal_alert, "Changed record version in TLS1.2");
175
176 #TLS1.3 specific tests
177 SKIP: {
178 skip "TLSv1.3 disabled", 8
179 if disabled("tls1_3") || (disabled("ec") && disabled("dh"));
180
181 #Test 13: Sending a different record version in TLS1.3 should fail
182 $proxy->clear();
183 $proxy->filter(\&change_version);
184 $proxy->start();
185 ok(TLSProxy::Message->fail(), "Changed record version in TLS1.3");
186
187 #Test 14: Sending an unrecognised record type in TLS1.3 should fail
188 $fatal_alert = 0;
189 $proxy->clear();
190 $proxy->filter(\&add_unknown_record_type);
191 $proxy->start();
192 ok($fatal_alert, "Unrecognised record type in TLS1.3");
193
194 #Test 15: Sending an outer record type other than app data once encrypted
195 #should fail
196 $fatal_alert = 0;
197 $proxy->clear();
198 $proxy->filter(\&change_outer_record_type);
199 $proxy->start();
200 ok($fatal_alert, "Wrong outer record type in TLS1.3");
201
202 use constant {
203 DATA_AFTER_SERVER_HELLO => 0,
204 DATA_AFTER_FINISHED => 1,
205 DATA_AFTER_KEY_UPDATE => 2,
206 DATA_BETWEEN_KEY_UPDATE => 3,
207 NO_DATA_BETWEEN_KEY_UPDATE => 4,
208 };
209
210 #Test 16: Sending a ServerHello which doesn't end on a record boundary
211 # should fail
212 $fatal_alert = 0;
213 $proxy->clear();
214 $boundary_test_type = DATA_AFTER_SERVER_HELLO;
215 $proxy->filter(\&not_on_record_boundary);
216 $proxy->start();
217 ok($fatal_alert, "Record not on boundary in TLS1.3 (ServerHello)");
218
219 #Test 17: Sending a Finished which doesn't end on a record boundary
220 # should fail
221 $fatal_alert = 0;
222 $proxy->clear();
223 $boundary_test_type = DATA_AFTER_FINISHED;
224 $proxy->start();
225 ok($fatal_alert, "Record not on boundary in TLS1.3 (Finished)");
226
227 #Test 18: Sending a KeyUpdate which doesn't end on a record boundary
228 # should fail
229 $fatal_alert = 0;
230 $proxy->clear();
231 $boundary_test_type = DATA_AFTER_KEY_UPDATE;
232 $proxy->start();
233 ok($fatal_alert, "Record not on boundary in TLS1.3 (KeyUpdate)");
234
235 #Test 19: Sending application data in the middle of a fragmented KeyUpdate
236 # should fail. Strictly speaking this is not a record boundary test
237 # but we use the same filter.
238 $fatal_alert = 0;
239 $proxy->clear();
240 $boundary_test_type = DATA_BETWEEN_KEY_UPDATE;
241 $proxy->start();
242 ok($fatal_alert, "Data between KeyUpdate");
243
244 #Test 20: Fragmented KeyUpdate. This should succeed. Strictly speaking this
245 # is not a record boundary test but we use the same filter.
246 $proxy->clear();
247 $boundary_test_type = NO_DATA_BETWEEN_KEY_UPDATE;
248 $proxy->start();
249 ok(TLSProxy::Message->success(), "No data between KeyUpdate");
250 }
251
252
253 sub add_empty_recs_filter
254 {
255 my $proxy = shift;
256 my $records = $proxy->record_list;
257
258 # We're only interested in the initial ClientHello
259 if ($proxy->flight != 0) {
260 $fatal_alert = 1 if @{$records}[-1]->is_fatal_alert(1) == 10;
261 return;
262 }
263
264 for (my $i = 0; $i < $inject_recs_num; $i++) {
265 my $record = TLSProxy::Record->new(
266 0,
267 $content_type,
268 TLSProxy::Record::VERS_TLS_1_2,
269 0,
270 0,
271 0,
272 0,
273 "",
274 ""
275 );
276 push @{$records}, $record;
277 }
278 }
279
280 sub add_frag_alert_filter
281 {
282 my $proxy = shift;
283 my $records = $proxy->record_list;
284 my $byte;
285
286 # We're only interested in the initial ClientHello
287 if ($proxy->flight != 0) {
288 $fatal_alert = 1 if @{$records}[-1]->is_fatal_alert(1) == 10;
289 return;
290 }
291
292 # Add a zero length fragment first
293 #my $record = TLSProxy::Record->new(
294 # 0,
295 # TLSProxy::Record::RT_ALERT,
296 # TLSProxy::Record::VERS_TLS_1_2,
297 # 0,
298 # 0,
299 # 0,
300 # "",
301 # ""
302 #);
303 #push @{$proxy->record_list}, $record;
304
305 # Now add the alert level (Fatal) as a separate record
306 $byte = pack('C', TLSProxy::Message::AL_LEVEL_FATAL);
307 my $record = TLSProxy::Record->new(
308 0,
309 TLSProxy::Record::RT_ALERT,
310 TLSProxy::Record::VERS_TLS_1_2,
311 1,
312 0,
313 1,
314 1,
315 $byte,
316 $byte
317 );
318 push @{$records}, $record;
319
320 # And finally the description (Unexpected message) in a third record
321 $byte = pack('C', TLSProxy::Message::AL_DESC_UNEXPECTED_MESSAGE);
322 $record = TLSProxy::Record->new(
323 0,
324 TLSProxy::Record::RT_ALERT,
325 TLSProxy::Record::VERS_TLS_1_2,
326 1,
327 0,
328 1,
329 1,
330 $byte,
331 $byte
332 );
333 push @{$records}, $record;
334 }
335
336 sub add_sslv2_filter
337 {
338 my $proxy = shift;
339 my $clienthello;
340 my $record;
341
342 # We're only interested in the initial ClientHello
343 if ($proxy->flight != 0) {
344 return;
345 }
346
347 # Ditch the real ClientHello - we're going to replace it with our own
348 shift @{$proxy->record_list};
349
350 if ($sslv2testtype == ALERT_BEFORE_SSLV2) {
351 my $alert = pack('CC', TLSProxy::Message::AL_LEVEL_FATAL,
352 TLSProxy::Message::AL_DESC_NO_RENEGOTIATION);
353 my $alertlen = length $alert;
354 $record = TLSProxy::Record->new(
355 0,
356 TLSProxy::Record::RT_ALERT,
357 TLSProxy::Record::VERS_TLS_1_2,
358 $alertlen,
359 0,
360 $alertlen,
361 $alertlen,
362 $alert,
363 $alert
364 );
365
366 push @{$proxy->record_list}, $record;
367 }
368
369 if ($sslv2testtype == ALERT_BEFORE_SSLV2
370 || $sslv2testtype == TLSV1_2_IN_SSLV2
371 || $sslv2testtype == SSLV2_IN_SSLV2) {
372 # This is an SSLv2 format ClientHello
373 $clienthello =
374 pack "C44",
375 0x01, # ClientHello
376 0x03, 0x03, #TLSv1.2
377 0x00, 0x03, # Ciphersuites len
378 0x00, 0x00, # Session id len
379 0x00, 0x20, # Challenge len
380 0x00, 0x00, 0x2f, #AES128-SHA
381 0x01, 0x18, 0x9F, 0x76, 0xEC, 0x57, 0xCE, 0xE5, 0xB3, 0xAB, 0x79, 0x90,
382 0xAD, 0xAC, 0x6E, 0xD1, 0x58, 0x35, 0x03, 0x97, 0x16, 0x10, 0x82, 0x56,
383 0xD8, 0x55, 0xFF, 0xE1, 0x8A, 0xA3, 0x2E, 0xF6; # Challenge
384
385 if ($sslv2testtype == SSLV2_IN_SSLV2) {
386 # Set the version to "real" SSLv2
387 vec($clienthello, 1, 8) = 0x00;
388 vec($clienthello, 2, 8) = 0x02;
389 }
390
391 my $chlen = length $clienthello;
392
393 $record = TLSProxy::Record->new(
394 0,
395 TLSProxy::Record::RT_HANDSHAKE,
396 TLSProxy::Record::VERS_TLS_1_2,
397 $chlen,
398 1, #SSLv2
399 $chlen,
400 $chlen,
401 $clienthello,
402 $clienthello
403 );
404
405 push @{$proxy->record_list}, $record;
406 } else {
407 # For this test we're using a real TLS ClientHello
408 $clienthello =
409 pack "C49",
410 0x01, # ClientHello
411 0x00, 0x00, 0x2D, # Message length
412 0x03, 0x03, # TLSv1.2
413 0x01, 0x18, 0x9F, 0x76, 0xEC, 0x57, 0xCE, 0xE5, 0xB3, 0xAB, 0x79, 0x90,
414 0xAD, 0xAC, 0x6E, 0xD1, 0x58, 0x35, 0x03, 0x97, 0x16, 0x10, 0x82, 0x56,
415 0xD8, 0x55, 0xFF, 0xE1, 0x8A, 0xA3, 0x2E, 0xF6, # Random
416 0x00, # Session id len
417 0x00, 0x04, # Ciphersuites len
418 0x00, 0x2f, # AES128-SHA
419 0x00, 0xff, # Empty reneg info SCSV
420 0x01, # Compression methods len
421 0x00, # Null compression
422 0x00, 0x00; # Extensions len
423
424 # Split this into 3: A TLS record; a SSLv2 record and a TLS record.
425 # We deliberately split the second record prior to the Challenge/Random
426 # and set the first byte of the random to 1. This makes the second SSLv2
427 # record look like an SSLv2 ClientHello
428 my $frag1 = substr $clienthello, 0, 6;
429 my $frag2 = substr $clienthello, 6, 32;
430 my $frag3 = substr $clienthello, 38;
431
432 my $fraglen = length $frag1;
433 $record = TLSProxy::Record->new(
434 0,
435 TLSProxy::Record::RT_HANDSHAKE,
436 TLSProxy::Record::VERS_TLS_1_2,
437 $fraglen,
438 0,
439 $fraglen,
440 $fraglen,
441 $frag1,
442 $frag1
443 );
444 push @{$proxy->record_list}, $record;
445
446 $fraglen = length $frag2;
447 my $recvers;
448 if ($sslv2testtype == FRAGMENTED_IN_SSLV2) {
449 $recvers = 1;
450 } else {
451 $recvers = 0;
452 }
453 $record = TLSProxy::Record->new(
454 0,
455 TLSProxy::Record::RT_HANDSHAKE,
456 TLSProxy::Record::VERS_TLS_1_2,
457 $fraglen,
458 $recvers,
459 $fraglen,
460 $fraglen,
461 $frag2,
462 $frag2
463 );
464 push @{$proxy->record_list}, $record;
465
466 $fraglen = length $frag3;
467 $record = TLSProxy::Record->new(
468 0,
469 TLSProxy::Record::RT_HANDSHAKE,
470 TLSProxy::Record::VERS_TLS_1_2,
471 $fraglen,
472 0,
473 $fraglen,
474 $fraglen,
475 $frag3,
476 $frag3
477 );
478 push @{$proxy->record_list}, $record;
479 }
480
481 }
482
483 sub add_unknown_record_type
484 {
485 my $proxy = shift;
486 my $records = $proxy->record_list;
487 state $added_record;
488
489 # We'll change a record after the initial version neg has taken place
490 if ($proxy->flight == 0) {
491 $added_record = 0;
492 return;
493 } elsif ($proxy->flight != 1 || $added_record) {
494 $fatal_alert = 1 if @{$records}[-1]->is_fatal_alert(0) == 10;
495 return;
496 }
497
498 my $record = TLSProxy::Record->new(
499 1,
500 TLSProxy::Record::RT_UNKNOWN,
501 @{$records}[-1]->version(),
502 1,
503 0,
504 1,
505 1,
506 "X",
507 "X"
508 );
509
510 #Find ServerHello record and insert after that
511 my $i;
512 for ($i = 0; ${$proxy->record_list}[$i]->flight() < 1; $i++) {
513 next;
514 }
515 $i++;
516
517 splice @{$proxy->record_list}, $i, 0, $record;
518 $added_record = 1;
519 }
520
521 sub change_version
522 {
523 my $proxy = shift;
524 my $records = $proxy->record_list;
525
526 # We'll change a version after the initial version neg has taken place
527 if ($proxy->flight != 1) {
528 $fatal_alert = 1 if @{$records}[-1]->is_fatal_alert(0) == 70;
529 return;
530 }
531
532 if ($#{$records} > 1) {
533 # ... typically in ServerHelloDone
534 @{$records}[-1]->version(TLSProxy::Record::VERS_TLS_1_1);
535 }
536 }
537
538 sub change_outer_record_type
539 {
540 my $proxy = shift;
541 my $records = $proxy->record_list;
542
543 # We'll change a record after the initial version neg has taken place
544 if ($proxy->flight != 1) {
545 $fatal_alert = 1 if @{$records}[-1]->is_fatal_alert(0) == 10;
546 return;
547 }
548
549 # Find CCS record and change record after that
550 my $i = 0;
551 foreach my $record (@{$records}) {
552 last if $record->content_type == TLSProxy::Record::RT_CCS;
553 $i++;
554 }
555 if (defined(${$records}[++$i])) {
556 ${$records}[$i]->outer_content_type(TLSProxy::Record::RT_HANDSHAKE);
557 }
558 }
559
560 sub not_on_record_boundary
561 {
562 my $proxy = shift;
563 my $records = $proxy->record_list;
564 my $data;
565
566 #Find server's first flight
567 if ($proxy->flight != 1) {
568 $fatal_alert = 1 if @{$records}[-1]->is_fatal_alert(0) == 10;
569 return;
570 }
571
572 if ($boundary_test_type == DATA_AFTER_SERVER_HELLO) {
573 #Merge the ServerHello and EncryptedExtensions records into one
574 my $i = 0;
575 foreach my $record (@{$records}) {
576 if ($record->content_type == TLSProxy::Record::RT_HANDSHAKE) {
577 $record->{sent} = 1; # pretend it's sent already
578 last;
579 }
580 $i++;
581 }
582
583 if (defined(${$records}[$i+1])) {
584 $data = ${$records}[$i]->data();
585 $data .= ${$records}[$i+1]->decrypt_data();
586 ${$records}[$i+1]->data($data);
587 ${$records}[$i+1]->len(length $data);
588
589 #Delete the old ServerHello record
590 splice @{$records}, $i, 1;
591 }
592 } elsif ($boundary_test_type == DATA_AFTER_FINISHED) {
593 return if @{$proxy->{message_list}}[-1]->{mt}
594 != TLSProxy::Message::MT_FINISHED;
595
596 my $last_record = @{$records}[-1];
597 $data = $last_record->decrypt_data;
598
599 #Add a KeyUpdate message onto the end of the Finished record
600 my $keyupdate = pack "C5",
601 0x18, # KeyUpdate
602 0x00, 0x00, 0x01, # Message length
603 0x00; # Update not requested
604
605 $data .= $keyupdate;
606
607 #Add content type and tag
608 $data .= pack("C", TLSProxy::Record::RT_HANDSHAKE).("\0"x16);
609
610 #Update the record
611 $last_record->data($data);
612 $last_record->len(length $data);
613 } elsif ($boundary_test_type == DATA_AFTER_KEY_UPDATE) {
614 return if @{$proxy->{message_list}}[-1]->{mt}
615 != TLSProxy::Message::MT_FINISHED;
616
617 #KeyUpdates must end on a record boundary
618
619 my $record = TLSProxy::Record->new(
620 1,
621 TLSProxy::Record::RT_APPLICATION_DATA,
622 TLSProxy::Record::VERS_TLS_1_2,
623 0,
624 0,
625 0,
626 0,
627 "",
628 ""
629 );
630
631 #Add two KeyUpdate messages into a single record
632 my $keyupdate = pack "C5",
633 0x18, # KeyUpdate
634 0x00, 0x00, 0x01, # Message length
635 0x00; # Update not requested
636
637 $data = $keyupdate.$keyupdate;
638
639 #Add content type and tag
640 $data .= pack("C", TLSProxy::Record::RT_HANDSHAKE).("\0"x16);
641
642 $record->data($data);
643 $record->len(length $data);
644 push @{$records}, $record;
645 } else {
646 return if @{$proxy->{message_list}}[-1]->{mt}
647 != TLSProxy::Message::MT_FINISHED;
648
649 my $record = TLSProxy::Record->new(
650 1,
651 TLSProxy::Record::RT_APPLICATION_DATA,
652 TLSProxy::Record::VERS_TLS_1_2,
653 0,
654 0,
655 0,
656 0,
657 "",
658 ""
659 );
660
661 #Add a partial KeyUpdate message into the record
662 $data = pack "C1",
663 0x18; # KeyUpdate message type. Omit the rest of the message header
664
665 #Add content type and tag
666 $data .= pack("C", TLSProxy::Record::RT_HANDSHAKE).("\0"x16);
667
668 $record->data($data);
669 $record->len(length $data);
670 push @{$records}, $record;
671
672 if ($boundary_test_type == DATA_BETWEEN_KEY_UPDATE) {
673 #Now add an app data record
674 $record = TLSProxy::Record->new(
675 1,
676 TLSProxy::Record::RT_APPLICATION_DATA,
677 TLSProxy::Record::VERS_TLS_1_2,
678 0,
679 0,
680 0,
681 0,
682 "",
683 ""
684 );
685
686 #Add an empty app data record (just content type and tag)
687 $data = pack("C", TLSProxy::Record::RT_APPLICATION_DATA).("\0"x16);
688
689 $record->data($data);
690 $record->len(length $data);
691 push @{$records}, $record;
692 }
693
694 #Now add the rest of the KeyUpdate message
695 $record = TLSProxy::Record->new(
696 1,
697 TLSProxy::Record::RT_APPLICATION_DATA,
698 TLSProxy::Record::VERS_TLS_1_2,
699 0,
700 0,
701 0,
702 0,
703 "",
704 ""
705 );
706
707 #Add the last 4 bytes of the KeyUpdate record
708 $data = pack "C4",
709 0x00, 0x00, 0x01, # Message length
710 0x00; # Update not requested
711
712 #Add content type and tag
713 $data .= pack("C", TLSProxy::Record::RT_HANDSHAKE).("\0"x16);
714
715 $record->data($data);
716 $record->len(length $data);
717 push @{$records}, $record;
718
719 }
720 }