CVE-2024-28960
Description
Mbed TLS / Mbed Crypto PSA Crypto API mishandles shared memory, enabling TOCTOU attacks that can lead to privilege escalation or information disclosure.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Mbed TLS / Mbed Crypto PSA Crypto API mishandles shared memory, enabling TOCTOU attacks that can lead to privilege escalation or information disclosure.
Vulnerability
An issue in Mbed TLS versions 2.18.0 through 2.28.7 and 3.0.0 through 3.5.2, as well as all versions of Mbed Crypto, allows the PSA Crypto API to mishandle shared memory when domain isolation is used between a client application and a crypto server. The vulnerability specifically affects configurations where communication relies on shared memory and the other domain is untrusted. Applications using Mbed TLS as a library within a single process are not impacted [1].
Exploitation
An attacker in an untrusted protection domain that shares memory with the PSA Crypto API implementation can exploit a time-of-check/time-of-use (TOCTOU) race condition. By modifying input parameters or intermediate results in shared memory while a cryptographic function is executing, the attacker can cause the function to operate on inconsistent or attacker-controlled data. This requires the attacker to have the ability to write to the shared memory region during the API call [1].
Impact
Successful exploitation can result in several security consequences: (1) validation bypass and processing of invalid data, potentially leading to privilege escalation or further exploits; (2) violation of the function's internal expectations, enabling arbitrary behavior; (3) leakage of confidential information from intermediate results stored in output parameters. The PSA Crypto API specification requires protection against such attacks, but Mbed TLS did not implement the necessary safeguards [1].
Mitigation
Fixed versions are Mbed TLS 2.28.8 and 3.6.0, released on 25 March 2024. Users should update to these versions or later. No workaround is available for affected configurations. The vulnerability applies to all versions of Mbed Crypto, which is no longer separately maintained; users should migrate to Mbed TLS 3.6.0 [1].
AI Insight generated on May 25, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected products
4- Mbed TLS/Mbed Cryptodescription
Patches
22ca6c285a0ddMerge pull request #1215 from Mbed-TLS/mbedtls-3.6.0rc1-pr
2 files changed · +1 −4
include/mbedtls/mbedtls_config.h+0 −3 modified@@ -1744,9 +1744,6 @@ * * Enable support for RFC 8449 record_size_limit extension in SSL (TLS 1.3 only). * - * \warning This extension is currently in development and must NOT be used except - * for testing purposes. - * * Requires: MBEDTLS_SSL_PROTO_TLS1_3 * * Uncomment this macro to enable support for the record_size_limit extension
include/psa/crypto_types.h+1 −1 modified@@ -469,7 +469,7 @@ typedef uint16_t psa_key_derivation_step_t; * - \c flags: must be 0. * - \c data: the public exponent, in little-endian order. * This must be an odd integer and must not be 1. - * Implementations must support 65535, should support 3 and may + * Implementations must support 65537, should support 3 and may * support other values. * When not using a driver, Mbed TLS supports values up to \c INT_MAX. * If this is empty or if the custom production parameters are omitted
5a764e5555c6Merge pull request #1214 from Mbed-TLS/mbedtls-2.28.8rc0-pr
53 files changed · +3956 −221
ChangeLog+52 −0 modified@@ -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
ChangeLog.d/8372.txt+0 −3 removed@@ -1,3 +0,0 @@ -Features - * AES-NI is now supported in Windows builds with clang and clang-cl. - Resolves #8372.
ChangeLog.d/cmake_use_GnuInstallDirs.txt+0 −5 removed@@ -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.
ChangeLog.d/fix-alpn-negotiating-bug.txt+0 −3 removed@@ -1,3 +0,0 @@ -Bugfix - * Fix the restoration of the ALPN when loading serialized connection with - * the mbedtls_ssl_context_load() API.
ChangeLog.d/fix-cmake-3rdparty-custom-config.txt+0 −3 removed@@ -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.
ChangeLog.d/fix_kdf_incorrect_initial_capacity.txt+0 −3 removed@@ -1,3 +0,0 @@ -Bugfix - * Correct initial capacities for key derivation algorithms:TLS12_PRF, - TLS12_PSK_TO_MS
ChangeLog.d/fix-mingw32-build.txt+0 −4 removed@@ -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.
ChangeLog.d/fix-ssl-session-serialization-config.txt+0 −4 removed@@ -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.
ChangeLog.d/gen-key-segfault.txt+0 −3 removed@@ -1,3 +0,0 @@ -Bugfix - * Avoid segmentation fault caused by releasing not initialized - entropy resource in gen_key example. Fixes #8809.
ChangeLog.d/license.txt+0 −3 removed@@ -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.
ChangeLog.d/pkg-config-files-addition.txt+0 −3 removed@@ -1,3 +0,0 @@ -Features - * Add pc files for pkg-config. eg.: - pkg-config --cflags --libs (mbedtls|mbedcrypto|mbedx509)
ChangeLog.d/pkwrite-pem-use-heap.txt+0 −4 removed@@ -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.
ChangeLog.d/rsa-bitlen.txt+0 −3 removed@@ -1,3 +0,0 @@ -Bugfix - * Fix mbedtls_pk_get_bitlen() for RSA keys whose size is not a - multiple of 8. Fixes #868.
doxygen/input/doc_mainpage.h+1 −1 modified@@ -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
doxygen/mbedtls.doxyfile+1 −1 modified@@ -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
include/mbedtls/config.h+20 −0 modified@@ -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 *
include/mbedtls/version.h+4 −4 modified@@ -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)
library/CMakeLists.txt+6 −4 modified@@ -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
library/gcm.c+3 −3 modified@@ -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);
library/psa_crypto.c+754 −141 modified@@ -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,15 +1497,21 @@ 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 }; status = psa_driver_wrapper_export_key(&attributes, 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,14 +1571,15 @@ 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) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; 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,39 +2320,65 @@ 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: if (status != PSA_SUCCESS) { 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,13 +2887,17 @@ 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; } 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,20 +3866,24 @@ 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, output_length); 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,26 +4105,40 @@ 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; } 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,24 +4575,19 @@ 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) { /* This is a blank operation. */ 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,21 +5465,25 @@ 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) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; 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,31 +5510,40 @@ 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 * verification errors. This is better than filling the buffer with * 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 */
library/psa_crypto_cipher.c+5 −1 modified@@ -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));
library/psa_crypto_core.h+70 −0 modified@@ -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 */
library/psa_crypto_invasive.h+15 −0 modified@@ -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 */
library/version_features.c+3 −0 modified@@ -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 */
pkgconfig/CMakeLists.txt+1 −1 modified@@ -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
programs/Makefile+4 −0 modified@@ -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
programs/test/metatest.c+91 −0 modified@@ -28,10 +28,12 @@ #define MBEDTLS_ALLOW_PRIVATE_ACCESS +#include <mbedtls/debug.h> #include <mbedtls/platform.h> #include <mbedtls/platform_util.h> #include "test/helpers.h" #include "test/macros.h" +#include "test/memory.h" #include <stdio.h> #include <string.h> @@ -40,6 +42,11 @@ #include <mbedtls/threading.h> #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 },
programs/test/query_config.c+12 −0 modified@@ -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 */
scripts/config.py+1 −0 modified@@ -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
scripts/mbedtls_dev/c_parsing_helper.py+131 −0 added@@ -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<type>\w[\w\s*]*?)\s*' + + r'(?!(?:' + r'|'.join(_KEYWORDS) + r'))(?P<name>\b\w+\b)?' + + r'\s*(?P<suffix>\[[^][]*\])?\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<qualifiers>(?:(?:extern|inline|static)\b\s*)*)' + r'(?P<return_type>\w[\w\s*]*?)\s*' + + r'\b(?P<name>\w+)' + + r'\s*\((?P<arguments>.*)\)\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)
scripts/mbedtls_dev/c_wrapper_generator.py+477 −0 added@@ -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 <stdio.h> +#include <inttypes.h> +#include <mbedtls/debug.h> // for MBEDTLS_PRINTF_SIZET +#include <mbedtls/platform.h> // 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)
tests/include/test/memory.h+103 −0 added@@ -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 */
tests/include/test/psa_crypto_helpers.h+1 −0 modified@@ -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. */
tests/include/test/psa_memory_poisoning_wrappers.h+40 −0 added@@ -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 */
tests/include/test/psa_test_wrappers.h+489 −0 added@@ -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 <psa/crypto.h> + +#include <test/memory.h> +#include <test/psa_crypto_helpers.h> +#include <test/psa_test_wrappers.h> + +#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. */
tests/scripts/all.sh+13 −2 modified@@ -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
tests/scripts/check-generated-files.sh+1 −0 modified@@ -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)
tests/scripts/generate_psa_wrappers.py+260 −0 added@@ -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 <psa/crypto.h> + +#include <test/memory.h> +#include <test/psa_crypto_helpers.h> +#include <test/psa_test_wrappers.h> +""" + .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()
tests/src/helpers.c+16 −0 modified@@ -17,6 +17,10 @@ #include <test/psa_crypto_helpers.h> #endif +#if defined(MBEDTLS_TEST_HOOKS) && defined(MBEDTLS_PSA_CRYPTO_C) +#include <test/psa_memory_poisoning_wrappers.h> +#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 */
tests/src/psa_memory_poisoning_wrappers.c+31 −0 added@@ -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 */
tests/src/psa_test_wrappers.c+880 −0 added@@ -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 <psa/crypto.h> + +#include <test/memory.h> +#include <test/psa_crypto_helpers.h> +#include <test/psa_test_wrappers.h> + +/* 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. */
tests/src/test_memory.c+60 −0 added@@ -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 <test/helpers.h> +#include <test/macros.h> +#include <test/memory.h> + +#if defined(MBEDTLS_TEST_MEMORY_CAN_POISON) +#include <sanitizer/asan_interface.h> +#include <stdint.h> +#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 */
tests/suites/test_suite_debug.data+6 −0 modified@@ -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
tests/suites/test_suite_psa_crypto.data+5 −0 modified@@ -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
tests/suites/test_suite_psa_crypto_driver_wrappers.function+1 −16 modified@@ -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,
tests/suites/test_suite_psa_crypto.function+6 −2 modified@@ -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,
tests/suites/test_suite_psa_crypto_memory.data+62 −0 added@@ -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
tests/suites/test_suite_psa_crypto_memory.function+258 −0 added@@ -0,0 +1,258 @@ +/* BEGIN_HEADER */ +#include <stdint.h> + +#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 */
tests/suites/test_suite_psa_crypto_op_fail.function+2 −2 modified@@ -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();
tests/suites/test_suite_test_helpers.data+23 −0 added@@ -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
tests/suites/test_suite_test_helpers.function+40 −0 added@@ -0,0 +1,40 @@ +/* BEGIN_HEADER */ + +/* Test some parts of the test framework. */ + +#include <test/helpers.h> +#include <test/memory.h> + +/* 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 */
tests/suites/test_suite_version.data+2 −2 modified@@ -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
visualc/VS2010/mbedTLS.vcxproj+6 −0 modified@@ -243,9 +243,12 @@ <ClInclude Include="..\..\tests\include\test\fake_external_rng_for_test.h" /> <ClInclude Include="..\..\tests\include\test\helpers.h" /> <ClInclude Include="..\..\tests\include\test\macros.h" /> + <ClInclude Include="..\..\tests\include\test\memory.h" /> <ClInclude Include="..\..\tests\include\test\psa_crypto_helpers.h" /> <ClInclude Include="..\..\tests\include\test\psa_exercise_key.h" /> <ClInclude Include="..\..\tests\include\test\psa_helpers.h" /> + <ClInclude Include="..\..\tests\include\test\psa_memory_poisoning_wrappers.h" /> + <ClInclude Include="..\..\tests\include\test\psa_test_wrappers.h" /> <ClInclude Include="..\..\tests\include\test\random.h" /> <ClInclude Include="..\..\tests\include\test\ssl_helpers.h" /> <ClInclude Include="..\..\tests\include\test\drivers\aead.h" /> @@ -390,7 +393,10 @@ <ClCompile Include="..\..\tests\src\helpers.c" /> <ClCompile Include="..\..\tests\src\psa_crypto_helpers.c" /> <ClCompile Include="..\..\tests\src\psa_exercise_key.c" /> + <ClCompile Include="..\..\tests\src\psa_memory_poisoning_wrappers.c" /> + <ClCompile Include="..\..\tests\src\psa_test_wrappers.c" /> <ClCompile Include="..\..\tests\src\random.c" /> + <ClCompile Include="..\..\tests\src\test_memory.c" /> <ClCompile Include="..\..\tests\src\threading_helpers.c" /> <ClCompile Include="..\..\tests\src\drivers\hash.c" /> <ClCompile Include="..\..\tests\src\drivers\platform_builtin_keys.c" />
Vulnerability mechanics
No source-code context for this CVE — mechanics is only generated when we can read the actual fix diff. Without that, the four sections (root cause, attack vector, affected code, fix) would be speculation rather than analysis.
References
8- github.com/Mbed-TLS/mbedtls-docs/blob/main/security-advisories/mbedtls-security-advisory-2024-03.mdnvdVendor Advisory
- lists.fedoraproject.org/archives/list/package-announce%40lists.fedoraproject.org/message/5YE3QRREGJC6K34JD4LZ5P3IALNX4QYY/nvdMailing ListThird Party Advisory
- lists.fedoraproject.org/archives/list/package-announce%40lists.fedoraproject.org/message/6UZNBMKYEV2J5DI7R4BQGL472V7X3WJY/nvdMailing ListThird Party Advisory
- lists.fedoraproject.org/archives/list/package-announce%40lists.fedoraproject.org/message/NCDU52ZDA7TX3HC5JCU6ZZIJQOPTNBK6/nvdMailing ListThird Party Advisory
- mbed-tls.readthedocs.io/en/latest/tech-updates/security-advisories/nvdVendor Advisory
- lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/5YE3QRREGJC6K34JD4LZ5P3IALNX4QYY/nvd
- lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/6UZNBMKYEV2J5DI7R4BQGL472V7X3WJY/nvd
- lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/NCDU52ZDA7TX3HC5JCU6ZZIJQOPTNBK6/nvd
News mentions
0No linked articles in our index yet.