diff --git a/.travis.yml b/.travis.yml index 2b41c28f14..cdf74c7177 100644 --- a/.travis.yml +++ b/.travis.yml @@ -27,8 +27,44 @@ jobs: - tests/scripts/all.sh -k build_arm_linux_gnueabi_gcc_arm5vte build_arm_none_eabi_gcc_m0plus - name: full configuration + os: linux + dist: focal + addons: + apt: + packages: + - clang-10 + - gnutls-bin script: - - tests/scripts/all.sh -k test_full_cmake_gcc_asan + # Do a manual build+test sequence rather than using all.sh, + # because there's no all.sh component that does what we want, + # which is a build with Clang >= 10 and ASan, running all the SSL + # testing. + # - The clang executable in the default PATH is Clang 7 on + # Travis's focal instances, but we want Clang >= 10. + # - Running all the SSL testing requires a specific set of + # OpenSSL and GnuTLS versions and we don't want to bother + # with those on Travis. + # So we explicitly select clang-10 as the compiler, and we + # have ad hoc restrictions on SSL testing based on what is + # passing at the time of writing. We will remove these limitations + # gradually. + - make CC=clang-10 CFLAGS='-Werror -Wall -Wextra -fsanitize=address,undefined -fno-sanitize-recover=all -O2' LDFLAGS='-Werror -Wall -Wextra -fsanitize=address,undefined -fno-sanitize-recover=all' + - make test + - programs/test/selftest + - tests/scripts/test_psa_constant_names.py + # Exclude a few test cases that are failing mysteriously. + # https://github.com/Mbed-TLS/mbedtls/issues/6660 + - tests/ssl-opt.sh -e 'Fallback SCSV:\ .*list' + # Modern OpenSSL does not support fixed ECDH, null or ancient ciphers. + - tests/compat.sh -p OpenSSL -e 'NULL\|ECDH-\|DES\|RC4' + - tests/scripts/travis-log-failure.sh + # GnuTLS supports CAMELLIA but compat.sh doesn't properly enable it. + # Modern GnuTLS does not support DES. + # One NULL cipher suite is strangely missing in pre-1.2 protocol + # versions (it works with (D)TLS1.2, but don't bother). + - tests/compat.sh -p GnuTLS -e 'CAMELLIA\|DES\|TLS-RSA-WITH-NULL-SHA256' + - tests/scripts/travis-log-failure.sh + - tests/context-info.sh - name: Windows os: windows diff --git a/ChangeLog.d/psa-ecb-ub.txt b/ChangeLog.d/psa-ecb-ub.txt new file mode 100644 index 0000000000..9d725ac706 --- /dev/null +++ b/ChangeLog.d/psa-ecb-ub.txt @@ -0,0 +1,3 @@ +Bugfix + * Fix undefined behavior (typically harmless in practice) in PSA ECB + encryption and decryption. diff --git a/library/aria.c b/library/aria.c index 924f952834..5e52eea91e 100644 --- a/library/aria.c +++ b/library/aria.c @@ -37,11 +37,6 @@ #include "mbedtls/platform_util.h" -#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ - !defined(inline) && !defined(__cplusplus) -#define inline __inline -#endif - /* Parameter validation macros */ #define ARIA_VALIDATE_RET( cond ) \ MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_ARIA_BAD_INPUT_DATA ) diff --git a/library/chacha20.c b/library/chacha20.c index 44d1612bfe..bd0701482c 100644 --- a/library/chacha20.c +++ b/library/chacha20.c @@ -36,11 +36,6 @@ #if !defined(MBEDTLS_CHACHA20_ALT) -#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ - !defined(inline) && !defined(__cplusplus) -#define inline __inline -#endif - /* Parameter validation macros */ #define CHACHA20_VALIDATE_RET( cond ) \ MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA ) diff --git a/library/common.h b/library/common.h index c06472418d..1663d50226 100644 --- a/library/common.h +++ b/library/common.h @@ -29,8 +29,15 @@ #include "mbedtls/config.h" #endif +#include #include +/* Define `inline` on some non-C99-compliant compilers. */ +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif + /** Helper to define a function as static except when building invasive tests. * * If a function is only used inside its own source file and should be @@ -52,6 +59,44 @@ #define MBEDTLS_STATIC_TESTABLE static #endif +/** Return an offset into a buffer. + * + * This is just the addition of an offset to a pointer, except that this + * function also accepts an offset of 0 into a buffer whose pointer is null. + * (`p + n` has undefined behavior when `p` is null, even when `n == 0`. + * A null pointer is a valid buffer pointer when the size is 0, for example + * as the result of `malloc(0)` on some platforms.) + * + * \param p Pointer to a buffer of at least n bytes. + * This may be \p NULL if \p n is zero. + * \param n An offset in bytes. + * \return Pointer to offset \p n in the buffer \p p. + * Note that this is only a valid pointer if the size of the + * buffer is at least \p n + 1. + */ +static inline unsigned char *mbedtls_buffer_offset( + unsigned char *p, size_t n ) +{ + return( p == NULL ? NULL : p + n ); +} + +/** Return an offset into a read-only buffer. + * + * Similar to mbedtls_buffer_offset(), but for const pointers. + * + * \param p Pointer to a buffer of at least n bytes. + * This may be \p NULL if \p n is zero. + * \param n An offset in bytes. + * \return Pointer to offset \p n in the buffer \p p. + * Note that this is only a valid pointer if the size of the + * buffer is at least \p n + 1. + */ +static inline const unsigned char *mbedtls_buffer_offset_const( + const unsigned char *p, size_t n ) +{ + return( p == NULL ? NULL : p + n ); +} + /** Byte Reading Macros * * Given a multi-byte integer \p x, MBEDTLS_BYTE_n retrieves the n-th diff --git a/library/debug.c b/library/debug.c index 0cc5af8d1c..353b4bf07b 100644 --- a/library/debug.c +++ b/library/debug.c @@ -30,11 +30,6 @@ #include #include -#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ - !defined(inline) && !defined(__cplusplus) -#define inline __inline -#endif - #define DEBUG_BUF_SIZE 512 static int debug_threshold = 0; diff --git a/library/ecp.c b/library/ecp.c index 80adc55c8b..ad19e05fb2 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -104,11 +104,6 @@ #endif #endif /* MBEDTLS_ECP_NO_INTERNAL_RNG */ -#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ - !defined(inline) && !defined(__cplusplus) -#define inline __inline -#endif - #if defined(MBEDTLS_SELF_TEST) /* * Counts of point addition and doubling, and field multiplications. diff --git a/library/ecp_curves.c b/library/ecp_curves.c index 2199be6461..47761eef4e 100644 --- a/library/ecp_curves.c +++ b/library/ecp_curves.c @@ -38,11 +38,6 @@ #define ECP_VALIDATE( cond ) \ MBEDTLS_INTERNAL_VALIDATE( cond ) -#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ - !defined(inline) && !defined(__cplusplus) -#define inline __inline -#endif - #define ECP_MPI_INIT(s, n, p) {s, (n), (mbedtls_mpi_uint *)(p)} #define ECP_MPI_INIT_ARRAY(x) \ diff --git a/library/mps_reader.c b/library/mps_reader.c index 9af5073cc9..b304db3f42 100644 --- a/library/mps_reader.c +++ b/library/mps_reader.c @@ -29,11 +29,6 @@ #include -#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ - !defined(inline) && !defined(__cplusplus) -#define inline __inline -#endif - #if defined(MBEDTLS_MPS_ENABLE_TRACE) static int mbedtls_mps_trace_id = MBEDTLS_MPS_TRACE_BIT_READER; #endif /* MBEDTLS_MPS_ENABLE_TRACE */ diff --git a/library/poly1305.c b/library/poly1305.c index f38f48a457..a1c5b19d8e 100644 --- a/library/poly1305.c +++ b/library/poly1305.c @@ -32,11 +32,6 @@ #if !defined(MBEDTLS_POLY1305_ALT) -#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ - !defined(inline) && !defined(__cplusplus) -#define inline __inline -#endif - /* Parameter validation macros */ #define POLY1305_VALIDATE_RET( cond ) \ MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA ) diff --git a/library/psa_crypto.c b/library/psa_crypto.c index f76c8296de..10c7d1e668 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -3638,8 +3638,8 @@ psa_status_t psa_cipher_encrypt( mbedtls_svc_key_id_t key, status = psa_driver_wrapper_cipher_encrypt( &attributes, slot->key.data, slot->key.bytes, alg, local_iv, default_iv_length, input, input_length, - output + default_iv_length, output_size - default_iv_length, - output_length ); + mbedtls_buffer_offset( output, default_iv_length ), + output_size - default_iv_length, output_length ); exit: unlock_status = psa_unlock_key_slot( slot ); diff --git a/library/psa_crypto_cipher.c b/library/psa_crypto_cipher.c index 38962cd848..13006fa4ae 100644 --- a/library/psa_crypto_cipher.c +++ b/library/psa_crypto_cipher.c @@ -514,9 +514,10 @@ psa_status_t mbedtls_psa_cipher_encrypt( const psa_key_attributes_t *attributes, if( status != PSA_SUCCESS ) goto exit; - status = mbedtls_psa_cipher_finish( &operation, output + update_output_length, - output_size - update_output_length, - &finish_output_length ); + status = mbedtls_psa_cipher_finish( + &operation, + mbedtls_buffer_offset( output, update_output_length ), + output_size - update_output_length, &finish_output_length ); if( status != PSA_SUCCESS ) goto exit; @@ -560,17 +561,20 @@ psa_status_t mbedtls_psa_cipher_decrypt( goto exit; } - status = mbedtls_psa_cipher_update( &operation, input + operation.iv_length, - input_length - operation.iv_length, - output, output_size, &olength ); + status = mbedtls_psa_cipher_update( + &operation, + mbedtls_buffer_offset_const( input, operation.iv_length ), + input_length - operation.iv_length, + output, output_size, &olength ); if( status != PSA_SUCCESS ) goto exit; accumulated_length = olength; - status = mbedtls_psa_cipher_finish( &operation, output + accumulated_length, - output_size - accumulated_length, - &olength ); + status = mbedtls_psa_cipher_finish( + &operation, + mbedtls_buffer_offset( output, accumulated_length ), + output_size - accumulated_length, &olength ); if( status != PSA_SUCCESS ) goto exit; diff --git a/tests/compat.sh b/tests/compat.sh index 9d955186d7..6791c5511a 100755 --- a/tests/compat.sh +++ b/tests/compat.sh @@ -934,6 +934,20 @@ setup_arguments() G_CLIENT_ARGS="-p $PORT --debug 3 $G_MODE" G_CLIENT_PRIO="NONE:$G_PRIO_MODE:+COMP-NULL:+CURVE-ALL:+SIGN-ALL" + # Newer versions of OpenSSL have a syntax to enable all "ciphers", even + # low-security ones. This covers not just cipher suites but also protocol + # versions. It is necessary, for example, to use (D)TLS 1.0/1.1 on + # OpenSSL 1.1.1f from Ubuntu 20.04. The syntax was only introduced in + # OpenSSL 1.1.0 (21e0c1d23afff48601eb93135defddae51f7e2e3) and I can't find + # a way to discover it from -help, so check the openssl version. + case $($OPENSSL_CMD version) in + "OpenSSL 0"*|"OpenSSL 1.0"*) :;; + *) + O_CLIENT_ARGS="$O_CLIENT_ARGS -cipher ALL@SECLEVEL=0" + O_SERVER_ARGS="$O_SERVER_ARGS -cipher ALL@SECLEVEL=0" + ;; + esac + if [ "X$VERIFY" = "XYES" ]; then M_SERVER_ARGS="$M_SERVER_ARGS ca_file=data_files/test-ca_cat12.crt auth_mode=required" diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh index fbf3bf7b8e..c1fffa9ede 100755 --- a/tests/ssl-opt.sh +++ b/tests/ssl-opt.sh @@ -1493,6 +1493,20 @@ if [ -n "${OPENSSL_LEGACY:-}" ]; then O_LEGACY_CLI="$O_LEGACY_CLI -connect 127.0.0.1:+SRV_PORT" fi +# Newer versions of OpenSSL have a syntax to enable all "ciphers", even +# low-security ones. This covers not just cipher suites but also protocol +# versions. It is necessary, for example, to use (D)TLS 1.0/1.1 on +# OpenSSL 1.1.1f from Ubuntu 20.04. The syntax was only introduced in +# OpenSSL 1.1.0 (21e0c1d23afff48601eb93135defddae51f7e2e3) and I can't find +# a way to discover it from -help, so check the openssl version. +case $($OPENSSL_CMD version) in + "OpenSSL 0"*|"OpenSSL 1.0"*) :;; + *) + O_CLI="$O_CLI -cipher ALL@SECLEVEL=0" + O_SRV="$O_SRV -cipher ALL@SECLEVEL=0" + ;; +esac + if [ -n "${OPENSSL_NEXT:-}" ]; then O_NEXT_SRV="$O_NEXT_SRV -accept $SRV_PORT" O_NEXT_CLI="$O_NEXT_CLI -connect 127.0.0.1:+SRV_PORT" diff --git a/tests/suites/test_suite_psa_crypto.function b/tests/suites/test_suite_psa_crypto.function index f9e909372a..0f4e313335 100644 --- a/tests/suites/test_suite_psa_crypto.function +++ b/tests/suites/test_suite_psa_crypto.function @@ -4,6 +4,7 @@ #include "mbedtls/asn1.h" #include "mbedtls/asn1write.h" #include "mbedtls/oid.h" +#include "common.h" /* For MBEDTLS_CTR_DRBG_MAX_REQUEST, knowing that psa_generate_random() * uses mbedtls_ctr_drbg internally. */ @@ -2658,7 +2659,7 @@ void cipher_alg_without_iv( int alg_arg, int key_type_arg, data_t *key_data, TEST_LE_U( length, output_buffer_size ); output_length += length; PSA_ASSERT( psa_cipher_finish( &operation, - output + output_length, + mbedtls_buffer_offset( output, output_length ), output_buffer_size - output_length, &length ) ); output_length += length; @@ -2676,7 +2677,7 @@ void cipher_alg_without_iv( int alg_arg, int key_type_arg, data_t *key_data, TEST_LE_U( length, output_buffer_size ); output_length += length; PSA_ASSERT( psa_cipher_finish( &operation, - output + output_length, + mbedtls_buffer_offset( output, output_length ), output_buffer_size - output_length, &length ) ); output_length += length;