mirror of
https://github.com/openssl/openssl.git
synced 2026-01-25 02:56:43 +00:00
Drop support for the SSLv2 Client Hello. We allowed that a client send an SSLv2 compatible Client Hello. Reviewed-by: Dmitry Belyavskiy <beldmit@gmail.com> Reviewed-by: Alicja Kario <hkario@redhat.com> Reviewed-by: Tomas Mraz <tomas@openssl.org> Reviewed-by: Matt Caswell <matt@openssl.org> (Merged from https://github.com/openssl/openssl/pull/28041)
703 lines
22 KiB
Perl
703 lines
22 KiB
Perl
#! /usr/bin/env perl
|
|
# Copyright 2016-2025 The OpenSSL Project Authors. All Rights Reserved.
|
|
#
|
|
# Licensed under the Apache License 2.0 (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;
|
|
use TLSProxy::Message;
|
|
use Cwd qw(abs_path);
|
|
|
|
my $test_name = "test_sslrecords";
|
|
setup($test_name);
|
|
|
|
$ENV{OPENSSL_MODULES} = abs_path(bldtop_dir("test"));
|
|
|
|
plan skip_all => "TLSProxy isn't usable on $^O"
|
|
if $^O =~ /^(VMS)$/;
|
|
|
|
plan skip_all => "$test_name needs the module feature enabled"
|
|
if disabled("module");
|
|
|
|
plan skip_all => "$test_name needs the sock feature enabled"
|
|
if disabled("sock");
|
|
|
|
my $inject_recs_num = undef;
|
|
my $content_type = undef;
|
|
my $boundary_test_type = undef;
|
|
my $fatal_alert = undef; # set by filters at expected fatal alerts
|
|
my $proxy_start_success = 0;
|
|
|
|
plan tests => 34;
|
|
|
|
SKIP: {
|
|
skip "TLS 1.2 is disabled", 17 if disabled("tls1_2");
|
|
# Run tests with TLS
|
|
run_tests(0);
|
|
}
|
|
|
|
SKIP: {
|
|
skip "DTLS 1.2 is disabled", 17 if disabled("dtls1_2");
|
|
skip "DTLSProxy does not work on Windows", 17 if $^O =~ /^(MSWin32)$/;
|
|
run_tests(1);
|
|
}
|
|
|
|
sub run_tests
|
|
{
|
|
my $run_test_as_dtls = shift;
|
|
|
|
my $proxy;
|
|
if ($run_test_as_dtls == 1) {
|
|
$proxy = TLSProxy::Proxy->new_dtls(
|
|
\&add_empty_recs_filter,
|
|
cmdstr(app([ "openssl" ]), display => 1),
|
|
srctop_file("apps", "server.pem"),
|
|
(!$ENV{HARNESS_ACTIVE} || $ENV{HARNESS_VERBOSE})
|
|
);
|
|
} else {
|
|
$proxy = TLSProxy::Proxy->new(
|
|
\&add_empty_recs_filter,
|
|
cmdstr(app([ "openssl" ]), display => 1),
|
|
srctop_file("apps", "server.pem"),
|
|
(!$ENV{HARNESS_ACTIVE} || $ENV{HARNESS_VERBOSE})
|
|
);
|
|
}
|
|
|
|
$fatal_alert = 0; # set by filters at expected fatal alerts
|
|
SKIP: {
|
|
skip "Record tests not intended for dtls", 1 if $run_test_as_dtls == 1;
|
|
#Test 1: Injecting out of context empty records should fail
|
|
$proxy->clear();
|
|
$content_type = TLSProxy::Record::RT_APPLICATION_DATA;
|
|
$inject_recs_num = 1;
|
|
$fatal_alert = 0;
|
|
$proxy->serverflags("-tls1_2");
|
|
$proxy->clientflags("-no_tls1_3");
|
|
$proxy_start_success = $proxy->start();
|
|
ok($fatal_alert, "Out of context empty records test");
|
|
}
|
|
|
|
skip "TLSProxy did not start correctly", 21 if $proxy_start_success == 0
|
|
&& $run_test_as_dtls == 0;
|
|
|
|
#Test 2: Injecting in context empty records should succeed
|
|
$proxy->clear();
|
|
$content_type = TLSProxy::Record::RT_HANDSHAKE;
|
|
if ($run_test_as_dtls == 1) {
|
|
$proxy->serverflags("-min_protocol DTLSv1.2 -max_protocol DTLSv1.2");
|
|
$proxy->clientflags("-max_protocol DTLSv1.2");
|
|
} else {
|
|
$proxy->serverflags("-tls1_2");
|
|
$proxy->clientflags("-no_tls1_3");
|
|
}
|
|
$proxy_start_success = $proxy->start();
|
|
|
|
skip "TLSProxy did not start correctly", 20 if $proxy_start_success == 0
|
|
&& $run_test_as_dtls == 1;
|
|
|
|
ok($proxy_start_success && TLSProxy::Message->success(),
|
|
"In context empty records test".($run_test_as_dtls == 1) ? " for DTLS" : " for TLS");
|
|
|
|
SKIP: {
|
|
skip "Record tests not intended for dtls", 2 if $run_test_as_dtls == 1;
|
|
#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->clientflags("-no_tls1_3");
|
|
$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->clientflags("-no_tls1_3");
|
|
$proxy->start();
|
|
ok($fatal_alert, "Fragmented alert records test");
|
|
}
|
|
#Unrecognised record type tests
|
|
|
|
#Test 5: Sending an unrecognised record type in TLS1.2 should fail
|
|
$fatal_alert = 0;
|
|
$proxy->clear();
|
|
if ($run_test_as_dtls == 1) {
|
|
$proxy->serverflags("-min_protocol DTLSv1.2 -max_protocol DTLSv1.2");
|
|
$proxy->clientflags("-max_protocol DTLSv1.2");
|
|
} else {
|
|
$proxy->serverflags("-tls1_2");
|
|
$proxy->clientflags("-no_tls1_3");
|
|
}
|
|
$proxy->filter(\&add_unknown_record_type);
|
|
$proxy_start_success = $proxy->start();
|
|
|
|
if ($run_test_as_dtls == 1) {
|
|
ok($proxy_start_success == 0, "Unrecognised record type in DTLS1.2");
|
|
} else {
|
|
ok($fatal_alert, "Unrecognised record type in TLS1.2");
|
|
}
|
|
|
|
SKIP: {
|
|
skip "TLSv1.1 or DTLSv1 disabled", 1 if ($run_test_as_dtls == 0 && disabled("tls1_1"))
|
|
|| ($run_test_as_dtls == 1 && disabled("dtls1"));
|
|
|
|
#Test 6: Sending an unrecognised record type in TLS1.1 should fail
|
|
$fatal_alert = 0;
|
|
$proxy->clear();
|
|
if ($run_test_as_dtls == 1) {
|
|
$proxy->clientflags("-min_protocol DTLSv1 -max_protocol DTLSv1 -cipher DEFAULT:\@SECLEVEL=0");
|
|
} else {
|
|
$proxy->clientflags("-tls1_1 -cipher DEFAULT:\@SECLEVEL=0");
|
|
}
|
|
$proxy->ciphers("AES128-SHA:\@SECLEVEL=0");
|
|
$proxy_start_success = $proxy->start();
|
|
if ($run_test_as_dtls == 1) {
|
|
ok($proxy_start_success == 0, "Unrecognised record type in DTLSv1");
|
|
} else {
|
|
ok($fatal_alert, "Unrecognised record type in TLSv1.1");
|
|
}
|
|
}
|
|
|
|
SKIP: {
|
|
skip "Record tests not intended for dtls", 10 if $run_test_as_dtls == 1;
|
|
#Test 7: 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", 9
|
|
if disabled("tls1_3") || (disabled("ec") && disabled("dh"));
|
|
|
|
#Test 8: 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 9: 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 10: 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,
|
|
DATA_BETWEEN_KEY_UPDATE => 3,
|
|
NO_DATA_BETWEEN_KEY_UPDATE => 4,
|
|
};
|
|
|
|
#Test 11: 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 12: 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->start();
|
|
ok($fatal_alert, "Record not on boundary in TLS1.3 (Finished)");
|
|
|
|
#Test 13: 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->start();
|
|
ok($fatal_alert, "Record not on boundary in TLS1.3 (KeyUpdate)");
|
|
|
|
#Test 14: Sending application data in the middle of a fragmented KeyUpdate
|
|
# should fail. Strictly speaking this is not a record boundary test
|
|
# but we use the same filter.
|
|
$fatal_alert = 0;
|
|
$proxy->clear();
|
|
$boundary_test_type = DATA_BETWEEN_KEY_UPDATE;
|
|
$proxy->start();
|
|
ok($fatal_alert, "Data between KeyUpdate");
|
|
|
|
#Test 15: Fragmented KeyUpdate. This should succeed. Strictly speaking this
|
|
# is not a record boundary test but we use the same filter.
|
|
$proxy->clear();
|
|
$boundary_test_type = NO_DATA_BETWEEN_KEY_UPDATE;
|
|
$proxy->start();
|
|
ok(TLSProxy::Message->success(), "No data between KeyUpdate");
|
|
|
|
SKIP: {
|
|
skip "EC disabled", 1 if disabled("ec");
|
|
|
|
#Test 16: Force an HRR and change the "real" ServerHello to have a protocol
|
|
# record version of 0x0301 (TLSv1.0). At this point we have already
|
|
# decided that we are doing TLSv1.3 but are still using plaintext
|
|
# records. The server should be sending a record version of 0x303
|
|
# (TLSv1.2), but the RFC requires us to ignore this field so we
|
|
# should tolerate the incorrect version.
|
|
$proxy->clear();
|
|
$proxy->filter(\&change_server_hello_version);
|
|
$proxy->serverflags("-groups P-256"); # Force an HRR
|
|
$proxy->start();
|
|
ok(TLSProxy::Message->success(), "Bad ServerHello record version after HRR");
|
|
}
|
|
}
|
|
}
|
|
|
|
SKIP: {
|
|
skip "DTLS only record tests", 1 if $run_test_as_dtls != 1;
|
|
#Test 17: We should ignore empty app data records
|
|
$proxy->clear();
|
|
$proxy->filter(\&empty_app_data);
|
|
$proxy->start();
|
|
ok(TLSProxy::Message->success(), "Empty app data in DTLS");
|
|
|
|
}
|
|
}
|
|
|
|
sub add_empty_recs_filter
|
|
{
|
|
my $proxy = shift;
|
|
my $records = $proxy->record_list;
|
|
my $isdtls = $proxy->isdtls();
|
|
|
|
# We're only interested in the initial ClientHello
|
|
if ($proxy->flight != 0) {
|
|
$fatal_alert = 1 if @{$records}[-1]->is_fatal_alert(1) == TLSProxy::Message::AL_DESC_UNEXPECTED_MESSAGE;
|
|
return;
|
|
}
|
|
|
|
for (my $i = 0; $i < $inject_recs_num; $i++) {
|
|
my $record;
|
|
if ($isdtls == 1) {
|
|
$record = TLSProxy::Record->new_dtls(
|
|
0,
|
|
$content_type,
|
|
TLSProxy::Record::VERS_DTLS_1_2,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
"",
|
|
""
|
|
);
|
|
} else {
|
|
$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) == TLSProxy::Message::AL_DESC_UNEXPECTED_MESSAGE;
|
|
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_unknown_record_type
|
|
{
|
|
my $proxy = shift;
|
|
my $records = $proxy->record_list;
|
|
my $isdtls = $proxy->isdtls;
|
|
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) == TLSProxy::Message::AL_DESC_UNEXPECTED_MESSAGE;
|
|
return;
|
|
}
|
|
|
|
my $record;
|
|
|
|
if ($isdtls) {
|
|
$record = TLSProxy::Record->new_dtls(
|
|
1,
|
|
TLSProxy::Record::RT_UNKNOWN,
|
|
@{$records}[-1]->version(),
|
|
@{$records}[-1]->epoch(),
|
|
@{$records}[-1]->seq() +1,
|
|
1,
|
|
0,
|
|
1,
|
|
1,
|
|
"X",
|
|
"X"
|
|
);
|
|
} else {
|
|
$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) == TLSProxy::Message::AL_DESC_PROTOCOL_VERSION;
|
|
return;
|
|
}
|
|
|
|
if ($#{$records} > 1) {
|
|
# ... typically in ServerHelloDone
|
|
@{$records}[-1]->version(TLSProxy::Record::VERS_TLS_1_1);
|
|
}
|
|
}
|
|
|
|
sub change_server_hello_version
|
|
{
|
|
my $proxy = shift;
|
|
my $records = $proxy->record_list;
|
|
|
|
# We're only interested in changing the ServerHello after an HRR
|
|
if ($proxy->flight != 3) {
|
|
return;
|
|
}
|
|
|
|
# The ServerHello has index 5
|
|
# 0 - ClientHello
|
|
# 1 - HRR
|
|
# 2 - CCS
|
|
# 3 - ClientHello(2)
|
|
# 4 - CCS
|
|
# 5 - ServerHello
|
|
@{$records}[5]->version(TLSProxy::Record::VERS_TLS_1_0);
|
|
}
|
|
|
|
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) == TLSProxy::Message::AL_DESC_UNEXPECTED_MESSAGE;
|
|
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) == TLSProxy::Message::AL_DESC_UNEXPECTED_MESSAGE;
|
|
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);
|
|
} elsif ($boundary_test_type == DATA_AFTER_KEY_UPDATE) {
|
|
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;
|
|
} else {
|
|
return if @{$proxy->{message_list}}[-1]->{mt}
|
|
!= TLSProxy::Message::MT_FINISHED;
|
|
|
|
my $record = TLSProxy::Record->new(
|
|
1,
|
|
TLSProxy::Record::RT_APPLICATION_DATA,
|
|
TLSProxy::Record::VERS_TLS_1_2,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
"",
|
|
""
|
|
);
|
|
|
|
#Add a partial KeyUpdate message into the record
|
|
$data = pack "C1",
|
|
0x18; # KeyUpdate message type. Omit the rest of the message header
|
|
|
|
#Add content type and tag
|
|
$data .= pack("C", TLSProxy::Record::RT_HANDSHAKE).("\0"x16);
|
|
|
|
$record->data($data);
|
|
$record->len(length $data);
|
|
push @{$records}, $record;
|
|
|
|
if ($boundary_test_type == DATA_BETWEEN_KEY_UPDATE) {
|
|
#Now add an app data record
|
|
$record = TLSProxy::Record->new(
|
|
1,
|
|
TLSProxy::Record::RT_APPLICATION_DATA,
|
|
TLSProxy::Record::VERS_TLS_1_2,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
"",
|
|
""
|
|
);
|
|
|
|
#Add an empty app data record (just content type and tag)
|
|
$data = pack("C", TLSProxy::Record::RT_APPLICATION_DATA).("\0"x16);
|
|
|
|
$record->data($data);
|
|
$record->len(length $data);
|
|
push @{$records}, $record;
|
|
}
|
|
|
|
#Now add the rest of the KeyUpdate message
|
|
$record = TLSProxy::Record->new(
|
|
1,
|
|
TLSProxy::Record::RT_APPLICATION_DATA,
|
|
TLSProxy::Record::VERS_TLS_1_2,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
"",
|
|
""
|
|
);
|
|
|
|
#Add the last 4 bytes of the KeyUpdate record
|
|
$data = pack "C4",
|
|
0x00, 0x00, 0x01, # Message length
|
|
0x00; # Update not requested
|
|
|
|
#Add content type and tag
|
|
$data .= pack("C", TLSProxy::Record::RT_HANDSHAKE).("\0"x16);
|
|
|
|
$record->data($data);
|
|
$record->len(length $data);
|
|
push @{$records}, $record;
|
|
|
|
}
|
|
}
|
|
|
|
sub empty_app_data
|
|
{
|
|
my $proxy = shift;
|
|
|
|
# We're only interested in the client's Certificate..Finished flight
|
|
if ($proxy->flight != 4) {
|
|
return;
|
|
}
|
|
|
|
my $data = pack "C52",
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, #IV
|
|
0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
|
|
0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, #One block of empty padded data
|
|
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
|
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
|
|
0x10, 0x11, 0x12, 0x13; #MAC, assume to be 20 bytes
|
|
|
|
# Add a zero length app data record at the end
|
|
# This will have the same sequence number as the subsequent app data record
|
|
# that s_client will send - which will cause that second record to be
|
|
# dropped. But that isn't important for this test.
|
|
my $record = TLSProxy::Record->new_dtls(
|
|
4,
|
|
TLSProxy::Record::RT_APPLICATION_DATA,
|
|
TLSProxy::Record::VERS_DTLS_1_2,
|
|
1,
|
|
1,
|
|
length($data),
|
|
0,
|
|
length($data),
|
|
0,
|
|
$data,
|
|
""
|
|
);
|
|
push @{$proxy->record_list}, $record;
|
|
}
|