diff --git a/library/psa_crypto.c b/library/psa_crypto.c index fc5e241900..7b4fc6c9d3 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -8473,6 +8473,16 @@ psa_status_t psa_crypto_alloc_and_copy(const uint8_t *input, size_t input_len, * on any pointers safely. */ memset(buffers, 0, sizeof(*buffers)); + /* Since calloc() may return NULL if we try to allocate zero-length + * buffers anyway, deal with this corner case explicitly to ensure + * predictable behaviour. Represent zero-length buffers as NULL. */ + if (input_len == 0) { + input = NULL; + } + if (output_len == 0) { + output = NULL; + } + if (output != NULL) { buffers->output = mbedtls_calloc(output_len, 1); if (buffers->output == NULL) { diff --git a/tests/suites/test_suite_psa_crypto.function b/tests/suites/test_suite_psa_crypto.function index 073bb6b4f3..8057763283 100644 --- a/tests/suites/test_suite_psa_crypto.function +++ b/tests/suites/test_suite_psa_crypto.function @@ -10430,8 +10430,16 @@ void psa_crypto_alloc_and_copy_zero_length(int input_zero_length, &buffer_copies); TEST_EQUAL(ret, PSA_SUCCESS); - TEST_MEMORY_COMPARE(input_buffer, input_len, buffer_copies.input, buffer_copies.input_len); - TEST_EQUAL(output_len, buffer_copies.output_len); + if (input_zero_length) { + TEST_ASSERT(buffer_copies.input == NULL); + } else { + TEST_MEMORY_COMPARE(input_buffer, input_len, buffer_copies.input, buffer_copies.input_len); + } + if (output_zero_length) { + TEST_ASSERT(buffer_copies.output == NULL); + } else { + TEST_EQUAL(output_len, buffer_copies.output_len); + } exit: mbedtls_free(buffer_copies.input);