mirror of
https://github.com/Mbed-TLS/mbedtls.git
synced 2025-07-28 00:21:48 +03:00
Merge branch 'Mbed-TLS:development' into codegen_1.1
This commit is contained in:
@ -259,7 +259,7 @@ General options:
|
||||
--no-force Refuse to overwrite modified files (default).
|
||||
--no-keep-going Stop at the first error (default).
|
||||
--no-memory No additional memory tests (default).
|
||||
--no-quiet Print full ouput from components.
|
||||
--no-quiet Print full output from components.
|
||||
--out-of-source-dir=<path> Directory used for CMake out-of-source build tests.
|
||||
--outcome-file=<path> File where test outcomes are written (not done if
|
||||
empty; default: \$MBEDTLS_TEST_OUTCOME_FILE).
|
||||
@ -866,6 +866,12 @@ component_check_test_cases () {
|
||||
fi
|
||||
tests/scripts/check_test_cases.py $opt
|
||||
unset opt
|
||||
|
||||
# Check that no tests are explicitely disabled when USE_PSA_CRYPTO is set
|
||||
# as a matter of policy to ensure there is no missed testing
|
||||
msg "Check: explicitely disabled test with USE_PSA_CRYPTO" # < 1s
|
||||
not grep -n 'depends_on:.*!MBEDTLS_USE_PSA_CRYPTO' tests/suites/*.function tests/suites/*.data
|
||||
not grep -n '^ *requires_config_disabled.*MBEDTLS_USE_PSA_CRYPTO' tests/ssl-opt.sh tests/opt-testcases/*.sh
|
||||
}
|
||||
|
||||
component_check_doxygen_warnings () {
|
||||
@ -1059,6 +1065,7 @@ component_test_no_ctr_drbg_classic () {
|
||||
scripts/config.py full
|
||||
scripts/config.py unset MBEDTLS_CTR_DRBG_C
|
||||
scripts/config.py unset MBEDTLS_USE_PSA_CRYPTO
|
||||
scripts/config.py unset MBEDTLS_SSL_PROTO_TLS1_3
|
||||
|
||||
CC=gcc cmake -D CMAKE_BUILD_TYPE:String=Asan .
|
||||
make
|
||||
@ -1104,6 +1111,7 @@ component_test_no_hmac_drbg_classic () {
|
||||
scripts/config.py unset MBEDTLS_HMAC_DRBG_C
|
||||
scripts/config.py unset MBEDTLS_ECDSA_DETERMINISTIC # requires HMAC_DRBG
|
||||
scripts/config.py unset MBEDTLS_USE_PSA_CRYPTO
|
||||
scripts/config.py unset MBEDTLS_SSL_PROTO_TLS1_3
|
||||
|
||||
CC=gcc cmake -D CMAKE_BUILD_TYPE:String=Asan .
|
||||
make
|
||||
@ -1156,6 +1164,7 @@ component_test_psa_external_rng_no_drbg_classic () {
|
||||
msg "build: PSA_CRYPTO_EXTERNAL_RNG minus *_DRBG, classic crypto in TLS"
|
||||
scripts/config.py full
|
||||
scripts/config.py unset MBEDTLS_USE_PSA_CRYPTO
|
||||
scripts/config.py unset MBEDTLS_SSL_PROTO_TLS1_3
|
||||
scripts/config.py set MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG
|
||||
scripts/config.py unset MBEDTLS_ENTROPY_C
|
||||
scripts/config.py unset MBEDTLS_ENTROPY_NV_SEED
|
||||
@ -1194,6 +1203,72 @@ component_test_psa_external_rng_no_drbg_use_psa () {
|
||||
tests/ssl-opt.sh -f 'Default\|opaque'
|
||||
}
|
||||
|
||||
component_test_crypto_full_no_md () {
|
||||
msg "build: crypto_full minus MD"
|
||||
scripts/config.py crypto_full
|
||||
scripts/config.py unset MBEDTLS_MD_C
|
||||
# Direct dependencies
|
||||
scripts/config.py unset MBEDTLS_HKDF_C
|
||||
scripts/config.py unset MBEDTLS_HMAC_DRBG_C
|
||||
# Indirect dependencies
|
||||
scripts/config.py unset MBEDTLS_ECDSA_DETERMINISTIC
|
||||
make
|
||||
|
||||
msg "test: crypto_full minus MD"
|
||||
make test
|
||||
}
|
||||
|
||||
component_test_full_no_cipher () {
|
||||
msg "build: full minus CIPHER"
|
||||
scripts/config.py full
|
||||
scripts/config.py unset MBEDTLS_CIPHER_C
|
||||
# Direct dependencies
|
||||
scripts/config.py unset MBEDTLS_CCM_C
|
||||
scripts/config.py unset MBEDTLS_CMAC_C
|
||||
scripts/config.py unset MBEDTLS_GCM_C
|
||||
scripts/config.py unset MBEDTLS_NIST_KW_C
|
||||
scripts/config.py unset MBEDTLS_PKCS12_C
|
||||
scripts/config.py unset MBEDTLS_PKCS5_C
|
||||
scripts/config.py unset MBEDTLS_PSA_CRYPTO_C
|
||||
scripts/config.py unset MBEDTLS_SSL_TLS_C
|
||||
scripts/config.py unset MBEDTLS_SSL_TICKET_C
|
||||
# Indirect dependencies
|
||||
scripts/config.py unset MBEDTLS_SSL_CLI_C
|
||||
scripts/config.py unset MBEDTLS_PSA_CRYPTO_SE_C
|
||||
scripts/config.py unset MBEDTLS_PSA_CRYPTO_STORAGE_C
|
||||
scripts/config.py unset MBEDTLS_SSL_DTLS_ANTI_REPLAY
|
||||
scripts/config.py unset MBEDTLS_SSL_DTLS_CONNECTION_ID
|
||||
scripts/config.py unset MBEDTLS_SSL_PROTO_TLS1_3
|
||||
scripts/config.py unset MBEDTLS_SSL_SRV_C
|
||||
scripts/config.py unset MBEDTLS_USE_PSA_CRYPTO
|
||||
make
|
||||
|
||||
msg "test: full minus CIPHER"
|
||||
make test
|
||||
}
|
||||
|
||||
component_test_crypto_full_no_cipher () {
|
||||
msg "build: crypto_full minus CIPHER"
|
||||
scripts/config.py crypto_full
|
||||
scripts/config.py unset MBEDTLS_CIPHER_C
|
||||
# Direct dependencies
|
||||
scripts/config.py unset MBEDTLS_CCM_C
|
||||
scripts/config.py unset MBEDTLS_CMAC_C
|
||||
scripts/config.py unset MBEDTLS_GCM_C
|
||||
scripts/config.py unset MBEDTLS_NIST_KW_C
|
||||
scripts/config.py unset MBEDTLS_PKCS12_C
|
||||
scripts/config.py unset MBEDTLS_PKCS5_C
|
||||
scripts/config.py unset MBEDTLS_PSA_CRYPTO_C
|
||||
# Indirect dependencies
|
||||
scripts/config.py unset MBEDTLS_PSA_CRYPTO_SE_C
|
||||
scripts/config.py unset MBEDTLS_PSA_CRYPTO_STORAGE_C
|
||||
scripts/config.py unset MBEDTLS_USE_PSA_CRYPTO
|
||||
make
|
||||
|
||||
msg "test: crypto_full minus CIPHER"
|
||||
make test
|
||||
}
|
||||
|
||||
component_test_psa_external_rng_use_psa_crypto () {
|
||||
msg "build: full + PSA_CRYPTO_EXTERNAL_RNG + USE_PSA_CRYPTO minus CTR_DRBG"
|
||||
scripts/config.py full
|
||||
@ -1223,7 +1298,7 @@ component_test_everest () {
|
||||
|
||||
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.
|
||||
tests/compat.sh -f ECDH -V NO -e 'ARIA\|CAMELLIA\|CHACHA\|DES'
|
||||
tests/compat.sh -f ECDH -V NO -e 'ARIA\|CAMELLIA\|CHACHA'
|
||||
}
|
||||
|
||||
component_test_everest_curve25519_only () {
|
||||
@ -1311,14 +1386,33 @@ component_test_full_cmake_clang () {
|
||||
msg "test: ssl-opt.sh default, ECJPAKE, SSL async (full config)" # ~ 1s
|
||||
tests/ssl-opt.sh -f 'Default\|ECJPAKE\|SSL async private'
|
||||
|
||||
msg "test: compat.sh DES, 3DES & NULL (full config)" # ~ 2 min
|
||||
env OPENSSL_CMD="$OPENSSL_LEGACY" GNUTLS_CLI="$GNUTLS_LEGACY_CLI" GNUTLS_SERV="$GNUTLS_LEGACY_SERV" tests/compat.sh -e '^$' -f 'NULL\|DES'
|
||||
msg "test: compat.sh NULL (full config)" # ~ 2 min
|
||||
env OPENSSL_CMD="$OPENSSL_LEGACY" GNUTLS_CLI="$GNUTLS_LEGACY_CLI" GNUTLS_SERV="$GNUTLS_LEGACY_SERV" tests/compat.sh -e '^$' -f 'NULL'
|
||||
|
||||
msg "test: compat.sh ARIA + ChachaPoly"
|
||||
env OPENSSL_CMD="$OPENSSL_NEXT" tests/compat.sh -e '^$' -f 'ARIA\|CHACHA'
|
||||
}
|
||||
|
||||
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:
|
||||
# - unset MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN - does the failure persist?
|
||||
# - or alternatively, change the build type to MemSanDbg, which enables
|
||||
# origin tracking and nicer stack traces (which are useful for debugging
|
||||
# anyway), and check if the origin was TEST_CF_SECRET() or something else.
|
||||
msg "build: cmake MSan (clang), full config minus MBEDTLS_USE_PSA_CRYPTO with constant flow testing"
|
||||
scripts/config.py full
|
||||
scripts/config.py set MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN
|
||||
scripts/config.py unset MBEDTLS_USE_PSA_CRYPTO
|
||||
scripts/config.py unset MBEDTLS_AESNI_C # memsan doesn't grok asm
|
||||
CC=clang cmake -D CMAKE_BUILD_TYPE:String=MemSan .
|
||||
make
|
||||
|
||||
msg "test: main suites (full minus MBEDTLS_USE_PSA_CRYPTO, Msan + constant flow)"
|
||||
make test
|
||||
}
|
||||
|
||||
component_test_memsan_constant_flow_psa () {
|
||||
# This tests both (1) accesses to undefined memory, and (2) branches or
|
||||
# memory access depending on secret values. To distinguish between those:
|
||||
# - unset MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN - does the failure persist?
|
||||
@ -1337,6 +1431,29 @@ component_test_memsan_constant_flow () {
|
||||
}
|
||||
|
||||
component_test_valgrind_constant_flow () {
|
||||
# This tests both (1) everything that valgrind's memcheck usually checks
|
||||
# (heap buffer overflows, use of uninitialized memory, use-after-free,
|
||||
# etc.) and (2) branches or memory access depending on secret values,
|
||||
# which will be reported as uninitialized memory. To distinguish between
|
||||
# secret and actually uninitialized:
|
||||
# - unset MBEDTLS_TEST_CONSTANT_FLOW_VALGRIND - does the failure persist?
|
||||
# - or alternatively, build with debug info and manually run the offending
|
||||
# test suite with valgrind --track-origins=yes, then check if the origin
|
||||
# was TEST_CF_SECRET() or something else.
|
||||
msg "build: cmake release GCC, full config minus MBEDTLS_USE_PSA_CRYPTO with constant flow testing"
|
||||
scripts/config.py full
|
||||
scripts/config.py set MBEDTLS_TEST_CONSTANT_FLOW_VALGRIND
|
||||
scripts/config.py unset MBEDTLS_USE_PSA_CRYPTO
|
||||
cmake -D CMAKE_BUILD_TYPE:String=Release .
|
||||
make
|
||||
|
||||
# this only shows a summary of the results (how many of each type)
|
||||
# details are left in Testing/<date>/DynamicAnalysis.xml
|
||||
msg "test: main suites (full minus MBEDTLS_USE_PSA_CRYPTO, valgrind + constant flow)"
|
||||
make memcheck
|
||||
}
|
||||
|
||||
component_test_valgrind_constant_flow_psa () {
|
||||
# This tests both (1) everything that valgrind's memcheck usually checks
|
||||
# (heap buffer overflows, use of uninitialized memory, use-after-free,
|
||||
# etc.) and (2) branches or memory access depending on secret values,
|
||||
@ -1435,9 +1552,24 @@ component_build_crypto_full () {
|
||||
component_build_crypto_baremetal () {
|
||||
msg "build: make, crypto only, baremetal config"
|
||||
scripts/config.py crypto_baremetal
|
||||
make CFLAGS='-O1 -Werror'
|
||||
make CFLAGS="-O1 -Werror -I$PWD/tests/include/baremetal-override/"
|
||||
are_empty_libraries library/libmbedx509.* library/libmbedtls.*
|
||||
}
|
||||
support_build_crypto_baremetal () {
|
||||
support_build_baremetal "$@"
|
||||
}
|
||||
|
||||
component_build_baremetal () {
|
||||
msg "build: make, baremetal config"
|
||||
scripts/config.py baremetal
|
||||
make CFLAGS="-O1 -Werror -I$PWD/tests/include/baremetal-override/"
|
||||
}
|
||||
support_build_baremetal () {
|
||||
# Older Glibc versions include time.h from other headers such as stdlib.h,
|
||||
# which makes the no-time.h-in-baremetal check fail. Ubuntu 16.04 has this
|
||||
# problem, Ubuntu 18.04 is ok.
|
||||
! grep -q -F time.h /usr/include/x86_64-linux-gnu/sys/types.h
|
||||
}
|
||||
|
||||
component_test_depends_curves () {
|
||||
msg "test/build: curves.pl (gcc)" # ~ 4 min
|
||||
@ -1498,6 +1630,12 @@ component_build_module_alt () {
|
||||
# The SpecifiedECDomain parsing code accesses mbedtls_ecp_group fields
|
||||
# directly and assumes the implementation works with partial groups.
|
||||
scripts/config.py unset MBEDTLS_PK_PARSE_EC_EXTENDED
|
||||
# MBEDTLS_SHA256_*ALT can't be used with MBEDTLS_SHA256_USE_A64_CRYPTO_*
|
||||
scripts/config.py unset MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT
|
||||
scripts/config.py unset MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY
|
||||
# MBEDTLS_SHA512_*ALT can't be used with MBEDTLS_SHA512_USE_A64_CRYPTO_*
|
||||
scripts/config.py unset MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT
|
||||
scripts/config.py unset MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY
|
||||
# Enable all MBEDTLS_XXX_ALT for whole modules. Do not enable
|
||||
# MBEDTLS_XXX_YYY_ALT which are for single functions.
|
||||
scripts/config.py set-all 'MBEDTLS_([A-Z0-9]*|NIST_KW)_ALT'
|
||||
@ -1541,8 +1679,8 @@ component_test_no_use_psa_crypto_full_cmake_asan() {
|
||||
msg "test: compat.sh default (full minus MBEDTLS_USE_PSA_CRYPTO)"
|
||||
tests/compat.sh
|
||||
|
||||
msg "test: compat.sh DES & NULL (full minus MBEDTLS_USE_PSA_CRYPTO)"
|
||||
env OPENSSL_CMD="$OPENSSL_LEGACY" GNUTLS_CLI="$GNUTLS_LEGACY_CLI" GNUTLS_SERV="$GNUTLS_LEGACY_SERV" tests/compat.sh -e '3DES\|DES-CBC3' -f 'NULL\|DES'
|
||||
msg "test: compat.sh NULL (full minus MBEDTLS_USE_PSA_CRYPTO)"
|
||||
env OPENSSL_CMD="$OPENSSL_LEGACY" GNUTLS_CLI="$GNUTLS_LEGACY_CLI" GNUTLS_SERV="$GNUTLS_LEGACY_SERV" tests/compat.sh -f 'NULL'
|
||||
|
||||
msg "test: compat.sh ARIA + ChachaPoly (full minus MBEDTLS_USE_PSA_CRYPTO)"
|
||||
env OPENSSL_CMD="$OPENSSL_NEXT" tests/compat.sh -e '^$' -f 'ARIA\|CHACHA'
|
||||
@ -1571,6 +1709,7 @@ component_test_psa_crypto_config_accel_ecdsa () {
|
||||
scripts/config.py set MBEDTLS_PSA_CRYPTO_DRIVERS
|
||||
scripts/config.py set MBEDTLS_PSA_CRYPTO_CONFIG
|
||||
scripts/config.py unset MBEDTLS_USE_PSA_CRYPTO
|
||||
scripts/config.py unset MBEDTLS_SSL_PROTO_TLS1_3
|
||||
scripts/config.py unset MBEDTLS_ECDSA_C
|
||||
scripts/config.py unset MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
|
||||
scripts/config.py unset MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED
|
||||
@ -1617,6 +1756,8 @@ component_test_psa_crypto_config_accel_rsa_signature () {
|
||||
|
||||
scripts/config.py -f tests/include/test/drivers/config_test_driver.h set MBEDTLS_SHA1_C
|
||||
scripts/config.py -f tests/include/test/drivers/config_test_driver.h set MBEDTLS_SHA512_C
|
||||
# We need to define either MD_C or all of the PSA_WANT_ALG_SHAxxx.
|
||||
scripts/config.py -f tests/include/test/drivers/config_test_driver.h set MBEDTLS_MD_C
|
||||
# We need PEM parsing in the test library as well to support the import
|
||||
# of PEM encoded RSA keys.
|
||||
scripts/config.py -f tests/include/test/drivers/config_test_driver.h set MBEDTLS_PEM_PARSE_C
|
||||
@ -1629,6 +1770,7 @@ component_test_psa_crypto_config_accel_rsa_signature () {
|
||||
# Restore test driver base configuration
|
||||
scripts/config.py -f tests/include/test/drivers/config_test_driver.h unset MBEDTLS_SHA1_C
|
||||
scripts/config.py -f tests/include/test/drivers/config_test_driver.h unset MBEDTLS_SHA512_C
|
||||
scripts/config.py -f tests/include/test/drivers/config_test_driver.h unset MBEDTLS_MD_C
|
||||
scripts/config.py -f tests/include/test/drivers/config_test_driver.h unset MBEDTLS_PEM_PARSE_C
|
||||
scripts/config.py -f tests/include/test/drivers/config_test_driver.h unset MBEDTLS_BASE64_C
|
||||
|
||||
@ -1684,12 +1826,6 @@ component_test_psa_crypto_config_accel_hash () {
|
||||
# Don't unset MBEDTLS_SHA256_C as it is needed by PSA crypto core.
|
||||
scripts/config.py unset MBEDTLS_SHA384_C
|
||||
scripts/config.py unset MBEDTLS_SHA512_C
|
||||
# Unset MBEDTLS_SSL_PROTO_SSL3, MBEDTLS_SSL_PROTO_TLS1 and MBEDTLS_SSL_PROTO_TLS1_1 as they depend on MBEDTLS_SHA1_C
|
||||
scripts/config.py unset MBEDTLS_SSL_PROTO_SSL3
|
||||
scripts/config.py unset MBEDTLS_SSL_PROTO_TLS1
|
||||
scripts/config.py unset MBEDTLS_SSL_PROTO_TLS1_1
|
||||
# Unset MBEDTLS_SSL_CBC_RECORD_SPLITTING as it depends on MBEDTLS_SSL_PROTO_TLS1 in the default configuration.
|
||||
scripts/config.py unset MBEDTLS_SSL_CBC_RECORD_SPLITTING
|
||||
loc_accel_flags="$loc_accel_flags $( echo "$loc_accel_list" | sed 's/[^ ]* */-DMBEDTLS_PSA_ACCEL_&/g' )"
|
||||
make CFLAGS="$ASAN_CFLAGS -Werror -I../tests/include -I../tests -DPSA_CRYPTO_DRIVER_TEST -DMBEDTLS_TEST_LIBTESTDRIVER1 $loc_accel_flags" LDFLAGS="-ltestdriver1 $ASAN_CFLAGS"
|
||||
|
||||
@ -1700,6 +1836,67 @@ component_test_psa_crypto_config_accel_hash () {
|
||||
make test
|
||||
}
|
||||
|
||||
component_test_psa_crypto_config_accel_hash_use_psa () {
|
||||
msg "test: MBEDTLS_PSA_CRYPTO_CONFIG with accelerated hash and USE_PSA"
|
||||
|
||||
# Disable ALG_STREAM_CIPHER and ALG_ECB_NO_PADDING to avoid having
|
||||
# partial support for cipher operations in the driver test library.
|
||||
scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_STREAM_CIPHER
|
||||
scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_ECB_NO_PADDING
|
||||
|
||||
loc_accel_list="ALG_MD5 ALG_RIPEMD160 ALG_SHA_1 ALG_SHA_224 ALG_SHA_256 ALG_SHA_384 ALG_SHA_512"
|
||||
loc_accel_flags=$( echo "$loc_accel_list" | sed 's/[^ ]* */-DLIBTESTDRIVER1_MBEDTLS_PSA_ACCEL_&/g' )
|
||||
make -C tests libtestdriver1.a CFLAGS="$ASAN_CFLAGS $loc_accel_flags" LDFLAGS="$ASAN_CFLAGS"
|
||||
|
||||
scripts/config.py set MBEDTLS_PSA_CRYPTO_DRIVERS
|
||||
scripts/config.py set MBEDTLS_PSA_CRYPTO_CONFIG
|
||||
scripts/config.py set MBEDTLS_USE_PSA_CRYPTO
|
||||
scripts/config.py unset MBEDTLS_MD5_C
|
||||
scripts/config.py unset MBEDTLS_RIPEMD160_C
|
||||
scripts/config.py unset MBEDTLS_SHA1_C
|
||||
scripts/config.py unset MBEDTLS_SHA224_C
|
||||
scripts/config.py unset MBEDTLS_SHA256_C # see external RNG below
|
||||
scripts/config.py unset MBEDTLS_SHA384_C
|
||||
scripts/config.py unset MBEDTLS_SHA512_C
|
||||
# Use an external RNG as currently internal RNGs depend on entropy.c
|
||||
# which in turn hard-depends on SHA256_C (or SHA512_C).
|
||||
# See component_test_psa_external_rng_no_drbg_use_psa.
|
||||
scripts/config.py set MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG
|
||||
scripts/config.py unset MBEDTLS_ENTROPY_C
|
||||
# Also unset MD_C and things that depend on it;
|
||||
# see component_test_crypto_full_no_md.
|
||||
scripts/config.py unset MBEDTLS_MD_C
|
||||
scripts/config.py unset MBEDTLS_HKDF_C
|
||||
scripts/config.py unset MBEDTLS_HMAC_DRBG_C
|
||||
scripts/config.py unset MBEDTLS_ECDSA_DETERMINISTIC
|
||||
scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_DETERMINISTIC_ECDSA
|
||||
# Enable TLS 1.3: use PSA implementation for hashes
|
||||
scripts/config.py set MBEDTLS_SSL_PROTO_TLS1_3
|
||||
scripts/config.py set MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE
|
||||
scripts/config.py set MBEDTLS_SSL_CID_TLS1_3_PADDING_GRANULARITY 1
|
||||
|
||||
loc_accel_flags="$loc_accel_flags $( echo "$loc_accel_list" | sed 's/[^ ]* */-DMBEDTLS_PSA_ACCEL_&/g' )"
|
||||
make CFLAGS="$ASAN_CFLAGS -Werror -I../tests/include -I../tests -I../../tests -DPSA_CRYPTO_DRIVER_TEST -DMBEDTLS_TEST_LIBTESTDRIVER1 $loc_accel_flags" LDFLAGS="-ltestdriver1 $ASAN_CFLAGS" all
|
||||
|
||||
# There's a risk of something getting re-enabled via config_psa.h;
|
||||
# make sure it did not happen.
|
||||
not grep mbedtls_md library/md.o
|
||||
not grep mbedtls_md5 library/md5.o
|
||||
not grep mbedtls_sha1 library/sha1.o
|
||||
not grep mbedtls_sha256 library/sha256.o
|
||||
not grep mbedtls_sha512 library/sha512.o
|
||||
not grep mbedtls_ripemd160 library/ripemd160.o
|
||||
|
||||
msg "test: MBEDTLS_PSA_CRYPTO_CONFIG with accelerated hash and USE_PSA"
|
||||
make test
|
||||
|
||||
msg "test: ssl-opt.sh, MBEDTLS_PSA_CRYPTO_CONFIG with accelerated hash and USE_PSA"
|
||||
tests/ssl-opt.sh
|
||||
|
||||
msg "test: compat.sh, MBEDTLS_PSA_CRYPTO_CONFIG with accelerated hash and USE_PSA"
|
||||
tests/compat.sh
|
||||
}
|
||||
|
||||
component_test_psa_crypto_config_accel_cipher () {
|
||||
msg "test: MBEDTLS_PSA_CRYPTO_CONFIG with accelerated cipher"
|
||||
|
||||
@ -1732,7 +1929,7 @@ component_test_psa_crypto_config_accel_cipher () {
|
||||
|
||||
not grep mbedtls_des* library/des.o
|
||||
|
||||
msg "test: MBEDTLS_PSA_CRYPTO_CONFIG with accelerated hash"
|
||||
msg "test: MBEDTLS_PSA_CRYPTO_CONFIG with accelerated cipher"
|
||||
make test
|
||||
}
|
||||
|
||||
@ -1743,6 +1940,7 @@ component_test_psa_crypto_config_no_driver() {
|
||||
scripts/config.py set MBEDTLS_PSA_CRYPTO_CONFIG
|
||||
scripts/config.py unset MBEDTLS_PSA_CRYPTO_DRIVERS
|
||||
scripts/config.py unset MBEDTLS_USE_PSA_CRYPTO
|
||||
scripts/config.py unset MBEDTLS_SSL_PROTO_TLS1_3
|
||||
make CC=gcc CFLAGS="$ASAN_CFLAGS -O2" LDFLAGS="$ASAN_CFLAGS"
|
||||
|
||||
msg "test: full + MBEDTLS_PSA_CRYPTO_CONFIG minus MBEDTLS_PSA_CRYPTO_DRIVERS"
|
||||
@ -1773,6 +1971,7 @@ component_build_psa_accel_alg_ecdsa() {
|
||||
scripts/config.py set MBEDTLS_PSA_CRYPTO_CONFIG
|
||||
scripts/config.py set MBEDTLS_PSA_CRYPTO_DRIVERS
|
||||
scripts/config.py unset MBEDTLS_USE_PSA_CRYPTO
|
||||
scripts/config.py unset MBEDTLS_SSL_PROTO_TLS1_3
|
||||
scripts/config.py unset MBEDTLS_ECDSA_C
|
||||
scripts/config.py unset MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED
|
||||
scripts/config.py unset MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
|
||||
@ -1789,6 +1988,7 @@ component_build_psa_accel_alg_ecdh() {
|
||||
scripts/config.py set MBEDTLS_PSA_CRYPTO_CONFIG
|
||||
scripts/config.py set MBEDTLS_PSA_CRYPTO_DRIVERS
|
||||
scripts/config.py unset MBEDTLS_USE_PSA_CRYPTO
|
||||
scripts/config.py unset MBEDTLS_SSL_PROTO_TLS1_3
|
||||
scripts/config.py unset MBEDTLS_ECDH_C
|
||||
scripts/config.py unset MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED
|
||||
scripts/config.py unset MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED
|
||||
@ -1807,6 +2007,7 @@ component_build_psa_accel_key_type_ecc_key_pair() {
|
||||
scripts/config.py set MBEDTLS_PSA_CRYPTO_CONFIG
|
||||
scripts/config.py set MBEDTLS_PSA_CRYPTO_DRIVERS
|
||||
scripts/config.py unset MBEDTLS_USE_PSA_CRYPTO
|
||||
scripts/config.py unset MBEDTLS_SSL_PROTO_TLS1_3
|
||||
scripts/config.py -f include/psa/crypto_config.h set PSA_WANT_KEY_TYPE_ECC_KEY_PAIR 1
|
||||
scripts/config.py -f include/psa/crypto_config.h set PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY 1
|
||||
# Need to define the correct symbol and include the test driver header path in order to build with the test driver
|
||||
@ -1821,6 +2022,7 @@ component_build_psa_accel_key_type_ecc_public_key() {
|
||||
scripts/config.py set MBEDTLS_PSA_CRYPTO_CONFIG
|
||||
scripts/config.py set MBEDTLS_PSA_CRYPTO_DRIVERS
|
||||
scripts/config.py unset MBEDTLS_USE_PSA_CRYPTO
|
||||
scripts/config.py unset MBEDTLS_SSL_PROTO_TLS1_3
|
||||
scripts/config.py -f include/psa/crypto_config.h set PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY 1
|
||||
scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
|
||||
# Need to define the correct symbol and include the test driver header path in order to build with the test driver
|
||||
@ -1835,6 +2037,7 @@ component_build_psa_accel_alg_hmac() {
|
||||
scripts/config.py set MBEDTLS_PSA_CRYPTO_CONFIG
|
||||
scripts/config.py set MBEDTLS_PSA_CRYPTO_DRIVERS
|
||||
scripts/config.py unset MBEDTLS_USE_PSA_CRYPTO
|
||||
scripts/config.py unset MBEDTLS_SSL_PROTO_TLS1_3
|
||||
# Need to define the correct symbol and include the test driver header path in order to build with the test driver
|
||||
make CC=gcc CFLAGS="$ASAN_CFLAGS -DPSA_CRYPTO_DRIVER_TEST -DMBEDTLS_PSA_ACCEL_ALG_HMAC -I../tests/include -O2" LDFLAGS="$ASAN_CFLAGS"
|
||||
}
|
||||
@ -1848,6 +2051,7 @@ component_build_psa_accel_alg_hkdf() {
|
||||
scripts/config.py set MBEDTLS_PSA_CRYPTO_CONFIG
|
||||
scripts/config.py set MBEDTLS_PSA_CRYPTO_DRIVERS
|
||||
scripts/config.py unset MBEDTLS_USE_PSA_CRYPTO
|
||||
scripts/config.py unset MBEDTLS_SSL_PROTO_TLS1_3
|
||||
scripts/config.py unset MBEDTLS_HKDF_C
|
||||
# Make sure to unset TLS1_3 since it requires HKDF_C and will not build properly without it.
|
||||
scripts/config.py unset MBEDTLS_SSL_PROTO_TLS1_3
|
||||
@ -1863,6 +2067,7 @@ component_build_psa_accel_alg_md5() {
|
||||
scripts/config.py set MBEDTLS_PSA_CRYPTO_CONFIG
|
||||
scripts/config.py set MBEDTLS_PSA_CRYPTO_DRIVERS
|
||||
scripts/config.py unset MBEDTLS_USE_PSA_CRYPTO
|
||||
scripts/config.py unset MBEDTLS_SSL_PROTO_TLS1_3
|
||||
scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_RIPEMD160
|
||||
scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_SHA_1
|
||||
scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_SHA_224
|
||||
@ -1881,6 +2086,7 @@ component_build_psa_accel_alg_ripemd160() {
|
||||
scripts/config.py set MBEDTLS_PSA_CRYPTO_CONFIG
|
||||
scripts/config.py set MBEDTLS_PSA_CRYPTO_DRIVERS
|
||||
scripts/config.py unset MBEDTLS_USE_PSA_CRYPTO
|
||||
scripts/config.py unset MBEDTLS_SSL_PROTO_TLS1_3
|
||||
scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_MD5
|
||||
scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_SHA_1
|
||||
scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_SHA_224
|
||||
@ -1899,6 +2105,7 @@ component_build_psa_accel_alg_sha1() {
|
||||
scripts/config.py set MBEDTLS_PSA_CRYPTO_CONFIG
|
||||
scripts/config.py set MBEDTLS_PSA_CRYPTO_DRIVERS
|
||||
scripts/config.py unset MBEDTLS_USE_PSA_CRYPTO
|
||||
scripts/config.py unset MBEDTLS_SSL_PROTO_TLS1_3
|
||||
scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_MD5
|
||||
scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_RIPEMD160
|
||||
scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_SHA_224
|
||||
@ -1917,6 +2124,7 @@ component_build_psa_accel_alg_sha224() {
|
||||
scripts/config.py set MBEDTLS_PSA_CRYPTO_CONFIG
|
||||
scripts/config.py set MBEDTLS_PSA_CRYPTO_DRIVERS
|
||||
scripts/config.py unset MBEDTLS_USE_PSA_CRYPTO
|
||||
scripts/config.py unset MBEDTLS_SSL_PROTO_TLS1_3
|
||||
scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_MD5
|
||||
scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_RIPEMD160
|
||||
scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_SHA_1
|
||||
@ -1934,6 +2142,7 @@ component_build_psa_accel_alg_sha256() {
|
||||
scripts/config.py set MBEDTLS_PSA_CRYPTO_CONFIG
|
||||
scripts/config.py set MBEDTLS_PSA_CRYPTO_DRIVERS
|
||||
scripts/config.py unset MBEDTLS_USE_PSA_CRYPTO
|
||||
scripts/config.py unset MBEDTLS_SSL_PROTO_TLS1_3
|
||||
scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_MD5
|
||||
scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_RIPEMD160
|
||||
scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_SHA_1
|
||||
@ -1952,6 +2161,7 @@ component_build_psa_accel_alg_sha384() {
|
||||
scripts/config.py set MBEDTLS_PSA_CRYPTO_CONFIG
|
||||
scripts/config.py set MBEDTLS_PSA_CRYPTO_DRIVERS
|
||||
scripts/config.py unset MBEDTLS_USE_PSA_CRYPTO
|
||||
scripts/config.py unset MBEDTLS_SSL_PROTO_TLS1_3
|
||||
scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_MD5
|
||||
scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_RIPEMD160
|
||||
scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_SHA_1
|
||||
@ -1969,6 +2179,7 @@ component_build_psa_accel_alg_sha512() {
|
||||
scripts/config.py set MBEDTLS_PSA_CRYPTO_CONFIG
|
||||
scripts/config.py set MBEDTLS_PSA_CRYPTO_DRIVERS
|
||||
scripts/config.py unset MBEDTLS_USE_PSA_CRYPTO
|
||||
scripts/config.py unset MBEDTLS_SSL_PROTO_TLS1_3
|
||||
scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_MD5
|
||||
scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_RIPEMD160
|
||||
scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_SHA_1
|
||||
@ -1987,6 +2198,7 @@ component_build_psa_accel_alg_rsa_pkcs1v15_crypt() {
|
||||
scripts/config.py set MBEDTLS_PSA_CRYPTO_CONFIG
|
||||
scripts/config.py set MBEDTLS_PSA_CRYPTO_DRIVERS
|
||||
scripts/config.py unset MBEDTLS_USE_PSA_CRYPTO
|
||||
scripts/config.py unset MBEDTLS_SSL_PROTO_TLS1_3
|
||||
scripts/config.py -f include/psa/crypto_config.h set PSA_WANT_ALG_RSA_PKCS1V15_CRYPT 1
|
||||
scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_RSA_PKCS1V15_SIGN
|
||||
scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_RSA_OAEP
|
||||
@ -2003,6 +2215,7 @@ component_build_psa_accel_alg_rsa_pkcs1v15_sign() {
|
||||
scripts/config.py set MBEDTLS_PSA_CRYPTO_CONFIG
|
||||
scripts/config.py set MBEDTLS_PSA_CRYPTO_DRIVERS
|
||||
scripts/config.py unset MBEDTLS_USE_PSA_CRYPTO
|
||||
scripts/config.py unset MBEDTLS_SSL_PROTO_TLS1_3
|
||||
scripts/config.py -f include/psa/crypto_config.h set PSA_WANT_ALG_RSA_PKCS1V15_SIGN 1
|
||||
scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_RSA_PKCS1V15_CRYPT
|
||||
scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_RSA_OAEP
|
||||
@ -2019,6 +2232,7 @@ component_build_psa_accel_alg_rsa_oaep() {
|
||||
scripts/config.py set MBEDTLS_PSA_CRYPTO_CONFIG
|
||||
scripts/config.py set MBEDTLS_PSA_CRYPTO_DRIVERS
|
||||
scripts/config.py unset MBEDTLS_USE_PSA_CRYPTO
|
||||
scripts/config.py unset MBEDTLS_SSL_PROTO_TLS1_3
|
||||
scripts/config.py -f include/psa/crypto_config.h set PSA_WANT_ALG_RSA_OAEP 1
|
||||
scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_RSA_PKCS1V15_CRYPT
|
||||
scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_RSA_PKCS1V15_SIGN
|
||||
@ -2035,6 +2249,7 @@ component_build_psa_accel_alg_rsa_pss() {
|
||||
scripts/config.py set MBEDTLS_PSA_CRYPTO_CONFIG
|
||||
scripts/config.py set MBEDTLS_PSA_CRYPTO_DRIVERS
|
||||
scripts/config.py unset MBEDTLS_USE_PSA_CRYPTO
|
||||
scripts/config.py unset MBEDTLS_SSL_PROTO_TLS1_3
|
||||
scripts/config.py -f include/psa/crypto_config.h set PSA_WANT_ALG_RSA_PSS 1
|
||||
scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_RSA_PKCS1V15_CRYPT
|
||||
scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_RSA_PKCS1V15_SIGN
|
||||
@ -2051,6 +2266,7 @@ component_build_psa_accel_key_type_rsa_key_pair() {
|
||||
scripts/config.py set MBEDTLS_PSA_CRYPTO_CONFIG
|
||||
scripts/config.py set MBEDTLS_PSA_CRYPTO_DRIVERS
|
||||
scripts/config.py unset MBEDTLS_USE_PSA_CRYPTO
|
||||
scripts/config.py unset MBEDTLS_SSL_PROTO_TLS1_3
|
||||
scripts/config.py -f include/psa/crypto_config.h set PSA_WANT_ALG_RSA_PSS 1
|
||||
scripts/config.py -f include/psa/crypto_config.h set PSA_WANT_KEY_TYPE_RSA_KEY_PAIR 1
|
||||
# Need to define the correct symbol and include the test driver header path in order to build with the test driver
|
||||
@ -2065,6 +2281,7 @@ component_build_psa_accel_key_type_rsa_public_key() {
|
||||
scripts/config.py set MBEDTLS_PSA_CRYPTO_CONFIG
|
||||
scripts/config.py set MBEDTLS_PSA_CRYPTO_DRIVERS
|
||||
scripts/config.py unset MBEDTLS_USE_PSA_CRYPTO
|
||||
scripts/config.py unset MBEDTLS_SSL_PROTO_TLS1_3
|
||||
scripts/config.py -f include/psa/crypto_config.h set PSA_WANT_ALG_RSA_PSS 1
|
||||
scripts/config.py -f include/psa/crypto_config.h set PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY 1
|
||||
# Need to define the correct symbol and include the test driver header path in order to build with the test driver
|
||||
@ -2085,6 +2302,7 @@ component_test_no_platform () {
|
||||
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_PLATFORM_SETBUF_ALT
|
||||
scripts/config.py unset MBEDTLS_PLATFORM_NV_SEED_ALT
|
||||
scripts/config.py unset MBEDTLS_ENTROPY_NV_SEED
|
||||
scripts/config.py unset MBEDTLS_FS_IO
|
||||
@ -2109,14 +2327,14 @@ component_build_no_std_function () {
|
||||
}
|
||||
|
||||
component_build_no_ssl_srv () {
|
||||
msg "build: full config except ssl_srv.c, make, gcc" # ~ 30s
|
||||
msg "build: full config except SSL server, make, gcc" # ~ 30s
|
||||
scripts/config.py full
|
||||
scripts/config.py unset MBEDTLS_SSL_SRV_C
|
||||
make CC=gcc CFLAGS='-Werror -Wall -Wextra -O1'
|
||||
}
|
||||
|
||||
component_build_no_ssl_cli () {
|
||||
msg "build: full config except ssl_cli.c, make, gcc" # ~ 30s
|
||||
msg "build: full config except SSL client, make, gcc" # ~ 30s
|
||||
scripts/config.py full
|
||||
scripts/config.py unset MBEDTLS_SSL_CLI_C
|
||||
make CC=gcc CFLAGS='-Werror -Wall -Wextra -O1'
|
||||
@ -2239,18 +2457,6 @@ component_test_variable_ssl_in_out_buffer_len_CID () {
|
||||
tests/compat.sh
|
||||
}
|
||||
|
||||
component_test_CID_no_debug() {
|
||||
msg "build: Connection ID enabled, debug disabled"
|
||||
scripts/config.py unset MBEDTLS_DEBUG_C
|
||||
scripts/config.py set MBEDTLS_SSL_DTLS_CONNECTION_ID
|
||||
|
||||
CC=gcc cmake .
|
||||
make
|
||||
|
||||
msg "test: Connection ID enabled, debug disabled"
|
||||
make test
|
||||
}
|
||||
|
||||
component_test_ssl_alloc_buffer_and_mfl () {
|
||||
msg "build: default config with memory buffer allocator and MFL extension"
|
||||
scripts/config.py set MBEDTLS_MEMORY_BUFFER_ALLOC_C
|
||||
@ -2457,13 +2663,42 @@ component_test_gcc_opt () {
|
||||
|
||||
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.py full
|
||||
sed 's!"check_config.h"!"mbedtls/check_config.h"!' <"$CONFIG_H" >full_config.h
|
||||
scripts/config.py -w full_config.h full
|
||||
echo '#error "MBEDTLS_CONFIG_FILE is not working"' >"$CONFIG_H"
|
||||
make CFLAGS="-I '$PWD' -DMBEDTLS_CONFIG_FILE='\"full_config.h\"'"
|
||||
rm -f full_config.h
|
||||
# Make sure this feature is enabled. We'll disable it in the next phase.
|
||||
programs/test/query_compile_time_config MBEDTLS_NIST_KW_C
|
||||
make clean
|
||||
|
||||
msg "build: make with MBEDTLS_CONFIG_FILE + MBEDTLS_USER_CONFIG_FILE"
|
||||
# In the user config, disable one feature (for simplicity, pick a feature
|
||||
# that nothing else depends on).
|
||||
echo '#undef MBEDTLS_NIST_KW_C' >user_config.h
|
||||
make CFLAGS="-I '$PWD' -DMBEDTLS_CONFIG_FILE='\"full_config.h\"' -DMBEDTLS_USER_CONFIG_FILE='\"user_config.h\"'"
|
||||
not programs/test/query_compile_time_config MBEDTLS_NIST_KW_C
|
||||
|
||||
rm -f user_config.h full_config.h
|
||||
}
|
||||
|
||||
component_build_psa_config_file () {
|
||||
msg "build: make with MBEDTLS_PSA_CRYPTO_CONFIG_FILE" # ~40s
|
||||
scripts/config.py set MBEDTLS_PSA_CRYPTO_CONFIG
|
||||
cp "$CRYPTO_CONFIG_H" psa_test_config.h
|
||||
echo '#error "MBEDTLS_PSA_CRYPTO_CONFIG_FILE is not working"' >"$CRYPTO_CONFIG_H"
|
||||
make CFLAGS="-I '$PWD' -DMBEDTLS_PSA_CRYPTO_CONFIG_FILE='\"psa_test_config.h\"'"
|
||||
# Make sure this feature is enabled. We'll disable it in the next phase.
|
||||
programs/test/query_compile_time_config MBEDTLS_CMAC_C
|
||||
make clean
|
||||
|
||||
msg "build: make with MBEDTLS_PSA_CRYPTO_CONFIG_FILE + MBEDTLS_PSA_CRYPTO_USER_CONFIG_FILE" # ~40s
|
||||
# In the user config, disable one feature, which will reflect on the
|
||||
# mbedtls configuration so we can query it with query_compile_time_config.
|
||||
echo '#undef PSA_WANT_ALG_CMAC' >psa_user_config.h
|
||||
scripts/config.py unset MBEDTLS_CMAC_C
|
||||
make CFLAGS="-I '$PWD' -DMBEDTLS_PSA_CRYPTO_CONFIG_FILE='\"psa_test_config.h\"' -DMBEDTLS_PSA_CRYPTO_USER_CONFIG_FILE='\"psa_user_config.h\"'"
|
||||
not programs/test/query_compile_time_config MBEDTLS_CMAC_C
|
||||
|
||||
rm -f psa_test_config.h psa_user_config.h
|
||||
}
|
||||
|
||||
component_test_m32_o0 () {
|
||||
@ -2513,7 +2748,7 @@ component_test_m32_everest () {
|
||||
|
||||
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.
|
||||
tests/compat.sh -f ECDH -V NO -e 'ARIA\|CAMELLIA\|CHACHA\|DES'
|
||||
tests/compat.sh -f ECDH -V NO -e 'ARIA\|CAMELLIA\|CHACHA'
|
||||
}
|
||||
support_test_m32_everest () {
|
||||
support_test_m32_o0 "$@"
|
||||
@ -2615,25 +2850,25 @@ component_test_no_x509_info () {
|
||||
}
|
||||
|
||||
component_build_arm_none_eabi_gcc () {
|
||||
msg "build: ${ARM_NONE_EABI_GCC_PREFIX}gcc -O1" # ~ 10s
|
||||
msg "build: ${ARM_NONE_EABI_GCC_PREFIX}gcc -O1, baremetal+debug" # ~ 10s
|
||||
scripts/config.py baremetal
|
||||
make CC="${ARM_NONE_EABI_GCC_PREFIX}gcc" AR="${ARM_NONE_EABI_GCC_PREFIX}ar" LD="${ARM_NONE_EABI_GCC_PREFIX}ld" CFLAGS='-std=c99 -Werror -Wall -Wextra -O1' lib
|
||||
|
||||
msg "size: ${ARM_NONE_EABI_GCC_PREFIX}gcc -O1"
|
||||
msg "size: ${ARM_NONE_EABI_GCC_PREFIX}gcc -O1, baremetal+debug"
|
||||
${ARM_NONE_EABI_GCC_PREFIX}size library/*.o
|
||||
}
|
||||
|
||||
component_build_arm_linux_gnueabi_gcc_arm5vte () {
|
||||
msg "build: ${ARM_LINUX_GNUEABI_GCC_PREFIX}gcc -march=arm5vte" # ~ 10s
|
||||
msg "build: ${ARM_LINUX_GNUEABI_GCC_PREFIX}gcc -march=arm5vte, baremetal+debug" # ~ 10s
|
||||
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.
|
||||
# See https://github.com/Mbed-TLS/mbedtls/pull/2169 and comments.
|
||||
# Build everything including programs, see for example
|
||||
# https://github.com/ARMmbed/mbedtls/pull/3449#issuecomment-675313720
|
||||
# https://github.com/Mbed-TLS/mbedtls/pull/3449#issuecomment-675313720
|
||||
make CC="${ARM_LINUX_GNUEABI_GCC_PREFIX}gcc" AR="${ARM_LINUX_GNUEABI_GCC_PREFIX}ar" CFLAGS='-Werror -Wall -Wextra -march=armv5te -O1' LDFLAGS='-march=armv5te'
|
||||
|
||||
msg "size: ${ARM_LINUX_GNUEABI_GCC_PREFIX}gcc -march=armv5te -O1"
|
||||
msg "size: ${ARM_LINUX_GNUEABI_GCC_PREFIX}gcc -march=armv5te -O1, baremetal+debug"
|
||||
${ARM_LINUX_GNUEABI_GCC_PREFIX}size library/*.o
|
||||
}
|
||||
support_build_arm_linux_gnueabi_gcc_arm5vte () {
|
||||
@ -2641,23 +2876,23 @@ support_build_arm_linux_gnueabi_gcc_arm5vte () {
|
||||
}
|
||||
|
||||
component_build_arm_none_eabi_gcc_arm5vte () {
|
||||
msg "build: ${ARM_NONE_EABI_GCC_PREFIX}gcc -march=arm5vte" # ~ 10s
|
||||
msg "build: ${ARM_NONE_EABI_GCC_PREFIX}gcc -march=arm5vte, baremetal+debug" # ~ 10s
|
||||
scripts/config.py baremetal
|
||||
# This is an imperfect substitute for
|
||||
# component_build_arm_linux_gnueabi_gcc_arm5vte
|
||||
# in case the gcc-arm-linux-gnueabi toolchain is not available
|
||||
make CC="${ARM_NONE_EABI_GCC_PREFIX}gcc" AR="${ARM_NONE_EABI_GCC_PREFIX}ar" CFLAGS='-std=c99 -Werror -Wall -Wextra -march=armv5te -O1' LDFLAGS='-march=armv5te' SHELL='sh -x' lib
|
||||
|
||||
msg "size: ${ARM_NONE_EABI_GCC_PREFIX}gcc -march=armv5te -O1"
|
||||
msg "size: ${ARM_NONE_EABI_GCC_PREFIX}gcc -march=armv5te -O1, baremetal+debug"
|
||||
${ARM_NONE_EABI_GCC_PREFIX}size library/*.o
|
||||
}
|
||||
|
||||
component_build_arm_none_eabi_gcc_m0plus () {
|
||||
msg "build: ${ARM_NONE_EABI_GCC_PREFIX}gcc -mthumb -mcpu=cortex-m0plus" # ~ 10s
|
||||
scripts/config.py baremetal
|
||||
msg "build: ${ARM_NONE_EABI_GCC_PREFIX}gcc -mthumb -mcpu=cortex-m0plus, baremetal_size" # ~ 10s
|
||||
scripts/config.py baremetal_size
|
||||
make CC="${ARM_NONE_EABI_GCC_PREFIX}gcc" AR="${ARM_NONE_EABI_GCC_PREFIX}ar" LD="${ARM_NONE_EABI_GCC_PREFIX}ld" CFLAGS='-std=c99 -Werror -Wall -Wextra -mthumb -mcpu=cortex-m0plus -Os' lib
|
||||
|
||||
msg "size: ${ARM_NONE_EABI_GCC_PREFIX}gcc -mthumb -mcpu=cortex-m0plus -Os"
|
||||
msg "size: ${ARM_NONE_EABI_GCC_PREFIX}gcc -mthumb -mcpu=cortex-m0plus -Os, baremetal_size"
|
||||
${ARM_NONE_EABI_GCC_PREFIX}size library/*.o
|
||||
}
|
||||
|
||||
@ -2682,6 +2917,10 @@ component_build_arm_none_eabi_gcc_no_64bit_multiplication () {
|
||||
component_build_armcc () {
|
||||
msg "build: ARM Compiler 5"
|
||||
scripts/config.py baremetal
|
||||
# armc[56] don't support SHA-512 intrinsics
|
||||
scripts/config.py unset MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT
|
||||
scripts/config.py set MBEDTLS_HAVE_ASM
|
||||
|
||||
make CC="$ARMC5_CC" AR="$ARMC5_AR" WARNING_CFLAGS='--strict --c99' lib
|
||||
|
||||
msg "size: ARM Compiler 5"
|
||||
@ -2689,20 +2928,25 @@ component_build_armcc () {
|
||||
|
||||
make clean
|
||||
|
||||
# Compile with -O1 since some Arm inline assembly is disabled for -O0.
|
||||
|
||||
# ARM Compiler 6 - Target ARMv7-A
|
||||
armc6_build_test "--target=arm-arm-none-eabi -march=armv7-a"
|
||||
armc6_build_test "-O1 --target=arm-arm-none-eabi -march=armv7-a"
|
||||
|
||||
# ARM Compiler 6 - Target ARMv7-M
|
||||
armc6_build_test "--target=arm-arm-none-eabi -march=armv7-m"
|
||||
armc6_build_test "-O1 --target=arm-arm-none-eabi -march=armv7-m"
|
||||
|
||||
# ARM Compiler 6 - Target ARMv7-M+DSP
|
||||
armc6_build_test "-O1 --target=arm-arm-none-eabi -march=armv7-m+dsp"
|
||||
|
||||
# ARM Compiler 6 - Target ARMv8-A - AArch32
|
||||
armc6_build_test "--target=arm-arm-none-eabi -march=armv8.2-a"
|
||||
armc6_build_test "-O1 --target=arm-arm-none-eabi -march=armv8.2-a"
|
||||
|
||||
# ARM Compiler 6 - Target ARMv8-M
|
||||
armc6_build_test "--target=arm-arm-none-eabi -march=armv8-m.main"
|
||||
armc6_build_test "-O1 --target=arm-arm-none-eabi -march=armv8-m.main"
|
||||
|
||||
# ARM Compiler 6 - Target ARMv8-A - AArch64
|
||||
armc6_build_test "--target=aarch64-arm-none-eabi -march=armv8.2-a"
|
||||
# ARM Compiler 6 - Target ARMv8.2-A - AArch64
|
||||
armc6_build_test "-O1 --target=aarch64-arm-none-eabi -march=armv8.2-a+crypto"
|
||||
}
|
||||
|
||||
component_test_tls13_only () {
|
||||
@ -2716,6 +2960,18 @@ component_test_tls13_only () {
|
||||
if_build_succeeded tests/ssl-opt.sh
|
||||
}
|
||||
|
||||
component_test_tls13_only_with_hooks () {
|
||||
msg "build: default config with MBEDTLS_SSL_PROTO_TLS1_3 and MBEDTLS_TEST_HOOKS, without MBEDTLS_SSL_PROTO_TLS1_2"
|
||||
scripts/config.py set MBEDTLS_TEST_HOOKS
|
||||
make CFLAGS="'-DMBEDTLS_USER_CONFIG_FILE=\"../tests/configs/tls13-only.h\"'"
|
||||
|
||||
msg "test: default config with MBEDTLS_SSL_PROTO_TLS1_3 enabled, without MBEDTLS_SSL_PROTO_TLS1_2"
|
||||
if_build_succeeded make test
|
||||
|
||||
msg "ssl-opt.sh (TLS 1.3)"
|
||||
if_build_succeeded tests/ssl-opt.sh
|
||||
}
|
||||
|
||||
component_test_tls13 () {
|
||||
msg "build: default config with MBEDTLS_SSL_PROTO_TLS1_3 enabled, without padding"
|
||||
scripts/config.py set MBEDTLS_SSL_PROTO_TLS1_3
|
||||
@ -2888,16 +3144,17 @@ component_test_cmake_out_of_source () {
|
||||
|
||||
msg "test: cmake 'out-of-source' build"
|
||||
make test
|
||||
# Test an SSL option that requires an auxiliary script in test/scripts/.
|
||||
# Check that ssl-opt.sh can find the test programs.
|
||||
# Also ensure that there are no error messages such as
|
||||
# "No such file or directory", which would indicate that some required
|
||||
# file is missing (ssl-opt.sh tolerates the absence of some files so
|
||||
# may exit with status 0 but emit errors).
|
||||
./tests/ssl-opt.sh -f 'Fallback SCSV: beginning of list' 2>ssl-opt.err
|
||||
./tests/ssl-opt.sh -f 'Default' >ssl-opt.out 2>ssl-opt.err
|
||||
grep PASS ssl-opt.out
|
||||
cat ssl-opt.err >&2
|
||||
# If ssl-opt.err is non-empty, record an error and keep going.
|
||||
[ ! -s ssl-opt.err ]
|
||||
rm ssl-opt.err
|
||||
rm ssl-opt.out ssl-opt.err
|
||||
cd "$MBEDTLS_ROOT_DIR"
|
||||
rm -rf "$OUT_OF_SOURCE_DIR"
|
||||
}
|
||||
@ -3045,7 +3302,7 @@ run_component () {
|
||||
local dd_cmd
|
||||
dd_cmd=(dd if=/dev/urandom of=./tests/seedfile bs=64 count=1)
|
||||
case $OSTYPE in
|
||||
linux*|freebsd*|openbsd*|darwin*) dd_cmd+=(status=none)
|
||||
linux*|freebsd*|openbsd*) dd_cmd+=(status=none)
|
||||
esac
|
||||
"${dd_cmd[@]}"
|
||||
|
||||
|
@ -121,13 +121,13 @@ echo
|
||||
echo '################ compat.sh ################'
|
||||
{
|
||||
echo '#### compat.sh: Default versions'
|
||||
sh compat.sh -m 'tls1_2 dtls1_2'
|
||||
sh compat.sh
|
||||
echo
|
||||
|
||||
echo '#### compat.sh: legacy (null, DES)'
|
||||
echo '#### compat.sh: legacy (null)'
|
||||
OPENSSL_CMD="$OPENSSL_LEGACY" \
|
||||
GNUTLS_CLI="$GNUTLS_LEGACY_CLI" GNUTLS_SERV="$GNUTLS_LEGACY_SERV" \
|
||||
sh compat.sh -e '^$' -f 'NULL\|DES'
|
||||
sh compat.sh -e '^$' -f 'NULL'
|
||||
echo
|
||||
|
||||
echo '#### compat.sh: next (ARIA, ChaCha)'
|
||||
|
@ -76,7 +76,7 @@ check()
|
||||
|
||||
for FILE in "$@"; do
|
||||
if [ -e "$FILE" ]; then
|
||||
cp "$FILE" "$FILE.bak"
|
||||
cp -p "$FILE" "$FILE.bak"
|
||||
else
|
||||
rm -f "$FILE.bak"
|
||||
fi
|
||||
@ -86,17 +86,18 @@ check()
|
||||
|
||||
# Compare the script output to the old files and remove backups
|
||||
for FILE in "$@"; do
|
||||
if ! diff "$FILE" "$FILE.bak" >/dev/null 2>&1; then
|
||||
if diff "$FILE" "$FILE.bak" >/dev/null 2>&1; then
|
||||
# Move the original file back so that $FILE's timestamp doesn't
|
||||
# change (avoids spurious rebuilds with make).
|
||||
mv "$FILE.bak" "$FILE"
|
||||
else
|
||||
echo "'$FILE' was either modified or deleted by '$SCRIPT'"
|
||||
if [ -z "$UPDATE" ]; then
|
||||
exit 1
|
||||
else
|
||||
rm -f "$FILE.bak"
|
||||
fi
|
||||
fi
|
||||
if [ -z "$UPDATE" ]; then
|
||||
mv "$FILE.bak" "$FILE"
|
||||
else
|
||||
rm -f "$FILE.bak"
|
||||
fi
|
||||
done
|
||||
|
||||
if [ -n "$directory" ]; then
|
||||
@ -125,4 +126,5 @@ check scripts/generate_ssl_debug_helpers.py library/ssl_debug_helpers_generated.
|
||||
# the step that creates or updates these files.
|
||||
check scripts/generate_visualc_files.pl visualc/VS2010
|
||||
check scripts/generate_psa_constants.py programs/psa/psa_constant_names_generated.c
|
||||
check tests/scripts/generate_bignum_tests.py $(tests/scripts/generate_bignum_tests.py --list)
|
||||
check tests/scripts/generate_psa_tests.py $(tests/scripts/generate_psa_tests.py --list)
|
||||
|
@ -187,7 +187,7 @@ class ShebangIssueTracker(FileIssueTracker):
|
||||
# Allow either /bin/sh, /bin/bash, or /usr/bin/env.
|
||||
# Allow at most one argument (this is a Linux limitation).
|
||||
# For sh and bash, the argument if present must be options.
|
||||
# For env, the argument must be the base name of the interpeter.
|
||||
# For env, the argument must be the base name of the interpreter.
|
||||
_shebang_re = re.compile(rb'^#! ?(?:/bin/(bash|sh)(?: -[^\n ]*)?'
|
||||
rb'|/usr/bin/env ([^\n /]+))$')
|
||||
_extensions = {
|
||||
|
@ -58,8 +58,9 @@ import logging
|
||||
|
||||
# Naming patterns to check against. These are defined outside the NameCheck
|
||||
# class for ease of modification.
|
||||
MACRO_PATTERN = r"^(MBEDTLS|PSA)_[0-9A-Z_]*[0-9A-Z]$"
|
||||
CONSTANTS_PATTERN = MACRO_PATTERN
|
||||
PUBLIC_MACRO_PATTERN = r"^(MBEDTLS|PSA)_[0-9A-Z_]*[0-9A-Z]$"
|
||||
INTERNAL_MACRO_PATTERN = r"^[0-9A-Za-z_]*[0-9A-Z]$"
|
||||
CONSTANTS_PATTERN = PUBLIC_MACRO_PATTERN
|
||||
IDENTIFIER_PATTERN = r"^(mbedtls|psa)_[0-9a-z_]*[0-9a-z]$"
|
||||
|
||||
class Match(): # pylint: disable=too-few-public-methods
|
||||
@ -249,14 +250,17 @@ class CodeParser():
|
||||
.format(str(self.excluded_files))
|
||||
)
|
||||
|
||||
all_macros = self.parse_macros([
|
||||
all_macros = {"public": [], "internal": []}
|
||||
all_macros["public"] = self.parse_macros([
|
||||
"include/mbedtls/*.h",
|
||||
"include/psa/*.h",
|
||||
"library/*.h",
|
||||
"tests/include/test/drivers/*.h",
|
||||
"3rdparty/everest/include/everest/everest.h",
|
||||
"3rdparty/everest/include/everest/x25519.h"
|
||||
])
|
||||
all_macros["internal"] = self.parse_macros([
|
||||
"library/*.h",
|
||||
"tests/include/test/drivers/*.h",
|
||||
])
|
||||
enum_consts = self.parse_enum_consts([
|
||||
"include/mbedtls/*.h",
|
||||
"library/*.h",
|
||||
@ -284,20 +288,25 @@ class CodeParser():
|
||||
|
||||
# Remove identifier macros like mbedtls_printf or mbedtls_calloc
|
||||
identifiers_justname = [x.name for x in identifiers]
|
||||
actual_macros = []
|
||||
for macro in all_macros:
|
||||
if macro.name not in identifiers_justname:
|
||||
actual_macros.append(macro)
|
||||
actual_macros = {"public": [], "internal": []}
|
||||
for scope in actual_macros:
|
||||
for macro in all_macros[scope]:
|
||||
if macro.name not in identifiers_justname:
|
||||
actual_macros[scope].append(macro)
|
||||
|
||||
self.log.debug("Found:")
|
||||
# Aligns the counts on the assumption that none exceeds 4 digits
|
||||
self.log.debug(" {:4} Total Macros".format(len(all_macros)))
|
||||
self.log.debug(" {:4} Non-identifier Macros".format(len(actual_macros)))
|
||||
for scope in actual_macros:
|
||||
self.log.debug(" {:4} Total {} Macros"
|
||||
.format(len(all_macros[scope]), scope))
|
||||
self.log.debug(" {:4} {} Non-identifier Macros"
|
||||
.format(len(actual_macros[scope]), scope))
|
||||
self.log.debug(" {:4} Enum Constants".format(len(enum_consts)))
|
||||
self.log.debug(" {:4} Identifiers".format(len(identifiers)))
|
||||
self.log.debug(" {:4} Exported Symbols".format(len(symbols)))
|
||||
return {
|
||||
"macros": actual_macros,
|
||||
"public_macros": actual_macros["public"],
|
||||
"internal_macros": actual_macros["internal"],
|
||||
"enum_consts": enum_consts,
|
||||
"identifiers": identifiers,
|
||||
"symbols": symbols,
|
||||
@ -741,7 +750,8 @@ class NameChecker():
|
||||
problems += self.check_symbols_declared_in_header()
|
||||
|
||||
pattern_checks = [
|
||||
("macros", MACRO_PATTERN),
|
||||
("public_macros", PUBLIC_MACRO_PATTERN),
|
||||
("internal_macros", INTERNAL_MACRO_PATTERN),
|
||||
("enum_consts", CONSTANTS_PATTERN),
|
||||
("identifiers", IDENTIFIER_PATTERN)
|
||||
]
|
||||
@ -813,7 +823,7 @@ class NameChecker():
|
||||
|
||||
def check_for_typos(self):
|
||||
"""
|
||||
Perform a check that all words in the soure code beginning with MBED are
|
||||
Perform a check that all words in the source code beginning with MBED are
|
||||
either defined as macros, or as enum constants.
|
||||
Assumes parse_names_in_source() was called before this.
|
||||
|
||||
@ -825,7 +835,10 @@ class NameChecker():
|
||||
all_caps_names = {
|
||||
match.name
|
||||
for match
|
||||
in self.parse_result["macros"] + self.parse_result["enum_consts"]}
|
||||
in self.parse_result["public_macros"] +
|
||||
self.parse_result["internal_macros"] +
|
||||
self.parse_result["enum_consts"]
|
||||
}
|
||||
typo_exclusion = re.compile(r"XXX|__|_$|^MBEDTLS_.*CONFIG_FILE$|"
|
||||
r"MBEDTLS_TEST_LIBTESTDRIVER*")
|
||||
|
||||
|
@ -20,18 +20,24 @@
|
||||
# Purpose
|
||||
#
|
||||
# The purpose of this test script is to validate that the library works
|
||||
# with any combination of elliptic curves. To this effect, build the library
|
||||
# and run the test suite with each tested combination of elliptic curves.
|
||||
# when only a single curve is enabled. In particular, this validates that
|
||||
# curve-specific code is guarded by the proper preprocessor conditionals,
|
||||
# both in the library and in tests.
|
||||
#
|
||||
# Testing all 2^n combinations would be too much, so we only test 2*n:
|
||||
# Since this script only tests builds with a single curve, it can't detect
|
||||
# bugs that are only triggered when multiple curves are present. We do
|
||||
# also test in many configurations where all curves are enabled, as well
|
||||
# as a few configurations in configs/*.h with a restricted subset of curves.
|
||||
#
|
||||
# 1. Test with a single curve, for each curve. This validates that the
|
||||
# library works with any curve, and in particular that curve-specific
|
||||
# code is guarded by the proper preprocessor conditionals.
|
||||
# 2. Test with all curves except one, for each curve. This validates that
|
||||
# the test cases have correct dependencies. Testing with a single curve
|
||||
# doesn't validate this for tests that require more than one curve.
|
||||
|
||||
# Here are some known test gaps that could be addressed by testing all
|
||||
# 2^n combinations of support for n curves, which is impractical:
|
||||
# * There could be product bugs when curves A and B are enabled but not C.
|
||||
# For example, a MAX_SIZE calculation that forgets B, where
|
||||
# size(A) < size(B) < size(C).
|
||||
# * For test cases that require three or more curves, validate that they're
|
||||
# not missing dependencies. This is extremely rare. (For test cases that
|
||||
# require curves A and B but are missing a dependency on B, this is
|
||||
# detected in the A-only build.)
|
||||
# Usage: tests/scripts/curves.pl
|
||||
#
|
||||
# This script should be executed from the root of the project directory.
|
||||
@ -115,31 +121,6 @@ for my $curve (@curves) {
|
||||
and abort "Failed to disable $curve\n";
|
||||
}
|
||||
|
||||
system( "cp $config_h.bak $config_h" ) and die "$config_h not restored\n";
|
||||
|
||||
# Test with $curve disabled but the others enabled, for each $curve.
|
||||
for my $curve (@curves) {
|
||||
system( "cp $config_h.bak $config_h" ) and die "$config_h not restored\n";
|
||||
system( "make clean" ) and die;
|
||||
|
||||
# depends on a specific curve. Also, ignore error if it wasn't enabled
|
||||
system( "scripts/config.py unset MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED" );
|
||||
|
||||
print "\n******************************************\n";
|
||||
print "* Testing without curve: $curve\n";
|
||||
print "******************************************\n";
|
||||
$ENV{MBEDTLS_TEST_CONFIGURATION} = "-$curve";
|
||||
|
||||
system( "scripts/config.py unset $curve" )
|
||||
and abort "Failed to disable $curve\n";
|
||||
|
||||
system( "CFLAGS='-Werror -Wall -Wextra' make" )
|
||||
and abort "Failed to build: all but $curve\n";
|
||||
system( "make test" )
|
||||
and abort "Failed test suite: all but $curve\n";
|
||||
|
||||
}
|
||||
|
||||
system( "mv $config_h.bak $config_h" ) and die "$config_h not restored\n";
|
||||
system( "make clean" ) and die;
|
||||
exit 0;
|
||||
|
@ -46,12 +46,12 @@ my $config_h = 'include/mbedtls/mbedtls_config.h';
|
||||
|
||||
# as many SSL options depend on specific hashes,
|
||||
# and SSL is not in the test suites anyways,
|
||||
# disable it to avoid dependcies issues
|
||||
# disable it to avoid dependency issues
|
||||
my $ssl_sed_cmd = 's/^#define \(MBEDTLS_SSL.*\)/\1/p';
|
||||
my @ssl = split( /\s+/, `sed -n -e '$ssl_sed_cmd' $config_h` );
|
||||
|
||||
# Each element of this array holds list of configuration options that
|
||||
# should be tested together. Certain options depend on eachother and
|
||||
# should be tested together. Certain options depend on each other and
|
||||
# separating them would generate invalid configurations.
|
||||
my @hash_configs = (
|
||||
['unset MBEDTLS_MD5_C'],
|
||||
|
238
tests/scripts/generate_bignum_tests.py
Executable file
238
tests/scripts/generate_bignum_tests.py
Executable file
@ -0,0 +1,238 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Generate test data for bignum functions.
|
||||
|
||||
With no arguments, generate all test data. With non-option arguments,
|
||||
generate only the specified files.
|
||||
|
||||
Class structure:
|
||||
|
||||
Child classes of test_generation.BaseTarget (file targets) represent an output
|
||||
file. These indicate where test cases will be written to, for all subclasses of
|
||||
this target. Multiple file targets should not reuse a `target_basename`.
|
||||
|
||||
Each subclass derived from a file target can either be:
|
||||
- A concrete class, representing a test function, which generates test cases.
|
||||
- An abstract class containing shared methods and attributes, not associated
|
||||
with a test function. An example is BignumOperation, which provides
|
||||
common features used for bignum binary operations.
|
||||
|
||||
Both concrete and abstract subclasses can be derived from, to implement
|
||||
additional test cases (see BignumCmp and BignumCmpAbs for examples of deriving
|
||||
from abstract and concrete classes).
|
||||
|
||||
|
||||
Adding test case generation for a function:
|
||||
|
||||
A subclass representing the test function should be added, deriving from a
|
||||
file target such as BignumTarget. This test class must set/implement the
|
||||
following:
|
||||
- test_function: the function name from the associated .function file.
|
||||
- test_name: a descriptive name or brief summary to refer to the test
|
||||
function.
|
||||
- arguments(): a method to generate the list of arguments required for the
|
||||
test_function.
|
||||
- generate_function_test(): a method to generate TestCases for the function.
|
||||
This should create instances of the class with required input data, and
|
||||
call `.create_test_case()` to yield the TestCase.
|
||||
|
||||
Additional details and other attributes/methods are given in the documentation
|
||||
of BaseTarget in test_generation.py.
|
||||
"""
|
||||
|
||||
# Copyright The Mbed TLS Contributors
|
||||
# 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.
|
||||
|
||||
import itertools
|
||||
import sys
|
||||
import typing
|
||||
|
||||
from abc import ABCMeta, abstractmethod
|
||||
from typing import Iterator, List, Tuple, TypeVar
|
||||
|
||||
import scripts_path # pylint: disable=unused-import
|
||||
from mbedtls_dev import test_case
|
||||
from mbedtls_dev import test_generation
|
||||
|
||||
T = TypeVar('T') #pylint: disable=invalid-name
|
||||
|
||||
def hex_to_int(val: str) -> int:
|
||||
return int(val, 16) if val else 0
|
||||
|
||||
def quote_str(val) -> str:
|
||||
return "\"{}\"".format(val)
|
||||
|
||||
def combination_pairs(values: List[T]) -> List[Tuple[T, T]]:
|
||||
"""Return all pair combinations from input values.
|
||||
|
||||
The return value is cast, as older versions of mypy are unable to derive
|
||||
the specific type returned by itertools.combinations_with_replacement.
|
||||
"""
|
||||
return typing.cast(
|
||||
List[Tuple[T, T]],
|
||||
list(itertools.combinations_with_replacement(values, 2))
|
||||
)
|
||||
|
||||
|
||||
class BignumTarget(test_generation.BaseTarget, metaclass=ABCMeta):
|
||||
#pylint: disable=abstract-method
|
||||
"""Target for bignum (mpi) test case generation."""
|
||||
target_basename = 'test_suite_mpi.generated'
|
||||
|
||||
|
||||
class BignumOperation(BignumTarget, metaclass=ABCMeta):
|
||||
"""Common features for bignum binary operations.
|
||||
|
||||
This adds functionality common in binary operation tests. This includes
|
||||
generation of case descriptions, using descriptions of values and symbols
|
||||
to represent the operation or result.
|
||||
|
||||
Attributes:
|
||||
symbol: Symbol used for the operation in case description.
|
||||
input_values: List of values to use as test case inputs. These are
|
||||
combined to produce pairs of values.
|
||||
input_cases: List of tuples containing pairs of test case inputs. This
|
||||
can be used to implement specific pairs of inputs.
|
||||
"""
|
||||
symbol = ""
|
||||
input_values = [
|
||||
"", "0", "7b", "-7b",
|
||||
"0000000000000000123", "-0000000000000000123",
|
||||
"1230000000000000000", "-1230000000000000000"
|
||||
] # type: List[str]
|
||||
input_cases = [] # type: List[Tuple[str, str]]
|
||||
|
||||
def __init__(self, val_a: str, val_b: str) -> None:
|
||||
self.arg_a = val_a
|
||||
self.arg_b = val_b
|
||||
self.int_a = hex_to_int(val_a)
|
||||
self.int_b = hex_to_int(val_b)
|
||||
|
||||
def arguments(self) -> List[str]:
|
||||
return [quote_str(self.arg_a), quote_str(self.arg_b), self.result()]
|
||||
|
||||
def description(self) -> str:
|
||||
"""Generate a description for the test case.
|
||||
|
||||
If not set, case_description uses the form A `symbol` B, where symbol
|
||||
is used to represent the operation. Descriptions of each value are
|
||||
generated to provide some context to the test case.
|
||||
"""
|
||||
if not self.case_description:
|
||||
self.case_description = "{} {} {}".format(
|
||||
self.value_description(self.arg_a),
|
||||
self.symbol,
|
||||
self.value_description(self.arg_b)
|
||||
)
|
||||
return super().description()
|
||||
|
||||
@abstractmethod
|
||||
def result(self) -> str:
|
||||
"""Get the result of the operation.
|
||||
|
||||
This could be calculated during initialization and stored as `_result`
|
||||
and then returned, or calculated when the method is called.
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
@staticmethod
|
||||
def value_description(val) -> str:
|
||||
"""Generate a description of the argument val.
|
||||
|
||||
This produces a simple description of the value, which is used in test
|
||||
case naming to add context.
|
||||
"""
|
||||
if val == "":
|
||||
return "0 (null)"
|
||||
if val == "0":
|
||||
return "0 (1 limb)"
|
||||
|
||||
if val[0] == "-":
|
||||
tmp = "negative"
|
||||
val = val[1:]
|
||||
else:
|
||||
tmp = "positive"
|
||||
if val[0] == "0":
|
||||
tmp += " with leading zero limb"
|
||||
elif len(val) > 10:
|
||||
tmp = "large " + tmp
|
||||
return tmp
|
||||
|
||||
@classmethod
|
||||
def get_value_pairs(cls) -> Iterator[Tuple[str, str]]:
|
||||
"""Generator to yield pairs of inputs.
|
||||
|
||||
Combinations are first generated from all input values, and then
|
||||
specific cases provided.
|
||||
"""
|
||||
yield from combination_pairs(cls.input_values)
|
||||
yield from cls.input_cases
|
||||
|
||||
@classmethod
|
||||
def generate_function_tests(cls) -> Iterator[test_case.TestCase]:
|
||||
for a_value, b_value in cls.get_value_pairs():
|
||||
cur_op = cls(a_value, b_value)
|
||||
yield cur_op.create_test_case()
|
||||
|
||||
|
||||
class BignumCmp(BignumOperation):
|
||||
"""Test cases for bignum value comparison."""
|
||||
count = 0
|
||||
test_function = "mbedtls_mpi_cmp_mpi"
|
||||
test_name = "MPI compare"
|
||||
input_cases = [
|
||||
("-2", "-3"),
|
||||
("-2", "-2"),
|
||||
("2b4", "2b5"),
|
||||
("2b5", "2b6")
|
||||
]
|
||||
|
||||
def __init__(self, val_a, val_b) -> None:
|
||||
super().__init__(val_a, val_b)
|
||||
self._result = int(self.int_a > self.int_b) - int(self.int_a < self.int_b)
|
||||
self.symbol = ["<", "==", ">"][self._result + 1]
|
||||
|
||||
def result(self) -> str:
|
||||
return str(self._result)
|
||||
|
||||
|
||||
class BignumCmpAbs(BignumCmp):
|
||||
"""Test cases for absolute bignum value comparison."""
|
||||
count = 0
|
||||
test_function = "mbedtls_mpi_cmp_abs"
|
||||
test_name = "MPI compare (abs)"
|
||||
|
||||
def __init__(self, val_a, val_b) -> None:
|
||||
super().__init__(val_a.strip("-"), val_b.strip("-"))
|
||||
|
||||
|
||||
class BignumAdd(BignumOperation):
|
||||
"""Test cases for bignum value addition."""
|
||||
count = 0
|
||||
symbol = "+"
|
||||
test_function = "mbedtls_mpi_add_mpi"
|
||||
test_name = "MPI add"
|
||||
input_cases = combination_pairs(
|
||||
[
|
||||
"1c67967269c6", "9cde3",
|
||||
"-1c67967269c6", "-9cde3",
|
||||
]
|
||||
)
|
||||
|
||||
def result(self) -> str:
|
||||
return quote_str("{:x}".format(self.int_a + self.int_b))
|
||||
|
||||
if __name__ == '__main__':
|
||||
# Use the section of the docstring relevant to the CLI as description
|
||||
test_generation.main(sys.argv[1:], "\n".join(__doc__.splitlines()[:4]))
|
@ -20,21 +20,17 @@ generate only the specified files.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import posixpath
|
||||
import enum
|
||||
import re
|
||||
import sys
|
||||
from typing import Callable, Dict, FrozenSet, Iterable, Iterator, List, Optional, TypeVar
|
||||
from typing import Callable, Dict, FrozenSet, Iterable, Iterator, List, Optional
|
||||
|
||||
import scripts_path # pylint: disable=unused-import
|
||||
from mbedtls_dev import build_tree
|
||||
from mbedtls_dev import crypto_knowledge
|
||||
from mbedtls_dev import macro_collector
|
||||
from mbedtls_dev import psa_storage
|
||||
from mbedtls_dev import test_case
|
||||
|
||||
T = TypeVar('T') #pylint: disable=invalid-name
|
||||
from mbedtls_dev import test_generation
|
||||
|
||||
|
||||
def psa_want_symbol(name: str) -> str:
|
||||
@ -144,7 +140,7 @@ def test_case_for_key_type_not_supported(
|
||||
"""
|
||||
hack_dependencies_not_implemented(dependencies)
|
||||
tc = test_case.TestCase()
|
||||
short_key_type = re.sub(r'PSA_(KEY_TYPE|ECC_FAMILY)_', r'', key_type)
|
||||
short_key_type = crypto_knowledge.short_expression(key_type)
|
||||
adverb = 'not' if dependencies else 'never'
|
||||
if param_descr:
|
||||
adverb = param_descr + ' ' + adverb
|
||||
@ -164,6 +160,7 @@ class NotSupported:
|
||||
ALWAYS_SUPPORTED = frozenset([
|
||||
'PSA_KEY_TYPE_DERIVE',
|
||||
'PSA_KEY_TYPE_RAW_DATA',
|
||||
'PSA_KEY_TYPE_HMAC'
|
||||
])
|
||||
def test_cases_for_key_type_not_supported(
|
||||
self,
|
||||
@ -205,7 +202,7 @@ class NotSupported:
|
||||
continue
|
||||
# For public key we expect that key generation fails with
|
||||
# INVALID_ARGUMENT. It is handled by KeyGenerate class.
|
||||
if not kt.name.endswith('_PUBLIC_KEY'):
|
||||
if not kt.is_public():
|
||||
yield test_case_for_key_type_not_supported(
|
||||
'generate', kt.expression, bits,
|
||||
finish_family_dependencies(generate_dependencies, bits),
|
||||
@ -242,7 +239,7 @@ def test_case_for_key_generation(
|
||||
"""
|
||||
hack_dependencies_not_implemented(dependencies)
|
||||
tc = test_case.TestCase()
|
||||
short_key_type = re.sub(r'PSA_(KEY_TYPE|ECC_FAMILY)_', r'', key_type)
|
||||
short_key_type = crypto_knowledge.short_expression(key_type)
|
||||
tc.set_description('PSA {} {}-bit'
|
||||
.format(short_key_type, bits))
|
||||
tc.set_dependencies(dependencies)
|
||||
@ -305,6 +302,145 @@ class KeyGenerate:
|
||||
kt = crypto_knowledge.KeyType(constr, [curve_family])
|
||||
yield from self.test_cases_for_key_type_key_generation(kt)
|
||||
|
||||
class OpFail:
|
||||
"""Generate test cases for operations that must fail."""
|
||||
#pylint: disable=too-few-public-methods
|
||||
|
||||
class Reason(enum.Enum):
|
||||
NOT_SUPPORTED = 0
|
||||
INVALID = 1
|
||||
INCOMPATIBLE = 2
|
||||
PUBLIC = 3
|
||||
|
||||
def __init__(self, info: Information) -> None:
|
||||
self.constructors = info.constructors
|
||||
key_type_expressions = self.constructors.generate_expressions(
|
||||
sorted(self.constructors.key_types)
|
||||
)
|
||||
self.key_types = [crypto_knowledge.KeyType(kt_expr)
|
||||
for kt_expr in key_type_expressions]
|
||||
|
||||
def make_test_case(
|
||||
self,
|
||||
alg: crypto_knowledge.Algorithm,
|
||||
category: crypto_knowledge.AlgorithmCategory,
|
||||
reason: 'Reason',
|
||||
kt: Optional[crypto_knowledge.KeyType] = None,
|
||||
not_deps: FrozenSet[str] = frozenset(),
|
||||
) -> test_case.TestCase:
|
||||
"""Construct a failure test case for a one-key or keyless operation."""
|
||||
#pylint: disable=too-many-arguments,too-many-locals
|
||||
tc = test_case.TestCase()
|
||||
pretty_alg = alg.short_expression()
|
||||
if reason == self.Reason.NOT_SUPPORTED:
|
||||
short_deps = [re.sub(r'PSA_WANT_ALG_', r'', dep)
|
||||
for dep in not_deps]
|
||||
pretty_reason = '!' + '&'.join(sorted(short_deps))
|
||||
else:
|
||||
pretty_reason = reason.name.lower()
|
||||
if kt:
|
||||
key_type = kt.expression
|
||||
pretty_type = kt.short_expression()
|
||||
else:
|
||||
key_type = ''
|
||||
pretty_type = ''
|
||||
tc.set_description('PSA {} {}: {}{}'
|
||||
.format(category.name.lower(),
|
||||
pretty_alg,
|
||||
pretty_reason,
|
||||
' with ' + pretty_type if pretty_type else ''))
|
||||
dependencies = automatic_dependencies(alg.base_expression, key_type)
|
||||
for i, dep in enumerate(dependencies):
|
||||
if dep in not_deps:
|
||||
dependencies[i] = '!' + dep
|
||||
tc.set_dependencies(dependencies)
|
||||
tc.set_function(category.name.lower() + '_fail')
|
||||
arguments = []
|
||||
if kt:
|
||||
key_material = kt.key_material(kt.sizes_to_test()[0])
|
||||
arguments += [key_type, test_case.hex_string(key_material)]
|
||||
arguments.append(alg.expression)
|
||||
if category.is_asymmetric():
|
||||
arguments.append('1' if reason == self.Reason.PUBLIC else '0')
|
||||
error = ('NOT_SUPPORTED' if reason == self.Reason.NOT_SUPPORTED else
|
||||
'INVALID_ARGUMENT')
|
||||
arguments.append('PSA_ERROR_' + error)
|
||||
tc.set_arguments(arguments)
|
||||
return tc
|
||||
|
||||
def no_key_test_cases(
|
||||
self,
|
||||
alg: crypto_knowledge.Algorithm,
|
||||
category: crypto_knowledge.AlgorithmCategory,
|
||||
) -> Iterator[test_case.TestCase]:
|
||||
"""Generate failure test cases for keyless operations with the specified algorithm."""
|
||||
if alg.can_do(category):
|
||||
# Compatible operation, unsupported algorithm
|
||||
for dep in automatic_dependencies(alg.base_expression):
|
||||
yield self.make_test_case(alg, category,
|
||||
self.Reason.NOT_SUPPORTED,
|
||||
not_deps=frozenset([dep]))
|
||||
else:
|
||||
# Incompatible operation, supported algorithm
|
||||
yield self.make_test_case(alg, category, self.Reason.INVALID)
|
||||
|
||||
def one_key_test_cases(
|
||||
self,
|
||||
alg: crypto_knowledge.Algorithm,
|
||||
category: crypto_knowledge.AlgorithmCategory,
|
||||
) -> Iterator[test_case.TestCase]:
|
||||
"""Generate failure test cases for one-key operations with the specified algorithm."""
|
||||
for kt in self.key_types:
|
||||
key_is_compatible = kt.can_do(alg)
|
||||
if key_is_compatible and alg.can_do(category):
|
||||
# Compatible key and operation, unsupported algorithm
|
||||
for dep in automatic_dependencies(alg.base_expression):
|
||||
yield self.make_test_case(alg, category,
|
||||
self.Reason.NOT_SUPPORTED,
|
||||
kt=kt, not_deps=frozenset([dep]))
|
||||
# Public key for a private-key operation
|
||||
if category.is_asymmetric() and kt.is_public():
|
||||
yield self.make_test_case(alg, category,
|
||||
self.Reason.PUBLIC,
|
||||
kt=kt)
|
||||
elif key_is_compatible:
|
||||
# Compatible key, incompatible operation, supported algorithm
|
||||
yield self.make_test_case(alg, category,
|
||||
self.Reason.INVALID,
|
||||
kt=kt)
|
||||
elif alg.can_do(category):
|
||||
# Incompatible key, compatible operation, supported algorithm
|
||||
yield self.make_test_case(alg, category,
|
||||
self.Reason.INCOMPATIBLE,
|
||||
kt=kt)
|
||||
else:
|
||||
# Incompatible key and operation. Don't test cases where
|
||||
# multiple things are wrong, to keep the number of test
|
||||
# cases reasonable.
|
||||
pass
|
||||
|
||||
def test_cases_for_algorithm(
|
||||
self,
|
||||
alg: crypto_knowledge.Algorithm,
|
||||
) -> Iterator[test_case.TestCase]:
|
||||
"""Generate operation failure test cases for the specified algorithm."""
|
||||
for category in crypto_knowledge.AlgorithmCategory:
|
||||
if category == crypto_knowledge.AlgorithmCategory.PAKE:
|
||||
# PAKE operations are not implemented yet
|
||||
pass
|
||||
elif category.requires_key():
|
||||
yield from self.one_key_test_cases(alg, category)
|
||||
else:
|
||||
yield from self.no_key_test_cases(alg, category)
|
||||
|
||||
def all_test_cases(self) -> Iterator[test_case.TestCase]:
|
||||
"""Generate all test cases for operations that must fail."""
|
||||
algorithms = sorted(self.constructors.algorithms)
|
||||
for expr in self.constructors.generate_expressions(algorithms):
|
||||
alg = crypto_knowledge.Algorithm(expr)
|
||||
yield from self.test_cases_for_algorithm(alg)
|
||||
|
||||
|
||||
class StorageKey(psa_storage.Key):
|
||||
"""Representation of a key for storage format testing."""
|
||||
|
||||
@ -316,7 +452,7 @@ class StorageKey(psa_storage.Key):
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
usage: str,
|
||||
usage: Iterable[str],
|
||||
without_implicit_usage: Optional[bool] = False,
|
||||
**kwargs
|
||||
) -> None:
|
||||
@ -325,13 +461,16 @@ class StorageKey(psa_storage.Key):
|
||||
* `usage` : The usage flags used for the key.
|
||||
* `without_implicit_usage`: Flag to defide to apply the usage extension
|
||||
"""
|
||||
super().__init__(usage=usage, **kwargs)
|
||||
|
||||
usage_flags = set(usage)
|
||||
if not without_implicit_usage:
|
||||
for flag, implicit in self.IMPLICIT_USAGE_FLAGS.items():
|
||||
if self.usage.value() & psa_storage.Expr(flag).value() and \
|
||||
self.usage.value() & psa_storage.Expr(implicit).value() == 0:
|
||||
self.usage = psa_storage.Expr(self.usage.string + ' | ' + implicit)
|
||||
for flag in sorted(usage_flags):
|
||||
if flag in self.IMPLICIT_USAGE_FLAGS:
|
||||
usage_flags.add(self.IMPLICIT_USAGE_FLAGS[flag])
|
||||
if usage_flags:
|
||||
usage_expression = ' | '.join(sorted(usage_flags))
|
||||
else:
|
||||
usage_expression = '0'
|
||||
super().__init__(usage=usage_expression, **kwargs)
|
||||
|
||||
class StorageTestData(StorageKey):
|
||||
"""Representation of test case data for storage format testing."""
|
||||
@ -339,7 +478,7 @@ class StorageTestData(StorageKey):
|
||||
def __init__(
|
||||
self,
|
||||
description: str,
|
||||
expected_usage: Optional[str] = None,
|
||||
expected_usage: Optional[List[str]] = None,
|
||||
**kwargs
|
||||
) -> None:
|
||||
"""Prepare to generate test data
|
||||
@ -351,7 +490,12 @@ class StorageTestData(StorageKey):
|
||||
"""
|
||||
super().__init__(**kwargs)
|
||||
self.description = description #type: str
|
||||
self.expected_usage = expected_usage if expected_usage else self.usage.string #type: str
|
||||
if expected_usage is None:
|
||||
self.expected_usage = self.usage #type: psa_storage.Expr
|
||||
elif expected_usage:
|
||||
self.expected_usage = psa_storage.Expr(' | '.join(expected_usage))
|
||||
else:
|
||||
self.expected_usage = psa_storage.Expr(0)
|
||||
|
||||
class StorageFormat:
|
||||
"""Storage format stability test cases."""
|
||||
@ -370,6 +514,47 @@ class StorageFormat:
|
||||
self.version = version #type: int
|
||||
self.forward = forward #type: bool
|
||||
|
||||
RSA_OAEP_RE = re.compile(r'PSA_ALG_RSA_OAEP\((.*)\)\Z')
|
||||
BRAINPOOL_RE = re.compile(r'PSA_KEY_TYPE_\w+\(PSA_ECC_FAMILY_BRAINPOOL_\w+\)\Z')
|
||||
@classmethod
|
||||
def exercise_key_with_algorithm(
|
||||
cls,
|
||||
key_type: psa_storage.Expr, bits: int,
|
||||
alg: psa_storage.Expr
|
||||
) -> bool:
|
||||
"""Whether to the given key with the given algorithm.
|
||||
|
||||
Normally only the type and algorithm matter for compatibility, and
|
||||
this is handled in crypto_knowledge.KeyType.can_do(). This function
|
||||
exists to detect exceptional cases. Exceptional cases detected here
|
||||
are not tested in OpFail and should therefore have manually written
|
||||
test cases.
|
||||
"""
|
||||
# Some test keys have the RAW_DATA type and attributes that don't
|
||||
# necessarily make sense. We do this to validate numerical
|
||||
# encodings of the attributes.
|
||||
# Raw data keys have no useful exercise anyway so there is no
|
||||
# loss of test coverage.
|
||||
if key_type.string == 'PSA_KEY_TYPE_RAW_DATA':
|
||||
return False
|
||||
# OAEP requires room for two hashes plus wrapping
|
||||
m = cls.RSA_OAEP_RE.match(alg.string)
|
||||
if m:
|
||||
hash_alg = m.group(1)
|
||||
hash_length = crypto_knowledge.Algorithm.hash_length(hash_alg)
|
||||
key_length = (bits + 7) // 8
|
||||
# Leave enough room for at least one byte of plaintext
|
||||
return key_length > 2 * hash_length + 2
|
||||
# There's nothing wrong with ECC keys on Brainpool curves,
|
||||
# but operations with them are very slow. So we only exercise them
|
||||
# with a single algorithm, not with all possible hashes. We do
|
||||
# exercise other curves with all algorithms so test coverage is
|
||||
# perfectly adequate like this.
|
||||
m = cls.BRAINPOOL_RE.match(key_type.string)
|
||||
if m and alg.string != 'PSA_ALG_ECDSA_ANY':
|
||||
return False
|
||||
return True
|
||||
|
||||
def make_test_case(self, key: StorageTestData) -> test_case.TestCase:
|
||||
"""Construct a storage format test case for the given key.
|
||||
|
||||
@ -381,10 +566,10 @@ class StorageFormat:
|
||||
"""
|
||||
verb = 'save' if self.forward else 'read'
|
||||
tc = test_case.TestCase()
|
||||
tc.set_description('PSA storage {}: {}'.format(verb, key.description))
|
||||
tc.set_description(verb + ' ' + key.description)
|
||||
dependencies = automatic_dependencies(
|
||||
key.lifetime.string, key.type.string,
|
||||
key.expected_usage, key.alg.string, key.alg2.string,
|
||||
key.alg.string, key.alg2.string,
|
||||
)
|
||||
dependencies = finish_family_dependencies(dependencies, key.bits)
|
||||
tc.set_dependencies(dependencies)
|
||||
@ -393,19 +578,15 @@ class StorageFormat:
|
||||
extra_arguments = []
|
||||
else:
|
||||
flags = []
|
||||
# Some test keys have the RAW_DATA type and attributes that don't
|
||||
# necessarily make sense. We do this to validate numerical
|
||||
# encodings of the attributes.
|
||||
# Raw data keys have no useful exercise anyway so there is no
|
||||
# loss of test coverage.
|
||||
if key.type.string != 'PSA_KEY_TYPE_RAW_DATA':
|
||||
if self.exercise_key_with_algorithm(key.type, key.bits, key.alg):
|
||||
flags.append('TEST_FLAG_EXERCISE')
|
||||
if 'READ_ONLY' in key.lifetime.string:
|
||||
flags.append('TEST_FLAG_READ_ONLY')
|
||||
extra_arguments = [' | '.join(flags) if flags else '0']
|
||||
tc.set_arguments([key.lifetime.string,
|
||||
key.type.string, str(key.bits),
|
||||
key.expected_usage, key.alg.string, key.alg2.string,
|
||||
key.expected_usage.string,
|
||||
key.alg.string, key.alg2.string,
|
||||
'"' + key.material.hex() + '"',
|
||||
'"' + key.hex() + '"',
|
||||
*extra_arguments])
|
||||
@ -419,12 +600,12 @@ class StorageFormat:
|
||||
short = lifetime
|
||||
short = re.sub(r'PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION',
|
||||
r'', short)
|
||||
short = re.sub(r'PSA_KEY_[A-Z]+_', r'', short)
|
||||
short = crypto_knowledge.short_expression(short)
|
||||
description = 'lifetime: ' + short
|
||||
key = StorageTestData(version=self.version,
|
||||
id=1, lifetime=lifetime,
|
||||
type='PSA_KEY_TYPE_RAW_DATA', bits=8,
|
||||
usage='PSA_KEY_USAGE_EXPORT', alg=0, alg2=0,
|
||||
usage=['PSA_KEY_USAGE_EXPORT'], alg=0, alg2=0,
|
||||
material=b'L',
|
||||
description=description)
|
||||
return key
|
||||
@ -443,99 +624,112 @@ class StorageFormat:
|
||||
continue
|
||||
yield self.key_for_lifetime(lifetime)
|
||||
|
||||
def keys_for_usage_flags(
|
||||
def key_for_usage_flags(
|
||||
self,
|
||||
usage_flags: List[str],
|
||||
short: Optional[str] = None,
|
||||
test_implicit_usage: Optional[bool] = False
|
||||
) -> Iterator[StorageTestData]:
|
||||
test_implicit_usage: Optional[bool] = True
|
||||
) -> StorageTestData:
|
||||
"""Construct a test key for the given key usage."""
|
||||
usage = ' | '.join(usage_flags) if usage_flags else '0'
|
||||
if short is None:
|
||||
short = re.sub(r'\bPSA_KEY_USAGE_', r'', usage)
|
||||
extra_desc = ' with implication' if test_implicit_usage else ''
|
||||
description = 'usage' + extra_desc + ': ' + short
|
||||
extra_desc = ' without implication' if test_implicit_usage else ''
|
||||
description = 'usage' + extra_desc + ': '
|
||||
key1 = StorageTestData(version=self.version,
|
||||
id=1, lifetime=0x00000001,
|
||||
type='PSA_KEY_TYPE_RAW_DATA', bits=8,
|
||||
expected_usage=usage,
|
||||
usage=usage, alg=0, alg2=0,
|
||||
expected_usage=usage_flags,
|
||||
without_implicit_usage=not test_implicit_usage,
|
||||
usage=usage_flags, alg=0, alg2=0,
|
||||
material=b'K',
|
||||
description=description)
|
||||
yield key1
|
||||
|
||||
if test_implicit_usage:
|
||||
description = 'usage without implication' + ': ' + short
|
||||
key2 = StorageTestData(version=self.version,
|
||||
id=1, lifetime=0x00000001,
|
||||
type='PSA_KEY_TYPE_RAW_DATA', bits=8,
|
||||
without_implicit_usage=True,
|
||||
usage=usage, alg=0, alg2=0,
|
||||
material=b'K',
|
||||
description=description)
|
||||
yield key2
|
||||
if short is None:
|
||||
usage_expr = key1.expected_usage.string
|
||||
key1.description += crypto_knowledge.short_expression(usage_expr)
|
||||
else:
|
||||
key1.description += short
|
||||
return key1
|
||||
|
||||
def generate_keys_for_usage_flags(self, **kwargs) -> Iterator[StorageTestData]:
|
||||
"""Generate test keys covering usage flags."""
|
||||
known_flags = sorted(self.constructors.key_usage_flags)
|
||||
yield from self.keys_for_usage_flags(['0'], **kwargs)
|
||||
yield self.key_for_usage_flags(['0'], **kwargs)
|
||||
for usage_flag in known_flags:
|
||||
yield from self.keys_for_usage_flags([usage_flag], **kwargs)
|
||||
yield self.key_for_usage_flags([usage_flag], **kwargs)
|
||||
for flag1, flag2 in zip(known_flags,
|
||||
known_flags[1:] + [known_flags[0]]):
|
||||
yield from self.keys_for_usage_flags([flag1, flag2], **kwargs)
|
||||
yield self.key_for_usage_flags([flag1, flag2], **kwargs)
|
||||
|
||||
def generate_key_for_all_usage_flags(self) -> Iterator[StorageTestData]:
|
||||
known_flags = sorted(self.constructors.key_usage_flags)
|
||||
yield from self.keys_for_usage_flags(known_flags, short='all known')
|
||||
yield self.key_for_usage_flags(known_flags, short='all known')
|
||||
|
||||
def all_keys_for_usage_flags(self) -> Iterator[StorageTestData]:
|
||||
yield from self.generate_keys_for_usage_flags()
|
||||
yield from self.generate_key_for_all_usage_flags()
|
||||
|
||||
def key_for_type_and_alg(
|
||||
self,
|
||||
kt: crypto_knowledge.KeyType,
|
||||
bits: int,
|
||||
alg: Optional[crypto_knowledge.Algorithm] = None,
|
||||
) -> StorageTestData:
|
||||
"""Construct a test key of the given type.
|
||||
|
||||
If alg is not None, this key allows it.
|
||||
"""
|
||||
usage_flags = ['PSA_KEY_USAGE_EXPORT']
|
||||
alg1 = 0 #type: psa_storage.Exprable
|
||||
alg2 = 0
|
||||
if alg is not None:
|
||||
alg1 = alg.expression
|
||||
usage_flags += alg.usage_flags(public=kt.is_public())
|
||||
key_material = kt.key_material(bits)
|
||||
description = 'type: {} {}-bit'.format(kt.short_expression(1), bits)
|
||||
if alg is not None:
|
||||
description += ', ' + alg.short_expression(1)
|
||||
key = StorageTestData(version=self.version,
|
||||
id=1, lifetime=0x00000001,
|
||||
type=kt.expression, bits=bits,
|
||||
usage=usage_flags, alg=alg1, alg2=alg2,
|
||||
material=key_material,
|
||||
description=description)
|
||||
return key
|
||||
|
||||
def keys_for_type(
|
||||
self,
|
||||
key_type: str,
|
||||
params: Optional[Iterable[str]] = None
|
||||
all_algorithms: List[crypto_knowledge.Algorithm],
|
||||
) -> Iterator[StorageTestData]:
|
||||
"""Generate test keys for the given key type.
|
||||
|
||||
For key types that depend on a parameter (e.g. elliptic curve family),
|
||||
`param` is the parameter to pass to the constructor. Only a single
|
||||
parameter is supported.
|
||||
"""
|
||||
kt = crypto_knowledge.KeyType(key_type, params)
|
||||
"""Generate test keys for the given key type."""
|
||||
kt = crypto_knowledge.KeyType(key_type)
|
||||
for bits in kt.sizes_to_test():
|
||||
usage_flags = 'PSA_KEY_USAGE_EXPORT'
|
||||
alg = 0
|
||||
alg2 = 0
|
||||
key_material = kt.key_material(bits)
|
||||
short_expression = re.sub(r'\bPSA_(?:KEY_TYPE|ECC_FAMILY)_',
|
||||
r'',
|
||||
kt.expression)
|
||||
description = 'type: {} {}-bit'.format(short_expression, bits)
|
||||
key = StorageTestData(version=self.version,
|
||||
id=1, lifetime=0x00000001,
|
||||
type=kt.expression, bits=bits,
|
||||
usage=usage_flags, alg=alg, alg2=alg2,
|
||||
material=key_material,
|
||||
description=description)
|
||||
yield key
|
||||
# Test a non-exercisable key, as well as exercisable keys for
|
||||
# each compatible algorithm.
|
||||
# To do: test reading a key from storage with an incompatible
|
||||
# or unsupported algorithm.
|
||||
yield self.key_for_type_and_alg(kt, bits)
|
||||
compatible_algorithms = [alg for alg in all_algorithms
|
||||
if kt.can_do(alg)]
|
||||
for alg in compatible_algorithms:
|
||||
yield self.key_for_type_and_alg(kt, bits, alg)
|
||||
|
||||
def all_keys_for_types(self) -> Iterator[StorageTestData]:
|
||||
"""Generate test keys covering key types and their representations."""
|
||||
key_types = sorted(self.constructors.key_types)
|
||||
all_algorithms = [crypto_knowledge.Algorithm(alg)
|
||||
for alg in self.constructors.generate_expressions(
|
||||
sorted(self.constructors.algorithms)
|
||||
)]
|
||||
for key_type in self.constructors.generate_expressions(key_types):
|
||||
yield from self.keys_for_type(key_type)
|
||||
yield from self.keys_for_type(key_type, all_algorithms)
|
||||
|
||||
def keys_for_algorithm(self, alg: str) -> Iterator[StorageTestData]:
|
||||
"""Generate test keys for the specified algorithm."""
|
||||
# For now, we don't have information on the compatibility of key
|
||||
# types and algorithms. So we just test the encoding of algorithms,
|
||||
# and not that operations can be performed with them.
|
||||
descr = re.sub(r'PSA_ALG_', r'', alg)
|
||||
descr = re.sub(r',', r', ', re.sub(r' +', r'', descr))
|
||||
usage = 'PSA_KEY_USAGE_EXPORT'
|
||||
"""Generate test keys for the encoding of the specified algorithm."""
|
||||
# These test cases only validate the encoding of algorithms, not
|
||||
# whether the key read from storage is suitable for an operation.
|
||||
# `keys_for_types` generate read tests with an algorithm and a
|
||||
# compatible key.
|
||||
descr = crypto_knowledge.short_expression(alg, 1)
|
||||
usage = ['PSA_KEY_USAGE_EXPORT']
|
||||
key1 = StorageTestData(version=self.version,
|
||||
id=1, lifetime=0x00000001,
|
||||
type='PSA_KEY_TYPE_RAW_DATA', bits=8,
|
||||
@ -593,8 +787,8 @@ class StorageFormatV0(StorageFormat):
|
||||
|
||||
def all_keys_for_usage_flags(self) -> Iterator[StorageTestData]:
|
||||
"""Generate test keys covering usage flags."""
|
||||
yield from self.generate_keys_for_usage_flags(test_implicit_usage=True)
|
||||
yield from self.generate_key_for_all_usage_flags()
|
||||
yield from super().all_keys_for_usage_flags()
|
||||
yield from self.generate_keys_for_usage_flags(test_implicit_usage=False)
|
||||
|
||||
def keys_for_implicit_usage(
|
||||
self,
|
||||
@ -608,17 +802,14 @@ class StorageFormatV0(StorageFormat):
|
||||
"""
|
||||
bits = key_type.sizes_to_test()[0]
|
||||
implicit_usage = StorageKey.IMPLICIT_USAGE_FLAGS[implyer_usage]
|
||||
usage_flags = 'PSA_KEY_USAGE_EXPORT'
|
||||
material_usage_flags = usage_flags + ' | ' + implyer_usage
|
||||
expected_usage_flags = material_usage_flags + ' | ' + implicit_usage
|
||||
usage_flags = ['PSA_KEY_USAGE_EXPORT']
|
||||
material_usage_flags = usage_flags + [implyer_usage]
|
||||
expected_usage_flags = material_usage_flags + [implicit_usage]
|
||||
alg2 = 0
|
||||
key_material = key_type.key_material(bits)
|
||||
usage_expression = re.sub(r'PSA_KEY_USAGE_', r'', implyer_usage)
|
||||
alg_expression = re.sub(r'PSA_ALG_', r'', alg)
|
||||
alg_expression = re.sub(r',', r', ', re.sub(r' +', r'', alg_expression))
|
||||
key_type_expression = re.sub(r'\bPSA_(?:KEY_TYPE|ECC_FAMILY)_',
|
||||
r'',
|
||||
key_type.expression)
|
||||
usage_expression = crypto_knowledge.short_expression(implyer_usage, 1)
|
||||
alg_expression = crypto_knowledge.short_expression(alg, 1)
|
||||
key_type_expression = key_type.short_expression(1)
|
||||
description = 'implied by {}: {} {} {}-bit'.format(
|
||||
usage_expression, alg_expression, key_type_expression, bits)
|
||||
key = StorageTestData(version=self.version,
|
||||
@ -635,7 +826,7 @@ class StorageFormatV0(StorageFormat):
|
||||
def gather_key_types_for_sign_alg(self) -> Dict[str, List[str]]:
|
||||
# pylint: disable=too-many-locals
|
||||
"""Match possible key types for sign algorithms."""
|
||||
# To create a valid combinaton both the algorithms and key types
|
||||
# To create a valid combination both the algorithms and key types
|
||||
# must be filtered. Pair them with keywords created from its names.
|
||||
incompatible_alg_keyword = frozenset(['RAW', 'ANY', 'PURE'])
|
||||
incompatible_key_type_keywords = frozenset(['MONTGOMERY'])
|
||||
@ -659,7 +850,7 @@ class StorageFormatV0(StorageFormat):
|
||||
if re.match(pattern, keyword):
|
||||
alg_keywords.remove(keyword)
|
||||
alg_keywords.add(replace)
|
||||
# Filter out incompatible algortihms
|
||||
# Filter out incompatible algorithms
|
||||
if not alg_keywords.isdisjoint(incompatible_alg_keyword):
|
||||
continue
|
||||
|
||||
@ -667,7 +858,7 @@ class StorageFormatV0(StorageFormat):
|
||||
# Generate keywords from the of the key type
|
||||
key_type_keywords = set(key_type.translate(translation_table).split(sep='_')[3:])
|
||||
|
||||
# Remove ambigious keywords
|
||||
# Remove ambiguous keywords
|
||||
for keyword1, keyword2 in exclusive_keywords.items():
|
||||
if keyword1 in key_type_keywords:
|
||||
key_type_keywords.remove(keyword2)
|
||||
@ -684,7 +875,7 @@ class StorageFormatV0(StorageFormat):
|
||||
"""Generate test keys for usage flag extensions."""
|
||||
# Generate a key type and algorithm pair for each extendable usage
|
||||
# flag to generate a valid key for exercising. The key is generated
|
||||
# without usage extension to check the extension compatiblity.
|
||||
# without usage extension to check the extension compatibility.
|
||||
alg_with_keys = self.gather_key_types_for_sign_alg()
|
||||
|
||||
for usage in sorted(StorageKey.IMPLICIT_USAGE_FLAGS, key=str):
|
||||
@ -692,90 +883,38 @@ class StorageFormatV0(StorageFormat):
|
||||
for key_type in sorted(alg_with_keys[alg]):
|
||||
# The key types must be filtered to fit the specific usage flag.
|
||||
kt = crypto_knowledge.KeyType(key_type)
|
||||
if kt.is_valid_for_signature(usage):
|
||||
yield self.keys_for_implicit_usage(usage, alg, kt)
|
||||
if kt.is_public() and '_SIGN_' in usage:
|
||||
# Can't sign with a public key
|
||||
continue
|
||||
yield self.keys_for_implicit_usage(usage, alg, kt)
|
||||
|
||||
def generate_all_keys(self) -> Iterator[StorageTestData]:
|
||||
yield from super().generate_all_keys()
|
||||
yield from self.all_keys_for_implicit_usage()
|
||||
|
||||
class TestGenerator:
|
||||
"""Generate test data."""
|
||||
|
||||
def __init__(self, options) -> None:
|
||||
self.test_suite_directory = self.get_option(options, 'directory',
|
||||
'tests/suites')
|
||||
self.info = Information()
|
||||
|
||||
@staticmethod
|
||||
def get_option(options, name: str, default: T) -> T:
|
||||
value = getattr(options, name, None)
|
||||
return default if value is None else value
|
||||
|
||||
def filename_for(self, basename: str) -> str:
|
||||
"""The location of the data file with the specified base name."""
|
||||
return posixpath.join(self.test_suite_directory, basename + '.data')
|
||||
|
||||
def write_test_data_file(self, basename: str,
|
||||
test_cases: Iterable[test_case.TestCase]) -> None:
|
||||
"""Write the test cases to a .data file.
|
||||
|
||||
The output file is ``basename + '.data'`` in the test suite directory.
|
||||
"""
|
||||
filename = self.filename_for(basename)
|
||||
test_case.write_data_file(filename, test_cases)
|
||||
|
||||
# Note that targets whose name containns 'test_format' have their content
|
||||
class PSATestGenerator(test_generation.TestGenerator):
|
||||
"""Test generator subclass including PSA targets and info."""
|
||||
# Note that targets whose names contain 'test_format' have their content
|
||||
# validated by `abi_check.py`.
|
||||
TARGETS = {
|
||||
targets = {
|
||||
'test_suite_psa_crypto_generate_key.generated':
|
||||
lambda info: KeyGenerate(info).test_cases_for_key_generation(),
|
||||
'test_suite_psa_crypto_not_supported.generated':
|
||||
lambda info: NotSupported(info).test_cases_for_not_supported(),
|
||||
'test_suite_psa_crypto_op_fail.generated':
|
||||
lambda info: OpFail(info).all_test_cases(),
|
||||
'test_suite_psa_crypto_storage_format.current':
|
||||
lambda info: StorageFormatForward(info, 0).all_test_cases(),
|
||||
'test_suite_psa_crypto_storage_format.v0':
|
||||
lambda info: StorageFormatV0(info).all_test_cases(),
|
||||
} #type: Dict[str, Callable[[Information], Iterable[test_case.TestCase]]]
|
||||
|
||||
def generate_target(self, name: str) -> None:
|
||||
test_cases = self.TARGETS[name](self.info)
|
||||
self.write_test_data_file(name, test_cases)
|
||||
def __init__(self, options):
|
||||
super().__init__(options)
|
||||
self.info = Information()
|
||||
|
||||
def main(args):
|
||||
"""Command line entry point."""
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument('--list', action='store_true',
|
||||
help='List available targets and exit')
|
||||
parser.add_argument('--list-for-cmake', action='store_true',
|
||||
help='Print \';\'-separated list of available targets and exit')
|
||||
parser.add_argument('--directory', metavar='DIR',
|
||||
help='Output directory (default: tests/suites)')
|
||||
parser.add_argument('targets', nargs='*', metavar='TARGET',
|
||||
help='Target file to generate (default: all; "-": none)')
|
||||
options = parser.parse_args(args)
|
||||
build_tree.chdir_to_root()
|
||||
generator = TestGenerator(options)
|
||||
if options.list:
|
||||
for name in sorted(generator.TARGETS):
|
||||
print(generator.filename_for(name))
|
||||
return
|
||||
# List in a cmake list format (i.e. ';'-separated)
|
||||
if options.list_for_cmake:
|
||||
print(';'.join(generator.filename_for(name)
|
||||
for name in sorted(generator.TARGETS)), end='')
|
||||
return
|
||||
if options.targets:
|
||||
# Allow "-" as a special case so you can run
|
||||
# ``generate_psa_tests.py - $targets`` and it works uniformly whether
|
||||
# ``$targets`` is empty or not.
|
||||
options.targets = [os.path.basename(re.sub(r'\.data\Z', r'', target))
|
||||
for target in options.targets
|
||||
if target != '-']
|
||||
else:
|
||||
options.targets = sorted(generator.TARGETS)
|
||||
for target in options.targets:
|
||||
generator.generate_target(target)
|
||||
def generate_target(self, name: str, *target_args) -> None:
|
||||
super().generate_target(name, self.info)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main(sys.argv[1:])
|
||||
test_generation.main(sys.argv[1:], __doc__, PSATestGenerator)
|
||||
|
@ -24,11 +24,9 @@ Generate TLSv1.3 Compat test cases
|
||||
|
||||
import sys
|
||||
import os
|
||||
import abc
|
||||
import argparse
|
||||
import itertools
|
||||
from collections import namedtuple
|
||||
# pylint: disable=useless-super-delegation
|
||||
|
||||
# define certificates configuration entry
|
||||
Certificate = namedtuple("Certificate", ['cafile', 'certfile', 'keyfile'])
|
||||
@ -71,18 +69,27 @@ NAMED_GROUP_IANA_VALUE = {
|
||||
'x448': 0x1e,
|
||||
}
|
||||
|
||||
class TLSProgram(metaclass=abc.ABCMeta):
|
||||
|
||||
class TLSProgram:
|
||||
"""
|
||||
Base class for generate server/client command.
|
||||
"""
|
||||
|
||||
def __init__(self, ciphersuite, signature_algorithm, named_group, compat_mode=True):
|
||||
# pylint: disable=too-many-arguments
|
||||
def __init__(self, ciphersuite=None, signature_algorithm=None, named_group=None,
|
||||
cert_sig_alg=None, compat_mode=True):
|
||||
self._ciphers = []
|
||||
self._sig_algs = []
|
||||
self._named_groups = []
|
||||
self.add_ciphersuites(ciphersuite)
|
||||
self.add_named_groups(named_group)
|
||||
self.add_signature_algorithms(signature_algorithm)
|
||||
self._cert_sig_algs = []
|
||||
if ciphersuite:
|
||||
self.add_ciphersuites(ciphersuite)
|
||||
if named_group:
|
||||
self.add_named_groups(named_group)
|
||||
if signature_algorithm:
|
||||
self.add_signature_algorithms(signature_algorithm)
|
||||
if cert_sig_alg:
|
||||
self.add_cert_signature_algorithms(cert_sig_alg)
|
||||
self._compat_mode = compat_mode
|
||||
|
||||
# add_ciphersuites should not override by sub class
|
||||
@ -95,27 +102,42 @@ class TLSProgram(metaclass=abc.ABCMeta):
|
||||
self._sig_algs.extend(
|
||||
[sig_alg for sig_alg in signature_algorithms if sig_alg not in self._sig_algs])
|
||||
|
||||
# add_signature_algorithms should not override by sub class
|
||||
# add_named_groups should not override by sub class
|
||||
def add_named_groups(self, *named_groups):
|
||||
self._named_groups.extend(
|
||||
[named_group for named_group in named_groups if named_group not in self._named_groups])
|
||||
|
||||
@abc.abstractmethod
|
||||
# add_cert_signature_algorithms should not override by sub class
|
||||
def add_cert_signature_algorithms(self, *signature_algorithms):
|
||||
self._cert_sig_algs.extend(
|
||||
[sig_alg for sig_alg in signature_algorithms if sig_alg not in self._cert_sig_algs])
|
||||
|
||||
# pylint: disable=no-self-use
|
||||
def pre_checks(self):
|
||||
return []
|
||||
|
||||
@abc.abstractmethod
|
||||
# pylint: disable=no-self-use
|
||||
def cmd(self):
|
||||
pass
|
||||
if not self._cert_sig_algs:
|
||||
self._cert_sig_algs = list(CERTIFICATES.keys())
|
||||
return self.pre_cmd()
|
||||
|
||||
@abc.abstractmethod
|
||||
# pylint: disable=no-self-use
|
||||
def post_checks(self):
|
||||
return []
|
||||
|
||||
# pylint: disable=no-self-use
|
||||
def pre_cmd(self):
|
||||
return ['false']
|
||||
|
||||
class OpenSSLServ(TLSProgram):
|
||||
# pylint: disable=unused-argument,no-self-use
|
||||
def hrr_post_checks(self, named_group):
|
||||
return []
|
||||
|
||||
|
||||
class OpenSSLBase(TLSProgram):
|
||||
"""
|
||||
Generate test commands for OpenSSL server.
|
||||
Generate base test commands for OpenSSL.
|
||||
"""
|
||||
|
||||
NAMED_GROUP = {
|
||||
@ -127,34 +149,66 @@ class OpenSSLServ(TLSProgram):
|
||||
}
|
||||
|
||||
def cmd(self):
|
||||
ret = ['$O_NEXT_SRV_NO_CERT']
|
||||
for _, cert, key in map(lambda sig_alg: CERTIFICATES[sig_alg], self._sig_algs):
|
||||
ret += ['-cert {cert} -key {key}'.format(cert=cert, key=key)]
|
||||
ret += ['-accept $SRV_PORT']
|
||||
ciphersuites = ','.join(self._ciphers)
|
||||
signature_algorithms = ','.join(self._sig_algs)
|
||||
named_groups = ','.join(
|
||||
map(lambda named_group: self.NAMED_GROUP[named_group], self._named_groups))
|
||||
ret += ["-ciphersuites {ciphersuites}".format(ciphersuites=ciphersuites),
|
||||
"-sigalgs {signature_algorithms}".format(
|
||||
signature_algorithms=signature_algorithms),
|
||||
"-groups {named_groups}".format(named_groups=named_groups)]
|
||||
ret += ['-msg -tls1_3 -num_tickets 0 -no_resume_ephemeral -no_cache']
|
||||
ret = super().cmd()
|
||||
|
||||
if self._ciphers:
|
||||
ciphersuites = ':'.join(self._ciphers)
|
||||
ret += ["-ciphersuites {ciphersuites}".format(ciphersuites=ciphersuites)]
|
||||
|
||||
if self._sig_algs:
|
||||
signature_algorithms = set(self._sig_algs + self._cert_sig_algs)
|
||||
signature_algorithms = ':'.join(signature_algorithms)
|
||||
ret += ["-sigalgs {signature_algorithms}".format(
|
||||
signature_algorithms=signature_algorithms)]
|
||||
|
||||
if self._named_groups:
|
||||
named_groups = ':'.join(
|
||||
map(lambda named_group: self.NAMED_GROUP[named_group], self._named_groups))
|
||||
ret += ["-groups {named_groups}".format(named_groups=named_groups)]
|
||||
|
||||
ret += ['-msg -tls1_3']
|
||||
if not self._compat_mode:
|
||||
ret += ['-no_middlebox']
|
||||
|
||||
return ' '.join(ret)
|
||||
return ret
|
||||
|
||||
def pre_checks(self):
|
||||
return ["requires_openssl_tls1_3"]
|
||||
|
||||
|
||||
class OpenSSLServ(OpenSSLBase):
|
||||
"""
|
||||
Generate test commands for OpenSSL server.
|
||||
"""
|
||||
|
||||
def cmd(self):
|
||||
ret = super().cmd()
|
||||
ret += ['-num_tickets 0 -no_resume_ephemeral -no_cache']
|
||||
return ret
|
||||
|
||||
def post_checks(self):
|
||||
return ['-c "HTTP/1.0 200 ok"']
|
||||
|
||||
def pre_cmd(self):
|
||||
ret = ['$O_NEXT_SRV_NO_CERT']
|
||||
for _, cert, key in map(lambda sig_alg: CERTIFICATES[sig_alg], self._cert_sig_algs):
|
||||
ret += ['-cert {cert} -key {key}'.format(cert=cert, key=key)]
|
||||
return ret
|
||||
|
||||
class GnuTLSServ(TLSProgram):
|
||||
|
||||
class OpenSSLCli(OpenSSLBase):
|
||||
"""
|
||||
Generate test commands for GnuTLS server.
|
||||
Generate test commands for OpenSSL client.
|
||||
"""
|
||||
|
||||
def pre_cmd(self):
|
||||
return ['$O_NEXT_CLI_NO_CERT',
|
||||
'-CAfile {cafile}'.format(cafile=CERTIFICATES[self._cert_sig_algs[0]].cafile)]
|
||||
|
||||
|
||||
class GnuTLSBase(TLSProgram):
|
||||
"""
|
||||
Generate base test commands for GnuTLS.
|
||||
"""
|
||||
|
||||
CIPHER_SUITE = {
|
||||
@ -198,16 +252,8 @@ class GnuTLSServ(TLSProgram):
|
||||
"requires_gnutls_next_no_ticket",
|
||||
"requires_gnutls_next_disable_tls13_compat", ]
|
||||
|
||||
def post_checks(self):
|
||||
return ['-c "HTTP/1.0 200 OK"']
|
||||
|
||||
def cmd(self):
|
||||
ret = ['$G_NEXT_SRV_NO_CERT', '--http',
|
||||
'--disable-client-cert', '--debug=4']
|
||||
|
||||
for _, cert, key in map(lambda sig_alg: CERTIFICATES[sig_alg], self._sig_algs):
|
||||
ret += ['--x509certfile {cert} --x509keyfile {key}'.format(
|
||||
cert=cert, key=key)]
|
||||
ret = super().cmd()
|
||||
|
||||
priority_string_list = []
|
||||
|
||||
@ -216,28 +262,70 @@ class GnuTLSServ(TLSProgram):
|
||||
for i in map_table[item]:
|
||||
if i not in priority_string_list:
|
||||
yield i
|
||||
priority_string_list.extend(update_priority_string_list(
|
||||
self._sig_algs, self.SIGNATURE_ALGORITHM))
|
||||
priority_string_list.extend(
|
||||
update_priority_string_list(self._ciphers, self.CIPHER_SUITE))
|
||||
priority_string_list.extend(update_priority_string_list(
|
||||
self._named_groups, self.NAMED_GROUP))
|
||||
priority_string_list = ['NONE'] + sorted(priority_string_list) + ['VERS-TLS1.3']
|
||||
|
||||
if self._ciphers:
|
||||
priority_string_list.extend(update_priority_string_list(
|
||||
self._ciphers, self.CIPHER_SUITE))
|
||||
else:
|
||||
priority_string_list.extend(['CIPHER-ALL', 'MAC-ALL'])
|
||||
|
||||
if self._sig_algs:
|
||||
signature_algorithms = set(self._sig_algs + self._cert_sig_algs)
|
||||
priority_string_list.extend(update_priority_string_list(
|
||||
signature_algorithms, self.SIGNATURE_ALGORITHM))
|
||||
else:
|
||||
priority_string_list.append('SIGN-ALL')
|
||||
|
||||
|
||||
if self._named_groups:
|
||||
priority_string_list.extend(update_priority_string_list(
|
||||
self._named_groups, self.NAMED_GROUP))
|
||||
else:
|
||||
priority_string_list.append('GROUP-ALL')
|
||||
|
||||
priority_string_list = ['NONE'] + \
|
||||
priority_string_list + ['VERS-TLS1.3']
|
||||
|
||||
priority_string = ':+'.join(priority_string_list)
|
||||
priority_string += ':%NO_TICKETS'
|
||||
|
||||
if not self._compat_mode:
|
||||
priority_string += [':%DISABLE_TLS13_COMPAT_MODE']
|
||||
|
||||
ret += ['--priority={priority_string}'.format(
|
||||
priority_string=priority_string)]
|
||||
ret = ' '.join(ret)
|
||||
return ret
|
||||
|
||||
|
||||
class MbedTLSCli(TLSProgram):
|
||||
class GnuTLSServ(GnuTLSBase):
|
||||
"""
|
||||
Generate test commands for mbedTLS client.
|
||||
Generate test commands for GnuTLS server.
|
||||
"""
|
||||
|
||||
def pre_cmd(self):
|
||||
ret = ['$G_NEXT_SRV_NO_CERT', '--http', '--disable-client-cert', '--debug=4']
|
||||
|
||||
for _, cert, key in map(lambda sig_alg: CERTIFICATES[sig_alg], self._cert_sig_algs):
|
||||
ret += ['--x509certfile {cert} --x509keyfile {key}'.format(
|
||||
cert=cert, key=key)]
|
||||
return ret
|
||||
|
||||
def post_checks(self):
|
||||
return ['-c "HTTP/1.0 200 OK"']
|
||||
|
||||
|
||||
class GnuTLSCli(GnuTLSBase):
|
||||
"""
|
||||
Generate test commands for GnuTLS client.
|
||||
"""
|
||||
|
||||
def pre_cmd(self):
|
||||
return ['$G_NEXT_CLI_NO_CERT', '--debug=4', '--single-key-share',
|
||||
'--x509cafile {cafile}'.format(cafile=CERTIFICATES[self._cert_sig_algs[0]].cafile)]
|
||||
|
||||
|
||||
class MbedTLSBase(TLSProgram):
|
||||
"""
|
||||
Generate base test commands for mbedTLS.
|
||||
"""
|
||||
|
||||
CIPHER_SUITE = {
|
||||
@ -248,79 +336,181 @@ class MbedTLSCli(TLSProgram):
|
||||
'TLS_AES_128_CCM_8_SHA256': 'TLS1-3-AES-128-CCM-8-SHA256'}
|
||||
|
||||
def cmd(self):
|
||||
ret = ['$P_CLI']
|
||||
ret += ['server_addr=127.0.0.1', 'server_port=$SRV_PORT',
|
||||
'debug_level=4', 'force_version=tls13']
|
||||
ret += ['ca_file={cafile}'.format(
|
||||
cafile=CERTIFICATES[self._sig_algs[0]].cafile)]
|
||||
ret = super().cmd()
|
||||
ret += ['debug_level=4']
|
||||
|
||||
|
||||
if self._ciphers:
|
||||
ciphers = ','.join(
|
||||
map(lambda cipher: self.CIPHER_SUITE[cipher], self._ciphers))
|
||||
ret += ["force_ciphersuite={ciphers}".format(ciphers=ciphers)]
|
||||
|
||||
if self._sig_algs:
|
||||
if self._sig_algs + self._cert_sig_algs:
|
||||
ret += ['sig_algs={sig_algs}'.format(
|
||||
sig_algs=','.join(self._sig_algs))]
|
||||
for sig_alg in self._sig_algs:
|
||||
if sig_alg in ('ecdsa_secp256r1_sha256',
|
||||
'ecdsa_secp384r1_sha384',
|
||||
'ecdsa_secp521r1_sha512'):
|
||||
self.add_named_groups(sig_alg.split('_')[1])
|
||||
sig_algs=','.join(set(self._sig_algs + self._cert_sig_algs)))]
|
||||
|
||||
if self._named_groups:
|
||||
named_groups = ','.join(self._named_groups)
|
||||
ret += ["curves={named_groups}".format(named_groups=named_groups)]
|
||||
|
||||
ret = ' '.join(ret)
|
||||
ret += ['force_version=tls13']
|
||||
return ret
|
||||
|
||||
def pre_checks(self):
|
||||
ret = ['requires_config_enabled MBEDTLS_DEBUG_C',
|
||||
'requires_config_enabled MBEDTLS_SSL_CLI_C',
|
||||
'requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3']
|
||||
|
||||
if self._compat_mode:
|
||||
ret += ['requires_config_enabled MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE']
|
||||
|
||||
if 'rsa_pss_rsae_sha256' in self._sig_algs:
|
||||
if 'rsa_pss_rsae_sha256' in self._sig_algs + self._cert_sig_algs:
|
||||
ret.append(
|
||||
'requires_config_enabled MBEDTLS_X509_RSASSA_PSS_SUPPORT')
|
||||
return ret
|
||||
|
||||
|
||||
class MbedTLSServ(MbedTLSBase):
|
||||
"""
|
||||
Generate test commands for mbedTLS server.
|
||||
"""
|
||||
|
||||
def cmd(self):
|
||||
ret = super().cmd()
|
||||
ret += ['tls13_kex_modes=ephemeral cookies=0 tickets=0']
|
||||
return ret
|
||||
|
||||
def pre_checks(self):
|
||||
return ['requires_config_enabled MBEDTLS_SSL_SRV_C'] + super().pre_checks()
|
||||
|
||||
def post_checks(self):
|
||||
check_strings = ["ECDH curve: {group}".format(group=self._named_groups[0]),
|
||||
"server hello, chosen ciphersuite: ( {:04x} ) - {}".format(
|
||||
CIPHER_SUITE_IANA_VALUE[self._ciphers[0]],
|
||||
self.CIPHER_SUITE[self._ciphers[0]]),
|
||||
"Certificate Verify: Signature algorithm ( {:04x} )".format(
|
||||
SIG_ALG_IANA_VALUE[self._sig_algs[0]]),
|
||||
"Verifying peer X.509 certificate... ok", ]
|
||||
check_strings = ["Protocol is TLSv1.3"]
|
||||
if self._ciphers:
|
||||
check_strings.append(
|
||||
"server hello, chosen ciphersuite: {} ( id={:04d} )".format(
|
||||
self.CIPHER_SUITE[self._ciphers[0]],
|
||||
CIPHER_SUITE_IANA_VALUE[self._ciphers[0]]))
|
||||
if self._sig_algs:
|
||||
check_strings.append(
|
||||
"received signature algorithm: 0x{:x}".format(
|
||||
SIG_ALG_IANA_VALUE[self._sig_algs[0]]))
|
||||
|
||||
for named_group in self._named_groups:
|
||||
check_strings += ['got named group: {named_group}({iana_value:04x})'.format(
|
||||
named_group=named_group,
|
||||
iana_value=NAMED_GROUP_IANA_VALUE[named_group])]
|
||||
|
||||
check_strings.append("Verifying peer X.509 certificate... ok")
|
||||
return ['-s "{}"'.format(i) for i in check_strings]
|
||||
|
||||
def pre_cmd(self):
|
||||
ret = ['$P_SRV']
|
||||
for _, cert, key in map(lambda sig_alg: CERTIFICATES[sig_alg], self._cert_sig_algs):
|
||||
ret += ['crt_file={cert} key_file={key}'.format(cert=cert, key=key)]
|
||||
return ret
|
||||
|
||||
def hrr_post_checks(self, named_group):
|
||||
return ['-s "HRR selected_group: {:s}"'.format(named_group)]
|
||||
|
||||
|
||||
class MbedTLSCli(MbedTLSBase):
|
||||
"""
|
||||
Generate test commands for mbedTLS client.
|
||||
"""
|
||||
|
||||
def pre_cmd(self):
|
||||
return ['$P_CLI',
|
||||
'ca_file={cafile}'.format(cafile=CERTIFICATES[self._cert_sig_algs[0]].cafile)]
|
||||
|
||||
def pre_checks(self):
|
||||
return ['requires_config_enabled MBEDTLS_SSL_CLI_C'] + super().pre_checks()
|
||||
|
||||
def hrr_post_checks(self, named_group):
|
||||
ret = ['-c "received HelloRetryRequest message"']
|
||||
ret += ['-c "selected_group ( {:d} )"'.format(NAMED_GROUP_IANA_VALUE[named_group])]
|
||||
return ret
|
||||
|
||||
def post_checks(self):
|
||||
check_strings = ["Protocol is TLSv1.3"]
|
||||
if self._ciphers:
|
||||
check_strings.append(
|
||||
"server hello, chosen ciphersuite: ( {:04x} ) - {}".format(
|
||||
CIPHER_SUITE_IANA_VALUE[self._ciphers[0]],
|
||||
self.CIPHER_SUITE[self._ciphers[0]]))
|
||||
if self._sig_algs:
|
||||
check_strings.append(
|
||||
"Certificate Verify: Signature algorithm ( {:04x} )".format(
|
||||
SIG_ALG_IANA_VALUE[self._sig_algs[0]]))
|
||||
|
||||
for named_group in self._named_groups:
|
||||
check_strings += ['NamedGroup: {named_group} ( {iana_value:x} )'.format(
|
||||
named_group=named_group,
|
||||
iana_value=NAMED_GROUP_IANA_VALUE[named_group])]
|
||||
|
||||
check_strings.append("Verifying peer X.509 certificate... ok")
|
||||
return ['-c "{}"'.format(i) for i in check_strings]
|
||||
|
||||
|
||||
SERVER_CLASSES = {'OpenSSL': OpenSSLServ, 'GnuTLS': GnuTLSServ}
|
||||
CLIENT_CLASSES = {'mbedTLS': MbedTLSCli}
|
||||
SERVER_CLASSES = {'OpenSSL': OpenSSLServ, 'GnuTLS': GnuTLSServ, 'mbedTLS': MbedTLSServ}
|
||||
CLIENT_CLASSES = {'OpenSSL': OpenSSLCli, 'GnuTLS': GnuTLSCli, 'mbedTLS': MbedTLSCli}
|
||||
|
||||
|
||||
def generate_compat_test(server=None, client=None, cipher=None, sig_alg=None, named_group=None):
|
||||
def generate_compat_test(client=None, server=None, cipher=None, named_group=None, sig_alg=None):
|
||||
"""
|
||||
Generate test case with `ssl-opt.sh` format.
|
||||
"""
|
||||
name = 'TLS 1.3 {client[0]}->{server[0]}: {cipher},{named_group},{sig_alg}'.format(
|
||||
client=client, server=server, cipher=cipher, sig_alg=sig_alg, named_group=named_group)
|
||||
server_object = SERVER_CLASSES[server](cipher, sig_alg, named_group)
|
||||
client_object = CLIENT_CLASSES[client](cipher, sig_alg, named_group)
|
||||
client=client, server=server, cipher=cipher[4:], sig_alg=sig_alg, named_group=named_group)
|
||||
|
||||
cmd = ['run_test "{}"'.format(name), '"{}"'.format(
|
||||
server_object.cmd()), '"{}"'.format(client_object.cmd()), '0']
|
||||
server_object = SERVER_CLASSES[server](ciphersuite=cipher,
|
||||
named_group=named_group,
|
||||
signature_algorithm=sig_alg,
|
||||
cert_sig_alg=sig_alg)
|
||||
client_object = CLIENT_CLASSES[client](ciphersuite=cipher,
|
||||
named_group=named_group,
|
||||
signature_algorithm=sig_alg,
|
||||
cert_sig_alg=sig_alg)
|
||||
|
||||
cmd = ['run_test "{}"'.format(name),
|
||||
'"{}"'.format(' '.join(server_object.cmd())),
|
||||
'"{}"'.format(' '.join(client_object.cmd())),
|
||||
'0']
|
||||
cmd += server_object.post_checks()
|
||||
cmd += client_object.post_checks()
|
||||
cmd += ['-C "received HelloRetryRequest message"']
|
||||
prefix = ' \\\n' + (' '*9)
|
||||
cmd = prefix.join(cmd)
|
||||
return '\n'.join(server_object.pre_checks() + client_object.pre_checks() + [cmd])
|
||||
|
||||
|
||||
def generate_hrr_compat_test(client=None, server=None,
|
||||
client_named_group=None, server_named_group=None,
|
||||
cert_sig_alg=None):
|
||||
"""
|
||||
Generate Hello Retry Request test case with `ssl-opt.sh` format.
|
||||
"""
|
||||
name = 'TLS 1.3 {client[0]}->{server[0]}: HRR {c_named_group} -> {s_named_group}'.format(
|
||||
client=client, server=server, c_named_group=client_named_group,
|
||||
s_named_group=server_named_group)
|
||||
server_object = SERVER_CLASSES[server](named_group=server_named_group,
|
||||
cert_sig_alg=cert_sig_alg)
|
||||
|
||||
client_object = CLIENT_CLASSES[client](named_group=client_named_group,
|
||||
cert_sig_alg=cert_sig_alg)
|
||||
client_object.add_named_groups(server_named_group)
|
||||
|
||||
cmd = ['run_test "{}"'.format(name),
|
||||
'"{}"'.format(' '.join(server_object.cmd())),
|
||||
'"{}"'.format(' '.join(client_object.cmd())),
|
||||
'0']
|
||||
cmd += server_object.post_checks()
|
||||
cmd += client_object.post_checks()
|
||||
cmd += server_object.hrr_post_checks(server_named_group)
|
||||
cmd += client_object.hrr_post_checks(server_named_group)
|
||||
prefix = ' \\\n' + (' '*9)
|
||||
cmd = prefix.join(cmd)
|
||||
return '\n'.join(server_object.pre_checks() +
|
||||
client_object.pre_checks() +
|
||||
[cmd])
|
||||
|
||||
SSL_OUTPUT_HEADER = '''#!/bin/sh
|
||||
|
||||
# {filename}
|
||||
@ -343,14 +533,13 @@ SSL_OUTPUT_HEADER = '''#!/bin/sh
|
||||
# Purpose
|
||||
#
|
||||
# List TLS1.3 compat test cases. They are generated by
|
||||
# `generate_tls13_compat_tests.py -a`.
|
||||
# `{cmd}`.
|
||||
#
|
||||
# PLEASE DO NOT EDIT THIS FILE. IF NEEDED, PLEASE MODIFY `generate_tls13_compat_tests.py`
|
||||
# AND REGENERATE THIS FILE.
|
||||
#
|
||||
'''
|
||||
|
||||
|
||||
def main():
|
||||
"""
|
||||
Main function of this program
|
||||
@ -397,22 +586,42 @@ def main():
|
||||
args = parser.parse_args()
|
||||
|
||||
def get_all_test_cases():
|
||||
for cipher, sig_alg, named_group, server, client in \
|
||||
itertools.product(CIPHER_SUITE_IANA_VALUE.keys(), SIG_ALG_IANA_VALUE.keys(),
|
||||
NAMED_GROUP_IANA_VALUE.keys(), SERVER_CLASSES.keys(),
|
||||
CLIENT_CLASSES.keys()):
|
||||
yield generate_compat_test(cipher=cipher, sig_alg=sig_alg, named_group=named_group,
|
||||
server=server, client=client)
|
||||
# Generate normal compat test cases
|
||||
for client, server, cipher, named_group, sig_alg in \
|
||||
itertools.product(CLIENT_CLASSES.keys(),
|
||||
SERVER_CLASSES.keys(),
|
||||
CIPHER_SUITE_IANA_VALUE.keys(),
|
||||
NAMED_GROUP_IANA_VALUE.keys(),
|
||||
SIG_ALG_IANA_VALUE.keys()):
|
||||
if server == 'mbedTLS' or client == 'mbedTLS':
|
||||
yield generate_compat_test(client=client, server=server,
|
||||
cipher=cipher, named_group=named_group,
|
||||
sig_alg=sig_alg)
|
||||
|
||||
|
||||
# Generate Hello Retry Request compat test cases
|
||||
for client, server, client_named_group, server_named_group in \
|
||||
itertools.product(CLIENT_CLASSES.keys(),
|
||||
SERVER_CLASSES.keys(),
|
||||
NAMED_GROUP_IANA_VALUE.keys(),
|
||||
NAMED_GROUP_IANA_VALUE.keys()):
|
||||
|
||||
if (client == 'mbedTLS' or server == 'mbedTLS') and \
|
||||
client_named_group != server_named_group:
|
||||
yield generate_hrr_compat_test(client=client, server=server,
|
||||
client_named_group=client_named_group,
|
||||
server_named_group=server_named_group,
|
||||
cert_sig_alg="ecdsa_secp256r1_sha256")
|
||||
|
||||
if args.generate_all_tls13_compat_tests:
|
||||
if args.output:
|
||||
with open(args.output, 'w', encoding="utf-8") as f:
|
||||
f.write(SSL_OUTPUT_HEADER.format(
|
||||
filename=os.path.basename(args.output)))
|
||||
filename=os.path.basename(args.output), cmd=' '.join(sys.argv)))
|
||||
f.write('\n\n'.join(get_all_test_cases()))
|
||||
f.write('\n')
|
||||
else:
|
||||
print('\n'.join(get_all_test_cases()))
|
||||
print('\n\n'.join(get_all_test_cases()))
|
||||
return 0
|
||||
|
||||
if args.list_ciphers or args.list_sig_algs or args.list_named_groups \
|
||||
|
@ -4,7 +4,7 @@
|
||||
# (Multiple recursion where a() calls b() which calls a() not covered.)
|
||||
#
|
||||
# When the recursion depth might depend on data controlled by the attacker in
|
||||
# an unbounded way, those functions should use interation instead.
|
||||
# an unbounded way, those functions should use iteration instead.
|
||||
#
|
||||
# Typical usage: scripts/recursion.pl library/*.c
|
||||
#
|
||||
|
@ -32,11 +32,19 @@ my %configs = (
|
||||
'compat' => '-m tls12 -f \'^TLS-PSK-WITH-AES-...-CCM-8\'',
|
||||
'test_again_with_use_psa' => 1
|
||||
},
|
||||
'config-ccm-psk-dtls1_2.h' => {
|
||||
'compat' => '-m dtls12 -f \'^TLS-PSK-WITH-AES-...-CCM-8\'',
|
||||
'opt' => ' ',
|
||||
'opt_needs_debug' => 1,
|
||||
'test_again_with_use_psa' => 1
|
||||
},
|
||||
'config-no-entropy.h' => {
|
||||
},
|
||||
'config-suite-b.h' => {
|
||||
'compat' => "-m tls12 -f 'ECDHE-ECDSA.*AES.*GCM' -p mbedTLS",
|
||||
'test_again_with_use_psa' => 1,
|
||||
'opt' => ' ',
|
||||
'opt_needs_debug' => 1,
|
||||
},
|
||||
'config-symmetric-only.h' => {
|
||||
'test_again_with_use_psa' => 0, # Uses PSA by default, no need to test it twice
|
||||
@ -49,17 +57,14 @@ my %configs = (
|
||||
|
||||
# If no config-name is provided, use all known configs.
|
||||
# Otherwise, use the provided names only.
|
||||
my @configs_to_test = sort keys %configs;
|
||||
if ($#ARGV >= 0) {
|
||||
my %configs_ori = ( %configs );
|
||||
%configs = ();
|
||||
|
||||
foreach my $conf_name (@ARGV) {
|
||||
if( ! exists $configs_ori{$conf_name} ) {
|
||||
foreach my $conf_name ( @ARGV ) {
|
||||
if( ! exists $configs{$conf_name} ) {
|
||||
die "Unknown configuration: $conf_name\n";
|
||||
} else {
|
||||
$configs{$conf_name} = $configs_ori{$conf_name};
|
||||
}
|
||||
}
|
||||
@configs_to_test = @ARGV;
|
||||
}
|
||||
|
||||
-d 'library' && -d 'include' && -d 'tests' or die "Must be run from root\n";
|
||||
@ -84,25 +89,27 @@ if (!-e "tests/seedfile" || -s "tests/seedfile" < 64) {
|
||||
}
|
||||
|
||||
sub perform_test {
|
||||
my $conf = $_[0];
|
||||
my $conf_file = $_[0];
|
||||
my $data = $_[1];
|
||||
my $test_with_psa = $_[2];
|
||||
|
||||
my $conf_name = $conf_file;
|
||||
if ( $test_with_psa )
|
||||
{
|
||||
$conf_name .= "+PSA";
|
||||
}
|
||||
|
||||
system( "cp $config_h.bak $config_h" ) and die;
|
||||
system( "make clean" ) and die;
|
||||
|
||||
print "\n******************************************\n";
|
||||
print "* Testing configuration: $conf\n";
|
||||
if ( $test_with_psa )
|
||||
{
|
||||
print "* ENABLING MBEDTLS_PSA_CRYPTO_C and MBEDTLS_USE_PSA_CRYPTO \n";
|
||||
}
|
||||
print "* Testing configuration: $conf_name\n";
|
||||
print "******************************************\n";
|
||||
|
||||
$ENV{MBEDTLS_TEST_CONFIGURATION} = $conf;
|
||||
$ENV{MBEDTLS_TEST_CONFIGURATION} = $conf_name;
|
||||
|
||||
system( "cp configs/$conf $config_h" )
|
||||
and abort "Failed to activate $conf\n";
|
||||
system( "cp configs/$conf_file $config_h" )
|
||||
and abort "Failed to activate $conf_file\n";
|
||||
|
||||
if ( $test_with_psa )
|
||||
{
|
||||
@ -110,41 +117,52 @@ sub perform_test {
|
||||
system( "scripts/config.py set MBEDTLS_USE_PSA_CRYPTO" );
|
||||
}
|
||||
|
||||
system( "CFLAGS='-Os -Werror -Wall -Wextra' make" ) and abort "Failed to build: $conf\n";
|
||||
system( "make test" ) and abort "Failed test suite: $conf\n";
|
||||
system( "CFLAGS='-Os -Werror -Wall -Wextra' make" ) and abort "Failed to build: $conf_name\n";
|
||||
system( "make test" ) and abort "Failed test suite: $conf_name\n";
|
||||
|
||||
my $compat = $data->{'compat'};
|
||||
if( $compat )
|
||||
{
|
||||
print "\nrunning compat.sh $compat\n";
|
||||
print "\nrunning compat.sh $compat ($conf_name)\n";
|
||||
system( "tests/compat.sh $compat" )
|
||||
and abort "Failed compat.sh: $conf\n";
|
||||
and abort "Failed compat.sh: $conf_name\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
print "\nskipping compat.sh\n";
|
||||
print "\nskipping compat.sh ($conf_name)\n";
|
||||
}
|
||||
|
||||
my $opt = $data->{'opt'};
|
||||
if( $opt )
|
||||
{
|
||||
print "\nrunning ssl-opt.sh $opt\n";
|
||||
if( $data->{'opt_needs_debug'} )
|
||||
{
|
||||
print "\nrebuilding with debug traces for ssl-opt ($conf_name)\n";
|
||||
$conf_name .= '+DEBUG';
|
||||
$ENV{MBEDTLS_TEST_CONFIGURATION} = $conf_name;
|
||||
system( "make clean" );
|
||||
system( "scripts/config.py set MBEDTLS_DEBUG_C" );
|
||||
system( "scripts/config.py set MBEDTLS_ERROR_C" );
|
||||
system( "CFLAGS='-Os -Werror -Wall -Wextra' make" ) and abort "Failed to build: $conf_name\n";
|
||||
}
|
||||
|
||||
print "\nrunning ssl-opt.sh $opt ($conf_name)\n";
|
||||
system( "tests/ssl-opt.sh $opt" )
|
||||
and abort "Failed ssl-opt.sh: $conf\n";
|
||||
and abort "Failed ssl-opt.sh: $conf_name\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
print "\nskipping ssl-opt.sh\n";
|
||||
print "\nskipping ssl-opt.sh ($conf_name)\n";
|
||||
}
|
||||
}
|
||||
|
||||
while( my ($conf, $data) = each %configs ) {
|
||||
my $test_with_psa = $data->{'test_again_with_use_psa'};
|
||||
foreach my $conf ( @configs_to_test ) {
|
||||
my $test_with_psa = $configs{$conf}{'test_again_with_use_psa'};
|
||||
if ( $test_with_psa )
|
||||
{
|
||||
perform_test( $conf, $data, $test_with_psa );
|
||||
perform_test( $conf, $configs{$conf}, $test_with_psa );
|
||||
}
|
||||
perform_test( $conf, $data, 0 );
|
||||
perform_test( $conf, $configs{$conf}, 0 );
|
||||
}
|
||||
|
||||
system( "mv $config_h.bak $config_h" ) and warn "$config_h not restored\n";
|
||||
|
@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Run the PSA Cryto API compliance test suite.
|
||||
"""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 complie 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,
|
||||
@ -47,7 +47,7 @@ EXPECTED_FAILURES = {
|
||||
#
|
||||
# Web URL: https://github.com/bensze01/psa-arch-tests/tree/fixes-for-mbedtls-3
|
||||
PSA_ARCH_TESTS_REPO = 'https://github.com/bensze01/psa-arch-tests.git'
|
||||
PSA_ARCH_TESTS_REF = 'fix-pr-5139-3'
|
||||
PSA_ARCH_TESTS_REF = 'fix-pr-5736'
|
||||
|
||||
#pylint: disable=too-many-branches,too-many-statements
|
||||
def main():
|
||||
|
@ -77,6 +77,22 @@ def normalize(expr: str) -> str:
|
||||
"""
|
||||
return re.sub(NORMALIZE_STRIP_RE, '', expr)
|
||||
|
||||
ALG_TRUNCATED_TO_SELF_RE = \
|
||||
re.compile(r'PSA_ALG_AEAD_WITH_SHORTENED_TAG\('
|
||||
r'PSA_ALG_(?:CCM|CHACHA20_POLY1305|GCM)'
|
||||
r', *16\)\Z')
|
||||
|
||||
def is_simplifiable(expr: str) -> bool:
|
||||
"""Determine whether an expression is simplifiable.
|
||||
|
||||
Simplifiable expressions can't be output in their input form, since
|
||||
the output will be the simple form. Therefore they must be excluded
|
||||
from testing.
|
||||
"""
|
||||
if ALG_TRUNCATED_TO_SELF_RE.match(expr):
|
||||
return True
|
||||
return False
|
||||
|
||||
def collect_values(inputs: InputsForTest,
|
||||
type_word: str,
|
||||
include_path: Optional[str] = None,
|
||||
@ -87,7 +103,9 @@ def collect_values(inputs: InputsForTest,
|
||||
value is a string representation of its integer value.
|
||||
"""
|
||||
names = inputs.get_names(type_word)
|
||||
expressions = sorted(inputs.generate_expressions(names))
|
||||
expressions = sorted(expr
|
||||
for expr in inputs.generate_expressions(names)
|
||||
if not is_simplifiable(expr))
|
||||
values = run_c(type_word, expressions,
|
||||
include_path=include_path, keep_c=keep_c)
|
||||
return expressions, values
|
||||
|
Reference in New Issue
Block a user