2 # Copyright 2016-2022 The OpenSSL Project Authors. All Rights Reserved.
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
12 use OpenSSL
::Test qw
/:DEFAULT cmdstr srctop_file bldtop_dir/;
13 use OpenSSL
::Test
::Utils
;
15 use TLSProxy
::Message
;
17 my $test_name = "test_sslrecords";
20 plan skip_all
=> "TLSProxy isn't usable on $^O"
23 plan skip_all
=> "$test_name needs the dynamic engine feature enabled"
24 if disabled
("engine") || disabled
("dynamic-engine");
26 plan skip_all
=> "$test_name needs the sock feature enabled"
29 my $inject_recs_num = undef;
30 my $content_type = undef;
31 my $boundary_test_type = undef;
32 my $fatal_alert = undef; # set by filters at expected fatal alerts
33 my $sslv2testtype = undef;
34 my $proxy_start_success = 0;
39 skip
"TLS 1.2 is disabled", 21 if disabled
("tls1_2");
45 skip
"DTLS 1.2 is disabled", 21 if disabled
("dtls1_2");
46 skip
"DTLSProxy does not work on Windows", 21 if $^O
=~ /^(MSWin32)$/;
52 my $run_test_as_dtls = shift;
55 if ($run_test_as_dtls == 1) {
56 $proxy = TLSProxy
::Proxy
->new_dtls(
57 \
&add_empty_recs_filter
,
58 cmdstr
(app
([ "openssl" ]), display
=> 1),
59 srctop_file
("apps", "server.pem"),
60 (!$ENV{HARNESS_ACTIVE
} || $ENV{HARNESS_VERBOSE
})
63 $proxy = TLSProxy
::Proxy
->new(
64 \
&add_empty_recs_filter
,
65 cmdstr
(app
([ "openssl" ]), display
=> 1),
66 srctop_file
("apps", "server.pem"),
67 (!$ENV{HARNESS_ACTIVE
} || $ENV{HARNESS_VERBOSE
})
71 $fatal_alert = 0; # set by filters at expected fatal alerts
73 skip
"Record tests not intended for dtls", 1 if $run_test_as_dtls == 1;
74 #Test 1: Injecting out of context empty records should fail
76 $content_type = TLSProxy
::Record
::RT_APPLICATION_DATA
;
79 $proxy->serverflags("-tls1_2");
80 $proxy->clientflags("-no_tls1_3");
81 $proxy_start_success = $proxy->start();
82 ok
($fatal_alert, "Out of context empty records test");
85 skip
"TLSProxy did not start correctly", 21 if $proxy_start_success == 0
86 && $run_test_as_dtls == 0;
88 #Test 2: Injecting in context empty records should succeed
90 $content_type = TLSProxy
::Record
::RT_HANDSHAKE
;
91 if ($run_test_as_dtls == 1) {
92 $proxy->serverflags("-min_protocol DTLSv1.2 -max_protocol DTLSv1.2");
93 $proxy->clientflags("-max_protocol DTLSv1.2");
95 $proxy->serverflags("-tls1_2");
96 $proxy->clientflags("-no_tls1_3");
98 $proxy_start_success = $proxy->start();
100 skip
"TLSProxy did not start correctly", 20 if $proxy_start_success == 0
101 && $run_test_as_dtls == 1;
103 ok
($proxy_start_success && TLSProxy
::Message
->success(),
104 "In context empty records test".($run_test_as_dtls == 1) ?
" for DTLS" : " for TLS");
107 skip
"Record tests not intended for dtls", 7 if $run_test_as_dtls == 1;
108 #Test 3: Injecting too many in context empty records should fail
111 #We allow 32 consecutive in context empty records
112 $inject_recs_num = 33;
113 $proxy->serverflags("-tls1_2");
114 $proxy->clientflags("-no_tls1_3");
116 ok
($fatal_alert, "Too many in context empty records test");
118 #Test 4: Injecting a fragmented fatal alert should fail. We expect the server to
119 # send back an alert of its own because it cannot handle fragmented
123 $proxy->filter(\
&add_frag_alert_filter
);
124 $proxy->serverflags("-tls1_2");
125 $proxy->clientflags("-no_tls1_3");
127 ok
($fatal_alert, "Fragmented alert records test");
129 #Run some SSLv2 ClientHello tests
132 TLSV1_2_IN_SSLV2
=> 0,
134 FRAGMENTED_IN_TLSV1_2
=> 2,
135 FRAGMENTED_IN_SSLV2
=> 3,
136 ALERT_BEFORE_SSLV2
=> 4
139 # The TLSv1.2 in SSLv2 ClientHello need to run at security level 0
140 # because in a SSLv2 ClientHello we can't send extensions to indicate
141 # which signature algorithm we want to use, and the default is SHA1.
143 #Test 5: Inject an SSLv2 style record format for a TLSv1.2 ClientHello
144 $sslv2testtype = TLSV1_2_IN_SSLV2
;
146 $proxy->filter(\
&add_sslv2_filter
);
147 $proxy->serverflags("-tls1_2");
148 $proxy->clientflags("-no_tls1_3 -legacy_renegotiation");
149 $proxy->ciphers("AES128-SHA:\@SECLEVEL=0");
151 ok
(TLSProxy
::Message
->success(), "TLSv1.2 in SSLv2 ClientHello test");
153 #Test 6: Inject an SSLv2 style record format for an SSLv2 ClientHello. We don't
154 # support this so it should fail. We actually treat it as an unknown
155 # protocol so we don't even send an alert in this case.
156 $sslv2testtype = SSLV2_IN_SSLV2
;
158 $proxy->serverflags("-tls1_2");
159 $proxy->clientflags("-no_tls1_3");
160 $proxy->ciphers("AES128-SHA:\@SECLEVEL=0");
162 ok
(TLSProxy
::Message
->fail(), "SSLv2 in SSLv2 ClientHello test");
164 #Test 7: Sanity check ClientHello fragmentation. This isn't really an SSLv2 test
165 # at all, but it gives us confidence that Test 8 fails for the right
167 $sslv2testtype = FRAGMENTED_IN_TLSV1_2
;
169 $proxy->serverflags("-tls1_2");
170 $proxy->clientflags("-no_tls1_3");
171 $proxy->ciphers("AES128-SHA:\@SECLEVEL=0");
173 ok
(TLSProxy
::Message
->success(), "Fragmented ClientHello in TLSv1.2 test");
175 #Test 8: Fragment a TLSv1.2 ClientHello across a TLS1.2 record; an SSLv2
176 # record; and another TLS1.2 record. This isn't allowed so should fail
177 $sslv2testtype = FRAGMENTED_IN_SSLV2
;
179 $proxy->serverflags("-tls1_2");
180 $proxy->clientflags("-no_tls1_3");
181 $proxy->ciphers("AES128-SHA:\@SECLEVEL=0");
183 ok
(TLSProxy
::Message
->fail(), "Fragmented ClientHello in TLSv1.2/SSLv2 test");
185 #Test 9: Send a TLS warning alert before an SSLv2 ClientHello. This should
186 # fail because an SSLv2 ClientHello must be the first record.
187 $sslv2testtype = ALERT_BEFORE_SSLV2
;
189 $proxy->serverflags("-tls1_2");
190 $proxy->clientflags("-no_tls1_3");
191 $proxy->ciphers("AES128-SHA:\@SECLEVEL=0");
193 ok
(TLSProxy
::Message
->fail(), "Alert before SSLv2 ClientHello test");
195 #Unrecognised record type tests
197 #Test 10: Sending an unrecognised record type in TLS1.2 should fail
200 if ($run_test_as_dtls == 1) {
201 $proxy->serverflags("-min_protocol DTLSv1.2 -max_protocol DTLSv1.2");
202 $proxy->clientflags("-max_protocol DTLSv1.2");
204 $proxy->serverflags("-tls1_2");
205 $proxy->clientflags("-no_tls1_3");
207 $proxy->filter(\
&add_unknown_record_type
);
208 $proxy_start_success = $proxy->start();
210 if ($run_test_as_dtls == 1) {
211 ok
($proxy_start_success == 0, "Unrecognised record type in DTLS1.2");
213 ok
($fatal_alert, "Unrecognised record type in TLS1.2");
217 skip
"TLSv1.1 or DTLSv1 disabled", 1 if ($run_test_as_dtls == 0 && disabled
("tls1_1"))
218 || ($run_test_as_dtls == 1 && disabled
("dtls1"));
220 #Test 11: Sending an unrecognised record type in TLS1.1 should fail
223 if ($run_test_as_dtls == 1) {
224 $proxy->clientflags("-min_protocol DTLSv1 -max_protocol DTLSv1 -cipher DEFAULT:\@SECLEVEL=0");
226 $proxy->clientflags("-tls1_1 -cipher DEFAULT:\@SECLEVEL=0");
228 $proxy->ciphers("AES128-SHA:\@SECLEVEL=0");
229 $proxy_start_success = $proxy->start();
230 if ($run_test_as_dtls == 1) {
231 ok
($proxy_start_success == 0, "Unrecognised record type in DTLSv1");
233 ok
($fatal_alert, "Unrecognised record type in TLSv1.1");
238 skip
"Record tests not intended for dtls", 10 if $run_test_as_dtls == 1;
239 #Test 12: Sending a different record version in TLS1.2 should fail
242 $proxy->clientflags("-tls1_2");
243 $proxy->filter(\
&change_version
);
245 ok
($fatal_alert, "Changed record version in TLS1.2");
247 #TLS1.3 specific tests
249 skip
"TLSv1.3 disabled", 9
250 if disabled
("tls1_3") || (disabled
("ec") && disabled
("dh"));
252 #Test 13: Sending a different record version in TLS1.3 should fail
254 $proxy->filter(\
&change_version
);
256 ok
(TLSProxy
::Message
->fail(), "Changed record version in TLS1.3");
258 #Test 14: Sending an unrecognised record type in TLS1.3 should fail
261 $proxy->filter(\
&add_unknown_record_type
);
263 ok
($fatal_alert, "Unrecognised record type in TLS1.3");
265 #Test 15: Sending an outer record type other than app data once encrypted
269 $proxy->filter(\
&change_outer_record_type
);
271 ok
($fatal_alert, "Wrong outer record type in TLS1.3");
274 DATA_AFTER_SERVER_HELLO
=> 0,
275 DATA_AFTER_FINISHED
=> 1,
276 DATA_AFTER_KEY_UPDATE
=> 2,
277 DATA_BETWEEN_KEY_UPDATE
=> 3,
278 NO_DATA_BETWEEN_KEY_UPDATE
=> 4,
281 #Test 16: Sending a ServerHello which doesn't end on a record boundary
285 $boundary_test_type = DATA_AFTER_SERVER_HELLO
;
286 $proxy->filter(\
¬_on_record_boundary
);
288 ok
($fatal_alert, "Record not on boundary in TLS1.3 (ServerHello)");
290 #Test 17: Sending a Finished which doesn't end on a record boundary
294 $boundary_test_type = DATA_AFTER_FINISHED
;
296 ok
($fatal_alert, "Record not on boundary in TLS1.3 (Finished)");
298 #Test 18: Sending a KeyUpdate which doesn't end on a record boundary
302 $boundary_test_type = DATA_AFTER_KEY_UPDATE
;
304 ok
($fatal_alert, "Record not on boundary in TLS1.3 (KeyUpdate)");
306 #Test 19: Sending application data in the middle of a fragmented KeyUpdate
307 # should fail. Strictly speaking this is not a record boundary test
308 # but we use the same filter.
311 $boundary_test_type = DATA_BETWEEN_KEY_UPDATE
;
313 ok
($fatal_alert, "Data between KeyUpdate");
315 #Test 20: Fragmented KeyUpdate. This should succeed. Strictly speaking this
316 # is not a record boundary test but we use the same filter.
318 $boundary_test_type = NO_DATA_BETWEEN_KEY_UPDATE
;
320 ok
(TLSProxy
::Message
->success(), "No data between KeyUpdate");
323 skip
"EC disabled", 1 if disabled
("ec");
325 #Test 21: Force an HRR and change the "real" ServerHello to have a protocol
326 # record version of 0x0301 (TLSv1.0). At this point we have already
327 # decided that we are doing TLSv1.3 but are still using plaintext
328 # records. The server should be sending a record version of 0x303
329 # (TLSv1.2), but the RFC requires us to ignore this field so we
330 # should tolerate the incorrect version.
332 $proxy->filter(\
&change_server_hello_version
);
333 $proxy->serverflags("-groups P-256"); # Force an HRR
335 ok
(TLSProxy
::Message
->success(), "Bad ServerHello record version after HRR");
342 sub add_empty_recs_filter
345 my $records = $proxy->record_list;
346 my $isdtls = $proxy->isdtls();
348 # We're only interested in the initial ClientHello
349 if ($proxy->flight != 0) {
350 $fatal_alert = 1 if @
{$records}[-1]->is_fatal_alert(1) == TLSProxy
::Message
::AL_DESC_UNEXPECTED_MESSAGE
;
354 for (my $i = 0; $i < $inject_recs_num; $i++) {
357 $record = TLSProxy
::Record
->new_dtls(
360 TLSProxy
::Record
::VERS_DTLS_1_2
,
371 $record = TLSProxy
::Record
->new(
374 TLSProxy
::Record
::VERS_TLS_1_2
,
383 push @
{$records}, $record;
387 sub add_frag_alert_filter
390 my $records = $proxy->record_list;
393 # We're only interested in the initial ClientHello
394 if ($proxy->flight != 0) {
395 $fatal_alert = 1 if @
{$records}[-1]->is_fatal_alert(1) == TLSProxy
::Message
::AL_DESC_UNEXPECTED_MESSAGE
;
399 # Add a zero length fragment first
400 #my $record = TLSProxy::Record->new(
402 # TLSProxy::Record::RT_ALERT,
403 # TLSProxy::Record::VERS_TLS_1_2,
410 #push @{$proxy->record_list}, $record;
412 # Now add the alert level (Fatal) as a separate record
413 $byte = pack('C', TLSProxy
::Message
::AL_LEVEL_FATAL
);
414 my $record = TLSProxy
::Record
->new(
416 TLSProxy
::Record
::RT_ALERT
,
417 TLSProxy
::Record
::VERS_TLS_1_2
,
425 push @
{$records}, $record;
427 # And finally the description (Unexpected message) in a third record
428 $byte = pack('C', TLSProxy
::Message
::AL_DESC_UNEXPECTED_MESSAGE
);
429 $record = TLSProxy
::Record
->new(
431 TLSProxy
::Record
::RT_ALERT
,
432 TLSProxy
::Record
::VERS_TLS_1_2
,
440 push @
{$records}, $record;
449 # We're only interested in the initial ClientHello
450 if ($proxy->flight != 0) {
454 # Ditch the real ClientHello - we're going to replace it with our own
455 shift @
{$proxy->record_list};
457 if ($sslv2testtype == ALERT_BEFORE_SSLV2
) {
458 my $alert = pack('CC', TLSProxy
::Message
::AL_LEVEL_FATAL
,
459 TLSProxy
::Message
::AL_DESC_NO_RENEGOTIATION
);
460 my $alertlen = length $alert;
461 $record = TLSProxy
::Record
->new(
463 TLSProxy
::Record
::RT_ALERT
,
464 TLSProxy
::Record
::VERS_TLS_1_2
,
473 push @
{$proxy->record_list}, $record;
476 if ($sslv2testtype == ALERT_BEFORE_SSLV2
477 || $sslv2testtype == TLSV1_2_IN_SSLV2
478 || $sslv2testtype == SSLV2_IN_SSLV2
) {
479 # This is an SSLv2 format ClientHello
484 0x00, 0x03, # Ciphersuites len
485 0x00, 0x00, # Session id len
486 0x00, 0x20, # Challenge len
487 0x00, 0x00, 0x2f, #AES128-SHA
488 0x01, 0x18, 0x9F, 0x76, 0xEC, 0x57, 0xCE, 0xE5, 0xB3, 0xAB, 0x79, 0x90,
489 0xAD, 0xAC, 0x6E, 0xD1, 0x58, 0x35, 0x03, 0x97, 0x16, 0x10, 0x82, 0x56,
490 0xD8, 0x55, 0xFF, 0xE1, 0x8A, 0xA3, 0x2E, 0xF6; # Challenge
492 if ($sslv2testtype == SSLV2_IN_SSLV2
) {
493 # Set the version to "real" SSLv2
494 vec($clienthello, 1, 8) = 0x00;
495 vec($clienthello, 2, 8) = 0x02;
498 my $chlen = length $clienthello;
500 $record = TLSProxy
::Record
->new(
502 TLSProxy
::Record
::RT_HANDSHAKE
,
503 TLSProxy
::Record
::VERS_TLS_1_2
,
512 push @
{$proxy->record_list}, $record;
514 # For this test we're using a real TLS ClientHello
518 0x00, 0x00, 0x2D, # Message length
519 0x03, 0x03, # TLSv1.2
520 0x01, 0x18, 0x9F, 0x76, 0xEC, 0x57, 0xCE, 0xE5, 0xB3, 0xAB, 0x79, 0x90,
521 0xAD, 0xAC, 0x6E, 0xD1, 0x58, 0x35, 0x03, 0x97, 0x16, 0x10, 0x82, 0x56,
522 0xD8, 0x55, 0xFF, 0xE1, 0x8A, 0xA3, 0x2E, 0xF6, # Random
523 0x00, # Session id len
524 0x00, 0x04, # Ciphersuites len
525 0x00, 0x2f, # AES128-SHA
526 0x00, 0xff, # Empty reneg info SCSV
527 0x01, # Compression methods len
528 0x00, # Null compression
529 0x00, 0x00; # Extensions len
531 # Split this into 3: A TLS record; a SSLv2 record and a TLS record.
532 # We deliberately split the second record prior to the Challenge/Random
533 # and set the first byte of the random to 1. This makes the second SSLv2
534 # record look like an SSLv2 ClientHello
535 my $frag1 = substr $clienthello, 0, 6;
536 my $frag2 = substr $clienthello, 6, 32;
537 my $frag3 = substr $clienthello, 38;
539 my $fraglen = length $frag1;
540 $record = TLSProxy
::Record
->new(
542 TLSProxy
::Record
::RT_HANDSHAKE
,
543 TLSProxy
::Record
::VERS_TLS_1_2
,
551 push @
{$proxy->record_list}, $record;
553 $fraglen = length $frag2;
555 if ($sslv2testtype == FRAGMENTED_IN_SSLV2
) {
560 $record = TLSProxy
::Record
->new(
562 TLSProxy
::Record
::RT_HANDSHAKE
,
563 TLSProxy
::Record
::VERS_TLS_1_2
,
571 push @
{$proxy->record_list}, $record;
573 $fraglen = length $frag3;
574 $record = TLSProxy
::Record
->new(
576 TLSProxy
::Record
::RT_HANDSHAKE
,
577 TLSProxy
::Record
::VERS_TLS_1_2
,
585 push @
{$proxy->record_list}, $record;
590 sub add_unknown_record_type
593 my $records = $proxy->record_list;
594 my $isdtls = $proxy->isdtls;
597 # We'll change a record after the initial version neg has taken place
598 if ($proxy->flight == 0) {
601 } elsif ($proxy->flight != 1 || $added_record) {
602 $fatal_alert = 1 if @
{$records}[-1]->is_fatal_alert(0) == TLSProxy
::Message
::AL_DESC_UNEXPECTED_MESSAGE
;
609 $record = TLSProxy
::Record
->new_dtls(
611 TLSProxy
::Record
::RT_UNKNOWN
,
612 @
{$records}[-1]->version(),
613 @
{$records}[-1]->epoch(),
614 @
{$records}[-1]->seq() +1,
623 $record = TLSProxy
::Record
->new(
625 TLSProxy
::Record
::RT_UNKNOWN
,
626 @
{$records}[-1]->version(),
636 #Find ServerHello record and insert after that
638 for ($i = 0; ${$proxy->record_list}[$i]->flight() < 1; $i++) {
643 splice @
{$proxy->record_list}, $i, 0, $record;
650 my $records = $proxy->record_list;
652 # We'll change a version after the initial version neg has taken place
653 if ($proxy->flight != 1) {
654 $fatal_alert = 1 if @
{$records}[-1]->is_fatal_alert(0) == TLSProxy
::Message
::AL_DESC_PROTOCOL_VERSION
;
658 if ($#{$records} > 1) {
659 # ... typically in ServerHelloDone
660 @
{$records}[-1]->version(TLSProxy
::Record
::VERS_TLS_1_1
);
664 sub change_server_hello_version
667 my $records = $proxy->record_list;
669 # We're only interested in changing the ServerHello after an HRR
670 if ($proxy->flight != 3) {
674 # The ServerHello has index 5
681 @
{$records}[5]->version(TLSProxy
::Record
::VERS_TLS_1_0
);
684 sub change_outer_record_type
687 my $records = $proxy->record_list;
689 # We'll change a record after the initial version neg has taken place
690 if ($proxy->flight != 1) {
691 $fatal_alert = 1 if @
{$records}[-1]->is_fatal_alert(0) == TLSProxy
::Message
::AL_DESC_UNEXPECTED_MESSAGE
;
695 # Find CCS record and change record after that
697 foreach my $record (@
{$records}) {
698 last if $record->content_type == TLSProxy
::Record
::RT_CCS
;
701 if (defined(${$records}[++$i])) {
702 ${$records}[$i]->outer_content_type(TLSProxy
::Record
::RT_HANDSHAKE
);
706 sub not_on_record_boundary
709 my $records = $proxy->record_list;
712 #Find server's first flight
713 if ($proxy->flight != 1) {
714 $fatal_alert = 1 if @
{$records}[-1]->is_fatal_alert(0) == TLSProxy
::Message
::AL_DESC_UNEXPECTED_MESSAGE
;
718 if ($boundary_test_type == DATA_AFTER_SERVER_HELLO
) {
719 #Merge the ServerHello and EncryptedExtensions records into one
721 foreach my $record (@
{$records}) {
722 if ($record->content_type == TLSProxy
::Record
::RT_HANDSHAKE
) {
723 $record->{sent
} = 1; # pretend it's sent already
729 if (defined(${$records}[$i+1])) {
730 $data = ${$records}[$i]->data();
731 $data .= ${$records}[$i+1]->decrypt_data();
732 ${$records}[$i+1]->data($data);
733 ${$records}[$i+1]->len(length $data);
735 #Delete the old ServerHello record
736 splice @
{$records}, $i, 1;
738 } elsif ($boundary_test_type == DATA_AFTER_FINISHED
) {
739 return if @
{$proxy->{message_list
}}[-1]->{mt
}
740 != TLSProxy
::Message
::MT_FINISHED
;
742 my $last_record = @
{$records}[-1];
743 $data = $last_record->decrypt_data;
745 #Add a KeyUpdate message onto the end of the Finished record
746 my $keyupdate = pack "C5",
748 0x00, 0x00, 0x01, # Message length
749 0x00; # Update not requested
753 #Add content type and tag
754 $data .= pack("C", TLSProxy
::Record
::RT_HANDSHAKE
).("\0"x16
);
757 $last_record->data($data);
758 $last_record->len(length $data);
759 } elsif ($boundary_test_type == DATA_AFTER_KEY_UPDATE
) {
760 return if @
{$proxy->{message_list
}}[-1]->{mt
}
761 != TLSProxy
::Message
::MT_FINISHED
;
763 #KeyUpdates must end on a record boundary
765 my $record = TLSProxy
::Record
->new(
767 TLSProxy
::Record
::RT_APPLICATION_DATA
,
768 TLSProxy
::Record
::VERS_TLS_1_2
,
777 #Add two KeyUpdate messages into a single record
778 my $keyupdate = pack "C5",
780 0x00, 0x00, 0x01, # Message length
781 0x00; # Update not requested
783 $data = $keyupdate.$keyupdate;
785 #Add content type and tag
786 $data .= pack("C", TLSProxy
::Record
::RT_HANDSHAKE
).("\0"x16
);
788 $record->data($data);
789 $record->len(length $data);
790 push @
{$records}, $record;
792 return if @
{$proxy->{message_list
}}[-1]->{mt
}
793 != TLSProxy
::Message
::MT_FINISHED
;
795 my $record = TLSProxy
::Record
->new(
797 TLSProxy
::Record
::RT_APPLICATION_DATA
,
798 TLSProxy
::Record
::VERS_TLS_1_2
,
807 #Add a partial KeyUpdate message into the record
809 0x18; # KeyUpdate message type. Omit the rest of the message header
811 #Add content type and tag
812 $data .= pack("C", TLSProxy
::Record
::RT_HANDSHAKE
).("\0"x16
);
814 $record->data($data);
815 $record->len(length $data);
816 push @
{$records}, $record;
818 if ($boundary_test_type == DATA_BETWEEN_KEY_UPDATE
) {
819 #Now add an app data record
820 $record = TLSProxy
::Record
->new(
822 TLSProxy
::Record
::RT_APPLICATION_DATA
,
823 TLSProxy
::Record
::VERS_TLS_1_2
,
832 #Add an empty app data record (just content type and tag)
833 $data = pack("C", TLSProxy
::Record
::RT_APPLICATION_DATA
).("\0"x16
);
835 $record->data($data);
836 $record->len(length $data);
837 push @
{$records}, $record;
840 #Now add the rest of the KeyUpdate message
841 $record = TLSProxy
::Record
->new(
843 TLSProxy
::Record
::RT_APPLICATION_DATA
,
844 TLSProxy
::Record
::VERS_TLS_1_2
,
853 #Add the last 4 bytes of the KeyUpdate record
855 0x00, 0x00, 0x01, # Message length
856 0x00; # Update not requested
858 #Add content type and tag
859 $data .= pack("C", TLSProxy
::Record
::RT_HANDSHAKE
).("\0"x16
);
861 $record->data($data);
862 $record->len(length $data);
863 push @
{$records}, $record;