openssl/test/recipes/70-test_comp.t
erbsland-dev 80008d4a94 Refactor and Enhance Compression Field Testing
Fixes #7940: Enhances the existing test for compression methods in the ClientHello message, aligning with RFC 8446 specifications.

Refactored the test code to improve modularity and maintainability, making it easier to extend and modify in the future.

Added checks for the appropriate alerts, ensuring that `SSL_AD_ILLEGAL_PARAMETER` or `SSL_AD_DECODE_ERROR` are correctly triggered as per the RFC 8446 guidelines.

Expanded Test Coverage: Introduced additional test cases to cover scenarios involving:
- Lists of unknown compression methods
- Absence of any compression method
- Validation of a single null compression method, which should always succeed.

Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/25255)
2024-08-29 19:16:38 +02:00

201 lines
6.7 KiB
Perl

#! /usr/bin/env perl
# Copyright 2017-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 OpenSSL::Test qw/:DEFAULT cmdstr srctop_file srctop_dir bldtop_dir/;
use OpenSSL::Test::Utils;
use File::Temp qw(tempfile);
use TLSProxy::Proxy;
my $test_name = "test_comp";
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.3 or TLSv1.2 enabled"
if disabled("tls1_3") && disabled("tls1_2");
# The injected compression field.
use constant {
MULTIPLE_COMPRESSIONS => 0, # Includes NULL, OK for >=TLS1.2
NON_NULL_COMPRESSION => 1, # Alert for all TLS versions
MULTIPLE_NO_NULL => 2, # Alert for all TLS versions
NO_COMPRESSION => 3, # Alert for all TLS versions
NULL_COMPRESSION => 4, # OK for all TLS versions
};
my %test_type_message = (
MULTIPLE_COMPRESSIONS, "multiple, including null compression",
NON_NULL_COMPRESSION, "one, not null compression",
MULTIPLE_NO_NULL, "multiple, no null compression",
NO_COMPRESSION, "no compression",
NULL_COMPRESSION, "one, null compression",
);
my %compression_field_for_test = (
# [null, unknown]
MULTIPLE_COMPRESSIONS, [0x00, 0xff],
# [unknown]
NON_NULL_COMPRESSION, [0xff],
# [unknown, unknown, unknown]
MULTIPLE_NO_NULL, [0xfd, 0xfe, 0xff],
# []
NO_COMPRESSION, [],
# [null]
NULL_COMPRESSION, [0x00],
);
my $testtype;
# The tested TLS version
use constant {
TEST_TLS_1_2 => 0, # Test TLSv1.2 and older
TEST_TLS_1_3 => 1, # Test TLSv1.3 and newer
};
my %test_tls_message = (
TEST_TLS_1_2, "TLS version 1.2 or older",
TEST_TLS_1_3, "TLS version 1.3 or newer",
);
# The expected result from a test
use constant {
EXPECT_SUCCESS => 0,
EXPECT_DECODE_ERROR => 1,
EXPECT_ILLEGAL_PARAMETER => 2,
};
my %expect_message = (
EXPECT_SUCCESS, "Expected success",
EXPECT_DECODE_ERROR, "Expected decode error",
EXPECT_ILLEGAL_PARAMETER, "Expected illegal parameter alert",
);
my $proxy = TLSProxy::Proxy->new(
undef,
cmdstr(app(["openssl"]), display => 1),
srctop_file("apps", "server.pem"),
(!$ENV{HARNESS_ACTIVE} || $ENV{HARNESS_VERBOSE})
);
$proxy->start() or plan skip_all => "Unable to start up Proxy for tests";
plan tests => 10;
SKIP: {
skip "TLSv1.2 disabled", 5 if disabled("tls1_2");
# Test 1: Check that sending multiple compression methods in a TLSv1.2
# ClientHello succeeds
do_test(TEST_TLS_1_2, MULTIPLE_COMPRESSIONS, EXPECT_SUCCESS);
# Test 2: Check that sending a non-null compression method in a TLSv1.2
# ClientHello results in an illegal parameter alert
do_test(TEST_TLS_1_2, NON_NULL_COMPRESSION, EXPECT_ILLEGAL_PARAMETER);
# Test 3: Check that sending multiple compression methods without null in
# a TLSv1.2 ClientHello results in an illegal parameter alert
do_test(TEST_TLS_1_2, MULTIPLE_NO_NULL, EXPECT_ILLEGAL_PARAMETER);
# Test 4: Check that sending no compression methods in a TLSv1.2
# ClientHello results in a decode error
do_test(TEST_TLS_1_2, NO_COMPRESSION, EXPECT_DECODE_ERROR);
# Test 5: Check that sending only null compression in a TLSv1.2
# ClientHello succeeds
do_test(TEST_TLS_1_2, NULL_COMPRESSION, EXPECT_SUCCESS);
}
SKIP: {
skip "TLSv1.3 disabled", 5
if disabled("tls1_3") || (disabled("ec") && disabled("dh"));
# Test 6: Check that sending multiple compression methods in a TLSv1.3
# ClientHello results in an illegal parameter alert
do_test(TEST_TLS_1_3, MULTIPLE_COMPRESSIONS, EXPECT_ILLEGAL_PARAMETER);
# Test 7: Check that sending a non-null compression method in a TLSv1.3
# ClientHello results in an illegal parameter alert
do_test(TEST_TLS_1_3, NON_NULL_COMPRESSION, EXPECT_ILLEGAL_PARAMETER);
# Test 8: Check that sending multiple compression methods without null in
# a TLSv1.3 ClientHello results in an illegal parameter alert
do_test(TEST_TLS_1_3, MULTIPLE_NO_NULL, EXPECT_ILLEGAL_PARAMETER);
# Test 9: Check that sending no compression methods in a TLSv1.3
# ClientHello results in a decode error
do_test(TEST_TLS_1_3, NO_COMPRESSION, EXPECT_DECODE_ERROR);
# Test 10: Check that sending only null compression in a TLSv1.3
# ClientHello succeeds
do_test(TEST_TLS_1_3, NULL_COMPRESSION, EXPECT_SUCCESS);
}
sub do_test
{
my $tls = shift; # The tested TLS version.
my $type = shift; # The test type to perform.
my $expect = shift; # The expected result.
$proxy->clear();
$proxy->filter(\&add_comp_filter);
if ($tls == TEST_TLS_1_2) {
$proxy->clientflags("-no_tls1_3");
} else {
$proxy->clientflags("-min_protocol TLSv1.3");
}
$testtype = $type;
$proxy->start();
print $expect, $tls, $type , "\n";
my $failure_message = $expect_message{$expect} . " for " .
$test_tls_message{$tls} . " with " .
$test_type_message{$type};
if ($expect == EXPECT_SUCCESS) {
ok(TLSProxy::Message->success(), $failure_message);
} elsif ($expect == EXPECT_DECODE_ERROR) {
ok(is_alert_message(TLSProxy::Message::AL_DESC_DECODE_ERROR),
$failure_message);
} elsif ($expect == EXPECT_ILLEGAL_PARAMETER) {
ok(is_alert_message(TLSProxy::Message::AL_DESC_ILLEGAL_PARAMETER),
$failure_message);
} else {
die "Unexpected test expectation: $expect";
}
}
# Test if the last message was a failure and matches the expected type.
sub is_alert_message
{
my $alert_type = shift;
return 0 unless TLSProxy::Message->fail();
return 1 if TLSProxy::Message->alert->description() == $alert_type;
return 0;
}
# Filter to insert the selected compression method into the hello message.
sub add_comp_filter
{
my $proxy = shift;
my $message;
my @comp;
# Only look at the ClientHello
return if $proxy->flight != 0;
$message = ${$proxy->message_list}[0];
return if (!defined $message
|| $message->mt != TLSProxy::Message::MT_CLIENT_HELLO);
@comp = @{$compression_field_for_test{$testtype}};
$message->comp_meths(\@comp);
$message->comp_meth_len(scalar @comp);
$message->repack();
}