Merge pull request #321 from dgreen-arm/config_py

Replace config.pl by config.py
This commit is contained in:
Jaeden Amero 2019-11-14 16:56:12 +00:00 committed by GitHub
commit 63ad668145
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 764 additions and 427 deletions

View File

@ -10,7 +10,7 @@ set(everest_src
list(APPEND everest_inc ${CMAKE_CURRENT_SOURCE_DIR}/include ${CMAKE_CURRENT_SOURCE_DIR}/include/everest ${CMAKE_CURRENT_SOURCE_DIR}/include/everest/kremlib)
execute_process(COMMAND ${PERL_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/../../scripts/config.pl -f ${CMAKE_CURRENT_SOURCE_DIR}/../../include/mbedtls/config.h get MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED RESULT_VARIABLE result)
execute_process(COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/../../scripts/config.py -f ${CMAKE_CURRENT_SOURCE_DIR}/../../include/mbedtls/config.h get MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED RESULT_VARIABLE result)
if(${result} EQUAL 0)

View File

@ -46,19 +46,19 @@ set(CTR_DRBG_128_BIT_KEY_WARNING "${WARNING_BORDER}"
"${CTR_DRBG_128_BIT_KEY_WARN_L3}"
"${WARNING_BORDER}")
find_package(PythonInterp)
find_package(Perl)
if(PERL_FOUND)
# Python 3 is only needed here to check for configuration warnings.
find_package(PythonInterp 3)
if(PYTHONINTERP_FOUND)
# If 128-bit keys are configured for CTR_DRBG, display an appropriate warning
execute_process(COMMAND ${PERL_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/scripts/config.pl -f ${CMAKE_CURRENT_SOURCE_DIR}/include/mbedtls/config.h get MBEDTLS_CTR_DRBG_USE_128_BIT_KEY
execute_process(COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/scripts/config.py -f ${CMAKE_CURRENT_SOURCE_DIR}/include/mbedtls/config.h get MBEDTLS_CTR_DRBG_USE_128_BIT_KEY
RESULT_VARIABLE result)
if(${result} EQUAL 0)
message(WARNING ${CTR_DRBG_128_BIT_KEY_WARNING})
endif()
# If NULL Entropy is configured, display an appropriate warning
execute_process(COMMAND ${PERL_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/scripts/config.pl -f ${CMAKE_CURRENT_SOURCE_DIR}/include/mbedtls/config.h get MBEDTLS_TEST_NULL_ENTROPY
execute_process(COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/scripts/config.py -f ${CMAKE_CURRENT_SOURCE_DIR}/include/mbedtls/config.h get MBEDTLS_TEST_NULL_ENTROPY
RESULT_VARIABLE result)
if(${result} EQUAL 0)
message(WARNING ${NULL_ENTROPY_WARNING})

View File

@ -70,11 +70,11 @@ post_build:
ifndef WINDOWS
# If 128-bit keys are configured for CTR_DRBG, display an appropriate warning
-scripts/config.pl get MBEDTLS_CTR_DRBG_USE_128_BIT_KEY && ([ $$? -eq 0 ]) && \
-scripts/config.py get MBEDTLS_CTR_DRBG_USE_128_BIT_KEY && ([ $$? -eq 0 ]) && \
echo '$(CTR_DRBG_128_BIT_KEY_WARNING)'
# If NULL Entropy is configured, display an appropriate warning
-scripts/config.pl get MBEDTLS_TEST_NULL_ENTROPY && ([ $$? -eq 0 ]) && \
-scripts/config.py get MBEDTLS_TEST_NULL_ENTROPY && ([ $$? -eq 0 ]) && \
echo '$(NULL_ENTROPY_WARNING)'
endif

View File

@ -45,7 +45,7 @@
#endif
/* Fix the config here. Not convenient to put an #ifdef _WIN32 in config.h as
* it would confuse config.pl. */
* it would confuse config.py. */
#if !defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) && \
!defined(MBEDTLS_PLATFORM_SNPRINTF_MACRO)
#define MBEDTLS_PLATFORM_SNPRINTF_ALT

View File

@ -19,7 +19,7 @@ fi
CONFIG_BAK=${CONFIG_H}.bak
cp -p $CONFIG_H $CONFIG_BAK
scripts/config.pl realfull
scripts/config.py realfull
make apidoc
mv $CONFIG_BAK $CONFIG_H

View File

@ -1,296 +1,27 @@
#!/usr/bin/env perl
#
# This file is part of mbed TLS (https://tls.mbed.org)
#
# Copyright (c) 2014-2016, ARM Limited, All Rights Reserved
#
# Purpose
#
# Comments and uncomments #define lines in the given header file and optionally
# sets their value or can get the value. This is to provide scripting control of
# what preprocessor symbols, and therefore what build time configuration flags
# are set in the 'config.h' file.
#
# Usage: config.pl [-f <file> | --file <file>] [-o | --force]
# [set <symbol> <value> | unset <symbol> | get <symbol> |
# full | realfull]
#
# Full usage description provided below.
#
# The following options are disabled instead of enabled with "full".
#
# MBEDTLS_TEST_NULL_ENTROPY
# MBEDTLS_DEPRECATED_REMOVED
# MBEDTLS_HAVE_SSE2
# MBEDTLS_PLATFORM_NO_STD_FUNCTIONS
# MBEDTLS_ECP_DP_M221_ENABLED
# MBEDTLS_ECP_DP_M383_ENABLED
# MBEDTLS_ECP_DP_M511_ENABLED
# MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES
# MBEDTLS_NO_PLATFORM_ENTROPY
# MBEDTLS_RSA_NO_CRT
# MBEDTLS_PSA_CRYPTO_SPM
# MBEDTLS_PSA_INJECT_ENTROPY
# MBEDTLS_ECP_RESTARTABLE
# and any symbol beginning _ALT
#
# Backward compatibility redirection
use warnings;
use strict;
## Copyright (C) 2019, ARM Limited, All Rights Reserved
## SPDX-License-Identifier: Apache-2.0
##
## Licensed under the Apache License, Version 2.0 (the "License"); you may
## not use this file except in compliance with the License.
## You may obtain a copy of the License at
##
## http://www.apache.org/licenses/LICENSE-2.0
##
## Unless required by applicable law or agreed to in writing, software
## distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
## WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
## See the License for the specific language governing permissions and
## limitations under the License.
##
## This file is part of Mbed TLS (https://tls.mbed.org)
my $config_file = "include/mbedtls/config.h";
my $usage = <<EOU;
$0 [-f <file> | --file <file>] [-o | --force]
[set <symbol> <value> | unset <symbol> | get <symbol> |
full | realfull | baremetal]
Commands
set <symbol> [<value>] - Uncomments or adds a #define for the <symbol> to
the configuration file, and optionally making it
of <value>.
If the symbol isn't present in the file an error
is returned.
unset <symbol> - Comments out the #define for the given symbol if
present in the configuration file.
get <symbol> - Finds the #define for the given symbol, returning
an exitcode of 0 if the symbol is found, and 1 if
not. The value of the symbol is output if one is
specified in the configuration file.
full - Uncomments all #define's in the configuration file
excluding some reserved symbols, until the
'Module configuration options' section
realfull - Uncomments all #define's with no exclusions
baremetal - Sets full configuration suitable for baremetal build.
Options
-f | --file <filename> - The file or file path for the configuration file
to edit. When omitted, the following default is
used:
$config_file
-o | --force - If the symbol isn't present in the configuration
file when setting its value, a #define is
appended to the end of the file.
EOU
my @excluded = qw(
MBEDTLS_TEST_NULL_ENTROPY
MBEDTLS_DEPRECATED_REMOVED
MBEDTLS_HAVE_SSE2
MBEDTLS_PLATFORM_NO_STD_FUNCTIONS
MBEDTLS_CTR_DRBG_USE_128_BIT_KEY
MBEDTLS_ECP_DP_M221_ENABLED
MBEDTLS_ECP_DP_M383_ENABLED
MBEDTLS_ECP_DP_M511_ENABLED
MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES
MBEDTLS_NO_PLATFORM_ENTROPY
MBEDTLS_RSA_NO_CRT
MBEDTLS_NO_UDBL_DIVISION
MBEDTLS_NO_64BIT_MULTIPLICATION
MBEDTLS_PSA_CRYPTO_SE_C
MBEDTLS_PSA_CRYPTO_SPM
MBEDTLS_PSA_CRYPTO_KEY_FILE_ID_ENCODES_OWNER
MBEDTLS_PSA_INJECT_ENTROPY
MBEDTLS_ECP_RESTARTABLE
MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED
_ALT\s*$
);
# Things that should be disabled in "baremetal"
my @excluded_baremetal = qw(
MBEDTLS_TIMING_C
MBEDTLS_FS_IO
MBEDTLS_ENTROPY_NV_SEED
MBEDTLS_HAVE_TIME
MBEDTLS_HAVE_TIME_DATE
MBEDTLS_DEPRECATED_WARNING
MBEDTLS_HAVEGE_C
MBEDTLS_THREADING_C
MBEDTLS_THREADING_PTHREAD
MBEDTLS_MEMORY_BACKTRACE
MBEDTLS_MEMORY_BUFFER_ALLOC_C
MBEDTLS_PLATFORM_TIME_ALT
MBEDTLS_PLATFORM_FPRINTF_ALT
MBEDTLS_PSA_ITS_FILE_C
MBEDTLS_PSA_CRYPTO_SE_C
MBEDTLS_PSA_CRYPTO_STORAGE_C
);
# Things that should be enabled in "full" even if they match @excluded
my @non_excluded = qw(
PLATFORM_[A-Z0-9]+_ALT
);
# Things that should be enabled in "baremetal"
my @non_excluded_baremetal = qw(
MBEDTLS_NO_PLATFORM_ENTROPY
);
# Process the command line arguments
my $force_option = 0;
my ($arg, $name, $value, $action);
while ($arg = shift) {
# Check if the argument is an option
if ($arg eq "-f" || $arg eq "--file") {
$config_file = shift;
-f $config_file or die "No such file: $config_file\n";
}
elsif ($arg eq "-o" || $arg eq "--force") {
$force_option = 1;
}
else
{
# ...else assume it's a command
$action = $arg;
if ($action eq "full" || $action eq "realfull" || $action eq "baremetal" ) {
# No additional parameters
die $usage if @ARGV;
}
elsif ($action eq "unset" || $action eq "get") {
die $usage unless @ARGV;
$name = shift;
}
elsif ($action eq "set") {
die $usage unless @ARGV;
$name = shift;
$value = shift if @ARGV;
}
else {
die "Command '$action' not recognised.\n\n".$usage;
}
}
}
# If no command was specified, exit...
if ( not defined($action) ){ die $usage; }
# Check the config file is present
if (! -f $config_file) {
chdir '..' or die;
# Confirm this is the project root directory and try again
if ( !(-d 'scripts' && -d 'include' && -d 'library' && -f $config_file) ) {
die "If no file specified, must be run from the project root or scripts directory.\n";
}
}
# Now read the file and process the contents
open my $config_read, '<', $config_file or die "read $config_file: $!\n";
my @config_lines = <$config_read>;
close $config_read;
# Add required baremetal symbols to the list that is included.
if ( $action eq "baremetal" ) {
@non_excluded = ( @non_excluded, @non_excluded_baremetal );
}
my ($exclude_re, $no_exclude_re, $exclude_baremetal_re);
if ($action eq "realfull") {
$exclude_re = qr/^$/;
$no_exclude_re = qr/./;
} else {
$exclude_re = join '|', @excluded;
$no_exclude_re = join '|', @non_excluded;
}
if ( $action eq "baremetal" ) {
$exclude_baremetal_re = join '|', @excluded_baremetal;
}
my $config_write = undef;
if ($action ne "get") {
open $config_write, '>', $config_file or die "write $config_file: $!\n";
}
my $done;
for my $line (@config_lines) {
if ($action eq "full" || $action eq "realfull" || $action eq "baremetal" ) {
if ($line =~ /name SECTION: Module configuration options/) {
$done = 1;
}
if (!$done && $line =~ m!^//\s?#define! &&
( $line !~ /$exclude_re/ || $line =~ /$no_exclude_re/ ) &&
( $action ne "baremetal" || ( $line !~ /$exclude_baremetal_re/ ) ) ) {
$line =~ s!^//\s?!!;
}
if (!$done && $line =~ m!^\s?#define! &&
! ( ( $line !~ /$exclude_re/ || $line =~ /$no_exclude_re/ ) &&
( $action ne "baremetal" || ( $line !~ /$exclude_baremetal_re/ ) ) ) ) {
$line =~ s!^!//!;
}
} elsif ($action eq "unset") {
if (!$done && $line =~ /^\s*#define\s*$name\b/) {
$line = '//' . $line;
$done = 1;
}
} elsif (!$done && $action eq "set") {
if ($line =~ m!^(?://)?\s*#define\s*$name\b!) {
$line = "#define $name";
$line .= " $value" if defined $value && $value ne "";
$line .= "\n";
$done = 1;
}
} elsif (!$done && $action eq "get") {
if ($line =~ /^\s*#define\s*$name(?:\s+(.*?))\s*(?:$|\/\*|\/\/)/) {
$value = $1;
$done = 1;
}
}
if (defined $config_write) {
print $config_write $line or die "write $config_file: $!\n";
}
}
# Did the set command work?
if ($action eq "set" && $force_option && !$done) {
# If the force option was set, append the symbol to the end of the file
my $line = "#define $name";
$line .= " $value" if defined $value && $value ne "";
$line .= "\n";
$done = 1;
print $config_write $line or die "write $config_file: $!\n";
}
if (defined $config_write) {
close $config_write or die "close $config_file: $!\n";
}
if ($action eq "get") {
if ($done) {
if ($value ne '') {
print "$value\n";
}
exit 0;
} else {
# If the symbol was not found, return an error
exit 1;
}
}
if ($action eq "full" && !$done) {
die "Configuration section was not found in $config_file\n";
}
if ($action ne "full" && $action ne "unset" && !$done) {
die "A #define for the symbol $name was not found in $config_file\n";
}
__END__
my $py = $0;
$py =~ s/\.pl$/.py/;
exec 'python3', $py, @ARGV;
print STDERR "$0: python3: $!\n";
exec 'python', $py, @ARGV;
print STDERR "$0: python: $!\n";
exit 127;

419
scripts/config.py Executable file
View File

@ -0,0 +1,419 @@
#!/usr/bin/env python3
"""Mbed TLS configuration file manipulation library and tool
Basic usage, to read the Mbed TLS or Mbed Crypto configuration:
config = ConfigFile()
if 'MBEDTLS_RSA_C' in config: print('RSA is enabled')
"""
## Copyright (C) 2019, ARM Limited, All Rights Reserved
## SPDX-License-Identifier: Apache-2.0
##
## Licensed under the Apache License, Version 2.0 (the "License"); you may
## not use this file except in compliance with the License.
## You may obtain a copy of the License at
##
## http://www.apache.org/licenses/LICENSE-2.0
##
## Unless required by applicable law or agreed to in writing, software
## distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
## WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
## See the License for the specific language governing permissions and
## limitations under the License.
##
## This file is part of Mbed TLS (https://tls.mbed.org)
import os
import re
class Setting:
"""Representation of one Mbed TLS config.h setting.
Fields:
* name: the symbol name ('MBEDTLS_xxx').
* value: the value of the macro. The empty string for a plain #define
with no value.
* active: True if name is defined, False if a #define for name is
present in config.h but commented out.
* section: the name of the section that contains this symbol.
"""
# pylint: disable=too-few-public-methods
def __init__(self, active, name, value='', section=None):
self.active = active
self.name = name
self.value = value
self.section = section
class Config:
"""Representation of the Mbed TLS configuration.
In the documentation of this class, a symbol is said to be *active*
if there is a #define for it that is not commented out, and *known*
if there is a #define for it whether commented out or not.
This class supports the following protocols:
* `name in config` is `True` if the symbol `name` is active, `False`
otherwise (whether `name` is inactive or not known).
* `config[name]` is the value of the macro `name`. If `name` is inactive,
raise `KeyError` (even if `name` is known).
* `config[name] = value` sets the value associated to `name`. `name`
must be known, but does not need to be set. This does not cause
name to become set.
"""
def __init__(self):
self.settings = {}
def __contains__(self, name):
"""True if the given symbol is active (i.e. set).
False if the given symbol is not set, even if a definition
is present but commented out.
"""
return name in self.settings and self.settings[name].active
def all(self, *names):
"""True if all the elements of names are active (i.e. set)."""
return all(self.__contains__(name) for name in names)
def any(self, *names):
"""True if at least one symbol in names are active (i.e. set)."""
return any(self.__contains__(name) for name in names)
def known(self, name):
"""True if a #define for name is present, whether it's commented out or not."""
return name in self.settings
def __getitem__(self, name):
"""Get the value of name, i.e. what the preprocessor symbol expands to.
If name is not known, raise KeyError. name does not need to be active.
"""
return self.settings[name].value
def get(self, name, default=None):
"""Get the value of name. If name is inactive (not set), return default.
If a #define for name is present and not commented out, return
its expansion, even if this is the empty string.
If a #define for name is present but commented out, return default.
"""
if name in self.settings:
return self.settings[name].value
else:
return default
def __setitem__(self, name, value):
"""If name is known, set its value.
If name is not known, raise KeyError.
"""
self.settings[name].value = value
def set(self, name, value=None):
"""Set name to the given value and make it active.
If value is None and name is already known, don't change its value.
If value is None and name is not known, set its value to the empty
string.
"""
if name in self.settings:
if value is not None:
self.settings[name].value = value
self.settings[name].active = True
else:
self.settings[name] = Setting(True, name, value=value)
def unset(self, name):
"""Make name unset (inactive).
name remains known if it was known before.
"""
if name not in self.settings:
return
self.settings[name].active = False
def adapt(self, adapter):
"""Run adapter on each known symbol and (de)activate it accordingly.
`adapter` must be a function that returns a boolean. It is called as
`adapter(name, active, section)` for each setting, where `active` is
`True` if `name` is set and `False` if `name` is known but unset,
and `section` is the name of the section containing `name`. If
`adapter` returns `True`, then set `name` (i.e. make it active),
otherwise unset `name` (i.e. make it known but inactive).
"""
for setting in self.settings.values():
setting.active = adapter(setting.name, setting.active,
setting.section)
def is_full_section(section):
"""Is this section affected by "config.py full" and friends?"""
return section.endswith('support') or section.endswith('modules')
def realfull_adapter(_name, active, section):
"""Activate all symbols found in the system and feature sections."""
if not is_full_section(section):
return active
return True
def include_in_full(name):
"""Rules for symbols in the "full" configuration."""
if re.search(r'PLATFORM_[A-Z0-9]+_ALT', name):
return True
if name in [
'MBEDTLS_CTR_DRBG_USE_128_BIT_KEY',
'MBEDTLS_DEPRECATED_REMOVED',
'MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED',
'MBEDTLS_ECP_RESTARTABLE',
'MBEDTLS_HAVE_SSE2',
'MBEDTLS_NO_64BIT_MULTIPLICATION',
'MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES',
'MBEDTLS_NO_PLATFORM_ENTROPY',
'MBEDTLS_NO_UDBL_DIVISION',
'MBEDTLS_PLATFORM_NO_STD_FUNCTIONS',
'MBEDTLS_PSA_CRYPTO_KEY_FILE_ID_ENCODES_OWNER',
'MBEDTLS_PSA_CRYPTO_SE_C',
'MBEDTLS_PSA_CRYPTO_SPM',
'MBEDTLS_PSA_INJECT_ENTROPY',
'MBEDTLS_RSA_NO_CRT',
'MBEDTLS_TEST_NULL_ENTROPY',
]:
return False
if name.endswith('_ALT'):
return False
return True
def full_adapter(name, active, section):
"""Config adapter for "full"."""
if not is_full_section(section):
return active
return include_in_full(name)
def keep_in_baremetal(name):
"""Rules for symbols in the "baremetal" configuration."""
if name in [
'MBEDTLS_DEPRECATED_WARNING',
'MBEDTLS_ENTROPY_NV_SEED',
'MBEDTLS_FS_IO',
'MBEDTLS_HAVEGE_C',
'MBEDTLS_HAVE_TIME',
'MBEDTLS_HAVE_TIME_DATE',
'MBEDTLS_MEMORY_BACKTRACE',
'MBEDTLS_MEMORY_BUFFER_ALLOC_C',
'MBEDTLS_PLATFORM_FPRINTF_ALT',
'MBEDTLS_PLATFORM_TIME_ALT',
'MBEDTLS_PSA_CRYPTO_SE_C',
'MBEDTLS_PSA_CRYPTO_STORAGE_C',
'MBEDTLS_PSA_ITS_FILE_C',
'MBEDTLS_THREADING_C',
'MBEDTLS_THREADING_PTHREAD',
'MBEDTLS_TIMING_C',
]:
return False
return True
def baremetal_adapter(name, active, section):
"""Config adapter for "baremetal"."""
if not is_full_section(section):
return active
if name == 'MBEDTLS_NO_PLATFORM_ENTROPY':
return True
return include_in_full(name) and keep_in_baremetal(name)
class ConfigFile(Config):
"""Representation of the Mbed TLS configuration read for a file.
See the documentation of the `Config` class for methods to query
and modify the configuration.
"""
_path_in_tree = 'include/mbedtls/config.h'
default_path = [_path_in_tree,
os.path.join(os.path.dirname(__file__),
os.pardir,
_path_in_tree),
os.path.join(os.path.dirname(os.path.abspath(os.path.dirname(__file__))),
_path_in_tree)]
def __init__(self, filename=None):
"""Read the Mbed TLS configuration file."""
if filename is None:
for filename in self.default_path:
if os.path.lexists(filename):
break
super().__init__()
self.filename = filename
self.current_section = 'header'
with open(filename, 'r', encoding='utf-8') as file:
self.templates = [self._parse_line(line) for line in file]
self.current_section = None
def set(self, name, value=None):
if name not in self.settings:
self.templates.append((name, '', '#define ' + name + ' '))
super().set(name, value)
_define_line_regexp = (r'(?P<indentation>\s*)' +
r'(?P<commented_out>(//\s*)?)' +
r'(?P<define>#\s*define\s+)' +
r'(?P<name>\w+)' +
r'(?P<arguments>(?:\((?:\w|\s|,)*\))?)' +
r'(?P<separator>\s*)' +
r'(?P<value>.*)')
_section_line_regexp = (r'\s*/?\*+\s*[\\@]name\s+SECTION:\s*' +
r'(?P<section>.*)[ */]*')
_config_line_regexp = re.compile(r'|'.join([_define_line_regexp,
_section_line_regexp]))
def _parse_line(self, line):
"""Parse a line in config.h and return the corresponding template."""
line = line.rstrip('\r\n')
m = re.match(self._config_line_regexp, line)
if m is None:
return line
elif m.group('section'):
self.current_section = m.group('section')
return line
else:
active = not m.group('commented_out')
name = m.group('name')
value = m.group('value')
template = (name,
m.group('indentation'),
m.group('define') + name +
m.group('arguments') + m.group('separator'))
self.settings[name] = Setting(active, name, value,
self.current_section)
return template
def _format_template(self, name, indent, middle):
"""Build a line for config.h for the given setting.
The line has the form "<indent>#define <name> <value>"
where <middle> is "#define <name> ".
"""
setting = self.settings[name]
value = setting.value
if value is None:
value = ''
# Normally the whitespace to separte the symbol name from the
# value is part of middle, and there's no whitespace for a symbol
# with no value. But if a symbol has been changed from having a
# value to not having one, the whitespace is wrong, so fix it.
if value:
if middle[-1] not in '\t ':
middle += ' '
else:
middle = middle.rstrip()
return ''.join([indent,
'' if setting.active else '//',
middle,
value]).rstrip()
def write_to_stream(self, output):
"""Write the whole configuration to output."""
for template in self.templates:
if isinstance(template, str):
line = template
else:
line = self._format_template(*template)
output.write(line + '\n')
def write(self, filename=None):
"""Write the whole configuration to the file it was read from.
If filename is specified, write to this file instead.
"""
if filename is None:
filename = self.filename
with open(filename, 'w', encoding='utf-8') as output:
self.write_to_stream(output)
if __name__ == '__main__':
def main():
"""Command line config.h manipulation tool."""
parser = argparse.ArgumentParser(description="""
Mbed TLS and Mbed Crypto configuration file manipulation tool.
""")
parser.add_argument('--file', '-f',
help="""File to read (and modify if requested).
Default: {}.
""".format(ConfigFile.default_path))
parser.add_argument('--force', '-o',
action='store_true',
help="""For the set command, if SYMBOL is not
present, add a definition for it.""")
parser.add_argument('--write', '-w', metavar='FILE',
help="""File to write to instead of the input file.""")
subparsers = parser.add_subparsers(dest='command',
title='Commands')
parser_get = subparsers.add_parser('get',
help="""Find the value of SYMBOL
and print it. Exit with
status 0 if a #define for SYMBOL is
found, 1 otherwise.
""")
parser_get.add_argument('symbol', metavar='SYMBOL')
parser_set = subparsers.add_parser('set',
help="""Set SYMBOL to VALUE.
If VALUE is omitted, just uncomment
the #define for SYMBOL.
Error out of a line defining
SYMBOL (commented or not) is not
found, unless --force is passed.
""")
parser_set.add_argument('symbol', metavar='SYMBOL')
parser_set.add_argument('value', metavar='VALUE', nargs='?',
default='')
parser_unset = subparsers.add_parser('unset',
help="""Comment out the #define
for SYMBOL. Do nothing if none
is present.""")
parser_unset.add_argument('symbol', metavar='SYMBOL')
def add_adapter(name, function, description):
subparser = subparsers.add_parser(name, help=description)
subparser.set_defaults(adapter=function)
add_adapter('baremetal', baremetal_adapter,
"""Like full, but exclude features that require platform
features such as file input-output.""")
add_adapter('full', full_adapter,
"""Uncomment most features.
Exclude alternative implementations and platform support
options, as well as some options that are awkward to test.
""")
add_adapter('realfull', realfull_adapter,
"""Uncomment all boolean #defines.
Suitable for generating documentation, but not for building.""")
args = parser.parse_args()
config = ConfigFile(args.file)
if args.command is None:
parser.print_help()
return 1
elif args.command == 'get':
if args.symbol in config:
value = config[args.symbol]
if value:
sys.stdout.write(value + '\n')
return args.symbol not in config
elif args.command == 'set':
if not args.force and args.symbol not in config.settings:
sys.stderr.write("A #define for the symbol {} "
"was not found in {}\n"
.format(args.symbol, config.filename))
return 1
config.set(args.symbol, value=args.value)
elif args.command == 'unset':
config.unset(args.symbol)
else:
config.adapt(args.adapter)
config.write(args.write)
# Import modules only used by main only if main is defined and called.
# pylint: disable=wrong-import-position
import argparse
import sys
sys.exit(main())

View File

@ -59,8 +59,8 @@ EOF
for F in 0 1; do
for W in 2 3 4 5 6; do
scripts/config.pl set MBEDTLS_ECP_WINDOW_SIZE $W
scripts/config.pl set MBEDTLS_ECP_FIXED_POINT_OPTIM $F
scripts/config.py set MBEDTLS_ECP_WINDOW_SIZE $W
scripts/config.py set MBEDTLS_ECP_FIXED_POINT_OPTIM $F
make benchmark >/dev/null 2>&1
echo "fixed point optim = $F, max window size = $W"
echo "--------------------------------------------"

View File

@ -62,9 +62,9 @@ doit()
fi
{
scripts/config.pl unset MBEDTLS_TIMING_C || true
scripts/config.pl unset MBEDTLS_FS_IO || true
scripts/config.pl --force set MBEDTLS_NO_PLATFORM_ENTROPY || true
scripts/config.py unset MBEDTLS_TIMING_C || true
scripts/config.py unset MBEDTLS_FS_IO || true
scripts/config.py --force set MBEDTLS_NO_PLATFORM_ENTROPY || true
} >/dev/null 2>&1
make clean >/dev/null

View File

@ -9,9 +9,9 @@ if(NOT DEFINED MBEDTLS_DIR)
set(MBEDTLS_DIR ${CMAKE_SOURCE_DIR})
endif()
find_package(Perl)
if(NOT PERL_FOUND)
message(FATAL_ERROR "Cannot build test suites without Perl")
find_package(PythonInterp)
if(NOT PYTHONINTERP_FOUND)
message(FATAL_ERROR "Cannot build test suites without Python 2 or 3")
endif()
# Enable definition of various functions used throughout the testsuite

View File

@ -590,10 +590,10 @@ component_test_ref_configs () {
component_test_no_pem_no_fs () {
msg "build: Default + !MBEDTLS_PEM_PARSE_C + !MBEDTLS_FS_IO (ASan build)"
scripts/config.pl unset MBEDTLS_PEM_PARSE_C
scripts/config.pl unset MBEDTLS_FS_IO
scripts/config.pl unset MBEDTLS_PSA_ITS_FILE_C # requires a filesystem
scripts/config.pl unset MBEDTLS_PSA_CRYPTO_STORAGE_C # requires PSA ITS
scripts/config.py unset MBEDTLS_PEM_PARSE_C
scripts/config.py unset MBEDTLS_FS_IO
scripts/config.py unset MBEDTLS_PSA_ITS_FILE_C # requires a filesystem
scripts/config.py unset MBEDTLS_PSA_CRYPTO_STORAGE_C # requires PSA ITS
CC=gcc cmake -D CMAKE_BUILD_TYPE:String=Asan .
make
@ -603,7 +603,7 @@ component_test_no_pem_no_fs () {
component_test_rsa_no_crt () {
msg "build: Default + RSA_NO_CRT (ASan build)" # ~ 6 min
scripts/config.pl set MBEDTLS_RSA_NO_CRT
scripts/config.py set MBEDTLS_RSA_NO_CRT
CC=gcc cmake -D CMAKE_BUILD_TYPE:String=Asan .
make
@ -613,7 +613,7 @@ component_test_rsa_no_crt () {
component_test_new_ecdh_context () {
msg "build: new ECDH context (ASan build)" # ~ 6 min
scripts/config.pl unset MBEDTLS_ECDH_LEGACY_CONTEXT
scripts/config.py unset MBEDTLS_ECDH_LEGACY_CONTEXT
CC=gcc cmake -D CMAKE_BUILD_TYPE:String=Asan .
make
@ -623,8 +623,8 @@ component_test_new_ecdh_context () {
component_test_everest () {
msg "build: Everest ECDH context (ASan build)" # ~ 6 min
scripts/config.pl unset MBEDTLS_ECDH_LEGACY_CONTEXT
scripts/config.pl set MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED
scripts/config.py unset MBEDTLS_ECDH_LEGACY_CONTEXT
scripts/config.py set MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED
CC=clang cmake -D CMAKE_BUILD_TYPE:String=Asan .
make
@ -634,8 +634,8 @@ component_test_everest () {
component_test_psa_collect_statuses () {
msg "build+test: psa_collect_statuses" # ~30s
scripts/config.pl full
scripts/config.pl unset MBEDTLS_MEMORY_BUFFER_ALLOC_C # slow and irrelevant
scripts/config.py full
scripts/config.py unset MBEDTLS_MEMORY_BUFFER_ALLOC_C # slow and irrelevant
record_status tests/scripts/psa_collect_statuses.py
# Check that psa_crypto_init() succeeded at least once
record_status grep -q '^0:psa_crypto_init:' tests/statuses.log
@ -644,8 +644,8 @@ component_test_psa_collect_statuses () {
component_test_full_cmake_clang () {
msg "build: cmake, full config, clang" # ~ 50s
scripts/config.pl full
scripts/config.pl unset MBEDTLS_MEMORY_BACKTRACE # too slow for tests
scripts/config.py full
scripts/config.py unset MBEDTLS_MEMORY_BACKTRACE # too slow for tests
CC=clang cmake -D CMAKE_BUILD_TYPE:String=Check -D ENABLE_TESTING=On .
make
@ -658,8 +658,8 @@ component_test_full_cmake_clang () {
component_test_full_make_gcc_o0 () {
msg "build: make, full config, gcc -O0" # ~ 50s
scripts/config.pl full
scripts/config.pl unset MBEDTLS_MEMORY_BACKTRACE # too slow for tests
scripts/config.py full
scripts/config.py unset MBEDTLS_MEMORY_BACKTRACE # too slow for tests
make CC=gcc CFLAGS='-O0'
msg "test: main suites (full config, gcc -O0)" # ~ 5s
@ -668,8 +668,8 @@ component_test_full_make_gcc_o0 () {
component_build_deprecated () {
msg "build: make, full config + DEPRECATED_WARNING, gcc -O" # ~ 30s
scripts/config.pl full
scripts/config.pl set MBEDTLS_DEPRECATED_WARNING
scripts/config.py full
scripts/config.py set MBEDTLS_DEPRECATED_WARNING
# Build with -O -Wextra to catch a maximum of issues.
make CC=gcc CFLAGS='-O -Werror -Wall -Wextra' lib programs
make CC=gcc CFLAGS='-O -Werror -Wall -Wextra -Wno-unused-function' tests
@ -677,8 +677,8 @@ component_build_deprecated () {
msg "build: make, full config + DEPRECATED_REMOVED, clang -O" # ~ 30s
# No cleanup, just tweak the configuration and rebuild
make clean
scripts/config.pl unset MBEDTLS_DEPRECATED_WARNING
scripts/config.pl set MBEDTLS_DEPRECATED_REMOVED
scripts/config.py unset MBEDTLS_DEPRECATED_WARNING
scripts/config.py set MBEDTLS_DEPRECATED_REMOVED
# Build with -O -Wextra to catch a maximum of issues.
make CC=clang CFLAGS='-O -Werror -Wall -Wextra' lib programs
make CC=clang CFLAGS='-O -Werror -Wall -Wextra -Wno-unused-function' tests
@ -713,13 +713,13 @@ component_build_default_make_gcc_and_cxx () {
component_test_no_use_psa_crypto_full_cmake_asan() {
# full minus MBEDTLS_USE_PSA_CRYPTO: run the same set of tests as basic-build-test.sh
msg "build: cmake, full config + MBEDTLS_USE_PSA_CRYPTO, ASan"
scripts/config.pl full
scripts/config.pl unset MBEDTLS_MEMORY_BUFFER_ALLOC_C
scripts/config.pl set MBEDTLS_ECP_RESTARTABLE # not using PSA, so enable restartable ECC
scripts/config.pl set MBEDTLS_PSA_CRYPTO_C
scripts/config.pl unset MBEDTLS_USE_PSA_CRYPTO
scripts/config.pl unset MBEDTLS_PSA_ITS_FILE_C
scripts/config.pl unset MBEDTLS_PSA_CRYPTO_STORAGE_C
scripts/config.py full
scripts/config.py unset MBEDTLS_MEMORY_BUFFER_ALLOC_C
scripts/config.py set MBEDTLS_ECP_RESTARTABLE # not using PSA, so enable restartable ECC
scripts/config.py set MBEDTLS_PSA_CRYPTO_C
scripts/config.py unset MBEDTLS_USE_PSA_CRYPTO
scripts/config.py unset MBEDTLS_PSA_ITS_FILE_C
scripts/config.py unset MBEDTLS_PSA_CRYPTO_STORAGE_C
CC=gcc cmake -D CMAKE_BUILD_TYPE:String=Asan .
make
@ -729,10 +729,10 @@ component_test_no_use_psa_crypto_full_cmake_asan() {
component_test_check_params_functionality () {
msg "build+test: MBEDTLS_CHECK_PARAMS functionality"
scripts/config.pl full # includes CHECK_PARAMS
scripts/config.py full # includes CHECK_PARAMS
# Make MBEDTLS_PARAM_FAILED call mbedtls_param_failed().
scripts/config.pl unset MBEDTLS_CHECK_PARAMS_ASSERT
scripts/config.pl unset MBEDTLS_MEMORY_BUFFER_ALLOC_C
scripts/config.py unset MBEDTLS_CHECK_PARAMS_ASSERT
scripts/config.py unset MBEDTLS_MEMORY_BUFFER_ALLOC_C
# Only build and run tests. Do not build sample programs, because
# they don't have a mbedtls_param_failed() function.
make CC=gcc CFLAGS='-Werror -O1' lib test
@ -740,25 +740,25 @@ component_test_check_params_functionality () {
component_test_check_params_without_platform () {
msg "build+test: MBEDTLS_CHECK_PARAMS without MBEDTLS_PLATFORM_C"
scripts/config.pl full # includes CHECK_PARAMS
scripts/config.py full # includes CHECK_PARAMS
# Keep MBEDTLS_PARAM_FAILED as assert.
scripts/config.pl unset MBEDTLS_MEMORY_BACKTRACE # too slow for tests
scripts/config.pl unset MBEDTLS_MEMORY_BUFFER_ALLOC_C
scripts/config.pl unset MBEDTLS_PLATFORM_EXIT_ALT
scripts/config.pl unset MBEDTLS_PLATFORM_TIME_ALT
scripts/config.pl unset MBEDTLS_PLATFORM_FPRINTF_ALT
scripts/config.pl unset MBEDTLS_PLATFORM_MEMORY
scripts/config.pl unset MBEDTLS_PLATFORM_PRINTF_ALT
scripts/config.pl unset MBEDTLS_PLATFORM_SNPRINTF_ALT
scripts/config.pl unset MBEDTLS_ENTROPY_NV_SEED
scripts/config.pl unset MBEDTLS_PLATFORM_C
scripts/config.py unset MBEDTLS_MEMORY_BACKTRACE # too slow for tests
scripts/config.py unset MBEDTLS_MEMORY_BUFFER_ALLOC_C
scripts/config.py unset MBEDTLS_PLATFORM_EXIT_ALT
scripts/config.py unset MBEDTLS_PLATFORM_TIME_ALT
scripts/config.py unset MBEDTLS_PLATFORM_FPRINTF_ALT
scripts/config.py unset MBEDTLS_PLATFORM_MEMORY
scripts/config.py unset MBEDTLS_PLATFORM_PRINTF_ALT
scripts/config.py unset MBEDTLS_PLATFORM_SNPRINTF_ALT
scripts/config.py unset MBEDTLS_ENTROPY_NV_SEED
scripts/config.py unset MBEDTLS_PLATFORM_C
make CC=gcc CFLAGS='-Werror -O1' all test
}
component_test_check_params_silent () {
msg "build+test: MBEDTLS_CHECK_PARAMS with alternative MBEDTLS_PARAM_FAILED()"
scripts/config.pl full # includes CHECK_PARAMS
scripts/config.pl unset MBEDTLS_MEMORY_BACKTRACE # too slow for tests
scripts/config.py full # includes CHECK_PARAMS
scripts/config.py unset MBEDTLS_MEMORY_BACKTRACE # too slow for tests
# Set MBEDTLS_PARAM_FAILED to nothing.
sed -i 's/.*\(#define MBEDTLS_PARAM_FAILED( cond )\).*/\1/' "$CONFIG_H"
make CC=gcc CFLAGS='-Werror -O1' all test
@ -769,20 +769,20 @@ component_test_no_platform () {
# This should catch missing mbedtls_printf definitions, and by disabling file
# IO, it should catch missing '#include <stdio.h>'
msg "build: full config except platform/fsio/net, make, gcc, C99" # ~ 30s
scripts/config.pl full
scripts/config.pl unset MBEDTLS_PLATFORM_C
scripts/config.pl unset MBEDTLS_PLATFORM_MEMORY
scripts/config.pl unset MBEDTLS_PLATFORM_PRINTF_ALT
scripts/config.pl unset MBEDTLS_PLATFORM_FPRINTF_ALT
scripts/config.pl unset MBEDTLS_PLATFORM_SNPRINTF_ALT
scripts/config.pl unset MBEDTLS_PLATFORM_TIME_ALT
scripts/config.pl unset MBEDTLS_PLATFORM_EXIT_ALT
scripts/config.pl unset MBEDTLS_ENTROPY_NV_SEED
scripts/config.pl unset MBEDTLS_MEMORY_BUFFER_ALLOC_C
scripts/config.pl unset MBEDTLS_FS_IO
scripts/config.pl unset MBEDTLS_PSA_CRYPTO_SE_C
scripts/config.pl unset MBEDTLS_PSA_CRYPTO_STORAGE_C
scripts/config.pl unset MBEDTLS_PSA_ITS_FILE_C
scripts/config.py full
scripts/config.py unset MBEDTLS_PLATFORM_C
scripts/config.py unset MBEDTLS_PLATFORM_MEMORY
scripts/config.py unset MBEDTLS_PLATFORM_PRINTF_ALT
scripts/config.py unset MBEDTLS_PLATFORM_FPRINTF_ALT
scripts/config.py unset MBEDTLS_PLATFORM_SNPRINTF_ALT
scripts/config.py unset MBEDTLS_PLATFORM_TIME_ALT
scripts/config.py unset MBEDTLS_PLATFORM_EXIT_ALT
scripts/config.py unset MBEDTLS_ENTROPY_NV_SEED
scripts/config.py unset MBEDTLS_MEMORY_BUFFER_ALLOC_C
scripts/config.py unset MBEDTLS_FS_IO
scripts/config.py unset MBEDTLS_PSA_CRYPTO_SE_C
scripts/config.py unset MBEDTLS_PSA_CRYPTO_STORAGE_C
scripts/config.py unset MBEDTLS_PSA_ITS_FILE_C
# Note, _DEFAULT_SOURCE needs to be defined for platforms using glibc version >2.19,
# to re-enable platform integration features otherwise disabled in C99 builds
make CC=gcc CFLAGS='-Werror -Wall -Wextra -std=c99 -pedantic -O0 -D_DEFAULT_SOURCE' lib programs
@ -792,20 +792,20 @@ component_test_no_platform () {
component_build_no_std_function () {
# catch compile bugs in _uninit functions
msg "build: full config with NO_STD_FUNCTION, make, gcc" # ~ 30s
scripts/config.pl full
scripts/config.pl set MBEDTLS_PLATFORM_NO_STD_FUNCTIONS
scripts/config.pl unset MBEDTLS_ENTROPY_NV_SEED
scripts/config.py full
scripts/config.py set MBEDTLS_PLATFORM_NO_STD_FUNCTIONS
scripts/config.py unset MBEDTLS_ENTROPY_NV_SEED
make CC=gcc CFLAGS='-Werror -Wall -Wextra -O0'
}
component_test_null_entropy () {
msg "build: default config with MBEDTLS_TEST_NULL_ENTROPY (ASan build)"
scripts/config.pl set MBEDTLS_TEST_NULL_ENTROPY
scripts/config.pl set MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES
scripts/config.pl set MBEDTLS_ENTROPY_C
scripts/config.pl unset MBEDTLS_ENTROPY_NV_SEED
scripts/config.pl unset MBEDTLS_ENTROPY_HARDWARE_ALT
scripts/config.pl unset MBEDTLS_HAVEGE_C
scripts/config.py set MBEDTLS_TEST_NULL_ENTROPY
scripts/config.py set MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES
scripts/config.py set MBEDTLS_ENTROPY_C
scripts/config.py unset MBEDTLS_ENTROPY_NV_SEED
scripts/config.py unset MBEDTLS_ENTROPY_HARDWARE_ALT
scripts/config.py unset MBEDTLS_HAVEGE_C
CC=gcc cmake -D CMAKE_BUILD_TYPE:String=Asan -D UNSAFE_BUILD=ON .
make
@ -815,9 +815,9 @@ component_test_null_entropy () {
component_test_platform_calloc_macro () {
msg "build: MBEDTLS_PLATFORM_{CALLOC/FREE}_MACRO enabled (ASan build)"
scripts/config.pl set MBEDTLS_PLATFORM_MEMORY
scripts/config.pl set MBEDTLS_PLATFORM_CALLOC_MACRO calloc
scripts/config.pl set MBEDTLS_PLATFORM_FREE_MACRO free
scripts/config.py set MBEDTLS_PLATFORM_MEMORY
scripts/config.py set MBEDTLS_PLATFORM_CALLOC_MACRO calloc
scripts/config.py set MBEDTLS_PLATFORM_FREE_MACRO free
CC=gcc cmake -D CMAKE_BUILD_TYPE:String=Asan .
make
@ -827,8 +827,8 @@ component_test_platform_calloc_macro () {
component_test_malloc_0_null () {
msg "build: malloc(0) returns NULL (ASan+UBSan build)"
scripts/config.pl full
scripts/config.pl unset MBEDTLS_MEMORY_BUFFER_ALLOC_C
scripts/config.py full
scripts/config.py unset MBEDTLS_MEMORY_BUFFER_ALLOC_C
make CC=gcc CFLAGS="'-DMBEDTLS_CONFIG_FILE=\"$PWD/tests/configs/config-wrapper-malloc-0-null.h\"' $ASAN_CFLAGS -O" LDFLAGS="$ASAN_CFLAGS"
msg "test: malloc(0) returns NULL (ASan+UBSan build)"
@ -842,7 +842,7 @@ component_test_malloc_0_null () {
component_test_aes_fewer_tables () {
msg "build: default config with AES_FEWER_TABLES enabled"
scripts/config.pl set MBEDTLS_AES_FEWER_TABLES
scripts/config.py set MBEDTLS_AES_FEWER_TABLES
make CC=gcc CFLAGS='-Werror -Wall -Wextra'
msg "test: AES_FEWER_TABLES"
@ -851,7 +851,7 @@ component_test_aes_fewer_tables () {
component_test_aes_rom_tables () {
msg "build: default config with AES_ROM_TABLES enabled"
scripts/config.pl set MBEDTLS_AES_ROM_TABLES
scripts/config.py set MBEDTLS_AES_ROM_TABLES
make CC=gcc CFLAGS='-Werror -Wall -Wextra'
msg "test: AES_ROM_TABLES"
@ -860,8 +860,8 @@ component_test_aes_rom_tables () {
component_test_aes_fewer_tables_and_rom_tables () {
msg "build: default config with AES_ROM_TABLES and AES_FEWER_TABLES enabled"
scripts/config.pl set MBEDTLS_AES_FEWER_TABLES
scripts/config.pl set MBEDTLS_AES_ROM_TABLES
scripts/config.py set MBEDTLS_AES_FEWER_TABLES
scripts/config.py set MBEDTLS_AES_ROM_TABLES
make CC=gcc CFLAGS='-Werror -Wall -Wextra'
msg "test: AES_FEWER_TABLES + AES_ROM_TABLES"
@ -870,7 +870,7 @@ component_test_aes_fewer_tables_and_rom_tables () {
component_test_se_default () {
msg "build: default config + MBEDTLS_PSA_CRYPTO_SE_C"
scripts/config.pl set MBEDTLS_PSA_CRYPTO_SE_C
scripts/config.py set MBEDTLS_PSA_CRYPTO_SE_C
make CC=clang CFLAGS="$ASAN_CFLAGS -Os" LDFLAGS="$ASAN_CFLAGS"
msg "test: default config + MBEDTLS_PSA_CRYPTO_SE_C"
@ -879,9 +879,9 @@ component_test_se_default () {
component_test_se_full () {
msg "build: full config + MBEDTLS_PSA_CRYPTO_SE_C"
scripts/config.pl full
scripts/config.pl unset MBEDTLS_MEMORY_BUFFER_ALLOC_C
scripts/config.pl set MBEDTLS_PSA_CRYPTO_SE_C
scripts/config.py full
scripts/config.py unset MBEDTLS_MEMORY_BUFFER_ALLOC_C
scripts/config.py set MBEDTLS_PSA_CRYPTO_SE_C
make CC=gcc CFLAGS="$ASAN_CFLAGS -O2" LDFLAGS="$ASAN_CFLAGS"
msg "test: full config + MBEDTLS_PSA_CRYPTO_SE_C"
@ -906,7 +906,7 @@ component_build_mbedtls_config_file () {
msg "build: make with MBEDTLS_CONFIG_FILE" # ~40s
# Use the full config so as to catch a maximum of places where
# the check of MBEDTLS_CONFIG_FILE might be missing.
scripts/config.pl full
scripts/config.py full
sed 's!"check_config.h"!"mbedtls/check_config.h"!' <"$CONFIG_H" >full_config.h
echo '#error "MBEDTLS_CONFIG_FILE is not working"' >"$CONFIG_H"
make CFLAGS="-I '$PWD' -DMBEDTLS_CONFIG_FILE='\"full_config.h\"'"
@ -916,7 +916,7 @@ component_build_mbedtls_config_file () {
component_test_m32_o0 () {
# Build once with -O0, to compile out the i386 specific inline assembly
msg "build: i386, make, gcc -O0 (ASan build)" # ~ 30s
scripts/config.pl full
scripts/config.py full
make CC=gcc CFLAGS="$ASAN_CFLAGS -m32 -O0" LDFLAGS="-m32 $ASAN_CFLAGS"
msg "test: i386, make, gcc -O0 (ASan build)"
@ -932,10 +932,10 @@ support_test_m32_o0 () {
component_test_m32_o1 () {
# Build again with -O1, to compile in the i386 specific inline assembly
msg "build: i386, make, gcc -O1 (ASan build)" # ~ 30s
scripts/config.pl full
scripts/config.pl unset MBEDTLS_MEMORY_BACKTRACE
scripts/config.pl unset MBEDTLS_MEMORY_BUFFER_ALLOC_C
scripts/config.pl unset MBEDTLS_MEMORY_DEBUG
scripts/config.py full
scripts/config.py unset MBEDTLS_MEMORY_BACKTRACE
scripts/config.py unset MBEDTLS_MEMORY_BUFFER_ALLOC_C
scripts/config.py unset MBEDTLS_MEMORY_DEBUG
make CC=gcc CFLAGS="$ASAN_CFLAGS -m32 -O1" LDFLAGS="-m32 $ASAN_CFLAGS"
msg "test: i386, make, gcc -O1 (ASan build)"
@ -947,8 +947,8 @@ support_test_m32_o1 () {
component_test_m32_everest () {
msg "build: i386, Everest ECDH context (ASan build)" # ~ 6 min
scripts/config.pl unset MBEDTLS_ECDH_LEGACY_CONTEXT
scripts/config.pl set MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED
scripts/config.py unset MBEDTLS_ECDH_LEGACY_CONTEXT
scripts/config.py set MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED
make CC=gcc CFLAGS="$ASAN_CFLAGS -m32 -O2" LDFLAGS="-m32 $ASAN_CFLAGS"
msg "test: i386, Everest ECDH context - main suites (inc. selftests) (ASan build)" # ~ 50s
@ -960,7 +960,7 @@ support_test_m32_everest () {
component_test_mx32 () {
msg "build: 64-bit ILP32, make, gcc" # ~ 30s
scripts/config.pl full
scripts/config.py full
make CC=gcc CFLAGS='-Werror -Wall -Wextra -mx32' LDFLAGS='-mx32'
msg "test: 64-bit ILP32, make, gcc"
@ -975,7 +975,7 @@ support_test_mx32 () {
component_test_min_mpi_window_size () {
msg "build: Default + MBEDTLS_MPI_WINDOW_SIZE=1 (ASan build)" # ~ 10s
scripts/config.pl set MBEDTLS_MPI_WINDOW_SIZE 1
scripts/config.py set MBEDTLS_MPI_WINDOW_SIZE 1
CC=gcc cmake -D CMAKE_BUILD_TYPE:String=Asan .
make
@ -985,9 +985,9 @@ component_test_min_mpi_window_size () {
component_test_have_int32 () {
msg "build: gcc, force 32-bit bignum limbs"
scripts/config.pl unset MBEDTLS_HAVE_ASM
scripts/config.pl unset MBEDTLS_AESNI_C
scripts/config.pl unset MBEDTLS_PADLOCK_C
scripts/config.py unset MBEDTLS_HAVE_ASM
scripts/config.py unset MBEDTLS_AESNI_C
scripts/config.py unset MBEDTLS_PADLOCK_C
make CC=gcc CFLAGS='-Werror -Wall -Wextra -DMBEDTLS_HAVE_INT32'
msg "test: gcc, force 32-bit bignum limbs"
@ -996,9 +996,9 @@ component_test_have_int32 () {
component_test_have_int64 () {
msg "build: gcc, force 64-bit bignum limbs"
scripts/config.pl unset MBEDTLS_HAVE_ASM
scripts/config.pl unset MBEDTLS_AESNI_C
scripts/config.pl unset MBEDTLS_PADLOCK_C
scripts/config.py unset MBEDTLS_HAVE_ASM
scripts/config.py unset MBEDTLS_AESNI_C
scripts/config.py unset MBEDTLS_PADLOCK_C
make CC=gcc CFLAGS='-Werror -Wall -Wextra -DMBEDTLS_HAVE_INT64'
msg "test: gcc, force 64-bit bignum limbs"
@ -1007,9 +1007,9 @@ component_test_have_int64 () {
component_test_no_udbl_division () {
msg "build: MBEDTLS_NO_UDBL_DIVISION native" # ~ 10s
scripts/config.pl full
scripts/config.pl unset MBEDTLS_MEMORY_BACKTRACE # too slow for tests
scripts/config.pl set MBEDTLS_NO_UDBL_DIVISION
scripts/config.py full
scripts/config.py unset MBEDTLS_MEMORY_BACKTRACE # too slow for tests
scripts/config.py set MBEDTLS_NO_UDBL_DIVISION
make CFLAGS='-Werror -O1'
msg "test: MBEDTLS_NO_UDBL_DIVISION native" # ~ 10s
@ -1018,9 +1018,9 @@ component_test_no_udbl_division () {
component_test_no_64bit_multiplication () {
msg "build: MBEDTLS_NO_64BIT_MULTIPLICATION native" # ~ 10s
scripts/config.pl full
scripts/config.pl unset MBEDTLS_MEMORY_BACKTRACE # too slow for tests
scripts/config.pl set MBEDTLS_NO_64BIT_MULTIPLICATION
scripts/config.py full
scripts/config.py unset MBEDTLS_MEMORY_BACKTRACE # too slow for tests
scripts/config.py set MBEDTLS_NO_64BIT_MULTIPLICATION
make CFLAGS='-Werror -O1'
msg "test: MBEDTLS_NO_64BIT_MULTIPLICATION native" # ~ 10s
@ -1029,13 +1029,13 @@ component_test_no_64bit_multiplication () {
component_build_arm_none_eabi_gcc () {
msg "build: arm-none-eabi-gcc, make" # ~ 10s
scripts/config.pl baremetal
scripts/config.py baremetal
make CC=arm-none-eabi-gcc AR=arm-none-eabi-ar LD=arm-none-eabi-ld CFLAGS='-Werror -Wall -Wextra' lib
}
component_build_arm_none_eabi_gcc_arm5vte () {
msg "build: arm-none-eabi-gcc -march=arm5vte, make" # ~ 10s
scripts/config.pl baremetal
scripts/config.py baremetal
# Build for a target platform that's close to what Debian uses
# for its "armel" distribution (https://wiki.debian.org/ArmEabiPort).
# See https://github.com/ARMmbed/mbedtls/pull/2169 and comments.
@ -1046,8 +1046,8 @@ component_build_arm_none_eabi_gcc_arm5vte () {
component_build_arm_none_eabi_gcc_no_udbl_division () {
msg "build: arm-none-eabi-gcc -DMBEDTLS_NO_UDBL_DIVISION, make" # ~ 10s
scripts/config.pl baremetal
scripts/config.pl set MBEDTLS_NO_UDBL_DIVISION
scripts/config.py baremetal
scripts/config.py set MBEDTLS_NO_UDBL_DIVISION
make CC=arm-none-eabi-gcc AR=arm-none-eabi-ar LD=arm-none-eabi-ld CFLAGS='-Werror -Wall -Wextra' lib
echo "Checking that software 64-bit division is not required"
if_build_succeeded not grep __aeabi_uldiv library/*.o
@ -1055,8 +1055,8 @@ component_build_arm_none_eabi_gcc_no_udbl_division () {
component_build_arm_none_eabi_gcc_no_64bit_multiplication () {
msg "build: arm-none-eabi-gcc MBEDTLS_NO_64BIT_MULTIPLICATION, make" # ~ 10s
scripts/config.pl baremetal
scripts/config.pl set MBEDTLS_NO_64BIT_MULTIPLICATION
scripts/config.py baremetal
scripts/config.py set MBEDTLS_NO_64BIT_MULTIPLICATION
make CC=arm-none-eabi-gcc AR=arm-none-eabi-ar LD=arm-none-eabi-ld CFLAGS='-Werror -O1 -march=armv6-m -mthumb' lib
echo "Checking that software 64-bit multiplication is not required"
if_build_succeeded not grep __aeabi_lmul library/*.o
@ -1064,7 +1064,7 @@ component_build_arm_none_eabi_gcc_no_64bit_multiplication () {
component_build_armcc () {
msg "build: ARM Compiler 5, make"
scripts/config.pl baremetal
scripts/config.py baremetal
make CC="$ARMC5_CC" AR="$ARMC5_AR" WARNING_CFLAGS='--strict --c99' lib
make clean
@ -1107,7 +1107,7 @@ support_build_mingw() {
component_test_memsan () {
msg "build: MSan (clang)" # ~ 1 min 20s
scripts/config.pl unset MBEDTLS_AESNI_C # memsan doesn't grok asm
scripts/config.py unset MBEDTLS_AESNI_C # memsan doesn't grok asm
CC=clang cmake -D CMAKE_BUILD_TYPE:String=MemSan .
make

View File

@ -46,8 +46,8 @@ export CFLAGS=' --coverage -g3 -O0 '
export LDFLAGS=' --coverage'
make clean
cp "$CONFIG_H" "$CONFIG_BAK"
scripts/config.pl full
scripts/config.pl unset MBEDTLS_MEMORY_BACKTRACE
scripts/config.py full
scripts/config.py unset MBEDTLS_MEMORY_BACKTRACE
make -j

View File

@ -46,13 +46,13 @@ for my $curve (@curves) {
system( "make clean" ) and die;
# depends on a specific curve. Also, ignore error if it wasn't enabled
system( "scripts/config.pl unset MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED" );
system( "scripts/config.py unset MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED" );
print "\n******************************************\n";
print "* Testing without curve: $curve\n";
print "******************************************\n";
system( "scripts/config.pl unset $curve" )
system( "scripts/config.py unset $curve" )
and abort "Failed to disable $curve\n";
system( "CFLAGS='-Werror -Wall -Wextra' make lib" )

View File

@ -58,11 +58,11 @@ for my $hash (@hashes) {
print "* Testing without hash: $hash\n";
print "******************************************\n";
system( "scripts/config.pl unset $hash" )
system( "scripts/config.py unset $hash" )
and abort "Failed to disable $hash\n";
for my $opt (@ssl) {
system( "scripts/config.pl unset $opt" )
system( "scripts/config.py unset $opt" )
and abort "Failed to disable $opt\n";
}

View File

@ -60,10 +60,10 @@ while( my ($alg, $extras) = each %algs ) {
print "* Testing without alg: $alg\n";
print "******************************************\n";
system( "scripts/config.pl unset $alg" )
system( "scripts/config.py unset $alg" )
and abort "Failed to disable $alg\n";
for my $opt (@$extras) {
system( "scripts/config.pl unset $opt" )
system( "scripts/config.py unset $opt" )
and abort "Failed to disable $opt\n";
}

View File

@ -13,7 +13,7 @@ if grep -i cmake Makefile >/dev/null; then
fi
cp include/mbedtls/config.h include/mbedtls/config.h.bak
scripts/config.pl full
scripts/config.py full
make clean
make_ret=
CFLAGS=-fno-asynchronous-unwind-tables make lib \

View File

@ -0,0 +1,187 @@
#!/usr/bin/env python3
"""Test helper for the Mbed TLS configuration file tool
Run config.py with various parameters and write the results to files.
This is a harness to help regression testing, not a functional tester.
Sample usage:
test_config_script.py -d old
## Modify config.py and/or config.h ##
test_config_script.py -d new
diff -ru old new
"""
## Copyright (C) 2019, ARM Limited, All Rights Reserved
## SPDX-License-Identifier: Apache-2.0
##
## Licensed under the Apache License, Version 2.0 (the "License"); you may
## not use this file except in compliance with the License.
## You may obtain a copy of the License at
##
## http://www.apache.org/licenses/LICENSE-2.0
##
## Unless required by applicable law or agreed to in writing, software
## distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
## WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
## See the License for the specific language governing permissions and
## limitations under the License.
##
## This file is part of Mbed TLS (https://tls.mbed.org)
import argparse
import glob
import os
import re
import shutil
import subprocess
OUTPUT_FILE_PREFIX = 'config-'
def output_file_name(directory, stem, extension):
return os.path.join(directory,
'{}{}.{}'.format(OUTPUT_FILE_PREFIX,
stem, extension))
def cleanup_directory(directory):
"""Remove old output files."""
for extension in []:
pattern = output_file_name(directory, '*', extension)
filenames = glob.glob(pattern)
for filename in filenames:
os.remove(filename)
def prepare_directory(directory):
"""Create the output directory if it doesn't exist yet.
If there are old output files, remove them.
"""
if os.path.exists(directory):
cleanup_directory(directory)
else:
os.makedirs(directory)
def guess_presets_from_help(help_text):
"""Figure out what presets the script supports.
help_text should be the output from running the script with --help.
"""
# Try the output format from config.py
hits = re.findall(r'\{([-\w,]+)\}', help_text)
for hit in hits:
words = set(hit.split(','))
if 'get' in words and 'set' in words and 'unset' in words:
words.remove('get')
words.remove('set')
words.remove('unset')
return words
# Try the output format from config.pl
hits = re.findall(r'\n +([-\w]+) +- ', help_text)
if hits:
return hits
raise Exception("Unable to figure out supported presets. Pass the '-p' option.")
def list_presets(options):
"""Return the list of presets to test.
The list is taken from the command line if present, otherwise it is
extracted from running the config script with --help.
"""
if options.presets:
return re.split(r'[ ,]+', options.presets)
else:
help_text = subprocess.run([options.script, '--help'],
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT).stdout
return guess_presets_from_help(help_text.decode('ascii'))
def run_one(options, args, stem_prefix='', input_file=None):
"""Run the config script with the given arguments.
Take the original content from input_file if specified, defaulting
to options.input_file if input_file is None.
Write the following files, where xxx contains stem_prefix followed by
a filename-friendly encoding of args:
* config-xxx.h: modified file.
* config-xxx.out: standard output.
* config-xxx.err: standard output.
* config-xxx.status: exit code.
Return ("xxx+", "path/to/config-xxx.h") which can be used as
stem_prefix and input_file to call this function again with new args.
"""
if input_file is None:
input_file = options.input_file
stem = stem_prefix + '-'.join(args)
data_filename = output_file_name(options.output_directory, stem, 'h')
stdout_filename = output_file_name(options.output_directory, stem, 'out')
stderr_filename = output_file_name(options.output_directory, stem, 'err')
status_filename = output_file_name(options.output_directory, stem, 'status')
shutil.copy(input_file, data_filename)
# Pass only the file basename, not the full path, to avoid getting the
# directory name in error messages, which would make comparisons
# between output directories more difficult.
cmd = [os.path.abspath(options.script),
'-f', os.path.basename(data_filename)]
with open(stdout_filename, 'wb') as out:
with open(stderr_filename, 'wb') as err:
status = subprocess.call(cmd + args,
cwd=options.output_directory,
stdin=subprocess.DEVNULL,
stdout=out, stderr=err)
with open(status_filename, 'w') as status_file:
status_file.write('{}\n'.format(status))
return stem + "+", data_filename
### A list of symbols to test with.
### This script currently tests what happens when you change a symbol from
### having a value to not having a value or vice versa. This is not
### necessarily useful behavior, and we may not consider it a bug if
### config.py stops handling that case correctly.
TEST_SYMBOLS = [
'CUSTOM_SYMBOL', # does not exist
'MBEDTLS_AES_C', # set, no value
'MBEDTLS_MPI_MAX_SIZE', # unset, has a value
'MBEDTLS_NO_UDBL_DIVISION', # unset, in "System support"
'MBEDTLS_PLATFORM_ZEROIZE_ALT', # unset, in "Customisation configuration options"
]
def run_all(options):
"""Run all the command lines to test."""
presets = list_presets(options)
for preset in presets:
run_one(options, [preset])
for symbol in TEST_SYMBOLS:
run_one(options, ['get', symbol])
(stem, filename) = run_one(options, ['set', symbol])
run_one(options, ['get', symbol], stem_prefix=stem, input_file=filename)
run_one(options, ['--force', 'set', symbol])
(stem, filename) = run_one(options, ['set', symbol, 'value'])
run_one(options, ['get', symbol], stem_prefix=stem, input_file=filename)
run_one(options, ['--force', 'set', symbol, 'value'])
run_one(options, ['unset', symbol])
def main():
"""Command line entry point."""
parser = argparse.ArgumentParser(description=__doc__,
formatter_class=argparse.RawDescriptionHelpFormatter)
parser.add_argument('-d', metavar='DIR',
dest='output_directory', required=True,
help="""Output directory.""")
parser.add_argument('-f', metavar='FILE',
dest='input_file', default='include/mbedtls/config.h',
help="""Config file (default: %(default)s).""")
parser.add_argument('-p', metavar='PRESET,...',
dest='presets',
help="""Presets to test (default: guessed from --help).""")
parser.add_argument('-s', metavar='FILE',
dest='script', default='scripts/config.py',
help="""Configuration script (default: %(default)s).""")
options = parser.parse_args()
prepare_directory(options.output_directory)
run_all(options)
if __name__ == '__main__':
main()