summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--test/recipes/70-test_dtlsrecords.t153
-rw-r--r--test/recipes/70-test_sslrecords.t581
-rw-r--r--util/perl/TLSProxy/Proxy.pm6
3 files changed, 346 insertions, 394 deletions
diff --git a/test/recipes/70-test_dtlsrecords.t b/test/recipes/70-test_dtlsrecords.t
deleted file mode 100644
index dc223ea759..0000000000
--- a/test/recipes/70-test_dtlsrecords.t
+++ /dev/null
@@ -1,153 +0,0 @@
-#! /usr/bin/env perl
-# Copyright 2024 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;
-
-my $test_name = "test_dtlsrecords";
-setup($test_name);
-
-plan skip_all => "TLSProxy isn't usable on $^O"
- if $^O =~ /^(VMS|MSWin32)$/;
-
-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 DTLSv1.2 enabled"
- if disabled("dtls1_2");
-
-my $proxy = TLSProxy::Proxy->new_dtls(
- undef,
- cmdstr(app(["openssl"]), display => 1),
- srctop_file("apps", "server.pem"),
- (!$ENV{HARNESS_ACTIVE} || $ENV{HARNESS_VERBOSE})
-);
-
-plan tests => 4;
-
-my $fatal_alert = 0; # set by filters at expected fatal alerts
-my $inject_recs_num = 0; # used by add_empty_recs_filter
-my $proxy_start_success = 0;
-
-#Test 1: Injecting out of context empty records should succeed
-my $content_type = TLSProxy::Record::RT_APPLICATION_DATA;
-$inject_recs_num = 1;
-$proxy->serverflags("-min_protocol DTLSv1.2 -max_protocol DTLSv1.2");
-$proxy->clientflags("-max_protocol DTLSv1.2");
-$proxy->filter(\&add_empty_recs_filter);
-$proxy_start_success = $proxy->start();
-ok($proxy_start_success && TLSProxy::Message->success(), "Out of context empty records test");
-
-#Test 2: Injecting in context empty records should succeed
-$proxy->clear();
-$content_type = TLSProxy::Record::RT_HANDSHAKE;
-$inject_recs_num = 1;
-$proxy->serverflags("-min_protocol DTLSv1.2 -max_protocol DTLSv1.2");
-$proxy->clientflags("-max_protocol DTLSv1.2");
-$proxy->filter(\&add_empty_recs_filter);
-$proxy_start_success = $proxy->start();
-ok($proxy_start_success && TLSProxy::Message->success(), "In context empty records test");
-
-#Unrecognised record type tests
-
-#Test 3: Sending an unrecognised record type in DTLSv1.2 should fail
-$fatal_alert = 0;
-$proxy->clear();
-$proxy->serverflags("-min_protocol DTLSv1.2 -max_protocol DTLSv1.2");
-$proxy->clientflags("-max_protocol DTLSv1.2");
-$proxy->filter(\&add_unknown_record_type);
-ok($proxy->start() == 0, "Unrecognised record type in DTLS1.2");
-
-SKIP: {
- skip "DTLSv1 disabled", 1 if disabled("dtls1");
-
- #Test 4: Sending an unrecognised record type in DTLSv1 should fail
- $fatal_alert = 0;
- $proxy->clear();
- $proxy->clientflags("-min_protocol DTLSv1 -max_protocol DTLSv1 -cipher DEFAULT:\@SECLEVEL=0");
- $proxy->ciphers("AES128-SHA:\@SECLEVEL=0");
- $proxy->filter(\&add_unknown_record_type);
- ok($proxy->start() == 0, "Unrecognised record type in DTLSv1");
-}
-
-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) == TLSProxy::Message::AL_DESC_UNEXPECTED_MESSAGE;
- return;
- }
-
- for (my $i = 0; $i < $inject_recs_num; $i++) {
- my $record = TLSProxy::Record->new_dtls(
- 0,
- $content_type,
- TLSProxy::Record::VERS_TLS_1_2,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- "",
- ""
- );
- push @{$records}, $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) == TLSProxy::Message::AL_DESC_UNEXPECTED_MESSAGE;
- return;
- }
-
- my $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"
- );
-
- #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;
-}
diff --git a/test/recipes/70-test_sslrecords.t b/test/recipes/70-test_sslrecords.t
index 43e288b63e..02110714e9 100644
--- a/test/recipes/70-test_sslrecords.t
+++ b/test/recipes/70-test_sslrecords.t
@@ -29,248 +29,311 @@ plan skip_all => "$test_name needs the sock feature enabled"
plan skip_all => "$test_name needs TLSv1.2 enabled"
if disabled("tls1_2");
-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->clientflags("-no_tls1_3");
-$proxy->start() or plan skip_all => "Unable to start up Proxy for tests";
-plan tests => 21;
-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->clientflags("-no_tls1_3");
-$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->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");
-
-#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
-};
-
-# The TLSv1.2 in SSLv2 ClientHello need to run at security level 0
-# because in a SSLv2 ClientHello we can't send extensions to indicate
-# which signature algorithm we want to use, and the default is SHA1.
-
-#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->clientflags("-no_tls1_3 -legacy_renegotiation");
-$proxy->ciphers("AES128-SHA:\@SECLEVEL=0");
-$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->clientflags("-no_tls1_3");
-$proxy->ciphers("AES128-SHA:\@SECLEVEL=0");
-$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->clientflags("-no_tls1_3");
-$proxy->ciphers("AES128-SHA:\@SECLEVEL=0");
-$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->clientflags("-no_tls1_3");
-$proxy->ciphers("AES128-SHA:\@SECLEVEL=0");
-$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->clientflags("-no_tls1_3");
-$proxy->ciphers("AES128-SHA:\@SECLEVEL=0");
-$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->clientflags("-no_tls1_3");
-$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;
+my $testplanisset = 0;
+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 $sslv2testtype = undef;
+my $proxy_start_success = 0;
+
+# Run tests with TLS
+run_tests(0);
+# Run tests with DTLS
+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
+ $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() or plan skip_all => "Unable to start up Proxy for tests";
+ if ($testplanisset == 0) {
+ plan tests => 42;
+ $testplanisset = 1;
+ }
+ ok($fatal_alert, "Out of context empty records test");
+ }
+
+ #Test 2: Injecting in context empty records should succeed
$proxy->clear();
- $proxy->clientflags("-tls1_1 -cipher DEFAULT:\@SECLEVEL=0");
- $proxy->ciphers("AES128-SHA:\@SECLEVEL=0");
- $proxy->start();
- ok($fatal_alert, "Unrecognised record type in TLS1.1");
-}
+ $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();
+ ok($proxy_start_success && TLSProxy::Message->success(),
+ "In context empty records test".($run_test_as_dtls == 1) ? " for DTLS" : " for TLS");
-#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");
+ SKIP: {
+ skip "Record tests not intended for dtls", 7 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");
-#TLS1.3 specific tests
-SKIP: {
- skip "TLSv1.3 disabled", 9
- if disabled("tls1_3") || (disabled("ec") && disabled("dh"));
+ #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");
- #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");
+ #Run some SSLv2 ClientHello tests
- #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");
+ 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 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,
- DATA_BETWEEN_KEY_UPDATE => 3,
- NO_DATA_BETWEEN_KEY_UPDATE => 4,
- };
-
- #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(\&not_on_record_boundary);
- $proxy->start();
- ok($fatal_alert, "Record not on boundary in TLS1.3 (ServerHello)");
+ # The TLSv1.2 in SSLv2 ClientHello need to run at security level 0
+ # because in a SSLv2 ClientHello we can't send extensions to indicate
+ # which signature algorithm we want to use, and the default is SHA1.
- #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->start();
- ok($fatal_alert, "Record not on boundary in TLS1.3 (Finished)");
+ #Test 5: Inject an SSLv2 style record format for a TLSv1.2 ClientHello
+ $sslv2testtype = TLSV1_2_IN_SSLV2;
+ $proxy->clear();
+ $proxy->filter(\&add_sslv2_filter);
+ $proxy->serverflags("-tls1_2");
+ $proxy->clientflags("-no_tls1_3 -legacy_renegotiation");
+ $proxy->ciphers("AES128-SHA:\@SECLEVEL=0");
+ $proxy->start();
+ ok(TLSProxy::Message->success(), "TLSv1.2 in SSLv2 ClientHello test");
- #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->start();
- ok($fatal_alert, "Record not on boundary in TLS1.3 (KeyUpdate)");
+ #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->clientflags("-no_tls1_3");
+ $proxy->ciphers("AES128-SHA:\@SECLEVEL=0");
+ $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->clientflags("-no_tls1_3");
+ $proxy->ciphers("AES128-SHA:\@SECLEVEL=0");
+ $proxy->start();
+ ok(TLSProxy::Message->success(), "Fragmented ClientHello in TLSv1.2 test");
- #Test 19: 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.
+ #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->clientflags("-no_tls1_3");
+ $proxy->ciphers("AES128-SHA:\@SECLEVEL=0");
+ $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->clientflags("-no_tls1_3");
+ $proxy->ciphers("AES128-SHA:\@SECLEVEL=0");
+ $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();
- $boundary_test_type = DATA_BETWEEN_KEY_UPDATE;
- $proxy->start();
- ok($fatal_alert, "Data between KeyUpdate");
+ 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();
- #Test 20: 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");
+ 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 11: 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 "EC disabled", 1 if disabled("ec");
-
- #Test 21: 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.
+ skip "Record tests not intended for dtls", 10 if $run_test_as_dtls == 1;
+ #Test 12: Sending a different record version in TLS1.2 should fail
+ $fatal_alert = 0;
$proxy->clear();
- $proxy->filter(\&change_server_hello_version);
- $proxy->serverflags("-groups P-256"); # Force an HRR
+ $proxy->clientflags("-tls1_2");
+ $proxy->filter(\&change_version);
$proxy->start();
- ok(TLSProxy::Message->success(), "Bad ServerHello record version after HRR");
+ 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 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,
+ DATA_BETWEEN_KEY_UPDATE => 3,
+ NO_DATA_BETWEEN_KEY_UPDATE => 4,
+ };
+
+ #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(\&not_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->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->start();
+ ok($fatal_alert, "Record not on boundary in TLS1.3 (KeyUpdate)");
+
+ #Test 19: 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 20: 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 21: 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");
+ }
+ }
}
- }
+}
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) {
@@ -279,17 +342,34 @@ sub add_empty_recs_filter
}
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,
- "",
- ""
- );
+ 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;
}
}
@@ -501,6 +581,7 @@ 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
@@ -512,17 +593,35 @@ sub add_unknown_record_type
return;
}
- my $record = TLSProxy::Record->new(
- 1,
- TLSProxy::Record::RT_UNKNOWN,
- @{$records}[-1]->version(),
- 1,
- 0,
- 1,
- 1,
- "X",
- "X"
- );
+ 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;
diff --git a/util/perl/TLSProxy/Proxy.pm b/util/perl/TLSProxy/Proxy.pm
index 3ecbd1893e..06de4fbb39 100644
--- a/util/perl/TLSProxy/Proxy.pm
+++ b/util/perl/TLSProxy/Proxy.pm
@@ -750,4 +750,10 @@ sub ciphersuite
return $ciphersuite;
}
+sub isdtls
+{
+ my $self = shift;
+ return $self->{isdtls}; #read-only
+}
+
1;