1
0
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:
Yanray Wang
2023-09-07 16:18:00 +08:00
73 changed files with 2724 additions and 1288 deletions

View File

@@ -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

View File

@@ -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']):

View File

@@ -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."""

View File

@@ -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))