c4220c0f9a
This fixes only those tests that were failing when network data was fragmented. Remaining ones might succeed for "wrong reasons". Bunch of tests have to fail to be considered successful and when data is fragmented they might fail for reasons other than originally intended. Reviewed-by: Richard Levitte <levitte@openssl.org> (Merged from https://github.com/openssl/openssl/pull/5975)
609 lines
18 KiB
Perl
609 lines
18 KiB
Perl
#! /usr/bin/env perl
|
|
# Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved.
|
|
#
|
|
# Licensed under the OpenSSL license (the "License"). You may not use
|
|
# this file except in compliance with the License. You can obtain a copy
|
|
# in the file LICENSE in the source distribution or at
|
|
# https://www.openssl.org/source/license.html
|
|
|
|
use strict;
|
|
use feature 'state';
|
|
|
|
use OpenSSL::Test qw/:DEFAULT cmdstr srctop_file bldtop_dir/;
|
|
use OpenSSL::Test::Utils;
|
|
use TLSProxy::Proxy;
|
|
|
|
my $test_name = "test_sslrecords";
|
|
setup($test_name);
|
|
|
|
plan skip_all => "TLSProxy isn't usable on $^O"
|
|
if $^O =~ /^(VMS)$/;
|
|
|
|
plan skip_all => "$test_name needs the dynamic engine feature enabled"
|
|
if disabled("engine") || disabled("dynamic-engine");
|
|
|
|
plan skip_all => "$test_name needs the sock feature enabled"
|
|
if disabled("sock");
|
|
|
|
plan skip_all => "$test_name needs TLSv1.2 enabled"
|
|
if disabled("tls1_2");
|
|
|
|
$ENV{OPENSSL_ia32cap} = '~0x200000200000000';
|
|
my $proxy = TLSProxy::Proxy->new(
|
|
\&add_empty_recs_filter,
|
|
cmdstr(app(["openssl"]), display => 1),
|
|
srctop_file("apps", "server.pem"),
|
|
(!$ENV{HARNESS_ACTIVE} || $ENV{HARNESS_VERBOSE})
|
|
);
|
|
|
|
my $boundary_test_type;
|
|
my $fatal_alert = 0; # set by filters at expected fatal alerts
|
|
|
|
#Test 1: Injecting out of context empty records should fail
|
|
my $content_type = TLSProxy::Record::RT_APPLICATION_DATA;
|
|
my $inject_recs_num = 1;
|
|
$proxy->serverflags("-tls1_2");
|
|
$proxy->start() or plan skip_all => "Unable to start up Proxy for tests";
|
|
plan tests => 18;
|
|
ok($fatal_alert, "Out of context empty records test");
|
|
|
|
#Test 2: Injecting in context empty records should succeed
|
|
$proxy->clear();
|
|
$content_type = TLSProxy::Record::RT_HANDSHAKE;
|
|
$proxy->serverflags("-tls1_2");
|
|
$proxy->start();
|
|
ok(TLSProxy::Message->success(), "In context empty records test");
|
|
|
|
#Test 3: Injecting too many in context empty records should fail
|
|
$fatal_alert = 0;
|
|
$proxy->clear();
|
|
#We allow 32 consecutive in context empty records
|
|
$inject_recs_num = 33;
|
|
$proxy->serverflags("-tls1_2");
|
|
$proxy->start();
|
|
ok($fatal_alert, "Too many in context empty records test");
|
|
|
|
#Test 4: Injecting a fragmented fatal alert should fail. We expect the server to
|
|
# send back an alert of its own because it cannot handle fragmented
|
|
# alerts
|
|
$fatal_alert = 0;
|
|
$proxy->clear();
|
|
$proxy->filter(\&add_frag_alert_filter);
|
|
$proxy->serverflags("-tls1_2");
|
|
$proxy->start();
|
|
ok($fatal_alert, "Fragmented alert records test");
|
|
|
|
#Run some SSLv2 ClientHello tests
|
|
|
|
use constant {
|
|
TLSV1_2_IN_SSLV2 => 0,
|
|
SSLV2_IN_SSLV2 => 1,
|
|
FRAGMENTED_IN_TLSV1_2 => 2,
|
|
FRAGMENTED_IN_SSLV2 => 3,
|
|
ALERT_BEFORE_SSLV2 => 4
|
|
};
|
|
#Test 5: Inject an SSLv2 style record format for a TLSv1.2 ClientHello
|
|
my $sslv2testtype = TLSV1_2_IN_SSLV2;
|
|
$proxy->clear();
|
|
$proxy->filter(\&add_sslv2_filter);
|
|
$proxy->serverflags("-tls1_2");
|
|
$proxy->start();
|
|
ok(TLSProxy::Message->success(), "TLSv1.2 in SSLv2 ClientHello test");
|
|
|
|
#Test 6: Inject an SSLv2 style record format for an SSLv2 ClientHello. We don't
|
|
# support this so it should fail. We actually treat it as an unknown
|
|
# protocol so we don't even send an alert in this case.
|
|
$sslv2testtype = SSLV2_IN_SSLV2;
|
|
$proxy->clear();
|
|
$proxy->serverflags("-tls1_2");
|
|
$proxy->start();
|
|
ok(TLSProxy::Message->fail(), "SSLv2 in SSLv2 ClientHello test");
|
|
|
|
#Test 7: Sanity check ClientHello fragmentation. This isn't really an SSLv2 test
|
|
# at all, but it gives us confidence that Test 8 fails for the right
|
|
# reasons
|
|
$sslv2testtype = FRAGMENTED_IN_TLSV1_2;
|
|
$proxy->clear();
|
|
$proxy->serverflags("-tls1_2");
|
|
$proxy->start();
|
|
ok(TLSProxy::Message->success(), "Fragmented ClientHello in TLSv1.2 test");
|
|
|
|
#Test 8: Fragment a TLSv1.2 ClientHello across a TLS1.2 record; an SSLv2
|
|
# record; and another TLS1.2 record. This isn't allowed so should fail
|
|
$sslv2testtype = FRAGMENTED_IN_SSLV2;
|
|
$proxy->clear();
|
|
$proxy->serverflags("-tls1_2");
|
|
$proxy->start();
|
|
ok(TLSProxy::Message->fail(), "Fragmented ClientHello in TLSv1.2/SSLv2 test");
|
|
|
|
#Test 9: Send a TLS warning alert before an SSLv2 ClientHello. This should
|
|
# fail because an SSLv2 ClientHello must be the first record.
|
|
$sslv2testtype = ALERT_BEFORE_SSLV2;
|
|
$proxy->clear();
|
|
$proxy->serverflags("-tls1_2");
|
|
$proxy->start();
|
|
ok(TLSProxy::Message->fail(), "Alert before SSLv2 ClientHello test");
|
|
|
|
#Unrecognised record type tests
|
|
|
|
#Test 10: Sending an unrecognised record type in TLS1.2 should fail
|
|
$fatal_alert = 0;
|
|
$proxy->clear();
|
|
$proxy->serverflags("-tls1_2");
|
|
$proxy->filter(\&add_unknown_record_type);
|
|
$proxy->start();
|
|
ok($fatal_alert, "Unrecognised record type in TLS1.2");
|
|
|
|
SKIP: {
|
|
skip "TLSv1.1 disabled", 1 if disabled("tls1_1");
|
|
|
|
#Test 11: Sending an unrecognised record type in TLS1.1 should fail
|
|
$fatal_alert = 0;
|
|
$proxy->clear();
|
|
$proxy->clientflags("-tls1_1");
|
|
$proxy->start();
|
|
ok($fatal_alert, "Unrecognised record type in TLS1.1");
|
|
}
|
|
|
|
#Test 12: Sending a different record version in TLS1.2 should fail
|
|
$fatal_alert = 0;
|
|
$proxy->clear();
|
|
$proxy->clientflags("-tls1_2");
|
|
$proxy->filter(\&change_version);
|
|
$proxy->start();
|
|
ok($fatal_alert, "Changed record version in TLS1.2");
|
|
|
|
#TLS1.3 specific tests
|
|
SKIP: {
|
|
skip "TLSv1.3 disabled", 6 if disabled("tls1_3");
|
|
|
|
#Test 13: Sending a different record version in TLS1.3 should fail
|
|
$proxy->clear();
|
|
$proxy->filter(\&change_version);
|
|
$proxy->start();
|
|
ok(TLSProxy::Message->fail(), "Changed record version in TLS1.3");
|
|
|
|
#Test 14: Sending an unrecognised record type in TLS1.3 should fail
|
|
$fatal_alert = 0;
|
|
$proxy->clear();
|
|
$proxy->filter(\&add_unknown_record_type);
|
|
$proxy->start();
|
|
ok($fatal_alert, "Unrecognised record type in TLS1.3");
|
|
|
|
#Test 15: Sending an outer record type other than app data once encrypted
|
|
#should fail
|
|
$fatal_alert = 0;
|
|
$proxy->clear();
|
|
$proxy->filter(\&change_outer_record_type);
|
|
$proxy->start();
|
|
ok($fatal_alert, "Wrong outer record type in TLS1.3");
|
|
|
|
use constant {
|
|
DATA_AFTER_SERVER_HELLO => 0,
|
|
DATA_AFTER_FINISHED => 1,
|
|
DATA_AFTER_KEY_UPDATE => 2
|
|
};
|
|
|
|
#Test 16: Sending a ServerHello which doesn't end on a record boundary
|
|
# should fail
|
|
$fatal_alert = 0;
|
|
$proxy->clear();
|
|
$boundary_test_type = DATA_AFTER_SERVER_HELLO;
|
|
$proxy->filter(\¬_on_record_boundary);
|
|
$proxy->start();
|
|
ok($fatal_alert, "Record not on boundary in TLS1.3 (ServerHello)");
|
|
|
|
#Test 17: Sending a Finished which doesn't end on a record boundary
|
|
# should fail
|
|
$fatal_alert = 0;
|
|
$proxy->clear();
|
|
$boundary_test_type = DATA_AFTER_FINISHED;
|
|
$proxy->filter(\¬_on_record_boundary);
|
|
$proxy->start();
|
|
ok($fatal_alert, "Record not on boundary in TLS1.3 (Finished)");
|
|
|
|
#Test 18: Sending a KeyUpdate which doesn't end on a record boundary
|
|
# should fail
|
|
$fatal_alert = 0;
|
|
$proxy->clear();
|
|
$boundary_test_type = DATA_AFTER_KEY_UPDATE;
|
|
$proxy->filter(\¬_on_record_boundary);
|
|
$proxy->start();
|
|
ok($fatal_alert, "Record not on boundary in TLS1.3 (KeyUpdate)");
|
|
}
|
|
|
|
|
|
sub add_empty_recs_filter
|
|
{
|
|
my $proxy = shift;
|
|
my $records = $proxy->record_list;
|
|
|
|
# We're only interested in the initial ClientHello
|
|
if ($proxy->flight != 0) {
|
|
$fatal_alert = 1 if @{$records}[-1]->is_fatal_alert(1) == 10;
|
|
return;
|
|
}
|
|
|
|
for (my $i = 0; $i < $inject_recs_num; $i++) {
|
|
my $record = TLSProxy::Record->new(
|
|
0,
|
|
$content_type,
|
|
TLSProxy::Record::VERS_TLS_1_2,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
"",
|
|
""
|
|
);
|
|
push @{$records}, $record;
|
|
}
|
|
}
|
|
|
|
sub add_frag_alert_filter
|
|
{
|
|
my $proxy = shift;
|
|
my $records = $proxy->record_list;
|
|
my $byte;
|
|
|
|
# We're only interested in the initial ClientHello
|
|
if ($proxy->flight != 0) {
|
|
$fatal_alert = 1 if @{$records}[-1]->is_fatal_alert(1) == 10;
|
|
return;
|
|
}
|
|
|
|
# Add a zero length fragment first
|
|
#my $record = TLSProxy::Record->new(
|
|
# 0,
|
|
# TLSProxy::Record::RT_ALERT,
|
|
# TLSProxy::Record::VERS_TLS_1_2,
|
|
# 0,
|
|
# 0,
|
|
# 0,
|
|
# "",
|
|
# ""
|
|
#);
|
|
#push @{$proxy->record_list}, $record;
|
|
|
|
# Now add the alert level (Fatal) as a separate record
|
|
$byte = pack('C', TLSProxy::Message::AL_LEVEL_FATAL);
|
|
my $record = TLSProxy::Record->new(
|
|
0,
|
|
TLSProxy::Record::RT_ALERT,
|
|
TLSProxy::Record::VERS_TLS_1_2,
|
|
1,
|
|
0,
|
|
1,
|
|
1,
|
|
$byte,
|
|
$byte
|
|
);
|
|
push @{$records}, $record;
|
|
|
|
# And finally the description (Unexpected message) in a third record
|
|
$byte = pack('C', TLSProxy::Message::AL_DESC_UNEXPECTED_MESSAGE);
|
|
$record = TLSProxy::Record->new(
|
|
0,
|
|
TLSProxy::Record::RT_ALERT,
|
|
TLSProxy::Record::VERS_TLS_1_2,
|
|
1,
|
|
0,
|
|
1,
|
|
1,
|
|
$byte,
|
|
$byte
|
|
);
|
|
push @{$records}, $record;
|
|
}
|
|
|
|
sub add_sslv2_filter
|
|
{
|
|
my $proxy = shift;
|
|
my $clienthello;
|
|
my $record;
|
|
|
|
# We're only interested in the initial ClientHello
|
|
if ($proxy->flight != 0) {
|
|
return;
|
|
}
|
|
|
|
# Ditch the real ClientHello - we're going to replace it with our own
|
|
shift @{$proxy->record_list};
|
|
|
|
if ($sslv2testtype == ALERT_BEFORE_SSLV2) {
|
|
my $alert = pack('CC', TLSProxy::Message::AL_LEVEL_FATAL,
|
|
TLSProxy::Message::AL_DESC_NO_RENEGOTIATION);
|
|
my $alertlen = length $alert;
|
|
$record = TLSProxy::Record->new(
|
|
0,
|
|
TLSProxy::Record::RT_ALERT,
|
|
TLSProxy::Record::VERS_TLS_1_2,
|
|
$alertlen,
|
|
0,
|
|
$alertlen,
|
|
$alertlen,
|
|
$alert,
|
|
$alert
|
|
);
|
|
|
|
push @{$proxy->record_list}, $record;
|
|
}
|
|
|
|
if ($sslv2testtype == ALERT_BEFORE_SSLV2
|
|
|| $sslv2testtype == TLSV1_2_IN_SSLV2
|
|
|| $sslv2testtype == SSLV2_IN_SSLV2) {
|
|
# This is an SSLv2 format ClientHello
|
|
$clienthello =
|
|
pack "C44",
|
|
0x01, # ClientHello
|
|
0x03, 0x03, #TLSv1.2
|
|
0x00, 0x03, # Ciphersuites len
|
|
0x00, 0x00, # Session id len
|
|
0x00, 0x20, # Challenge len
|
|
0x00, 0x00, 0x2f, #AES128-SHA
|
|
0x01, 0x18, 0x9F, 0x76, 0xEC, 0x57, 0xCE, 0xE5, 0xB3, 0xAB, 0x79, 0x90,
|
|
0xAD, 0xAC, 0x6E, 0xD1, 0x58, 0x35, 0x03, 0x97, 0x16, 0x10, 0x82, 0x56,
|
|
0xD8, 0x55, 0xFF, 0xE1, 0x8A, 0xA3, 0x2E, 0xF6; # Challenge
|
|
|
|
if ($sslv2testtype == SSLV2_IN_SSLV2) {
|
|
# Set the version to "real" SSLv2
|
|
vec($clienthello, 1, 8) = 0x00;
|
|
vec($clienthello, 2, 8) = 0x02;
|
|
}
|
|
|
|
my $chlen = length $clienthello;
|
|
|
|
$record = TLSProxy::Record->new(
|
|
0,
|
|
TLSProxy::Record::RT_HANDSHAKE,
|
|
TLSProxy::Record::VERS_TLS_1_2,
|
|
$chlen,
|
|
1, #SSLv2
|
|
$chlen,
|
|
$chlen,
|
|
$clienthello,
|
|
$clienthello
|
|
);
|
|
|
|
push @{$proxy->record_list}, $record;
|
|
} else {
|
|
# For this test we're using a real TLS ClientHello
|
|
$clienthello =
|
|
pack "C49",
|
|
0x01, # ClientHello
|
|
0x00, 0x00, 0x2D, # Message length
|
|
0x03, 0x03, # TLSv1.2
|
|
0x01, 0x18, 0x9F, 0x76, 0xEC, 0x57, 0xCE, 0xE5, 0xB3, 0xAB, 0x79, 0x90,
|
|
0xAD, 0xAC, 0x6E, 0xD1, 0x58, 0x35, 0x03, 0x97, 0x16, 0x10, 0x82, 0x56,
|
|
0xD8, 0x55, 0xFF, 0xE1, 0x8A, 0xA3, 0x2E, 0xF6, # Random
|
|
0x00, # Session id len
|
|
0x00, 0x04, # Ciphersuites len
|
|
0x00, 0x2f, # AES128-SHA
|
|
0x00, 0xff, # Empty reneg info SCSV
|
|
0x01, # Compression methods len
|
|
0x00, # Null compression
|
|
0x00, 0x00; # Extensions len
|
|
|
|
# Split this into 3: A TLS record; a SSLv2 record and a TLS record.
|
|
# We deliberately split the second record prior to the Challenge/Random
|
|
# and set the first byte of the random to 1. This makes the second SSLv2
|
|
# record look like an SSLv2 ClientHello
|
|
my $frag1 = substr $clienthello, 0, 6;
|
|
my $frag2 = substr $clienthello, 6, 32;
|
|
my $frag3 = substr $clienthello, 38;
|
|
|
|
my $fraglen = length $frag1;
|
|
$record = TLSProxy::Record->new(
|
|
0,
|
|
TLSProxy::Record::RT_HANDSHAKE,
|
|
TLSProxy::Record::VERS_TLS_1_2,
|
|
$fraglen,
|
|
0,
|
|
$fraglen,
|
|
$fraglen,
|
|
$frag1,
|
|
$frag1
|
|
);
|
|
push @{$proxy->record_list}, $record;
|
|
|
|
$fraglen = length $frag2;
|
|
my $recvers;
|
|
if ($sslv2testtype == FRAGMENTED_IN_SSLV2) {
|
|
$recvers = 1;
|
|
} else {
|
|
$recvers = 0;
|
|
}
|
|
$record = TLSProxy::Record->new(
|
|
0,
|
|
TLSProxy::Record::RT_HANDSHAKE,
|
|
TLSProxy::Record::VERS_TLS_1_2,
|
|
$fraglen,
|
|
$recvers,
|
|
$fraglen,
|
|
$fraglen,
|
|
$frag2,
|
|
$frag2
|
|
);
|
|
push @{$proxy->record_list}, $record;
|
|
|
|
$fraglen = length $frag3;
|
|
$record = TLSProxy::Record->new(
|
|
0,
|
|
TLSProxy::Record::RT_HANDSHAKE,
|
|
TLSProxy::Record::VERS_TLS_1_2,
|
|
$fraglen,
|
|
0,
|
|
$fraglen,
|
|
$fraglen,
|
|
$frag3,
|
|
$frag3
|
|
);
|
|
push @{$proxy->record_list}, $record;
|
|
}
|
|
|
|
}
|
|
|
|
sub add_unknown_record_type
|
|
{
|
|
my $proxy = shift;
|
|
my $records = $proxy->record_list;
|
|
state $added_record;
|
|
|
|
# We'll change a record after the initial version neg has taken place
|
|
if ($proxy->flight == 0) {
|
|
$added_record = 0;
|
|
return;
|
|
} elsif ($proxy->flight != 1 || $added_record) {
|
|
$fatal_alert = 1 if @{$records}[-1]->is_fatal_alert(0) == 10;
|
|
return;
|
|
}
|
|
|
|
my $record = TLSProxy::Record->new(
|
|
1,
|
|
TLSProxy::Record::RT_UNKNOWN,
|
|
@{$records}[-1]->version(),
|
|
1,
|
|
0,
|
|
1,
|
|
1,
|
|
"X",
|
|
"X"
|
|
);
|
|
|
|
#Find ServerHello record and insert after that
|
|
my $i;
|
|
for ($i = 0; ${$proxy->record_list}[$i]->flight() < 1; $i++) {
|
|
next;
|
|
}
|
|
$i++;
|
|
|
|
splice @{$proxy->record_list}, $i, 0, $record;
|
|
$added_record = 1;
|
|
}
|
|
|
|
sub change_version
|
|
{
|
|
my $proxy = shift;
|
|
my $records = $proxy->record_list;
|
|
|
|
# We'll change a version after the initial version neg has taken place
|
|
if ($proxy->flight != 1) {
|
|
$fatal_alert = 1 if @{$records}[-1]->is_fatal_alert(0) == 70;
|
|
return;
|
|
}
|
|
|
|
if ($#{$records} > 1) {
|
|
# ... typically in ServerHelloDone
|
|
@{$records}[-1]->version(TLSProxy::Record::VERS_TLS_1_1);
|
|
}
|
|
}
|
|
|
|
sub change_outer_record_type
|
|
{
|
|
my $proxy = shift;
|
|
my $records = $proxy->record_list;
|
|
|
|
# We'll change a record after the initial version neg has taken place
|
|
if ($proxy->flight != 1) {
|
|
$fatal_alert = 1 if @{$records}[-1]->is_fatal_alert(0) == 10;
|
|
return;
|
|
}
|
|
|
|
# Find CCS record and change record after that
|
|
my $i = 0;
|
|
foreach my $record (@{$records}) {
|
|
last if $record->content_type == TLSProxy::Record::RT_CCS;
|
|
$i++;
|
|
}
|
|
if (defined(${$records}[++$i])) {
|
|
${$records}[$i]->outer_content_type(TLSProxy::Record::RT_HANDSHAKE);
|
|
}
|
|
}
|
|
|
|
sub not_on_record_boundary
|
|
{
|
|
my $proxy = shift;
|
|
my $records = $proxy->record_list;
|
|
my $data;
|
|
|
|
#Find server's first flight
|
|
if ($proxy->flight != 1) {
|
|
$fatal_alert = 1 if @{$records}[-1]->is_fatal_alert(0) == 10;
|
|
return;
|
|
}
|
|
|
|
if ($boundary_test_type == DATA_AFTER_SERVER_HELLO) {
|
|
#Merge the ServerHello and EncryptedExtensions records into one
|
|
my $i = 0;
|
|
foreach my $record (@{$records}) {
|
|
if ($record->content_type == TLSProxy::Record::RT_HANDSHAKE) {
|
|
$record->{sent} = 1; # pretend it's sent already
|
|
last;
|
|
}
|
|
$i++;
|
|
}
|
|
|
|
if (defined(${$records}[$i+1])) {
|
|
$data = ${$records}[$i]->data();
|
|
$data .= ${$records}[$i+1]->decrypt_data();
|
|
${$records}[$i+1]->data($data);
|
|
${$records}[$i+1]->len(length $data);
|
|
|
|
#Delete the old ServerHello record
|
|
splice @{$records}, $i, 1;
|
|
}
|
|
} elsif ($boundary_test_type == DATA_AFTER_FINISHED) {
|
|
return if @{$proxy->{message_list}}[-1]->{mt}
|
|
!= TLSProxy::Message::MT_FINISHED;
|
|
|
|
my $last_record = @{$records}[-1];
|
|
$data = $last_record->decrypt_data;
|
|
|
|
#Add a KeyUpdate message onto the end of the Finished record
|
|
my $keyupdate = pack "C5",
|
|
0x18, # KeyUpdate
|
|
0x00, 0x00, 0x01, # Message length
|
|
0x00; # Update not requested
|
|
|
|
$data .= $keyupdate;
|
|
|
|
#Add content type and tag
|
|
$data .= pack("C", TLSProxy::Record::RT_HANDSHAKE).("\0"x16);
|
|
|
|
#Update the record
|
|
$last_record->data($data);
|
|
$last_record->len(length $data);
|
|
} else {
|
|
return if @{$proxy->{message_list}}[-1]->{mt}
|
|
!= TLSProxy::Message::MT_FINISHED;
|
|
|
|
#KeyUpdates must end on a record boundary
|
|
|
|
my $record = TLSProxy::Record->new(
|
|
1,
|
|
TLSProxy::Record::RT_APPLICATION_DATA,
|
|
TLSProxy::Record::VERS_TLS_1_2,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
"",
|
|
""
|
|
);
|
|
|
|
#Add two KeyUpdate messages into a single record
|
|
my $keyupdate = pack "C5",
|
|
0x18, # KeyUpdate
|
|
0x00, 0x00, 0x01, # Message length
|
|
0x00; # Update not requested
|
|
|
|
$data = $keyupdate.$keyupdate;
|
|
|
|
#Add content type and tag
|
|
$data .= pack("C", TLSProxy::Record::RT_HANDSHAKE).("\0"x16);
|
|
|
|
$record->data($data);
|
|
$record->len(length $data);
|
|
push @{$records}, $record;
|
|
}
|
|
}
|