diff --git a/ChangeLog b/ChangeLog index 5434e5509b1e..4df6a665346b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,57 @@ Mbed TLS ChangeLog (Sorted per branch, date) += Mbed TLS 2.28.8 branch released 2024-03-28 + +Features + * AES-NI is now supported in Windows builds with clang and clang-cl. + Resolves #8372. + * Add pc files for pkg-config, e.g.: + pkg-config --cflags --libs (mbedtls|mbedcrypto|mbedx509) + +Security + * Passing buffers that are stored in untrusted memory as arguments + to PSA functions is now secure by default. + The PSA core now protects against modification of inputs or exposure + of intermediate outputs during operations. This is currently implemented + by copying buffers. + This feature increases code size and memory usage. If buffers passed to + PSA functions are owned exclusively by the PSA core for the duration of + the function call (i.e. no buffer parameters are in shared memory), + copying may be disabled by setting MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS. + Note that setting this option will cause input-output buffer overlap to + be only partially supported (#3266). + Fixes CVE-2024-28960. + +Bugfix + * Fix the build with CMake when Everest is enabled through + a user configuration file or the compiler command line. Fixes #8165. + * Fix an inconsistency between implementations and usages of `__cpuid`, + which mainly causes failures when building Windows target using + mingw or clang. Fixes #8334 & #8332. + * Correct initial capacities for key derivation algorithms: TLS12_PRF, + TLS12_PSK_TO_MS. + * Fix mbedtls_pk_get_bitlen() for RSA keys whose size is not a + multiple of 8. Fixes #868. + * Avoid segmentation fault caused by releasing not initialized + entropy resource in gen_key example. Fixes #8809. + * Fix missing bitflags in SSL session serialization headers. Their absence + allowed SSL sessions saved in one configuration to be loaded in a + different, incompatible configuration. + * Fix the restoration of the ALPN when loading serialized connection with + the mbedtls_ssl_context_load() API. + * Fully support arbitrary overlap between inputs and outputs of PSA + functions. Note that overlap is still only partially supported when + MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS is set (#3266). + +Changes + * Use heap memory to allocate DER encoded public/private key. + This reduces stack usage significantly for writing a public/private + key to a PEM string. + * cmake: Use GnuInstallDirs to customize install directories + Replace custom LIB_INSTALL_DIR variable with standard CMAKE_INSTALL_LIBDIR + variable. For backward compatibility, set CMAKE_INSTALL_LIBDIR if + LIB_INSTALL_DIR is set. + = Mbed TLS 2.28.7 branch released 2024-01-26 Security diff --git a/ChangeLog.d/8372.txt b/ChangeLog.d/8372.txt deleted file mode 100644 index 4a72edfb1a95..000000000000 --- a/ChangeLog.d/8372.txt +++ /dev/null @@ -1,3 +0,0 @@ -Features - * AES-NI is now supported in Windows builds with clang and clang-cl. - Resolves #8372. diff --git a/ChangeLog.d/cmake_use_GnuInstallDirs.txt b/ChangeLog.d/cmake_use_GnuInstallDirs.txt deleted file mode 100644 index d8487555d161..000000000000 --- a/ChangeLog.d/cmake_use_GnuInstallDirs.txt +++ /dev/null @@ -1,5 +0,0 @@ -Changes - * cmake: Use GnuInstallDirs to customize install directories - Replace custom LIB_INSTALL_DIR variable with standard CMAKE_INSTALL_LIBDIR - variable. For backward compatibility, set CMAKE_INSTALL_LIBDIR if - LIB_INSTALL_DIR is set. diff --git a/ChangeLog.d/fix-alpn-negotiating-bug.txt b/ChangeLog.d/fix-alpn-negotiating-bug.txt deleted file mode 100644 index 3bceb37f38c8..000000000000 --- a/ChangeLog.d/fix-alpn-negotiating-bug.txt +++ /dev/null @@ -1,3 +0,0 @@ -Bugfix - * Fix the restoration of the ALPN when loading serialized connection with - * the mbedtls_ssl_context_load() API. diff --git a/ChangeLog.d/fix-cmake-3rdparty-custom-config.txt b/ChangeLog.d/fix-cmake-3rdparty-custom-config.txt deleted file mode 100644 index c52aa3deeed5..000000000000 --- a/ChangeLog.d/fix-cmake-3rdparty-custom-config.txt +++ /dev/null @@ -1,3 +0,0 @@ -Bugfix - * Fix the build with CMake when Everest is enabled through - a user configuration file or the compiler command line. Fixes #8165. diff --git a/ChangeLog.d/fix-mingw32-build.txt b/ChangeLog.d/fix-mingw32-build.txt deleted file mode 100644 index feef0a2c517f..000000000000 --- a/ChangeLog.d/fix-mingw32-build.txt +++ /dev/null @@ -1,4 +0,0 @@ -Bugfix - * Fix an inconsistency between implementations and usages of `__cpuid`, - which mainly causes failures when building Windows target using - mingw or clang. Fixes #8334 & #8332. diff --git a/ChangeLog.d/fix-ssl-session-serialization-config.txt b/ChangeLog.d/fix-ssl-session-serialization-config.txt deleted file mode 100644 index ca1cc81f5e21..000000000000 --- a/ChangeLog.d/fix-ssl-session-serialization-config.txt +++ /dev/null @@ -1,4 +0,0 @@ -Bugfix - * Fix missing bitflags in SSL session serialization headers. Their absence - allowed SSL sessions saved in one configuration to be loaded in a - different, incompatible configuration. diff --git a/ChangeLog.d/fix_kdf_incorrect_initial_capacity.txt b/ChangeLog.d/fix_kdf_incorrect_initial_capacity.txt deleted file mode 100644 index 11b82782fbea..000000000000 --- a/ChangeLog.d/fix_kdf_incorrect_initial_capacity.txt +++ /dev/null @@ -1,3 +0,0 @@ -Bugfix - * Correct initial capacities for key derivation algorithms:TLS12_PRF, - TLS12_PSK_TO_MS diff --git a/ChangeLog.d/gen-key-segfault.txt b/ChangeLog.d/gen-key-segfault.txt deleted file mode 100644 index fefc702726b9..000000000000 --- a/ChangeLog.d/gen-key-segfault.txt +++ /dev/null @@ -1,3 +0,0 @@ -Bugfix - * Avoid segmentation fault caused by releasing not initialized - entropy resource in gen_key example. Fixes #8809. diff --git a/ChangeLog.d/license.txt b/ChangeLog.d/license.txt deleted file mode 100644 index 0b6bb1f02258..000000000000 --- a/ChangeLog.d/license.txt +++ /dev/null @@ -1,3 +0,0 @@ -Changes - * Mbed TLS is now released under a dual Apache-2.0 OR GPL-2.0-or-later - license. Users may choose which license they take the code under. diff --git a/ChangeLog.d/pkg-config-files-addition.txt b/ChangeLog.d/pkg-config-files-addition.txt deleted file mode 100644 index 5df6ffb3be20..000000000000 --- a/ChangeLog.d/pkg-config-files-addition.txt +++ /dev/null @@ -1,3 +0,0 @@ -Features - * Add pc files for pkg-config. eg.: - pkg-config --cflags --libs (mbedtls|mbedcrypto|mbedx509) diff --git a/ChangeLog.d/pkwrite-pem-use-heap.txt b/ChangeLog.d/pkwrite-pem-use-heap.txt deleted file mode 100644 index 11db7b6b06cf..000000000000 --- a/ChangeLog.d/pkwrite-pem-use-heap.txt +++ /dev/null @@ -1,4 +0,0 @@ -Changes - * Use heap memory to allocate DER encoded public/private key. - This reduces stack usage significantly for writing a public/private - key to a PEM string. diff --git a/ChangeLog.d/rsa-bitlen.txt b/ChangeLog.d/rsa-bitlen.txt deleted file mode 100644 index 9cb868947ae1..000000000000 --- a/ChangeLog.d/rsa-bitlen.txt +++ /dev/null @@ -1,3 +0,0 @@ -Bugfix - * Fix mbedtls_pk_get_bitlen() for RSA keys whose size is not a - multiple of 8. Fixes #868. diff --git a/doxygen/input/doc_mainpage.h b/doxygen/input/doc_mainpage.h index f22ca106d379..7a240216be33 100644 --- a/doxygen/input/doc_mainpage.h +++ b/doxygen/input/doc_mainpage.h @@ -10,7 +10,7 @@ */ /** - * @mainpage Mbed TLS v2.28.7 API Documentation + * @mainpage Mbed TLS v2.28.8 API Documentation * * This documentation describes the internal structure of Mbed TLS. It was * automatically generated from specially formatted comment blocks in diff --git a/doxygen/mbedtls.doxyfile b/doxygen/mbedtls.doxyfile index 2c710406beac..971a8b2af54b 100644 --- a/doxygen/mbedtls.doxyfile +++ b/doxygen/mbedtls.doxyfile @@ -1,4 +1,4 @@ -PROJECT_NAME = "Mbed TLS v2.28.7" +PROJECT_NAME = "Mbed TLS v2.28.8" OUTPUT_DIRECTORY = ../apidoc/ FULL_PATH_NAMES = NO OPTIMIZE_OUTPUT_FOR_C = YES diff --git a/include/mbedtls/config.h b/include/mbedtls/config.h index ac2146ea114b..4842fd494c9b 100644 --- a/include/mbedtls/config.h +++ b/include/mbedtls/config.h @@ -1570,6 +1570,26 @@ */ //#define MBEDTLS_PSA_INJECT_ENTROPY +/** + * \def MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS + * + * Assume all buffers passed to PSA functions are owned exclusively by the + * PSA function and are not stored in shared memory. + * + * This option may be enabled if all buffers passed to any PSA function reside + * in memory that is accessible only to the PSA function during its execution. + * + * This option MUST be disabled whenever buffer arguments are in memory shared + * with an untrusted party, for example where arguments to PSA calls are passed + * across a trust boundary. + * + * \note Enabling this option reduces memory usage and code size. + * + * \note Enabling this option causes overlap of input and output buffers + * not to be supported by PSA functions. + */ +//#define MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS + /** * \def MBEDTLS_RSA_NO_CRT * diff --git a/include/mbedtls/version.h b/include/mbedtls/version.h index 0533bca68128..bbe76b173929 100644 --- a/include/mbedtls/version.h +++ b/include/mbedtls/version.h @@ -26,16 +26,16 @@ */ #define MBEDTLS_VERSION_MAJOR 2 #define MBEDTLS_VERSION_MINOR 28 -#define MBEDTLS_VERSION_PATCH 7 +#define MBEDTLS_VERSION_PATCH 8 /** * The single version number has the following structure: * MMNNPP00 * Major version | Minor version | Patch version */ -#define MBEDTLS_VERSION_NUMBER 0x021C0700 -#define MBEDTLS_VERSION_STRING "2.28.7" -#define MBEDTLS_VERSION_STRING_FULL "Mbed TLS 2.28.7" +#define MBEDTLS_VERSION_NUMBER 0x021C0800 +#define MBEDTLS_VERSION_STRING "2.28.8" +#define MBEDTLS_VERSION_STRING_FULL "Mbed TLS 2.28.8" #if defined(MBEDTLS_VERSION_C) diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt index 798f42f713cf..48e51a1581db 100644 --- a/library/CMakeLists.txt +++ b/library/CMakeLists.txt @@ -204,15 +204,15 @@ endif(USE_STATIC_MBEDTLS_LIBRARY) if(USE_SHARED_MBEDTLS_LIBRARY) set(CMAKE_LIBRARY_PATH ${CMAKE_CURRENT_BINARY_DIR}) add_library(${mbedcrypto_target} SHARED ${src_crypto}) - set_target_properties(${mbedcrypto_target} PROPERTIES VERSION 2.28.7 SOVERSION 7) + set_target_properties(${mbedcrypto_target} PROPERTIES VERSION 2.28.8 SOVERSION 7) target_link_libraries(${mbedcrypto_target} PUBLIC ${libs}) add_library(${mbedx509_target} SHARED ${src_x509}) - set_target_properties(${mbedx509_target} PROPERTIES VERSION 2.28.7 SOVERSION 1) + set_target_properties(${mbedx509_target} PROPERTIES VERSION 2.28.8 SOVERSION 1) target_link_libraries(${mbedx509_target} PUBLIC ${libs} ${mbedcrypto_target}) add_library(${mbedtls_target} SHARED ${src_tls}) - set_target_properties(${mbedtls_target} PROPERTIES VERSION 2.28.7 SOVERSION 14) + set_target_properties(${mbedtls_target} PROPERTIES VERSION 2.28.8 SOVERSION 14) target_link_libraries(${mbedtls_target} PUBLIC ${libs} ${mbedx509_target}) endif(USE_SHARED_MBEDTLS_LIBRARY) @@ -226,7 +226,9 @@ foreach(target IN LISTS target_libraries) PUBLIC ${MBEDTLS_DIR}/include/ PUBLIC ${thirdparty_inc_public} PRIVATE ${MBEDTLS_DIR}/library/ - PRIVATE ${thirdparty_inc}) + PRIVATE ${thirdparty_inc} + # Needed to include psa_crypto_driver_wrappers.h + ${CMAKE_CURRENT_BINARY_DIR}) target_compile_definitions(${target} PRIVATE ${thirdparty_def}) # Pass-through MBEDTLS_CONFIG_FILE and MBEDTLS_USER_CONFIG_FILE diff --git a/library/gcm.c b/library/gcm.c index 86d5fa2b5fce..d3e773278fbb 100644 --- a/library/gcm.c +++ b/library/gcm.c @@ -241,7 +241,7 @@ int mbedtls_gcm_starts(mbedtls_gcm_context *ctx, uint64_t iv_bits; GCM_VALIDATE_RET(ctx != NULL); - GCM_VALIDATE_RET(iv != NULL); + GCM_VALIDATE_RET(iv_len == 0 || iv != NULL); GCM_VALIDATE_RET(add_len == 0 || add != NULL); /* IV and AD are limited to 2^64 bits, so 2^61 bytes */ @@ -433,7 +433,7 @@ int mbedtls_gcm_crypt_and_tag(mbedtls_gcm_context *ctx, int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; GCM_VALIDATE_RET(ctx != NULL); - GCM_VALIDATE_RET(iv != NULL); + GCM_VALIDATE_RET(iv_len == 0 || iv != NULL); GCM_VALIDATE_RET(add_len == 0 || add != NULL); GCM_VALIDATE_RET(length == 0 || input != NULL); GCM_VALIDATE_RET(length == 0 || output != NULL); @@ -470,7 +470,7 @@ int mbedtls_gcm_auth_decrypt(mbedtls_gcm_context *ctx, int diff; GCM_VALIDATE_RET(ctx != NULL); - GCM_VALIDATE_RET(iv != NULL); + GCM_VALIDATE_RET(iv_len == 0 || iv != NULL); GCM_VALIDATE_RET(add_len == 0 || add != NULL); GCM_VALIDATE_RET(tag != NULL); GCM_VALIDATE_RET(length == 0 || input != NULL); diff --git a/library/psa_crypto.c b/library/psa_crypto.c index ec5934e0e0f6..e85e5792e2b8 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -106,6 +106,117 @@ mbedtls_psa_drbg_context_t *const mbedtls_psa_random_state = if (global_data.initialized == 0) \ return PSA_ERROR_BAD_STATE; +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) + +/* Declare a local copy of an input buffer and a variable that will be used + * to store a pointer to the start of the buffer. + * + * Note: This macro must be called before any operations which may jump to + * the exit label, so that the local input copy object is safe to be freed. + * + * Assumptions: + * - input is the name of a pointer to the buffer to be copied + * - The name LOCAL_INPUT_COPY_OF_input is unused in the current scope + * - input_copy_name is a name that is unused in the current scope + */ +#define LOCAL_INPUT_DECLARE(input, input_copy_name) \ + psa_crypto_local_input_t LOCAL_INPUT_COPY_OF_##input = PSA_CRYPTO_LOCAL_INPUT_INIT; \ + const uint8_t *input_copy_name = NULL; + +/* Allocate a copy of the buffer input and set the pointer input_copy to + * point to the start of the copy. + * + * Assumptions: + * - psa_status_t status exists + * - An exit label is declared + * - input is the name of a pointer to the buffer to be copied + * - LOCAL_INPUT_DECLARE(input, input_copy) has previously been called + */ +#define LOCAL_INPUT_ALLOC(input, length, input_copy) \ + status = psa_crypto_local_input_alloc(input, length, \ + &LOCAL_INPUT_COPY_OF_##input); \ + if (status != PSA_SUCCESS) { \ + goto exit; \ + } \ + input_copy = LOCAL_INPUT_COPY_OF_##input.buffer; + +/* Free the local input copy allocated previously by LOCAL_INPUT_ALLOC() + * + * Assumptions: + * - input_copy is the name of the input copy pointer set by LOCAL_INPUT_ALLOC() + * - input is the name of the original buffer that was copied + */ +#define LOCAL_INPUT_FREE(input, input_copy) \ + input_copy = NULL; \ + psa_crypto_local_input_free(&LOCAL_INPUT_COPY_OF_##input); + +/* Declare a local copy of an output buffer and a variable that will be used + * to store a pointer to the start of the buffer. + * + * Note: This macro must be called before any operations which may jump to + * the exit label, so that the local output copy object is safe to be freed. + * + * Assumptions: + * - output is the name of a pointer to the buffer to be copied + * - The name LOCAL_OUTPUT_COPY_OF_output is unused in the current scope + * - output_copy_name is a name that is unused in the current scope + */ +#define LOCAL_OUTPUT_DECLARE(output, output_copy_name) \ + psa_crypto_local_output_t LOCAL_OUTPUT_COPY_OF_##output = PSA_CRYPTO_LOCAL_OUTPUT_INIT; \ + uint8_t *output_copy_name = NULL; + +/* Allocate a copy of the buffer output and set the pointer output_copy to + * point to the start of the copy. + * + * Assumptions: + * - psa_status_t status exists + * - An exit label is declared + * - output is the name of a pointer to the buffer to be copied + * - LOCAL_OUTPUT_DECLARE(output, output_copy) has previously been called + */ +#define LOCAL_OUTPUT_ALLOC(output, length, output_copy) \ + status = psa_crypto_local_output_alloc(output, length, \ + &LOCAL_OUTPUT_COPY_OF_##output); \ + if (status != PSA_SUCCESS) { \ + goto exit; \ + } \ + output_copy = LOCAL_OUTPUT_COPY_OF_##output.buffer; + +/* Free the local output copy allocated previously by LOCAL_OUTPUT_ALLOC() + * after first copying back its contents to the original buffer. + * + * Assumptions: + * - psa_status_t status exists + * - output_copy is the name of the output copy pointer set by LOCAL_OUTPUT_ALLOC() + * - output is the name of the original buffer that was copied + */ +#define LOCAL_OUTPUT_FREE(output, output_copy) \ + output_copy = NULL; \ + do { \ + psa_status_t local_output_status; \ + local_output_status = psa_crypto_local_output_free(&LOCAL_OUTPUT_COPY_OF_##output); \ + if (local_output_status != PSA_SUCCESS) { \ + /* Since this error case is an internal error, it's more serious than \ + * any existing error code and so it's fine to overwrite the existing \ + * status. */ \ + status = local_output_status; \ + } \ + } while (0) +#else /* !MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS */ +#define LOCAL_INPUT_DECLARE(input, input_copy_name) \ + const uint8_t *input_copy_name = NULL; +#define LOCAL_INPUT_ALLOC(input, length, input_copy) \ + input_copy = input; +#define LOCAL_INPUT_FREE(input, input_copy) \ + input_copy = NULL; +#define LOCAL_OUTPUT_DECLARE(output, output_copy_name) \ + uint8_t *output_copy_name = NULL; +#define LOCAL_OUTPUT_ALLOC(output, length, output_copy) \ + output_copy = output; +#define LOCAL_OUTPUT_FREE(output, output_copy) \ + output_copy = NULL; +#endif /* !MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS */ + psa_status_t mbedtls_to_psa_error(int ret) { /* Mbed TLS error codes can combine a high-level error code and a @@ -1355,14 +1466,14 @@ psa_status_t psa_export_key_internal( } psa_status_t psa_export_key(mbedtls_svc_key_id_t key, - uint8_t *data, + uint8_t *data_external, size_t data_size, size_t *data_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_slot_t *slot; - + LOCAL_OUTPUT_DECLARE(data_external, data); /* Reject a zero-length output buffer now, since this can never be a * valid key representation. This way we know that data must be a valid * pointer and we can do things like memset(data, ..., data_size). */ @@ -1386,6 +1497,8 @@ psa_status_t psa_export_key(mbedtls_svc_key_id_t key, return status; } + LOCAL_OUTPUT_ALLOC(data_external, data_size, data); + psa_key_attributes_t attributes = { .core = slot->attr }; @@ -1393,8 +1506,12 @@ psa_status_t psa_export_key(mbedtls_svc_key_id_t key, slot->key.data, slot->key.bytes, data, data_size, data_length); +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) +exit: +#endif unlock_status = psa_unlock_key_slot(slot); + LOCAL_OUTPUT_FREE(data_external, data); return (status == PSA_SUCCESS) ? unlock_status : status; } @@ -1454,7 +1571,7 @@ psa_status_t psa_export_public_key_internal( } psa_status_t psa_export_public_key(mbedtls_svc_key_id_t key, - uint8_t *data, + uint8_t *data_external, size_t data_size, size_t *data_length) { @@ -1462,6 +1579,7 @@ psa_status_t psa_export_public_key(mbedtls_svc_key_id_t key, psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_attributes_t attributes; psa_key_slot_t *slot; + LOCAL_OUTPUT_DECLARE(data_external, data); /* Reject a zero-length output buffer now, since this can never be a * valid key representation. This way we know that data must be a valid @@ -1482,6 +1600,8 @@ psa_status_t psa_export_public_key(mbedtls_svc_key_id_t key, return status; } + LOCAL_OUTPUT_ALLOC(data_external, data_size, data); + if (!PSA_KEY_TYPE_IS_ASYMMETRIC(slot->attr.type)) { status = PSA_ERROR_INVALID_ARGUMENT; goto exit; @@ -1497,6 +1617,7 @@ psa_status_t psa_export_public_key(mbedtls_svc_key_id_t key, exit: unlock_status = psa_unlock_key_slot(slot); + LOCAL_OUTPUT_FREE(data_external, data); return (status == PSA_SUCCESS) ? unlock_status : status; } @@ -1935,11 +2056,12 @@ static psa_status_t psa_validate_optional_attributes( } psa_status_t psa_import_key(const psa_key_attributes_t *attributes, - const uint8_t *data, + const uint8_t *data_external, size_t data_length, mbedtls_svc_key_id_t *key) { psa_status_t status; + LOCAL_INPUT_DECLARE(data_external, data); psa_key_slot_t *slot = NULL; psa_se_drv_table_entry_t *driver = NULL; size_t bits; @@ -1953,6 +2075,8 @@ psa_status_t psa_import_key(const psa_key_attributes_t *attributes, return PSA_ERROR_INVALID_ARGUMENT; } + LOCAL_INPUT_ALLOC(data_external, data_length, data); + status = psa_start_key_creation(PSA_KEY_CREATION_IMPORT, attributes, &slot, &driver); if (status != PSA_SUCCESS) { @@ -1994,6 +2118,7 @@ psa_status_t psa_import_key(const psa_key_attributes_t *attributes, status = psa_finish_key_creation(slot, driver, key); exit: + LOCAL_INPUT_FREE(data_external, data); if (status != PSA_SUCCESS) { psa_fail_key_creation(slot, driver); } @@ -2178,10 +2303,11 @@ psa_status_t psa_hash_setup(psa_hash_operation_t *operation, } psa_status_t psa_hash_update(psa_hash_operation_t *operation, - const uint8_t *input, + const uint8_t *input_external, size_t input_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + LOCAL_INPUT_DECLARE(input_external, input); if (operation->id == 0) { status = PSA_ERROR_BAD_STATE; @@ -2194,6 +2320,7 @@ psa_status_t psa_hash_update(psa_hash_operation_t *operation, return PSA_SUCCESS; } + LOCAL_INPUT_ALLOC(input_external, input_length, input); status = psa_driver_wrapper_hash_update(operation, input, input_length); exit: @@ -2201,32 +2328,57 @@ psa_status_t psa_hash_update(psa_hash_operation_t *operation, psa_hash_abort(operation); } + LOCAL_INPUT_FREE(input_external, input); return status; } -psa_status_t psa_hash_finish(psa_hash_operation_t *operation, - uint8_t *hash, - size_t hash_size, - size_t *hash_length) +static psa_status_t psa_hash_finish_internal(psa_hash_operation_t *operation, + uint8_t *hash, + size_t hash_size, + size_t *hash_length) { + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + *hash_length = 0; if (operation->id == 0) { return PSA_ERROR_BAD_STATE; } - psa_status_t status = psa_driver_wrapper_hash_finish( + status = psa_driver_wrapper_hash_finish( operation, hash, hash_size, hash_length); psa_hash_abort(operation); + + return status; +} + +psa_status_t psa_hash_finish(psa_hash_operation_t *operation, + uint8_t *hash_external, + size_t hash_size, + size_t *hash_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + LOCAL_OUTPUT_DECLARE(hash_external, hash); + + LOCAL_OUTPUT_ALLOC(hash_external, hash_size, hash); + status = psa_hash_finish_internal(operation, hash, hash_size, hash_length); + +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) +exit: +#endif + LOCAL_OUTPUT_FREE(hash_external, hash); return status; } psa_status_t psa_hash_verify(psa_hash_operation_t *operation, - const uint8_t *hash, + const uint8_t *hash_external, size_t hash_length) { uint8_t actual_hash[PSA_HASH_MAX_SIZE]; size_t actual_hash_length; - psa_status_t status = psa_hash_finish( + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + LOCAL_INPUT_DECLARE(hash_external, hash); + + status = psa_hash_finish_internal( operation, actual_hash, sizeof(actual_hash), &actual_hash_length); @@ -2240,6 +2392,7 @@ psa_status_t psa_hash_verify(psa_hash_operation_t *operation, goto exit; } + LOCAL_INPUT_ALLOC(hash_external, hash_length, hash); if (mbedtls_psa_safer_memcmp(hash, actual_hash, actual_hash_length) != 0) { status = PSA_ERROR_INVALID_SIGNATURE; } @@ -2249,36 +2402,55 @@ psa_status_t psa_hash_verify(psa_hash_operation_t *operation, if (status != PSA_SUCCESS) { psa_hash_abort(operation); } - + LOCAL_INPUT_FREE(hash_external, hash); return status; } psa_status_t psa_hash_compute(psa_algorithm_t alg, - const uint8_t *input, size_t input_length, - uint8_t *hash, size_t hash_size, + const uint8_t *input_external, size_t input_length, + uint8_t *hash_external, size_t hash_size, size_t *hash_length) { + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + LOCAL_INPUT_DECLARE(input_external, input); + LOCAL_OUTPUT_DECLARE(hash_external, hash); + *hash_length = 0; if (!PSA_ALG_IS_HASH(alg)) { return PSA_ERROR_INVALID_ARGUMENT; } - return psa_driver_wrapper_hash_compute(alg, input, input_length, - hash, hash_size, hash_length); + LOCAL_INPUT_ALLOC(input_external, input_length, input); + LOCAL_OUTPUT_ALLOC(hash_external, hash_size, hash); + status = psa_driver_wrapper_hash_compute(alg, input, input_length, + hash, hash_size, hash_length); + +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) +exit: +#endif + LOCAL_INPUT_FREE(input_external, input); + LOCAL_OUTPUT_FREE(hash_external, hash); + return status; } psa_status_t psa_hash_compare(psa_algorithm_t alg, - const uint8_t *input, size_t input_length, - const uint8_t *hash, size_t hash_length) + const uint8_t *input_external, size_t input_length, + const uint8_t *hash_external, size_t hash_length) { uint8_t actual_hash[PSA_HASH_MAX_SIZE]; size_t actual_hash_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + LOCAL_INPUT_DECLARE(input_external, input); + LOCAL_INPUT_DECLARE(hash_external, hash); if (!PSA_ALG_IS_HASH(alg)) { - return PSA_ERROR_INVALID_ARGUMENT; + status = PSA_ERROR_INVALID_ARGUMENT; + return status; } - psa_status_t status = psa_driver_wrapper_hash_compute( + LOCAL_INPUT_ALLOC(input_external, input_length, input); + status = psa_driver_wrapper_hash_compute( alg, input, input_length, actual_hash, sizeof(actual_hash), &actual_hash_length); @@ -2289,12 +2461,18 @@ psa_status_t psa_hash_compare(psa_algorithm_t alg, status = PSA_ERROR_INVALID_SIGNATURE; goto exit; } + + LOCAL_INPUT_ALLOC(hash_external, hash_length, hash); if (mbedtls_psa_safer_memcmp(hash, actual_hash, actual_hash_length) != 0) { status = PSA_ERROR_INVALID_SIGNATURE; } exit: mbedtls_platform_zeroize(actual_hash, sizeof(actual_hash)); + + LOCAL_INPUT_FREE(input_external, input); + LOCAL_INPUT_FREE(hash_external, hash); + return status; } @@ -2464,35 +2642,48 @@ psa_status_t psa_mac_verify_setup(psa_mac_operation_t *operation, } psa_status_t psa_mac_update(psa_mac_operation_t *operation, - const uint8_t *input, + const uint8_t *input_external, size_t input_length) { + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + LOCAL_INPUT_DECLARE(input_external, input); + if (operation->id == 0) { - return PSA_ERROR_BAD_STATE; + status = PSA_ERROR_BAD_STATE; + return status; } /* Don't require hash implementations to behave correctly on a * zero-length input, which may have an invalid pointer. */ if (input_length == 0) { - return PSA_SUCCESS; + status = PSA_SUCCESS; + return status; } - psa_status_t status = psa_driver_wrapper_mac_update(operation, - input, input_length); + LOCAL_INPUT_ALLOC(input_external, input_length, input); + status = psa_driver_wrapper_mac_update(operation, input, input_length); + if (status != PSA_SUCCESS) { psa_mac_abort(operation); } +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) +exit: +#endif + LOCAL_INPUT_FREE(input_external, input); + return status; } psa_status_t psa_mac_sign_finish(psa_mac_operation_t *operation, - uint8_t *mac, + uint8_t *mac_external, size_t mac_size, size_t *mac_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_status_t abort_status = PSA_ERROR_CORRUPTION_DETECTED; + LOCAL_OUTPUT_DECLARE(mac_external, mac); + LOCAL_OUTPUT_ALLOC(mac_external, mac_size, mac); if (operation->id == 0) { status = PSA_ERROR_BAD_STATE; @@ -2532,22 +2723,24 @@ psa_status_t psa_mac_sign_finish(psa_mac_operation_t *operation, operation->mac_size = 0; } - if (mac_size > operation->mac_size) { + if ((mac != NULL) && (mac_size > operation->mac_size)) { memset(&mac[operation->mac_size], '!', mac_size - operation->mac_size); } abort_status = psa_mac_abort(operation); + LOCAL_OUTPUT_FREE(mac_external, mac); return status == PSA_SUCCESS ? abort_status : status; } psa_status_t psa_mac_verify_finish(psa_mac_operation_t *operation, - const uint8_t *mac, + const uint8_t *mac_external, size_t mac_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_status_t abort_status = PSA_ERROR_CORRUPTION_DETECTED; + LOCAL_INPUT_DECLARE(mac_external, mac); if (operation->id == 0) { status = PSA_ERROR_BAD_STATE; @@ -2564,11 +2757,13 @@ psa_status_t psa_mac_verify_finish(psa_mac_operation_t *operation, goto exit; } + LOCAL_INPUT_ALLOC(mac_external, mac_length, mac); status = psa_driver_wrapper_mac_verify_finish(operation, mac, mac_length); exit: abort_status = psa_mac_abort(operation); + LOCAL_INPUT_FREE(mac_external, mac); return status == PSA_SUCCESS ? abort_status : status; } @@ -2641,28 +2836,45 @@ static psa_status_t psa_mac_compute_internal(mbedtls_svc_key_id_t key, psa_status_t psa_mac_compute(mbedtls_svc_key_id_t key, psa_algorithm_t alg, - const uint8_t *input, + const uint8_t *input_external, size_t input_length, - uint8_t *mac, + uint8_t *mac_external, size_t mac_size, size_t *mac_length) { - return psa_mac_compute_internal(key, alg, - input, input_length, - mac, mac_size, mac_length, 1); + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + LOCAL_INPUT_DECLARE(input_external, input); + LOCAL_OUTPUT_DECLARE(mac_external, mac); + + LOCAL_INPUT_ALLOC(input_external, input_length, input); + LOCAL_OUTPUT_ALLOC(mac_external, mac_size, mac); + status = psa_mac_compute_internal(key, alg, + input, input_length, + mac, mac_size, mac_length, 1); + +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) +exit: +#endif + LOCAL_INPUT_FREE(input_external, input); + LOCAL_OUTPUT_FREE(mac_external, mac); + + return status; } psa_status_t psa_mac_verify(mbedtls_svc_key_id_t key, psa_algorithm_t alg, - const uint8_t *input, + const uint8_t *input_external, size_t input_length, - const uint8_t *mac, + const uint8_t *mac_external, size_t mac_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; uint8_t actual_mac[PSA_MAC_MAX_SIZE]; size_t actual_mac_length; + LOCAL_INPUT_DECLARE(input_external, input); + LOCAL_INPUT_DECLARE(mac_external, mac); + LOCAL_INPUT_ALLOC(input_external, input_length, input); status = psa_mac_compute_internal(key, alg, input, input_length, actual_mac, sizeof(actual_mac), @@ -2675,6 +2887,8 @@ psa_status_t psa_mac_verify(mbedtls_svc_key_id_t key, status = PSA_ERROR_INVALID_SIGNATURE; goto exit; } + + LOCAL_INPUT_ALLOC(mac_external, mac_length, mac); if (mbedtls_psa_safer_memcmp(mac, actual_mac, actual_mac_length) != 0) { status = PSA_ERROR_INVALID_SIGNATURE; goto exit; @@ -2682,6 +2896,8 @@ psa_status_t psa_mac_verify(mbedtls_svc_key_id_t key, exit: mbedtls_platform_zeroize(actual_mac, sizeof(actual_mac)); + LOCAL_INPUT_FREE(input_external, input); + LOCAL_INPUT_FREE(mac_external, mac); return status; } @@ -2879,15 +3095,27 @@ psa_status_t psa_sign_message_builtin( psa_status_t psa_sign_message(mbedtls_svc_key_id_t key, psa_algorithm_t alg, - const uint8_t *input, + const uint8_t *input_external, size_t input_length, - uint8_t *signature, + uint8_t *signature_external, size_t signature_size, size_t *signature_length) { - return psa_sign_internal( - key, 1, alg, input, input_length, - signature, signature_size, signature_length); + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + LOCAL_INPUT_DECLARE(input_external, input); + LOCAL_OUTPUT_DECLARE(signature_external, signature); + + LOCAL_INPUT_ALLOC(input_external, input_length, input); + LOCAL_OUTPUT_ALLOC(signature_external, signature_size, signature); + status = psa_sign_internal(key, 1, alg, input, input_length, signature, + signature_size, signature_length); + +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) +exit: +#endif + LOCAL_INPUT_FREE(input_external, input); + LOCAL_OUTPUT_FREE(signature_external, signature); + return status; } psa_status_t psa_verify_message_builtin( @@ -2926,14 +3154,27 @@ psa_status_t psa_verify_message_builtin( psa_status_t psa_verify_message(mbedtls_svc_key_id_t key, psa_algorithm_t alg, - const uint8_t *input, + const uint8_t *input_external, size_t input_length, - const uint8_t *signature, + const uint8_t *signature_external, size_t signature_length) { - return psa_verify_internal( - key, 1, alg, input, input_length, - signature, signature_length); + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + LOCAL_INPUT_DECLARE(input_external, input); + LOCAL_INPUT_DECLARE(signature_external, signature); + + LOCAL_INPUT_ALLOC(input_external, input_length, input); + LOCAL_INPUT_ALLOC(signature_external, signature_length, signature); + status = psa_verify_internal(key, 1, alg, input, input_length, signature, + signature_length); + +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) +exit: +#endif + LOCAL_INPUT_FREE(input_external, input); + LOCAL_INPUT_FREE(signature_external, signature); + + return status; } psa_status_t psa_sign_hash_builtin( @@ -2986,15 +3227,28 @@ psa_status_t psa_sign_hash_builtin( psa_status_t psa_sign_hash(mbedtls_svc_key_id_t key, psa_algorithm_t alg, - const uint8_t *hash, + const uint8_t *hash_external, size_t hash_length, - uint8_t *signature, + uint8_t *signature_external, size_t signature_size, size_t *signature_length) { - return psa_sign_internal( - key, 0, alg, hash, hash_length, - signature, signature_size, signature_length); + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + LOCAL_INPUT_DECLARE(hash_external, hash); + LOCAL_OUTPUT_DECLARE(signature_external, signature); + + LOCAL_INPUT_ALLOC(hash_external, hash_length, hash); + LOCAL_OUTPUT_ALLOC(signature_external, signature_size, signature); + status = psa_sign_internal(key, 0, alg, hash, hash_length, signature, + signature_size, signature_length); + +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) +exit: +#endif + LOCAL_INPUT_FREE(hash_external, hash); + LOCAL_OUTPUT_FREE(signature_external, signature); + + return status; } psa_status_t psa_verify_hash_builtin( @@ -3046,14 +3300,27 @@ psa_status_t psa_verify_hash_builtin( psa_status_t psa_verify_hash(mbedtls_svc_key_id_t key, psa_algorithm_t alg, - const uint8_t *hash, + const uint8_t *hash_external, size_t hash_length, - const uint8_t *signature, + const uint8_t *signature_external, size_t signature_length) { - return psa_verify_internal( - key, 0, alg, hash, hash_length, - signature, signature_length); + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + LOCAL_INPUT_DECLARE(hash_external, hash); + LOCAL_INPUT_DECLARE(signature_external, signature); + + LOCAL_INPUT_ALLOC(hash_external, hash_length, hash); + LOCAL_INPUT_ALLOC(signature_external, signature_length, signature); + status = psa_verify_internal(key, 0, alg, hash, hash_length, signature, + signature_length); + +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) +exit: +#endif + LOCAL_INPUT_FREE(hash_external, hash); + LOCAL_INPUT_FREE(signature_external, signature); + + return status; } #if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) @@ -3069,17 +3336,20 @@ static void psa_rsa_oaep_set_padding_mode(psa_algorithm_t alg, psa_status_t psa_asymmetric_encrypt(mbedtls_svc_key_id_t key, psa_algorithm_t alg, - const uint8_t *input, + const uint8_t *input_external, size_t input_length, - const uint8_t *salt, + const uint8_t *salt_external, size_t salt_length, - uint8_t *output, + uint8_t *output_external, size_t output_size, size_t *output_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_slot_t *slot; + LOCAL_INPUT_DECLARE(input_external, input); + LOCAL_INPUT_DECLARE(salt_external, salt); + LOCAL_OUTPUT_DECLARE(output_external, output); (void) input; (void) input_length; @@ -3122,6 +3392,9 @@ psa_status_t psa_asymmetric_encrypt(mbedtls_svc_key_id_t key, } #endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) */ + LOCAL_INPUT_ALLOC(input_external, input_length, input); + LOCAL_INPUT_ALLOC(salt_external, salt_length, salt); + LOCAL_OUTPUT_ALLOC(output_external, output_size, output); if (alg == PSA_ALG_RSA_PKCS1V15_CRYPT) { #if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) status = mbedtls_to_psa_error( @@ -3172,22 +3445,29 @@ psa_status_t psa_asymmetric_encrypt(mbedtls_svc_key_id_t key, exit: unlock_status = psa_unlock_key_slot(slot); + LOCAL_INPUT_FREE(input_external, input); + LOCAL_INPUT_FREE(salt_external, salt); + LOCAL_OUTPUT_FREE(output_external, output); + return (status == PSA_SUCCESS) ? unlock_status : status; } psa_status_t psa_asymmetric_decrypt(mbedtls_svc_key_id_t key, psa_algorithm_t alg, - const uint8_t *input, + const uint8_t *input_external, size_t input_length, - const uint8_t *salt, + const uint8_t *salt_external, size_t salt_length, - uint8_t *output, + uint8_t *output_external, size_t output_size, size_t *output_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_slot_t *slot; + LOCAL_INPUT_DECLARE(input_external, input); + LOCAL_INPUT_DECLARE(salt_external, salt); + LOCAL_OUTPUT_DECLARE(output_external, output); (void) input; (void) input_length; @@ -3229,7 +3509,9 @@ psa_status_t psa_asymmetric_decrypt(mbedtls_svc_key_id_t key, } #endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) */ - + LOCAL_INPUT_ALLOC(input_external, input_length, input); + LOCAL_INPUT_ALLOC(salt_external, salt_length, salt); + LOCAL_OUTPUT_ALLOC(output_external, output_size, output); if (alg == PSA_ALG_RSA_PKCS1V15_CRYPT) { #if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) status = mbedtls_to_psa_error( @@ -3279,9 +3561,59 @@ psa_status_t psa_asymmetric_decrypt(mbedtls_svc_key_id_t key, exit: unlock_status = psa_unlock_key_slot(slot); + LOCAL_INPUT_FREE(input_external, input); + LOCAL_INPUT_FREE(salt_external, salt); + LOCAL_OUTPUT_FREE(output_external, output); + return (status == PSA_SUCCESS) ? unlock_status : status; } +static psa_status_t psa_generate_random_internal(uint8_t *output, + size_t output_size) +{ + GUARD_MODULE_INITIALIZED; + + psa_status_t status; + +#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) + + size_t output_length = 0; + status = mbedtls_psa_external_get_random(&global_data.rng, + output, output_size, + &output_length); + if (status != PSA_SUCCESS) { + goto exit; + } + /* Breaking up a request into smaller chunks is currently not supported + * for the external RNG interface. */ + if (output_length != output_size) { + status = PSA_ERROR_INSUFFICIENT_ENTROPY; + goto exit; + } + status = PSA_SUCCESS; + +#else /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ + + while (output_size > 0) { + size_t request_size = + (output_size > MBEDTLS_PSA_RANDOM_MAX_REQUEST ? + MBEDTLS_PSA_RANDOM_MAX_REQUEST : + output_size); + int ret = mbedtls_psa_get_random(MBEDTLS_PSA_RANDOM_STATE, + output, request_size); + if (ret != 0) { + status = mbedtls_to_psa_error(ret); + goto exit; + } + output_size -= request_size; + output += request_size; + } + status = PSA_SUCCESS; +#endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ + +exit: + return status; +} /****************************************************************/ @@ -3375,14 +3707,15 @@ psa_status_t psa_cipher_decrypt_setup(psa_cipher_operation_t *operation, } psa_status_t psa_cipher_generate_iv(psa_cipher_operation_t *operation, - uint8_t *iv, + uint8_t *iv_external, size_t iv_size, size_t *iv_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; - uint8_t local_iv[PSA_CIPHER_IV_MAX_SIZE]; size_t default_iv_length = 0; + LOCAL_OUTPUT_DECLARE(iv_external, iv); + if (operation->id == 0) { status = PSA_ERROR_BAD_STATE; goto exit; @@ -3404,33 +3737,40 @@ psa_status_t psa_cipher_generate_iv(psa_cipher_operation_t *operation, goto exit; } - status = psa_generate_random(local_iv, default_iv_length); + LOCAL_OUTPUT_ALLOC(iv_external, default_iv_length, iv); + + status = psa_generate_random_internal(iv, default_iv_length); if (status != PSA_SUCCESS) { goto exit; } status = psa_driver_wrapper_cipher_set_iv(operation, - local_iv, default_iv_length); + iv, default_iv_length); exit: if (status == PSA_SUCCESS) { - memcpy(iv, local_iv, default_iv_length); *iv_length = default_iv_length; operation->iv_set = 1; } else { *iv_length = 0; psa_cipher_abort(operation); + if (iv != NULL) { + mbedtls_platform_zeroize(iv, default_iv_length); + } } + LOCAL_OUTPUT_FREE(iv_external, iv); return status; } psa_status_t psa_cipher_set_iv(psa_cipher_operation_t *operation, - const uint8_t *iv, + const uint8_t *iv_external, size_t iv_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + LOCAL_INPUT_DECLARE(iv_external, iv); + if (operation->id == 0) { status = PSA_ERROR_BAD_STATE; goto exit; @@ -3446,6 +3786,8 @@ psa_status_t psa_cipher_set_iv(psa_cipher_operation_t *operation, goto exit; } + LOCAL_INPUT_ALLOC(iv_external, iv_length, iv); + status = psa_driver_wrapper_cipher_set_iv(operation, iv, iv_length); @@ -3456,18 +3798,24 @@ psa_status_t psa_cipher_set_iv(psa_cipher_operation_t *operation, } else { psa_cipher_abort(operation); } + + LOCAL_INPUT_FREE(iv_external, iv); + return status; } psa_status_t psa_cipher_update(psa_cipher_operation_t *operation, - const uint8_t *input, + const uint8_t *input_external, size_t input_length, - uint8_t *output, + uint8_t *output_external, size_t output_size, size_t *output_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + LOCAL_INPUT_DECLARE(input_external, input); + LOCAL_OUTPUT_DECLARE(output_external, output); + if (operation->id == 0) { status = PSA_ERROR_BAD_STATE; goto exit; @@ -3478,6 +3826,9 @@ psa_status_t psa_cipher_update(psa_cipher_operation_t *operation, goto exit; } + LOCAL_INPUT_ALLOC(input_external, input_length, input); + LOCAL_OUTPUT_ALLOC(output_external, output_size, output); + status = psa_driver_wrapper_cipher_update(operation, input, input_length, @@ -3490,16 +3841,21 @@ psa_status_t psa_cipher_update(psa_cipher_operation_t *operation, psa_cipher_abort(operation); } + LOCAL_INPUT_FREE(input_external, input); + LOCAL_OUTPUT_FREE(output_external, output); + return status; } psa_status_t psa_cipher_finish(psa_cipher_operation_t *operation, - uint8_t *output, + uint8_t *output_external, size_t output_size, size_t *output_length) { psa_status_t status = PSA_ERROR_GENERIC_ERROR; + LOCAL_OUTPUT_DECLARE(output_external, output); + if (operation->id == 0) { status = PSA_ERROR_BAD_STATE; goto exit; @@ -3510,6 +3866,8 @@ psa_status_t psa_cipher_finish(psa_cipher_operation_t *operation, goto exit; } + LOCAL_OUTPUT_ALLOC(output_external, output_size, output); + status = psa_driver_wrapper_cipher_finish(operation, output, output_size, @@ -3517,13 +3875,15 @@ psa_status_t psa_cipher_finish(psa_cipher_operation_t *operation, exit: if (status == PSA_SUCCESS) { - return psa_cipher_abort(operation); + status = psa_cipher_abort(operation); } else { *output_length = 0; (void) psa_cipher_abort(operation); - - return status; } + + LOCAL_OUTPUT_FREE(output_external, output); + + return status; } psa_status_t psa_cipher_abort(psa_cipher_operation_t *operation) @@ -3546,9 +3906,9 @@ psa_status_t psa_cipher_abort(psa_cipher_operation_t *operation) psa_status_t psa_cipher_encrypt(mbedtls_svc_key_id_t key, psa_algorithm_t alg, - const uint8_t *input, + const uint8_t *input_external, size_t input_length, - uint8_t *output, + uint8_t *output_external, size_t output_size, size_t *output_length) { @@ -3559,6 +3919,9 @@ psa_status_t psa_cipher_encrypt(mbedtls_svc_key_id_t key, uint8_t local_iv[PSA_CIPHER_IV_MAX_SIZE]; size_t default_iv_length = 0; + LOCAL_INPUT_DECLARE(input_external, input); + LOCAL_OUTPUT_DECLARE(output_external, output); + if (!PSA_ALG_IS_CIPHER(alg)) { status = PSA_ERROR_INVALID_ARGUMENT; goto exit; @@ -3587,12 +3950,15 @@ psa_status_t psa_cipher_encrypt(mbedtls_svc_key_id_t key, goto exit; } - status = psa_generate_random(local_iv, default_iv_length); + status = psa_generate_random_internal(local_iv, default_iv_length); if (status != PSA_SUCCESS) { goto exit; } } + LOCAL_INPUT_ALLOC(input_external, input_length, input); + LOCAL_OUTPUT_ALLOC(output_external, output_size, output); + status = psa_driver_wrapper_cipher_encrypt( &attributes, slot->key.data, slot->key.bytes, alg, local_iv, default_iv_length, input, input_length, @@ -3614,14 +3980,17 @@ psa_status_t psa_cipher_encrypt(mbedtls_svc_key_id_t key, *output_length = 0; } + LOCAL_INPUT_FREE(input_external, input); + LOCAL_OUTPUT_FREE(output_external, output); + return status; } psa_status_t psa_cipher_decrypt(mbedtls_svc_key_id_t key, psa_algorithm_t alg, - const uint8_t *input, + const uint8_t *input_external, size_t input_length, - uint8_t *output, + uint8_t *output_external, size_t output_size, size_t *output_length) { @@ -3630,6 +3999,9 @@ psa_status_t psa_cipher_decrypt(mbedtls_svc_key_id_t key, psa_key_attributes_t attributes; psa_key_slot_t *slot = NULL; + LOCAL_INPUT_DECLARE(input_external, input); + LOCAL_OUTPUT_DECLARE(output_external, output); + if (!PSA_ALG_IS_CIPHER(alg)) { status = PSA_ERROR_INVALID_ARGUMENT; goto exit; @@ -3651,6 +4023,9 @@ psa_status_t psa_cipher_decrypt(mbedtls_svc_key_id_t key, goto exit; } + LOCAL_INPUT_ALLOC(input_external, input_length, input); + LOCAL_OUTPUT_ALLOC(output_external, output_size, output); + status = psa_driver_wrapper_cipher_decrypt( &attributes, slot->key.data, slot->key.bytes, alg, input, input_length, @@ -3666,6 +4041,9 @@ psa_status_t psa_cipher_decrypt(mbedtls_svc_key_id_t key, *output_length = 0; } + LOCAL_INPUT_FREE(input_external, input); + LOCAL_OUTPUT_FREE(output_external, output); + return status; } @@ -3676,19 +4054,24 @@ psa_status_t psa_cipher_decrypt(mbedtls_svc_key_id_t key, psa_status_t psa_aead_encrypt(mbedtls_svc_key_id_t key, psa_algorithm_t alg, - const uint8_t *nonce, + const uint8_t *nonce_external, size_t nonce_length, - const uint8_t *additional_data, + const uint8_t *additional_data_external, size_t additional_data_length, - const uint8_t *plaintext, + const uint8_t *plaintext_external, size_t plaintext_length, - uint8_t *ciphertext, + uint8_t *ciphertext_external, size_t ciphertext_size, size_t *ciphertext_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_slot_t *slot; + LOCAL_INPUT_DECLARE(nonce_external, nonce); + LOCAL_INPUT_DECLARE(additional_data_external, additional_data); + LOCAL_INPUT_DECLARE(plaintext_external, plaintext); + LOCAL_OUTPUT_DECLARE(ciphertext_external, ciphertext); + *ciphertext_length = 0; if (!PSA_ALG_IS_AEAD(alg) || PSA_ALG_IS_WILDCARD(alg)) { @@ -3705,6 +4088,11 @@ psa_status_t psa_aead_encrypt(mbedtls_svc_key_id_t key, .core = slot->attr }; + LOCAL_INPUT_ALLOC(nonce_external, nonce_length, nonce); + LOCAL_INPUT_ALLOC(additional_data_external, additional_data_length, additional_data); + LOCAL_INPUT_ALLOC(plaintext_external, plaintext_length, plaintext); + LOCAL_OUTPUT_ALLOC(ciphertext_external, ciphertext_size, ciphertext); + status = psa_driver_wrapper_aead_encrypt( &attributes, slot->key.data, slot->key.bytes, alg, @@ -3717,6 +4105,15 @@ psa_status_t psa_aead_encrypt(mbedtls_svc_key_id_t key, memset(ciphertext, 0, ciphertext_size); } +/* Exit label is only used for buffer copying, prevent unused warnings. */ +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) +exit: +#endif + LOCAL_INPUT_FREE(nonce_external, nonce); + LOCAL_INPUT_FREE(additional_data_external, additional_data); + LOCAL_INPUT_FREE(plaintext_external, plaintext); + LOCAL_OUTPUT_FREE(ciphertext_external, ciphertext); + psa_unlock_key_slot(slot); return status; @@ -3724,19 +4121,24 @@ psa_status_t psa_aead_encrypt(mbedtls_svc_key_id_t key, psa_status_t psa_aead_decrypt(mbedtls_svc_key_id_t key, psa_algorithm_t alg, - const uint8_t *nonce, + const uint8_t *nonce_external, size_t nonce_length, - const uint8_t *additional_data, + const uint8_t *additional_data_external, size_t additional_data_length, - const uint8_t *ciphertext, + const uint8_t *ciphertext_external, size_t ciphertext_length, - uint8_t *plaintext, + uint8_t *plaintext_external, size_t plaintext_size, size_t *plaintext_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_slot_t *slot; + LOCAL_INPUT_DECLARE(nonce_external, nonce); + LOCAL_INPUT_DECLARE(additional_data_external, additional_data); + LOCAL_INPUT_DECLARE(ciphertext_external, ciphertext); + LOCAL_OUTPUT_DECLARE(plaintext_external, plaintext); + *plaintext_length = 0; if (!PSA_ALG_IS_AEAD(alg) || PSA_ALG_IS_WILDCARD(alg)) { @@ -3753,6 +4155,12 @@ psa_status_t psa_aead_decrypt(mbedtls_svc_key_id_t key, .core = slot->attr }; + LOCAL_INPUT_ALLOC(nonce_external, nonce_length, nonce); + LOCAL_INPUT_ALLOC(additional_data_external, additional_data_length, + additional_data); + LOCAL_INPUT_ALLOC(ciphertext_external, ciphertext_length, ciphertext); + LOCAL_OUTPUT_ALLOC(plaintext_external, plaintext_size, plaintext); + status = psa_driver_wrapper_aead_decrypt( &attributes, slot->key.data, slot->key.bytes, alg, @@ -3765,6 +4173,15 @@ psa_status_t psa_aead_decrypt(mbedtls_svc_key_id_t key, memset(plaintext, 0, plaintext_size); } +/* Exit label is only used for buffer copying, prevent unused warnings. */ +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) +exit: +#endif + LOCAL_INPUT_FREE(nonce_external, nonce); + LOCAL_INPUT_FREE(additional_data_external, additional_data); + LOCAL_INPUT_FREE(ciphertext_external, ciphertext); + LOCAL_OUTPUT_FREE(plaintext_external, plaintext); + psa_unlock_key_slot(slot); return status; @@ -4158,10 +4575,12 @@ static psa_status_t psa_key_derivation_tls12_prf_read( psa_status_t psa_key_derivation_output_bytes( psa_key_derivation_operation_t *operation, - uint8_t *output, + uint8_t *output_external, size_t output_length) { psa_status_t status; + LOCAL_OUTPUT_DECLARE(output_external, output); + psa_algorithm_t kdf_alg = psa_key_derivation_get_kdf_alg(operation); if (operation->alg == 0) { @@ -4169,13 +4588,6 @@ psa_status_t psa_key_derivation_output_bytes( return PSA_ERROR_BAD_STATE; } - if (output_length > operation->capacity) { - operation->capacity = 0; - /* Go through the error path to wipe all confidential data now - * that the operation object is useless. */ - status = PSA_ERROR_INSUFFICIENT_DATA; - goto exit; - } if (output_length == 0 && operation->capacity == 0) { /* Edge case: this is a finished operation, and 0 bytes * were requested. The right error in this case could @@ -4185,6 +4597,15 @@ psa_status_t psa_key_derivation_output_bytes( * output_length > 0. */ return PSA_ERROR_INSUFFICIENT_DATA; } + + LOCAL_OUTPUT_ALLOC(output_external, output_length, output); + if (output_length > operation->capacity) { + operation->capacity = 0; + /* Go through the error path to wipe all confidential data now + * that the operation object is useless. */ + status = PSA_ERROR_INSUFFICIENT_DATA; + goto exit; + } operation->capacity -= output_length; #if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF) @@ -4206,7 +4627,10 @@ psa_status_t psa_key_derivation_output_bytes( * MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS */ { (void) kdf_alg; - return PSA_ERROR_BAD_STATE; + status = PSA_ERROR_BAD_STATE; + LOCAL_OUTPUT_FREE(output_external, output); + + return status; } exit: @@ -4218,8 +4642,12 @@ psa_status_t psa_key_derivation_output_bytes( psa_algorithm_t alg = operation->alg; psa_key_derivation_abort(operation); operation->alg = alg; - memset(output, '!', output_length); + if (output != NULL) { + memset(output, '!', output_length); + } } + + LOCAL_OUTPUT_FREE(output_external, output); return status; } @@ -4793,12 +5221,22 @@ static psa_status_t psa_key_derivation_input_internal( psa_status_t psa_key_derivation_input_bytes( psa_key_derivation_operation_t *operation, psa_key_derivation_step_t step, - const uint8_t *data, + const uint8_t *data_external, size_t data_length) { - return psa_key_derivation_input_internal(operation, step, - PSA_KEY_TYPE_NONE, - data, data_length); + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + LOCAL_INPUT_DECLARE(data_external, data); + + LOCAL_INPUT_ALLOC(data_external, data_length, data); + + status = psa_key_derivation_input_internal(operation, step, + PSA_KEY_TYPE_NONE, + data, data_length); +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) +exit: +#endif + LOCAL_INPUT_FREE(data_external, data); + return status; } psa_status_t psa_key_derivation_input_key( @@ -4990,12 +5428,13 @@ static psa_status_t psa_key_agreement_internal(psa_key_derivation_operation_t *o psa_status_t psa_key_derivation_key_agreement(psa_key_derivation_operation_t *operation, psa_key_derivation_step_t step, mbedtls_svc_key_id_t private_key, - const uint8_t *peer_key, + const uint8_t *peer_key_external, size_t peer_key_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_slot_t *slot; + LOCAL_INPUT_DECLARE(peer_key_external, peer_key); if (!PSA_ALG_IS_KEY_AGREEMENT(operation->alg)) { return PSA_ERROR_INVALID_ARGUMENT; @@ -5005,9 +5444,15 @@ psa_status_t psa_key_derivation_key_agreement(psa_key_derivation_operation_t *op if (status != PSA_SUCCESS) { return status; } + + LOCAL_INPUT_ALLOC(peer_key_external, peer_key_length, peer_key); status = psa_key_agreement_internal(operation, step, slot, peer_key, peer_key_length); + +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) +exit: +#endif if (status != PSA_SUCCESS) { psa_key_derivation_abort(operation); } else { @@ -5020,14 +5465,15 @@ psa_status_t psa_key_derivation_key_agreement(psa_key_derivation_operation_t *op unlock_status = psa_unlock_key_slot(slot); + LOCAL_INPUT_FREE(peer_key_external, peer_key); return (status == PSA_SUCCESS) ? unlock_status : status; } psa_status_t psa_raw_key_agreement(psa_algorithm_t alg, mbedtls_svc_key_id_t private_key, - const uint8_t *peer_key, + const uint8_t *peer_key_external, size_t peer_key_length, - uint8_t *output, + uint8_t *output_external, size_t output_size, size_t *output_length) { @@ -5035,6 +5481,9 @@ psa_status_t psa_raw_key_agreement(psa_algorithm_t alg, psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_slot_t *slot = NULL; size_t expected_length; + LOCAL_INPUT_DECLARE(peer_key_external, peer_key); + LOCAL_OUTPUT_DECLARE(output_external, output); + LOCAL_OUTPUT_ALLOC(output_external, output_size, output); if (!PSA_ALG_IS_KEY_AGREEMENT(alg)) { status = PSA_ERROR_INVALID_ARGUMENT; @@ -5061,13 +5510,16 @@ psa_status_t psa_raw_key_agreement(psa_algorithm_t alg, goto exit; } + LOCAL_INPUT_ALLOC(peer_key_external, peer_key_length, peer_key); status = psa_key_agreement_raw_internal(alg, slot, peer_key, peer_key_length, output, output_size, output_length); exit: - if (status != PSA_SUCCESS) { + /* Check for successful allocation of output, + * with an unsuccessful status. */ + if (output != NULL && status != PSA_SUCCESS) { /* If an error happens and is not handled properly, the output * may be used as a key to protect sensitive data. Arrange for such * a key to be random, which is likely to result in decryption or @@ -5075,17 +5527,23 @@ psa_status_t psa_raw_key_agreement(psa_algorithm_t alg, * some constant data such as zeros, which would result in the data * being protected with a reproducible, easily knowable key. */ - psa_generate_random(output, output_size); + psa_generate_random_internal(output, output_size); *output_length = output_size; } + if (output == NULL) { + /* output allocation failed. */ + *output_length = 0; + } + unlock_status = psa_unlock_key_slot(slot); + LOCAL_INPUT_FREE(peer_key_external, peer_key); + LOCAL_OUTPUT_FREE(output_external, output); return (status == PSA_SUCCESS) ? unlock_status : status; } - /****************************************************************/ /* Random generation */ /****************************************************************/ @@ -5154,44 +5612,21 @@ static psa_status_t mbedtls_psa_random_seed(mbedtls_psa_random_context_t *rng) #endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ } -psa_status_t psa_generate_random(uint8_t *output, +psa_status_t psa_generate_random(uint8_t *output_external, size_t output_size) { - GUARD_MODULE_INITIALIZED; - -#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) + psa_status_t status; - size_t output_length = 0; - psa_status_t status = mbedtls_psa_external_get_random(&global_data.rng, - output, output_size, - &output_length); - if (status != PSA_SUCCESS) { - return status; - } - /* Breaking up a request into smaller chunks is currently not supported - * for the external RNG interface. */ - if (output_length != output_size) { - return PSA_ERROR_INSUFFICIENT_ENTROPY; - } - return PSA_SUCCESS; + LOCAL_OUTPUT_DECLARE(output_external, output); + LOCAL_OUTPUT_ALLOC(output_external, output_size, output); -#else /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ + status = psa_generate_random_internal(output, output_size); - while (output_size > 0) { - size_t request_size = - (output_size > MBEDTLS_PSA_RANDOM_MAX_REQUEST ? - MBEDTLS_PSA_RANDOM_MAX_REQUEST : - output_size); - int ret = mbedtls_psa_get_random(MBEDTLS_PSA_RANDOM_STATE, - output, request_size); - if (ret != 0) { - return mbedtls_to_psa_error(ret); - } - output_size -= request_size; - output += request_size; - } - return PSA_SUCCESS; -#endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) +exit: +#endif + LOCAL_OUTPUT_FREE(output_external, output); + return status; } /* Wrapper function allowing the classic API to use the PSA RNG. @@ -5534,4 +5969,182 @@ psa_status_t psa_crypto_init(void) return status; } +/* Memory copying test hooks. These are called before input copy, after input + * copy, before output copy and after output copy, respectively. + * They are used by memory-poisoning tests to temporarily unpoison buffers + * while they are copied. */ +#if defined(MBEDTLS_TEST_HOOKS) +void (*psa_input_pre_copy_hook)(const uint8_t *input, size_t input_len) = NULL; +void (*psa_input_post_copy_hook)(const uint8_t *input, size_t input_len) = NULL; +void (*psa_output_pre_copy_hook)(const uint8_t *output, size_t output_len) = NULL; +void (*psa_output_post_copy_hook)(const uint8_t *output, size_t output_len) = NULL; +#endif + +/** Copy from an input buffer to a local copy. + * + * \param[in] input Pointer to input buffer. + * \param[in] input_len Length of the input buffer. + * \param[out] input_copy Pointer to a local copy in which to store the input data. + * \param[out] input_copy_len Length of the local copy buffer. + * \return #PSA_SUCCESS, if the buffer was successfully + * copied. + * \return #PSA_ERROR_CORRUPTION_DETECTED, if the local + * copy is too small to hold contents of the + * input buffer. + */ +MBEDTLS_STATIC_TESTABLE +psa_status_t psa_crypto_copy_input(const uint8_t *input, size_t input_len, + uint8_t *input_copy, size_t input_copy_len) +{ + if (input_len > input_copy_len) { + return PSA_ERROR_CORRUPTION_DETECTED; + } + +#if defined(MBEDTLS_TEST_HOOKS) + if (psa_input_pre_copy_hook != NULL) { + psa_input_pre_copy_hook(input, input_len); + } +#endif + + if (input_len > 0) { + memcpy(input_copy, input, input_len); + } + +#if defined(MBEDTLS_TEST_HOOKS) + if (psa_input_post_copy_hook != NULL) { + psa_input_post_copy_hook(input, input_len); + } +#endif + + return PSA_SUCCESS; +} + +/** Copy from a local output buffer into a user-supplied one. + * + * \param[in] output_copy Pointer to a local buffer containing the output. + * \param[in] output_copy_len Length of the local buffer. + * \param[out] output Pointer to user-supplied output buffer. + * \param[out] output_len Length of the user-supplied output buffer. + * \return #PSA_SUCCESS, if the buffer was successfully + * copied. + * \return #PSA_ERROR_BUFFER_TOO_SMALL, if the + * user-supplied output buffer is too small to + * hold the contents of the local buffer. + */ +MBEDTLS_STATIC_TESTABLE +psa_status_t psa_crypto_copy_output(const uint8_t *output_copy, size_t output_copy_len, + uint8_t *output, size_t output_len) +{ + if (output_len < output_copy_len) { + return PSA_ERROR_BUFFER_TOO_SMALL; + } + +#if defined(MBEDTLS_TEST_HOOKS) + if (psa_output_pre_copy_hook != NULL) { + psa_output_pre_copy_hook(output, output_len); + } +#endif + + if (output_copy_len > 0) { + memcpy(output, output_copy, output_copy_len); + } + +#if defined(MBEDTLS_TEST_HOOKS) + if (psa_output_post_copy_hook != NULL) { + psa_output_post_copy_hook(output, output_len); + } +#endif + + return PSA_SUCCESS; +} + +psa_status_t psa_crypto_local_input_alloc(const uint8_t *input, size_t input_len, + psa_crypto_local_input_t *local_input) +{ + psa_status_t status; + + *local_input = PSA_CRYPTO_LOCAL_INPUT_INIT; + + if (input_len == 0) { + return PSA_SUCCESS; + } + + local_input->buffer = mbedtls_calloc(input_len, 1); + if (local_input->buffer == NULL) { + /* Since we dealt with the zero-length case above, we know that + * a NULL return value means a failure of allocation. */ + return PSA_ERROR_INSUFFICIENT_MEMORY; + } + /* From now on, we must free local_input->buffer on error. */ + + local_input->length = input_len; + + status = psa_crypto_copy_input(input, input_len, + local_input->buffer, local_input->length); + if (status != PSA_SUCCESS) { + goto error; + } + + return PSA_SUCCESS; + +error: + mbedtls_free(local_input->buffer); + local_input->buffer = NULL; + local_input->length = 0; + return status; +} + +void psa_crypto_local_input_free(psa_crypto_local_input_t *local_input) +{ + mbedtls_free(local_input->buffer); + local_input->buffer = NULL; + local_input->length = 0; +} + +psa_status_t psa_crypto_local_output_alloc(uint8_t *output, size_t output_len, + psa_crypto_local_output_t *local_output) +{ + *local_output = PSA_CRYPTO_LOCAL_OUTPUT_INIT; + + if (output_len == 0) { + return PSA_SUCCESS; + } + local_output->buffer = mbedtls_calloc(output_len, 1); + if (local_output->buffer == NULL) { + /* Since we dealt with the zero-length case above, we know that + * a NULL return value means a failure of allocation. */ + return PSA_ERROR_INSUFFICIENT_MEMORY; + } + local_output->length = output_len; + local_output->original = output; + + return PSA_SUCCESS; +} + +psa_status_t psa_crypto_local_output_free(psa_crypto_local_output_t *local_output) +{ + psa_status_t status; + + if (local_output->buffer == NULL) { + local_output->length = 0; + return PSA_SUCCESS; + } + if (local_output->original == NULL) { + /* We have an internal copy but nothing to copy back to. */ + return PSA_ERROR_CORRUPTION_DETECTED; + } + + status = psa_crypto_copy_output(local_output->buffer, local_output->length, + local_output->original, local_output->length); + if (status != PSA_SUCCESS) { + return status; + } + + mbedtls_free(local_output->buffer); + local_output->buffer = NULL; + local_output->length = 0; + + return PSA_SUCCESS; +} + #endif /* MBEDTLS_PSA_CRYPTO_C */ diff --git a/library/psa_crypto_cipher.c b/library/psa_crypto_cipher.c index 545bb50cc879..93a6b93f1cba 100644 --- a/library/psa_crypto_cipher.c +++ b/library/psa_crypto_cipher.c @@ -402,7 +402,11 @@ psa_status_t mbedtls_psa_cipher_update( output_length); } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING */ - { + if (input_length == 0) { + /* There is no input, nothing to be done */ + *output_length = 0; + status = PSA_SUCCESS; + } else { status = mbedtls_to_psa_error( mbedtls_cipher_update(&operation->ctx.cipher, input, input_length, output, output_length)); diff --git a/library/psa_crypto_core.h b/library/psa_crypto_core.h index 6bcd78fe08bc..4731064f85f3 100644 --- a/library/psa_crypto_core.h +++ b/library/psa_crypto_core.h @@ -503,4 +503,74 @@ psa_status_t psa_verify_hash_builtin( psa_algorithm_t alg, const uint8_t *hash, size_t hash_length, const uint8_t *signature, size_t signature_length); +typedef struct psa_crypto_local_input_s { + uint8_t *buffer; + size_t length; +} psa_crypto_local_input_t; + +#define PSA_CRYPTO_LOCAL_INPUT_INIT ((psa_crypto_local_input_t) { NULL, 0 }) + +/** Allocate a local copy of an input buffer and copy the contents into it. + * + * \param[in] input Pointer to input buffer. + * \param[in] input_len Length of the input buffer. + * \param[out] local_input Pointer to a psa_crypto_local_input_t struct + * containing a local input copy. + * \return #PSA_SUCCESS, if the buffer was successfully + * copied. + * \return #PSA_ERROR_INSUFFICIENT_MEMORY, if a copy of + * the buffer cannot be allocated. + */ +psa_status_t psa_crypto_local_input_alloc(const uint8_t *input, size_t input_len, + psa_crypto_local_input_t *local_input); + +/** Free a local copy of an input buffer. + * + * \param[in] local_input Pointer to a psa_crypto_local_input_t struct + * populated by a previous call to + * psa_crypto_local_input_alloc(). + */ +void psa_crypto_local_input_free(psa_crypto_local_input_t *local_input); + +typedef struct psa_crypto_local_output_s { + uint8_t *original; + uint8_t *buffer; + size_t length; +} psa_crypto_local_output_t; + +#define PSA_CRYPTO_LOCAL_OUTPUT_INIT ((psa_crypto_local_output_t) { NULL, NULL, 0 }) + +/** Allocate a local copy of an output buffer. + * + * \note This does not copy any data from the original + * output buffer but only allocates a buffer + * whose contents will be copied back to the + * original in a future call to + * psa_crypto_local_output_free(). + * + * \param[in] output Pointer to output buffer. + * \param[in] output_len Length of the output buffer. + * \param[out] local_output Pointer to a psa_crypto_local_output_t struct to + * populate with the local output copy. + * \return #PSA_SUCCESS, if the buffer was successfully + * copied. + * \return #PSA_ERROR_INSUFFICIENT_MEMORY, if a copy of + * the buffer cannot be allocated. + */ +psa_status_t psa_crypto_local_output_alloc(uint8_t *output, size_t output_len, + psa_crypto_local_output_t *local_output); + +/** Copy from a local copy of an output buffer back to the original, then + * free the local copy. + * + * \param[in] local_output Pointer to a psa_crypto_local_output_t struct + * populated by a previous call to + * psa_crypto_local_output_alloc(). + * \return #PSA_SUCCESS, if the local output was + * successfully copied back to the original. + * \return #PSA_ERROR_CORRUPTION_DETECTED, if the output + * could not be copied back to the original. + */ +psa_status_t psa_crypto_local_output_free(psa_crypto_local_output_t *local_output); + #endif /* PSA_CRYPTO_CORE_H */ diff --git a/library/psa_crypto_invasive.h b/library/psa_crypto_invasive.h index c70d896479ab..a1281d14fd75 100644 --- a/library/psa_crypto_invasive.h +++ b/library/psa_crypto_invasive.h @@ -69,6 +69,21 @@ psa_status_t mbedtls_psa_crypto_configure_entropy_sources( psa_status_t psa_mac_key_can_do( psa_algorithm_t algorithm, psa_key_type_t key_type); + +psa_status_t psa_crypto_copy_input(const uint8_t *input, size_t input_len, + uint8_t *input_copy, size_t input_copy_len); + +psa_status_t psa_crypto_copy_output(const uint8_t *output_copy, size_t output_copy_len, + uint8_t *output, size_t output_len); + +/* + * Test hooks to use for memory unpoisoning/poisoning in copy functions. + */ +extern void (*psa_input_pre_copy_hook)(const uint8_t *input, size_t input_len); +extern void (*psa_input_post_copy_hook)(const uint8_t *input, size_t input_len); +extern void (*psa_output_pre_copy_hook)(const uint8_t *output, size_t output_len); +extern void (*psa_output_post_copy_hook)(const uint8_t *output, size_t output_len); + #endif /* MBEDTLS_TEST_HOOKS && MBEDTLS_PSA_CRYPTO_C */ #endif /* PSA_CRYPTO_INVASIVE_H */ diff --git a/library/version_features.c b/library/version_features.c index 779325744b1b..6f663b12a730 100644 --- a/library/version_features.c +++ b/library/version_features.c @@ -456,6 +456,9 @@ static const char * const features[] = { #if defined(MBEDTLS_PSA_INJECT_ENTROPY) "MBEDTLS_PSA_INJECT_ENTROPY", #endif /* MBEDTLS_PSA_INJECT_ENTROPY */ +#if defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) + "MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS", +#endif /* MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS */ #if defined(MBEDTLS_RSA_NO_CRT) "MBEDTLS_RSA_NO_CRT", #endif /* MBEDTLS_RSA_NO_CRT */ diff --git a/pkgconfig/CMakeLists.txt b/pkgconfig/CMakeLists.txt index 6def088d2e83..40ef9fd1582a 100644 --- a/pkgconfig/CMakeLists.txt +++ b/pkgconfig/CMakeLists.txt @@ -9,7 +9,7 @@ if(NOT DISABLE_PACKAGE_CONFIG_AND_INSTALL) set(PKGCONFIG_PROJECT_HOMEPAGE_URL "https://www.trustedfirmware.org/projects/mbed-tls/") # Following the conventsion for DESCRIPTION and HOMEPAGE_URL, VERSION wasn't added until 3.0 and depends on policy CMP0048 - set(PKGCONFIG_VERSION 2.28.7) + set(PKGCONFIG_VERSION 2.28.8) configure_file(mbedcrypto.pc.in mbedcrypto.pc @ONLY) install(FILES diff --git a/programs/Makefile b/programs/Makefile index 2d32e0028830..255bd837dadd 100644 --- a/programs/Makefile +++ b/programs/Makefile @@ -27,6 +27,10 @@ endif include ../3rdparty/Makefile.inc LOCAL_CFLAGS+=$(THIRDPARTY_INCLUDES) +ifdef RECORD_PSA_STATUS_COVERAGE_LOG +LOCAL_CFLAGS += -Werror -DRECORD_PSA_STATUS_COVERAGE_LOG +endif + ifndef SHARED MBEDLIBS=../library/libmbedcrypto.a ../library/libmbedx509.a ../library/libmbedtls.a else diff --git a/programs/test/metatest.c b/programs/test/metatest.c index acc6865baf0e..21120048f25b 100644 --- a/programs/test/metatest.c +++ b/programs/test/metatest.c @@ -28,10 +28,12 @@ #define MBEDTLS_ALLOW_PRIVATE_ACCESS +#include #include #include #include "test/helpers.h" #include "test/macros.h" +#include "test/memory.h" #include #include @@ -40,6 +42,11 @@ #include #endif +/* C99 feature missing from older versions of MSVC */ +#if (defined(_MSC_VER) && (_MSC_VER <= 1900)) +#define /*no-check-names*/ __func__ __FUNCTION__ +#endif + /* This is an external variable, so the compiler doesn't know that we're never * changing its value. @@ -59,6 +66,15 @@ static void set_to_zero_but_the_compiler_does_not_know(volatile void *p, size_t memset((void *) p, false_but_the_compiler_does_not_know, n); } +/* Simulate an access to the given object, to avoid compiler optimizations + * in code that prepares or consumes the object. */ +static void do_nothing_with_object(void *p) +{ + (void) p; +} +void(*volatile do_nothing_with_object_but_the_compiler_does_not_know)(void *) = + do_nothing_with_object; + /****************************************************************/ /* Test framework features */ @@ -178,6 +194,65 @@ void memory_leak(const char *name) /* Leak of a heap object */ } +/* name = "test_memory_poison_%(start)_%(offset)_%(count)_%(direction)" + * Poison a region starting at start from an 8-byte aligned origin, + * encompassing count bytes. Access the region at offset from the start. + * %(start), %(offset) and %(count) are decimal integers. + * %(direction) is either the character 'r' for read or 'w' for write. + */ +void test_memory_poison(const char *name) +{ + size_t start = 0, offset = 0, count = 0; + char direction = 'r'; + if (sscanf(name, + "%*[^0-9]%" MBEDTLS_PRINTF_SIZET + "%*[^0-9]%" MBEDTLS_PRINTF_SIZET + "%*[^0-9]%" MBEDTLS_PRINTF_SIZET + "_%c", + &start, &offset, &count, &direction) != 4) { + mbedtls_fprintf(stderr, "%s: Bad name format: %s\n", __func__, name); + return; + } + + union { + long long ll; + unsigned char buf[32]; + } aligned; + memset(aligned.buf, 'a', sizeof(aligned.buf)); + + if (start > sizeof(aligned.buf)) { + mbedtls_fprintf(stderr, + "%s: start=%" MBEDTLS_PRINTF_SIZET + " > size=%" MBEDTLS_PRINTF_SIZET, + __func__, start, sizeof(aligned.buf)); + return; + } + if (start + count > sizeof(aligned.buf)) { + mbedtls_fprintf(stderr, + "%s: start+count=%" MBEDTLS_PRINTF_SIZET + " > size=%" MBEDTLS_PRINTF_SIZET, + __func__, start + count, sizeof(aligned.buf)); + return; + } + if (offset >= count) { + mbedtls_fprintf(stderr, + "%s: offset=%" MBEDTLS_PRINTF_SIZET + " >= count=%" MBEDTLS_PRINTF_SIZET, + __func__, offset, count); + return; + } + + MBEDTLS_TEST_MEMORY_POISON(aligned.buf + start, count); + + if (direction == 'w') { + aligned.buf[start + offset] = 'b'; + do_nothing_with_object_but_the_compiler_does_not_know(aligned.buf); + } else { + do_nothing_with_object_but_the_compiler_does_not_know(aligned.buf); + mbedtls_printf("%u\n", (unsigned) aligned.buf[start + offset]); + } +} + /****************************************************************/ /* Threading */ @@ -329,6 +404,22 @@ metatest_t metatests[] = { { "double_free", "asan", double_free }, { "read_uninitialized_stack", "msan", read_uninitialized_stack }, { "memory_leak", "asan", memory_leak }, + { "test_memory_poison_0_0_8_r", "poison", test_memory_poison }, + { "test_memory_poison_0_0_8_w", "poison", test_memory_poison }, + { "test_memory_poison_0_7_8_r", "poison", test_memory_poison }, + { "test_memory_poison_0_7_8_w", "poison", test_memory_poison }, + { "test_memory_poison_0_0_1_r", "poison", test_memory_poison }, + { "test_memory_poison_0_0_1_w", "poison", test_memory_poison }, + { "test_memory_poison_0_1_2_r", "poison", test_memory_poison }, + { "test_memory_poison_0_1_2_w", "poison", test_memory_poison }, + { "test_memory_poison_7_0_8_r", "poison", test_memory_poison }, + { "test_memory_poison_7_0_8_w", "poison", test_memory_poison }, + { "test_memory_poison_7_7_8_r", "poison", test_memory_poison }, + { "test_memory_poison_7_7_8_w", "poison", test_memory_poison }, + { "test_memory_poison_7_0_1_r", "poison", test_memory_poison }, + { "test_memory_poison_7_0_1_w", "poison", test_memory_poison }, + { "test_memory_poison_7_1_2_r", "poison", test_memory_poison }, + { "test_memory_poison_7_1_2_w", "poison", test_memory_poison }, { "mutex_lock_not_initialized", "pthread", mutex_lock_not_initialized }, { "mutex_unlock_not_initialized", "pthread", mutex_unlock_not_initialized }, { "mutex_free_not_initialized", "pthread", mutex_free_not_initialized }, diff --git a/programs/test/query_config.c b/programs/test/query_config.c index 859d824f84d5..5d9886bcd93b 100644 --- a/programs/test/query_config.c +++ b/programs/test/query_config.c @@ -1296,6 +1296,14 @@ int query_config(const char *config) } #endif /* MBEDTLS_PSA_INJECT_ENTROPY */ +#if defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) + if( strcmp( "MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS ); + return( 0 ); + } +#endif /* MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS */ + #if defined(MBEDTLS_RSA_NO_CRT) if( strcmp( "MBEDTLS_RSA_NO_CRT", config ) == 0 ) { @@ -3458,6 +3466,10 @@ void list_config(void) OUTPUT_MACRO_NAME_VALUE(MBEDTLS_PSA_INJECT_ENTROPY); #endif /* MBEDTLS_PSA_INJECT_ENTROPY */ +#if defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) + OUTPUT_MACRO_NAME_VALUE(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS); +#endif /* MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS */ + #if defined(MBEDTLS_RSA_NO_CRT) OUTPUT_MACRO_NAME_VALUE(MBEDTLS_RSA_NO_CRT); #endif /* MBEDTLS_RSA_NO_CRT */ diff --git a/scripts/config.py b/scripts/config.py index 604f8a847d41..22bdb5e6d94a 100755 --- a/scripts/config.py +++ b/scripts/config.py @@ -185,6 +185,7 @@ def realfull_adapter(_name, active, section): 'MBEDTLS_NO_UDBL_DIVISION', # influences anything that uses bignum 'MBEDTLS_PKCS11_C', # build dependency (libpkcs11-helper) 'MBEDTLS_PLATFORM_NO_STD_FUNCTIONS', # removes a feature + 'MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS', # removes a feature 'MBEDTLS_PSA_CRYPTO_CONFIG', # toggles old/new style PSA config 'MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG', # behavior change + build dependency 'MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER', # incompatible with USE_PSA_CRYPTO diff --git a/scripts/mbedtls_dev/c_parsing_helper.py b/scripts/mbedtls_dev/c_parsing_helper.py new file mode 100644 index 000000000000..2657b7d230dd --- /dev/null +++ b/scripts/mbedtls_dev/c_parsing_helper.py @@ -0,0 +1,131 @@ +"""Helper functions to parse C code in heavily constrained scenarios. + +Currently supported functionality: + +* read_function_declarations: read function declarations from a header file. +""" + +# Copyright The Mbed TLS Contributors +# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + +### WARNING: the code in this file has not been extensively reviewed yet. +### We do not think it is harmful, but it may be below our normal standards +### for robustness and maintainability. + +import re +from typing import Dict, Iterable, Iterator, List, Optional, Tuple + + +class ArgumentInfo: + """Information about an argument to an API function.""" + #pylint: disable=too-few-public-methods + + _KEYWORDS = [ + 'const', 'register', 'restrict', + 'int', 'long', 'short', 'signed', 'unsigned', + ] + _DECLARATION_RE = re.compile( + r'(?P\w[\w\s*]*?)\s*' + + r'(?!(?:' + r'|'.join(_KEYWORDS) + r'))(?P\b\w+\b)?' + + r'\s*(?P\[[^][]*\])?\Z', + re.A | re.S) + + @classmethod + def normalize_type(cls, typ: str) -> str: + """Normalize whitespace in a type.""" + typ = re.sub(r'\s+', r' ', typ) + typ = re.sub(r'\s*\*', r' *', typ) + return typ + + def __init__(self, decl: str) -> None: + self.decl = decl.strip() + m = self._DECLARATION_RE.match(self.decl) + if not m: + raise ValueError(self.decl) + self.type = self.normalize_type(m.group('type')) #type: str + self.name = m.group('name') #type: Optional[str] + self.suffix = m.group('suffix') if m.group('suffix') else '' #type: str + + +class FunctionInfo: + """Information about an API function.""" + #pylint: disable=too-few-public-methods + + # Regex matching the declaration of a function that returns void. + VOID_RE = re.compile(r'\s*\bvoid\s*\Z', re.A) + + def __init__(self, #pylint: disable=too-many-arguments + filename: str, + line_number: int, + qualifiers: Iterable[str], + return_type: str, + name: str, + arguments: List[str]) -> None: + self.filename = filename + self.line_number = line_number + self.qualifiers = frozenset(qualifiers) + self.return_type = return_type + self.name = name + self.arguments = [ArgumentInfo(arg) for arg in arguments] + + def returns_void(self) -> bool: + """Whether the function returns void.""" + return bool(self.VOID_RE.search(self.return_type)) + + +# Match one C comment. +# Note that we match both comment types, so things like // in a /*...*/ +# comment are handled correctly. +_C_COMMENT_RE = re.compile(r'//(?:[^\n]|\\\n)*|/\*.*?\*/', re.S) +_NOT_NEWLINES_RE = re.compile(r'[^\n]+') + +def read_logical_lines(filename: str) -> Iterator[Tuple[int, str]]: + """Read logical lines from a file. + + Logical lines are one or more physical line, with balanced parentheses. + """ + with open(filename, encoding='utf-8') as inp: + content = inp.read() + # Strip comments, but keep newlines for line numbering + content = re.sub(_C_COMMENT_RE, + lambda m: re.sub(_NOT_NEWLINES_RE, "", m.group(0)), + content) + lines = enumerate(content.splitlines(), 1) + for line_number, line in lines: + # Read a logical line, containing balanced parentheses. + # We assume that parentheses are balanced (this should be ok + # since comments have been stripped), otherwise there will be + # a gigantic logical line at the end. + paren_level = line.count('(') - line.count(')') + while paren_level > 0: + _, more = next(lines) #pylint: disable=stop-iteration-return + paren_level += more.count('(') - more.count(')') + line += '\n' + more + yield line_number, line + +_C_FUNCTION_DECLARATION_RE = re.compile( + r'(?P(?:(?:extern|inline|static)\b\s*)*)' + r'(?P\w[\w\s*]*?)\s*' + + r'\b(?P\w+)' + + r'\s*\((?P.*)\)\s*;', + re.A | re.S) + +def read_function_declarations(functions: Dict[str, FunctionInfo], + filename: str) -> None: + """Collect function declarations from a C header file.""" + for line_number, line in read_logical_lines(filename): + m = _C_FUNCTION_DECLARATION_RE.match(line) + if not m: + continue + qualifiers = m.group('qualifiers').split() + return_type = m.group('return_type') + name = m.group('name') + arguments = m.group('arguments').split(',') + if len(arguments) == 1 and re.match(FunctionInfo.VOID_RE, arguments[0]): + arguments = [] + # Note: we replace any existing declaration for the same name. + functions[name] = FunctionInfo(filename, line_number, + qualifiers, + return_type, + name, + arguments) diff --git a/scripts/mbedtls_dev/c_wrapper_generator.py b/scripts/mbedtls_dev/c_wrapper_generator.py new file mode 100644 index 000000000000..71d3ba25e7a1 --- /dev/null +++ b/scripts/mbedtls_dev/c_wrapper_generator.py @@ -0,0 +1,477 @@ +"""Generate C wrapper functions. +""" + +# Copyright The Mbed TLS Contributors +# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + +### WARNING: the code in this file has not been extensively reviewed yet. +### We do not think it is harmful, but it may be below our normal standards +### for robustness and maintainability. + +import os +import re +import sys +import typing +from typing import Dict, List, Optional, Tuple + +from .c_parsing_helper import ArgumentInfo, FunctionInfo +from . import typing_util + + +def c_declare(prefix: str, name: str, suffix: str) -> str: + """Format a declaration of name with the given type prefix and suffix.""" + if not prefix.endswith('*'): + prefix += ' ' + return prefix + name + suffix + + +WrapperInfo = typing.NamedTuple('WrapperInfo', [ + ('argument_names', List[str]), + ('guard', Optional[str]), + ('wrapper_name', str), +]) + + +class Base: + """Generate a C source file containing wrapper functions.""" + + # This class is designed to have many methods potentially overloaded. + # Tell pylint not to complain about methods that have unused arguments: + # child classes are likely to override those methods and need the + # arguments in question. + #pylint: disable=no-self-use,unused-argument + + # Prefix prepended to the function's name to form the wrapper name. + _WRAPPER_NAME_PREFIX = '' + # Suffix appended to the function's name to form the wrapper name. + _WRAPPER_NAME_SUFFIX = '_wrap' + + # Functions with one of these qualifiers are skipped. + _SKIP_FUNCTION_WITH_QUALIFIERS = frozenset(['inline', 'static']) + + def __init__(self): + """Construct a wrapper generator object. + """ + self.program_name = os.path.basename(sys.argv[0]) + # To be populated in a derived class + self.functions = {} #type: Dict[str, FunctionInfo] + # Preprocessor symbol used as a guard against multiple inclusion in the + # header. Must be set before writing output to a header. + # Not used when writing .c output. + self.header_guard = None #type: Optional[str] + + def _write_prologue(self, out: typing_util.Writable, header: bool) -> None: + """Write the prologue of a C file. + + This includes a description comment and some include directives. + """ + out.write("""/* Automatically generated by {}, do not edit! */ + +/* Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ +""" + .format(self.program_name)) + if header: + out.write(""" +#ifndef {guard} +#define {guard} + +#ifdef __cplusplus +extern "C" {{ +#endif +""" + .format(guard=self.header_guard)) + out.write(""" +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif +""") + + def _write_epilogue(self, out: typing_util.Writable, header: bool) -> None: + """Write the epilogue of a C file. + """ + if header: + out.write(""" +#ifdef __cplusplus +}} +#endif + +#endif /* {guard} */ +""" + .format(guard=self.header_guard)) + out.write(""" +/* End of automatically generated file. */ +""") + + def _wrapper_function_name(self, original_name: str) -> str: + """The name of the wrapper function. + + By default, this adds a suffix. + """ + return (self._WRAPPER_NAME_PREFIX + + original_name + + self._WRAPPER_NAME_SUFFIX) + + def _wrapper_declaration_start(self, + function: FunctionInfo, + wrapper_name: str) -> str: + """The beginning of the wrapper function declaration. + + This ends just before the opening parenthesis of the argument list. + + This is a string containing at least the return type and the + function name. It may start with additional qualifiers or attributes + such as `static`, `__attribute__((...))`, etc. + """ + return c_declare(function.return_type, wrapper_name, '') + + def _argument_name(self, + function_name: str, + num: int, + arg: ArgumentInfo) -> str: + """Name to use for the given argument in the wrapper function. + + Argument numbers count from 0. + """ + name = 'arg' + str(num) + if arg.name: + name += '_' + arg.name + return name + + def _wrapper_declaration_argument(self, + function_name: str, + num: int, name: str, + arg: ArgumentInfo) -> str: + """One argument definition in the wrapper function declaration. + + Argument numbers count from 0. + """ + return c_declare(arg.type, name, arg.suffix) + + def _underlying_function_name(self, function: FunctionInfo) -> str: + """The name of the underlying function. + + By default, this is the name of the wrapped function. + """ + return function.name + + def _return_variable_name(self, function: FunctionInfo) -> str: + """The name of the variable that will contain the return value.""" + return 'retval' + + def _write_function_call(self, out: typing_util.Writable, + function: FunctionInfo, + argument_names: List[str]) -> None: + """Write the call to the underlying function. + """ + # Note that the function name is in parentheses, to avoid calling + # a function-like macro with the same name, since in typical usage + # there is a function-like macro with the same name which is the + # wrapper. + call = '({})({})'.format(self._underlying_function_name(function), + ', '.join(argument_names)) + if function.returns_void(): + out.write(' {};\n'.format(call)) + else: + ret_name = self._return_variable_name(function) + ret_decl = c_declare(function.return_type, ret_name, '') + out.write(' {} = {};\n'.format(ret_decl, call)) + + def _write_function_return(self, out: typing_util.Writable, + function: FunctionInfo, + if_void: bool = False) -> None: + """Write a return statement. + + If the function returns void, only write a statement if if_void is true. + """ + if function.returns_void(): + if if_void: + out.write(' return;\n') + else: + ret_name = self._return_variable_name(function) + out.write(' return {};\n'.format(ret_name)) + + def _write_function_body(self, out: typing_util.Writable, + function: FunctionInfo, + argument_names: List[str]) -> None: + """Write the body of the wrapper code for the specified function. + """ + self._write_function_call(out, function, argument_names) + self._write_function_return(out, function) + + def _skip_function(self, function: FunctionInfo) -> bool: + """Whether to skip this function. + + By default, static or inline functions are skipped. + """ + if not self._SKIP_FUNCTION_WITH_QUALIFIERS.isdisjoint(function.qualifiers): + return True + return False + + _FUNCTION_GUARDS = { + } #type: Dict[str, str] + + def _function_guard(self, function: FunctionInfo) -> Optional[str]: + """A preprocessor condition for this function. + + The wrapper will be guarded with `#if` on this condition, if not None. + """ + return self._FUNCTION_GUARDS.get(function.name) + + def _wrapper_info(self, function: FunctionInfo) -> Optional[WrapperInfo]: + """Information about the wrapper for one function. + + Return None if the function should be skipped. + """ + if self._skip_function(function): + return None + argument_names = [self._argument_name(function.name, num, arg) + for num, arg in enumerate(function.arguments)] + return WrapperInfo( + argument_names=argument_names, + guard=self._function_guard(function), + wrapper_name=self._wrapper_function_name(function.name), + ) + + def _write_function_prototype(self, out: typing_util.Writable, + function: FunctionInfo, + wrapper: WrapperInfo, + header: bool) -> None: + """Write the prototype of a wrapper function. + + If header is true, write a function declaration, with a semicolon at + the end. Otherwise just write the prototype, intended to be followed + by the function's body. + """ + declaration_start = self._wrapper_declaration_start(function, + wrapper.wrapper_name) + arg_indent = ' ' + terminator = ';\n' if header else '\n' + if function.arguments: + out.write(declaration_start + '(\n') + for num in range(len(function.arguments)): + arg_def = self._wrapper_declaration_argument( + function.name, + num, wrapper.argument_names[num], function.arguments[num]) + arg_terminator = \ + (')' + terminator if num == len(function.arguments) - 1 else + ',\n') + out.write(arg_indent + arg_def + arg_terminator) + else: + out.write(declaration_start + '(void)' + terminator) + + def _write_c_function(self, out: typing_util.Writable, + function: FunctionInfo) -> None: + """Write wrapper code for one function. + + Do nothing if the function is skipped. + """ + wrapper = self._wrapper_info(function) + if wrapper is None: + return + out.write(""" +/* Wrapper for {} */ +""" + .format(function.name)) + if wrapper.guard is not None: + out.write('#if {}\n'.format(wrapper.guard)) + self._write_function_prototype(out, function, wrapper, False) + out.write('{\n') + self._write_function_body(out, function, wrapper.argument_names) + out.write('}\n') + if wrapper.guard is not None: + out.write('#endif /* {} */\n'.format(wrapper.guard)) + + def _write_h_function_declaration(self, out: typing_util.Writable, + function: FunctionInfo, + wrapper: WrapperInfo) -> None: + """Write the declaration of one wrapper function. + """ + self._write_function_prototype(out, function, wrapper, True) + + def _write_h_macro_definition(self, out: typing_util.Writable, + function: FunctionInfo, + wrapper: WrapperInfo) -> None: + """Write the macro definition for one wrapper. + """ + arg_list = ', '.join(wrapper.argument_names) + out.write('#define {function_name}({args}) \\\n {wrapper_name}({args})\n' + .format(function_name=function.name, + wrapper_name=wrapper.wrapper_name, + args=arg_list)) + + def _write_h_function(self, out: typing_util.Writable, + function: FunctionInfo) -> None: + """Write the complete header content for one wrapper. + + This is the declaration of the wrapper function, and the + definition of a function-like macro that calls the wrapper function. + + Do nothing if the function is skipped. + """ + wrapper = self._wrapper_info(function) + if wrapper is None: + return + out.write('\n') + if wrapper.guard is not None: + out.write('#if {}\n'.format(wrapper.guard)) + self._write_h_function_declaration(out, function, wrapper) + self._write_h_macro_definition(out, function, wrapper) + if wrapper.guard is not None: + out.write('#endif /* {} */\n'.format(wrapper.guard)) + + def write_c_file(self, filename: str) -> None: + """Output a whole C file containing function wrapper definitions.""" + with open(filename, 'w', encoding='utf-8') as out: + self._write_prologue(out, False) + for name in sorted(self.functions): + self._write_c_function(out, self.functions[name]) + self._write_epilogue(out, False) + + def _header_guard_from_file_name(self, filename: str) -> str: + """Preprocessor symbol used as a guard against multiple inclusion.""" + # Heuristic to strip irrelevant leading directories + filename = re.sub(r'.*include[\\/]', r'', filename) + return re.sub(r'[^0-9A-Za-z]', r'_', filename, re.A).upper() + + def write_h_file(self, filename: str) -> None: + """Output a header file with function wrapper declarations and macro definitions.""" + self.header_guard = self._header_guard_from_file_name(filename) + with open(filename, 'w', encoding='utf-8') as out: + self._write_prologue(out, True) + for name in sorted(self.functions): + self._write_h_function(out, self.functions[name]) + self._write_epilogue(out, True) + + +class UnknownTypeForPrintf(Exception): + """Exception raised when attempting to generate code that logs a value of an unknown type.""" + + def __init__(self, typ: str) -> None: + super().__init__("Unknown type for printf format generation: " + typ) + + +class Logging(Base): + """Generate wrapper functions that log the inputs and outputs.""" + + def __init__(self) -> None: + """Construct a wrapper generator including logging of inputs and outputs. + + Log to stdout by default. Call `set_stream` to change this. + """ + super().__init__() + self.stream = 'stdout' + + def set_stream(self, stream: str) -> None: + """Set the stdio stream to log to. + + Call this method before calling `write_c_output` or `write_h_output`. + """ + self.stream = stream + + def _write_prologue(self, out: typing_util.Writable, header: bool) -> None: + super()._write_prologue(out, header) + if not header: + out.write(""" +#if defined(MBEDTLS_FS_IO) && defined(MBEDTLS_TEST_HOOKS) +#include +#include +#include // for MBEDTLS_PRINTF_SIZET +#include // for mbedtls_fprintf +#endif /* defined(MBEDTLS_FS_IO) && defined(MBEDTLS_TEST_HOOKS) */ +""") + + _PRINTF_SIMPLE_FORMAT = { + 'int': '%d', + 'long': '%ld', + 'long long': '%lld', + 'size_t': '%"MBEDTLS_PRINTF_SIZET"', + 'unsigned': '0x%08x', + 'unsigned int': '0x%08x', + 'unsigned long': '0x%08lx', + 'unsigned long long': '0x%016llx', + } + + def _printf_simple_format(self, typ: str) -> Optional[str]: + """Use this printf format for a value of typ. + + Return None if values of typ need more complex handling. + """ + return self._PRINTF_SIMPLE_FORMAT.get(typ) + + _PRINTF_TYPE_CAST = { + 'int32_t': 'int', + 'uint32_t': 'unsigned', + 'uint64_t': 'unsigned long long', + } #type: Dict[str, str] + + def _printf_type_cast(self, typ: str) -> Optional[str]: + """Cast values of typ to this type before passing them to printf. + + Return None if values of the given type do not need a cast. + """ + return self._PRINTF_TYPE_CAST.get(typ) + + _POINTER_TYPE_RE = re.compile(r'\s*\*\Z') + + def _printf_parameters(self, typ: str, var: str) -> Tuple[str, List[str]]: + """The printf format and arguments for a value of type typ stored in var. + """ + expr = var + base_type = typ + # For outputs via a pointer, get the value that has been written. + # Note: we don't support pointers to pointers here. + pointer_match = self._POINTER_TYPE_RE.search(base_type) + if pointer_match: + base_type = base_type[:pointer_match.start(0)] + expr = '*({})'.format(expr) + # Maybe cast the value to a standard type. + cast_to = self._printf_type_cast(base_type) + if cast_to is not None: + expr = '({}) {}'.format(cast_to, expr) + base_type = cast_to + # Try standard types. + fmt = self._printf_simple_format(base_type) + if fmt is not None: + return '{}={}'.format(var, fmt), [expr] + raise UnknownTypeForPrintf(typ) + + def _write_function_logging(self, out: typing_util.Writable, + function: FunctionInfo, + argument_names: List[str]) -> None: + """Write code to log the function's inputs and outputs.""" + formats, values = '%s', ['"' + function.name + '"'] + for arg_info, arg_name in zip(function.arguments, argument_names): + fmt, vals = self._printf_parameters(arg_info.type, arg_name) + if fmt: + formats += ' ' + fmt + values += vals + if not function.returns_void(): + ret_name = self._return_variable_name(function) + fmt, vals = self._printf_parameters(function.return_type, ret_name) + if fmt: + formats += ' ' + fmt + values += vals + out.write("""\ +#if defined(MBEDTLS_FS_IO) && defined(MBEDTLS_TEST_HOOKS) + if ({stream}) {{ + mbedtls_fprintf({stream}, "{formats}\\n", + {values}); + }} +#endif /* defined(MBEDTLS_FS_IO) && defined(MBEDTLS_TEST_HOOKS) */ +""" + .format(stream=self.stream, + formats=formats, + values=', '.join(values))) + + def _write_function_body(self, out: typing_util.Writable, + function: FunctionInfo, + argument_names: List[str]) -> None: + """Write the body of the wrapper code for the specified function. + """ + self._write_function_call(out, function, argument_names) + self._write_function_logging(out, function, argument_names) + self._write_function_return(out, function) diff --git a/tests/include/test/memory.h b/tests/include/test/memory.h new file mode 100644 index 000000000000..d4bbeec0d4fe --- /dev/null +++ b/tests/include/test/memory.h @@ -0,0 +1,103 @@ +/** + * \file memory.h + * + * \brief Helper macros and functions related to testing memory management. + */ + +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#ifndef TEST_MEMORY_H +#define TEST_MEMORY_H + +#include "test/helpers.h" +#include "mbedtls/platform.h" + +/** \def MBEDTLS_TEST_MEMORY_CAN_POISON + * + * This macro is defined if the tests are compiled with a method to mark + * memory as poisoned, which can be used to enforce some memory access + * policies. + * + * Currently, only Asan (Address Sanitizer) is supported. + */ +#if defined(MBEDTLS_TEST_HAVE_ASAN) +# define MBEDTLS_TEST_MEMORY_CAN_POISON +#endif + +/** \def MBEDTLS_TEST_MEMORY_POISON(buf, size) + * + * Poison a memory area so that any attempt to read or write from it will + * cause a runtime failure. + * + * Depending on the implementation, this may poison a few bytes beyond the + * indicated region, but will never poison a separate object on the heap + * or a separate object with more than the alignment of a long long. + * + * The behavior is undefined if any part of the memory area is invalid. + * + * This is a no-op in builds without a poisoning method. + * See #MBEDTLS_TEST_MEMORY_CAN_POISON. + * + * \param buf Pointer to the beginning of the memory area to poison. + * \param size Size of the memory area in bytes. + */ + +/** \def MBEDTLS_TEST_MEMORY_UNPOISON(buf, size) + * + * Undo the effect of #MBEDTLS_TEST_MEMORY_POISON. + * + * The behavior is undefined if any part of the memory area is invalid, + * or if the memory area contains a mixture of poisoned and unpoisoned parts. + * + * This is a no-op in builds without a poisoning method. + * See #MBEDTLS_TEST_MEMORY_CAN_POISON. + * + * \param buf Pointer to the beginning of the memory area to unpoison. + * \param size Size of the memory area in bytes. + */ + +#if defined(MBEDTLS_TEST_MEMORY_CAN_POISON) + +/** Variable used to enable memory poisoning. This is set and unset in the + * test wrappers so that calls to PSA functions from the library do not + * poison memory. + */ +extern unsigned int mbedtls_test_memory_poisoning_count; + +/** Poison a memory area so that any attempt to read or write from it will + * cause a runtime failure. + * + * The behavior is undefined if any part of the memory area is invalid. + */ +void mbedtls_test_memory_poison(const unsigned char *ptr, size_t size); +#define MBEDTLS_TEST_MEMORY_POISON(ptr, size) \ + do { \ + mbedtls_test_memory_poisoning_count++; \ + mbedtls_test_memory_poison(ptr, size); \ + } while (0) + +/** Undo the effect of mbedtls_test_memory_poison(). + * + * This is a no-op if the given area is entirely valid, unpoisoned memory. + * + * The behavior is undefined if any part of the memory area is invalid, + * or if the memory area contains a mixture of poisoned and unpoisoned parts. + */ +void mbedtls_test_memory_unpoison(const unsigned char *ptr, size_t size); +#define MBEDTLS_TEST_MEMORY_UNPOISON(ptr, size) \ + do { \ + mbedtls_test_memory_unpoison(ptr, size); \ + if (mbedtls_test_memory_poisoning_count != 0) { \ + mbedtls_test_memory_poisoning_count--; \ + } \ + } while (0) + +#else /* MBEDTLS_TEST_MEMORY_CAN_POISON */ +#define MBEDTLS_TEST_MEMORY_POISON(ptr, size) ((void) (ptr), (void) (size)) +#define MBEDTLS_TEST_MEMORY_UNPOISON(ptr, size) ((void) (ptr), (void) (size)) +#endif /* MBEDTLS_TEST_MEMORY_CAN_POISON */ + +#endif /* TEST_MEMORY_H */ diff --git a/tests/include/test/psa_crypto_helpers.h b/tests/include/test/psa_crypto_helpers.h index 8d0f7e69d3d8..e60c96669fca 100644 --- a/tests/include/test/psa_crypto_helpers.h +++ b/tests/include/test/psa_crypto_helpers.h @@ -21,6 +21,7 @@ #include "mbedtls/psa_util.h" #endif + #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) /* Internal function for #TEST_USES_KEY_ID. Return 1 on success, 0 on failure. */ diff --git a/tests/include/test/psa_memory_poisoning_wrappers.h b/tests/include/test/psa_memory_poisoning_wrappers.h new file mode 100644 index 000000000000..3f30b65c0471 --- /dev/null +++ b/tests/include/test/psa_memory_poisoning_wrappers.h @@ -0,0 +1,40 @@ +/** Support for memory poisoning wrappers for PSA functions. + * + * The wrappers poison the input and output buffers of each function + * before calling it, to ensure that it does not access the buffers + * except by calling the approved buffer-copying functions. + * + * This header declares support functions. The wrappers themselves are + * decalred in the automatically generated file `test/psa_test_wrappers.h`. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#ifndef PSA_MEMORY_POISONING_WRAPPERS_H +#define PSA_MEMORY_POISONING_WRAPPERS_H + +#include "psa/crypto.h" + +#include "test/memory.h" + +#if defined(MBEDTLS_TEST_HOOKS) && defined(MBEDTLS_TEST_MEMORY_CAN_POISON) + +/** + * \brief Setup the memory poisoning test hooks used by + * psa_crypto_copy_input() and psa_crypto_copy_output() for + * memory poisoning. + */ +void mbedtls_poison_test_hooks_setup(void); + +/** + * \brief Teardown the memory poisoning test hooks used by + * psa_crypto_copy_input() and psa_crypto_copy_output() for + * memory poisoning. + */ +void mbedtls_poison_test_hooks_teardown(void); + +#endif /* MBEDTLS_TEST_HOOKS && MBEDTLS_TEST_MEMORY_CAN_POISON */ + +#endif /* PSA_MEMORY_POISONING_WRAPPERS_H */ diff --git a/tests/include/test/psa_test_wrappers.h b/tests/include/test/psa_test_wrappers.h new file mode 100644 index 000000000000..293329642fcc --- /dev/null +++ b/tests/include/test/psa_test_wrappers.h @@ -0,0 +1,489 @@ +/* Automatically generated by generate_psa_wrappers.py, do not edit! */ + +/* Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#ifndef TEST_PSA_TEST_WRAPPERS_H +#define TEST_PSA_TEST_WRAPPERS_H + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PSA_CRYPTO_C) && defined(MBEDTLS_TEST_HOOKS) && \ + !defined(RECORD_PSA_STATUS_COVERAGE_LOG) + +#include + +#include +#include +#include + +#if defined(MBEDTLS_PSA_INJECT_ENTROPY) +psa_status_t mbedtls_test_wrap_mbedtls_psa_inject_entropy( + const uint8_t *arg0_seed, + size_t arg1_seed_size); +#define mbedtls_psa_inject_entropy(arg0_seed, arg1_seed_size) \ + mbedtls_test_wrap_mbedtls_psa_inject_entropy(arg0_seed, arg1_seed_size) +#endif /* defined(MBEDTLS_PSA_INJECT_ENTROPY) */ + +#if defined(MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS) +psa_status_t mbedtls_test_wrap_mbedtls_psa_platform_get_builtin_key( + mbedtls_svc_key_id_t arg0_key_id, + psa_key_lifetime_t *arg1_lifetime, + psa_drv_slot_number_t *arg2_slot_number); +#define mbedtls_psa_platform_get_builtin_key(arg0_key_id, arg1_lifetime, arg2_slot_number) \ + mbedtls_test_wrap_mbedtls_psa_platform_get_builtin_key(arg0_key_id, arg1_lifetime, arg2_slot_number) +#endif /* defined(MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS) */ + +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) +psa_status_t mbedtls_test_wrap_mbedtls_psa_register_se_key( + const psa_key_attributes_t *arg0_attributes); +#define mbedtls_psa_register_se_key(arg0_attributes) \ + mbedtls_test_wrap_mbedtls_psa_register_se_key(arg0_attributes) +#endif /* defined(MBEDTLS_PSA_CRYPTO_SE_C) */ + +psa_status_t mbedtls_test_wrap_psa_aead_decrypt( + mbedtls_svc_key_id_t arg0_key, + psa_algorithm_t arg1_alg, + const uint8_t *arg2_nonce, + size_t arg3_nonce_length, + const uint8_t *arg4_additional_data, + size_t arg5_additional_data_length, + const uint8_t *arg6_ciphertext, + size_t arg7_ciphertext_length, + uint8_t *arg8_plaintext, + size_t arg9_plaintext_size, + size_t *arg10_plaintext_length); +#define psa_aead_decrypt(arg0_key, arg1_alg, arg2_nonce, arg3_nonce_length, arg4_additional_data, arg5_additional_data_length, arg6_ciphertext, arg7_ciphertext_length, arg8_plaintext, arg9_plaintext_size, arg10_plaintext_length) \ + mbedtls_test_wrap_psa_aead_decrypt(arg0_key, arg1_alg, arg2_nonce, arg3_nonce_length, arg4_additional_data, arg5_additional_data_length, arg6_ciphertext, arg7_ciphertext_length, arg8_plaintext, arg9_plaintext_size, arg10_plaintext_length) + +psa_status_t mbedtls_test_wrap_psa_aead_encrypt( + mbedtls_svc_key_id_t arg0_key, + psa_algorithm_t arg1_alg, + const uint8_t *arg2_nonce, + size_t arg3_nonce_length, + const uint8_t *arg4_additional_data, + size_t arg5_additional_data_length, + const uint8_t *arg6_plaintext, + size_t arg7_plaintext_length, + uint8_t *arg8_ciphertext, + size_t arg9_ciphertext_size, + size_t *arg10_ciphertext_length); +#define psa_aead_encrypt(arg0_key, arg1_alg, arg2_nonce, arg3_nonce_length, arg4_additional_data, arg5_additional_data_length, arg6_plaintext, arg7_plaintext_length, arg8_ciphertext, arg9_ciphertext_size, arg10_ciphertext_length) \ + mbedtls_test_wrap_psa_aead_encrypt(arg0_key, arg1_alg, arg2_nonce, arg3_nonce_length, arg4_additional_data, arg5_additional_data_length, arg6_plaintext, arg7_plaintext_length, arg8_ciphertext, arg9_ciphertext_size, arg10_ciphertext_length) + +psa_status_t mbedtls_test_wrap_psa_asymmetric_decrypt( + mbedtls_svc_key_id_t arg0_key, + psa_algorithm_t arg1_alg, + const uint8_t *arg2_input, + size_t arg3_input_length, + const uint8_t *arg4_salt, + size_t arg5_salt_length, + uint8_t *arg6_output, + size_t arg7_output_size, + size_t *arg8_output_length); +#define psa_asymmetric_decrypt(arg0_key, arg1_alg, arg2_input, arg3_input_length, arg4_salt, arg5_salt_length, arg6_output, arg7_output_size, arg8_output_length) \ + mbedtls_test_wrap_psa_asymmetric_decrypt(arg0_key, arg1_alg, arg2_input, arg3_input_length, arg4_salt, arg5_salt_length, arg6_output, arg7_output_size, arg8_output_length) + +psa_status_t mbedtls_test_wrap_psa_asymmetric_encrypt( + mbedtls_svc_key_id_t arg0_key, + psa_algorithm_t arg1_alg, + const uint8_t *arg2_input, + size_t arg3_input_length, + const uint8_t *arg4_salt, + size_t arg5_salt_length, + uint8_t *arg6_output, + size_t arg7_output_size, + size_t *arg8_output_length); +#define psa_asymmetric_encrypt(arg0_key, arg1_alg, arg2_input, arg3_input_length, arg4_salt, arg5_salt_length, arg6_output, arg7_output_size, arg8_output_length) \ + mbedtls_test_wrap_psa_asymmetric_encrypt(arg0_key, arg1_alg, arg2_input, arg3_input_length, arg4_salt, arg5_salt_length, arg6_output, arg7_output_size, arg8_output_length) + +psa_status_t mbedtls_test_wrap_psa_cipher_abort( + psa_cipher_operation_t *arg0_operation); +#define psa_cipher_abort(arg0_operation) \ + mbedtls_test_wrap_psa_cipher_abort(arg0_operation) + +psa_status_t mbedtls_test_wrap_psa_cipher_decrypt( + mbedtls_svc_key_id_t arg0_key, + psa_algorithm_t arg1_alg, + const uint8_t *arg2_input, + size_t arg3_input_length, + uint8_t *arg4_output, + size_t arg5_output_size, + size_t *arg6_output_length); +#define psa_cipher_decrypt(arg0_key, arg1_alg, arg2_input, arg3_input_length, arg4_output, arg5_output_size, arg6_output_length) \ + mbedtls_test_wrap_psa_cipher_decrypt(arg0_key, arg1_alg, arg2_input, arg3_input_length, arg4_output, arg5_output_size, arg6_output_length) + +psa_status_t mbedtls_test_wrap_psa_cipher_decrypt_setup( + psa_cipher_operation_t *arg0_operation, + mbedtls_svc_key_id_t arg1_key, + psa_algorithm_t arg2_alg); +#define psa_cipher_decrypt_setup(arg0_operation, arg1_key, arg2_alg) \ + mbedtls_test_wrap_psa_cipher_decrypt_setup(arg0_operation, arg1_key, arg2_alg) + +psa_status_t mbedtls_test_wrap_psa_cipher_encrypt( + mbedtls_svc_key_id_t arg0_key, + psa_algorithm_t arg1_alg, + const uint8_t *arg2_input, + size_t arg3_input_length, + uint8_t *arg4_output, + size_t arg5_output_size, + size_t *arg6_output_length); +#define psa_cipher_encrypt(arg0_key, arg1_alg, arg2_input, arg3_input_length, arg4_output, arg5_output_size, arg6_output_length) \ + mbedtls_test_wrap_psa_cipher_encrypt(arg0_key, arg1_alg, arg2_input, arg3_input_length, arg4_output, arg5_output_size, arg6_output_length) + +psa_status_t mbedtls_test_wrap_psa_cipher_encrypt_setup( + psa_cipher_operation_t *arg0_operation, + mbedtls_svc_key_id_t arg1_key, + psa_algorithm_t arg2_alg); +#define psa_cipher_encrypt_setup(arg0_operation, arg1_key, arg2_alg) \ + mbedtls_test_wrap_psa_cipher_encrypt_setup(arg0_operation, arg1_key, arg2_alg) + +psa_status_t mbedtls_test_wrap_psa_cipher_finish( + psa_cipher_operation_t *arg0_operation, + uint8_t *arg1_output, + size_t arg2_output_size, + size_t *arg3_output_length); +#define psa_cipher_finish(arg0_operation, arg1_output, arg2_output_size, arg3_output_length) \ + mbedtls_test_wrap_psa_cipher_finish(arg0_operation, arg1_output, arg2_output_size, arg3_output_length) + +psa_status_t mbedtls_test_wrap_psa_cipher_generate_iv( + psa_cipher_operation_t *arg0_operation, + uint8_t *arg1_iv, + size_t arg2_iv_size, + size_t *arg3_iv_length); +#define psa_cipher_generate_iv(arg0_operation, arg1_iv, arg2_iv_size, arg3_iv_length) \ + mbedtls_test_wrap_psa_cipher_generate_iv(arg0_operation, arg1_iv, arg2_iv_size, arg3_iv_length) + +psa_status_t mbedtls_test_wrap_psa_cipher_set_iv( + psa_cipher_operation_t *arg0_operation, + const uint8_t *arg1_iv, + size_t arg2_iv_length); +#define psa_cipher_set_iv(arg0_operation, arg1_iv, arg2_iv_length) \ + mbedtls_test_wrap_psa_cipher_set_iv(arg0_operation, arg1_iv, arg2_iv_length) + +psa_status_t mbedtls_test_wrap_psa_cipher_update( + psa_cipher_operation_t *arg0_operation, + const uint8_t *arg1_input, + size_t arg2_input_length, + uint8_t *arg3_output, + size_t arg4_output_size, + size_t *arg5_output_length); +#define psa_cipher_update(arg0_operation, arg1_input, arg2_input_length, arg3_output, arg4_output_size, arg5_output_length) \ + mbedtls_test_wrap_psa_cipher_update(arg0_operation, arg1_input, arg2_input_length, arg3_output, arg4_output_size, arg5_output_length) + +psa_status_t mbedtls_test_wrap_psa_copy_key( + mbedtls_svc_key_id_t arg0_source_key, + const psa_key_attributes_t *arg1_attributes, + mbedtls_svc_key_id_t *arg2_target_key); +#define psa_copy_key(arg0_source_key, arg1_attributes, arg2_target_key) \ + mbedtls_test_wrap_psa_copy_key(arg0_source_key, arg1_attributes, arg2_target_key) + +psa_status_t mbedtls_test_wrap_psa_crypto_init(void); +#define psa_crypto_init() \ + mbedtls_test_wrap_psa_crypto_init() + +psa_status_t mbedtls_test_wrap_psa_destroy_key( + mbedtls_svc_key_id_t arg0_key); +#define psa_destroy_key(arg0_key) \ + mbedtls_test_wrap_psa_destroy_key(arg0_key) + +psa_status_t mbedtls_test_wrap_psa_export_key( + mbedtls_svc_key_id_t arg0_key, + uint8_t *arg1_data, + size_t arg2_data_size, + size_t *arg3_data_length); +#define psa_export_key(arg0_key, arg1_data, arg2_data_size, arg3_data_length) \ + mbedtls_test_wrap_psa_export_key(arg0_key, arg1_data, arg2_data_size, arg3_data_length) + +psa_status_t mbedtls_test_wrap_psa_export_public_key( + mbedtls_svc_key_id_t arg0_key, + uint8_t *arg1_data, + size_t arg2_data_size, + size_t *arg3_data_length); +#define psa_export_public_key(arg0_key, arg1_data, arg2_data_size, arg3_data_length) \ + mbedtls_test_wrap_psa_export_public_key(arg0_key, arg1_data, arg2_data_size, arg3_data_length) + +psa_status_t mbedtls_test_wrap_psa_generate_key( + const psa_key_attributes_t *arg0_attributes, + mbedtls_svc_key_id_t *arg1_key); +#define psa_generate_key(arg0_attributes, arg1_key) \ + mbedtls_test_wrap_psa_generate_key(arg0_attributes, arg1_key) + +psa_status_t mbedtls_test_wrap_psa_generate_random( + uint8_t *arg0_output, + size_t arg1_output_size); +#define psa_generate_random(arg0_output, arg1_output_size) \ + mbedtls_test_wrap_psa_generate_random(arg0_output, arg1_output_size) + +psa_status_t mbedtls_test_wrap_psa_get_key_attributes( + mbedtls_svc_key_id_t arg0_key, + psa_key_attributes_t *arg1_attributes); +#define psa_get_key_attributes(arg0_key, arg1_attributes) \ + mbedtls_test_wrap_psa_get_key_attributes(arg0_key, arg1_attributes) + +psa_status_t mbedtls_test_wrap_psa_hash_abort( + psa_hash_operation_t *arg0_operation); +#define psa_hash_abort(arg0_operation) \ + mbedtls_test_wrap_psa_hash_abort(arg0_operation) + +psa_status_t mbedtls_test_wrap_psa_hash_clone( + const psa_hash_operation_t *arg0_source_operation, + psa_hash_operation_t *arg1_target_operation); +#define psa_hash_clone(arg0_source_operation, arg1_target_operation) \ + mbedtls_test_wrap_psa_hash_clone(arg0_source_operation, arg1_target_operation) + +psa_status_t mbedtls_test_wrap_psa_hash_compare( + psa_algorithm_t arg0_alg, + const uint8_t *arg1_input, + size_t arg2_input_length, + const uint8_t *arg3_hash, + size_t arg4_hash_length); +#define psa_hash_compare(arg0_alg, arg1_input, arg2_input_length, arg3_hash, arg4_hash_length) \ + mbedtls_test_wrap_psa_hash_compare(arg0_alg, arg1_input, arg2_input_length, arg3_hash, arg4_hash_length) + +psa_status_t mbedtls_test_wrap_psa_hash_compute( + psa_algorithm_t arg0_alg, + const uint8_t *arg1_input, + size_t arg2_input_length, + uint8_t *arg3_hash, + size_t arg4_hash_size, + size_t *arg5_hash_length); +#define psa_hash_compute(arg0_alg, arg1_input, arg2_input_length, arg3_hash, arg4_hash_size, arg5_hash_length) \ + mbedtls_test_wrap_psa_hash_compute(arg0_alg, arg1_input, arg2_input_length, arg3_hash, arg4_hash_size, arg5_hash_length) + +psa_status_t mbedtls_test_wrap_psa_hash_finish( + psa_hash_operation_t *arg0_operation, + uint8_t *arg1_hash, + size_t arg2_hash_size, + size_t *arg3_hash_length); +#define psa_hash_finish(arg0_operation, arg1_hash, arg2_hash_size, arg3_hash_length) \ + mbedtls_test_wrap_psa_hash_finish(arg0_operation, arg1_hash, arg2_hash_size, arg3_hash_length) + +psa_status_t mbedtls_test_wrap_psa_hash_setup( + psa_hash_operation_t *arg0_operation, + psa_algorithm_t arg1_alg); +#define psa_hash_setup(arg0_operation, arg1_alg) \ + mbedtls_test_wrap_psa_hash_setup(arg0_operation, arg1_alg) + +psa_status_t mbedtls_test_wrap_psa_hash_update( + psa_hash_operation_t *arg0_operation, + const uint8_t *arg1_input, + size_t arg2_input_length); +#define psa_hash_update(arg0_operation, arg1_input, arg2_input_length) \ + mbedtls_test_wrap_psa_hash_update(arg0_operation, arg1_input, arg2_input_length) + +psa_status_t mbedtls_test_wrap_psa_hash_verify( + psa_hash_operation_t *arg0_operation, + const uint8_t *arg1_hash, + size_t arg2_hash_length); +#define psa_hash_verify(arg0_operation, arg1_hash, arg2_hash_length) \ + mbedtls_test_wrap_psa_hash_verify(arg0_operation, arg1_hash, arg2_hash_length) + +psa_status_t mbedtls_test_wrap_psa_import_key( + const psa_key_attributes_t *arg0_attributes, + const uint8_t *arg1_data, + size_t arg2_data_length, + mbedtls_svc_key_id_t *arg3_key); +#define psa_import_key(arg0_attributes, arg1_data, arg2_data_length, arg3_key) \ + mbedtls_test_wrap_psa_import_key(arg0_attributes, arg1_data, arg2_data_length, arg3_key) + +psa_status_t mbedtls_test_wrap_psa_key_derivation_abort( + psa_key_derivation_operation_t *arg0_operation); +#define psa_key_derivation_abort(arg0_operation) \ + mbedtls_test_wrap_psa_key_derivation_abort(arg0_operation) + +psa_status_t mbedtls_test_wrap_psa_key_derivation_get_capacity( + const psa_key_derivation_operation_t *arg0_operation, + size_t *arg1_capacity); +#define psa_key_derivation_get_capacity(arg0_operation, arg1_capacity) \ + mbedtls_test_wrap_psa_key_derivation_get_capacity(arg0_operation, arg1_capacity) + +psa_status_t mbedtls_test_wrap_psa_key_derivation_input_bytes( + psa_key_derivation_operation_t *arg0_operation, + psa_key_derivation_step_t arg1_step, + const uint8_t *arg2_data, + size_t arg3_data_length); +#define psa_key_derivation_input_bytes(arg0_operation, arg1_step, arg2_data, arg3_data_length) \ + mbedtls_test_wrap_psa_key_derivation_input_bytes(arg0_operation, arg1_step, arg2_data, arg3_data_length) + +psa_status_t mbedtls_test_wrap_psa_key_derivation_input_key( + psa_key_derivation_operation_t *arg0_operation, + psa_key_derivation_step_t arg1_step, + mbedtls_svc_key_id_t arg2_key); +#define psa_key_derivation_input_key(arg0_operation, arg1_step, arg2_key) \ + mbedtls_test_wrap_psa_key_derivation_input_key(arg0_operation, arg1_step, arg2_key) + +psa_status_t mbedtls_test_wrap_psa_key_derivation_key_agreement( + psa_key_derivation_operation_t *arg0_operation, + psa_key_derivation_step_t arg1_step, + mbedtls_svc_key_id_t arg2_private_key, + const uint8_t *arg3_peer_key, + size_t arg4_peer_key_length); +#define psa_key_derivation_key_agreement(arg0_operation, arg1_step, arg2_private_key, arg3_peer_key, arg4_peer_key_length) \ + mbedtls_test_wrap_psa_key_derivation_key_agreement(arg0_operation, arg1_step, arg2_private_key, arg3_peer_key, arg4_peer_key_length) + +psa_status_t mbedtls_test_wrap_psa_key_derivation_output_bytes( + psa_key_derivation_operation_t *arg0_operation, + uint8_t *arg1_output, + size_t arg2_output_length); +#define psa_key_derivation_output_bytes(arg0_operation, arg1_output, arg2_output_length) \ + mbedtls_test_wrap_psa_key_derivation_output_bytes(arg0_operation, arg1_output, arg2_output_length) + +psa_status_t mbedtls_test_wrap_psa_key_derivation_output_key( + const psa_key_attributes_t *arg0_attributes, + psa_key_derivation_operation_t *arg1_operation, + mbedtls_svc_key_id_t *arg2_key); +#define psa_key_derivation_output_key(arg0_attributes, arg1_operation, arg2_key) \ + mbedtls_test_wrap_psa_key_derivation_output_key(arg0_attributes, arg1_operation, arg2_key) + +psa_status_t mbedtls_test_wrap_psa_key_derivation_set_capacity( + psa_key_derivation_operation_t *arg0_operation, + size_t arg1_capacity); +#define psa_key_derivation_set_capacity(arg0_operation, arg1_capacity) \ + mbedtls_test_wrap_psa_key_derivation_set_capacity(arg0_operation, arg1_capacity) + +psa_status_t mbedtls_test_wrap_psa_key_derivation_setup( + psa_key_derivation_operation_t *arg0_operation, + psa_algorithm_t arg1_alg); +#define psa_key_derivation_setup(arg0_operation, arg1_alg) \ + mbedtls_test_wrap_psa_key_derivation_setup(arg0_operation, arg1_alg) + +psa_status_t mbedtls_test_wrap_psa_mac_abort( + psa_mac_operation_t *arg0_operation); +#define psa_mac_abort(arg0_operation) \ + mbedtls_test_wrap_psa_mac_abort(arg0_operation) + +psa_status_t mbedtls_test_wrap_psa_mac_compute( + mbedtls_svc_key_id_t arg0_key, + psa_algorithm_t arg1_alg, + const uint8_t *arg2_input, + size_t arg3_input_length, + uint8_t *arg4_mac, + size_t arg5_mac_size, + size_t *arg6_mac_length); +#define psa_mac_compute(arg0_key, arg1_alg, arg2_input, arg3_input_length, arg4_mac, arg5_mac_size, arg6_mac_length) \ + mbedtls_test_wrap_psa_mac_compute(arg0_key, arg1_alg, arg2_input, arg3_input_length, arg4_mac, arg5_mac_size, arg6_mac_length) + +psa_status_t mbedtls_test_wrap_psa_mac_sign_finish( + psa_mac_operation_t *arg0_operation, + uint8_t *arg1_mac, + size_t arg2_mac_size, + size_t *arg3_mac_length); +#define psa_mac_sign_finish(arg0_operation, arg1_mac, arg2_mac_size, arg3_mac_length) \ + mbedtls_test_wrap_psa_mac_sign_finish(arg0_operation, arg1_mac, arg2_mac_size, arg3_mac_length) + +psa_status_t mbedtls_test_wrap_psa_mac_sign_setup( + psa_mac_operation_t *arg0_operation, + mbedtls_svc_key_id_t arg1_key, + psa_algorithm_t arg2_alg); +#define psa_mac_sign_setup(arg0_operation, arg1_key, arg2_alg) \ + mbedtls_test_wrap_psa_mac_sign_setup(arg0_operation, arg1_key, arg2_alg) + +psa_status_t mbedtls_test_wrap_psa_mac_update( + psa_mac_operation_t *arg0_operation, + const uint8_t *arg1_input, + size_t arg2_input_length); +#define psa_mac_update(arg0_operation, arg1_input, arg2_input_length) \ + mbedtls_test_wrap_psa_mac_update(arg0_operation, arg1_input, arg2_input_length) + +psa_status_t mbedtls_test_wrap_psa_mac_verify( + mbedtls_svc_key_id_t arg0_key, + psa_algorithm_t arg1_alg, + const uint8_t *arg2_input, + size_t arg3_input_length, + const uint8_t *arg4_mac, + size_t arg5_mac_length); +#define psa_mac_verify(arg0_key, arg1_alg, arg2_input, arg3_input_length, arg4_mac, arg5_mac_length) \ + mbedtls_test_wrap_psa_mac_verify(arg0_key, arg1_alg, arg2_input, arg3_input_length, arg4_mac, arg5_mac_length) + +psa_status_t mbedtls_test_wrap_psa_mac_verify_finish( + psa_mac_operation_t *arg0_operation, + const uint8_t *arg1_mac, + size_t arg2_mac_length); +#define psa_mac_verify_finish(arg0_operation, arg1_mac, arg2_mac_length) \ + mbedtls_test_wrap_psa_mac_verify_finish(arg0_operation, arg1_mac, arg2_mac_length) + +psa_status_t mbedtls_test_wrap_psa_mac_verify_setup( + psa_mac_operation_t *arg0_operation, + mbedtls_svc_key_id_t arg1_key, + psa_algorithm_t arg2_alg); +#define psa_mac_verify_setup(arg0_operation, arg1_key, arg2_alg) \ + mbedtls_test_wrap_psa_mac_verify_setup(arg0_operation, arg1_key, arg2_alg) + +psa_status_t mbedtls_test_wrap_psa_purge_key( + mbedtls_svc_key_id_t arg0_key); +#define psa_purge_key(arg0_key) \ + mbedtls_test_wrap_psa_purge_key(arg0_key) + +psa_status_t mbedtls_test_wrap_psa_raw_key_agreement( + psa_algorithm_t arg0_alg, + mbedtls_svc_key_id_t arg1_private_key, + const uint8_t *arg2_peer_key, + size_t arg3_peer_key_length, + uint8_t *arg4_output, + size_t arg5_output_size, + size_t *arg6_output_length); +#define psa_raw_key_agreement(arg0_alg, arg1_private_key, arg2_peer_key, arg3_peer_key_length, arg4_output, arg5_output_size, arg6_output_length) \ + mbedtls_test_wrap_psa_raw_key_agreement(arg0_alg, arg1_private_key, arg2_peer_key, arg3_peer_key_length, arg4_output, arg5_output_size, arg6_output_length) + +psa_status_t mbedtls_test_wrap_psa_sign_hash( + mbedtls_svc_key_id_t arg0_key, + psa_algorithm_t arg1_alg, + const uint8_t *arg2_hash, + size_t arg3_hash_length, + uint8_t *arg4_signature, + size_t arg5_signature_size, + size_t *arg6_signature_length); +#define psa_sign_hash(arg0_key, arg1_alg, arg2_hash, arg3_hash_length, arg4_signature, arg5_signature_size, arg6_signature_length) \ + mbedtls_test_wrap_psa_sign_hash(arg0_key, arg1_alg, arg2_hash, arg3_hash_length, arg4_signature, arg5_signature_size, arg6_signature_length) + +psa_status_t mbedtls_test_wrap_psa_sign_message( + mbedtls_svc_key_id_t arg0_key, + psa_algorithm_t arg1_alg, + const uint8_t *arg2_input, + size_t arg3_input_length, + uint8_t *arg4_signature, + size_t arg5_signature_size, + size_t *arg6_signature_length); +#define psa_sign_message(arg0_key, arg1_alg, arg2_input, arg3_input_length, arg4_signature, arg5_signature_size, arg6_signature_length) \ + mbedtls_test_wrap_psa_sign_message(arg0_key, arg1_alg, arg2_input, arg3_input_length, arg4_signature, arg5_signature_size, arg6_signature_length) + +psa_status_t mbedtls_test_wrap_psa_verify_hash( + mbedtls_svc_key_id_t arg0_key, + psa_algorithm_t arg1_alg, + const uint8_t *arg2_hash, + size_t arg3_hash_length, + const uint8_t *arg4_signature, + size_t arg5_signature_length); +#define psa_verify_hash(arg0_key, arg1_alg, arg2_hash, arg3_hash_length, arg4_signature, arg5_signature_length) \ + mbedtls_test_wrap_psa_verify_hash(arg0_key, arg1_alg, arg2_hash, arg3_hash_length, arg4_signature, arg5_signature_length) + +psa_status_t mbedtls_test_wrap_psa_verify_message( + mbedtls_svc_key_id_t arg0_key, + psa_algorithm_t arg1_alg, + const uint8_t *arg2_input, + size_t arg3_input_length, + const uint8_t *arg4_signature, + size_t arg5_signature_length); +#define psa_verify_message(arg0_key, arg1_alg, arg2_input, arg3_input_length, arg4_signature, arg5_signature_length) \ + mbedtls_test_wrap_psa_verify_message(arg0_key, arg1_alg, arg2_input, arg3_input_length, arg4_signature, arg5_signature_length) + +#endif /* defined(MBEDTLS_PSA_CRYPTO_C) && defined(MBEDTLS_TEST_HOOKS) && \ + !defined(RECORD_PSA_STATUS_COVERAGE_LOG) */ + +#ifdef __cplusplus +} +#endif + +#endif /* TEST_PSA_TEST_WRAPPERS_H */ + +/* End of automatically generated file. */ diff --git a/tests/scripts/all.sh b/tests/scripts/all.sh index 01ce3b9c2dec..6b4b4e4a3ecd 100755 --- a/tests/scripts/all.sh +++ b/tests/scripts/all.sh @@ -901,7 +901,7 @@ component_test_default_cmake_gcc_asan () { programs/test/selftest msg "test: metatests (GCC, ASan build)" - tests/scripts/run-metatests.sh any asan + tests/scripts/run-metatests.sh any asan poison msg "test: ssl-opt.sh (ASan build)" # ~ 1 min tests/ssl-opt.sh @@ -947,6 +947,17 @@ component_test_psa_crypto_key_id_encodes_owner () { make test } +component_test_psa_assume_exclusive_buffers () { + msg "build: full config + MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS, cmake, gcc, ASan" + scripts/config.py full + scripts/config.py set MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS + CC=gcc cmake -D CMAKE_BUILD_TYPE:String=Asan . + make + + msg "test: full config + MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS, cmake, gcc, ASan" + make test +} + # check_renamed_symbols HEADER LIB # Check that if HEADER contains '#define MACRO ...' then MACRO is not a symbol # name is LIB. @@ -1514,7 +1525,7 @@ component_test_everest () { make test msg "test: metatests (clang, ASan)" - tests/scripts/run-metatests.sh any asan + tests/scripts/run-metatests.sh any asan poison msg "test: Everest ECDH context - ECDH-related part of ssl-opt.sh (ASan build)" # ~ 5s tests/ssl-opt.sh -f ECDH diff --git a/tests/scripts/check-generated-files.sh b/tests/scripts/check-generated-files.sh index 28719bd7a83a..b1b969f7ebb8 100755 --- a/tests/scripts/check-generated-files.sh +++ b/tests/scripts/check-generated-files.sh @@ -100,5 +100,6 @@ check scripts/generate_query_config.pl programs/test/query_config.c check scripts/generate_features.pl library/version_features.c check scripts/generate_visualc_files.pl visualc/VS2010 check scripts/generate_psa_constants.py programs/psa/psa_constant_names_generated.c +check tests/scripts/generate_psa_wrappers.py tests/include/test/psa_test_wrappers.h tests/src/psa_test_wrappers.c check tests/scripts/generate_bignum_tests.py $(tests/scripts/generate_bignum_tests.py --list) check tests/scripts/generate_psa_tests.py $(tests/scripts/generate_psa_tests.py --list) diff --git a/tests/scripts/generate_psa_wrappers.py b/tests/scripts/generate_psa_wrappers.py new file mode 100755 index 000000000000..755a5842a73d --- /dev/null +++ b/tests/scripts/generate_psa_wrappers.py @@ -0,0 +1,260 @@ +#!/usr/bin/env python3 +"""Generate wrapper functions for PSA function calls. +""" + +# Copyright The Mbed TLS Contributors +# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + +### WARNING: the code in this file has not been extensively reviewed yet. +### We do not think it is harmful, but it may be below our normal standards +### for robustness and maintainability. + +import argparse +import itertools +import os +from typing import Iterator, List, Optional, Tuple + +import scripts_path #pylint: disable=unused-import +from mbedtls_dev import build_tree +from mbedtls_dev import c_parsing_helper +from mbedtls_dev import c_wrapper_generator +from mbedtls_dev import typing_util + + +class BufferParameter: + """Description of an input or output buffer parameter sequence to a PSA function.""" + #pylint: disable=too-few-public-methods + + def __init__(self, i: int, is_output: bool, + buffer_name: str, size_name: str) -> None: + """Initialize the parameter information. + + i is the index of the function argument that is the pointer to the buffer. + The size is argument i+1. For a variable-size output, the actual length + goes in argument i+2. + + buffer_name and size_names are the names of arguments i and i+1. + This class does not yet help with the output length. + """ + self.index = i + self.buffer_name = buffer_name + self.size_name = size_name + self.is_output = is_output + + +class PSAWrapperGenerator(c_wrapper_generator.Base): + """Generate a C source file containing wrapper functions for PSA Crypto API calls.""" + + _CPP_GUARDS = ('defined(MBEDTLS_PSA_CRYPTO_C) && ' + + 'defined(MBEDTLS_TEST_HOOKS) && \\\n ' + + '!defined(RECORD_PSA_STATUS_COVERAGE_LOG)') + _WRAPPER_NAME_PREFIX = 'mbedtls_test_wrap_' + _WRAPPER_NAME_SUFFIX = '' + + def gather_data(self) -> None: + root_dir = build_tree.guess_mbedtls_root() + for header_name in ['crypto.h', 'crypto_extra.h']: + header_path = os.path.join(root_dir, 'include', 'psa', header_name) + c_parsing_helper.read_function_declarations(self.functions, header_path) + + _SKIP_FUNCTIONS = frozenset([ + 'mbedtls_psa_external_get_random', # not a library function + 'psa_aead_abort', # not implemented yet + 'psa_aead_decrypt_setup', # not implemented yet + 'psa_aead_encrypt_setup', # not implemented yet + 'psa_aead_finish', # not implemented yet + 'psa_aead_generate_nonce', # not implemented yet + 'psa_aead_set_lengths', # not implemented yet + 'psa_aead_set_nonce', # not implemented yet + 'psa_aead_update', # not implemented yet + 'psa_aead_update_ad', # not implemented yet + 'psa_aead_verify', # not implemented yet + 'psa_get_key_domain_parameters', # client-side function + 'psa_get_key_slot_number', # client-side function + 'psa_set_key_domain_parameters', # client-side function + ]) + + def _skip_function(self, function: c_wrapper_generator.FunctionInfo) -> bool: + if function.return_type != 'psa_status_t': + return True + if function.name in self._SKIP_FUNCTIONS: + return True + return False + + # PAKE stuff: not implemented yet + _PAKE_STUFF = frozenset([ + 'psa_crypto_driver_pake_inputs_t *', + 'psa_pake_cipher_suite_t *', + ]) + + def _return_variable_name(self, + function: c_wrapper_generator.FunctionInfo) -> str: + """The name of the variable that will contain the return value.""" + if function.return_type == 'psa_status_t': + return 'status' + return super()._return_variable_name(function) + + _FUNCTION_GUARDS = c_wrapper_generator.Base._FUNCTION_GUARDS.copy() \ + #pylint: disable=protected-access + _FUNCTION_GUARDS.update({ + 'mbedtls_psa_register_se_key': 'defined(MBEDTLS_PSA_CRYPTO_SE_C)', + 'mbedtls_psa_inject_entropy': 'defined(MBEDTLS_PSA_INJECT_ENTROPY)', + 'mbedtls_psa_external_get_random': 'defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)', + 'mbedtls_psa_platform_get_builtin_key': 'defined(MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS)', + }) + + @staticmethod + def _detect_buffer_parameters(arguments: List[c_parsing_helper.ArgumentInfo], + argument_names: List[str]) -> Iterator[BufferParameter]: + """Detect function arguments that are buffers (pointer, size [,length]).""" + types = ['' if arg.suffix else arg.type for arg in arguments] + # pairs = list of (type_of_arg_N, type_of_arg_N+1) + # where each type_of_arg_X is the empty string if the type is an array + # or there is no argument X. + pairs = enumerate(itertools.zip_longest(types, types[1:], fillvalue='')) + for i, t01 in pairs: + if (t01[0] == 'const uint8_t *' or t01[0] == 'uint8_t *') and \ + t01[1] == 'size_t': + yield BufferParameter(i, not t01[0].startswith('const '), + argument_names[i], argument_names[i+1]) + + @staticmethod + def _write_poison_buffer_parameter(out: typing_util.Writable, + param: BufferParameter, + poison: bool) -> None: + """Write poisoning or unpoisoning code for a buffer parameter. + + Write poisoning code if poison is true, unpoisoning code otherwise. + """ + out.write(' MBEDTLS_TEST_MEMORY_{}({}, {});\n'.format( + 'POISON' if poison else 'UNPOISON', + param.buffer_name, param.size_name + )) + + def _write_poison_buffer_parameters(self, out: typing_util.Writable, + buffer_parameters: List[BufferParameter], + poison: bool) -> None: + """Write poisoning or unpoisoning code for the buffer parameters. + + Write poisoning code if poison is true, unpoisoning code otherwise. + """ + if not buffer_parameters: + return + out.write('#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)\n') + for param in buffer_parameters: + self._write_poison_buffer_parameter(out, param, poison) + out.write('#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */\n') + + @staticmethod + def _parameter_should_be_copied(function_name: str, + _buffer_name: Optional[str]) -> bool: + """Whether the specified buffer argument to a PSA function should be copied. + """ + if function_name == 'mbedtls_psa_inject_entropy': + return False + return True + + def _write_function_call(self, out: typing_util.Writable, + function: c_wrapper_generator.FunctionInfo, + argument_names: List[str]) -> None: + buffer_parameters = list( + param + for param in self._detect_buffer_parameters(function.arguments, + argument_names) + if self._parameter_should_be_copied(function.name, + function.arguments[param.index].name)) + self._write_poison_buffer_parameters(out, buffer_parameters, True) + super()._write_function_call(out, function, argument_names) + self._write_poison_buffer_parameters(out, buffer_parameters, False) + + def _write_prologue(self, out: typing_util.Writable, header: bool) -> None: + super()._write_prologue(out, header) + out.write(""" +#if {} + +#include + +#include +#include +#include +""" + .format(self._CPP_GUARDS)) + + def _write_epilogue(self, out: typing_util.Writable, header: bool) -> None: + out.write(""" +#endif /* {} */ +""" + .format(self._CPP_GUARDS)) + super()._write_epilogue(out, header) + + +class PSALoggingWrapperGenerator(PSAWrapperGenerator, c_wrapper_generator.Logging): + """Generate a C source file containing wrapper functions that log PSA Crypto API calls.""" + + def __init__(self, stream: str) -> None: + super().__init__() + self.set_stream(stream) + + _PRINTF_TYPE_CAST = c_wrapper_generator.Logging._PRINTF_TYPE_CAST.copy() + _PRINTF_TYPE_CAST.update({ + 'mbedtls_svc_key_id_t': 'unsigned', + 'psa_algorithm_t': 'unsigned', + 'psa_drv_slot_number_t': 'unsigned long long', + 'psa_key_derivation_step_t': 'int', + 'psa_key_id_t': 'unsigned', + 'psa_key_slot_number_t': 'unsigned long long', + 'psa_key_lifetime_t': 'unsigned', + 'psa_key_type_t': 'unsigned', + 'psa_key_usage_flags_t': 'unsigned', + 'psa_pake_role_t': 'int', + 'psa_pake_step_t': 'int', + 'psa_status_t': 'int', + }) + + def _printf_parameters(self, typ: str, var: str) -> Tuple[str, List[str]]: + if typ.startswith('const '): + typ = typ[6:] + if typ == 'uint8_t *': + # Skip buffers + return '', [] + if typ.endswith('operation_t *'): + return '', [] + if typ in self._PAKE_STUFF: + return '', [] + if typ == 'psa_key_attributes_t *': + return (var + '={id=%u, lifetime=0x%08x, type=0x%08x, bits=%u, alg=%08x, usage=%08x}', + ['(unsigned) psa_get_key_{}({})'.format(field, var) + for field in ['id', 'lifetime', 'type', 'bits', 'algorithm', 'usage_flags']]) + return super()._printf_parameters(typ, var) + + +DEFAULT_C_OUTPUT_FILE_NAME = 'tests/src/psa_test_wrappers.c' +DEFAULT_H_OUTPUT_FILE_NAME = 'tests/include/test/psa_test_wrappers.h' + +def main() -> None: + parser = argparse.ArgumentParser(description=globals()['__doc__']) + parser.add_argument('--log', + help='Stream to log to (default: no logging code)') + parser.add_argument('--output-c', + metavar='FILENAME', + default=DEFAULT_C_OUTPUT_FILE_NAME, + help=('Output .c file path (default: {}; skip .c output if empty)' + .format(DEFAULT_C_OUTPUT_FILE_NAME))) + parser.add_argument('--output-h', + metavar='FILENAME', + default=DEFAULT_H_OUTPUT_FILE_NAME, + help=('Output .h file path (default: {}; skip .h output if empty)' + .format(DEFAULT_H_OUTPUT_FILE_NAME))) + options = parser.parse_args() + if options.log: + generator = PSALoggingWrapperGenerator(options.log) #type: PSAWrapperGenerator + else: + generator = PSAWrapperGenerator() + generator.gather_data() + if options.output_h: + generator.write_h_file(options.output_h) + if options.output_c: + generator.write_c_file(options.output_c) + +if __name__ == '__main__': + main() diff --git a/tests/src/helpers.c b/tests/src/helpers.c index 2df3ce5b907c..a1e1d459ce88 100644 --- a/tests/src/helpers.c +++ b/tests/src/helpers.c @@ -17,6 +17,10 @@ #include #endif +#if defined(MBEDTLS_TEST_HOOKS) && defined(MBEDTLS_PSA_CRYPTO_C) +#include +#endif + /*----------------------------------------------------------------------------*/ /* Static global variables */ @@ -46,6 +50,12 @@ int mbedtls_test_platform_setup(void) { int ret = 0; +#if defined(MBEDTLS_TEST_HOOKS) && defined(MBEDTLS_PSA_CRYPTO_C) \ + && !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) \ + && defined(MBEDTLS_TEST_MEMORY_CAN_POISON) + mbedtls_poison_test_hooks_setup(); +#endif + #if defined(MBEDTLS_PSA_INJECT_ENTROPY) /* Make sure that injected entropy is present. Otherwise * psa_crypto_init() will fail. This is not necessary for test suites @@ -66,6 +76,12 @@ int mbedtls_test_platform_setup(void) void mbedtls_test_platform_teardown(void) { +#if defined(MBEDTLS_TEST_HOOKS) && defined(MBEDTLS_PSA_CRYPTO_C) \ + && !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) \ + && defined(MBEDTLS_TEST_MEMORY_CAN_POISON) + mbedtls_poison_test_hooks_teardown(); +#endif + #if defined(MBEDTLS_PLATFORM_C) mbedtls_platform_teardown(&platform_ctx); #endif /* MBEDTLS_PLATFORM_C */ diff --git a/tests/src/psa_memory_poisoning_wrappers.c b/tests/src/psa_memory_poisoning_wrappers.c new file mode 100644 index 000000000000..05cba18ee754 --- /dev/null +++ b/tests/src/psa_memory_poisoning_wrappers.c @@ -0,0 +1,31 @@ +/** Helper functions for memory poisoning in tests. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ +#include "test/memory.h" + +#include "psa_crypto_invasive.h" + +#if defined(MBEDTLS_TEST_HOOKS) && defined(MBEDTLS_PSA_CRYPTO_C) \ + && defined(MBEDTLS_TEST_MEMORY_CAN_POISON) + +void mbedtls_poison_test_hooks_setup(void) +{ + psa_input_pre_copy_hook = mbedtls_test_memory_unpoison; + psa_input_post_copy_hook = mbedtls_test_memory_poison; + psa_output_pre_copy_hook = mbedtls_test_memory_unpoison; + psa_output_post_copy_hook = mbedtls_test_memory_poison; +} + +void mbedtls_poison_test_hooks_teardown(void) +{ + psa_input_pre_copy_hook = NULL; + psa_input_post_copy_hook = NULL; + psa_output_pre_copy_hook = NULL; + psa_output_post_copy_hook = NULL; +} + +#endif /* MBEDTLS_TEST_HOOKS && MBEDTLS_PSA_CRYPTO_C && + MBEDTLS_TEST_MEMORY_CAN_POISON */ diff --git a/tests/src/psa_test_wrappers.c b/tests/src/psa_test_wrappers.c new file mode 100644 index 000000000000..e70ffb34af46 --- /dev/null +++ b/tests/src/psa_test_wrappers.c @@ -0,0 +1,880 @@ +/* Automatically generated by generate_psa_wrappers.py, do not edit! */ + +/* Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PSA_CRYPTO_C) && defined(MBEDTLS_TEST_HOOKS) && \ + !defined(RECORD_PSA_STATUS_COVERAGE_LOG) + +#include + +#include +#include +#include + +/* Wrapper for mbedtls_psa_inject_entropy */ +#if defined(MBEDTLS_PSA_INJECT_ENTROPY) +psa_status_t mbedtls_test_wrap_mbedtls_psa_inject_entropy( + const uint8_t *arg0_seed, + size_t arg1_seed_size) +{ + psa_status_t status = (mbedtls_psa_inject_entropy)(arg0_seed, arg1_seed_size); + return status; +} +#endif /* defined(MBEDTLS_PSA_INJECT_ENTROPY) */ + +/* Wrapper for mbedtls_psa_platform_get_builtin_key */ +#if defined(MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS) +psa_status_t mbedtls_test_wrap_mbedtls_psa_platform_get_builtin_key( + mbedtls_svc_key_id_t arg0_key_id, + psa_key_lifetime_t *arg1_lifetime, + psa_drv_slot_number_t *arg2_slot_number) +{ + psa_status_t status = (mbedtls_psa_platform_get_builtin_key)(arg0_key_id, arg1_lifetime, arg2_slot_number); + return status; +} +#endif /* defined(MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS) */ + +/* Wrapper for mbedtls_psa_register_se_key */ +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) +psa_status_t mbedtls_test_wrap_mbedtls_psa_register_se_key( + const psa_key_attributes_t *arg0_attributes) +{ + psa_status_t status = (mbedtls_psa_register_se_key)(arg0_attributes); + return status; +} +#endif /* defined(MBEDTLS_PSA_CRYPTO_SE_C) */ + +/* Wrapper for psa_aead_decrypt */ +psa_status_t mbedtls_test_wrap_psa_aead_decrypt( + mbedtls_svc_key_id_t arg0_key, + psa_algorithm_t arg1_alg, + const uint8_t *arg2_nonce, + size_t arg3_nonce_length, + const uint8_t *arg4_additional_data, + size_t arg5_additional_data_length, + const uint8_t *arg6_ciphertext, + size_t arg7_ciphertext_length, + uint8_t *arg8_plaintext, + size_t arg9_plaintext_size, + size_t *arg10_plaintext_length) +{ +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) + MBEDTLS_TEST_MEMORY_POISON(arg2_nonce, arg3_nonce_length); + MBEDTLS_TEST_MEMORY_POISON(arg4_additional_data, arg5_additional_data_length); + MBEDTLS_TEST_MEMORY_POISON(arg6_ciphertext, arg7_ciphertext_length); + MBEDTLS_TEST_MEMORY_POISON(arg8_plaintext, arg9_plaintext_size); +#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */ + psa_status_t status = (psa_aead_decrypt)(arg0_key, arg1_alg, arg2_nonce, arg3_nonce_length, arg4_additional_data, arg5_additional_data_length, arg6_ciphertext, arg7_ciphertext_length, arg8_plaintext, arg9_plaintext_size, arg10_plaintext_length); +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) + MBEDTLS_TEST_MEMORY_UNPOISON(arg2_nonce, arg3_nonce_length); + MBEDTLS_TEST_MEMORY_UNPOISON(arg4_additional_data, arg5_additional_data_length); + MBEDTLS_TEST_MEMORY_UNPOISON(arg6_ciphertext, arg7_ciphertext_length); + MBEDTLS_TEST_MEMORY_UNPOISON(arg8_plaintext, arg9_plaintext_size); +#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */ + return status; +} + +/* Wrapper for psa_aead_encrypt */ +psa_status_t mbedtls_test_wrap_psa_aead_encrypt( + mbedtls_svc_key_id_t arg0_key, + psa_algorithm_t arg1_alg, + const uint8_t *arg2_nonce, + size_t arg3_nonce_length, + const uint8_t *arg4_additional_data, + size_t arg5_additional_data_length, + const uint8_t *arg6_plaintext, + size_t arg7_plaintext_length, + uint8_t *arg8_ciphertext, + size_t arg9_ciphertext_size, + size_t *arg10_ciphertext_length) +{ +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) + MBEDTLS_TEST_MEMORY_POISON(arg2_nonce, arg3_nonce_length); + MBEDTLS_TEST_MEMORY_POISON(arg4_additional_data, arg5_additional_data_length); + MBEDTLS_TEST_MEMORY_POISON(arg6_plaintext, arg7_plaintext_length); + MBEDTLS_TEST_MEMORY_POISON(arg8_ciphertext, arg9_ciphertext_size); +#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */ + psa_status_t status = (psa_aead_encrypt)(arg0_key, arg1_alg, arg2_nonce, arg3_nonce_length, arg4_additional_data, arg5_additional_data_length, arg6_plaintext, arg7_plaintext_length, arg8_ciphertext, arg9_ciphertext_size, arg10_ciphertext_length); +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) + MBEDTLS_TEST_MEMORY_UNPOISON(arg2_nonce, arg3_nonce_length); + MBEDTLS_TEST_MEMORY_UNPOISON(arg4_additional_data, arg5_additional_data_length); + MBEDTLS_TEST_MEMORY_UNPOISON(arg6_plaintext, arg7_plaintext_length); + MBEDTLS_TEST_MEMORY_UNPOISON(arg8_ciphertext, arg9_ciphertext_size); +#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */ + return status; +} + +/* Wrapper for psa_asymmetric_decrypt */ +psa_status_t mbedtls_test_wrap_psa_asymmetric_decrypt( + mbedtls_svc_key_id_t arg0_key, + psa_algorithm_t arg1_alg, + const uint8_t *arg2_input, + size_t arg3_input_length, + const uint8_t *arg4_salt, + size_t arg5_salt_length, + uint8_t *arg6_output, + size_t arg7_output_size, + size_t *arg8_output_length) +{ +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) + MBEDTLS_TEST_MEMORY_POISON(arg2_input, arg3_input_length); + MBEDTLS_TEST_MEMORY_POISON(arg4_salt, arg5_salt_length); + MBEDTLS_TEST_MEMORY_POISON(arg6_output, arg7_output_size); +#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */ + psa_status_t status = (psa_asymmetric_decrypt)(arg0_key, arg1_alg, arg2_input, arg3_input_length, arg4_salt, arg5_salt_length, arg6_output, arg7_output_size, arg8_output_length); +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) + MBEDTLS_TEST_MEMORY_UNPOISON(arg2_input, arg3_input_length); + MBEDTLS_TEST_MEMORY_UNPOISON(arg4_salt, arg5_salt_length); + MBEDTLS_TEST_MEMORY_UNPOISON(arg6_output, arg7_output_size); +#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */ + return status; +} + +/* Wrapper for psa_asymmetric_encrypt */ +psa_status_t mbedtls_test_wrap_psa_asymmetric_encrypt( + mbedtls_svc_key_id_t arg0_key, + psa_algorithm_t arg1_alg, + const uint8_t *arg2_input, + size_t arg3_input_length, + const uint8_t *arg4_salt, + size_t arg5_salt_length, + uint8_t *arg6_output, + size_t arg7_output_size, + size_t *arg8_output_length) +{ +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) + MBEDTLS_TEST_MEMORY_POISON(arg2_input, arg3_input_length); + MBEDTLS_TEST_MEMORY_POISON(arg4_salt, arg5_salt_length); + MBEDTLS_TEST_MEMORY_POISON(arg6_output, arg7_output_size); +#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */ + psa_status_t status = (psa_asymmetric_encrypt)(arg0_key, arg1_alg, arg2_input, arg3_input_length, arg4_salt, arg5_salt_length, arg6_output, arg7_output_size, arg8_output_length); +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) + MBEDTLS_TEST_MEMORY_UNPOISON(arg2_input, arg3_input_length); + MBEDTLS_TEST_MEMORY_UNPOISON(arg4_salt, arg5_salt_length); + MBEDTLS_TEST_MEMORY_UNPOISON(arg6_output, arg7_output_size); +#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */ + return status; +} + +/* Wrapper for psa_cipher_abort */ +psa_status_t mbedtls_test_wrap_psa_cipher_abort( + psa_cipher_operation_t *arg0_operation) +{ + psa_status_t status = (psa_cipher_abort)(arg0_operation); + return status; +} + +/* Wrapper for psa_cipher_decrypt */ +psa_status_t mbedtls_test_wrap_psa_cipher_decrypt( + mbedtls_svc_key_id_t arg0_key, + psa_algorithm_t arg1_alg, + const uint8_t *arg2_input, + size_t arg3_input_length, + uint8_t *arg4_output, + size_t arg5_output_size, + size_t *arg6_output_length) +{ +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) + MBEDTLS_TEST_MEMORY_POISON(arg2_input, arg3_input_length); + MBEDTLS_TEST_MEMORY_POISON(arg4_output, arg5_output_size); +#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */ + psa_status_t status = (psa_cipher_decrypt)(arg0_key, arg1_alg, arg2_input, arg3_input_length, arg4_output, arg5_output_size, arg6_output_length); +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) + MBEDTLS_TEST_MEMORY_UNPOISON(arg2_input, arg3_input_length); + MBEDTLS_TEST_MEMORY_UNPOISON(arg4_output, arg5_output_size); +#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */ + return status; +} + +/* Wrapper for psa_cipher_decrypt_setup */ +psa_status_t mbedtls_test_wrap_psa_cipher_decrypt_setup( + psa_cipher_operation_t *arg0_operation, + mbedtls_svc_key_id_t arg1_key, + psa_algorithm_t arg2_alg) +{ + psa_status_t status = (psa_cipher_decrypt_setup)(arg0_operation, arg1_key, arg2_alg); + return status; +} + +/* Wrapper for psa_cipher_encrypt */ +psa_status_t mbedtls_test_wrap_psa_cipher_encrypt( + mbedtls_svc_key_id_t arg0_key, + psa_algorithm_t arg1_alg, + const uint8_t *arg2_input, + size_t arg3_input_length, + uint8_t *arg4_output, + size_t arg5_output_size, + size_t *arg6_output_length) +{ +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) + MBEDTLS_TEST_MEMORY_POISON(arg2_input, arg3_input_length); + MBEDTLS_TEST_MEMORY_POISON(arg4_output, arg5_output_size); +#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */ + psa_status_t status = (psa_cipher_encrypt)(arg0_key, arg1_alg, arg2_input, arg3_input_length, arg4_output, arg5_output_size, arg6_output_length); +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) + MBEDTLS_TEST_MEMORY_UNPOISON(arg2_input, arg3_input_length); + MBEDTLS_TEST_MEMORY_UNPOISON(arg4_output, arg5_output_size); +#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */ + return status; +} + +/* Wrapper for psa_cipher_encrypt_setup */ +psa_status_t mbedtls_test_wrap_psa_cipher_encrypt_setup( + psa_cipher_operation_t *arg0_operation, + mbedtls_svc_key_id_t arg1_key, + psa_algorithm_t arg2_alg) +{ + psa_status_t status = (psa_cipher_encrypt_setup)(arg0_operation, arg1_key, arg2_alg); + return status; +} + +/* Wrapper for psa_cipher_finish */ +psa_status_t mbedtls_test_wrap_psa_cipher_finish( + psa_cipher_operation_t *arg0_operation, + uint8_t *arg1_output, + size_t arg2_output_size, + size_t *arg3_output_length) +{ +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) + MBEDTLS_TEST_MEMORY_POISON(arg1_output, arg2_output_size); +#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */ + psa_status_t status = (psa_cipher_finish)(arg0_operation, arg1_output, arg2_output_size, arg3_output_length); +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) + MBEDTLS_TEST_MEMORY_UNPOISON(arg1_output, arg2_output_size); +#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */ + return status; +} + +/* Wrapper for psa_cipher_generate_iv */ +psa_status_t mbedtls_test_wrap_psa_cipher_generate_iv( + psa_cipher_operation_t *arg0_operation, + uint8_t *arg1_iv, + size_t arg2_iv_size, + size_t *arg3_iv_length) +{ +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) + MBEDTLS_TEST_MEMORY_POISON(arg1_iv, arg2_iv_size); +#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */ + psa_status_t status = (psa_cipher_generate_iv)(arg0_operation, arg1_iv, arg2_iv_size, arg3_iv_length); +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) + MBEDTLS_TEST_MEMORY_UNPOISON(arg1_iv, arg2_iv_size); +#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */ + return status; +} + +/* Wrapper for psa_cipher_set_iv */ +psa_status_t mbedtls_test_wrap_psa_cipher_set_iv( + psa_cipher_operation_t *arg0_operation, + const uint8_t *arg1_iv, + size_t arg2_iv_length) +{ +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) + MBEDTLS_TEST_MEMORY_POISON(arg1_iv, arg2_iv_length); +#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */ + psa_status_t status = (psa_cipher_set_iv)(arg0_operation, arg1_iv, arg2_iv_length); +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) + MBEDTLS_TEST_MEMORY_UNPOISON(arg1_iv, arg2_iv_length); +#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */ + return status; +} + +/* Wrapper for psa_cipher_update */ +psa_status_t mbedtls_test_wrap_psa_cipher_update( + psa_cipher_operation_t *arg0_operation, + const uint8_t *arg1_input, + size_t arg2_input_length, + uint8_t *arg3_output, + size_t arg4_output_size, + size_t *arg5_output_length) +{ +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) + MBEDTLS_TEST_MEMORY_POISON(arg1_input, arg2_input_length); + MBEDTLS_TEST_MEMORY_POISON(arg3_output, arg4_output_size); +#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */ + psa_status_t status = (psa_cipher_update)(arg0_operation, arg1_input, arg2_input_length, arg3_output, arg4_output_size, arg5_output_length); +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) + MBEDTLS_TEST_MEMORY_UNPOISON(arg1_input, arg2_input_length); + MBEDTLS_TEST_MEMORY_UNPOISON(arg3_output, arg4_output_size); +#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */ + return status; +} + +/* Wrapper for psa_copy_key */ +psa_status_t mbedtls_test_wrap_psa_copy_key( + mbedtls_svc_key_id_t arg0_source_key, + const psa_key_attributes_t *arg1_attributes, + mbedtls_svc_key_id_t *arg2_target_key) +{ + psa_status_t status = (psa_copy_key)(arg0_source_key, arg1_attributes, arg2_target_key); + return status; +} + +/* Wrapper for psa_crypto_init */ +psa_status_t mbedtls_test_wrap_psa_crypto_init(void) +{ + psa_status_t status = (psa_crypto_init)(); + return status; +} + +/* Wrapper for psa_destroy_key */ +psa_status_t mbedtls_test_wrap_psa_destroy_key( + mbedtls_svc_key_id_t arg0_key) +{ + psa_status_t status = (psa_destroy_key)(arg0_key); + return status; +} + +/* Wrapper for psa_export_key */ +psa_status_t mbedtls_test_wrap_psa_export_key( + mbedtls_svc_key_id_t arg0_key, + uint8_t *arg1_data, + size_t arg2_data_size, + size_t *arg3_data_length) +{ +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) + MBEDTLS_TEST_MEMORY_POISON(arg1_data, arg2_data_size); +#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */ + psa_status_t status = (psa_export_key)(arg0_key, arg1_data, arg2_data_size, arg3_data_length); +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) + MBEDTLS_TEST_MEMORY_UNPOISON(arg1_data, arg2_data_size); +#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */ + return status; +} + +/* Wrapper for psa_export_public_key */ +psa_status_t mbedtls_test_wrap_psa_export_public_key( + mbedtls_svc_key_id_t arg0_key, + uint8_t *arg1_data, + size_t arg2_data_size, + size_t *arg3_data_length) +{ +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) + MBEDTLS_TEST_MEMORY_POISON(arg1_data, arg2_data_size); +#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */ + psa_status_t status = (psa_export_public_key)(arg0_key, arg1_data, arg2_data_size, arg3_data_length); +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) + MBEDTLS_TEST_MEMORY_UNPOISON(arg1_data, arg2_data_size); +#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */ + return status; +} + +/* Wrapper for psa_generate_key */ +psa_status_t mbedtls_test_wrap_psa_generate_key( + const psa_key_attributes_t *arg0_attributes, + mbedtls_svc_key_id_t *arg1_key) +{ + psa_status_t status = (psa_generate_key)(arg0_attributes, arg1_key); + return status; +} + +/* Wrapper for psa_generate_random */ +psa_status_t mbedtls_test_wrap_psa_generate_random( + uint8_t *arg0_output, + size_t arg1_output_size) +{ +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) + MBEDTLS_TEST_MEMORY_POISON(arg0_output, arg1_output_size); +#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */ + psa_status_t status = (psa_generate_random)(arg0_output, arg1_output_size); +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) + MBEDTLS_TEST_MEMORY_UNPOISON(arg0_output, arg1_output_size); +#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */ + return status; +} + +/* Wrapper for psa_get_key_attributes */ +psa_status_t mbedtls_test_wrap_psa_get_key_attributes( + mbedtls_svc_key_id_t arg0_key, + psa_key_attributes_t *arg1_attributes) +{ + psa_status_t status = (psa_get_key_attributes)(arg0_key, arg1_attributes); + return status; +} + +/* Wrapper for psa_hash_abort */ +psa_status_t mbedtls_test_wrap_psa_hash_abort( + psa_hash_operation_t *arg0_operation) +{ + psa_status_t status = (psa_hash_abort)(arg0_operation); + return status; +} + +/* Wrapper for psa_hash_clone */ +psa_status_t mbedtls_test_wrap_psa_hash_clone( + const psa_hash_operation_t *arg0_source_operation, + psa_hash_operation_t *arg1_target_operation) +{ + psa_status_t status = (psa_hash_clone)(arg0_source_operation, arg1_target_operation); + return status; +} + +/* Wrapper for psa_hash_compare */ +psa_status_t mbedtls_test_wrap_psa_hash_compare( + psa_algorithm_t arg0_alg, + const uint8_t *arg1_input, + size_t arg2_input_length, + const uint8_t *arg3_hash, + size_t arg4_hash_length) +{ +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) + MBEDTLS_TEST_MEMORY_POISON(arg1_input, arg2_input_length); + MBEDTLS_TEST_MEMORY_POISON(arg3_hash, arg4_hash_length); +#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */ + psa_status_t status = (psa_hash_compare)(arg0_alg, arg1_input, arg2_input_length, arg3_hash, arg4_hash_length); +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) + MBEDTLS_TEST_MEMORY_UNPOISON(arg1_input, arg2_input_length); + MBEDTLS_TEST_MEMORY_UNPOISON(arg3_hash, arg4_hash_length); +#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */ + return status; +} + +/* Wrapper for psa_hash_compute */ +psa_status_t mbedtls_test_wrap_psa_hash_compute( + psa_algorithm_t arg0_alg, + const uint8_t *arg1_input, + size_t arg2_input_length, + uint8_t *arg3_hash, + size_t arg4_hash_size, + size_t *arg5_hash_length) +{ +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) + MBEDTLS_TEST_MEMORY_POISON(arg1_input, arg2_input_length); + MBEDTLS_TEST_MEMORY_POISON(arg3_hash, arg4_hash_size); +#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */ + psa_status_t status = (psa_hash_compute)(arg0_alg, arg1_input, arg2_input_length, arg3_hash, arg4_hash_size, arg5_hash_length); +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) + MBEDTLS_TEST_MEMORY_UNPOISON(arg1_input, arg2_input_length); + MBEDTLS_TEST_MEMORY_UNPOISON(arg3_hash, arg4_hash_size); +#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */ + return status; +} + +/* Wrapper for psa_hash_finish */ +psa_status_t mbedtls_test_wrap_psa_hash_finish( + psa_hash_operation_t *arg0_operation, + uint8_t *arg1_hash, + size_t arg2_hash_size, + size_t *arg3_hash_length) +{ +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) + MBEDTLS_TEST_MEMORY_POISON(arg1_hash, arg2_hash_size); +#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */ + psa_status_t status = (psa_hash_finish)(arg0_operation, arg1_hash, arg2_hash_size, arg3_hash_length); +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) + MBEDTLS_TEST_MEMORY_UNPOISON(arg1_hash, arg2_hash_size); +#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */ + return status; +} + +/* Wrapper for psa_hash_setup */ +psa_status_t mbedtls_test_wrap_psa_hash_setup( + psa_hash_operation_t *arg0_operation, + psa_algorithm_t arg1_alg) +{ + psa_status_t status = (psa_hash_setup)(arg0_operation, arg1_alg); + return status; +} + +/* Wrapper for psa_hash_update */ +psa_status_t mbedtls_test_wrap_psa_hash_update( + psa_hash_operation_t *arg0_operation, + const uint8_t *arg1_input, + size_t arg2_input_length) +{ +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) + MBEDTLS_TEST_MEMORY_POISON(arg1_input, arg2_input_length); +#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */ + psa_status_t status = (psa_hash_update)(arg0_operation, arg1_input, arg2_input_length); +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) + MBEDTLS_TEST_MEMORY_UNPOISON(arg1_input, arg2_input_length); +#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */ + return status; +} + +/* Wrapper for psa_hash_verify */ +psa_status_t mbedtls_test_wrap_psa_hash_verify( + psa_hash_operation_t *arg0_operation, + const uint8_t *arg1_hash, + size_t arg2_hash_length) +{ +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) + MBEDTLS_TEST_MEMORY_POISON(arg1_hash, arg2_hash_length); +#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */ + psa_status_t status = (psa_hash_verify)(arg0_operation, arg1_hash, arg2_hash_length); +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) + MBEDTLS_TEST_MEMORY_UNPOISON(arg1_hash, arg2_hash_length); +#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */ + return status; +} + +/* Wrapper for psa_import_key */ +psa_status_t mbedtls_test_wrap_psa_import_key( + const psa_key_attributes_t *arg0_attributes, + const uint8_t *arg1_data, + size_t arg2_data_length, + mbedtls_svc_key_id_t *arg3_key) +{ +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) + MBEDTLS_TEST_MEMORY_POISON(arg1_data, arg2_data_length); +#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */ + psa_status_t status = (psa_import_key)(arg0_attributes, arg1_data, arg2_data_length, arg3_key); +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) + MBEDTLS_TEST_MEMORY_UNPOISON(arg1_data, arg2_data_length); +#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */ + return status; +} + +/* Wrapper for psa_key_derivation_abort */ +psa_status_t mbedtls_test_wrap_psa_key_derivation_abort( + psa_key_derivation_operation_t *arg0_operation) +{ + psa_status_t status = (psa_key_derivation_abort)(arg0_operation); + return status; +} + +/* Wrapper for psa_key_derivation_get_capacity */ +psa_status_t mbedtls_test_wrap_psa_key_derivation_get_capacity( + const psa_key_derivation_operation_t *arg0_operation, + size_t *arg1_capacity) +{ + psa_status_t status = (psa_key_derivation_get_capacity)(arg0_operation, arg1_capacity); + return status; +} + +/* Wrapper for psa_key_derivation_input_bytes */ +psa_status_t mbedtls_test_wrap_psa_key_derivation_input_bytes( + psa_key_derivation_operation_t *arg0_operation, + psa_key_derivation_step_t arg1_step, + const uint8_t *arg2_data, + size_t arg3_data_length) +{ +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) + MBEDTLS_TEST_MEMORY_POISON(arg2_data, arg3_data_length); +#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */ + psa_status_t status = (psa_key_derivation_input_bytes)(arg0_operation, arg1_step, arg2_data, arg3_data_length); +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) + MBEDTLS_TEST_MEMORY_UNPOISON(arg2_data, arg3_data_length); +#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */ + return status; +} + +/* Wrapper for psa_key_derivation_input_key */ +psa_status_t mbedtls_test_wrap_psa_key_derivation_input_key( + psa_key_derivation_operation_t *arg0_operation, + psa_key_derivation_step_t arg1_step, + mbedtls_svc_key_id_t arg2_key) +{ + psa_status_t status = (psa_key_derivation_input_key)(arg0_operation, arg1_step, arg2_key); + return status; +} + +/* Wrapper for psa_key_derivation_key_agreement */ +psa_status_t mbedtls_test_wrap_psa_key_derivation_key_agreement( + psa_key_derivation_operation_t *arg0_operation, + psa_key_derivation_step_t arg1_step, + mbedtls_svc_key_id_t arg2_private_key, + const uint8_t *arg3_peer_key, + size_t arg4_peer_key_length) +{ +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) + MBEDTLS_TEST_MEMORY_POISON(arg3_peer_key, arg4_peer_key_length); +#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */ + psa_status_t status = (psa_key_derivation_key_agreement)(arg0_operation, arg1_step, arg2_private_key, arg3_peer_key, arg4_peer_key_length); +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) + MBEDTLS_TEST_MEMORY_UNPOISON(arg3_peer_key, arg4_peer_key_length); +#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */ + return status; +} + +/* Wrapper for psa_key_derivation_output_bytes */ +psa_status_t mbedtls_test_wrap_psa_key_derivation_output_bytes( + psa_key_derivation_operation_t *arg0_operation, + uint8_t *arg1_output, + size_t arg2_output_length) +{ +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) + MBEDTLS_TEST_MEMORY_POISON(arg1_output, arg2_output_length); +#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */ + psa_status_t status = (psa_key_derivation_output_bytes)(arg0_operation, arg1_output, arg2_output_length); +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) + MBEDTLS_TEST_MEMORY_UNPOISON(arg1_output, arg2_output_length); +#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */ + return status; +} + +/* Wrapper for psa_key_derivation_output_key */ +psa_status_t mbedtls_test_wrap_psa_key_derivation_output_key( + const psa_key_attributes_t *arg0_attributes, + psa_key_derivation_operation_t *arg1_operation, + mbedtls_svc_key_id_t *arg2_key) +{ + psa_status_t status = (psa_key_derivation_output_key)(arg0_attributes, arg1_operation, arg2_key); + return status; +} + +/* Wrapper for psa_key_derivation_set_capacity */ +psa_status_t mbedtls_test_wrap_psa_key_derivation_set_capacity( + psa_key_derivation_operation_t *arg0_operation, + size_t arg1_capacity) +{ + psa_status_t status = (psa_key_derivation_set_capacity)(arg0_operation, arg1_capacity); + return status; +} + +/* Wrapper for psa_key_derivation_setup */ +psa_status_t mbedtls_test_wrap_psa_key_derivation_setup( + psa_key_derivation_operation_t *arg0_operation, + psa_algorithm_t arg1_alg) +{ + psa_status_t status = (psa_key_derivation_setup)(arg0_operation, arg1_alg); + return status; +} + +/* Wrapper for psa_mac_abort */ +psa_status_t mbedtls_test_wrap_psa_mac_abort( + psa_mac_operation_t *arg0_operation) +{ + psa_status_t status = (psa_mac_abort)(arg0_operation); + return status; +} + +/* Wrapper for psa_mac_compute */ +psa_status_t mbedtls_test_wrap_psa_mac_compute( + mbedtls_svc_key_id_t arg0_key, + psa_algorithm_t arg1_alg, + const uint8_t *arg2_input, + size_t arg3_input_length, + uint8_t *arg4_mac, + size_t arg5_mac_size, + size_t *arg6_mac_length) +{ +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) + MBEDTLS_TEST_MEMORY_POISON(arg2_input, arg3_input_length); + MBEDTLS_TEST_MEMORY_POISON(arg4_mac, arg5_mac_size); +#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */ + psa_status_t status = (psa_mac_compute)(arg0_key, arg1_alg, arg2_input, arg3_input_length, arg4_mac, arg5_mac_size, arg6_mac_length); +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) + MBEDTLS_TEST_MEMORY_UNPOISON(arg2_input, arg3_input_length); + MBEDTLS_TEST_MEMORY_UNPOISON(arg4_mac, arg5_mac_size); +#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */ + return status; +} + +/* Wrapper for psa_mac_sign_finish */ +psa_status_t mbedtls_test_wrap_psa_mac_sign_finish( + psa_mac_operation_t *arg0_operation, + uint8_t *arg1_mac, + size_t arg2_mac_size, + size_t *arg3_mac_length) +{ +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) + MBEDTLS_TEST_MEMORY_POISON(arg1_mac, arg2_mac_size); +#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */ + psa_status_t status = (psa_mac_sign_finish)(arg0_operation, arg1_mac, arg2_mac_size, arg3_mac_length); +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) + MBEDTLS_TEST_MEMORY_UNPOISON(arg1_mac, arg2_mac_size); +#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */ + return status; +} + +/* Wrapper for psa_mac_sign_setup */ +psa_status_t mbedtls_test_wrap_psa_mac_sign_setup( + psa_mac_operation_t *arg0_operation, + mbedtls_svc_key_id_t arg1_key, + psa_algorithm_t arg2_alg) +{ + psa_status_t status = (psa_mac_sign_setup)(arg0_operation, arg1_key, arg2_alg); + return status; +} + +/* Wrapper for psa_mac_update */ +psa_status_t mbedtls_test_wrap_psa_mac_update( + psa_mac_operation_t *arg0_operation, + const uint8_t *arg1_input, + size_t arg2_input_length) +{ +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) + MBEDTLS_TEST_MEMORY_POISON(arg1_input, arg2_input_length); +#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */ + psa_status_t status = (psa_mac_update)(arg0_operation, arg1_input, arg2_input_length); +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) + MBEDTLS_TEST_MEMORY_UNPOISON(arg1_input, arg2_input_length); +#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */ + return status; +} + +/* Wrapper for psa_mac_verify */ +psa_status_t mbedtls_test_wrap_psa_mac_verify( + mbedtls_svc_key_id_t arg0_key, + psa_algorithm_t arg1_alg, + const uint8_t *arg2_input, + size_t arg3_input_length, + const uint8_t *arg4_mac, + size_t arg5_mac_length) +{ +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) + MBEDTLS_TEST_MEMORY_POISON(arg2_input, arg3_input_length); + MBEDTLS_TEST_MEMORY_POISON(arg4_mac, arg5_mac_length); +#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */ + psa_status_t status = (psa_mac_verify)(arg0_key, arg1_alg, arg2_input, arg3_input_length, arg4_mac, arg5_mac_length); +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) + MBEDTLS_TEST_MEMORY_UNPOISON(arg2_input, arg3_input_length); + MBEDTLS_TEST_MEMORY_UNPOISON(arg4_mac, arg5_mac_length); +#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */ + return status; +} + +/* Wrapper for psa_mac_verify_finish */ +psa_status_t mbedtls_test_wrap_psa_mac_verify_finish( + psa_mac_operation_t *arg0_operation, + const uint8_t *arg1_mac, + size_t arg2_mac_length) +{ +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) + MBEDTLS_TEST_MEMORY_POISON(arg1_mac, arg2_mac_length); +#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */ + psa_status_t status = (psa_mac_verify_finish)(arg0_operation, arg1_mac, arg2_mac_length); +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) + MBEDTLS_TEST_MEMORY_UNPOISON(arg1_mac, arg2_mac_length); +#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */ + return status; +} + +/* Wrapper for psa_mac_verify_setup */ +psa_status_t mbedtls_test_wrap_psa_mac_verify_setup( + psa_mac_operation_t *arg0_operation, + mbedtls_svc_key_id_t arg1_key, + psa_algorithm_t arg2_alg) +{ + psa_status_t status = (psa_mac_verify_setup)(arg0_operation, arg1_key, arg2_alg); + return status; +} + +/* Wrapper for psa_purge_key */ +psa_status_t mbedtls_test_wrap_psa_purge_key( + mbedtls_svc_key_id_t arg0_key) +{ + psa_status_t status = (psa_purge_key)(arg0_key); + return status; +} + +/* Wrapper for psa_raw_key_agreement */ +psa_status_t mbedtls_test_wrap_psa_raw_key_agreement( + psa_algorithm_t arg0_alg, + mbedtls_svc_key_id_t arg1_private_key, + const uint8_t *arg2_peer_key, + size_t arg3_peer_key_length, + uint8_t *arg4_output, + size_t arg5_output_size, + size_t *arg6_output_length) +{ +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) + MBEDTLS_TEST_MEMORY_POISON(arg2_peer_key, arg3_peer_key_length); + MBEDTLS_TEST_MEMORY_POISON(arg4_output, arg5_output_size); +#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */ + psa_status_t status = (psa_raw_key_agreement)(arg0_alg, arg1_private_key, arg2_peer_key, arg3_peer_key_length, arg4_output, arg5_output_size, arg6_output_length); +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) + MBEDTLS_TEST_MEMORY_UNPOISON(arg2_peer_key, arg3_peer_key_length); + MBEDTLS_TEST_MEMORY_UNPOISON(arg4_output, arg5_output_size); +#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */ + return status; +} + +/* Wrapper for psa_sign_hash */ +psa_status_t mbedtls_test_wrap_psa_sign_hash( + mbedtls_svc_key_id_t arg0_key, + psa_algorithm_t arg1_alg, + const uint8_t *arg2_hash, + size_t arg3_hash_length, + uint8_t *arg4_signature, + size_t arg5_signature_size, + size_t *arg6_signature_length) +{ +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) + MBEDTLS_TEST_MEMORY_POISON(arg2_hash, arg3_hash_length); + MBEDTLS_TEST_MEMORY_POISON(arg4_signature, arg5_signature_size); +#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */ + psa_status_t status = (psa_sign_hash)(arg0_key, arg1_alg, arg2_hash, arg3_hash_length, arg4_signature, arg5_signature_size, arg6_signature_length); +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) + MBEDTLS_TEST_MEMORY_UNPOISON(arg2_hash, arg3_hash_length); + MBEDTLS_TEST_MEMORY_UNPOISON(arg4_signature, arg5_signature_size); +#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */ + return status; +} + +/* Wrapper for psa_sign_message */ +psa_status_t mbedtls_test_wrap_psa_sign_message( + mbedtls_svc_key_id_t arg0_key, + psa_algorithm_t arg1_alg, + const uint8_t *arg2_input, + size_t arg3_input_length, + uint8_t *arg4_signature, + size_t arg5_signature_size, + size_t *arg6_signature_length) +{ +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) + MBEDTLS_TEST_MEMORY_POISON(arg2_input, arg3_input_length); + MBEDTLS_TEST_MEMORY_POISON(arg4_signature, arg5_signature_size); +#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */ + psa_status_t status = (psa_sign_message)(arg0_key, arg1_alg, arg2_input, arg3_input_length, arg4_signature, arg5_signature_size, arg6_signature_length); +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) + MBEDTLS_TEST_MEMORY_UNPOISON(arg2_input, arg3_input_length); + MBEDTLS_TEST_MEMORY_UNPOISON(arg4_signature, arg5_signature_size); +#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */ + return status; +} + +/* Wrapper for psa_verify_hash */ +psa_status_t mbedtls_test_wrap_psa_verify_hash( + mbedtls_svc_key_id_t arg0_key, + psa_algorithm_t arg1_alg, + const uint8_t *arg2_hash, + size_t arg3_hash_length, + const uint8_t *arg4_signature, + size_t arg5_signature_length) +{ +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) + MBEDTLS_TEST_MEMORY_POISON(arg2_hash, arg3_hash_length); + MBEDTLS_TEST_MEMORY_POISON(arg4_signature, arg5_signature_length); +#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */ + psa_status_t status = (psa_verify_hash)(arg0_key, arg1_alg, arg2_hash, arg3_hash_length, arg4_signature, arg5_signature_length); +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) + MBEDTLS_TEST_MEMORY_UNPOISON(arg2_hash, arg3_hash_length); + MBEDTLS_TEST_MEMORY_UNPOISON(arg4_signature, arg5_signature_length); +#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */ + return status; +} + +/* Wrapper for psa_verify_message */ +psa_status_t mbedtls_test_wrap_psa_verify_message( + mbedtls_svc_key_id_t arg0_key, + psa_algorithm_t arg1_alg, + const uint8_t *arg2_input, + size_t arg3_input_length, + const uint8_t *arg4_signature, + size_t arg5_signature_length) +{ +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) + MBEDTLS_TEST_MEMORY_POISON(arg2_input, arg3_input_length); + MBEDTLS_TEST_MEMORY_POISON(arg4_signature, arg5_signature_length); +#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */ + psa_status_t status = (psa_verify_message)(arg0_key, arg1_alg, arg2_input, arg3_input_length, arg4_signature, arg5_signature_length); +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) + MBEDTLS_TEST_MEMORY_UNPOISON(arg2_input, arg3_input_length); + MBEDTLS_TEST_MEMORY_UNPOISON(arg4_signature, arg5_signature_length); +#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */ + return status; +} + +#endif /* defined(MBEDTLS_PSA_CRYPTO_C) && defined(MBEDTLS_TEST_HOOKS) && \ + !defined(RECORD_PSA_STATUS_COVERAGE_LOG) */ + +/* End of automatically generated file. */ diff --git a/tests/src/test_memory.c b/tests/src/test_memory.c new file mode 100644 index 000000000000..9da7f20a36ce --- /dev/null +++ b/tests/src/test_memory.c @@ -0,0 +1,60 @@ +/** + * \file memory.c + * + * \brief Helper functions related to testing memory management. + */ + +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + */ + +#include +#include +#include + +#if defined(MBEDTLS_TEST_MEMORY_CAN_POISON) +#include +#include +#endif + +#if defined(MBEDTLS_TEST_MEMORY_CAN_POISON) + +unsigned int mbedtls_test_memory_poisoning_count = 0; + +static void align_for_asan(const unsigned char **p_ptr, size_t *p_size) +{ + uintptr_t start = (uintptr_t) *p_ptr; + uintptr_t end = start + (uintptr_t) *p_size; + /* ASan can only poison regions with 8-byte alignment, and only poisons a + * region if it's fully within the requested range. We want to poison the + * whole requested region and don't mind a few extra bytes. Therefore, + * align start down to an 8-byte boundary, and end up to an 8-byte + * boundary. */ + start = start & ~(uintptr_t) 7; + end = (end + 7) & ~(uintptr_t) 7; + *p_ptr = (const unsigned char *) start; + *p_size = end - start; +} + +void mbedtls_test_memory_poison(const unsigned char *ptr, size_t size) +{ + if (mbedtls_test_memory_poisoning_count == 0) { + return; + } + if (size == 0) { + return; + } + align_for_asan(&ptr, &size); + __asan_poison_memory_region(ptr, size); +} + +void mbedtls_test_memory_unpoison(const unsigned char *ptr, size_t size) +{ + if (size == 0) { + return; + } + align_for_asan(&ptr, &size); + __asan_unpoison_memory_region(ptr, size); +} +#endif /* Memory poisoning */ diff --git a/tests/suites/test_suite_debug.data b/tests/suites/test_suite_debug.data index 87ec67c8ce39..0b88695623cd 100644 --- a/tests/suites/test_suite_debug.data +++ b/tests/suites/test_suite_debug.data @@ -67,4 +67,10 @@ depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_BASE64_C:MBEDTLS_ECDSA_C:MBEDTLS_ECP_C:MB mbedtls_debug_print_crt:"data_files/test-ca2.crt":"MyFile":999:"PREFIX_":"MyFile(0999)\: PREFIX_ #1\:\nMyFile(0999)\: cert. version \: 3\nMyFile(0999)\: serial number \: C1\:43\:E2\:7E\:62\:43\:CC\:E8\nMyFile(0999)\: issuer name \: C=NL, O=PolarSSL, CN=Polarssl Test EC CA\nMyFile(0999)\: subject name \: C=NL, O=PolarSSL, CN=Polarssl Test EC CA\nMyFile(0999)\: issued on \: 2019-02-10 14\:44\:00\nMyFile(0999)\: expires on \: 2029-02-10 14\:44\:00\nMyFile(0999)\: signed using \: ECDSA with SHA256\nMyFile(0999)\: EC key size \: 384 bits\nMyFile(0999)\: basic constraints \: CA=true\nMyFile(0999)\: value of 'crt->eckey.Q(X)' (384 bits) is\:\nMyFile(0999)\: c3 da 2b 34 41 37 58 2f 87 56 fe fc 89 ba 29 43\nMyFile(0999)\: 4b 4e e0 6e c3 0e 57 53 33 39 58 d4 52 b4 91 95\nMyFile(0999)\: 39 0b 23 df 5f 17 24 62 48 fc 1a 95 29 ce 2c 2d\nMyFile(0999)\: value of 'crt->eckey.Q(Y)' (384 bits) is\:\nMyFile(0999)\: 87 c2 88 52 80 af d6 6a ab 21 dd b8 d3 1c 6e 58\nMyFile(0999)\: b8 ca e8 b2 69 8e f3 41 ad 29 c3 b4 5f 75 a7 47\nMyFile(0999)\: 6f d5 19 29 55 69 9a 53 3b 20 b4 66 16 60 33 1e\n" Check mbedtls_calloc overallocation +# This test case exercises an integer overflow in calloc. Under Asan, with +# a modern Clang, this triggers an ASan/MSan/TSan complaint. The complaint +# can be avoided with e.g. ASAN_OPTIONS=allocator_may_return_null=1, +# but this has to be set in the environment before the program starts, +# and could hide other errors. +depends_on:!MBEDTLS_TEST_HAVE_ASAN:!MBEDTLS_TEST_HAVE_MSAN:!MBEDTLS_TEST_HAVE_TSAN check_mbedtls_calloc_overallocation:1:1 diff --git a/tests/suites/test_suite_psa_crypto.data b/tests/suites/test_suite_psa_crypto.data index 718b10c5dca3..1ce38095b63f 100644 --- a/tests/suites/test_suite_psa_crypto.data +++ b/tests/suites/test_suite_psa_crypto.data @@ -1971,6 +1971,11 @@ PSA symmetric encrypt/decrypt multipart: AES-CBC-nopad, 16 bytes, good depends_on:PSA_WANT_ALG_CBC_NO_PADDING:PSA_WANT_KEY_TYPE_AES cipher_verify_output_multipart:PSA_ALG_CBC_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"6bc1bee22e409f96e93d7e117393172a":16 +# Encrypt 48 bytes total, initially 16. This forces both calls to update() to output data. +PSA symmetric encrypt/decrypt multipart: AES-CBC-nopad, 48 bytes, good +depends_on:PSA_WANT_ALG_CBC_NO_PADDING:PSA_WANT_KEY_TYPE_AES +cipher_verify_output_multipart:PSA_ALG_CBC_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"6bc1bee22e409f96e93d7e117393172a6bc1bee22e409f96e93d7e117393172a6bc1bee22e409f96e93d7e117393172a":16 + PSA symmetric encrypt/decrypt multipart: AES-CBC-PKCS#7, 16 bytes depends_on:PSA_WANT_ALG_CBC_PKCS7:PSA_WANT_KEY_TYPE_AES cipher_verify_output_multipart:PSA_ALG_CBC_PKCS7:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"6bc1bee22e409f96e93d7e117393172a":16 diff --git a/tests/suites/test_suite_psa_crypto.function b/tests/suites/test_suite_psa_crypto.function index 21b768bd3abb..02b30d22255a 100644 --- a/tests/suites/test_suite_psa_crypto.function +++ b/tests/suites/test_suite_psa_crypto.function @@ -13,6 +13,8 @@ #include "psa/crypto.h" #include "psa_crypto_slot_management.h" +#include "psa_crypto_core.h" + #include "test/asn1_helpers.h" #include "test/psa_crypto_helpers.h" #include "test/psa_exercise_key.h" @@ -3289,7 +3291,8 @@ void cipher_verify_output_multipart(int alg_arg, PSA_ASSERT(psa_cipher_update(&operation1, input->x + first_part_size, input->len - first_part_size, - output1, output1_buffer_size, + output1 + output1_length, + output1_buffer_size - output1_length, &function_output_length)); TEST_LE_U(function_output_length, PSA_CIPHER_UPDATE_OUTPUT_SIZE(key_type, @@ -3335,7 +3338,8 @@ void cipher_verify_output_multipart(int alg_arg, PSA_ASSERT(psa_cipher_update(&operation2, output1 + first_part_size, output1_length - first_part_size, - output2, output2_buffer_size, + output2 + output2_length, + output2_buffer_size - output2_length, &function_output_length)); TEST_LE_U(function_output_length, PSA_CIPHER_UPDATE_OUTPUT_SIZE(key_type, diff --git a/tests/suites/test_suite_psa_crypto_driver_wrappers.function b/tests/suites/test_suite_psa_crypto_driver_wrappers.function index b789908d0f5a..0394735aab5a 100644 --- a/tests/suites/test_suite_psa_crypto_driver_wrappers.function +++ b/tests/suites/test_suite_psa_crypto_driver_wrappers.function @@ -920,14 +920,7 @@ void cipher_entry_points(int alg_arg, int key_type_arg, output, output_buffer_size, &function_output_length); TEST_EQUAL(mbedtls_test_driver_cipher_hooks.hits, 1); TEST_EQUAL(status, PSA_ERROR_GENERIC_ERROR); - /* - * Check that the output buffer is still in the same state. - * This will fail if the output buffer is used by the core to pass the IV - * it generated to the driver (and is not restored). - */ - for (size_t i = 0; i < output_buffer_size; i++) { - TEST_EQUAL(output[i], 0xa5); - } + mbedtls_test_driver_cipher_hooks.hits = 0; /* Test setup call, encrypt */ @@ -990,14 +983,6 @@ void cipher_entry_points(int alg_arg, int key_type_arg, /* When generating the IV fails, it should call abort too */ TEST_EQUAL(mbedtls_test_driver_cipher_hooks.hits, 2); TEST_EQUAL(status, mbedtls_test_driver_cipher_hooks.forced_status); - /* - * Check that the output buffer is still in the same state. - * This will fail if the output buffer is used by the core to pass the IV - * it generated to the driver (and is not restored). - */ - for (size_t i = 0; i < 16; i++) { - TEST_EQUAL(output[i], 0xa5); - } /* Failure should prevent further operations from executing on the driver */ mbedtls_test_driver_cipher_hooks.hits = 0; status = psa_cipher_update(&operation, diff --git a/tests/suites/test_suite_psa_crypto_memory.data b/tests/suites/test_suite_psa_crypto_memory.data new file mode 100644 index 000000000000..2a828f573ab2 --- /dev/null +++ b/tests/suites/test_suite_psa_crypto_memory.data @@ -0,0 +1,62 @@ +PSA input buffer copy: straightforward copy +copy_input:20:20:PSA_SUCCESS + +PSA input buffer copy: copy buffer larger than required +copy_input:10:20:PSA_SUCCESS + +PSA input buffer copy: copy buffer too small +copy_input:20:10:PSA_ERROR_CORRUPTION_DETECTED + +PSA input buffer copy: zero-length source buffer +copy_input:0:10:PSA_SUCCESS + +PSA input buffer copy: zero-length both buffers +copy_input:0:0:PSA_SUCCESS + +PSA output buffer copy: straightforward copy +copy_output:20:20:PSA_SUCCESS + +PSA output buffer copy: output buffer larger than required +copy_output:10:20:PSA_SUCCESS + +PSA output buffer copy: output buffer too small +copy_output:20:10:PSA_ERROR_BUFFER_TOO_SMALL + +PSA output buffer copy: zero-length source buffer +copy_output:0:10:PSA_SUCCESS + +PSA output buffer copy: zero-length both buffers +copy_output:0:0:PSA_SUCCESS + +PSA crypto local input alloc +local_input_alloc:200:PSA_SUCCESS + +PSA crypto local input alloc, NULL buffer +local_input_alloc:0:PSA_SUCCESS + +PSA crypto local input free +local_input_free:200 + +PSA crypto local input free, NULL buffer +local_input_free:0 + +PSA crypto local input round-trip +local_input_round_trip + +PSA crypto local output alloc +local_output_alloc:200:PSA_SUCCESS + +PSA crypto local output alloc, NULL buffer +local_output_alloc:0:PSA_SUCCESS + +PSA crypto local output free +local_output_free:200:0:PSA_SUCCESS + +PSA crypto local output free, NULL buffer +local_output_free:0:0:PSA_SUCCESS + +PSA crypto local output free, NULL original buffer +local_output_free:200:1:PSA_ERROR_CORRUPTION_DETECTED + +PSA crypto local output round-trip +local_output_round_trip diff --git a/tests/suites/test_suite_psa_crypto_memory.function b/tests/suites/test_suite_psa_crypto_memory.function new file mode 100644 index 000000000000..55c00921b2f1 --- /dev/null +++ b/tests/suites/test_suite_psa_crypto_memory.function @@ -0,0 +1,258 @@ +/* BEGIN_HEADER */ +#include + +#include "common.h" + +#include "psa/crypto.h" + +#include "psa_crypto_core.h" +#include "psa_crypto_invasive.h" + +#include "test/psa_crypto_helpers.h" +#include "test/memory.h" + +/* Helper to fill a buffer with a data pattern. The pattern is not + * important, it just allows a basic check that the correct thing has + * been written, in a way that will detect an error in offset. */ +static void fill_buffer_pattern(uint8_t *buffer, size_t len) +{ + for (size_t i = 0; i < len; i++) { + buffer[i] = (uint8_t) (i % 256); + } +} +/* END_HEADER */ + +/* BEGIN_DEPENDENCIES + * depends_on:MBEDTLS_PSA_CRYPTO_C:MBEDTLS_TEST_HOOKS + * END_DEPENDENCIES + */ + +/* BEGIN_CASE */ +void copy_input(int src_len, int dst_len, psa_status_t exp_status) +{ + uint8_t *src_buffer = NULL; + uint8_t *dst_buffer = NULL; + psa_status_t status; + + TEST_CALLOC(src_buffer, src_len); + TEST_CALLOC(dst_buffer, dst_len); + + fill_buffer_pattern(src_buffer, src_len); + + status = psa_crypto_copy_input(src_buffer, src_len, dst_buffer, dst_len); + TEST_EQUAL(status, exp_status); + + if (exp_status == PSA_SUCCESS) { + MBEDTLS_TEST_MEMORY_UNPOISON(src_buffer, src_len); + /* Note: We compare the first src_len bytes of each buffer, as this is what was copied. */ + TEST_MEMORY_COMPARE(src_buffer, src_len, dst_buffer, src_len); + } + +exit: + mbedtls_free(src_buffer); + mbedtls_free(dst_buffer); +} +/* END_CASE */ + +/* BEGIN_CASE */ +void copy_output(int src_len, int dst_len, psa_status_t exp_status) +{ + uint8_t *src_buffer = NULL; + uint8_t *dst_buffer = NULL; + psa_status_t status; + + TEST_CALLOC(src_buffer, src_len); + TEST_CALLOC(dst_buffer, dst_len); + + fill_buffer_pattern(src_buffer, src_len); + + status = psa_crypto_copy_output(src_buffer, src_len, dst_buffer, dst_len); + TEST_EQUAL(status, exp_status); + + if (exp_status == PSA_SUCCESS) { + MBEDTLS_TEST_MEMORY_UNPOISON(dst_buffer, dst_len); + /* Note: We compare the first src_len bytes of each buffer, as this is what was copied. */ + TEST_MEMORY_COMPARE(src_buffer, src_len, dst_buffer, src_len); + } + +exit: + mbedtls_free(src_buffer); + mbedtls_free(dst_buffer); +} +/* END_CASE */ + +/* BEGIN_CASE */ +void local_input_alloc(int input_len, psa_status_t exp_status) +{ + uint8_t *input = NULL; + psa_crypto_local_input_t local_input; + psa_status_t status; + + local_input.buffer = NULL; + + TEST_CALLOC(input, input_len); + fill_buffer_pattern(input, input_len); + + status = psa_crypto_local_input_alloc(input, input_len, &local_input); + TEST_EQUAL(status, exp_status); + + if (exp_status == PSA_SUCCESS) { + MBEDTLS_TEST_MEMORY_UNPOISON(input, input_len); + if (input_len != 0) { + TEST_ASSERT(local_input.buffer != input); + } + TEST_MEMORY_COMPARE(input, input_len, + local_input.buffer, local_input.length); + } + +exit: + mbedtls_free(local_input.buffer); + mbedtls_free(input); +} +/* END_CASE */ + +/* BEGIN_CASE */ +void local_input_free(int input_len) +{ + psa_crypto_local_input_t local_input; + + local_input.buffer = NULL; + local_input.length = input_len; + TEST_CALLOC(local_input.buffer, local_input.length); + + psa_crypto_local_input_free(&local_input); + + TEST_ASSERT(local_input.buffer == NULL); + TEST_EQUAL(local_input.length, 0); + +exit: + mbedtls_free(local_input.buffer); + local_input.buffer = NULL; + local_input.length = 0; +} +/* END_CASE */ + +/* BEGIN_CASE */ +void local_input_round_trip() +{ + psa_crypto_local_input_t local_input; + uint8_t input[200]; + psa_status_t status; + + fill_buffer_pattern(input, sizeof(input)); + + status = psa_crypto_local_input_alloc(input, sizeof(input), &local_input); + TEST_EQUAL(status, PSA_SUCCESS); + + MBEDTLS_TEST_MEMORY_UNPOISON(input, sizeof(input)); + TEST_MEMORY_COMPARE(local_input.buffer, local_input.length, + input, sizeof(input)); + TEST_ASSERT(local_input.buffer != input); + + psa_crypto_local_input_free(&local_input); + TEST_ASSERT(local_input.buffer == NULL); + TEST_EQUAL(local_input.length, 0); +} +/* END_CASE */ + +/* BEGIN_CASE */ +void local_output_alloc(int output_len, psa_status_t exp_status) +{ + uint8_t *output = NULL; + psa_crypto_local_output_t local_output; + psa_status_t status; + + local_output.buffer = NULL; + + TEST_CALLOC(output, output_len); + + status = psa_crypto_local_output_alloc(output, output_len, &local_output); + TEST_EQUAL(status, exp_status); + + if (exp_status == PSA_SUCCESS) { + TEST_ASSERT(local_output.original == output); + TEST_EQUAL(local_output.length, output_len); + } + +exit: + mbedtls_free(local_output.buffer); + local_output.original = NULL; + local_output.buffer = NULL; + local_output.length = 0; + mbedtls_free(output); + output = NULL; +} +/* END_CASE */ + +/* BEGIN_CASE */ +void local_output_free(int output_len, int original_is_null, + psa_status_t exp_status) +{ + uint8_t *output = NULL; + uint8_t *buffer_copy_for_comparison = NULL; + psa_crypto_local_output_t local_output = PSA_CRYPTO_LOCAL_OUTPUT_INIT; + psa_status_t status; + + if (!original_is_null) { + TEST_CALLOC(output, output_len); + } + TEST_CALLOC(buffer_copy_for_comparison, output_len); + TEST_CALLOC(local_output.buffer, output_len); + local_output.length = output_len; + local_output.original = output; + + if (local_output.length != 0) { + fill_buffer_pattern(local_output.buffer, local_output.length); + memcpy(buffer_copy_for_comparison, local_output.buffer, local_output.length); + } + + status = psa_crypto_local_output_free(&local_output); + TEST_EQUAL(status, exp_status); + + if (exp_status == PSA_SUCCESS) { + MBEDTLS_TEST_MEMORY_UNPOISON(output, output_len); + TEST_ASSERT(local_output.buffer == NULL); + TEST_EQUAL(local_output.length, 0); + TEST_MEMORY_COMPARE(buffer_copy_for_comparison, output_len, + output, output_len); + } + +exit: + mbedtls_free(output); + mbedtls_free(buffer_copy_for_comparison); + mbedtls_free(local_output.buffer); + local_output.length = 0; +} +/* END_CASE */ + +/* BEGIN_CASE */ +void local_output_round_trip() +{ + psa_crypto_local_output_t local_output; + uint8_t output[200]; + uint8_t *buffer_copy_for_comparison = NULL; + psa_status_t status; + + status = psa_crypto_local_output_alloc(output, sizeof(output), &local_output); + TEST_EQUAL(status, PSA_SUCCESS); + TEST_ASSERT(local_output.buffer != output); + + /* Simulate the function generating output */ + fill_buffer_pattern(local_output.buffer, local_output.length); + + TEST_CALLOC(buffer_copy_for_comparison, local_output.length); + memcpy(buffer_copy_for_comparison, local_output.buffer, local_output.length); + + psa_crypto_local_output_free(&local_output); + TEST_ASSERT(local_output.buffer == NULL); + TEST_EQUAL(local_output.length, 0); + + MBEDTLS_TEST_MEMORY_UNPOISON(output, sizeof(output)); + /* Check that the buffer was correctly copied back */ + TEST_MEMORY_COMPARE(output, sizeof(output), + buffer_copy_for_comparison, sizeof(output)); + +exit: + mbedtls_free(buffer_copy_for_comparison); +} +/* END_CASE */ diff --git a/tests/suites/test_suite_psa_crypto_op_fail.function b/tests/suites/test_suite_psa_crypto_op_fail.function index 0d5d53890fce..4e709a0a8ada 100644 --- a/tests/suites/test_suite_psa_crypto_op_fail.function +++ b/tests/suites/test_suite_psa_crypto_op_fail.function @@ -332,9 +332,9 @@ void key_agreement_fail(int key_type_arg, data_t *key_data, psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT; uint8_t public_key[PSA_EXPORT_PUBLIC_KEY_MAX_SIZE] = { 0 }; - size_t public_key_length = SIZE_MAX; + size_t public_key_length = 0; uint8_t output[PSA_SIGNATURE_MAX_SIZE] = { 0 }; - size_t length = SIZE_MAX; + size_t length = 0; psa_key_derivation_operation_t operation = PSA_KEY_DERIVATION_OPERATION_INIT; PSA_INIT(); diff --git a/tests/suites/test_suite_test_helpers.data b/tests/suites/test_suite_test_helpers.data new file mode 100644 index 000000000000..1d221d7bf18d --- /dev/null +++ b/tests/suites/test_suite_test_helpers.data @@ -0,0 +1,23 @@ +Memory poison+unpoison: offset=0 len=42 +memory_poison_unpoison:0:42 + +Memory poison+unpoison: offset=0 len=1 +memory_poison_unpoison:0:1 + +Memory poison+unpoison: offset=0 len=2 +memory_poison_unpoison:0:2 + +Memory poison+unpoison: offset=1 len=1 +memory_poison_unpoison:1:1 + +Memory poison+unpoison: offset=1 len=2 +memory_poison_unpoison:1:2 + +Memory poison+unpoison: offset=7 len=1 +memory_poison_unpoison:7:1 + +Memory poison+unpoison: offset=7 len=2 +memory_poison_unpoison:7:2 + +Memory poison+unpoison: offset=0 len=0 +memory_poison_unpoison:0:0 diff --git a/tests/suites/test_suite_test_helpers.function b/tests/suites/test_suite_test_helpers.function new file mode 100644 index 000000000000..8c5d5adf654d --- /dev/null +++ b/tests/suites/test_suite_test_helpers.function @@ -0,0 +1,40 @@ +/* BEGIN_HEADER */ + +/* Test some parts of the test framework. */ + +#include +#include + +/* END_HEADER */ + +/* BEGIN_DEPENDENCIES */ + +/* END_DEPENDENCIES */ + +/* BEGIN_CASE depends_on:MBEDTLS_TEST_MEMORY_CAN_POISON */ +/* Test that poison+unpoison leaves the memory accessible. */ +/* We can't test that poisoning makes the memory inaccessible: + * there's no sane way to catch an Asan/Valgrind complaint. + * That negative testing is done in programs/test/metatest.c. */ +void memory_poison_unpoison(int align, int size) +{ + unsigned char *buf = NULL; + const size_t buffer_size = align + size; + TEST_CALLOC(buf, buffer_size); + + for (size_t i = 0; i < buffer_size; i++) { + buf[i] = (unsigned char) (i & 0xff); + } + + const unsigned char *start = buf == NULL ? NULL : buf + align; + mbedtls_test_memory_poison(start, (size_t) size); + mbedtls_test_memory_unpoison(start, (size_t) size); + + for (size_t i = 0; i < buffer_size; i++) { + TEST_EQUAL(buf[i], (unsigned char) (i & 0xff)); + } + +exit: + mbedtls_free(buf); +} +/* END_CASE */ diff --git a/tests/suites/test_suite_version.data b/tests/suites/test_suite_version.data index 7d8f252ccefc..148aa463dc43 100644 --- a/tests/suites/test_suite_version.data +++ b/tests/suites/test_suite_version.data @@ -1,8 +1,8 @@ Check compile time library version -check_compiletime_version:"2.28.7" +check_compiletime_version:"2.28.8" Check runtime library version -check_runtime_version:"2.28.7" +check_runtime_version:"2.28.8" Check for MBEDTLS_VERSION_C check_feature:"MBEDTLS_VERSION_C":0 diff --git a/visualc/VS2010/mbedTLS.vcxproj b/visualc/VS2010/mbedTLS.vcxproj index e36a7b5706e5..bcbbd4cc1f22 100644 --- a/visualc/VS2010/mbedTLS.vcxproj +++ b/visualc/VS2010/mbedTLS.vcxproj @@ -243,9 +243,12 @@ + + + @@ -390,7 +393,10 @@ + + +