curves.pl: test with each elliptic curve enabled

Previously curves.pl tested with all elliptic curves enabled except
one, for each curve. This catches tests that are missing dependencies
on one of the curve that they use, but does not catch misplaced
conditional directives around parts of the library.

Now, we additionally test with a single curve, for each curve. This
catches missing or extraneous guards around code that is specific to
one particular curve or to a class of curves.

Signed-off-by: Gilles Peskine <gilles.peskine@arm.com>
This commit is contained in:
Gilles Peskine 2018-09-17 18:40:33 +02:00
parent a088c81fcb
commit a2611604d4

View File

@ -2,7 +2,7 @@
# curves.pl # curves.pl
# #
# Copyright (c) 2014-2016, ARM Limited, All Rights Reserved # Copyright (c) 2014-2020, ARM Limited, All Rights Reserved
# SPDX-License-Identifier: Apache-2.0 # SPDX-License-Identifier: Apache-2.0
# #
# Licensed under the Apache License, Version 2.0 (the "License"); you may # Licensed under the Apache License, Version 2.0 (the "License"); you may
@ -21,21 +21,25 @@
# #
# Purpose # Purpose
# #
# To test the code dependencies on individual curves in each test suite. This # The purpose of this test script is to validate that the library works
# is a verification step to ensure we don't ship test suites that do not work # with any combination of elliptic curves. To this effect, build the library
# for some build options. # and run the test suite with each tested combination of elliptic curves.
# #
# The process is: # Testing all 2^n combinations would be too much, so we only test 2*n:
# for each possible curve
# build the library and test suites with the curve disabled
# execute the test suites
#
# And any test suite with the wrong dependencies will fail.
# #
# 1. Test with a single curve, for each curve. This validates that the
# library works with any curve, and in particular that curve-specific
# code is guarded by the proper preprocessor conditionals.
# 2. Test with all curves except one, for each curve. This validates that
# the test cases have correct dependencies. Testing with a single curve
# doesn't validate this for tests that require more than one curve.
# Usage: tests/scripts/curves.pl # Usage: tests/scripts/curves.pl
# #
# This script should be executed from the root of the project directory. # This script should be executed from the root of the project directory.
# #
# Only curves that are enabled in config.h will be tested.
#
# For best effect, run either with cmake disabled, or cmake enabled in a mode # For best effect, run either with cmake disabled, or cmake enabled in a mode
# that includes -Werror. # that includes -Werror.
@ -48,6 +52,25 @@ my $sed_cmd = 's/^#define \(MBEDTLS_ECP_DP.*_ENABLED\)/\1/p';
my $config_h = 'include/mbedtls/config.h'; my $config_h = 'include/mbedtls/config.h';
my @curves = split( /\s+/, `sed -n -e '$sed_cmd' $config_h` ); my @curves = split( /\s+/, `sed -n -e '$sed_cmd' $config_h` );
# Determine which curves support ECDSA by checking the dependencies of
# ECDSA in check_config.h.
my %curve_supports_ecdsa = ();
{
local $/ = "";
local *CHECK_CONFIG;
open(CHECK_CONFIG, '<', 'include/mbedtls/check_config.h')
or die "open include/mbedtls/check_config.h: $!";
while (my $stanza = <CHECK_CONFIG>) {
if ($stanza =~ /\A#if defined\(MBEDTLS_ECDSA_C\)/) {
for my $curve ($stanza =~ /(?<=\()MBEDTLS_ECP_DP_\w+_ENABLED(?=\))/g) {
$curve_supports_ecdsa{$curve} = 1;
}
last;
}
}
close(CHECK_CONFIG);
}
system( "cp $config_h $config_h.bak" ) and die; system( "cp $config_h $config_h.bak" ) and die;
sub abort { sub abort {
system( "mv $config_h.bak $config_h" ) and warn "$config_h not restored\n"; system( "mv $config_h.bak $config_h" ) and warn "$config_h not restored\n";
@ -56,6 +79,46 @@ sub abort {
exit 1; exit 1;
} }
# Disable all the curves. We'll then re-enable them one by one.
for my $curve (@curves) {
system( "scripts/config.pl unset $curve" )
and abort "Failed to disable $curve\n";
}
# Depends on a specific curve. Also, ignore error if it wasn't enabled.
system( "scripts/config.pl unset MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED" );
# Test with only $curve enabled, for each $curve.
for my $curve (@curves) {
system( "make clean" ) and die;
print "\n******************************************\n";
print "* Testing with only curve: $curve\n";
print "******************************************\n";
$ENV{MBEDTLS_TEST_CONFIGURATION} = "$curve";
system( "scripts/config.pl set $curve" )
and abort "Failed to enable $curve\n";
my $ecdsa = $curve_supports_ecdsa{$curve} ? "set" : "unset";
for my $dep (qw(MBEDTLS_ECDSA_C
MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED
MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)) {
system( "scripts/config.pl $ecdsa $dep" )
and abort "Failed to $ecdsa $dep\n";
}
system( "CFLAGS='-Werror -Wall -Wextra' make" )
and abort "Failed to build: only $curve\n";
system( "make test" )
and abort "Failed test suite: only $curve\n";
system( "scripts/config.pl unset $curve" )
and abort "Failed to disable $curve\n";
}
system( "cp $config_h.bak $config_h" ) and die "$config_h not restored\n";
# Test with $curve disabled but the others enabled, for each $curve.
for my $curve (@curves) { for my $curve (@curves) {
system( "cp $config_h.bak $config_h" ) and die "$config_h not restored\n"; system( "cp $config_h.bak $config_h" ) and die "$config_h not restored\n";
system( "make clean" ) and die; system( "make clean" ) and die;
@ -71,10 +134,10 @@ for my $curve (@curves) {
system( "scripts/config.py unset $curve" ) system( "scripts/config.py unset $curve" )
and abort "Failed to disable $curve\n"; and abort "Failed to disable $curve\n";
system( "CFLAGS='-Werror -Wall -Wextra' make lib" ) system( "CFLAGS='-Werror -Wall -Wextra' make" )
and abort "Failed to build lib: $curve\n"; and abort "Failed to build: all but $curve\n";
system( "make" ) and abort "Failed to build tests: $curve\n"; system( "make test" )
system( "make test" ) and abort "Failed test suite: $curve\n"; and abort "Failed test suite: all but $curve\n";
} }