mirror of
https://github.com/yuzu-mirror/mbedtls.git
synced 2026-04-04 22:19:05 +00:00
Merge mbed-crypto into mbedtls: the merge commit
Merge `unremove-non-crypto` into `mbedtls/development`. The branch
`unremove-non-crypto` was obtained by starting from `mbed-crypto/development`,
then reverting many commits that removed X.509 and TLS functionality when Mbed
Crypto forked from Mbed TLS (the “unremoval”), then make a few tweaks to
facilitate the merge.
The unremoval step restored old versions of some tls files. If a file doesn't
exist in mbed-crypto, check out the mbedtls version, regardless of what
happened during the unremoval of tls files in the crypto tree. Also
unconditionally take the mbedtls version of a few files where the
modifications are completely project-specific and are not relevant in
mbed-crypto:
* `.github/issue_template.md`: completely different. We may want to reconcile
them independently as a follow-up.
* `.travis.yml`: would only be reverted to an earlier tls version.
* `README.md`: completely different. We may want to reconcile them
independently as a follow-up.
* `doxygen/input/doc_mainpage.h`: the changes in crypto were minimal and not
relevant except as a stopgap as mbed-crypto did not have its own product
versioning in the Doxygen documentation.
* `tests/.jenkins/Jenkinsfile`: completely different.
* `tests/data_files/Makefile`: there were no changes in mbed-crypto,
but the unremoval step restored an old version.
Shell script for everything to do after the merge apart from the conflict
resolution:
```
tls_files=($(comm -23 <(git ls-tree -r --name-only HEAD) <(git ls-tree -r --name-only $(git merge-base upstream-crypto/development MERGE_HEAD))))
tls_files+=($tls_files .github/issue_template.md .travis.yml README.md doxygen/input/doc_mainpage.h tests/.jenkins/Jenkinsfile tests/data_files/Makefile)
git checkout --theirs HEAD -- $tls_files
git add -- $tls_files
```
Resolve the remaining conflicts:
* `library/CMakeLists.txt`:
* Keep the TLS definition of `src_crypto`
* `USE_SHARED_MBEDTLS_LIBRARY`: keep all three libraries, with both
`include` and `crypto/include` in `target_include_directories`, all with
version `2.21.0`.
* `programs/Makefile`:
* Reconcile the APPS lists (add/add from a differently-formatted common
ancestor): insert the `psa/*` from crypto into the tls list.
* Keep the `fuzz` target defined only in tls version.
* Keep the recipe (only in tls version) cleaning `ssl_pthread_server`
stuff for the `clean` target.
* `scripts/config.py`:
* `include_in_full`: add/add conflict. Keep both.
* `tests/scripts/all.sh`:
* `component_test_no_use_psa_crypto_full_cmake_asan`: partially old
version in crypto. Take the tls version.
* `component_test_malloc_0_null` and more: take
`component_test_malloc_0_null` from crypto (with `config.py` rather than
`config.pl`, and with `$ASAN_FLAGS` rather than an explicit list), but
add the call to `ssl-opt.sh` from tls. Take the other components from
crypto.
With this commit, building and running the unit tests with both `make ` and
`cmake` work in the default configuration on Linux. Other platforms, build
systems and configurations are likely not to work, and there is some
regression in test coverage.
There is some loss of functionality because the unremoval step restored older
versions of tls content. This commit contains the latest tls version of
tls-only files, but some changes from the tls side in files that existed on
both sides have regressed. Most problematic changes are hunks that remove some
tls-specific feature and contain either a C preprocessor symbol identifying a
tls-specific module or option, or the name of a tls-specific file. Hunks
that remove a tls-specific preprocessor symbol can be identified with the
regular expression `^-.*MBEDTLS_(ERR_)?(PKCS11|X509|NET|SSL)_`.
Subsequent commits will revert a few parts of the patch from this merge commit
in order to restore the tls functionality that it removes, ensure that the
test coverage includes what was covered in either branch, and fix test
failures.
This commit is contained in:
commit
b99bd39b4e
397 changed files with 168444 additions and 995 deletions
|
|
@ -24,8 +24,7 @@
|
|||
# configurations, and can and will arbitrarily change the current CMake
|
||||
# configuration. The following files must be committed into git:
|
||||
# * include/mbedtls/config.h
|
||||
# * Makefile, library/Makefile, programs/Makefile, tests/Makefile,
|
||||
# programs/fuzz/Makefile
|
||||
# * Makefile, library/Makefile, programs/Makefile, tests/Makefile
|
||||
# After running this script, the CMake cache will be lost and CMake
|
||||
# will no longer be initialised.
|
||||
#
|
||||
|
|
@ -76,9 +75,9 @@
|
|||
# * Run `make clean`.
|
||||
# * Restore `include/mbedtks/config.h` from a backup made before running
|
||||
# the component.
|
||||
# * Check out `Makefile`, `library/Makefile`, `programs/Makefile`,
|
||||
# `tests/Makefile` and `programs/fuzz/Makefile` from git.
|
||||
# This cleans up after an in-tree use of CMake.
|
||||
# * Check out `Makefile`, `library/Makefile`, `programs/Makefile` and
|
||||
# `tests/Makefile` from git. This cleans up after an in-tree use of
|
||||
# CMake.
|
||||
#
|
||||
# Any command that is expected to fail must be protected so that the
|
||||
# script keeps running in --keep-going mode despite `set -e`. In keep-going
|
||||
|
|
@ -144,6 +143,9 @@ pre_initialize_variables () {
|
|||
export MAKEFLAGS="-j"
|
||||
fi
|
||||
|
||||
# Include more verbose output for failing tests run by CMake
|
||||
export CTEST_OUTPUT_ON_FAILURE=1
|
||||
|
||||
# CFLAGS and LDFLAGS for Asan builds that don't use CMake
|
||||
ASAN_CFLAGS='-Werror -Wall -Wextra -fsanitize=address,undefined -fno-sanitize-recover=all'
|
||||
|
||||
|
|
@ -236,9 +238,6 @@ cleanup()
|
|||
fi
|
||||
|
||||
command make clean
|
||||
cd crypto
|
||||
command make clean
|
||||
cd ..
|
||||
|
||||
# Remove CMake artefacts
|
||||
find . -name .git -prune -o \
|
||||
|
|
@ -248,13 +247,13 @@ cleanup()
|
|||
-iname CMakeCache.txt \) -exec rm {} \+
|
||||
# Recover files overwritten by in-tree CMake builds
|
||||
rm -f include/Makefile include/mbedtls/Makefile programs/*/Makefile
|
||||
git update-index --no-skip-worktree Makefile library/Makefile programs/Makefile tests/Makefile programs/fuzz/Makefile
|
||||
git checkout -- Makefile library/Makefile programs/Makefile tests/Makefile programs/fuzz/Makefile
|
||||
cd crypto
|
||||
rm -f include/Makefile include/mbedtls/Makefile programs/*/Makefile
|
||||
git update-index --no-skip-worktree Makefile library/Makefile programs/Makefile tests/Makefile
|
||||
git checkout -- Makefile library/Makefile programs/Makefile tests/Makefile
|
||||
cd ..
|
||||
|
||||
# Remove any artifacts from the component_test_cmake_as_subdirectory test.
|
||||
rm -rf programs/test/cmake_subproject/build
|
||||
rm -f programs/test/cmake_subproject/Makefile
|
||||
rm -f programs/test/cmake_subproject/cmake_subproject
|
||||
|
||||
# Remove any artifacts from the component_test_cmake_as_subdirectory test.
|
||||
rm -rf programs/test/cmake_subproject/build
|
||||
|
|
@ -334,6 +333,9 @@ pre_parse_command_line () {
|
|||
all_except=0
|
||||
no_armcc=
|
||||
|
||||
# Note that legacy options are ignored instead of being omitted from this
|
||||
# list of options, so invocations that worked with previous version of
|
||||
# all.sh will still run and work properly.
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
--append-outcome) append_outcome=1;;
|
||||
|
|
@ -418,19 +420,6 @@ pre_check_git () {
|
|||
exit 1
|
||||
fi
|
||||
fi
|
||||
if ! [ -f crypto/Makefile ]; then
|
||||
echo "Please initialize the crypto submodule" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
pre_check_seedfile () {
|
||||
if [ ! -f "./tests/seedfile" ]; then
|
||||
dd if=/dev/urandom of=./tests/seedfile bs=32 count=1
|
||||
fi
|
||||
if [ ! -f "./crypto/tests/seedfile" ]; then
|
||||
dd if=/dev/urandom of=./crypto/tests/seedfile bs=32 count=1
|
||||
fi
|
||||
}
|
||||
|
||||
pre_setup_keep_going () {
|
||||
|
|
@ -516,7 +505,6 @@ pre_print_configuration () {
|
|||
echo "FORCE: $FORCE"
|
||||
echo "MBEDTLS_TEST_OUTCOME_FILE: ${MBEDTLS_TEST_OUTCOME_FILE:-(none)}"
|
||||
echo "SEED: ${SEED-"UNSET"}"
|
||||
echo
|
||||
echo "OPENSSL: $OPENSSL"
|
||||
echo "OPENSSL_LEGACY: $OPENSSL_LEGACY"
|
||||
echo "OPENSSL_NEXT: $OPENSSL_NEXT"
|
||||
|
|
@ -644,7 +632,6 @@ component_check_doxygen_warnings () {
|
|||
}
|
||||
|
||||
|
||||
|
||||
################################################################
|
||||
#### Build and test many configurations and targets
|
||||
################################################################
|
||||
|
|
@ -689,51 +676,6 @@ component_test_full_cmake_gcc_asan () {
|
|||
|
||||
msg "test: main suites (inc. selftests) (full config, ASan build)"
|
||||
make test
|
||||
|
||||
msg "test: ssl-opt.sh (full config, ASan build)"
|
||||
if_build_succeeded tests/ssl-opt.sh
|
||||
|
||||
msg "test: compat.sh (full config, ASan build)"
|
||||
if_build_succeeded tests/compat.sh
|
||||
}
|
||||
|
||||
component_test_zlib_make() {
|
||||
msg "build: zlib enabled, make"
|
||||
scripts/config.py set MBEDTLS_ZLIB_SUPPORT
|
||||
make ZLIB=1 CFLAGS='-Werror -O1'
|
||||
|
||||
msg "test: main suites (zlib, make)"
|
||||
make test
|
||||
|
||||
msg "test: ssl-opt.sh (zlib, make)"
|
||||
if_build_succeeded tests/ssl-opt.sh
|
||||
}
|
||||
support_test_zlib_make () {
|
||||
base=support_test_zlib_$$
|
||||
cat <<'EOF' > ${base}.c
|
||||
#include "zlib.h"
|
||||
int main(void) { return 0; }
|
||||
EOF
|
||||
gcc -o ${base}.exe ${base}.c -lz 2>/dev/null
|
||||
ret=$?
|
||||
rm -f ${base}.*
|
||||
return $ret
|
||||
}
|
||||
|
||||
component_test_zlib_cmake() {
|
||||
msg "build: zlib enabled, cmake"
|
||||
scripts/config.py set MBEDTLS_ZLIB_SUPPORT
|
||||
cmake -D ENABLE_ZLIB_SUPPORT=On -D CMAKE_BUILD_TYPE:String=Check .
|
||||
make
|
||||
|
||||
msg "test: main suites (zlib, cmake)"
|
||||
make test
|
||||
|
||||
msg "test: ssl-opt.sh (zlib, cmake)"
|
||||
if_build_succeeded tests/ssl-opt.sh
|
||||
}
|
||||
support_test_zlib_cmake () {
|
||||
support_test_zlib_make "$@"
|
||||
}
|
||||
|
||||
component_test_ref_configs () {
|
||||
|
|
@ -742,6 +684,19 @@ component_test_ref_configs () {
|
|||
record_status tests/scripts/test-ref-configs.pl
|
||||
}
|
||||
|
||||
component_test_no_pem_no_fs () {
|
||||
msg "build: Default + !MBEDTLS_PEM_PARSE_C + !MBEDTLS_FS_IO (ASan build)"
|
||||
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
|
||||
|
||||
msg "test: !MBEDTLS_PEM_PARSE_C !MBEDTLS_FS_IO - main suites (inc. selftests) (ASan build)" # ~ 50s
|
||||
make test
|
||||
}
|
||||
|
||||
component_test_sslv3 () {
|
||||
msg "build: Default + SSLv3 (ASan build)" # ~ 6 min
|
||||
scripts/config.py set MBEDTLS_SSL_PROTO_SSL3
|
||||
|
|
@ -772,20 +727,6 @@ component_test_no_renegotiation () {
|
|||
if_build_succeeded tests/ssl-opt.sh
|
||||
}
|
||||
|
||||
component_test_no_pem_no_fs () {
|
||||
msg "build: Default + !MBEDTLS_PEM_PARSE_C + !MBEDTLS_FS_IO (ASan build)"
|
||||
scripts/config.py unset MBEDTLS_PEM_PARSE_C
|
||||
scripts/config.py unset MBEDTLS_FS_IO
|
||||
CC=gcc cmake -D CMAKE_BUILD_TYPE:String=Asan .
|
||||
make
|
||||
|
||||
msg "test: !MBEDTLS_PEM_PARSE_C !MBEDTLS_FS_IO - main suites (inc. selftests) (ASan build)" # ~ 50s
|
||||
make test
|
||||
|
||||
msg "test: !MBEDTLS_PEM_PARSE_C !MBEDTLS_FS_IO - ssl-opt.sh (ASan build)" # ~ 6 min
|
||||
if_build_succeeded tests/ssl-opt.sh
|
||||
}
|
||||
|
||||
component_test_rsa_no_crt () {
|
||||
msg "build: Default + RSA_NO_CRT (ASan build)" # ~ 6 min
|
||||
scripts/config.py set MBEDTLS_RSA_NO_CRT
|
||||
|
|
@ -802,24 +743,6 @@ component_test_rsa_no_crt () {
|
|||
if_build_succeeded tests/compat.sh -t RSA
|
||||
}
|
||||
|
||||
component_test_everest () {
|
||||
msg "build: Everest ECDH context (ASan build)" # ~ 6 min
|
||||
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
|
||||
|
||||
msg "test: Everest ECDH context - main suites (inc. selftests) (ASan build)" # ~ 50s
|
||||
make test
|
||||
|
||||
msg "test: Everest ECDH context - ECDH-related part of ssl-opt.sh (ASan build)" # ~ 5s
|
||||
if_build_succeeded tests/ssl-opt.sh -f ECDH
|
||||
|
||||
msg "test: Everest ECDH context - compat.sh with some ECDH ciphersuites (ASan build)" # ~ 3 min
|
||||
# Exclude some symmetric ciphers that are redundant here to gain time.
|
||||
if_build_succeeded tests/compat.sh -f ECDH -V NO -e 'ARCFOUR\|ARIA\|CAMELLIA\|CHACHA\|DES\|RC4'
|
||||
}
|
||||
|
||||
component_test_small_ssl_out_content_len () {
|
||||
msg "build: small SSL_OUT_CONTENT_LEN (ASan build)"
|
||||
scripts/config.py set MBEDTLS_SSL_IN_CONTENT_LEN 16384
|
||||
|
|
@ -854,7 +777,7 @@ component_test_small_ssl_dtls_max_buffering () {
|
|||
|
||||
component_test_small_mbedtls_ssl_dtls_max_buffering () {
|
||||
msg "build: small MBEDTLS_SSL_DTLS_MAX_BUFFERING #1"
|
||||
scripts/config.py set MBEDTLS_SSL_DTLS_MAX_BUFFERING 190
|
||||
scripts/config.py set MBEDTLS_SSL_DTLS_MAX_BUFFERING 240
|
||||
CC=gcc cmake -D CMAKE_BUILD_TYPE:String=Asan .
|
||||
make
|
||||
|
||||
|
|
@ -862,15 +785,48 @@ component_test_small_mbedtls_ssl_dtls_max_buffering () {
|
|||
if_build_succeeded tests/ssl-opt.sh -f "DTLS reordering: Buffer encrypted Finished message, drop for fragmented NewSessionTicket"
|
||||
}
|
||||
|
||||
component_test_new_ecdh_context () {
|
||||
msg "build: new ECDH context (ASan build)" # ~ 6 min
|
||||
scripts/config.py unset MBEDTLS_ECDH_LEGACY_CONTEXT
|
||||
CC=gcc cmake -D CMAKE_BUILD_TYPE:String=Asan .
|
||||
make
|
||||
|
||||
msg "test: new ECDH context - main suites (inc. selftests) (ASan build)" # ~ 50s
|
||||
make test
|
||||
}
|
||||
|
||||
component_test_everest () {
|
||||
msg "build: Everest ECDH context (ASan build)" # ~ 6 min
|
||||
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
|
||||
|
||||
msg "test: Everest ECDH context - main suites (inc. selftests) (ASan build)" # ~ 50s
|
||||
make test
|
||||
}
|
||||
|
||||
component_test_psa_collect_statuses () {
|
||||
msg "build+test: psa_collect_statuses" # ~30s
|
||||
scripts/config.py full
|
||||
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
|
||||
rm -f tests/statuses.log
|
||||
}
|
||||
|
||||
component_test_full_cmake_clang () {
|
||||
msg "build: cmake, full config, clang" # ~ 50s
|
||||
scripts/config.py full
|
||||
CC=clang cmake -D CMAKE_BUILD_TYPE:String=Check -D ENABLE_TESTING=On .
|
||||
make
|
||||
|
||||
msg "test: main suites (full config)" # ~ 5s
|
||||
msg "test: main suites (full config, clang)" # ~ 5s
|
||||
make test
|
||||
|
||||
msg "test: psa_constant_names (full config, clang)" # ~ 1s
|
||||
record_status tests/scripts/test_psa_constant_names.py
|
||||
|
||||
msg "test: ssl-opt.sh default, ECJPAKE, SSL async (full config)" # ~ 1s
|
||||
if_build_succeeded tests/ssl-opt.sh -f 'Default\|ECJPAKE\|SSL async private'
|
||||
|
||||
|
|
@ -881,6 +837,15 @@ component_test_full_cmake_clang () {
|
|||
if_build_succeeded env OPENSSL_CMD="$OPENSSL_NEXT" tests/compat.sh -e '^$' -f 'ARIA\|CHACHA'
|
||||
}
|
||||
|
||||
component_test_full_make_gcc_o0 () {
|
||||
msg "build: make, full config, gcc -O0" # ~ 50s
|
||||
scripts/config.py full
|
||||
make CC=gcc CFLAGS='-O0'
|
||||
|
||||
msg "test: main suites (full config, gcc -O0)" # ~ 5s
|
||||
make test
|
||||
}
|
||||
|
||||
component_build_deprecated () {
|
||||
msg "build: make, full config + DEPRECATED_WARNING, gcc -O" # ~ 30s
|
||||
scripts/config.py full
|
||||
|
|
@ -889,6 +854,10 @@ component_build_deprecated () {
|
|||
make CC=gcc CFLAGS='-O -Werror -Wall -Wextra' lib programs
|
||||
make CC=gcc CFLAGS='-O -Werror -Wall -Wextra -Wno-unused-function' tests
|
||||
|
||||
msg "test: make, full config + DEPRECATED_WARNING, expect warnings" # ~ 30s
|
||||
make -C tests clean
|
||||
make CC=gcc CFLAGS='-O -Werror -Wall -Wextra -Wno-error=deprecated-declarations -DMBEDTLS_TEST_DEPRECATED' tests
|
||||
|
||||
msg "build: make, full config + DEPRECATED_REMOVED, clang -O" # ~ 30s
|
||||
# No cleanup, just tweak the configuration and rebuild
|
||||
make clean
|
||||
|
|
@ -1034,6 +1003,7 @@ component_test_no_platform () {
|
|||
scripts/config.py unset MBEDTLS_PLATFORM_EXIT_ALT
|
||||
scripts/config.py unset MBEDTLS_ENTROPY_NV_SEED
|
||||
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,
|
||||
|
|
@ -1097,10 +1067,6 @@ component_test_memory_buffer_allocator () {
|
|||
|
||||
msg "test: MBEDTLS_MEMORY_BUFFER_ALLOC_C"
|
||||
make test
|
||||
|
||||
msg "test: ssl-opt.sh, MBEDTLS_MEMORY_BUFFER_ALLOC_C"
|
||||
# MBEDTLS_MEMORY_BUFFER_ALLOC is slow. Skip tests that tend to time out.
|
||||
if_build_succeeded tests/ssl-opt.sh -e '^DTLS proxy'
|
||||
}
|
||||
|
||||
component_test_no_max_fragment_length () {
|
||||
|
|
@ -1142,20 +1108,6 @@ component_test_no_max_fragment_length_small_ssl_out_content_len () {
|
|||
if_build_succeeded tests/ssl-opt.sh -f "Max fragment length\|Large buffer"
|
||||
}
|
||||
|
||||
component_test_when_no_ciphersuites_have_mac () {
|
||||
msg "build: when no ciphersuites have MAC"
|
||||
scripts/config.py unset MBEDTLS_CIPHER_NULL_CIPHER
|
||||
scripts/config.py unset MBEDTLS_ARC4_C
|
||||
scripts/config.py unset MBEDTLS_CIPHER_MODE_CBC
|
||||
make
|
||||
|
||||
msg "test: !MBEDTLS_SSL_SOME_MODES_USE_MAC"
|
||||
make test
|
||||
|
||||
msg "test ssl-opt.sh: !MBEDTLS_SSL_SOME_MODES_USE_MAC"
|
||||
if_build_succeeded tests/ssl-opt.sh -f 'Default\|EtM' -e 'without EtM'
|
||||
}
|
||||
|
||||
component_test_null_entropy () {
|
||||
msg "build: default config with MBEDTLS_TEST_NULL_ENTROPY (ASan build)"
|
||||
scripts/config.py set MBEDTLS_TEST_NULL_ENTROPY
|
||||
|
|
@ -1186,8 +1138,7 @@ component_test_platform_calloc_macro () {
|
|||
component_test_malloc_0_null () {
|
||||
msg "build: malloc(0) returns NULL (ASan+UBSan build)"
|
||||
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\"' -O -Werror -Wall -Wextra -fsanitize=address,undefined" LDFLAGS='-fsanitize=address,undefined'
|
||||
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)"
|
||||
make test
|
||||
|
|
@ -1206,6 +1157,90 @@ component_test_malloc_0_null () {
|
|||
if_build_succeeded tests/ssl-opt.sh -e 'proxy'
|
||||
}
|
||||
|
||||
component_test_aes_fewer_tables () {
|
||||
msg "build: default config with AES_FEWER_TABLES enabled"
|
||||
scripts/config.py set MBEDTLS_AES_FEWER_TABLES
|
||||
make CC=gcc CFLAGS='-Werror -Wall -Wextra'
|
||||
|
||||
msg "test: AES_FEWER_TABLES"
|
||||
make test
|
||||
}
|
||||
|
||||
component_test_aes_rom_tables () {
|
||||
msg "build: default config with AES_ROM_TABLES enabled"
|
||||
scripts/config.py set MBEDTLS_AES_ROM_TABLES
|
||||
make CC=gcc CFLAGS='-Werror -Wall -Wextra'
|
||||
|
||||
msg "test: AES_ROM_TABLES"
|
||||
make test
|
||||
}
|
||||
|
||||
component_test_aes_fewer_tables_and_rom_tables () {
|
||||
msg "build: default config with AES_ROM_TABLES and AES_FEWER_TABLES enabled"
|
||||
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"
|
||||
make test
|
||||
}
|
||||
|
||||
component_test_ctr_drbg_aes_256_sha_256 () {
|
||||
msg "build: full + MBEDTLS_ENTROPY_FORCE_SHA256 (ASan build)"
|
||||
scripts/config.py full
|
||||
scripts/config.py unset MBEDTLS_MEMORY_BUFFER_ALLOC_C
|
||||
scripts/config.py set MBEDTLS_ENTROPY_FORCE_SHA256
|
||||
CC=gcc cmake -D CMAKE_BUILD_TYPE:String=Asan .
|
||||
make
|
||||
|
||||
msg "test: full + MBEDTLS_ENTROPY_FORCE_SHA256 (ASan build)"
|
||||
make test
|
||||
}
|
||||
|
||||
component_test_ctr_drbg_aes_128_sha_512 () {
|
||||
msg "build: full + MBEDTLS_CTR_DRBG_USE_128_BIT_KEY (ASan build)"
|
||||
scripts/config.py full
|
||||
scripts/config.py unset MBEDTLS_MEMORY_BUFFER_ALLOC_C
|
||||
scripts/config.py set MBEDTLS_CTR_DRBG_USE_128_BIT_KEY
|
||||
CC=gcc cmake -D CMAKE_BUILD_TYPE:String=Asan .
|
||||
make
|
||||
|
||||
msg "test: full + MBEDTLS_CTR_DRBG_USE_128_BIT_KEY (ASan build)"
|
||||
make test
|
||||
}
|
||||
|
||||
component_test_ctr_drbg_aes_128_sha_256 () {
|
||||
msg "build: full + MBEDTLS_CTR_DRBG_USE_128_BIT_KEY + MBEDTLS_ENTROPY_FORCE_SHA256 (ASan build)"
|
||||
scripts/config.py full
|
||||
scripts/config.py unset MBEDTLS_MEMORY_BUFFER_ALLOC_C
|
||||
scripts/config.py set MBEDTLS_CTR_DRBG_USE_128_BIT_KEY
|
||||
scripts/config.py set MBEDTLS_ENTROPY_FORCE_SHA256
|
||||
CC=gcc cmake -D CMAKE_BUILD_TYPE:String=Asan .
|
||||
make
|
||||
|
||||
msg "test: full + MBEDTLS_CTR_DRBG_USE_128_BIT_KEY + MBEDTLS_ENTROPY_FORCE_SHA256 (ASan build)"
|
||||
make test
|
||||
}
|
||||
|
||||
component_test_se_default () {
|
||||
msg "build: default config + 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"
|
||||
make test
|
||||
}
|
||||
|
||||
component_test_se_full () {
|
||||
msg "build: full config + MBEDTLS_PSA_CRYPTO_SE_C"
|
||||
scripts/config.py full
|
||||
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"
|
||||
make test
|
||||
}
|
||||
|
||||
component_test_make_shared () {
|
||||
msg "build/test: make shared" # ~ 40s
|
||||
make SHARED=1 all check
|
||||
|
|
@ -1279,9 +1314,6 @@ component_test_m32_o1 () {
|
|||
|
||||
msg "test: i386, make, gcc -O1 (ASan build)"
|
||||
make test
|
||||
|
||||
msg "test ssl-opt.sh, i386, make, gcc-O1"
|
||||
if_build_succeeded tests/ssl-opt.sh
|
||||
}
|
||||
support_test_m32_o1 () {
|
||||
support_test_m32_o0 "$@"
|
||||
|
|
@ -1295,13 +1327,6 @@ component_test_m32_everest () {
|
|||
|
||||
msg "test: i386, Everest ECDH context - main suites (inc. selftests) (ASan build)" # ~ 50s
|
||||
make test
|
||||
|
||||
msg "test: i386, Everest ECDH context - ECDH-related part of ssl-opt.sh (ASan build)" # ~ 5s
|
||||
if_build_succeeded tests/ssl-opt.sh -f ECDH
|
||||
|
||||
msg "test: i386, Everest ECDH context - compat.sh with some ECDH ciphersuites (ASan build)" # ~ 3 min
|
||||
# Exclude some symmetric ciphers that are redundant here to gain time.
|
||||
if_build_succeeded tests/compat.sh -f ECDH -V NO -e 'ARCFOUR\|ARIA\|CAMELLIA\|CHACHA\|DES\|RC4'
|
||||
}
|
||||
support_test_m32_everest () {
|
||||
support_test_m32_o0 "$@"
|
||||
|
|
@ -1322,6 +1347,58 @@ support_test_mx32 () {
|
|||
esac
|
||||
}
|
||||
|
||||
component_test_min_mpi_window_size () {
|
||||
msg "build: Default + MBEDTLS_MPI_WINDOW_SIZE=1 (ASan build)" # ~ 10s
|
||||
scripts/config.py set MBEDTLS_MPI_WINDOW_SIZE 1
|
||||
CC=gcc cmake -D CMAKE_BUILD_TYPE:String=Asan .
|
||||
make
|
||||
|
||||
msg "test: MBEDTLS_MPI_WINDOW_SIZE=1 - main suites (inc. selftests) (ASan build)" # ~ 10s
|
||||
make test
|
||||
}
|
||||
|
||||
component_test_have_int32 () {
|
||||
msg "build: gcc, force 32-bit bignum limbs"
|
||||
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"
|
||||
make test
|
||||
}
|
||||
|
||||
component_test_have_int64 () {
|
||||
msg "build: gcc, force 64-bit bignum limbs"
|
||||
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"
|
||||
make test
|
||||
}
|
||||
|
||||
component_test_no_udbl_division () {
|
||||
msg "build: MBEDTLS_NO_UDBL_DIVISION native" # ~ 10s
|
||||
scripts/config.py full
|
||||
scripts/config.py set MBEDTLS_NO_UDBL_DIVISION
|
||||
make CFLAGS='-Werror -O1'
|
||||
|
||||
msg "test: MBEDTLS_NO_UDBL_DIVISION native" # ~ 10s
|
||||
make test
|
||||
}
|
||||
|
||||
component_test_no_64bit_multiplication () {
|
||||
msg "build: MBEDTLS_NO_64BIT_MULTIPLICATION native" # ~ 10s
|
||||
scripts/config.py full
|
||||
scripts/config.py set MBEDTLS_NO_64BIT_MULTIPLICATION
|
||||
make CFLAGS='-Werror -O1'
|
||||
|
||||
msg "test: MBEDTLS_NO_64BIT_MULTIPLICATION native" # ~ 10s
|
||||
make test
|
||||
}
|
||||
|
||||
component_build_arm_none_eabi_gcc () {
|
||||
msg "build: arm-none-eabi-gcc, make" # ~ 10s
|
||||
scripts/config.py baremetal
|
||||
|
|
@ -1437,8 +1514,10 @@ component_test_valgrind () {
|
|||
msg "test: main suites valgrind (Release)"
|
||||
make memcheck
|
||||
|
||||
# Optional parts (slow; currently broken on OS X because programs don't
|
||||
# seem to receive signals under valgrind on OS X).
|
||||
# Optional part(s)
|
||||
# Currently broken, programs don't seem to receive signals
|
||||
# under valgrind on OS X
|
||||
|
||||
if [ "$MEMORY" -gt 0 ]; then
|
||||
msg "test: ssl-opt.sh --memcheck (Release)"
|
||||
if_build_succeeded tests/ssl-opt.sh --memcheck
|
||||
|
|
@ -1556,7 +1635,16 @@ run_component () {
|
|||
cp -p "$CONFIG_H" "$CONFIG_BAK"
|
||||
current_component="$1"
|
||||
export MBEDTLS_TEST_CONFIGURATION="$current_component"
|
||||
|
||||
# Unconditionally create a seedfile that's sufficiently long.
|
||||
# Do this before each component, because a previous component may
|
||||
# have messed it up or shortened it.
|
||||
dd if=/dev/urandom of=./tests/seedfile bs=64 count=1
|
||||
|
||||
# Run the component code.
|
||||
"$@"
|
||||
|
||||
# Restore the build tree to a clean state.
|
||||
cleanup
|
||||
}
|
||||
|
||||
|
|
@ -1566,7 +1654,6 @@ pre_initialize_variables
|
|||
pre_parse_command_line "$@"
|
||||
|
||||
pre_check_git
|
||||
pre_check_seedfile
|
||||
|
||||
build_status=0
|
||||
if [ $KEEP_GOING -eq 1 ]; then
|
||||
|
|
|
|||
|
|
@ -42,9 +42,6 @@ for compiler in clang gcc; do
|
|||
run_in_docker -e CC=${compiler} make
|
||||
run_in_docker -e CC=${compiler} make test
|
||||
run_in_docker programs/test/selftest
|
||||
run_in_docker -e OSSL_NO_DTLS=1 tests/compat.sh
|
||||
run_in_docker tests/ssl-opt.sh -e '\(DTLS\|SCSV\).*openssl'
|
||||
run_in_docker tests/scripts/test-ref-configs.pl
|
||||
run_in_docker tests/scripts/curves.pl
|
||||
run_in_docker tests/scripts/key-exchanges.pl
|
||||
done
|
||||
|
|
|
|||
|
|
@ -56,12 +56,15 @@ diff macros identifiers | sed -n -e 's/< //p' > actual-macros
|
|||
for THING in actual-macros enum-consts; do
|
||||
printf "Names of $THING: "
|
||||
test -r $THING
|
||||
BAD=$( grep -v '^MBEDTLS_[0-9A-Z_]*[0-9A-Z]$' $THING || true )
|
||||
if [ "x$BAD" = "x" ]; then
|
||||
BAD=$( grep -E -v '^(MBEDTLS|PSA)_[0-9A-Z_]*[0-9A-Z]$' $THING || true )
|
||||
UNDERSCORES=$( grep -E '.*__.*' $THING || true )
|
||||
|
||||
if [ "x$BAD" = "x" ] && [ "x$UNDERSCORES" = "x" ]; then
|
||||
echo "PASS"
|
||||
else
|
||||
echo "FAIL"
|
||||
echo "$BAD"
|
||||
echo "$UNDERSCORES"
|
||||
FAIL=1
|
||||
fi
|
||||
done
|
||||
|
|
@ -69,7 +72,7 @@ done
|
|||
for THING in identifiers; do
|
||||
printf "Names of $THING: "
|
||||
test -r $THING
|
||||
BAD=$( grep -v '^mbedtls_[0-9a-z_]*[0-9a-z]$' $THING || true )
|
||||
BAD=$( grep -E -v '^(mbedtls|psa)_[0-9a-z_]*[0-9a-z]$' $THING || true )
|
||||
if [ "x$BAD" = "x" ]; then
|
||||
echo "PASS"
|
||||
else
|
||||
|
|
@ -81,11 +84,14 @@ done
|
|||
|
||||
printf "Likely typos: "
|
||||
sort -u actual-macros enum-consts > _caps
|
||||
HEADERS=$( ls include/mbedtls/*.h crypto/include/mbedtls/*.h | egrep -v 'compat-1\.3\.h' )
|
||||
HEADERS=$( ls include/mbedtls/*.h include/psa/*.h | egrep -v 'compat-1\.3\.h' )
|
||||
HEADERS="$HEADERS 3rdparty/everest/include/everest/everest.h 3rdparty/everest/include/everest/x25519.h"
|
||||
LIBRARY="$( ls library/*.c )"
|
||||
LIBRARY="$LIBRARY 3rdparty/everest/library/everest.c 3rdparty/everest/library/x25519.c"
|
||||
NL='
|
||||
'
|
||||
sed -n 's/MBED..._[A-Z0-9_]*/\'"$NL"'&\'"$NL"/gp \
|
||||
$HEADERS library/*.c \
|
||||
$HEADERS $LIBRARY \
|
||||
| grep MBEDTLS | sort -u > _MBEDTLS_XXX
|
||||
TYPOS=$( diff _caps _MBEDTLS_XXX | sed -n 's/^> //p' \
|
||||
| egrep -v 'XXX|__|_$|^MBEDTLS_.*CONFIG_FILE$' || true )
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
#
|
||||
# This file is part of Mbed TLS (https://tls.mbed.org)
|
||||
|
||||
import argparse
|
||||
import glob
|
||||
import os
|
||||
import re
|
||||
|
|
@ -27,9 +28,11 @@ import sys
|
|||
|
||||
class Results:
|
||||
"""Store file and line information about errors or warnings in test suites."""
|
||||
def __init__(self):
|
||||
|
||||
def __init__(self, options):
|
||||
self.errors = 0
|
||||
self.warnings = 0
|
||||
self.ignore_warnings = options.quiet
|
||||
|
||||
def error(self, file_name, line_number, fmt, *args):
|
||||
sys.stderr.write(('{}:{}:ERROR:' + fmt + '\n').
|
||||
|
|
@ -37,9 +40,10 @@ class Results:
|
|||
self.errors += 1
|
||||
|
||||
def warning(self, file_name, line_number, fmt, *args):
|
||||
sys.stderr.write(('{}:{}:Warning:' + fmt + '\n')
|
||||
.format(file_name, line_number, *args))
|
||||
self.warnings += 1
|
||||
if not self.ignore_warnings:
|
||||
sys.stderr.write(('{}:{}:Warning:' + fmt + '\n')
|
||||
.format(file_name, line_number, *args))
|
||||
self.warnings += 1
|
||||
|
||||
def collect_test_directories():
|
||||
"""Get the relative path for the TLS and Crypto test directories."""
|
||||
|
|
@ -108,8 +112,16 @@ def check_ssl_opt_sh(results, file_name):
|
|||
file_name, line_number, description)
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument('--quiet', '-q',
|
||||
action='store_true',
|
||||
help='Hide warnings')
|
||||
parser.add_argument('--verbose', '-v',
|
||||
action='store_false', dest='quiet',
|
||||
help='Show warnings (default: on; undoes --quiet)')
|
||||
options = parser.parse_args()
|
||||
test_directories = collect_test_directories()
|
||||
results = Results()
|
||||
results = Results(options)
|
||||
for directory in test_directories:
|
||||
for data_file_name in glob.glob(os.path.join(directory, 'suites',
|
||||
'*.data')):
|
||||
|
|
@ -117,7 +129,7 @@ def main():
|
|||
ssl_opt_sh = os.path.join(directory, 'ssl-opt.sh')
|
||||
if os.path.exists(ssl_opt_sh):
|
||||
check_ssl_opt_sh(results, ssl_opt_sh)
|
||||
if results.warnings or results.errors:
|
||||
if (results.warnings or results.errors) and not options.quiet:
|
||||
sys.stderr.write('{}: {} errors, {} warnings\n'
|
||||
.format(sys.argv[0], results.errors, results.warnings))
|
||||
sys.exit(1 if results.errors else 0)
|
||||
|
|
|
|||
|
|
@ -40,8 +40,18 @@ my @ssl = split( /\s+/, `sed -n -e '$ssl_sed_cmd' $config_h` );
|
|||
# for md we want to catch MD5_C but not MD_C, hence the extra dot
|
||||
my $mdx_sed_cmd = 's/^#define \(MBEDTLS_MD..*_C\)/\1/p';
|
||||
my $sha_sed_cmd = 's/^#define \(MBEDTLS_SHA.*_C\)/\1/p';
|
||||
my @hashes = split( /\s+/,
|
||||
my @hash_modules = split( /\s+/,
|
||||
`sed -n -e '$mdx_sed_cmd' -e '$sha_sed_cmd' $config_h` );
|
||||
|
||||
# there are also negative options for truncated variants, disabled by default
|
||||
my $sha_trunc_sed_cmd = 's/^\/\/#define \(MBEDTLS_SHA..._NO_.*\)/\1/p';
|
||||
my @hash_negatives = split( /\s+/,
|
||||
`sed -n -e '$sha_trunc_sed_cmd' $config_h` );
|
||||
|
||||
# list hash options with corresponding actions
|
||||
my @hashes = ((map { "unset $_" } @hash_modules),
|
||||
(map { "set $_" } @hash_negatives));
|
||||
|
||||
system( "cp $config_h $config_h.bak" ) and die;
|
||||
sub abort {
|
||||
system( "mv $config_h.bak $config_h" ) and warn "$config_h not restored\n";
|
||||
|
|
@ -55,12 +65,12 @@ for my $hash (@hashes) {
|
|||
system( "make clean" ) and die;
|
||||
|
||||
print "\n******************************************\n";
|
||||
print "* Testing without hash: $hash\n";
|
||||
print "* Testing hash option: $hash\n";
|
||||
print "******************************************\n";
|
||||
$ENV{MBEDTLS_TEST_CONFIGURATION} = "-$hash";
|
||||
|
||||
system( "scripts/config.py unset $hash" )
|
||||
and abort "Failed to disable $hash\n";
|
||||
system( "scripts/config.py $hash" )
|
||||
and abort "Failed to $hash\n";
|
||||
|
||||
for my $opt (@ssl) {
|
||||
system( "scripts/config.py unset $opt" )
|
||||
|
|
|
|||
|
|
@ -8,7 +8,10 @@ use open qw(:std utf8);
|
|||
|
||||
-d 'include/mbedtls' or die "$0: must be run from root\n";
|
||||
|
||||
@ARGV = grep { ! /compat-1\.3\.h/ } <include/mbedtls/*.h crypto/include/mbedtls/*.h>;
|
||||
@ARGV = grep { ! /compat-1\.3\.h/ } <include/mbedtls/*.h>;
|
||||
push @ARGV, "3rdparty/everest/include/everest/everest.h";
|
||||
push @ARGV, "3rdparty/everest/include/everest/x25519.h";
|
||||
|
||||
|
||||
my @consts;
|
||||
my $state = 'out';
|
||||
|
|
|
|||
|
|
@ -32,16 +32,17 @@ done
|
|||
|
||||
if [ $INTERNAL ]
|
||||
then
|
||||
HEADERS=$( ls include/mbedtls/*_internal.h crypto/include/mbedtls/*_internal.h | egrep -v 'compat-1\.3\.h|bn_mul' )
|
||||
HEADERS=$( ls include/mbedtls/*_internal.h library/*.h | egrep -v 'compat-1\.3\.h|bn_mul' )
|
||||
else
|
||||
HEADERS=$( ls include/mbedtls/*.h crypto/include/mbedtls/*.h | egrep -v 'compat-1\.3\.h|bn_mul' )
|
||||
HEADERS=$( ls include/mbedtls/*.h include/psa/*.h library/*.h | egrep -v 'compat-1\.3\.h|bn_mul' )
|
||||
HEADERS="$HEADERS 3rdparty/everest/include/everest/everest.h 3rdparty/everest/include/everest/x25519.h"
|
||||
fi
|
||||
|
||||
rm -f identifiers
|
||||
|
||||
grep '^[^ /#{]' $HEADERS | \
|
||||
sed -e 's/^[^:]*://' | \
|
||||
egrep -v '^(extern "C"|(typedef )?(struct|enum)( {)?$|};?$)' \
|
||||
egrep -v '^(extern "C"|(typedef )?(struct|union|enum)( {)?$|};?$)' \
|
||||
> _decls
|
||||
|
||||
if true; then
|
||||
|
|
|
|||
|
|
@ -7,7 +7,8 @@ if [ -d include/mbedtls ]; then :; else
|
|||
exit 1
|
||||
fi
|
||||
|
||||
HEADERS=$( ls include/mbedtls/*.h crypto/include/mbedtls/*.h | egrep -v 'compat-1\.3\.h' )
|
||||
HEADERS=$( ls include/mbedtls/*.h include/psa/*.h | egrep -v 'compat-1\.3\.h' )
|
||||
HEADERS="$HEADERS 3rdparty/everest/include/everest/everest.h 3rdparty/everest/include/everest/x25519.h"
|
||||
|
||||
sed -n -e 's/.*#define \([a-zA-Z0-9_]*\).*/\1/p' $HEADERS \
|
||||
| egrep -v '^(asm|inline|EMIT|_CRT_SECURE_NO_DEPRECATE)$|^MULADDC_' \
|
||||
|
|
|
|||
125
tests/scripts/psa_collect_statuses.py
Executable file
125
tests/scripts/psa_collect_statuses.py
Executable file
|
|
@ -0,0 +1,125 @@
|
|||
#!/usr/bin/env python3
|
||||
"""Describe the test coverage of PSA functions in terms of return statuses.
|
||||
|
||||
1. Build Mbed Crypto with -DRECORD_PSA_STATUS_COVERAGE_LOG
|
||||
2. Run psa_collect_statuses.py
|
||||
|
||||
The output is a series of line of the form "psa_foo PSA_ERROR_XXX". Each
|
||||
function/status combination appears only once.
|
||||
|
||||
This script must be run from the top of an Mbed Crypto source tree.
|
||||
The build command is "make -DRECORD_PSA_STATUS_COVERAGE_LOG", which is
|
||||
only supported with make (as opposed to CMake or other build methods).
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
DEFAULT_STATUS_LOG_FILE = 'tests/statuses.log'
|
||||
DEFAULT_PSA_CONSTANT_NAMES = 'programs/psa/psa_constant_names'
|
||||
|
||||
class Statuses:
|
||||
"""Information about observed return statues of API functions."""
|
||||
|
||||
def __init__(self):
|
||||
self.functions = {}
|
||||
self.codes = set()
|
||||
self.status_names = {}
|
||||
|
||||
def collect_log(self, log_file_name):
|
||||
"""Read logs from RECORD_PSA_STATUS_COVERAGE_LOG.
|
||||
|
||||
Read logs produced by running Mbed Crypto test suites built with
|
||||
-DRECORD_PSA_STATUS_COVERAGE_LOG.
|
||||
"""
|
||||
with open(log_file_name) as log:
|
||||
for line in log:
|
||||
value, function, tail = line.split(':', 2)
|
||||
if function not in self.functions:
|
||||
self.functions[function] = {}
|
||||
fdata = self.functions[function]
|
||||
if value not in self.functions[function]:
|
||||
fdata[value] = []
|
||||
fdata[value].append(tail)
|
||||
self.codes.add(int(value))
|
||||
|
||||
def get_constant_names(self, psa_constant_names):
|
||||
"""Run psa_constant_names to obtain names for observed numerical values."""
|
||||
values = [str(value) for value in self.codes]
|
||||
cmd = [psa_constant_names, 'status'] + values
|
||||
output = subprocess.check_output(cmd).decode('ascii')
|
||||
for value, name in zip(values, output.rstrip().split('\n')):
|
||||
self.status_names[value] = name
|
||||
|
||||
def report(self):
|
||||
"""Report observed return values for each function.
|
||||
|
||||
The report is a series of line of the form "psa_foo PSA_ERROR_XXX".
|
||||
"""
|
||||
for function in sorted(self.functions.keys()):
|
||||
fdata = self.functions[function]
|
||||
names = [self.status_names[value] for value in fdata.keys()]
|
||||
for name in sorted(names):
|
||||
sys.stdout.write('{} {}\n'.format(function, name))
|
||||
|
||||
def collect_status_logs(options):
|
||||
"""Build and run unit tests and report observed function return statuses.
|
||||
|
||||
Build Mbed Crypto with -DRECORD_PSA_STATUS_COVERAGE_LOG, run the
|
||||
test suites and display information about observed return statuses.
|
||||
"""
|
||||
rebuilt = False
|
||||
if not options.use_existing_log and os.path.exists(options.log_file):
|
||||
os.remove(options.log_file)
|
||||
if not os.path.exists(options.log_file):
|
||||
if options.clean_before:
|
||||
subprocess.check_call(['make', 'clean'],
|
||||
cwd='tests',
|
||||
stdout=sys.stderr)
|
||||
with open(os.devnull, 'w') as devnull:
|
||||
make_q_ret = subprocess.call(['make', '-q', 'lib', 'tests'],
|
||||
stdout=devnull, stderr=devnull)
|
||||
if make_q_ret != 0:
|
||||
subprocess.check_call(['make', 'RECORD_PSA_STATUS_COVERAGE_LOG=1'],
|
||||
stdout=sys.stderr)
|
||||
rebuilt = True
|
||||
subprocess.check_call(['make', 'test'],
|
||||
stdout=sys.stderr)
|
||||
data = Statuses()
|
||||
data.collect_log(options.log_file)
|
||||
data.get_constant_names(options.psa_constant_names)
|
||||
if rebuilt and options.clean_after:
|
||||
subprocess.check_call(['make', 'clean'],
|
||||
cwd='tests',
|
||||
stdout=sys.stderr)
|
||||
return data
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description=globals()['__doc__'])
|
||||
parser.add_argument('--clean-after',
|
||||
action='store_true',
|
||||
help='Run "make clean" after rebuilding')
|
||||
parser.add_argument('--clean-before',
|
||||
action='store_true',
|
||||
help='Run "make clean" before regenerating the log file)')
|
||||
parser.add_argument('--log-file', metavar='FILE',
|
||||
default=DEFAULT_STATUS_LOG_FILE,
|
||||
help='Log file location (default: {})'.format(
|
||||
DEFAULT_STATUS_LOG_FILE
|
||||
))
|
||||
parser.add_argument('--psa-constant-names', metavar='PROGRAM',
|
||||
default=DEFAULT_PSA_CONSTANT_NAMES,
|
||||
help='Path to psa_constant_names (default: {})'.format(
|
||||
DEFAULT_PSA_CONSTANT_NAMES
|
||||
))
|
||||
parser.add_argument('--use-existing-log', '-e',
|
||||
action='store_true',
|
||||
help='Don\'t regenerate the log file if it exists')
|
||||
options = parser.parse_args()
|
||||
data = collect_status_logs(options)
|
||||
data.report()
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
|
@ -58,8 +58,8 @@ my $skip_re =
|
|||
')(\z|\.)' );
|
||||
|
||||
# in case test suites are linked dynamically
|
||||
$ENV{'LD_LIBRARY_PATH'} = '../library:../crypto/library';
|
||||
$ENV{'DYLD_LIBRARY_PATH'} = '../library:../crypto/library';
|
||||
$ENV{'LD_LIBRARY_PATH'} = '../library';
|
||||
$ENV{'DYLD_LIBRARY_PATH'} = '../library';
|
||||
|
||||
my $prefix = $^O eq "MSWin32" ? '' : './';
|
||||
|
||||
|
|
|
|||
|
|
@ -17,12 +17,18 @@ use warnings;
|
|||
use strict;
|
||||
|
||||
my %configs = (
|
||||
'config-default.h' => {
|
||||
'opt' => '-f Default',
|
||||
'compat' => '-m tls1_2 -V NO',
|
||||
},
|
||||
'config-mini-tls1_1.h' => {
|
||||
'compat' => '-m tls1_1 -f \'^DES-CBC3-SHA$\|^TLS-RSA-WITH-3DES-EDE-CBC-SHA$\'', #'
|
||||
'compat' => '-m tls1_1 -f \'^DES-CBC3-SHA$\|^TLS-RSA-WITH-3DES-EDE-CBC-SHA$\'',
|
||||
},
|
||||
'config-suite-b.h' => {
|
||||
'compat' => "-m tls1_2 -f 'ECDHE-ECDSA.*AES.*GCM' -p mbedTLS",
|
||||
},
|
||||
'config-symmetric-only.h' => {
|
||||
},
|
||||
'config-ccm-psk-tls1_2.h' => {
|
||||
'compat' => '-m tls1_2 -f \'^TLS-PSK-WITH-AES-...-CCM-8\'',
|
||||
},
|
||||
|
|
@ -58,6 +64,15 @@ sub abort {
|
|||
exit 1;
|
||||
}
|
||||
|
||||
# Create a seedfile for configurations that enable MBEDTLS_ENTROPY_NV_SEED.
|
||||
# For test purposes, this doesn't have to be cryptographically random.
|
||||
if (!-e "tests/seedfile" || -s "tests/seedfile" < 64) {
|
||||
local *SEEDFILE;
|
||||
open SEEDFILE, ">tests/seedfile" or die;
|
||||
print SEEDFILE "*" x 64 or die;
|
||||
close SEEDFILE or die;
|
||||
}
|
||||
|
||||
while( my ($conf, $data) = each %configs ) {
|
||||
system( "cp $config_h.bak $config_h" ) and die;
|
||||
system( "make clean" ) and die;
|
||||
|
|
|
|||
459
tests/scripts/test_psa_constant_names.py
Executable file
459
tests/scripts/test_psa_constant_names.py
Executable file
|
|
@ -0,0 +1,459 @@
|
|||
#!/usr/bin/env python3
|
||||
"""Test the program psa_constant_names.
|
||||
Gather constant names from header files and test cases. Compile a C program
|
||||
to print out their numerical values, feed these numerical values to
|
||||
psa_constant_names, and check that the output is the original name.
|
||||
Return 0 if all test cases pass, 1 if the output was not always as expected,
|
||||
or 1 (with a Python backtrace) if there was an operational error.
|
||||
"""
|
||||
|
||||
import argparse
|
||||
from collections import namedtuple
|
||||
import itertools
|
||||
import os
|
||||
import platform
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
|
||||
class ReadFileLineException(Exception):
|
||||
def __init__(self, filename, line_number):
|
||||
message = 'in {} at {}'.format(filename, line_number)
|
||||
super(ReadFileLineException, self).__init__(message)
|
||||
self.filename = filename
|
||||
self.line_number = line_number
|
||||
|
||||
class read_file_lines:
|
||||
# Dear Pylint, conventionally, a context manager class name is lowercase.
|
||||
# pylint: disable=invalid-name,too-few-public-methods
|
||||
"""Context manager to read a text file line by line.
|
||||
|
||||
```
|
||||
with read_file_lines(filename) as lines:
|
||||
for line in lines:
|
||||
process(line)
|
||||
```
|
||||
is equivalent to
|
||||
```
|
||||
with open(filename, 'r') as input_file:
|
||||
for line in input_file:
|
||||
process(line)
|
||||
```
|
||||
except that if process(line) raises an exception, then the read_file_lines
|
||||
snippet annotates the exception with the file name and line number.
|
||||
"""
|
||||
def __init__(self, filename, binary=False):
|
||||
self.filename = filename
|
||||
self.line_number = 'entry'
|
||||
self.generator = None
|
||||
self.binary = binary
|
||||
def __enter__(self):
|
||||
self.generator = enumerate(open(self.filename,
|
||||
'rb' if self.binary else 'r'))
|
||||
return self
|
||||
def __iter__(self):
|
||||
for line_number, content in self.generator:
|
||||
self.line_number = line_number
|
||||
yield content
|
||||
self.line_number = 'exit'
|
||||
def __exit__(self, exc_type, exc_value, exc_traceback):
|
||||
if exc_type is not None:
|
||||
raise ReadFileLineException(self.filename, self.line_number) \
|
||||
from exc_value
|
||||
|
||||
class Inputs:
|
||||
# pylint: disable=too-many-instance-attributes
|
||||
"""Accumulate information about macros to test.
|
||||
|
||||
This includes macro names as well as information about their arguments
|
||||
when applicable.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.all_declared = set()
|
||||
# Sets of names per type
|
||||
self.statuses = set(['PSA_SUCCESS'])
|
||||
self.algorithms = set(['0xffffffff'])
|
||||
self.ecc_curves = set(['0xff'])
|
||||
self.dh_groups = set(['0xff'])
|
||||
self.key_types = set(['0xffff'])
|
||||
self.key_usage_flags = set(['0x80000000'])
|
||||
# Hard-coded value for unknown algorithms
|
||||
self.hash_algorithms = set(['0x010000fe'])
|
||||
self.mac_algorithms = set(['0x02ff00ff'])
|
||||
self.ka_algorithms = set(['0x30fc0000'])
|
||||
self.kdf_algorithms = set(['0x200000ff'])
|
||||
# For AEAD algorithms, the only variability is over the tag length,
|
||||
# and this only applies to known algorithms, so don't test an
|
||||
# unknown algorithm.
|
||||
self.aead_algorithms = set()
|
||||
# Identifier prefixes
|
||||
self.table_by_prefix = {
|
||||
'ERROR': self.statuses,
|
||||
'ALG': self.algorithms,
|
||||
'ECC_CURVE': self.ecc_curves,
|
||||
'DH_GROUP': self.dh_groups,
|
||||
'KEY_TYPE': self.key_types,
|
||||
'KEY_USAGE': self.key_usage_flags,
|
||||
}
|
||||
# Test functions
|
||||
self.table_by_test_function = {
|
||||
# Any function ending in _algorithm also gets added to
|
||||
# self.algorithms.
|
||||
'key_type': [self.key_types],
|
||||
'block_cipher_key_type': [self.key_types],
|
||||
'stream_cipher_key_type': [self.key_types],
|
||||
'ecc_key_family': [self.ecc_curves],
|
||||
'ecc_key_types': [self.ecc_curves],
|
||||
'dh_key_family': [self.dh_groups],
|
||||
'dh_key_types': [self.dh_groups],
|
||||
'hash_algorithm': [self.hash_algorithms],
|
||||
'mac_algorithm': [self.mac_algorithms],
|
||||
'cipher_algorithm': [],
|
||||
'hmac_algorithm': [self.mac_algorithms],
|
||||
'aead_algorithm': [self.aead_algorithms],
|
||||
'key_derivation_algorithm': [self.kdf_algorithms],
|
||||
'key_agreement_algorithm': [self.ka_algorithms],
|
||||
'asymmetric_signature_algorithm': [],
|
||||
'asymmetric_signature_wildcard': [self.algorithms],
|
||||
'asymmetric_encryption_algorithm': [],
|
||||
'other_algorithm': [],
|
||||
}
|
||||
# macro name -> list of argument names
|
||||
self.argspecs = {}
|
||||
# argument name -> list of values
|
||||
self.arguments_for = {
|
||||
'mac_length': ['1', '63'],
|
||||
'tag_length': ['1', '63'],
|
||||
}
|
||||
|
||||
def get_names(self, type_word):
|
||||
"""Return the set of known names of values of the given type."""
|
||||
return {
|
||||
'status': self.statuses,
|
||||
'algorithm': self.algorithms,
|
||||
'ecc_curve': self.ecc_curves,
|
||||
'dh_group': self.dh_groups,
|
||||
'key_type': self.key_types,
|
||||
'key_usage': self.key_usage_flags,
|
||||
}[type_word]
|
||||
|
||||
def gather_arguments(self):
|
||||
"""Populate the list of values for macro arguments.
|
||||
|
||||
Call this after parsing all the inputs.
|
||||
"""
|
||||
self.arguments_for['hash_alg'] = sorted(self.hash_algorithms)
|
||||
self.arguments_for['mac_alg'] = sorted(self.mac_algorithms)
|
||||
self.arguments_for['ka_alg'] = sorted(self.ka_algorithms)
|
||||
self.arguments_for['kdf_alg'] = sorted(self.kdf_algorithms)
|
||||
self.arguments_for['aead_alg'] = sorted(self.aead_algorithms)
|
||||
self.arguments_for['curve'] = sorted(self.ecc_curves)
|
||||
self.arguments_for['group'] = sorted(self.dh_groups)
|
||||
|
||||
@staticmethod
|
||||
def _format_arguments(name, arguments):
|
||||
"""Format a macro call with arguments.."""
|
||||
return name + '(' + ', '.join(arguments) + ')'
|
||||
|
||||
def distribute_arguments(self, name):
|
||||
"""Generate macro calls with each tested argument set.
|
||||
|
||||
If name is a macro without arguments, just yield "name".
|
||||
If name is a macro with arguments, yield a series of
|
||||
"name(arg1,...,argN)" where each argument takes each possible
|
||||
value at least once.
|
||||
"""
|
||||
try:
|
||||
if name not in self.argspecs:
|
||||
yield name
|
||||
return
|
||||
argspec = self.argspecs[name]
|
||||
if argspec == []:
|
||||
yield name + '()'
|
||||
return
|
||||
argument_lists = [self.arguments_for[arg] for arg in argspec]
|
||||
arguments = [values[0] for values in argument_lists]
|
||||
yield self._format_arguments(name, arguments)
|
||||
# Dear Pylint, enumerate won't work here since we're modifying
|
||||
# the array.
|
||||
# pylint: disable=consider-using-enumerate
|
||||
for i in range(len(arguments)):
|
||||
for value in argument_lists[i][1:]:
|
||||
arguments[i] = value
|
||||
yield self._format_arguments(name, arguments)
|
||||
arguments[i] = argument_lists[0][0]
|
||||
except BaseException as e:
|
||||
raise Exception('distribute_arguments({})'.format(name)) from e
|
||||
|
||||
def generate_expressions(self, names):
|
||||
return itertools.chain(*map(self.distribute_arguments, names))
|
||||
|
||||
_argument_split_re = re.compile(r' *, *')
|
||||
@classmethod
|
||||
def _argument_split(cls, arguments):
|
||||
return re.split(cls._argument_split_re, arguments)
|
||||
|
||||
# Regex for interesting header lines.
|
||||
# Groups: 1=macro name, 2=type, 3=argument list (optional).
|
||||
_header_line_re = \
|
||||
re.compile(r'#define +' +
|
||||
r'(PSA_((?:(?:DH|ECC|KEY)_)?[A-Z]+)_\w+)' +
|
||||
r'(?:\(([^\n()]*)\))?')
|
||||
# Regex of macro names to exclude.
|
||||
_excluded_name_re = re.compile(r'_(?:GET|IS|OF)_|_(?:BASE|FLAG|MASK)\Z')
|
||||
# Additional excluded macros.
|
||||
_excluded_names = set([
|
||||
# Macros that provide an alternative way to build the same
|
||||
# algorithm as another macro.
|
||||
'PSA_ALG_AEAD_WITH_DEFAULT_TAG_LENGTH',
|
||||
'PSA_ALG_FULL_LENGTH_MAC',
|
||||
# Auxiliary macro whose name doesn't fit the usual patterns for
|
||||
# auxiliary macros.
|
||||
'PSA_ALG_AEAD_WITH_DEFAULT_TAG_LENGTH_CASE',
|
||||
])
|
||||
def parse_header_line(self, line):
|
||||
"""Parse a C header line, looking for "#define PSA_xxx"."""
|
||||
m = re.match(self._header_line_re, line)
|
||||
if not m:
|
||||
return
|
||||
name = m.group(1)
|
||||
self.all_declared.add(name)
|
||||
if re.search(self._excluded_name_re, name) or \
|
||||
name in self._excluded_names:
|
||||
return
|
||||
dest = self.table_by_prefix.get(m.group(2))
|
||||
if dest is None:
|
||||
return
|
||||
dest.add(name)
|
||||
if m.group(3):
|
||||
self.argspecs[name] = self._argument_split(m.group(3))
|
||||
|
||||
_nonascii_re = re.compile(rb'[^\x00-\x7f]+')
|
||||
def parse_header(self, filename):
|
||||
"""Parse a C header file, looking for "#define PSA_xxx"."""
|
||||
with read_file_lines(filename, binary=True) as lines:
|
||||
for line in lines:
|
||||
line = re.sub(self._nonascii_re, rb'', line).decode('ascii')
|
||||
self.parse_header_line(line)
|
||||
|
||||
_macro_identifier_re = re.compile(r'[A-Z]\w+')
|
||||
def generate_undeclared_names(self, expr):
|
||||
for name in re.findall(self._macro_identifier_re, expr):
|
||||
if name not in self.all_declared:
|
||||
yield name
|
||||
|
||||
def accept_test_case_line(self, function, argument):
|
||||
#pylint: disable=unused-argument
|
||||
undeclared = list(self.generate_undeclared_names(argument))
|
||||
if undeclared:
|
||||
raise Exception('Undeclared names in test case', undeclared)
|
||||
return True
|
||||
|
||||
def add_test_case_line(self, function, argument):
|
||||
"""Parse a test case data line, looking for algorithm metadata tests."""
|
||||
sets = []
|
||||
if function.endswith('_algorithm'):
|
||||
sets.append(self.algorithms)
|
||||
if function == 'key_agreement_algorithm' and \
|
||||
argument.startswith('PSA_ALG_KEY_AGREEMENT('):
|
||||
# We only want *raw* key agreement algorithms as such, so
|
||||
# exclude ones that are already chained with a KDF.
|
||||
# Keep the expression as one to test as an algorithm.
|
||||
function = 'other_algorithm'
|
||||
sets += self.table_by_test_function[function]
|
||||
if self.accept_test_case_line(function, argument):
|
||||
for s in sets:
|
||||
s.add(argument)
|
||||
|
||||
# Regex matching a *.data line containing a test function call and
|
||||
# its arguments. The actual definition is partly positional, but this
|
||||
# regex is good enough in practice.
|
||||
_test_case_line_re = re.compile(r'(?!depends_on:)(\w+):([^\n :][^:\n]*)')
|
||||
def parse_test_cases(self, filename):
|
||||
"""Parse a test case file (*.data), looking for algorithm metadata tests."""
|
||||
with read_file_lines(filename) as lines:
|
||||
for line in lines:
|
||||
m = re.match(self._test_case_line_re, line)
|
||||
if m:
|
||||
self.add_test_case_line(m.group(1), m.group(2))
|
||||
|
||||
def gather_inputs(headers, test_suites, inputs_class=Inputs):
|
||||
"""Read the list of inputs to test psa_constant_names with."""
|
||||
inputs = inputs_class()
|
||||
for header in headers:
|
||||
inputs.parse_header(header)
|
||||
for test_cases in test_suites:
|
||||
inputs.parse_test_cases(test_cases)
|
||||
inputs.gather_arguments()
|
||||
return inputs
|
||||
|
||||
def remove_file_if_exists(filename):
|
||||
"""Remove the specified file, ignoring errors."""
|
||||
if not filename:
|
||||
return
|
||||
try:
|
||||
os.remove(filename)
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
def run_c(type_word, expressions, include_path=None, keep_c=False):
|
||||
"""Generate and run a program to print out numerical values for expressions."""
|
||||
if include_path is None:
|
||||
include_path = []
|
||||
if type_word == 'status':
|
||||
cast_to = 'long'
|
||||
printf_format = '%ld'
|
||||
else:
|
||||
cast_to = 'unsigned long'
|
||||
printf_format = '0x%08lx'
|
||||
c_name = None
|
||||
exe_name = None
|
||||
try:
|
||||
c_fd, c_name = tempfile.mkstemp(prefix='tmp-{}-'.format(type_word),
|
||||
suffix='.c',
|
||||
dir='programs/psa')
|
||||
exe_suffix = '.exe' if platform.system() == 'Windows' else ''
|
||||
exe_name = c_name[:-2] + exe_suffix
|
||||
remove_file_if_exists(exe_name)
|
||||
c_file = os.fdopen(c_fd, 'w', encoding='ascii')
|
||||
c_file.write('/* Generated by test_psa_constant_names.py for {} values */'
|
||||
.format(type_word))
|
||||
c_file.write('''
|
||||
#include <stdio.h>
|
||||
#include <psa/crypto.h>
|
||||
int main(void)
|
||||
{
|
||||
''')
|
||||
for expr in expressions:
|
||||
c_file.write(' printf("{}\\n", ({}) {});\n'
|
||||
.format(printf_format, cast_to, expr))
|
||||
c_file.write(''' return 0;
|
||||
}
|
||||
''')
|
||||
c_file.close()
|
||||
cc = os.getenv('CC', 'cc')
|
||||
subprocess.check_call([cc] +
|
||||
['-I' + dir for dir in include_path] +
|
||||
['-o', exe_name, c_name])
|
||||
if keep_c:
|
||||
sys.stderr.write('List of {} tests kept at {}\n'
|
||||
.format(type_word, c_name))
|
||||
else:
|
||||
os.remove(c_name)
|
||||
output = subprocess.check_output([exe_name])
|
||||
return output.decode('ascii').strip().split('\n')
|
||||
finally:
|
||||
remove_file_if_exists(exe_name)
|
||||
|
||||
NORMALIZE_STRIP_RE = re.compile(r'\s+')
|
||||
def normalize(expr):
|
||||
"""Normalize the C expression so as not to care about trivial differences.
|
||||
|
||||
Currently "trivial differences" means whitespace.
|
||||
"""
|
||||
return re.sub(NORMALIZE_STRIP_RE, '', expr)
|
||||
|
||||
def collect_values(inputs, type_word, include_path=None, keep_c=False):
|
||||
"""Generate expressions using known macro names and calculate their values.
|
||||
|
||||
Return a list of pairs of (expr, value) where expr is an expression and
|
||||
value is a string representation of its integer value.
|
||||
"""
|
||||
names = inputs.get_names(type_word)
|
||||
expressions = sorted(inputs.generate_expressions(names))
|
||||
values = run_c(type_word, expressions,
|
||||
include_path=include_path, keep_c=keep_c)
|
||||
return expressions, values
|
||||
|
||||
class Tests:
|
||||
"""An object representing tests and their results."""
|
||||
|
||||
Error = namedtuple('Error',
|
||||
['type', 'expression', 'value', 'output'])
|
||||
|
||||
def __init__(self, options):
|
||||
self.options = options
|
||||
self.count = 0
|
||||
self.errors = []
|
||||
|
||||
def run_one(self, inputs, type_word):
|
||||
"""Test psa_constant_names for the specified type.
|
||||
|
||||
Run the program on the names for this type.
|
||||
Use the inputs to figure out what arguments to pass to macros that
|
||||
take arguments.
|
||||
"""
|
||||
expressions, values = collect_values(inputs, type_word,
|
||||
include_path=self.options.include,
|
||||
keep_c=self.options.keep_c)
|
||||
output = subprocess.check_output([self.options.program, type_word] +
|
||||
values)
|
||||
outputs = output.decode('ascii').strip().split('\n')
|
||||
self.count += len(expressions)
|
||||
for expr, value, output in zip(expressions, values, outputs):
|
||||
if self.options.show:
|
||||
sys.stdout.write('{} {}\t{}\n'.format(type_word, value, output))
|
||||
if normalize(expr) != normalize(output):
|
||||
self.errors.append(self.Error(type=type_word,
|
||||
expression=expr,
|
||||
value=value,
|
||||
output=output))
|
||||
|
||||
def run_all(self, inputs):
|
||||
"""Run psa_constant_names on all the gathered inputs."""
|
||||
for type_word in ['status', 'algorithm', 'ecc_curve', 'dh_group',
|
||||
'key_type', 'key_usage']:
|
||||
self.run_one(inputs, type_word)
|
||||
|
||||
def report(self, out):
|
||||
"""Describe each case where the output is not as expected.
|
||||
|
||||
Write the errors to ``out``.
|
||||
Also write a total.
|
||||
"""
|
||||
for error in self.errors:
|
||||
out.write('For {} "{}", got "{}" (value: {})\n'
|
||||
.format(error.type, error.expression,
|
||||
error.output, error.value))
|
||||
out.write('{} test cases'.format(self.count))
|
||||
if self.errors:
|
||||
out.write(', {} FAIL\n'.format(len(self.errors)))
|
||||
else:
|
||||
out.write(' PASS\n')
|
||||
|
||||
HEADERS = ['psa/crypto.h', 'psa/crypto_extra.h', 'psa/crypto_values.h']
|
||||
TEST_SUITES = ['tests/suites/test_suite_psa_crypto_metadata.data']
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description=globals()['__doc__'])
|
||||
parser.add_argument('--include', '-I',
|
||||
action='append', default=['include'],
|
||||
help='Directory for header files')
|
||||
parser.add_argument('--keep-c',
|
||||
action='store_true', dest='keep_c', default=False,
|
||||
help='Keep the intermediate C file')
|
||||
parser.add_argument('--no-keep-c',
|
||||
action='store_false', dest='keep_c',
|
||||
help='Don\'t keep the intermediate C file (default)')
|
||||
parser.add_argument('--program',
|
||||
default='programs/psa/psa_constant_names',
|
||||
help='Program to test')
|
||||
parser.add_argument('--show',
|
||||
action='store_true',
|
||||
help='Keep the intermediate C file')
|
||||
parser.add_argument('--no-show',
|
||||
action='store_false', dest='show',
|
||||
help='Don\'t show tested values (default)')
|
||||
options = parser.parse_args()
|
||||
headers = [os.path.join(options.include[0], h) for h in HEADERS]
|
||||
inputs = gather_inputs(headers, TEST_SUITES)
|
||||
tests = Tests(options)
|
||||
tests.run_all(inputs)
|
||||
tests.report(sys.stdout)
|
||||
if tests.errors:
|
||||
exit(1)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
Loading…
Add table
Add a link
Reference in a new issue