diff --git a/.travis.yml b/.travis.yml index c8ca79dc0..6a9b6f611 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,12 +5,6 @@ compiler: sudo: false cache: ccache -# blocklist -branches: - except: - - development-psa - - coverity_scan - script: - tests/scripts/recursion.pl library/*.c - tests/scripts/check-generated-files.sh @@ -27,7 +21,7 @@ script: env: global: - SEED=1 - - secure: "barHldniAfXyoWOD/vcO+E6/Xm4fmcaUoC9BeKW+LwsHqlDMLvugaJnmLXkSpkbYhVL61Hzf3bo0KPJn88AFc5Rkf8oYHPjH4adMnVXkf3B9ghHCgznqHsAH3choo6tnPxaFgOwOYmLGb382nQxfE5lUdvnM/W/psQjWt66A1+k=" + - secure: "FrI5d2s+ckckC17T66c8jm2jV6i2DkBPU5nyWzwbedjmEBeocREfQLd/x8yKpPzLDz7ghOvr+/GQvsPPn0dVkGlNzm3Q+hGHc/ujnASuUtGrcuMM+0ALnJ3k4rFr9xEvjJeWb4SmhJO5UCAZYvTItW4k7+bj9L+R6lt3TzQbXzg=" addons: apt: @@ -37,7 +31,7 @@ addons: coverity_scan: project: name: "ARMmbed/mbedtls" - notification_email: simon.butcher@arm.com + notification_email: support-mbedtls@arm.com build_command_prepend: build_command: make branch_pattern: coverity_scan diff --git a/3rdparty/everest/CMakeLists.txt b/3rdparty/everest/CMakeLists.txt index 18c8731bd..782c0c563 100644 --- a/3rdparty/everest/CMakeLists.txt +++ b/3rdparty/everest/CMakeLists.txt @@ -10,7 +10,7 @@ set(everest_src list(APPEND everest_inc ${CMAKE_CURRENT_SOURCE_DIR}/include ${CMAKE_CURRENT_SOURCE_DIR}/include/everest ${CMAKE_CURRENT_SOURCE_DIR}/include/everest/kremlib) -execute_process(COMMAND ${PERL_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/../../scripts/config.pl -f ${CMAKE_CURRENT_SOURCE_DIR}/../../include/mbedtls/config.h get MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED RESULT_VARIABLE result) +execute_process(COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/../../scripts/config.py -f ${CMAKE_CURRENT_SOURCE_DIR}/../../include/mbedtls/config.h get MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED RESULT_VARIABLE result) if(${result} EQUAL 0) diff --git a/CMakeLists.txt b/CMakeLists.txt index 81fa6cb89..6d5332d1a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -46,19 +46,19 @@ set(CTR_DRBG_128_BIT_KEY_WARNING "${WARNING_BORDER}" "${CTR_DRBG_128_BIT_KEY_WARN_L3}" "${WARNING_BORDER}") -find_package(PythonInterp) -find_package(Perl) -if(PERL_FOUND) +# Python 3 is only needed here to check for configuration warnings. +find_package(PythonInterp 3) +if(PYTHONINTERP_FOUND) # If 128-bit keys are configured for CTR_DRBG, display an appropriate warning - execute_process(COMMAND ${PERL_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/scripts/config.pl -f ${CMAKE_CURRENT_SOURCE_DIR}/include/mbedtls/config.h get MBEDTLS_CTR_DRBG_USE_128_BIT_KEY + execute_process(COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/scripts/config.py -f ${CMAKE_CURRENT_SOURCE_DIR}/include/mbedtls/config.h get MBEDTLS_CTR_DRBG_USE_128_BIT_KEY RESULT_VARIABLE result) if(${result} EQUAL 0) message(WARNING ${CTR_DRBG_128_BIT_KEY_WARNING}) endif() # If NULL Entropy is configured, display an appropriate warning - execute_process(COMMAND ${PERL_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/scripts/config.pl -f ${CMAKE_CURRENT_SOURCE_DIR}/include/mbedtls/config.h get MBEDTLS_TEST_NULL_ENTROPY + execute_process(COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/scripts/config.py -f ${CMAKE_CURRENT_SOURCE_DIR}/include/mbedtls/config.h get MBEDTLS_TEST_NULL_ENTROPY RESULT_VARIABLE result) if(${result} EQUAL 0) message(WARNING ${NULL_ENTROPY_WARNING}) diff --git a/Makefile b/Makefile index c9eb681ce..4fd7f8eaa 100644 --- a/Makefile +++ b/Makefile @@ -70,11 +70,11 @@ post_build: ifndef WINDOWS # If 128-bit keys are configured for CTR_DRBG, display an appropriate warning - -scripts/config.pl get MBEDTLS_CTR_DRBG_USE_128_BIT_KEY && ([ $$? -eq 0 ]) && \ + -scripts/config.py get MBEDTLS_CTR_DRBG_USE_128_BIT_KEY && ([ $$? -eq 0 ]) && \ echo '$(CTR_DRBG_128_BIT_KEY_WARNING)' # If NULL Entropy is configured, display an appropriate warning - -scripts/config.pl get MBEDTLS_TEST_NULL_ENTROPY && ([ $$? -eq 0 ]) && \ + -scripts/config.py get MBEDTLS_TEST_NULL_ENTROPY && ([ $$? -eq 0 ]) && \ echo '$(NULL_ENTROPY_WARNING)' endif diff --git a/configs/config-symmetric-only.h b/configs/config-symmetric-only.h new file mode 100644 index 000000000..94e80aba7 --- /dev/null +++ b/configs/config-symmetric-only.h @@ -0,0 +1,99 @@ +/** + * \file config-symmetric-only.h + * + * \brief Configuration without any asymmetric cryptography. + */ +/* + * Copyright (C) 2019, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#ifndef MBEDTLS_CONFIG_H +#define MBEDTLS_CONFIG_H + +/* System support */ +//#define MBEDTLS_HAVE_ASM +#define MBEDTLS_HAVE_TIME +#define MBEDTLS_HAVE_TIME_DATE + +/* Mbed Crypto feature support */ +#define MBEDTLS_CIPHER_MODE_CBC +#define MBEDTLS_CIPHER_MODE_CFB +#define MBEDTLS_CIPHER_MODE_CTR +#define MBEDTLS_CIPHER_MODE_OFB +#define MBEDTLS_CIPHER_MODE_XTS +#define MBEDTLS_CIPHER_PADDING_PKCS7 +#define MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS +#define MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN +#define MBEDTLS_CIPHER_PADDING_ZEROS +#define MBEDTLS_ERROR_STRERROR_DUMMY +#define MBEDTLS_FS_IO +#define MBEDTLS_ENTROPY_NV_SEED +#define MBEDTLS_SELF_TEST +#define MBEDTLS_USE_PSA_CRYPTO +#define MBEDTLS_VERSION_FEATURES + +/* Mbed Crypto modules */ +#define MBEDTLS_AES_C +#define MBEDTLS_ARC4_C +#define MBEDTLS_ASN1_PARSE_C +#define MBEDTLS_ASN1_WRITE_C +#define MBEDTLS_BASE64_C +#define MBEDTLS_BLOWFISH_C +#define MBEDTLS_CAMELLIA_C +#define MBEDTLS_ARIA_C +#define MBEDTLS_CCM_C +#define MBEDTLS_CHACHA20_C +#define MBEDTLS_CHACHAPOLY_C +#define MBEDTLS_CIPHER_C +#define MBEDTLS_CMAC_C +#define MBEDTLS_CTR_DRBG_C +#define MBEDTLS_DES_C +#define MBEDTLS_ENTROPY_C +#define MBEDTLS_ERROR_C +#define MBEDTLS_GCM_C +//#define MBEDTLS_HAVEGE_C +#define MBEDTLS_HKDF_C +#define MBEDTLS_HMAC_DRBG_C +#define MBEDTLS_NIST_KW_C +#define MBEDTLS_MD_C +#define MBEDTLS_MD2_C +#define MBEDTLS_MD4_C +#define MBEDTLS_MD5_C +#define MBEDTLS_OID_C +#define MBEDTLS_PEM_PARSE_C +#define MBEDTLS_PEM_WRITE_C +#define MBEDTLS_PKCS5_C +#define MBEDTLS_PKCS12_C +#define MBEDTLS_PLATFORM_C +#define MBEDTLS_POLY1305_C +#define MBEDTLS_PSA_CRYPTO_C +#define MBEDTLS_PSA_CRYPTO_SE_C +#define MBEDTLS_PSA_CRYPTO_STORAGE_C +#define MBEDTLS_PSA_ITS_FILE_C +#define MBEDTLS_RIPEMD160_C +#define MBEDTLS_SHA1_C +#define MBEDTLS_SHA256_C +#define MBEDTLS_SHA512_C +//#define MBEDTLS_THREADING_C +#define MBEDTLS_TIMING_C +#define MBEDTLS_VERSION_C +#define MBEDTLS_XTEA_C + +#include "check_config.h" + +#endif /* MBEDTLS_CONFIG_H */ diff --git a/docs/architecture/Makefile b/docs/architecture/Makefile index 258abcdb0..ab22fb16d 100644 --- a/docs/architecture/Makefile +++ b/docs/architecture/Makefile @@ -5,6 +5,7 @@ default: all all_markdown = \ mbed-crypto-storage-specification.md \ testing/driver-interface-test-strategy.md \ + testing/test-framework.md \ # This line is intentionally left blank html: $(all_markdown:.md=.html) diff --git a/docs/architecture/testing/test-framework.md b/docs/architecture/testing/test-framework.md new file mode 100644 index 000000000..e0e960f87 --- /dev/null +++ b/docs/architecture/testing/test-framework.md @@ -0,0 +1,58 @@ +# Mbed TLS test framework + +This document is an overview of the Mbed TLS test framework and test tools. + +This document is incomplete. You can help by expanding it. + +## Unit tests + +See + +### Unit test descriptions + +Each test case has a description which succinctly describes for a human audience what the test does. The first non-comment line of each paragraph in a `.data` file is the test description. The following rules and guidelines apply: + +* Test descriptions may not contain semicolons, line breaks and other control characters, or non-ASCII characters.
+ Rationale: keep the tools that process test descriptions (`generate_test_code.py`, [outcome file](#outcome-file) tools) simple. +* Test descriptions must be unique within a `.data` file. If you can't think of a better description, the convention is to append `#1`, `#2`, etc.
+ Rationale: make it easy to relate a failure log to the test data. Avoid confusion between cases in the [outcome file](#outcome-file). +* Test descriptions should be a maximum of **66 characters**.
+ Rationale: 66 characters is what our various tools assume (leaving room for 14 more characters on an 80-column line). Longer descriptions may be truncated or may break a visual alignment.
+ We have a lot of test cases with longer descriptions, but they should be avoided. At least please make sure that the first 66 characters describe the test uniquely. +* Make the description descriptive. “foo: x=2, y=4” is more descriptive than “foo #2”. “foo: 0 MBEDTLS_PK_SIGNATURE_MAX_SIZE +/* For RSA, the signature can be as large as the bignum module allows. + * For RSA_ALT, the signature size is not necessarily tied to what the + * bignum module can do, but in the absence of any specific setting, + * we use that (rsa_alt_sign_wrap in pk_wrap will check). */ +#undef MBEDTLS_PK_SIGNATURE_MAX_SIZE +#define MBEDTLS_PK_SIGNATURE_MAX_SIZE MBEDTLS_MPI_MAX_SIZE +#endif + +#if defined(MBEDTLS_ECDSA_C) && \ + MBEDTLS_ECDSA_MAX_LEN > MBEDTLS_PK_SIGNATURE_MAX_SIZE +/* For ECDSA, the ecdsa module exports a constant for the maximum + * signature size. */ +#undef MBEDTLS_PK_SIGNATURE_MAX_SIZE +#define MBEDTLS_PK_SIGNATURE_MAX_SIZE MBEDTLS_ECDSA_MAX_LEN +#endif + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#if PSA_ASYMMETRIC_SIGNATURE_MAX_SIZE > MBEDTLS_PK_SIGNATURE_MAX_SIZE +/* PSA_ASYMMETRIC_SIGNATURE_MAX_SIZE is the maximum size of a signature made + * through the PSA API in the PSA representation. */ +#undef MBEDTLS_PK_SIGNATURE_MAX_SIZE +#define MBEDTLS_PK_SIGNATURE_MAX_SIZE PSA_ASYMMETRIC_SIGNATURE_MAX_SIZE +#endif + +#if PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE + 11 > MBEDTLS_PK_SIGNATURE_MAX_SIZE +/* The Mbed TLS representation is different for ECDSA signatures: + * PSA uses the raw concatenation of r and s, + * whereas Mbed TLS uses the ASN.1 representation (SEQUENCE of two INTEGERs). + * Add the overhead of ASN.1: up to (1+2) + 2 * (1+2+1) for the + * types, lengths (represented by up to 2 bytes), and potential leading + * zeros of the INTEGERs and the SEQUENCE. */ +#undef MBEDTLS_PK_SIGNATURE_MAX_SIZE +#define MBEDTLS_PK_SIGNATURE_MAX_SIZE ( PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE + 11 ) +#endif +#endif /* defined(MBEDTLS_USE_PSA_CRYPTO) */ + /** * \brief Types for interfacing with the debug module */ @@ -442,8 +494,13 @@ int mbedtls_pk_verify_ext( mbedtls_pk_type_t type, const void *options, * \param md_alg Hash algorithm used (see notes) * \param hash Hash of the message to sign * \param hash_len Hash length or 0 (see notes) - * \param sig Place to write the signature - * \param sig_len Number of bytes written + * \param sig Place to write the signature. + * It must have enough room for the signature. + * #MBEDTLS_PK_SIGNATURE_MAX_SIZE is always enough. + * You may use a smaller buffer if it is large enough + * given the key type. + * \param sig_len On successful return, + * the number of bytes written to \p sig. * \param f_rng RNG function * \param p_rng RNG parameter * @@ -474,16 +531,21 @@ int mbedtls_pk_sign( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, * * \param ctx The PK context to use. It must have been set up * with a private key. - * \param md_alg Hash algorithm used (see notes) + * \param md_alg Hash algorithm used (see notes for mbedtls_pk_sign()) * \param hash Hash of the message to sign - * \param hash_len Hash length or 0 (see notes) - * \param sig Place to write the signature - * \param sig_len Number of bytes written + * \param hash_len Hash length or 0 (see notes for mbedtls_pk_sign()) + * \param sig Place to write the signature. + * It must have enough room for the signature. + * #MBEDTLS_PK_SIGNATURE_MAX_SIZE is always enough. + * You may use a smaller buffer if it is large enough + * given the key type. + * \param sig_len On successful return, + * the number of bytes written to \p sig. * \param f_rng RNG function * \param p_rng RNG parameter * \param rs_ctx Restart context (NULL to disable restart) * - * \return See \c mbedtls_pk_sign(), or + * \return See \c mbedtls_pk_sign(). * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of * operations was reached: see \c mbedtls_ecp_set_max_ops(). */ diff --git a/include/mbedtls/psa_util.h b/include/mbedtls/psa_util.h index 8d18fcc57..a87ca815b 100644 --- a/include/mbedtls/psa_util.h +++ b/include/mbedtls/psa_util.h @@ -230,9 +230,11 @@ static inline int mbedtls_psa_get_ecc_oid_from_id( *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_BP512R1 ); return( 0 ); #endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */ + default: + (void) oid; + (void) oid_len; + return( -1 ); } - - return( -1 ); } #define MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH 1 diff --git a/include/mbedtls/rsa.h b/include/mbedtls/rsa.h index 840540b0d..ec8d0d8de 100644 --- a/include/mbedtls/rsa.h +++ b/include/mbedtls/rsa.h @@ -907,7 +907,8 @@ int mbedtls_rsa_rsaes_oaep_decrypt( mbedtls_rsa_context *ctx, * the size of the hash corresponding to \p md_alg. * \param sig The buffer to hold the signature. This must be a writable * buffer of length \c ctx->len Bytes. For example, \c 256 Bytes - * for an 2048-bit RSA modulus. + * for an 2048-bit RSA modulus. A buffer length of + * #MBEDTLS_MPI_MAX_SIZE is always safe. * * \return \c 0 if the signing operation was successful. * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. @@ -954,7 +955,8 @@ int mbedtls_rsa_pkcs1_sign( mbedtls_rsa_context *ctx, * the size of the hash corresponding to \p md_alg. * \param sig The buffer to hold the signature. This must be a writable * buffer of length \c ctx->len Bytes. For example, \c 256 Bytes - * for an 2048-bit RSA modulus. + * for an 2048-bit RSA modulus. A buffer length of + * #MBEDTLS_MPI_MAX_SIZE is always safe. * * \return \c 0 if the signing operation was successful. * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. @@ -1015,7 +1017,8 @@ int mbedtls_rsa_rsassa_pkcs1_v15_sign( mbedtls_rsa_context *ctx, * the size of the hash corresponding to \p md_alg. * \param sig The buffer to hold the signature. This must be a writable * buffer of length \c ctx->len Bytes. For example, \c 256 Bytes - * for an 2048-bit RSA modulus. + * for an 2048-bit RSA modulus. A buffer length of + * #MBEDTLS_MPI_MAX_SIZE is always safe. * * \return \c 0 if the signing operation was successful. * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. diff --git a/include/mbedtls/version.h b/include/mbedtls/version.h index fd7783044..ae694eeda 100644 --- a/include/mbedtls/version.h +++ b/include/mbedtls/version.h @@ -39,17 +39,17 @@ * Major, Minor, Patchlevel */ #define MBEDTLS_VERSION_MAJOR 2 -#define MBEDTLS_VERSION_MINOR 17 -#define MBEDTLS_VERSION_PATCH 0 +#define MBEDTLS_VERSION_MINOR 19 +#define MBEDTLS_VERSION_PATCH 1 /** * The single version number has the following structure: * MMNNPP00 * Major version | Minor version | Patch version */ -#define MBEDTLS_VERSION_NUMBER 0x02110000 -#define MBEDTLS_VERSION_STRING "2.17.0" -#define MBEDTLS_VERSION_STRING_FULL "mbed TLS 2.17.0" +#define MBEDTLS_VERSION_NUMBER 0x02130100 +#define MBEDTLS_VERSION_STRING "2.19.1" +#define MBEDTLS_VERSION_STRING_FULL "mbed TLS 2.19.1" #if defined(MBEDTLS_VERSION_C) diff --git a/include/psa/crypto_sizes.h b/include/psa/crypto_sizes.h index bcca72482..33322472a 100644 --- a/include/psa/crypto_sizes.h +++ b/include/psa/crypto_sizes.h @@ -247,21 +247,6 @@ */ #define PSA_ALG_TLS12_PSK_TO_MS_MAX_PSK_LEN 128 -/** \def PSA_ASYMMETRIC_SIGNATURE_MAX_SIZE - * - * Maximum size of an asymmetric signature. - * - * This macro must expand to a compile-time constant integer. This value - * should be the maximum size of a MAC supported by the implementation, - * in bytes, and must be no smaller than this maximum. - */ -#define PSA_ASYMMETRIC_SIGNATURE_MAX_SIZE \ - PSA_BITS_TO_BYTES( \ - PSA_VENDOR_RSA_MAX_KEY_BITS > PSA_VENDOR_ECC_MAX_CURVE_BITS ? \ - PSA_VENDOR_RSA_MAX_KEY_BITS : \ - PSA_VENDOR_ECC_MAX_CURVE_BITS \ - ) - /** The maximum size of a block cipher supported by the implementation. */ #define PSA_MAX_BLOCK_CIPHER_BLOCK_SIZE 16 @@ -457,6 +442,22 @@ PSA_KEY_TYPE_IS_ECC(key_type) ? PSA_ECDSA_SIGNATURE_SIZE(key_bits) : \ ((void)alg, 0)) +#define PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE \ + PSA_ECDSA_SIGNATURE_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS) + +/** \def PSA_ASYMMETRIC_SIGNATURE_MAX_SIZE + * + * Maximum size of an asymmetric signature. + * + * This macro must expand to a compile-time constant integer. This value + * should be the maximum size of a signature supported by the implementation, + * in bytes, and must be no smaller than this maximum. + */ +#define PSA_ASYMMETRIC_SIGNATURE_MAX_SIZE \ + (PSA_BITS_TO_BYTES(PSA_VENDOR_RSA_MAX_KEY_BITS) > PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE ? \ + PSA_BITS_TO_BYTES(PSA_VENDOR_RSA_MAX_KEY_BITS) : \ + PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE) + /** Sufficient output buffer size for psa_asymmetric_encrypt(). * * This macro returns a sufficient buffer size for a ciphertext produced using diff --git a/library/Makefile b/library/Makefile index d7c156710..6aeb95f92 100644 --- a/library/Makefile +++ b/library/Makefile @@ -146,9 +146,11 @@ libmbedcrypto.dll: $(OBJS_CRYPTO) echo " LD $@" $(CC) -shared -Wl,-soname,$@ -Wl,--out-implib,$@.a -o $@ $(OBJS_CRYPTO) -lws2_32 -lwinmm -lgdi32 -static-libgcc $(LOCAL_LDFLAGS) $(LDFLAGS) +libmbedcrypto.$(DLEXT): | libmbedcrypto.a + .c.o: echo " CC $<" - $(CC) $(LOCAL_CFLAGS) $(CFLAGS) -c $< -o $@ + $(CC) $(LOCAL_CFLAGS) $(CFLAGS) -o $@ -c $< clean: ifndef WINDOWS diff --git a/library/bignum.c b/library/bignum.c index fd0e8b263..51015ec23 100644 --- a/library/bignum.c +++ b/library/bignum.c @@ -1733,6 +1733,7 @@ int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, int ret; size_t i, n, t, k; mbedtls_mpi X, Y, Z, T1, T2; + mbedtls_mpi_uint TP2[3]; MPI_VALIDATE_RET( A != NULL ); MPI_VALIDATE_RET( B != NULL ); @@ -1740,7 +1741,17 @@ int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO ); mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z ); - mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 ); + mbedtls_mpi_init( &T1 ); + /* + * Avoid dynamic memory allocations for constant-size T2. + * + * T2 is used for comparison only and the 3 limbs are assigned explicitly, + * so nobody increase the size of the MPI and we're safe to use an on-stack + * buffer. + */ + T2.s = 1; + T2.n = sizeof( TP2 ) / sizeof( *TP2 ); + T2.p = TP2; if( mbedtls_mpi_cmp_abs( A, B ) < 0 ) { @@ -1756,7 +1767,6 @@ int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T2, 3 ) ); k = mbedtls_mpi_bitlen( &Y ) % biL; if( k < biL - 1 ) @@ -1788,6 +1798,10 @@ int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, Y.p[t], NULL); } + T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2]; + T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1]; + T2.p[2] = X.p[i]; + Z.p[i - t - 1]++; do { @@ -1797,11 +1811,6 @@ int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1]; T1.p[1] = Y.p[t]; MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T2, 0 ) ); - T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2]; - T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1]; - T2.p[2] = X.p[i]; } while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 ); @@ -1837,7 +1846,8 @@ int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, cleanup: mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z ); - mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 ); + mbedtls_mpi_free( &T1 ); + mbedtls_platform_zeroize( TP2, sizeof( TP2 ) ); return( ret ); } diff --git a/library/entropy.c b/library/entropy.c index f8db1a550..d7091cbf7 100644 --- a/library/entropy.c +++ b/library/entropy.c @@ -258,7 +258,9 @@ int mbedtls_entropy_update_manual( mbedtls_entropy_context *ctx, */ static int entropy_gather_internal( mbedtls_entropy_context *ctx ) { - int ret, i, have_one_strong = 0; + int ret = MBEDTLS_ERR_ENTROPY_SOURCE_FAILED; + int i; + int have_one_strong = 0; unsigned char buf[MBEDTLS_ENTROPY_MAX_GATHER]; size_t olen; diff --git a/library/hmac_drbg.c b/library/hmac_drbg.c index 284c9b4e9..f71c95c44 100644 --- a/library/hmac_drbg.c +++ b/library/hmac_drbg.c @@ -74,7 +74,7 @@ int mbedtls_hmac_drbg_update_ret( mbedtls_hmac_drbg_context *ctx, unsigned char rounds = ( additional != NULL && add_len != 0 ) ? 2 : 1; unsigned char sep[1]; unsigned char K[MBEDTLS_MD_MAX_SIZE]; - int ret; + int ret = MBEDTLS_ERR_MD_BAD_INPUT_DATA; for( sep[0] = 0; sep[0] < rounds; sep[0]++ ) { diff --git a/library/pk_wrap.c b/library/pk_wrap.c index 5a699c030..702c3bbb4 100644 --- a/library/pk_wrap.c +++ b/library/pk_wrap.c @@ -774,6 +774,8 @@ static int rsa_alt_sign_wrap( void *ctx, mbedtls_md_type_t md_alg, #endif /* SIZE_MAX > UINT_MAX */ *sig_len = rsa_alt->key_len_func( rsa_alt->key ); + if( *sig_len > MBEDTLS_PK_SIGNATURE_MAX_SIZE ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); return( rsa_alt->sign_func( rsa_alt->key, f_rng, p_rng, MBEDTLS_RSA_PRIVATE, md_alg, (unsigned int) hash_len, hash, sig ) ); @@ -1017,6 +1019,8 @@ static int pk_opaque_sign_wrap( void *ctx, mbedtls_md_type_t md_alg, return( mbedtls_psa_err_translate_pk( status ) ); buf_len = MBEDTLS_ECDSA_MAX_SIG_LEN( psa_get_key_bits( &attributes ) ); psa_reset_key_attributes( &attributes ); + if( buf_len > MBEDTLS_PK_SIGNATURE_MAX_SIZE ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); /* make the signature */ status = psa_asymmetric_sign( *key, alg, hash, hash_len, diff --git a/library/pkwrite.c b/library/pkwrite.c index 438816078..c2c562348 100644 --- a/library/pkwrite.c +++ b/library/pkwrite.c @@ -38,7 +38,9 @@ #include "mbedtls/rsa.h" #endif #if defined(MBEDTLS_ECP_C) +#include "mbedtls/bignum.h" #include "mbedtls/ecp.h" +#include "mbedtls/platform_util.h" #endif #if defined(MBEDTLS_ECDSA_C) #include "mbedtls/ecdsa.h" @@ -154,6 +156,26 @@ static int pk_write_ec_param( unsigned char **p, unsigned char *start, return( (int) len ); } + +/* + * privateKey OCTET STRING -- always of length ceil(log2(n)/8) + */ +static int pk_write_ec_private( unsigned char **p, unsigned char *start, + mbedtls_ecp_keypair *ec ) +{ + int ret; + size_t byte_length = ( ec->grp.pbits + 7 ) / 8; + unsigned char tmp[MBEDTLS_ECP_MAX_BYTES]; + + ret = mbedtls_mpi_write_binary( &ec->d, tmp, byte_length ); + if( ret != 0 ) + goto exit; + ret = mbedtls_asn1_write_octet_string( p, start, tmp, byte_length ); + +exit: + mbedtls_platform_zeroize( tmp, byte_length ); + return( ret ); +} #endif /* MBEDTLS_ECP_C */ int mbedtls_pk_write_pubkey( unsigned char **p, unsigned char *start, @@ -424,9 +446,8 @@ int mbedtls_pk_write_key_der( mbedtls_pk_context *key, unsigned char *buf, size_ MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 0 ) ); len += par_len; - /* privateKey: write as MPI then fix tag */ - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf, &ec->d ) ); - *c = MBEDTLS_ASN1_OCTET_STRING; + /* privateKey */ + MBEDTLS_ASN1_CHK_ADD( len, pk_write_ec_private( &c, buf, ec ) ); /* version */ MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_int( &c, buf, 1 ) ); diff --git a/library/psa_crypto.c b/library/psa_crypto.c index 42c2969bf..e4d4924a9 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -2006,6 +2006,7 @@ exit: /* Message digests */ /****************************************************************/ +#if defined(MBEDTLS_RSA_C) || defined(MBEDTLS_ECDSA_DETERMINISTIC) static const mbedtls_md_info_t *mbedtls_md_info_from_psa( psa_algorithm_t alg ) { switch( alg ) @@ -2046,6 +2047,7 @@ static const mbedtls_md_info_t *mbedtls_md_info_from_psa( psa_algorithm_t alg ) return( NULL ); } } +#endif psa_status_t psa_hash_abort( psa_hash_operation_t *operation ) { diff --git a/library/psa_crypto_storage.c b/library/psa_crypto_storage.c index a27442cd9..1389fd451 100644 --- a/library/psa_crypto_storage.c +++ b/library/psa_crypto_storage.c @@ -419,7 +419,7 @@ psa_status_t psa_crypto_save_transaction( void ) { struct psa_storage_info_t p_info; psa_status_t status; - status = psa_its_get_info( PSA_CRYPTO_ITS_RANDOM_SEED_UID, &p_info ); + status = psa_its_get_info( PSA_CRYPTO_ITS_TRANSACTION_UID, &p_info ); if( status == PSA_SUCCESS ) { /* This shouldn't happen: we're trying to start a transaction while diff --git a/programs/Makefile b/programs/Makefile index add1a8649..f56df5f97 100644 --- a/programs/Makefile +++ b/programs/Makefile @@ -249,8 +249,8 @@ ifndef WINDOWS rm -f $(APPS) $(EXTRA_GENERATED) -rm -f test/cpp_dummy_build$(EXEXT) else - if exist *.o del /S /Q /F *.o - if exist *.exe del /S /Q /F *.exe + if exist *.o del /Q /F *.o + if exist *.exe del /Q /F *.exe if exist $(EXTRA_GENERATED) del /S /Q /F $(EXTRA_GENERATED) endif diff --git a/programs/pkey/pk_sign.c b/programs/pkey/pk_sign.c index 47a098a1a..a354e5b17 100644 --- a/programs/pkey/pk_sign.c +++ b/programs/pkey/pk_sign.c @@ -60,7 +60,6 @@ int main( void ) #include #include - int main( int argc, char *argv[] ) { FILE *f; @@ -70,7 +69,7 @@ int main( int argc, char *argv[] ) mbedtls_entropy_context entropy; mbedtls_ctr_drbg_context ctr_drbg; unsigned char hash[32]; - unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; + unsigned char buf[MBEDTLS_PK_SIGNATURE_MAX_SIZE]; char filename[512]; const char *pers = "mbedtls_pk_sign"; size_t olen = 0; diff --git a/programs/pkey/pk_verify.c b/programs/pkey/pk_verify.c index a6bfe3f29..72caf7139 100644 --- a/programs/pkey/pk_verify.c +++ b/programs/pkey/pk_verify.c @@ -65,7 +65,7 @@ int main( int argc, char *argv[] ) size_t i; mbedtls_pk_context pk; unsigned char hash[32]; - unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; + unsigned char buf[MBEDTLS_PK_SIGNATURE_MAX_SIZE]; char filename[512]; mbedtls_pk_init( &pk ); diff --git a/scripts/apidoc_full.sh b/scripts/apidoc_full.sh index bebab103e..dfe117710 100755 --- a/scripts/apidoc_full.sh +++ b/scripts/apidoc_full.sh @@ -19,7 +19,7 @@ fi CONFIG_BAK=${CONFIG_H}.bak cp -p $CONFIG_H $CONFIG_BAK -scripts/config.pl realfull +scripts/config.py realfull make apidoc mv $CONFIG_BAK $CONFIG_H diff --git a/scripts/config.pl b/scripts/config.pl index 8066bb019..95e31913a 100755 --- a/scripts/config.pl +++ b/scripts/config.pl @@ -1,296 +1,27 @@ #!/usr/bin/env perl -# -# This file is part of mbed TLS (https://tls.mbed.org) -# -# Copyright (c) 2014-2016, ARM Limited, All Rights Reserved -# -# Purpose -# -# Comments and uncomments #define lines in the given header file and optionally -# sets their value or can get the value. This is to provide scripting control of -# what preprocessor symbols, and therefore what build time configuration flags -# are set in the 'config.h' file. -# -# Usage: config.pl [-f | --file ] [-o | --force] -# [set | unset | get | -# full | realfull] -# -# Full usage description provided below. -# -# The following options are disabled instead of enabled with "full". -# -# MBEDTLS_TEST_NULL_ENTROPY -# MBEDTLS_DEPRECATED_REMOVED -# MBEDTLS_HAVE_SSE2 -# MBEDTLS_PLATFORM_NO_STD_FUNCTIONS -# MBEDTLS_ECP_DP_M221_ENABLED -# MBEDTLS_ECP_DP_M383_ENABLED -# MBEDTLS_ECP_DP_M511_ENABLED -# MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES -# MBEDTLS_NO_PLATFORM_ENTROPY -# MBEDTLS_RSA_NO_CRT -# MBEDTLS_PSA_CRYPTO_SPM -# MBEDTLS_PSA_INJECT_ENTROPY -# MBEDTLS_ECP_RESTARTABLE -# and any symbol beginning _ALT -# +# Backward compatibility redirection -use warnings; -use strict; +## Copyright (C) 2019, ARM Limited, All Rights Reserved +## SPDX-License-Identifier: Apache-2.0 +## +## Licensed under the Apache License, Version 2.0 (the "License"); you may +## not use this file except in compliance with the License. +## You may obtain a copy of the License at +## +## http://www.apache.org/licenses/LICENSE-2.0 +## +## Unless required by applicable law or agreed to in writing, software +## distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +## WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +## See the License for the specific language governing permissions and +## limitations under the License. +## +## This file is part of Mbed TLS (https://tls.mbed.org) -my $config_file = "include/mbedtls/config.h"; -my $usage = < | --file ] [-o | --force] - [set | unset | get | - full | realfull | baremetal] - -Commands - set [] - Uncomments or adds a #define for the to - the configuration file, and optionally making it - of . - If the symbol isn't present in the file an error - is returned. - unset - Comments out the #define for the given symbol if - present in the configuration file. - get - Finds the #define for the given symbol, returning - an exitcode of 0 if the symbol is found, and 1 if - not. The value of the symbol is output if one is - specified in the configuration file. - full - Uncomments all #define's in the configuration file - excluding some reserved symbols, until the - 'Module configuration options' section - realfull - Uncomments all #define's with no exclusions - baremetal - Sets full configuration suitable for baremetal build. - -Options - -f | --file - The file or file path for the configuration file - to edit. When omitted, the following default is - used: - $config_file - -o | --force - If the symbol isn't present in the configuration - file when setting its value, a #define is - appended to the end of the file. - -EOU - -my @excluded = qw( -MBEDTLS_TEST_NULL_ENTROPY -MBEDTLS_DEPRECATED_REMOVED -MBEDTLS_HAVE_SSE2 -MBEDTLS_PLATFORM_NO_STD_FUNCTIONS -MBEDTLS_CTR_DRBG_USE_128_BIT_KEY -MBEDTLS_ECP_DP_M221_ENABLED -MBEDTLS_ECP_DP_M383_ENABLED -MBEDTLS_ECP_DP_M511_ENABLED -MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES -MBEDTLS_NO_PLATFORM_ENTROPY -MBEDTLS_RSA_NO_CRT -MBEDTLS_NO_UDBL_DIVISION -MBEDTLS_NO_64BIT_MULTIPLICATION -MBEDTLS_PSA_CRYPTO_SE_C -MBEDTLS_PSA_CRYPTO_SPM -MBEDTLS_PSA_CRYPTO_KEY_FILE_ID_ENCODES_OWNER -MBEDTLS_PSA_INJECT_ENTROPY -MBEDTLS_ECP_RESTARTABLE -MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED -_ALT\s*$ -); - -# Things that should be disabled in "baremetal" -my @excluded_baremetal = qw( -MBEDTLS_TIMING_C -MBEDTLS_FS_IO -MBEDTLS_ENTROPY_NV_SEED -MBEDTLS_HAVE_TIME -MBEDTLS_HAVE_TIME_DATE -MBEDTLS_DEPRECATED_WARNING -MBEDTLS_HAVEGE_C -MBEDTLS_THREADING_C -MBEDTLS_THREADING_PTHREAD -MBEDTLS_MEMORY_BACKTRACE -MBEDTLS_MEMORY_BUFFER_ALLOC_C -MBEDTLS_PLATFORM_TIME_ALT -MBEDTLS_PLATFORM_FPRINTF_ALT -MBEDTLS_PSA_ITS_FILE_C -MBEDTLS_PSA_CRYPTO_SE_C -MBEDTLS_PSA_CRYPTO_STORAGE_C -); - -# Things that should be enabled in "full" even if they match @excluded -my @non_excluded = qw( -PLATFORM_[A-Z0-9]+_ALT -); - -# Things that should be enabled in "baremetal" -my @non_excluded_baremetal = qw( -MBEDTLS_NO_PLATFORM_ENTROPY -); - -# Process the command line arguments - -my $force_option = 0; - -my ($arg, $name, $value, $action); - -while ($arg = shift) { - - # Check if the argument is an option - if ($arg eq "-f" || $arg eq "--file") { - $config_file = shift; - - -f $config_file or die "No such file: $config_file\n"; - - } - elsif ($arg eq "-o" || $arg eq "--force") { - $force_option = 1; - - } - else - { - # ...else assume it's a command - $action = $arg; - - if ($action eq "full" || $action eq "realfull" || $action eq "baremetal" ) { - # No additional parameters - die $usage if @ARGV; - - } - elsif ($action eq "unset" || $action eq "get") { - die $usage unless @ARGV; - $name = shift; - - } - elsif ($action eq "set") { - die $usage unless @ARGV; - $name = shift; - $value = shift if @ARGV; - - } - else { - die "Command '$action' not recognised.\n\n".$usage; - } - } -} - -# If no command was specified, exit... -if ( not defined($action) ){ die $usage; } - -# Check the config file is present -if (! -f $config_file) { - - chdir '..' or die; - - # Confirm this is the project root directory and try again - if ( !(-d 'scripts' && -d 'include' && -d 'library' && -f $config_file) ) { - die "If no file specified, must be run from the project root or scripts directory.\n"; - } -} - - -# Now read the file and process the contents - -open my $config_read, '<', $config_file or die "read $config_file: $!\n"; -my @config_lines = <$config_read>; -close $config_read; - -# Add required baremetal symbols to the list that is included. -if ( $action eq "baremetal" ) { - @non_excluded = ( @non_excluded, @non_excluded_baremetal ); -} - -my ($exclude_re, $no_exclude_re, $exclude_baremetal_re); -if ($action eq "realfull") { - $exclude_re = qr/^$/; - $no_exclude_re = qr/./; -} else { - $exclude_re = join '|', @excluded; - $no_exclude_re = join '|', @non_excluded; -} -if ( $action eq "baremetal" ) { - $exclude_baremetal_re = join '|', @excluded_baremetal; -} - -my $config_write = undef; -if ($action ne "get") { - open $config_write, '>', $config_file or die "write $config_file: $!\n"; -} - -my $done; -for my $line (@config_lines) { - if ($action eq "full" || $action eq "realfull" || $action eq "baremetal" ) { - if ($line =~ /name SECTION: Module configuration options/) { - $done = 1; - } - - if (!$done && $line =~ m!^//\s?#define! && - ( $line !~ /$exclude_re/ || $line =~ /$no_exclude_re/ ) && - ( $action ne "baremetal" || ( $line !~ /$exclude_baremetal_re/ ) ) ) { - $line =~ s!^//\s?!!; - } - if (!$done && $line =~ m!^\s?#define! && - ! ( ( $line !~ /$exclude_re/ || $line =~ /$no_exclude_re/ ) && - ( $action ne "baremetal" || ( $line !~ /$exclude_baremetal_re/ ) ) ) ) { - $line =~ s!^!//!; - } - } elsif ($action eq "unset") { - if (!$done && $line =~ /^\s*#define\s*$name\b/) { - $line = '//' . $line; - $done = 1; - } - } elsif (!$done && $action eq "set") { - if ($line =~ m!^(?://)?\s*#define\s*$name\b!) { - $line = "#define $name"; - $line .= " $value" if defined $value && $value ne ""; - $line .= "\n"; - $done = 1; - } - } elsif (!$done && $action eq "get") { - if ($line =~ /^\s*#define\s*$name(?:\s+(.*?))\s*(?:$|\/\*|\/\/)/) { - $value = $1; - $done = 1; - } - } - - if (defined $config_write) { - print $config_write $line or die "write $config_file: $!\n"; - } -} - -# Did the set command work? -if ($action eq "set" && $force_option && !$done) { - - # If the force option was set, append the symbol to the end of the file - my $line = "#define $name"; - $line .= " $value" if defined $value && $value ne ""; - $line .= "\n"; - $done = 1; - - print $config_write $line or die "write $config_file: $!\n"; -} - -if (defined $config_write) { - close $config_write or die "close $config_file: $!\n"; -} - -if ($action eq "get") { - if ($done) { - if ($value ne '') { - print "$value\n"; - } - exit 0; - } else { - # If the symbol was not found, return an error - exit 1; - } -} - -if ($action eq "full" && !$done) { - die "Configuration section was not found in $config_file\n"; - -} - -if ($action ne "full" && $action ne "unset" && !$done) { - die "A #define for the symbol $name was not found in $config_file\n"; -} - -__END__ +my $py = $0; +$py =~ s/\.pl$/.py/; +exec 'python3', $py, @ARGV; +print STDERR "$0: python3: $!\n"; +exec 'python', $py, @ARGV; +print STDERR "$0: python: $!\n"; +exit 127; diff --git a/scripts/config.py b/scripts/config.py new file mode 100755 index 000000000..db2661c92 --- /dev/null +++ b/scripts/config.py @@ -0,0 +1,420 @@ +#!/usr/bin/env python3 + +"""Mbed TLS configuration file manipulation library and tool + +Basic usage, to read the Mbed TLS or Mbed Crypto configuration: + config = ConfigFile() + if 'MBEDTLS_RSA_C' in config: print('RSA is enabled') +""" + +## Copyright (C) 2019, ARM Limited, All Rights Reserved +## SPDX-License-Identifier: Apache-2.0 +## +## Licensed under the Apache License, Version 2.0 (the "License"); you may +## not use this file except in compliance with the License. +## You may obtain a copy of the License at +## +## http://www.apache.org/licenses/LICENSE-2.0 +## +## Unless required by applicable law or agreed to in writing, software +## distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +## WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +## See the License for the specific language governing permissions and +## limitations under the License. +## +## This file is part of Mbed TLS (https://tls.mbed.org) + +import os +import re + +class Setting: + """Representation of one Mbed TLS config.h setting. + + Fields: + * name: the symbol name ('MBEDTLS_xxx'). + * value: the value of the macro. The empty string for a plain #define + with no value. + * active: True if name is defined, False if a #define for name is + present in config.h but commented out. + * section: the name of the section that contains this symbol. + """ + # pylint: disable=too-few-public-methods + def __init__(self, active, name, value='', section=None): + self.active = active + self.name = name + self.value = value + self.section = section + +class Config: + """Representation of the Mbed TLS configuration. + + In the documentation of this class, a symbol is said to be *active* + if there is a #define for it that is not commented out, and *known* + if there is a #define for it whether commented out or not. + + This class supports the following protocols: + * `name in config` is `True` if the symbol `name` is active, `False` + otherwise (whether `name` is inactive or not known). + * `config[name]` is the value of the macro `name`. If `name` is inactive, + raise `KeyError` (even if `name` is known). + * `config[name] = value` sets the value associated to `name`. `name` + must be known, but does not need to be set. This does not cause + name to become set. + """ + + def __init__(self): + self.settings = {} + + def __contains__(self, name): + """True if the given symbol is active (i.e. set). + + False if the given symbol is not set, even if a definition + is present but commented out. + """ + return name in self.settings and self.settings[name].active + + def all(self, *names): + """True if all the elements of names are active (i.e. set).""" + return all(self.__contains__(name) for name in names) + + def any(self, *names): + """True if at least one symbol in names are active (i.e. set).""" + return any(self.__contains__(name) for name in names) + + def known(self, name): + """True if a #define for name is present, whether it's commented out or not.""" + return name in self.settings + + def __getitem__(self, name): + """Get the value of name, i.e. what the preprocessor symbol expands to. + + If name is not known, raise KeyError. name does not need to be active. + """ + return self.settings[name].value + + def get(self, name, default=None): + """Get the value of name. If name is inactive (not set), return default. + + If a #define for name is present and not commented out, return + its expansion, even if this is the empty string. + + If a #define for name is present but commented out, return default. + """ + if name in self.settings: + return self.settings[name].value + else: + return default + + def __setitem__(self, name, value): + """If name is known, set its value. + + If name is not known, raise KeyError. + """ + self.settings[name].value = value + + def set(self, name, value=None): + """Set name to the given value and make it active. + + If value is None and name is already known, don't change its value. + If value is None and name is not known, set its value to the empty + string. + """ + if name in self.settings: + if value is not None: + self.settings[name].value = value + self.settings[name].active = True + else: + self.settings[name] = Setting(True, name, value=value) + + def unset(self, name): + """Make name unset (inactive). + + name remains known if it was known before. + """ + if name not in self.settings: + return + self.settings[name].active = False + + def adapt(self, adapter): + """Run adapter on each known symbol and (de)activate it accordingly. + + `adapter` must be a function that returns a boolean. It is called as + `adapter(name, active, section)` for each setting, where `active` is + `True` if `name` is set and `False` if `name` is known but unset, + and `section` is the name of the section containing `name`. If + `adapter` returns `True`, then set `name` (i.e. make it active), + otherwise unset `name` (i.e. make it known but inactive). + """ + for setting in self.settings.values(): + setting.active = adapter(setting.name, setting.active, + setting.section) + +def is_full_section(section): + """Is this section affected by "config.py full" and friends?""" + return section.endswith('support') or section.endswith('modules') + +def realfull_adapter(_name, active, section): + """Activate all symbols found in the system and feature sections.""" + if not is_full_section(section): + return active + return True + +def include_in_full(name): + """Rules for symbols in the "full" configuration.""" + if re.search(r'PLATFORM_[A-Z0-9]+_ALT', name): + return True + if name in [ + 'MBEDTLS_CTR_DRBG_USE_128_BIT_KEY', + 'MBEDTLS_DEPRECATED_REMOVED', + 'MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED', + 'MBEDTLS_ECP_RESTARTABLE', + 'MBEDTLS_HAVE_SSE2', + 'MBEDTLS_MEMORY_BACKTRACE', + 'MBEDTLS_MEMORY_BUFFER_ALLOC_C', + 'MBEDTLS_MEMORY_DEBUG', + 'MBEDTLS_NO_64BIT_MULTIPLICATION', + 'MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES', + 'MBEDTLS_NO_PLATFORM_ENTROPY', + 'MBEDTLS_NO_UDBL_DIVISION', + 'MBEDTLS_PLATFORM_NO_STD_FUNCTIONS', + 'MBEDTLS_PSA_CRYPTO_KEY_FILE_ID_ENCODES_OWNER', + 'MBEDTLS_PSA_CRYPTO_SE_C', + 'MBEDTLS_PSA_CRYPTO_SPM', + 'MBEDTLS_PSA_INJECT_ENTROPY', + 'MBEDTLS_RSA_NO_CRT', + 'MBEDTLS_TEST_NULL_ENTROPY', + ]: + return False + if name.endswith('_ALT'): + return False + return True + +def full_adapter(name, active, section): + """Config adapter for "full".""" + if not is_full_section(section): + return active + return include_in_full(name) + +def keep_in_baremetal(name): + """Rules for symbols in the "baremetal" configuration.""" + if name in [ + 'MBEDTLS_DEPRECATED_WARNING', + 'MBEDTLS_ENTROPY_NV_SEED', + 'MBEDTLS_FS_IO', + 'MBEDTLS_HAVEGE_C', + 'MBEDTLS_HAVE_TIME', + 'MBEDTLS_HAVE_TIME_DATE', + 'MBEDTLS_PLATFORM_FPRINTF_ALT', + 'MBEDTLS_PLATFORM_TIME_ALT', + 'MBEDTLS_PSA_CRYPTO_SE_C', + 'MBEDTLS_PSA_CRYPTO_STORAGE_C', + 'MBEDTLS_PSA_ITS_FILE_C', + 'MBEDTLS_THREADING_C', + 'MBEDTLS_THREADING_PTHREAD', + 'MBEDTLS_TIMING_C', + ]: + return False + return True + +def baremetal_adapter(name, active, section): + """Config adapter for "baremetal".""" + if not is_full_section(section): + return active + if name == 'MBEDTLS_NO_PLATFORM_ENTROPY': + return True + return include_in_full(name) and keep_in_baremetal(name) + +class ConfigFile(Config): + """Representation of the Mbed TLS configuration read for a file. + + See the documentation of the `Config` class for methods to query + and modify the configuration. + """ + + _path_in_tree = 'include/mbedtls/config.h' + default_path = [_path_in_tree, + os.path.join(os.path.dirname(__file__), + os.pardir, + _path_in_tree), + os.path.join(os.path.dirname(os.path.abspath(os.path.dirname(__file__))), + _path_in_tree)] + + def __init__(self, filename=None): + """Read the Mbed TLS configuration file.""" + if filename is None: + for filename in self.default_path: + if os.path.lexists(filename): + break + super().__init__() + self.filename = filename + self.current_section = 'header' + with open(filename, 'r', encoding='utf-8') as file: + self.templates = [self._parse_line(line) for line in file] + self.current_section = None + + def set(self, name, value=None): + if name not in self.settings: + self.templates.append((name, '', '#define ' + name + ' ')) + super().set(name, value) + + _define_line_regexp = (r'(?P\s*)' + + r'(?P(//\s*)?)' + + r'(?P#\s*define\s+)' + + r'(?P\w+)' + + r'(?P(?:\((?:\w|\s|,)*\))?)' + + r'(?P\s*)' + + r'(?P.*)') + _section_line_regexp = (r'\s*/?\*+\s*[\\@]name\s+SECTION:\s*' + + r'(?P
.*)[ */]*') + _config_line_regexp = re.compile(r'|'.join([_define_line_regexp, + _section_line_regexp])) + def _parse_line(self, line): + """Parse a line in config.h and return the corresponding template.""" + line = line.rstrip('\r\n') + m = re.match(self._config_line_regexp, line) + if m is None: + return line + elif m.group('section'): + self.current_section = m.group('section') + return line + else: + active = not m.group('commented_out') + name = m.group('name') + value = m.group('value') + template = (name, + m.group('indentation'), + m.group('define') + name + + m.group('arguments') + m.group('separator')) + self.settings[name] = Setting(active, name, value, + self.current_section) + return template + + def _format_template(self, name, indent, middle): + """Build a line for config.h for the given setting. + + The line has the form "#define " + where is "#define ". + """ + setting = self.settings[name] + value = setting.value + if value is None: + value = '' + # Normally the whitespace to separte the symbol name from the + # value is part of middle, and there's no whitespace for a symbol + # with no value. But if a symbol has been changed from having a + # value to not having one, the whitespace is wrong, so fix it. + if value: + if middle[-1] not in '\t ': + middle += ' ' + else: + middle = middle.rstrip() + return ''.join([indent, + '' if setting.active else '//', + middle, + value]).rstrip() + + def write_to_stream(self, output): + """Write the whole configuration to output.""" + for template in self.templates: + if isinstance(template, str): + line = template + else: + line = self._format_template(*template) + output.write(line + '\n') + + def write(self, filename=None): + """Write the whole configuration to the file it was read from. + + If filename is specified, write to this file instead. + """ + if filename is None: + filename = self.filename + with open(filename, 'w', encoding='utf-8') as output: + self.write_to_stream(output) + +if __name__ == '__main__': + def main(): + """Command line config.h manipulation tool.""" + parser = argparse.ArgumentParser(description=""" + Mbed TLS and Mbed Crypto configuration file manipulation tool. + """) + parser.add_argument('--file', '-f', + help="""File to read (and modify if requested). + Default: {}. + """.format(ConfigFile.default_path)) + parser.add_argument('--force', '-o', + action='store_true', + help="""For the set command, if SYMBOL is not + present, add a definition for it.""") + parser.add_argument('--write', '-w', metavar='FILE', + help="""File to write to instead of the input file.""") + subparsers = parser.add_subparsers(dest='command', + title='Commands') + parser_get = subparsers.add_parser('get', + help="""Find the value of SYMBOL + and print it. Exit with + status 0 if a #define for SYMBOL is + found, 1 otherwise. + """) + parser_get.add_argument('symbol', metavar='SYMBOL') + parser_set = subparsers.add_parser('set', + help="""Set SYMBOL to VALUE. + If VALUE is omitted, just uncomment + the #define for SYMBOL. + Error out of a line defining + SYMBOL (commented or not) is not + found, unless --force is passed. + """) + parser_set.add_argument('symbol', metavar='SYMBOL') + parser_set.add_argument('value', metavar='VALUE', nargs='?', + default='') + parser_unset = subparsers.add_parser('unset', + help="""Comment out the #define + for SYMBOL. Do nothing if none + is present.""") + parser_unset.add_argument('symbol', metavar='SYMBOL') + + def add_adapter(name, function, description): + subparser = subparsers.add_parser(name, help=description) + subparser.set_defaults(adapter=function) + add_adapter('baremetal', baremetal_adapter, + """Like full, but exclude features that require platform + features such as file input-output.""") + add_adapter('full', full_adapter, + """Uncomment most features. + Exclude alternative implementations and platform support + options, as well as some options that are awkward to test. + """) + add_adapter('realfull', realfull_adapter, + """Uncomment all boolean #defines. + Suitable for generating documentation, but not for building.""") + + args = parser.parse_args() + config = ConfigFile(args.file) + if args.command is None: + parser.print_help() + return 1 + elif args.command == 'get': + if args.symbol in config: + value = config[args.symbol] + if value: + sys.stdout.write(value + '\n') + return args.symbol not in config + elif args.command == 'set': + if not args.force and args.symbol not in config.settings: + sys.stderr.write("A #define for the symbol {} " + "was not found in {}\n" + .format(args.symbol, config.filename)) + return 1 + config.set(args.symbol, value=args.value) + elif args.command == 'unset': + config.unset(args.symbol) + else: + config.adapt(args.adapter) + config.write(args.write) + + # Import modules only used by main only if main is defined and called. + # pylint: disable=wrong-import-position + import argparse + import sys + sys.exit(main()) diff --git a/scripts/ecc-heap.sh b/scripts/ecc-heap.sh index 94a04cf7e..69777a62c 100755 --- a/scripts/ecc-heap.sh +++ b/scripts/ecc-heap.sh @@ -59,8 +59,8 @@ EOF for F in 0 1; do for W in 2 3 4 5 6; do - scripts/config.pl set MBEDTLS_ECP_WINDOW_SIZE $W - scripts/config.pl set MBEDTLS_ECP_FIXED_POINT_OPTIM $F + scripts/config.py set MBEDTLS_ECP_WINDOW_SIZE $W + scripts/config.py set MBEDTLS_ECP_FIXED_POINT_OPTIM $F make benchmark >/dev/null 2>&1 echo "fixed point optim = $F, max window size = $W" echo "--------------------------------------------" diff --git a/scripts/footprint.sh b/scripts/footprint.sh index 697972f33..6cabcb925 100755 --- a/scripts/footprint.sh +++ b/scripts/footprint.sh @@ -62,9 +62,9 @@ doit() fi { - scripts/config.pl unset MBEDTLS_TIMING_C || true - scripts/config.pl unset MBEDTLS_FS_IO || true - scripts/config.pl --force set MBEDTLS_NO_PLATFORM_ENTROPY || true + scripts/config.py unset MBEDTLS_TIMING_C || true + scripts/config.py unset MBEDTLS_FS_IO || true + scripts/config.py --force set MBEDTLS_NO_PLATFORM_ENTROPY || true } >/dev/null 2>&1 make clean >/dev/null diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index bcf462f39..3b923a3a3 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -9,9 +9,9 @@ if(NOT DEFINED MBEDTLS_DIR) set(MBEDTLS_DIR ${CMAKE_SOURCE_DIR}) endif() -find_package(Perl) -if(NOT PERL_FOUND) - message(FATAL_ERROR "Cannot build test suites without Perl") +find_package(PythonInterp) +if(NOT PYTHONINTERP_FOUND) + message(FATAL_ERROR "Cannot build test suites without Python 2 or 3") endif() # Enable definition of various functions used throughout the testsuite diff --git a/tests/data_files/ec_256_long_prv.pem b/tests/data_files/ec_256_long_prv.pem new file mode 100644 index 000000000..5141e30b4 --- /dev/null +++ b/tests/data_files/ec_256_long_prv.pem @@ -0,0 +1,5 @@ +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIIcex4mqXsQamUKTVf8vXmTAJrQvGjh5mXG8p9+OR4xAoAoGCCqGSM49 +AwEHoUQDQgAEqJ2HQjPpc6fDwE/vSa6U35USXawkTo98y4U6NsAl+rOGuqMPEFXf +P1Srm/Jrzwa/RuppRL5kgyAsGJTUmwZEzQ== +-----END EC PRIVATE KEY----- diff --git a/tests/data_files/ec_521_short_prv.pem b/tests/data_files/ec_521_short_prv.pem new file mode 100644 index 000000000..427b7ad47 --- /dev/null +++ b/tests/data_files/ec_521_short_prv.pem @@ -0,0 +1,7 @@ +-----BEGIN EC PRIVATE KEY----- +MIHcAgEBBEIAOXdk7W+Hf5L7Hc9fKe44wmpaRNs5ERFTkv5CrlXv/Bu3y28M673q +vBNo7a/UE/6NNQHu2pQODEYFpMg6R34b5SigBwYFK4EEACOhgYkDgYYABAFUMHXV +KPA4vkMgq+pFgDoH96XoM517gF2GJFV6h2gLhykzIHL/otAyEpAStw7MBvbU0V21 +ixB+hjqzO7Snxaj9mwB8g87OKxm5eGfsqvJNPdJ0RZ/EKy06Ukg6KThlhQeyrtIk +g5PTCrPnNszlffAy6/jCOe3Moi59g15H13sSzwfX6g== +-----END EC PRIVATE KEY----- diff --git a/tests/scripts/all.sh b/tests/scripts/all.sh index 2414f452a..2567cc0dd 100755 --- a/tests/scripts/all.sh +++ b/tests/scripts/all.sh @@ -112,9 +112,15 @@ pre_initialize_variables () { CONFIG_H='include/mbedtls/config.h' CONFIG_BAK="$CONFIG_H.bak" + append_outcome=0 FORCE=0 KEEP_GOING=0 + : ${MBEDTLS_TEST_OUTCOME_FILE=} + : ${MBEDTLS_TEST_PLATFORM="$(uname -s | tr -c \\n0-9A-Za-z _)-$(uname -m | tr -c \\n0-9A-Za-z _)"} + export MBEDTLS_TEST_OUTCOME_FILE + export MBEDTLS_TEST_PLATFORM + # Default commands, can be overridden by the environment : ${OUT_OF_SOURCE_DIR:=./mbedtls_out_of_source_build} : ${ARMC5_BIN_DIR:=/usr/bin} @@ -183,14 +189,18 @@ General options: -f|--force Force the tests to overwrite any modified files. -k|--keep-going Run all tests and report errors at the end. -m|--memory Additional optional memory tests. + --append-outcome Append to the outcome file (if used). --armcc Run ARM Compiler builds (on by default). --except Exclude the COMPONENTs listed on the command line, instead of running only those. + --no-append-outcome Write a new outcome file and analyze it (default). --no-armcc Skip ARM Compiler builds. --no-force Refuse to overwrite modified files (default). --no-keep-going Stop at the first error (default). --no-memory No additional memory tests (default). --out-of-source-dir= Directory used for CMake out-of-source build tests. + --outcome-file= File where test outcomes are written (not done if + empty; default: \$MBEDTLS_TEST_OUTCOME_FILE). --random-seed Use a random seed value for randomized tests (default). -r|--release-test Run this script in release mode. This fixes the seed value to 1. -s|--seed Integer seed value to use for this test run. @@ -309,6 +319,7 @@ pre_parse_command_line () { # all.sh will still run and work properly. while [ $# -gt 0 ]; do case "$1" in + --append-outcome) append_outcome=1;; --armcc) no_armcc=;; --armc5-bin-dir) shift; ARMC5_BIN_DIR="$1";; --armc6-bin-dir) shift; ARMC6_BIN_DIR="$1";; @@ -323,6 +334,7 @@ pre_parse_command_line () { --list-all-components) printf '%s\n' $ALL_COMPONENTS; exit;; --list-components) printf '%s\n' $SUPPORTED_COMPONENTS; exit;; --memory|-m) ;; + --no-append-outcome) append_outcome=0;; --no-armcc) no_armcc=1;; --no-force) FORCE=0;; --no-keep-going) KEEP_GOING=0;; @@ -330,6 +342,7 @@ pre_parse_command_line () { --openssl) shift;; --openssl-legacy) shift;; --openssl-next) shift;; + --outcome-file) shift; MBEDTLS_TEST_OUTCOME_FILE="$1";; --out-of-source-dir) shift; OUT_OF_SOURCE_DIR="$1";; --random-seed) ;; --release-test|-r) ;; @@ -464,9 +477,19 @@ not() { ! "$@" } +pre_prepare_outcome_file () { + case "$MBEDTLS_TEST_OUTCOME_FILE" in + [!/]*) MBEDTLS_TEST_OUTCOME_FILE="$PWD/$MBEDTLS_TEST_OUTCOME_FILE";; + esac + if [ -n "$MBEDTLS_TEST_OUTCOME_FILE" ] && [ "$append_outcome" -eq 0 ]; then + rm -f "$MBEDTLS_TEST_OUTCOME_FILE" + fi +} + pre_print_configuration () { msg "info: $0 configuration" echo "FORCE: $FORCE" + echo "MBEDTLS_TEST_OUTCOME_FILE: ${MBEDTLS_TEST_OUTCOME_FILE:-(none)}" echo "ARMC5_BIN_DIR: $ARMC5_BIN_DIR" echo "ARMC6_BIN_DIR: $ARMC6_BIN_DIR" } @@ -528,32 +551,37 @@ pre_check_tools () { # Indicative running times are given for reference. component_check_recursion () { - msg "test: recursion.pl" # < 1s + msg "Check: recursion.pl" # < 1s record_status tests/scripts/recursion.pl library/*.c } component_check_generated_files () { - msg "test: freshness of generated source files" # < 1s + msg "Check: freshness of generated source files" # < 1s record_status tests/scripts/check-generated-files.sh } component_check_doxy_blocks () { - msg "test: doxygen markup outside doxygen blocks" # < 1s + msg "Check: doxygen markup outside doxygen blocks" # < 1s record_status tests/scripts/check-doxy-blocks.pl } component_check_files () { - msg "test: check-files.py" # < 1s + msg "Check: file sanity checks (permissions, encodings)" # < 1s record_status tests/scripts/check-files.py } component_check_names () { - msg "test/build: declared and exported names" # < 3s + msg "Check: declared and exported names (builds the library)" # < 3s record_status tests/scripts/check-names.sh -v } +component_check_test_cases () { + msg "Check: test case descriptions" # < 1s + record_status tests/scripts/check-test-cases.py +} + component_check_doxygen_warnings () { - msg "test: doxygen warnings" # ~ 3s + msg "Check: doxygen warnings (builds the documentation)" # ~ 3s record_status tests/scripts/doxygen.sh } @@ -565,12 +593,18 @@ component_check_doxygen_warnings () { component_test_default_out_of_box () { msg "build: make, default config (out-of-box)" # ~1min make + # Disable fancy stuff + SAVE_MBEDTLS_TEST_OUTCOME_FILE="$MBEDTLS_TEST_OUTCOME_FILE" + unset MBEDTLS_TEST_OUTCOME_FILE msg "test: main suites make, default config (out-of-box)" # ~10s make test msg "selftest: make, default config (out-of-box)" # ~10s programs/test/selftest + + export MBEDTLS_TEST_OUTCOME_FILE="$SAVE_MBEDTLS_TEST_OUTCOME_FILE" + unset SAVE_MBEDTLS_TEST_OUTCOME_FILE } component_test_default_cmake_gcc_asan () { @@ -582,6 +616,16 @@ component_test_default_cmake_gcc_asan () { make test } +component_test_full_cmake_gcc_asan () { + msg "build: full config, cmake, gcc, ASan" + scripts/config.py full + CC=gcc cmake -D CMAKE_BUILD_TYPE:String=Asan . + make + + msg "test: main suites (inc. selftests) (full config, ASan build)" + make test +} + component_test_ref_configs () { msg "test/build: ref-configs (ASan build)" # ~ 6 min 20s CC=gcc cmake -D CMAKE_BUILD_TYPE:String=Asan . @@ -590,10 +634,10 @@ component_test_ref_configs () { component_test_no_pem_no_fs () { msg "build: Default + !MBEDTLS_PEM_PARSE_C + !MBEDTLS_FS_IO (ASan build)" - scripts/config.pl unset MBEDTLS_PEM_PARSE_C - scripts/config.pl unset MBEDTLS_FS_IO - scripts/config.pl unset MBEDTLS_PSA_ITS_FILE_C # requires a filesystem - scripts/config.pl unset MBEDTLS_PSA_CRYPTO_STORAGE_C # requires PSA ITS + scripts/config.py unset MBEDTLS_PEM_PARSE_C + scripts/config.py unset MBEDTLS_FS_IO + scripts/config.py unset MBEDTLS_PSA_ITS_FILE_C # requires a filesystem + scripts/config.py unset MBEDTLS_PSA_CRYPTO_STORAGE_C # requires PSA ITS CC=gcc cmake -D CMAKE_BUILD_TYPE:String=Asan . make @@ -603,7 +647,7 @@ component_test_no_pem_no_fs () { component_test_rsa_no_crt () { msg "build: Default + RSA_NO_CRT (ASan build)" # ~ 6 min - scripts/config.pl set MBEDTLS_RSA_NO_CRT + scripts/config.py set MBEDTLS_RSA_NO_CRT CC=gcc cmake -D CMAKE_BUILD_TYPE:String=Asan . make @@ -613,7 +657,7 @@ component_test_rsa_no_crt () { component_test_new_ecdh_context () { msg "build: new ECDH context (ASan build)" # ~ 6 min - scripts/config.pl unset MBEDTLS_ECDH_LEGACY_CONTEXT + scripts/config.py unset MBEDTLS_ECDH_LEGACY_CONTEXT CC=gcc cmake -D CMAKE_BUILD_TYPE:String=Asan . make @@ -623,8 +667,8 @@ component_test_new_ecdh_context () { component_test_everest () { msg "build: Everest ECDH context (ASan build)" # ~ 6 min - scripts/config.pl unset MBEDTLS_ECDH_LEGACY_CONTEXT - scripts/config.pl set MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED + scripts/config.py unset MBEDTLS_ECDH_LEGACY_CONTEXT + scripts/config.py set MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED CC=clang cmake -D CMAKE_BUILD_TYPE:String=Asan . make @@ -634,8 +678,7 @@ component_test_everest () { component_test_psa_collect_statuses () { msg "build+test: psa_collect_statuses" # ~30s - scripts/config.pl full - scripts/config.pl unset MBEDTLS_MEMORY_BUFFER_ALLOC_C # slow and irrelevant + scripts/config.py full record_status tests/scripts/psa_collect_statuses.py # Check that psa_crypto_init() succeeded at least once record_status grep -q '^0:psa_crypto_init:' tests/statuses.log @@ -644,8 +687,7 @@ component_test_psa_collect_statuses () { component_test_full_cmake_clang () { msg "build: cmake, full config, clang" # ~ 50s - scripts/config.pl full - scripts/config.pl unset MBEDTLS_MEMORY_BACKTRACE # too slow for tests + scripts/config.py full CC=clang cmake -D CMAKE_BUILD_TYPE:String=Check -D ENABLE_TESTING=On . make @@ -658,8 +700,7 @@ component_test_full_cmake_clang () { component_test_full_make_gcc_o0 () { msg "build: make, full config, gcc -O0" # ~ 50s - scripts/config.pl full - scripts/config.pl unset MBEDTLS_MEMORY_BACKTRACE # too slow for tests + scripts/config.py full make CC=gcc CFLAGS='-O0' msg "test: main suites (full config, gcc -O0)" # ~ 5s @@ -668,8 +709,8 @@ component_test_full_make_gcc_o0 () { component_build_deprecated () { msg "build: make, full config + DEPRECATED_WARNING, gcc -O" # ~ 30s - scripts/config.pl full - scripts/config.pl set MBEDTLS_DEPRECATED_WARNING + scripts/config.py full + scripts/config.py set MBEDTLS_DEPRECATED_WARNING # Build with -O -Wextra to catch a maximum of issues. make CC=gcc CFLAGS='-O -Werror -Wall -Wextra' lib programs make CC=gcc CFLAGS='-O -Werror -Wall -Wextra -Wno-unused-function' tests @@ -677,8 +718,8 @@ component_build_deprecated () { msg "build: make, full config + DEPRECATED_REMOVED, clang -O" # ~ 30s # No cleanup, just tweak the configuration and rebuild make clean - scripts/config.pl unset MBEDTLS_DEPRECATED_WARNING - scripts/config.pl set MBEDTLS_DEPRECATED_REMOVED + scripts/config.py unset MBEDTLS_DEPRECATED_WARNING + scripts/config.py set MBEDTLS_DEPRECATED_REMOVED # Build with -O -Wextra to catch a maximum of issues. make CC=clang CFLAGS='-O -Werror -Wall -Wextra' lib programs make CC=clang CFLAGS='-O -Werror -Wall -Wextra -Wno-unused-function' tests @@ -712,14 +753,13 @@ component_build_default_make_gcc_and_cxx () { component_test_no_use_psa_crypto_full_cmake_asan() { # full minus MBEDTLS_USE_PSA_CRYPTO: run the same set of tests as basic-build-test.sh - msg "build: cmake, full config + MBEDTLS_USE_PSA_CRYPTO, ASan" - scripts/config.pl full - scripts/config.pl unset MBEDTLS_MEMORY_BUFFER_ALLOC_C - scripts/config.pl set MBEDTLS_ECP_RESTARTABLE # not using PSA, so enable restartable ECC - scripts/config.pl set MBEDTLS_PSA_CRYPTO_C - scripts/config.pl unset MBEDTLS_USE_PSA_CRYPTO - scripts/config.pl unset MBEDTLS_PSA_ITS_FILE_C - scripts/config.pl unset MBEDTLS_PSA_CRYPTO_STORAGE_C + msg "build: cmake, full config minus MBEDTLS_USE_PSA_CRYPTO, ASan" + scripts/config.py full + scripts/config.py set MBEDTLS_ECP_RESTARTABLE # not using PSA, so enable restartable ECC + scripts/config.py set MBEDTLS_PSA_CRYPTO_C + scripts/config.py unset MBEDTLS_USE_PSA_CRYPTO + scripts/config.py unset MBEDTLS_PSA_ITS_FILE_C + scripts/config.py unset MBEDTLS_PSA_CRYPTO_STORAGE_C CC=gcc cmake -D CMAKE_BUILD_TYPE:String=Asan . make @@ -729,10 +769,9 @@ component_test_no_use_psa_crypto_full_cmake_asan() { component_test_check_params_functionality () { msg "build+test: MBEDTLS_CHECK_PARAMS functionality" - scripts/config.pl full # includes CHECK_PARAMS + scripts/config.py full # includes CHECK_PARAMS # Make MBEDTLS_PARAM_FAILED call mbedtls_param_failed(). - scripts/config.pl unset MBEDTLS_CHECK_PARAMS_ASSERT - scripts/config.pl unset MBEDTLS_MEMORY_BUFFER_ALLOC_C + scripts/config.py unset MBEDTLS_CHECK_PARAMS_ASSERT # Only build and run tests. Do not build sample programs, because # they don't have a mbedtls_param_failed() function. make CC=gcc CFLAGS='-Werror -O1' lib test @@ -740,25 +779,22 @@ component_test_check_params_functionality () { component_test_check_params_without_platform () { msg "build+test: MBEDTLS_CHECK_PARAMS without MBEDTLS_PLATFORM_C" - scripts/config.pl full # includes CHECK_PARAMS + scripts/config.py full # includes CHECK_PARAMS # Keep MBEDTLS_PARAM_FAILED as assert. - scripts/config.pl unset MBEDTLS_MEMORY_BACKTRACE # too slow for tests - scripts/config.pl unset MBEDTLS_MEMORY_BUFFER_ALLOC_C - scripts/config.pl unset MBEDTLS_PLATFORM_EXIT_ALT - scripts/config.pl unset MBEDTLS_PLATFORM_TIME_ALT - scripts/config.pl unset MBEDTLS_PLATFORM_FPRINTF_ALT - scripts/config.pl unset MBEDTLS_PLATFORM_MEMORY - scripts/config.pl unset MBEDTLS_PLATFORM_PRINTF_ALT - scripts/config.pl unset MBEDTLS_PLATFORM_SNPRINTF_ALT - scripts/config.pl unset MBEDTLS_ENTROPY_NV_SEED - scripts/config.pl unset MBEDTLS_PLATFORM_C + scripts/config.py unset MBEDTLS_PLATFORM_EXIT_ALT + scripts/config.py unset MBEDTLS_PLATFORM_TIME_ALT + scripts/config.py unset MBEDTLS_PLATFORM_FPRINTF_ALT + scripts/config.py unset MBEDTLS_PLATFORM_MEMORY + scripts/config.py unset MBEDTLS_PLATFORM_PRINTF_ALT + scripts/config.py unset MBEDTLS_PLATFORM_SNPRINTF_ALT + scripts/config.py unset MBEDTLS_ENTROPY_NV_SEED + scripts/config.py unset MBEDTLS_PLATFORM_C make CC=gcc CFLAGS='-Werror -O1' all test } component_test_check_params_silent () { msg "build+test: MBEDTLS_CHECK_PARAMS with alternative MBEDTLS_PARAM_FAILED()" - scripts/config.pl full # includes CHECK_PARAMS - scripts/config.pl unset MBEDTLS_MEMORY_BACKTRACE # too slow for tests + scripts/config.py full # includes CHECK_PARAMS # Set MBEDTLS_PARAM_FAILED to nothing. sed -i 's/.*\(#define MBEDTLS_PARAM_FAILED( cond )\).*/\1/' "$CONFIG_H" make CC=gcc CFLAGS='-Werror -O1' all test @@ -769,20 +805,19 @@ component_test_no_platform () { # This should catch missing mbedtls_printf definitions, and by disabling file # IO, it should catch missing '#include ' msg "build: full config except platform/fsio/net, make, gcc, C99" # ~ 30s - scripts/config.pl full - scripts/config.pl unset MBEDTLS_PLATFORM_C - scripts/config.pl unset MBEDTLS_PLATFORM_MEMORY - scripts/config.pl unset MBEDTLS_PLATFORM_PRINTF_ALT - scripts/config.pl unset MBEDTLS_PLATFORM_FPRINTF_ALT - scripts/config.pl unset MBEDTLS_PLATFORM_SNPRINTF_ALT - scripts/config.pl unset MBEDTLS_PLATFORM_TIME_ALT - scripts/config.pl unset MBEDTLS_PLATFORM_EXIT_ALT - scripts/config.pl unset MBEDTLS_ENTROPY_NV_SEED - scripts/config.pl unset MBEDTLS_MEMORY_BUFFER_ALLOC_C - scripts/config.pl unset MBEDTLS_FS_IO - scripts/config.pl unset MBEDTLS_PSA_CRYPTO_SE_C - scripts/config.pl unset MBEDTLS_PSA_CRYPTO_STORAGE_C - scripts/config.pl unset MBEDTLS_PSA_ITS_FILE_C + scripts/config.py full + scripts/config.py unset MBEDTLS_PLATFORM_C + scripts/config.py unset MBEDTLS_PLATFORM_MEMORY + scripts/config.py unset MBEDTLS_PLATFORM_PRINTF_ALT + scripts/config.py unset MBEDTLS_PLATFORM_FPRINTF_ALT + scripts/config.py unset MBEDTLS_PLATFORM_SNPRINTF_ALT + scripts/config.py unset MBEDTLS_PLATFORM_TIME_ALT + scripts/config.py unset MBEDTLS_PLATFORM_EXIT_ALT + scripts/config.py unset MBEDTLS_ENTROPY_NV_SEED + scripts/config.py unset MBEDTLS_FS_IO + scripts/config.py unset MBEDTLS_PSA_CRYPTO_SE_C + scripts/config.py unset MBEDTLS_PSA_CRYPTO_STORAGE_C + scripts/config.py unset MBEDTLS_PSA_ITS_FILE_C # Note, _DEFAULT_SOURCE needs to be defined for platforms using glibc version >2.19, # to re-enable platform integration features otherwise disabled in C99 builds make CC=gcc CFLAGS='-Werror -Wall -Wextra -std=c99 -pedantic -O0 -D_DEFAULT_SOURCE' lib programs @@ -792,20 +827,20 @@ component_test_no_platform () { component_build_no_std_function () { # catch compile bugs in _uninit functions msg "build: full config with NO_STD_FUNCTION, make, gcc" # ~ 30s - scripts/config.pl full - scripts/config.pl set MBEDTLS_PLATFORM_NO_STD_FUNCTIONS - scripts/config.pl unset MBEDTLS_ENTROPY_NV_SEED + scripts/config.py full + scripts/config.py set MBEDTLS_PLATFORM_NO_STD_FUNCTIONS + scripts/config.py unset MBEDTLS_ENTROPY_NV_SEED make CC=gcc CFLAGS='-Werror -Wall -Wextra -O0' } component_test_null_entropy () { msg "build: default config with MBEDTLS_TEST_NULL_ENTROPY (ASan build)" - scripts/config.pl set MBEDTLS_TEST_NULL_ENTROPY - scripts/config.pl set MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES - scripts/config.pl set MBEDTLS_ENTROPY_C - scripts/config.pl unset MBEDTLS_ENTROPY_NV_SEED - scripts/config.pl unset MBEDTLS_ENTROPY_HARDWARE_ALT - scripts/config.pl unset MBEDTLS_HAVEGE_C + scripts/config.py set MBEDTLS_TEST_NULL_ENTROPY + scripts/config.py set MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES + scripts/config.py set MBEDTLS_ENTROPY_C + scripts/config.py unset MBEDTLS_ENTROPY_NV_SEED + scripts/config.py unset MBEDTLS_ENTROPY_HARDWARE_ALT + scripts/config.py unset MBEDTLS_HAVEGE_C CC=gcc cmake -D CMAKE_BUILD_TYPE:String=Asan -D UNSAFE_BUILD=ON . make @@ -815,9 +850,9 @@ component_test_null_entropy () { component_test_platform_calloc_macro () { msg "build: MBEDTLS_PLATFORM_{CALLOC/FREE}_MACRO enabled (ASan build)" - scripts/config.pl set MBEDTLS_PLATFORM_MEMORY - scripts/config.pl set MBEDTLS_PLATFORM_CALLOC_MACRO calloc - scripts/config.pl set MBEDTLS_PLATFORM_FREE_MACRO free + scripts/config.py set MBEDTLS_PLATFORM_MEMORY + scripts/config.py set MBEDTLS_PLATFORM_CALLOC_MACRO calloc + scripts/config.py set MBEDTLS_PLATFORM_FREE_MACRO free CC=gcc cmake -D CMAKE_BUILD_TYPE:String=Asan . make @@ -827,8 +862,7 @@ component_test_platform_calloc_macro () { component_test_malloc_0_null () { msg "build: malloc(0) returns NULL (ASan+UBSan build)" - scripts/config.pl full - scripts/config.pl unset MBEDTLS_MEMORY_BUFFER_ALLOC_C + scripts/config.py full make CC=gcc CFLAGS="'-DMBEDTLS_CONFIG_FILE=\"$PWD/tests/configs/config-wrapper-malloc-0-null.h\"' $ASAN_CFLAGS -O" LDFLAGS="$ASAN_CFLAGS" msg "test: malloc(0) returns NULL (ASan+UBSan build)" @@ -840,9 +874,33 @@ component_test_malloc_0_null () { if_build_succeeded programs/test/selftest calloc } +component_test_memory_buffer_allocator_backtrace () { + msg "build: default config with memory buffer allocator and backtrace enabled" + scripts/config.py set MBEDTLS_MEMORY_BUFFER_ALLOC_C + scripts/config.py set MBEDTLS_PLATFORM_MEMORY + scripts/config.py set MBEDTLS_MEMORY_BACKTRACE + scripts/config.py set MBEDTLS_MEMORY_DEBUG + CC=gcc cmake . + make + + msg "test: MBEDTLS_MEMORY_BUFFER_ALLOC_C and MBEDTLS_MEMORY_BACKTRACE" + make test +} + +component_test_memory_buffer_allocator () { + msg "build: default config with memory buffer allocator" + scripts/config.py set MBEDTLS_MEMORY_BUFFER_ALLOC_C + scripts/config.py set MBEDTLS_PLATFORM_MEMORY + CC=gcc cmake . + make + + msg "test: MBEDTLS_MEMORY_BUFFER_ALLOC_C" + make test +} + component_test_aes_fewer_tables () { msg "build: default config with AES_FEWER_TABLES enabled" - scripts/config.pl set MBEDTLS_AES_FEWER_TABLES + scripts/config.py set MBEDTLS_AES_FEWER_TABLES make CC=gcc CFLAGS='-Werror -Wall -Wextra' msg "test: AES_FEWER_TABLES" @@ -851,7 +909,7 @@ component_test_aes_fewer_tables () { component_test_aes_rom_tables () { msg "build: default config with AES_ROM_TABLES enabled" - scripts/config.pl set MBEDTLS_AES_ROM_TABLES + scripts/config.py set MBEDTLS_AES_ROM_TABLES make CC=gcc CFLAGS='-Werror -Wall -Wextra' msg "test: AES_ROM_TABLES" @@ -860,8 +918,8 @@ component_test_aes_rom_tables () { component_test_aes_fewer_tables_and_rom_tables () { msg "build: default config with AES_ROM_TABLES and AES_FEWER_TABLES enabled" - scripts/config.pl set MBEDTLS_AES_FEWER_TABLES - scripts/config.pl set MBEDTLS_AES_ROM_TABLES + scripts/config.py set MBEDTLS_AES_FEWER_TABLES + scripts/config.py set MBEDTLS_AES_ROM_TABLES make CC=gcc CFLAGS='-Werror -Wall -Wextra' msg "test: AES_FEWER_TABLES + AES_ROM_TABLES" @@ -870,7 +928,7 @@ component_test_aes_fewer_tables_and_rom_tables () { component_test_se_default () { msg "build: default config + MBEDTLS_PSA_CRYPTO_SE_C" - scripts/config.pl set MBEDTLS_PSA_CRYPTO_SE_C + scripts/config.py set MBEDTLS_PSA_CRYPTO_SE_C make CC=clang CFLAGS="$ASAN_CFLAGS -Os" LDFLAGS="$ASAN_CFLAGS" msg "test: default config + MBEDTLS_PSA_CRYPTO_SE_C" @@ -879,7 +937,8 @@ component_test_se_default () { component_test_se_full () { msg "build: full config + MBEDTLS_PSA_CRYPTO_SE_C" - scripts/config.pl set MBEDTLS_PSA_CRYPTO_SE_C + scripts/config.py full + scripts/config.py set MBEDTLS_PSA_CRYPTO_SE_C make CC=gcc CFLAGS="$ASAN_CFLAGS -O2" LDFLAGS="$ASAN_CFLAGS" msg "test: full config + MBEDTLS_PSA_CRYPTO_SE_C" @@ -888,7 +947,7 @@ component_test_se_full () { component_test_make_shared () { msg "build/test: make shared" # ~ 40s - make SHARED=1 all check -j1 + make SHARED=1 all check ldd programs/util/strerror | grep libmbedcrypto } @@ -904,7 +963,7 @@ component_build_mbedtls_config_file () { msg "build: make with MBEDTLS_CONFIG_FILE" # ~40s # Use the full config so as to catch a maximum of places where # the check of MBEDTLS_CONFIG_FILE might be missing. - scripts/config.pl full + scripts/config.py full sed 's!"check_config.h"!"mbedtls/check_config.h"!' <"$CONFIG_H" >full_config.h echo '#error "MBEDTLS_CONFIG_FILE is not working"' >"$CONFIG_H" make CFLAGS="-I '$PWD' -DMBEDTLS_CONFIG_FILE='\"full_config.h\"'" @@ -914,7 +973,7 @@ component_build_mbedtls_config_file () { component_test_m32_o0 () { # Build once with -O0, to compile out the i386 specific inline assembly msg "build: i386, make, gcc -O0 (ASan build)" # ~ 30s - scripts/config.pl full + scripts/config.py full make CC=gcc CFLAGS="$ASAN_CFLAGS -m32 -O0" LDFLAGS="-m32 $ASAN_CFLAGS" msg "test: i386, make, gcc -O0 (ASan build)" @@ -930,10 +989,7 @@ support_test_m32_o0 () { component_test_m32_o1 () { # Build again with -O1, to compile in the i386 specific inline assembly msg "build: i386, make, gcc -O1 (ASan build)" # ~ 30s - scripts/config.pl full - scripts/config.pl unset MBEDTLS_MEMORY_BACKTRACE - scripts/config.pl unset MBEDTLS_MEMORY_BUFFER_ALLOC_C - scripts/config.pl unset MBEDTLS_MEMORY_DEBUG + scripts/config.py full make CC=gcc CFLAGS="$ASAN_CFLAGS -m32 -O1" LDFLAGS="-m32 $ASAN_CFLAGS" msg "test: i386, make, gcc -O1 (ASan build)" @@ -945,8 +1001,8 @@ support_test_m32_o1 () { component_test_m32_everest () { msg "build: i386, Everest ECDH context (ASan build)" # ~ 6 min - scripts/config.pl unset MBEDTLS_ECDH_LEGACY_CONTEXT - scripts/config.pl set MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED + scripts/config.py unset MBEDTLS_ECDH_LEGACY_CONTEXT + scripts/config.py set MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED make CC=gcc CFLAGS="$ASAN_CFLAGS -m32 -O2" LDFLAGS="-m32 $ASAN_CFLAGS" msg "test: i386, Everest ECDH context - main suites (inc. selftests) (ASan build)" # ~ 50s @@ -958,7 +1014,7 @@ support_test_m32_everest () { component_test_mx32 () { msg "build: 64-bit ILP32, make, gcc" # ~ 30s - scripts/config.pl full + scripts/config.py full make CC=gcc CFLAGS='-Werror -Wall -Wextra -mx32' LDFLAGS='-mx32' msg "test: 64-bit ILP32, make, gcc" @@ -973,7 +1029,7 @@ support_test_mx32 () { component_test_min_mpi_window_size () { msg "build: Default + MBEDTLS_MPI_WINDOW_SIZE=1 (ASan build)" # ~ 10s - scripts/config.pl set MBEDTLS_MPI_WINDOW_SIZE 1 + scripts/config.py set MBEDTLS_MPI_WINDOW_SIZE 1 CC=gcc cmake -D CMAKE_BUILD_TYPE:String=Asan . make @@ -983,9 +1039,9 @@ component_test_min_mpi_window_size () { component_test_have_int32 () { msg "build: gcc, force 32-bit bignum limbs" - scripts/config.pl unset MBEDTLS_HAVE_ASM - scripts/config.pl unset MBEDTLS_AESNI_C - scripts/config.pl unset MBEDTLS_PADLOCK_C + scripts/config.py unset MBEDTLS_HAVE_ASM + scripts/config.py unset MBEDTLS_AESNI_C + scripts/config.py unset MBEDTLS_PADLOCK_C make CC=gcc CFLAGS='-Werror -Wall -Wextra -DMBEDTLS_HAVE_INT32' msg "test: gcc, force 32-bit bignum limbs" @@ -994,9 +1050,9 @@ component_test_have_int32 () { component_test_have_int64 () { msg "build: gcc, force 64-bit bignum limbs" - scripts/config.pl unset MBEDTLS_HAVE_ASM - scripts/config.pl unset MBEDTLS_AESNI_C - scripts/config.pl unset MBEDTLS_PADLOCK_C + scripts/config.py unset MBEDTLS_HAVE_ASM + scripts/config.py unset MBEDTLS_AESNI_C + scripts/config.py unset MBEDTLS_PADLOCK_C make CC=gcc CFLAGS='-Werror -Wall -Wextra -DMBEDTLS_HAVE_INT64' msg "test: gcc, force 64-bit bignum limbs" @@ -1005,9 +1061,8 @@ component_test_have_int64 () { component_test_no_udbl_division () { msg "build: MBEDTLS_NO_UDBL_DIVISION native" # ~ 10s - scripts/config.pl full - scripts/config.pl unset MBEDTLS_MEMORY_BACKTRACE # too slow for tests - scripts/config.pl set MBEDTLS_NO_UDBL_DIVISION + scripts/config.py full + scripts/config.py set MBEDTLS_NO_UDBL_DIVISION make CFLAGS='-Werror -O1' msg "test: MBEDTLS_NO_UDBL_DIVISION native" # ~ 10s @@ -1016,9 +1071,8 @@ component_test_no_udbl_division () { component_test_no_64bit_multiplication () { msg "build: MBEDTLS_NO_64BIT_MULTIPLICATION native" # ~ 10s - scripts/config.pl full - scripts/config.pl unset MBEDTLS_MEMORY_BACKTRACE # too slow for tests - scripts/config.pl set MBEDTLS_NO_64BIT_MULTIPLICATION + scripts/config.py full + scripts/config.py set MBEDTLS_NO_64BIT_MULTIPLICATION make CFLAGS='-Werror -O1' msg "test: MBEDTLS_NO_64BIT_MULTIPLICATION native" # ~ 10s @@ -1027,13 +1081,13 @@ component_test_no_64bit_multiplication () { component_build_arm_none_eabi_gcc () { msg "build: arm-none-eabi-gcc, make" # ~ 10s - scripts/config.pl baremetal + scripts/config.py baremetal make CC=arm-none-eabi-gcc AR=arm-none-eabi-ar LD=arm-none-eabi-ld CFLAGS='-Werror -Wall -Wextra' lib } component_build_arm_none_eabi_gcc_arm5vte () { msg "build: arm-none-eabi-gcc -march=arm5vte, make" # ~ 10s - scripts/config.pl baremetal + scripts/config.py baremetal # Build for a target platform that's close to what Debian uses # for its "armel" distribution (https://wiki.debian.org/ArmEabiPort). # See https://github.com/ARMmbed/mbedtls/pull/2169 and comments. @@ -1044,8 +1098,8 @@ component_build_arm_none_eabi_gcc_arm5vte () { component_build_arm_none_eabi_gcc_no_udbl_division () { msg "build: arm-none-eabi-gcc -DMBEDTLS_NO_UDBL_DIVISION, make" # ~ 10s - scripts/config.pl baremetal - scripts/config.pl set MBEDTLS_NO_UDBL_DIVISION + scripts/config.py baremetal + scripts/config.py set MBEDTLS_NO_UDBL_DIVISION make CC=arm-none-eabi-gcc AR=arm-none-eabi-ar LD=arm-none-eabi-ld CFLAGS='-Werror -Wall -Wextra' lib echo "Checking that software 64-bit division is not required" if_build_succeeded not grep __aeabi_uldiv library/*.o @@ -1053,8 +1107,8 @@ component_build_arm_none_eabi_gcc_no_udbl_division () { component_build_arm_none_eabi_gcc_no_64bit_multiplication () { msg "build: arm-none-eabi-gcc MBEDTLS_NO_64BIT_MULTIPLICATION, make" # ~ 10s - scripts/config.pl baremetal - scripts/config.pl set MBEDTLS_NO_64BIT_MULTIPLICATION + scripts/config.py baremetal + scripts/config.py set MBEDTLS_NO_64BIT_MULTIPLICATION make CC=arm-none-eabi-gcc AR=arm-none-eabi-ar LD=arm-none-eabi-ld CFLAGS='-Werror -O1 -march=armv6-m -mthumb' lib echo "Checking that software 64-bit multiplication is not required" if_build_succeeded not grep __aeabi_lmul library/*.o @@ -1062,7 +1116,7 @@ component_build_arm_none_eabi_gcc_no_64bit_multiplication () { component_build_armcc () { msg "build: ARM Compiler 5, make" - scripts/config.pl baremetal + scripts/config.py baremetal make CC="$ARMC5_CC" AR="$ARMC5_AR" WARNING_CFLAGS='--strict --c99' lib make clean @@ -1085,15 +1139,15 @@ component_build_armcc () { component_build_mingw () { msg "build: Windows cross build - mingw64, make (Link Library)" # ~ 30s - make CC=i686-w64-mingw32-gcc AR=i686-w64-mingw32-ar LD=i686-w64-minggw32-ld CFLAGS='-Werror -Wall -Wextra' WINDOWS_BUILD=1 lib programs -j1 + make CC=i686-w64-mingw32-gcc AR=i686-w64-mingw32-ar LD=i686-w64-minggw32-ld CFLAGS='-Werror -Wall -Wextra' WINDOWS_BUILD=1 lib programs # note Make tests only builds the tests, but doesn't run them - make CC=i686-w64-mingw32-gcc AR=i686-w64-mingw32-ar LD=i686-w64-minggw32-ld CFLAGS='-Werror' WINDOWS_BUILD=1 tests -j1 + make CC=i686-w64-mingw32-gcc AR=i686-w64-mingw32-ar LD=i686-w64-minggw32-ld CFLAGS='-Werror' WINDOWS_BUILD=1 tests make WINDOWS_BUILD=1 clean msg "build: Windows cross build - mingw64, make (DLL)" # ~ 30s - make CC=i686-w64-mingw32-gcc AR=i686-w64-mingw32-ar LD=i686-w64-minggw32-ld CFLAGS='-Werror -Wall -Wextra' WINDOWS_BUILD=1 SHARED=1 lib programs -j1 - make CC=i686-w64-mingw32-gcc AR=i686-w64-mingw32-ar LD=i686-w64-minggw32-ld CFLAGS='-Werror -Wall -Wextra' WINDOWS_BUILD=1 SHARED=1 tests -j1 + make CC=i686-w64-mingw32-gcc AR=i686-w64-mingw32-ar LD=i686-w64-minggw32-ld CFLAGS='-Werror -Wall -Wextra' WINDOWS_BUILD=1 SHARED=1 lib programs + make CC=i686-w64-mingw32-gcc AR=i686-w64-mingw32-ar LD=i686-w64-minggw32-ld CFLAGS='-Werror -Wall -Wextra' WINDOWS_BUILD=1 SHARED=1 tests make WINDOWS_BUILD=1 clean } support_build_mingw() { @@ -1105,7 +1159,7 @@ support_build_mingw() { component_test_memsan () { msg "build: MSan (clang)" # ~ 1 min 20s - scripts/config.pl unset MBEDTLS_AESNI_C # memsan doesn't grok asm + scripts/config.py unset MBEDTLS_AESNI_C # memsan doesn't grok asm CC=clang cmake -D CMAKE_BUILD_TYPE:String=MemSan . make @@ -1217,6 +1271,7 @@ run_component () { # The cleanup function will restore it. cp -p "$CONFIG_H" "$CONFIG_BAK" current_component="$1" + export MBEDTLS_TEST_CONFIGURATION="$current_component" "$@" cleanup } @@ -1237,6 +1292,7 @@ else "$@" } fi +pre_prepare_outcome_file pre_print_configuration pre_check_tools cleanup diff --git a/tests/scripts/basic-build-test.sh b/tests/scripts/basic-build-test.sh index 54ca93413..7ed0372ab 100755 --- a/tests/scripts/basic-build-test.sh +++ b/tests/scripts/basic-build-test.sh @@ -46,8 +46,8 @@ export CFLAGS=' --coverage -g3 -O0 ' export LDFLAGS=' --coverage' make clean cp "$CONFIG_H" "$CONFIG_BAK" -scripts/config.pl full -scripts/config.pl unset MBEDTLS_MEMORY_BACKTRACE +scripts/config.py full +scripts/config.py unset MBEDTLS_MEMORY_BACKTRACE make -j diff --git a/tests/scripts/check-test-cases.py b/tests/scripts/check-test-cases.py new file mode 100755 index 000000000..87a35e47e --- /dev/null +++ b/tests/scripts/check-test-cases.py @@ -0,0 +1,123 @@ +#!/usr/bin/env python3 + +"""Sanity checks for test data. +""" + +# Copyright (C) 2019, Arm Limited, All Rights Reserved +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# This file is part of Mbed TLS (https://tls.mbed.org) + +import glob +import os +import re +import sys + +class Results: + def __init__(self): + self.errors = 0 + self.warnings = 0 + + def error(self, file_name, line_number, fmt, *args): + sys.stderr.write(('{}:{}:ERROR:' + fmt + '\n'). + format(file_name, line_number, *args)) + self.errors += 1 + + def warning(self, file_name, line_number, fmt, *args): + sys.stderr.write(('{}:{}:Warning:' + fmt + '\n') + .format(file_name, line_number, *args)) + self.warnings += 1 + +def collect_test_directories(): + if os.path.isdir('tests'): + tests_dir = 'tests' + elif os.path.isdir('suites'): + tests_dir = '.' + elif os.path.isdir('../suites'): + tests_dir = '..' + directories = [tests_dir] + crypto_tests_dir = os.path.normpath(os.path.join(tests_dir, + '../crypto/tests')) + if os.path.isdir(crypto_tests_dir): + directories.append(crypto_tests_dir) + return directories + +def check_description(results, seen, file_name, line_number, description): + if description in seen: + results.error(file_name, line_number, + 'Duplicate description (also line {})', + seen[description]) + return + if re.search(br'[\t;]', description): + results.error(file_name, line_number, + 'Forbidden character \'{}\' in description', + re.search(br'[\t;]', description).group(0).decode('ascii')) + if re.search(br'[^ -~]', description): + results.error(file_name, line_number, + 'Non-ASCII character in description') + if len(description) > 66: + results.warning(file_name, line_number, + 'Test description too long ({} > 66)', + len(description)) + seen[description] = line_number + +def check_test_suite(results, data_file_name): + in_paragraph = False + descriptions = {} + with open(data_file_name, 'rb') as data_file: + for line_number, line in enumerate(data_file, 1): + line = line.rstrip(b'\r\n') + if not line: + in_paragraph = False + continue + if line.startswith(b'#'): + continue + if not in_paragraph: + # This is a test case description line. + check_description(results, descriptions, + data_file_name, line_number, line) + in_paragraph = True + +def check_ssl_opt_sh(results, file_name): + descriptions = {} + with open(file_name, 'rb') as file_contents: + for line_number, line in enumerate(file_contents, 1): + # Assume that all run_test calls have the same simple form + # with the test description entirely on the same line as the + # function name. + m = re.match(br'\s*run_test\s+"((?:[^\\"]|\\.)*)"', line) + if not m: + continue + description = m.group(1) + check_description(results, descriptions, + file_name, line_number, description) + +def main(): + test_directories = collect_test_directories() + results = Results() + for directory in test_directories: + for data_file_name in glob.glob(os.path.join(directory, 'suites', + '*.data')): + check_test_suite(results, data_file_name) + ssl_opt_sh = os.path.join(directory, 'ssl-opt.sh') + if os.path.exists(ssl_opt_sh): + check_ssl_opt_sh(results, ssl_opt_sh) + if results.warnings or results.errors: + sys.stderr.write('{}: {} errors, {} warnings\n' + .format(sys.argv[0], results.errors, results.warnings)) + sys.exit(1 if results.errors else 0) + +if __name__ == '__main__': + main() diff --git a/tests/scripts/curves.pl b/tests/scripts/curves.pl index 4791d5521..8119a46e6 100755 --- a/tests/scripts/curves.pl +++ b/tests/scripts/curves.pl @@ -46,13 +46,14 @@ for my $curve (@curves) { system( "make clean" ) and die; # depends on a specific curve. Also, ignore error if it wasn't enabled - system( "scripts/config.pl unset MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED" ); + system( "scripts/config.py unset MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED" ); print "\n******************************************\n"; print "* Testing without curve: $curve\n"; print "******************************************\n"; + $ENV{MBEDTLS_TEST_CONFIGURATION} = "-$curve"; - system( "scripts/config.pl unset $curve" ) + system( "scripts/config.py unset $curve" ) and abort "Failed to disable $curve\n"; system( "CFLAGS='-Werror -Wall -Wextra' make lib" ) diff --git a/tests/scripts/depends-hashes.pl b/tests/scripts/depends-hashes.pl index f57e7ed88..7cb41b55c 100755 --- a/tests/scripts/depends-hashes.pl +++ b/tests/scripts/depends-hashes.pl @@ -57,12 +57,13 @@ for my $hash (@hashes) { print "\n******************************************\n"; print "* Testing without hash: $hash\n"; print "******************************************\n"; + $ENV{MBEDTLS_TEST_CONFIGURATION} = "-$hash"; - system( "scripts/config.pl unset $hash" ) + system( "scripts/config.py unset $hash" ) and abort "Failed to disable $hash\n"; for my $opt (@ssl) { - system( "scripts/config.pl unset $opt" ) + system( "scripts/config.py unset $opt" ) and abort "Failed to disable $opt\n"; } diff --git a/tests/scripts/depends-pkalgs.pl b/tests/scripts/depends-pkalgs.pl index 72c7f4103..7fbd6d71e 100755 --- a/tests/scripts/depends-pkalgs.pl +++ b/tests/scripts/depends-pkalgs.pl @@ -59,11 +59,12 @@ while( my ($alg, $extras) = each %algs ) { print "\n******************************************\n"; print "* Testing without alg: $alg\n"; print "******************************************\n"; + $ENV{MBEDTLS_TEST_CONFIGURATION} = "-$alg"; - system( "scripts/config.pl unset $alg" ) + system( "scripts/config.py unset $alg" ) and abort "Failed to disable $alg\n"; for my $opt (@$extras) { - system( "scripts/config.pl unset $opt" ) + system( "scripts/config.py unset $opt" ) and abort "Failed to disable $opt\n"; } diff --git a/tests/scripts/list-symbols.sh b/tests/scripts/list-symbols.sh index 6ecc199bf..1c348a79c 100755 --- a/tests/scripts/list-symbols.sh +++ b/tests/scripts/list-symbols.sh @@ -13,7 +13,7 @@ if grep -i cmake Makefile >/dev/null; then fi cp include/mbedtls/config.h include/mbedtls/config.h.bak -scripts/config.pl full +scripts/config.py full make clean make_ret= CFLAGS=-fno-asynchronous-unwind-tables make lib \ diff --git a/tests/scripts/test-ref-configs.pl b/tests/scripts/test-ref-configs.pl index 09baebb66..b29d0dd1b 100755 --- a/tests/scripts/test-ref-configs.pl +++ b/tests/scripts/test-ref-configs.pl @@ -17,6 +17,8 @@ use warnings; use strict; my %configs = ( + 'config-symmetric-only.h' => { + }, 'config-suite-b.h' => { }, ); @@ -48,6 +50,15 @@ sub abort { exit 1; } +# Create a seedfile for configurations that enable MBEDTLS_ENTROPY_NV_SEED. +# For test purposes, this doesn't have to be cryptographically random. +if (!-e "tests/seedfile" || -s "tests/seedfile" < 64) { + local *SEEDFILE; + open SEEDFILE, ">tests/seedfile" or die; + print SEEDFILE "*" x 64 or die; + close SEEDFILE or die; +} + while( my ($conf, $data) = each %configs ) { system( "cp $config_h.bak $config_h" ) and die; system( "make clean" ) and die; @@ -55,6 +66,7 @@ while( my ($conf, $data) = each %configs ) { print "\n******************************************\n"; print "* Testing configuration: $conf\n"; print "******************************************\n"; + $ENV{MBEDTLS_TEST_CONFIGURATION} = $conf; system( "cp configs/$conf $config_h" ) and abort "Failed to activate $conf\n"; diff --git a/tests/scripts/test_config_script.py b/tests/scripts/test_config_script.py new file mode 100755 index 000000000..40ed9fd9b --- /dev/null +++ b/tests/scripts/test_config_script.py @@ -0,0 +1,187 @@ +#!/usr/bin/env python3 + +"""Test helper for the Mbed TLS configuration file tool + +Run config.py with various parameters and write the results to files. + +This is a harness to help regression testing, not a functional tester. +Sample usage: + + test_config_script.py -d old + ## Modify config.py and/or config.h ## + test_config_script.py -d new + diff -ru old new +""" + +## Copyright (C) 2019, ARM Limited, All Rights Reserved +## SPDX-License-Identifier: Apache-2.0 +## +## Licensed under the Apache License, Version 2.0 (the "License"); you may +## not use this file except in compliance with the License. +## You may obtain a copy of the License at +## +## http://www.apache.org/licenses/LICENSE-2.0 +## +## Unless required by applicable law or agreed to in writing, software +## distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +## WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +## See the License for the specific language governing permissions and +## limitations under the License. +## +## This file is part of Mbed TLS (https://tls.mbed.org) + +import argparse +import glob +import os +import re +import shutil +import subprocess + +OUTPUT_FILE_PREFIX = 'config-' + +def output_file_name(directory, stem, extension): + return os.path.join(directory, + '{}{}.{}'.format(OUTPUT_FILE_PREFIX, + stem, extension)) + +def cleanup_directory(directory): + """Remove old output files.""" + for extension in []: + pattern = output_file_name(directory, '*', extension) + filenames = glob.glob(pattern) + for filename in filenames: + os.remove(filename) + +def prepare_directory(directory): + """Create the output directory if it doesn't exist yet. + + If there are old output files, remove them. + """ + if os.path.exists(directory): + cleanup_directory(directory) + else: + os.makedirs(directory) + +def guess_presets_from_help(help_text): + """Figure out what presets the script supports. + + help_text should be the output from running the script with --help. + """ + # Try the output format from config.py + hits = re.findall(r'\{([-\w,]+)\}', help_text) + for hit in hits: + words = set(hit.split(',')) + if 'get' in words and 'set' in words and 'unset' in words: + words.remove('get') + words.remove('set') + words.remove('unset') + return words + # Try the output format from config.pl + hits = re.findall(r'\n +([-\w]+) +- ', help_text) + if hits: + return hits + raise Exception("Unable to figure out supported presets. Pass the '-p' option.") + +def list_presets(options): + """Return the list of presets to test. + + The list is taken from the command line if present, otherwise it is + extracted from running the config script with --help. + """ + if options.presets: + return re.split(r'[ ,]+', options.presets) + else: + help_text = subprocess.run([options.script, '--help'], + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT).stdout + return guess_presets_from_help(help_text.decode('ascii')) + +def run_one(options, args, stem_prefix='', input_file=None): + """Run the config script with the given arguments. + + Take the original content from input_file if specified, defaulting + to options.input_file if input_file is None. + + Write the following files, where xxx contains stem_prefix followed by + a filename-friendly encoding of args: + * config-xxx.h: modified file. + * config-xxx.out: standard output. + * config-xxx.err: standard output. + * config-xxx.status: exit code. + + Return ("xxx+", "path/to/config-xxx.h") which can be used as + stem_prefix and input_file to call this function again with new args. + """ + if input_file is None: + input_file = options.input_file + stem = stem_prefix + '-'.join(args) + data_filename = output_file_name(options.output_directory, stem, 'h') + stdout_filename = output_file_name(options.output_directory, stem, 'out') + stderr_filename = output_file_name(options.output_directory, stem, 'err') + status_filename = output_file_name(options.output_directory, stem, 'status') + shutil.copy(input_file, data_filename) + # Pass only the file basename, not the full path, to avoid getting the + # directory name in error messages, which would make comparisons + # between output directories more difficult. + cmd = [os.path.abspath(options.script), + '-f', os.path.basename(data_filename)] + with open(stdout_filename, 'wb') as out: + with open(stderr_filename, 'wb') as err: + status = subprocess.call(cmd + args, + cwd=options.output_directory, + stdin=subprocess.DEVNULL, + stdout=out, stderr=err) + with open(status_filename, 'w') as status_file: + status_file.write('{}\n'.format(status)) + return stem + "+", data_filename + +### A list of symbols to test with. +### This script currently tests what happens when you change a symbol from +### having a value to not having a value or vice versa. This is not +### necessarily useful behavior, and we may not consider it a bug if +### config.py stops handling that case correctly. +TEST_SYMBOLS = [ + 'CUSTOM_SYMBOL', # does not exist + 'MBEDTLS_AES_C', # set, no value + 'MBEDTLS_MPI_MAX_SIZE', # unset, has a value + 'MBEDTLS_NO_UDBL_DIVISION', # unset, in "System support" + 'MBEDTLS_PLATFORM_ZEROIZE_ALT', # unset, in "Customisation configuration options" +] + +def run_all(options): + """Run all the command lines to test.""" + presets = list_presets(options) + for preset in presets: + run_one(options, [preset]) + for symbol in TEST_SYMBOLS: + run_one(options, ['get', symbol]) + (stem, filename) = run_one(options, ['set', symbol]) + run_one(options, ['get', symbol], stem_prefix=stem, input_file=filename) + run_one(options, ['--force', 'set', symbol]) + (stem, filename) = run_one(options, ['set', symbol, 'value']) + run_one(options, ['get', symbol], stem_prefix=stem, input_file=filename) + run_one(options, ['--force', 'set', symbol, 'value']) + run_one(options, ['unset', symbol]) + +def main(): + """Command line entry point.""" + parser = argparse.ArgumentParser(description=__doc__, + formatter_class=argparse.RawDescriptionHelpFormatter) + parser.add_argument('-d', metavar='DIR', + dest='output_directory', required=True, + help="""Output directory.""") + parser.add_argument('-f', metavar='FILE', + dest='input_file', default='include/mbedtls/config.h', + help="""Config file (default: %(default)s).""") + parser.add_argument('-p', metavar='PRESET,...', + dest='presets', + help="""Presets to test (default: guessed from --help).""") + parser.add_argument('-s', metavar='FILE', + dest='script', default='scripts/config.py', + help="""Configuration script (default: %(default)s).""") + options = parser.parse_args() + prepare_directory(options.output_directory) + run_all(options) + +if __name__ == '__main__': + main() diff --git a/tests/suites/helpers.function b/tests/suites/helpers.function index 00320bca3..0cce463c0 100644 --- a/tests/suites/helpers.function +++ b/tests/suites/helpers.function @@ -406,7 +406,7 @@ typedef enum TEST_RESULT_SKIPPED } test_result_t; -static struct +typedef struct { paramfail_test_state_t paramfail_test_state; test_result_t result; @@ -415,7 +415,8 @@ static struct int line_no; unsigned long step; } -test_info; +test_info_t; +static test_info_t test_info; #if defined(MBEDTLS_PLATFORM_C) mbedtls_platform_context platform_ctx; diff --git a/tests/suites/host_test.function b/tests/suites/host_test.function index 24d9b9747..a87dc139c 100644 --- a/tests/suites/host_test.function +++ b/tests/suites/host_test.function @@ -368,6 +368,118 @@ static int run_test_snprintf( void ) test_snprintf( 5, "123", 3 ) != 0 ); } +/** \brief Write the description of the test case to the outcome CSV file. + * + * \param outcome_file The file to write to. + * If this is \c NULL, this function does nothing. + * \param argv0 The test suite name. + * \param test_case The test case description. + */ +static void write_outcome_entry( FILE *outcome_file, + const char *argv0, + const char *test_case ) +{ + /* The non-varying fields are initialized on first use. */ + static const char *platform = NULL; + static const char *configuration = NULL; + static const char *test_suite = NULL; + + if( outcome_file == NULL ) + return; + + if( platform == NULL ) + { + platform = getenv( "MBEDTLS_TEST_PLATFORM" ); + if( platform == NULL ) + platform = "unknown"; + } + if( configuration == NULL ) + { + configuration = getenv( "MBEDTLS_TEST_CONFIGURATION" ); + if( configuration == NULL ) + configuration = "unknown"; + } + if( test_suite == NULL ) + { + test_suite = strrchr( argv0, '/' ); + if( test_suite != NULL ) + test_suite += 1; // skip the '/' + else + test_suite = argv0; + } + + /* Write the beginning of the outcome line. + * Ignore errors: writing the outcome file is on a best-effort basis. */ + mbedtls_fprintf( outcome_file, "%s;%s;%s;%s;", + platform, configuration, test_suite, test_case ); +} + +/** \brief Write the result of the test case to the outcome CSV file. + * + * \param outcome_file The file to write to. + * If this is \c NULL, this function does nothing. + * \param unmet_dep_count The number of unmet dependencies. + * \param unmet_dependencies The array of unmet dependencies. + * \param ret The test dispatch status (DISPATCH_xxx). + * \param test_info A pointer to the test info structure. + */ +static void write_outcome_result( FILE *outcome_file, + size_t unmet_dep_count, + char *unmet_dependencies[], + int ret, + const test_info_t *info ) +{ + if( outcome_file == NULL ) + return; + + /* Write the end of the outcome line. + * Ignore errors: writing the outcome file is on a best-effort basis. */ + switch( ret ) + { + case DISPATCH_TEST_SUCCESS: + if( unmet_dep_count > 0 ) + { + size_t i; + mbedtls_fprintf( outcome_file, "SKIP" ); + for( i = 0; i < unmet_dep_count; i++ ) + { + mbedtls_fprintf( outcome_file, "%c%s", + i == 0 ? ';' : ':', + unmet_dependencies[i] ); + } + break; + } + switch( info->result ) + { + case TEST_RESULT_SUCCESS: + mbedtls_fprintf( outcome_file, "PASS;" ); + break; + case TEST_RESULT_SKIPPED: + mbedtls_fprintf( outcome_file, "SKIP;Runtime skip" ); + break; + default: + mbedtls_fprintf( outcome_file, "FAIL;%s:%d:%s", + info->filename, info->line_no, + info->test ); + break; + } + break; + case DISPATCH_TEST_FN_NOT_FOUND: + mbedtls_fprintf( outcome_file, "FAIL;Test function not found" ); + break; + case DISPATCH_INVALID_TEST_DATA: + mbedtls_fprintf( outcome_file, "FAIL;Invalid test data" ); + break; + case DISPATCH_UNSUPPORTED_SUITE: + mbedtls_fprintf( outcome_file, "SKIP;Unsupported suite" ); + break; + default: + mbedtls_fprintf( outcome_file, "FAIL;Unknown cause" ); + break; + } + mbedtls_fprintf( outcome_file, "\n" ); + fflush( outcome_file ); +} /** * \brief Desktop implementation of execute_tests(). @@ -385,15 +497,16 @@ int execute_tests( int argc , const char ** argv ) const char *default_filename = "DATA_FILE"; const char *test_filename = NULL; const char **test_files = NULL; - int testfile_count = 0; + size_t testfile_count = 0; int option_verbose = 0; int function_id = 0; /* Other Local variables */ int arg_index = 1; const char *next_arg; - int testfile_index, ret, i, cnt; - int total_errors = 0, total_tests = 0, total_skipped = 0; + size_t testfile_index, i, cnt; + int ret; + unsigned total_errors = 0, total_tests = 0, total_skipped = 0; FILE *file; char buf[5000]; char *params[50]; @@ -403,6 +516,8 @@ int execute_tests( int argc , const char ** argv ) #if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) int stdout_fd = -1; #endif /* __unix__ || __APPLE__ __MACH__ */ + const char *outcome_file_name = getenv( "MBEDTLS_TEST_OUTCOME_FILE" ); + FILE *outcome_file = NULL; #if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) && \ !defined(TEST_SUITE_MEMORY_BUFFER_ALLOC) @@ -410,6 +525,15 @@ int execute_tests( int argc , const char ** argv ) mbedtls_memory_buffer_alloc_init( alloc_buf, sizeof( alloc_buf ) ); #endif + if( outcome_file_name != NULL ) + { + outcome_file = fopen( outcome_file_name, "a" ); + if( outcome_file == NULL ) + { + mbedtls_fprintf( stderr, "Unable to open outcome file. Continuing anyway.\n" ); + } + } + /* * The C standard doesn't guarantee that all-bits-0 is the representation * of a NULL pointer. We do however use that in our code for initializing @@ -473,7 +597,7 @@ int execute_tests( int argc , const char ** argv ) testfile_index < testfile_count; testfile_index++ ) { - int unmet_dep_count = 0; + size_t unmet_dep_count = 0; char *unmet_dependencies[20]; test_filename = test_files[ testfile_index ]; @@ -505,6 +629,7 @@ int execute_tests( int argc , const char ** argv ) mbedtls_fprintf( stdout, "." ); mbedtls_fprintf( stdout, " " ); fflush( stdout ); + write_outcome_entry( outcome_file, argv[0], buf ); total_tests++; @@ -585,6 +710,9 @@ int execute_tests( int argc , const char ** argv ) } + write_outcome_result( outcome_file, + unmet_dep_count, unmet_dependencies, + ret, &test_info ); if( unmet_dep_count > 0 || ret == DISPATCH_UNSUPPORTED_SUITE ) { total_skipped++; @@ -645,7 +773,7 @@ int execute_tests( int argc , const char ** argv ) } else if( ret == DISPATCH_TEST_FN_NOT_FOUND ) { - mbedtls_fprintf( stderr, "FAILED: FATAL TEST FUNCTION NOT FUND\n" ); + mbedtls_fprintf( stderr, "FAILED: FATAL TEST FUNCTION NOT FOUND\n" ); fclose( file ); mbedtls_exit( 2 ); } @@ -659,14 +787,17 @@ int execute_tests( int argc , const char ** argv ) free( unmet_dependencies[i] ); } + if( outcome_file != NULL ) + fclose( outcome_file ); + mbedtls_fprintf( stdout, "\n----------------------------------------------------------------------------\n\n"); if( total_errors == 0 ) mbedtls_fprintf( stdout, "PASSED" ); else mbedtls_fprintf( stdout, "FAILED" ); - mbedtls_fprintf( stdout, " (%d / %d tests (%d skipped))\n", - total_tests - total_errors, total_tests, total_skipped ); + mbedtls_fprintf( stdout, " (%u / %u tests (%u skipped))\n", + total_tests - total_errors, total_tests, total_skipped ); #if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) && \ !defined(TEST_SUITE_MEMORY_BUFFER_ALLOC) diff --git a/tests/suites/test_suite_pk.data b/tests/suites/test_suite_pk.data index ea5fc4f22..caa4c7776 100644 --- a/tests/suites/test_suite_pk.data +++ b/tests/suites/test_suite_pk.data @@ -8,21 +8,41 @@ PK write valid parameters depends_on:MBEDTLS_RSA_C valid_parameters_pkwrite:"308204a20201000282010100a9021f3d406ad555538bfd36ee82652e15615e89bfb8e84590dbee881652d3f143504796125964876bfd2be046f973beddcf92e1915bed66a06f8929794580d0836ad54143775f397c09044782b0573970eda3ec15191ea8330847c10542a9fd4cc3b4dfdd061f4d1051406773130f40f86d81255f0ab153c6307e1539acf95aee7f929ea6055be7139785b52392d9d42406d50925897507dda61a8f3f0919bead652c64eb959bdcfe415e17a6da6c5b69cc02ba142c16249c4adccdd0f7526773f12da023fd7ef431ca2d70ca890b04db2ea64f706e9ecebd5889e253599e6e5a9265e2883f0c9419a3dde5e89d9513ed29dbab7012dc5aca6b17ab528254b10203010001028201001689f5e89142ae18a6ffb0513715a4b0b4a13b9e5b3729a2bd62d738c6e15cea7bf3a4d85ab2193a0628c9452bb1f0c1af8b132789df1c95e72778bf5330f5b0d915d242d5e0818e85001ed5fa93d1ce13455deb0a15438562e8e3c8d60ec1e4c9ebff9f2b36b9cde9332cc79f0d17a7ae79cc1353cd75409ad9b4b6d7ee3d82af6f3207656cf2ac98947c15c398db0cebf8dc3eef5398269480cdd09411b960273ae3f364da09af849f24aa87346c58618ea91d9d6cd1d3932c80dbfc1f0a4166a9036911999ca27761079f0ce02db02c1c909ff9b4278578d7bb1b54b2b7082fc9e864b6b394e331c0d11a9a68255565b6dd477f4119c5809839520700711102818100d7db987ad86de6a9b0749fb5da80bacde3bebd72dcc83f60a27db74f927ac3661386577bfce5b4a00ad024682401d6aad29713c8e223b53415305ca07559821099b187fdd1bad3dc4dec9da96f5fa6128331e8f7d89f1e1a788698d1a27256dc7cd392f04e531a9e38e7265bf4fd7eec01e7835e9b1a0dd8923e440381be1c2702818100c87025fff7a493c623404966fbc8b32ed164ca620ad1a0ad11ef42fd12118456017856a8b42e5d4ad36104e9dc9f8a2f3003c3957ffddb20e2f4e3fc3cf2cdddae01f57a56de4fd24b91ab6d3e5cc0e8af0473659594a6bbfdaacf958f19c8d508eac12d8977616af6877106288093d37904a139220c1bc278ea56edc086976702818043e708685c7cf5fa9b4f948e1856366d5e1f3a694f9a8e954f884c89f3823ac5798ee12657bfcaba2dac9c47464c6dc2fecc17a531be19da706fee336bb6e47b645dbc71d3eff9856bddeb1ac9b644ffbdd58d7ba9e1240f1faaf797ba8a4d58becbaf85789e1bd979fcfccc209d3db7f0416bc9eef09b3a6d86b8ce8199d4310281804f4b86ccffe49d0d8ace98fb63ea9f708b284ba483d130b6a75cb76cb4e4372d6b41774f20912319420ca4cbfc1b25a8cb5f01d6381f6ebc50ed3ef08010327f5ba2acc1ac7220b3fa6f7399314db2879b0db0b5647abd87abb01295815a5b086491b2c0d81c616ed67ef8a8ce0727f446711d7323d4147b5828a52143c43b4b028180540756beba83c20a0bda11d6dec706a71744ff28090cec079dffb507d82828038fe657f61496a20317f779cb683ce8196c29a6fe28839a282eef4de57773be56808b0c3e2ac7747e2b200b2fbf20b55258cd24622a1ce0099de098ab0855106ae087f08b0c8c346d81619400c1b4838e33ed9ff90f05db8fccf8fb7ab881ca12" -PK utils: RSA +PK utils: RSA 512-bit depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME -pk_utils:MBEDTLS_PK_RSA:512:64:"RSA" +pk_utils:MBEDTLS_PK_RSA:512:512:64:"RSA" -PK utils: ECKEY +PK utils: ECKEY SECP192R1 depends_on:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP192R1_ENABLED -pk_utils:MBEDTLS_PK_ECKEY:192:24:"EC" +pk_utils:MBEDTLS_PK_ECKEY:MBEDTLS_ECP_DP_SECP192R1:192:24:"EC" -PK utils: ECKEY_DH +PK utils: ECKEY_DH SECP192R1 depends_on:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP192R1_ENABLED -pk_utils:MBEDTLS_PK_ECKEY_DH:192:24:"EC_DH" +pk_utils:MBEDTLS_PK_ECKEY_DH:MBEDTLS_ECP_DP_SECP192R1:192:24:"EC_DH" -PK utils: ECDSA +PK utils: ECKEY_DH Curve25519 +depends_on:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_CURVE25519_ENABLED +pk_utils:MBEDTLS_PK_ECKEY_DH:MBEDTLS_ECP_DP_CURVE25519:255:32:"EC_DH" + +PK utils: ECKEY_DH Curve448 +depends_on:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_CURVE448_ENABLED +pk_utils:MBEDTLS_PK_ECKEY_DH:MBEDTLS_ECP_DP_CURVE448:448:56:"EC_DH" + +PK utils: ECDSA SECP192R1 depends_on:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP192R1_ENABLED -pk_utils:MBEDTLS_PK_ECDSA:192:24:"ECDSA" +pk_utils:MBEDTLS_PK_ECDSA:MBEDTLS_ECP_DP_SECP192R1:192:24:"ECDSA" + +PK utils: ECDSA SECP256R1 +depends_on:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED +pk_utils:MBEDTLS_PK_ECDSA:MBEDTLS_ECP_DP_SECP256R1:256:32:"ECDSA" + +PK utils: ECDSA SECP384R1 +depends_on:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP384R1_ENABLED +pk_utils:MBEDTLS_PK_ECDSA:MBEDTLS_ECP_DP_SECP384R1:384:48:"ECDSA" + +PK utils: ECDSA SECP521R1 +depends_on:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP521R1_ENABLED +pk_utils:MBEDTLS_PK_ECDSA:MBEDTLS_ECP_DP_SECP521R1:521:66:"ECDSA" PK PSA utilities: setup/free, info functions, unsupported operations pk_psa_utils: @@ -83,21 +103,41 @@ EC(DSA) verify test vector: good, bitlen(s) = 247 depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED pk_ec_test_vec:MBEDTLS_PK_ECKEY:MBEDTLS_ECP_DP_SECP256R1:"0437cc56d976091e5a723ec7592dff206eee7cf9069174d0ad14b5f768225962924ee500d82311ffea2fd2345d5d16bd8a88c26b770d55cd8a2a0efa01c8b4edff":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855":"30430220685a6994daa6a14e4411b5267edc2a00beee907f2dddd956b2a5a1df791c15f8021f675db4538c000c734489ac737fddd5a739c5a23cd6c6eceea70c286ca4fac9":0 -ECDSA sign-verify +ECDSA sign-verify: SECP192R1 depends_on:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP192R1_ENABLED -pk_sign_verify:MBEDTLS_PK_ECDSA:0:0 +pk_sign_verify:MBEDTLS_PK_ECDSA:MBEDTLS_ECP_DP_SECP192R1:0:0 -EC(DSA) sign-verify +ECDSA sign-verify: SECP256R1 +depends_on:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED +pk_sign_verify:MBEDTLS_PK_ECDSA:MBEDTLS_ECP_DP_SECP256R1:0:0 + +ECDSA sign-verify: SECP384R1 +depends_on:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP384R1_ENABLED +pk_sign_verify:MBEDTLS_PK_ECDSA:MBEDTLS_ECP_DP_SECP384R1:0:0 + +ECDSA sign-verify: SECP521R1 +depends_on:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP521R1_ENABLED +pk_sign_verify:MBEDTLS_PK_ECDSA:MBEDTLS_ECP_DP_SECP521R1:0:0 + +ECDSA sign-verify: BP256R1 +depends_on:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_BP256R1_ENABLED +pk_sign_verify:MBEDTLS_PK_ECDSA:MBEDTLS_ECP_DP_BP256R1:0:0 + +ECDSA sign-verify: BP512R1 +depends_on:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_BP512R1_ENABLED +pk_sign_verify:MBEDTLS_PK_ECDSA:MBEDTLS_ECP_DP_BP512R1:0:0 + +EC(DSA) sign-verify: SECP192R1 depends_on:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP192R1_ENABLED -pk_sign_verify:MBEDTLS_PK_ECKEY:0:0 +pk_sign_verify:MBEDTLS_PK_ECKEY:MBEDTLS_ECP_DP_SECP192R1:0:0 -EC_DH (no) sign-verify +EC_DH (no) sign-verify: SECP192R1 depends_on:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP192R1_ENABLED -pk_sign_verify:MBEDTLS_PK_ECKEY_DH:MBEDTLS_ERR_PK_TYPE_MISMATCH:MBEDTLS_ERR_PK_TYPE_MISMATCH +pk_sign_verify:MBEDTLS_PK_ECKEY_DH:MBEDTLS_ECP_DP_SECP192R1:MBEDTLS_ERR_PK_TYPE_MISMATCH:MBEDTLS_ERR_PK_TYPE_MISMATCH RSA sign-verify depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_GENPRIME -pk_sign_verify:MBEDTLS_PK_RSA:0:0 +pk_sign_verify:MBEDTLS_PK_RSA:512:0:0 RSA encrypt test vector depends_on:MBEDTLS_PKCS1_V15 diff --git a/tests/suites/test_suite_pk.function b/tests/suites/test_suite_pk.function index b34907522..ccf173632 100644 --- a/tests/suites/test_suite_pk.function +++ b/tests/suites/test_suite_pk.function @@ -27,13 +27,27 @@ static int rnd_std_rand( void *rng_state, unsigned char *output, size_t len ); #define RSA_KEY_SIZE 512 #define RSA_KEY_LEN 64 -static int pk_genkey( mbedtls_pk_context *pk ) +/** Generate a key of the desired type. + * + * \param pk The PK object to fill. It must have been initialized + * with mbedtls_pk_setup(). + * \param parameter - For RSA keys, the key size in bits. + * - For EC keys, the curve (\c MBEDTLS_ECP_DP_xxx). + * + * \return The status from the underlying type-specific key + * generation function. + * \return -1 if the key type is not recognized. + */ +static int pk_genkey( mbedtls_pk_context *pk, int parameter ) { ((void) pk); + (void) parameter; #if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_GENPRIME) if( mbedtls_pk_get_type( pk ) == MBEDTLS_PK_RSA ) - return mbedtls_rsa_gen_key( mbedtls_pk_rsa( *pk ), rnd_std_rand, NULL, RSA_KEY_SIZE, 3 ); + return mbedtls_rsa_gen_key( mbedtls_pk_rsa( *pk ), + rnd_std_rand, NULL, + parameter, 3 ); #endif #if defined(MBEDTLS_ECP_C) if( mbedtls_pk_get_type( pk ) == MBEDTLS_PK_ECKEY || @@ -42,7 +56,7 @@ static int pk_genkey( mbedtls_pk_context *pk ) { int ret; if( ( ret = mbedtls_ecp_group_load( &mbedtls_pk_ec( *pk )->grp, - MBEDTLS_ECP_DP_SECP192R1 ) ) != 0 ) + parameter ) ) != 0 ) return( ret ); return mbedtls_ecp_gen_keypair( &mbedtls_pk_ec( *pk )->grp, &mbedtls_pk_ec( *pk )->d, @@ -608,18 +622,18 @@ void invalid_parameters( ) /* END_CASE */ /* BEGIN_CASE */ -void pk_utils( int type, int size, int len, char * name ) +void pk_utils( int type, int parameter, int bitlen, int len, char * name ) { mbedtls_pk_context pk; mbedtls_pk_init( &pk ); TEST_ASSERT( mbedtls_pk_setup( &pk, mbedtls_pk_info_from_type( type ) ) == 0 ); - TEST_ASSERT( pk_genkey( &pk ) == 0 ); + TEST_ASSERT( pk_genkey( &pk, parameter ) == 0 ); TEST_ASSERT( (int) mbedtls_pk_get_type( &pk ) == type ); TEST_ASSERT( mbedtls_pk_can_do( &pk, type ) ); - TEST_ASSERT( mbedtls_pk_get_bitlen( &pk ) == (unsigned) size ); + TEST_ASSERT( mbedtls_pk_get_bitlen( &pk ) == (unsigned) bitlen ); TEST_ASSERT( mbedtls_pk_get_len( &pk ) == (unsigned) len ); TEST_ASSERT( strcmp( mbedtls_pk_get_name( &pk), name ) == 0 ); @@ -897,11 +911,12 @@ exit: /* END_CASE */ /* BEGIN_CASE depends_on:MBEDTLS_SHA256_C */ -void pk_sign_verify( int type, int sign_ret, int verify_ret ) +void pk_sign_verify( int type, int parameter, int sign_ret, int verify_ret ) { mbedtls_pk_context pk; - unsigned char hash[50], sig[5000]; size_t sig_len; + unsigned char hash[MBEDTLS_MD_MAX_SIZE]; + unsigned char sig[MBEDTLS_PK_SIGNATURE_MAX_SIZE]; void *rs_ctx = NULL; #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) mbedtls_pk_restart_ctx ctx; @@ -921,11 +936,15 @@ void pk_sign_verify( int type, int sign_ret, int verify_ret ) memset( sig, 0, sizeof sig ); TEST_ASSERT( mbedtls_pk_setup( &pk, mbedtls_pk_info_from_type( type ) ) == 0 ); - TEST_ASSERT( pk_genkey( &pk ) == 0 ); + TEST_ASSERT( pk_genkey( &pk, parameter ) == 0 ); TEST_ASSERT( mbedtls_pk_sign_restartable( &pk, MBEDTLS_MD_SHA256, hash, sizeof hash, sig, &sig_len, rnd_std_rand, NULL, rs_ctx ) == sign_ret ); + if( sign_ret == 0 ) + TEST_ASSERT( sig_len <= MBEDTLS_PK_SIGNATURE_MAX_SIZE ); + else + sig_len = MBEDTLS_PK_SIGNATURE_MAX_SIZE; TEST_ASSERT( mbedtls_pk_verify( &pk, MBEDTLS_MD_SHA256, hash, sizeof hash, sig, sig_len ) == verify_ret ); @@ -945,6 +964,10 @@ void pk_sign_verify( int type, int sign_ret, int verify_ret ) TEST_ASSERT( mbedtls_pk_sign( &pk, MBEDTLS_MD_SHA256, hash, sizeof hash, sig, &sig_len, rnd_std_rand, NULL ) == sign_ret ); + if( sign_ret == 0 ) + TEST_ASSERT( sig_len <= MBEDTLS_PK_SIGNATURE_MAX_SIZE ); + else + sig_len = MBEDTLS_PK_SIGNATURE_MAX_SIZE; TEST_ASSERT( mbedtls_pk_verify_restartable( &pk, MBEDTLS_MD_SHA256, hash, sizeof hash, sig, sig_len, rs_ctx ) == verify_ret ); @@ -1153,7 +1176,7 @@ void pk_rsa_alt( ) /* Initiliaze PK RSA context with random key */ TEST_ASSERT( mbedtls_pk_setup( &rsa, mbedtls_pk_info_from_type( MBEDTLS_PK_RSA ) ) == 0 ); - TEST_ASSERT( pk_genkey( &rsa ) == 0 ); + TEST_ASSERT( pk_genkey( &rsa, RSA_KEY_SIZE ) == 0 ); /* Extract key to the raw rsa context */ TEST_ASSERT( mbedtls_rsa_copy( &raw, mbedtls_pk_rsa( rsa ) ) == 0 ); diff --git a/tests/suites/test_suite_pkwrite.data b/tests/suites/test_suite_pkwrite.data index c8ff1773c..e0101ccdf 100644 --- a/tests/suites/test_suite_pkwrite.data +++ b/tests/suites/test_suite_pkwrite.data @@ -30,10 +30,18 @@ Private key write check EC 192 bits depends_on:MBEDTLS_ECP_C:MBEDTLS_BASE64_C:MBEDTLS_ECP_DP_SECP192R1_ENABLED pk_write_key_check:"data_files/ec_prv.sec1.pem" +Private key write check EC 256 bits (top bit set) +depends_on:MBEDTLS_ECP_C:MBEDTLS_BASE64_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED +pk_write_key_check:"data_files/ec_256_long_prv.pem" + Private key write check EC 521 bits depends_on:MBEDTLS_ECP_C:MBEDTLS_BASE64_C:MBEDTLS_ECP_DP_SECP521R1_ENABLED pk_write_key_check:"data_files/ec_521_prv.pem" +Private key write check EC 521 bits (top byte is 0) +depends_on:MBEDTLS_ECP_C:MBEDTLS_BASE64_C:MBEDTLS_ECP_DP_SECP521R1_ENABLED +pk_write_key_check:"data_files/ec_521_short_prv.pem" + Private key write check EC Brainpool 512 bits depends_on:MBEDTLS_ECP_C:MBEDTLS_BASE64_C:MBEDTLS_ECP_DP_BP512R1_ENABLED pk_write_key_check:"data_files/ec_bp512_prv.pem" diff --git a/tests/suites/test_suite_psa_crypto.function b/tests/suites/test_suite_psa_crypto.function index 2fd70c6d3..f3f79abcf 100644 --- a/tests/suites/test_suite_psa_crypto.function +++ b/tests/suites/test_suite_psa_crypto.function @@ -899,6 +899,8 @@ static int exported_key_sanity_check( psa_key_type_t type, size_t bits, "No sanity check for public key type=0x%08lx", (unsigned long) type ); test_fail( message, __LINE__, __FILE__ ); + (void) p; + (void) end; return( 0 ); } } diff --git a/tests/suites/test_suite_version.data b/tests/suites/test_suite_version.data index a4575ab00..b6dca233b 100644 --- a/tests/suites/test_suite_version.data +++ b/tests/suites/test_suite_version.data @@ -1,8 +1,8 @@ Check compiletime library version -check_compiletime_version:"2.17.0" +check_compiletime_version:"2.19.1" Check runtime library version -check_runtime_version:"2.17.0" +check_runtime_version:"2.19.1" Check for MBEDTLS_VERSION_C check_feature:"MBEDTLS_VERSION_C":0