mirror of
https://github.com/Mbed-TLS/mbedtls.git
synced 2025-08-08 17:42:09 +03:00
Merge remote-tracking branch 'origin/development' into support_cipher_encrypt_only
This commit is contained in:
@@ -123,15 +123,27 @@ set -e -o pipefail -u
|
||||
# Enable ksh/bash extended file matching patterns
|
||||
shopt -s extglob
|
||||
|
||||
in_mbedtls_repo () {
|
||||
test -d include -a -d library -a -d programs -a -d tests
|
||||
}
|
||||
|
||||
in_psa_crypto_repo () {
|
||||
test -d include -a -d core -a -d drivers -a -d programs -a -d tests
|
||||
}
|
||||
|
||||
pre_check_environment () {
|
||||
if [ -d library -a -d include -a -d tests ]; then :; else
|
||||
echo "Must be run from mbed TLS root" >&2
|
||||
if in_mbedtls_repo || in_psa_crypto_repo; then :; else
|
||||
echo "Must be run from Mbed TLS / psa-crypto root" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
pre_initialize_variables () {
|
||||
CONFIG_H='include/mbedtls/mbedtls_config.h'
|
||||
if in_mbedtls_repo; then
|
||||
CONFIG_H='include/mbedtls/mbedtls_config.h'
|
||||
else
|
||||
CONFIG_H='drivers/builtin/include/mbedtls/mbedtls_config.h'
|
||||
fi
|
||||
CRYPTO_CONFIG_H='include/psa/crypto_config.h'
|
||||
CONFIG_TEST_DRIVER_H='tests/include/test/drivers/config_test_driver.h'
|
||||
|
||||
@@ -141,8 +153,10 @@ pre_initialize_variables () {
|
||||
backup_suffix='.all.bak'
|
||||
# Files clobbered by config.py
|
||||
files_to_back_up="$CONFIG_H $CRYPTO_CONFIG_H $CONFIG_TEST_DRIVER_H"
|
||||
# Files clobbered by in-tree cmake
|
||||
files_to_back_up="$files_to_back_up Makefile library/Makefile programs/Makefile tests/Makefile programs/fuzz/Makefile"
|
||||
if in_mbedtls_repo; then
|
||||
# Files clobbered by in-tree cmake
|
||||
files_to_back_up="$files_to_back_up Makefile library/Makefile programs/Makefile tests/Makefile programs/fuzz/Makefile"
|
||||
fi
|
||||
|
||||
append_outcome=0
|
||||
MEMORY=0
|
||||
@@ -299,7 +313,9 @@ EOF
|
||||
# Does not remove generated source files.
|
||||
cleanup()
|
||||
{
|
||||
command make clean
|
||||
if in_mbedtls_repo; then
|
||||
command make clean
|
||||
fi
|
||||
|
||||
# Remove CMake artefacts
|
||||
find . -name .git -prune -o \
|
||||
@@ -556,7 +572,7 @@ pre_check_git () {
|
||||
fi
|
||||
|
||||
if ! git diff --quiet "$CONFIG_H"; then
|
||||
err_msg "Warning - the configuration file 'include/mbedtls/mbedtls_config.h' has been edited. "
|
||||
err_msg "Warning - the configuration file '$CONFIG_H' has been edited. "
|
||||
echo "You can either delete or preserve your work, or force the test by rerunning the"
|
||||
echo "script as: $0 --force"
|
||||
exit 1
|
||||
@@ -1872,6 +1888,16 @@ skip_suites_without_constant_flow () {
|
||||
export SKIP_TEST_SUITES
|
||||
}
|
||||
|
||||
skip_all_except_given_suite () {
|
||||
# Skip all but the given test suite
|
||||
SKIP_TEST_SUITES=$(
|
||||
ls -1 tests/suites/test_suite_*.function |
|
||||
grep -v $1.function |
|
||||
sed 's/tests.suites.test_suite_//; s/\.function$//' |
|
||||
tr '\n' ,)
|
||||
export SKIP_TEST_SUITES
|
||||
}
|
||||
|
||||
component_test_memsan_constant_flow () {
|
||||
# This tests both (1) accesses to undefined memory, and (2) branches or
|
||||
# memory access depending on secret values. To distinguish between those:
|
||||
@@ -1931,6 +1957,16 @@ component_test_valgrind_constant_flow () {
|
||||
# details are left in Testing/<date>/DynamicAnalysis.xml
|
||||
msg "test: some suites (full minus MBEDTLS_USE_PSA_CRYPTO, valgrind + constant flow)"
|
||||
make memcheck
|
||||
|
||||
# Test asm path in constant time module - by default, it will test the plain C
|
||||
# path under Valgrind or Memsan. Running only the constant_time tests is fast (<1s)
|
||||
msg "test: valgrind asm constant_time"
|
||||
scripts/config.py --force set MBEDTLS_TEST_CONSTANT_FLOW_ASM
|
||||
skip_all_except_given_suite test_suite_constant_time
|
||||
cmake -D CMAKE_BUILD_TYPE:String=Release .
|
||||
make clean
|
||||
make
|
||||
make memcheck
|
||||
}
|
||||
|
||||
component_test_valgrind_constant_flow_psa () {
|
||||
@@ -5215,6 +5251,16 @@ support_build_cmake_custom_config_file () {
|
||||
}
|
||||
|
||||
|
||||
component_build_zeroize_checks () {
|
||||
msg "build: check for obviously wrong calls to mbedtls_platform_zeroize()"
|
||||
|
||||
scripts/config.py full
|
||||
|
||||
# Only compile - we're looking for sizeof-pointer-memaccess warnings
|
||||
make CC=gcc CFLAGS="'-DMBEDTLS_USER_CONFIG_FILE=\"../tests/configs/user-config-zeroize-memset.h\"' -DMBEDTLS_TEST_DEFINES_ZEROIZE -Werror -Wsizeof-pointer-memaccess"
|
||||
}
|
||||
|
||||
|
||||
component_test_zeroize () {
|
||||
# Test that the function mbedtls_platform_zeroize() is not optimized away by
|
||||
# different combinations of compilers and optimization flags by using an
|
||||
@@ -5398,7 +5444,9 @@ pre_prepare_outcome_file
|
||||
pre_print_configuration
|
||||
pre_check_tools
|
||||
cleanup
|
||||
pre_generate_files
|
||||
if in_mbedtls_repo; then
|
||||
pre_generate_files
|
||||
fi
|
||||
|
||||
# Run the requested tests.
|
||||
for ((error_test_i=1; error_test_i <= error_test; error_test_i++)); do
|
||||
|
@@ -73,15 +73,22 @@ def execute_reference_driver_tests(ref_component, driver_component, outcome_file
|
||||
Results.log("Error: failed to run reference/driver components")
|
||||
sys.exit(ret_val)
|
||||
|
||||
def analyze_coverage(results, outcomes):
|
||||
def analyze_coverage(results, outcomes, allow_list, full_coverage):
|
||||
"""Check that all available test cases are executed at least once."""
|
||||
available = check_test_cases.collect_available_test_cases()
|
||||
for key in available:
|
||||
hits = outcomes[key].hits() if key in outcomes else 0
|
||||
if hits == 0:
|
||||
# Make this a warning, not an error, as long as we haven't
|
||||
# fixed this branch to have full coverage of test cases.
|
||||
results.warning('Test case not executed: {}', key)
|
||||
if hits == 0 and key not in allow_list:
|
||||
if full_coverage:
|
||||
results.error('Test case not executed: {}', key)
|
||||
else:
|
||||
results.warning('Test case not executed: {}', key)
|
||||
elif hits != 0 and key in allow_list:
|
||||
# Test Case should be removed from the allow list.
|
||||
if full_coverage:
|
||||
results.error('Allow listed test case was executed: {}', key)
|
||||
else:
|
||||
results.warning('Allow listed test case was executed: {}', key)
|
||||
|
||||
def analyze_driver_vs_reference(outcomes, component_ref, component_driver,
|
||||
ignored_suites, ignored_test=None):
|
||||
@@ -122,10 +129,11 @@ def analyze_driver_vs_reference(outcomes, component_ref, component_driver,
|
||||
result = False
|
||||
return result
|
||||
|
||||
def analyze_outcomes(outcomes):
|
||||
def analyze_outcomes(outcomes, args):
|
||||
"""Run all analyses on the given outcome collection."""
|
||||
results = Results()
|
||||
analyze_coverage(results, outcomes)
|
||||
analyze_coverage(results, outcomes, args['allow_list'],
|
||||
args['full_coverage'])
|
||||
return results
|
||||
|
||||
def read_outcome_file(outcome_file):
|
||||
@@ -151,10 +159,9 @@ by a semicolon.
|
||||
|
||||
def do_analyze_coverage(outcome_file, args):
|
||||
"""Perform coverage analysis."""
|
||||
del args # unused
|
||||
outcomes = read_outcome_file(outcome_file)
|
||||
Results.log("\n*** Analyze coverage ***\n")
|
||||
results = analyze_outcomes(outcomes)
|
||||
results = analyze_outcomes(outcomes, args)
|
||||
return results.error_count == 0
|
||||
|
||||
def do_analyze_driver_vs_reference(outcome_file, args):
|
||||
@@ -175,8 +182,16 @@ def do_analyze_driver_vs_reference(outcome_file, args):
|
||||
TASKS = {
|
||||
'analyze_coverage': {
|
||||
'test_function': do_analyze_coverage,
|
||||
'args': {}
|
||||
},
|
||||
'args': {
|
||||
'allow_list': [
|
||||
# Algorithm not supported yet
|
||||
'test_suite_psa_crypto_metadata;Asymmetric signature: pure EdDSA',
|
||||
# Algorithm not supported yet
|
||||
'test_suite_psa_crypto_metadata;Cipher: XTS',
|
||||
],
|
||||
'full_coverage': False,
|
||||
}
|
||||
},
|
||||
# There are 2 options to use analyze_driver_vs_reference_xxx locally:
|
||||
# 1. Run tests and then analysis:
|
||||
# - tests/scripts/all.sh --outcome-file "$PWD/out.csv" <component_ref> <component_driver>
|
||||
@@ -426,6 +441,11 @@ def main():
|
||||
'comma/space-separated list of tasks. ')
|
||||
parser.add_argument('--list', action='store_true',
|
||||
help='List all available tasks and exit.')
|
||||
parser.add_argument('--require-full-coverage', action='store_true',
|
||||
dest='full_coverage', help="Require all available "
|
||||
"test cases to be executed and issue an error "
|
||||
"otherwise. This flag is ignored if 'task' is "
|
||||
"neither 'all' nor 'analyze_coverage'")
|
||||
options = parser.parse_args()
|
||||
|
||||
if options.list:
|
||||
@@ -445,6 +465,9 @@ def main():
|
||||
Results.log('Error: invalid task: {}'.format(task))
|
||||
sys.exit(1)
|
||||
|
||||
TASKS['analyze_coverage']['args']['full_coverage'] = \
|
||||
options.full_coverage
|
||||
|
||||
for task in TASKS:
|
||||
if task in tasks:
|
||||
if not TASKS[task]['test_function'](options.outcomes, TASKS[task]['args']):
|
||||
|
@@ -25,6 +25,7 @@ import argparse
|
||||
import glob
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
class Results:
|
||||
@@ -111,6 +112,19 @@ state may override this method.
|
||||
self.process_test_case(descriptions,
|
||||
file_name, line_number, description)
|
||||
|
||||
def walk_compat_sh(self, file_name):
|
||||
"""Iterate over the test cases compat.sh with a similar format."""
|
||||
descriptions = self.new_per_file_state() # pylint: disable=assignment-from-none
|
||||
compat_cmd = ['sh', file_name, '--list-test-case']
|
||||
compat_output = subprocess.check_output(compat_cmd)
|
||||
# Assume compat.sh is responsible for printing identical format of
|
||||
# test case description between --list-test-case and its OUTCOME.CSV
|
||||
description = compat_output.strip().split(b'\n')
|
||||
# idx indicates the number of test case since there is no line number
|
||||
# in `compat.sh` for each test case.
|
||||
for idx, descrip in enumerate(description):
|
||||
self.process_test_case(descriptions, file_name, idx, descrip)
|
||||
|
||||
@staticmethod
|
||||
def collect_test_directories():
|
||||
"""Get the relative path for the TLS and Crypto test directories."""
|
||||
@@ -136,6 +150,9 @@ state may override this method.
|
||||
for ssl_opt_file_name in glob.glob(os.path.join(directory, 'opt-testcases',
|
||||
'*.sh')):
|
||||
self.walk_ssl_opt_sh(ssl_opt_file_name)
|
||||
compat_sh = os.path.join(directory, 'compat.sh')
|
||||
if os.path.exists(compat_sh):
|
||||
self.walk_compat_sh(compat_sh)
|
||||
|
||||
class TestDescriptions(TestDescriptionExplorer):
|
||||
"""Collect the available test cases."""
|
||||
|
@@ -1,10 +1,10 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Run the PSA Crypto API compliance test suite.
|
||||
Clone the repo and check out the commit specified by PSA_ARCH_TEST_REPO and PSA_ARCH_TEST_REF,
|
||||
then compile and run the test suite. The clone is stored at <Mbed TLS root>/psa-arch-tests.
|
||||
Known defects in either the test suite or mbedtls - identified by their test number - are ignored,
|
||||
while unexpected failures AND successes are reported as errors,
|
||||
to help keep the list of known defects as up to date as possible.
|
||||
then compile and run the test suite. The clone is stored at <repository root>/psa-arch-tests.
|
||||
Known defects in either the test suite or mbedtls / psa-crypto - identified by their test
|
||||
number - are ignored, while unexpected failures AND successes are reported as errors, to help
|
||||
keep the list of known defects as up to date as possible.
|
||||
"""
|
||||
|
||||
# Copyright The Mbed TLS Contributors
|
||||
@@ -22,13 +22,20 @@ to help keep the list of known defects as up to date as possible.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import re
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
from typing import List
|
||||
|
||||
# PSA Compliance tests we expect to fail due to known defects in Mbed TLS (or the test suite)
|
||||
#pylint: disable=unused-import
|
||||
import scripts_path
|
||||
from mbedtls_dev import build_tree
|
||||
|
||||
# PSA Compliance tests we expect to fail due to known defects in Mbed TLS / PSA Crypto
|
||||
# (or the test suite).
|
||||
# The test numbers correspond to the numbers used by the console output of the test suite.
|
||||
# Test number 2xx corresponds to the files in the folder
|
||||
# psa-arch-tests/api-tests/dev_apis/crypto/test_c0xx
|
||||
@@ -49,12 +56,32 @@ EXPECTED_FAILURES = {
|
||||
PSA_ARCH_TESTS_REPO = 'https://github.com/bensze01/psa-arch-tests.git'
|
||||
PSA_ARCH_TESTS_REF = 'fix-pr-5736'
|
||||
|
||||
#pylint: disable=too-many-branches,too-many-statements
|
||||
def main():
|
||||
mbedtls_dir = os.getcwd()
|
||||
#pylint: disable=too-many-branches,too-many-statements,too-many-locals
|
||||
def main(library_build_dir: str):
|
||||
root_dir = os.getcwd()
|
||||
|
||||
if not os.path.exists('library/libmbedcrypto.a'):
|
||||
subprocess.check_call(['make', '-C', 'library', 'libmbedcrypto.a'])
|
||||
in_psa_crypto_repo = build_tree.looks_like_psa_crypto_root(root_dir)
|
||||
|
||||
if in_psa_crypto_repo:
|
||||
crypto_name = 'psacrypto'
|
||||
library_subdir = 'core'
|
||||
else:
|
||||
crypto_name = 'mbedcrypto'
|
||||
library_subdir = 'library'
|
||||
|
||||
crypto_lib_filename = (library_build_dir + '/' +
|
||||
library_subdir + '/' +
|
||||
'lib' + crypto_name + '.a')
|
||||
|
||||
if not os.path.exists(crypto_lib_filename):
|
||||
#pylint: disable=bad-continuation
|
||||
subprocess.check_call([
|
||||
'cmake', '.',
|
||||
'-GUnix Makefiles',
|
||||
'-B' + library_build_dir
|
||||
])
|
||||
subprocess.check_call(['cmake', '--build', library_build_dir,
|
||||
'--target', crypto_name])
|
||||
|
||||
psa_arch_tests_dir = 'psa-arch-tests'
|
||||
os.makedirs(psa_arch_tests_dir, exist_ok=True)
|
||||
@@ -74,6 +101,9 @@ def main():
|
||||
os.mkdir(build_dir)
|
||||
os.chdir(build_dir)
|
||||
|
||||
extra_includes = (';{}/drivers/builtin/include'.format(root_dir)
|
||||
if in_psa_crypto_repo else '')
|
||||
|
||||
#pylint: disable=bad-continuation
|
||||
subprocess.check_call([
|
||||
'cmake', '..',
|
||||
@@ -81,8 +111,9 @@ def main():
|
||||
'-DTARGET=tgt_dev_apis_stdc',
|
||||
'-DTOOLCHAIN=HOST_GCC',
|
||||
'-DSUITE=CRYPTO',
|
||||
'-DPSA_CRYPTO_LIB_FILENAME={}/library/libmbedcrypto.a'.format(mbedtls_dir),
|
||||
'-DPSA_INCLUDE_PATHS={}/include'.format(mbedtls_dir)
|
||||
'-DPSA_CRYPTO_LIB_FILENAME={}/{}'.format(root_dir,
|
||||
crypto_lib_filename),
|
||||
('-DPSA_INCLUDE_PATHS={}/include' + extra_includes).format(root_dir)
|
||||
])
|
||||
subprocess.check_call(['cmake', '--build', '.'])
|
||||
|
||||
@@ -95,8 +126,11 @@ def main():
|
||||
)
|
||||
test = -1
|
||||
unexpected_successes = set(EXPECTED_FAILURES)
|
||||
expected_failures = []
|
||||
unexpected_failures = []
|
||||
expected_failures = [] # type: List[int]
|
||||
unexpected_failures = [] # type: List[int]
|
||||
if proc.stdout is None:
|
||||
return 1
|
||||
|
||||
for line in proc.stdout:
|
||||
print(line, end='')
|
||||
match = test_re.match(line)
|
||||
@@ -136,7 +170,18 @@ def main():
|
||||
print('SUCCESS')
|
||||
return 0
|
||||
finally:
|
||||
os.chdir(mbedtls_dir)
|
||||
os.chdir(root_dir)
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
||||
BUILD_DIR = 'out_of_source_build'
|
||||
|
||||
# pylint: disable=invalid-name
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('--build-dir', nargs=1,
|
||||
help='path to Mbed TLS / PSA Crypto build directory')
|
||||
args = parser.parse_args()
|
||||
|
||||
if args.build_dir is not None:
|
||||
BUILD_DIR = args.build_dir[0]
|
||||
|
||||
sys.exit(main(BUILD_DIR))
|
||||
|
Reference in New Issue
Block a user