Merge branch 'mbedtls-2.28-restricted' into bp228_buffer_protection_for_cipher
Signed-off-by: Gábor Mezei <63054694+gabor-mezei-arm@users.noreply.github.com>
diff --git a/library/psa_crypto.c b/library/psa_crypto.c
index 9d73578..d634486 100644
--- a/library/psa_crypto.c
+++ b/library/psa_crypto.c
@@ -230,6 +230,8 @@
uint8_t *output_copy_name = NULL;
#define LOCAL_OUTPUT_ALLOC(output, length, output_copy) \
output_copy = output;
+#define LOCAL_OUTPUT_ALLOC_WITH_COPY(output, length, output_copy) \
+ output_copy = output;
#define LOCAL_OUTPUT_FREE(output, output_copy) \
output_copy = NULL;
#endif /* MBEDTLS_PSA_COPY_CALLER_BUFFERS */
@@ -3724,14 +3726,15 @@
}
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;
@@ -3753,33 +3756,40 @@
goto exit;
}
+ LOCAL_OUTPUT_ALLOC(iv_external, default_iv_length, iv);
+
status = psa_generate_random_internal(local_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;
@@ -3795,6 +3805,8 @@
goto exit;
}
+ LOCAL_INPUT_ALLOC(iv_external, iv_length, iv);
+
status = psa_driver_wrapper_cipher_set_iv(operation,
iv,
iv_length);
@@ -3805,18 +3817,24 @@
} 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;
@@ -3827,6 +3845,9 @@
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,
@@ -3839,16 +3860,21 @@
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;
@@ -3859,6 +3885,8 @@
goto exit;
}
+ LOCAL_OUTPUT_ALLOC(output_external, output_size, output);
+
status = psa_driver_wrapper_cipher_finish(operation,
output,
output_size,
@@ -3866,13 +3894,15 @@
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)
@@ -3911,9 +3941,6 @@
LOCAL_INPUT_DECLARE(input_external, input);
LOCAL_OUTPUT_DECLARE(output_external, output);
- LOCAL_INPUT_ALLOC(input_external, input_length, input);
- LOCAL_OUTPUT_ALLOC(output_external, output_size, output);
-
if (!PSA_ALG_IS_CIPHER(alg)) {
status = PSA_ERROR_INVALID_ARGUMENT;
goto exit;
@@ -3948,6 +3975,9 @@
}
}
+ 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,
@@ -3977,9 +4007,9 @@
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)
{
@@ -3988,6 +4018,9 @@
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;
@@ -4009,6 +4042,9 @@
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,
@@ -4024,6 +4060,9 @@
*output_length = 0;
}
+ LOCAL_INPUT_FREE(input_external, input);
+ LOCAL_OUTPUT_FREE(output_external, output);
+
return status;
}
diff --git a/library/psa_crypto_cipher.c b/library/psa_crypto_cipher.c
index 545bb50..93a6b93 100644
--- a/library/psa_crypto_cipher.c
+++ b/library/psa_crypto_cipher.c
@@ -402,7 +402,11 @@
output_length);
} else
#endif /* MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING */
- {
+ if (input_length == 0) {
+ /* There is no input, nothing to be done */
+ *output_length = 0;
+ status = PSA_SUCCESS;
+ } else {
status = mbedtls_to_psa_error(
mbedtls_cipher_update(&operation->ctx.cipher, input,
input_length, output, output_length));
diff --git a/tests/scripts/generate_psa_wrappers.py b/tests/scripts/generate_psa_wrappers.py
index 1879bd4..49c673f 100755
--- a/tests/scripts/generate_psa_wrappers.py
+++ b/tests/scripts/generate_psa_wrappers.py
@@ -153,7 +153,9 @@
#pylint: disable=too-many-return-statements
if function_name.startswith('psa_aead'):
return True
- if function_name == 'psa_cipher_encrypt':
+ if function_name in {'psa_cipher_encrypt', 'psa_cipher_decrypt',
+ 'psa_cipher_update', 'psa_cipher_finish',
+ 'psa_cipher_generate_iv', 'psa_cipher_set_iv'}:
return True
if function_name in ('psa_key_derivation_output_bytes',
'psa_key_derivation_input_bytes'):
diff --git a/tests/src/psa_test_wrappers.c b/tests/src/psa_test_wrappers.c
index 7dcd932..ca6afde 100644
--- a/tests/src/psa_test_wrappers.c
+++ b/tests/src/psa_test_wrappers.c
@@ -182,7 +182,15 @@
size_t arg5_output_size,
size_t *arg6_output_length)
{
+#if defined(MBEDTLS_PSA_COPY_CALLER_BUFFERS)
+ MBEDTLS_TEST_MEMORY_POISON(arg2_input, arg3_input_length);
+ MBEDTLS_TEST_MEMORY_POISON(arg4_output, arg5_output_size);
+#endif /* defined(MBEDTLS_PSA_COPY_CALLER_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_COPY_CALLER_BUFFERS)
+ MBEDTLS_TEST_MEMORY_UNPOISON(arg2_input, arg3_input_length);
+ MBEDTLS_TEST_MEMORY_UNPOISON(arg4_output, arg5_output_size);
+#endif /* defined(MBEDTLS_PSA_COPY_CALLER_BUFFERS) */
return status;
}
@@ -235,7 +243,13 @@
size_t arg2_output_size,
size_t *arg3_output_length)
{
+#if defined(MBEDTLS_PSA_COPY_CALLER_BUFFERS)
+ MBEDTLS_TEST_MEMORY_POISON(arg1_output, arg2_output_size);
+#endif /* defined(MBEDTLS_PSA_COPY_CALLER_BUFFERS) */
psa_status_t status = (psa_cipher_finish)(arg0_operation, arg1_output, arg2_output_size, arg3_output_length);
+#if defined(MBEDTLS_PSA_COPY_CALLER_BUFFERS)
+ MBEDTLS_TEST_MEMORY_UNPOISON(arg1_output, arg2_output_size);
+#endif /* defined(MBEDTLS_PSA_COPY_CALLER_BUFFERS) */
return status;
}
@@ -246,7 +260,13 @@
size_t arg2_iv_size,
size_t *arg3_iv_length)
{
+#if defined(MBEDTLS_PSA_COPY_CALLER_BUFFERS)
+ MBEDTLS_TEST_MEMORY_POISON(arg1_iv, arg2_iv_size);
+#endif /* defined(MBEDTLS_PSA_COPY_CALLER_BUFFERS) */
psa_status_t status = (psa_cipher_generate_iv)(arg0_operation, arg1_iv, arg2_iv_size, arg3_iv_length);
+#if defined(MBEDTLS_PSA_COPY_CALLER_BUFFERS)
+ MBEDTLS_TEST_MEMORY_UNPOISON(arg1_iv, arg2_iv_size);
+#endif /* defined(MBEDTLS_PSA_COPY_CALLER_BUFFERS) */
return status;
}
@@ -256,7 +276,13 @@
const uint8_t *arg1_iv,
size_t arg2_iv_length)
{
+#if defined(MBEDTLS_PSA_COPY_CALLER_BUFFERS)
+ MBEDTLS_TEST_MEMORY_POISON(arg1_iv, arg2_iv_length);
+#endif /* defined(MBEDTLS_PSA_COPY_CALLER_BUFFERS) */
psa_status_t status = (psa_cipher_set_iv)(arg0_operation, arg1_iv, arg2_iv_length);
+#if defined(MBEDTLS_PSA_COPY_CALLER_BUFFERS)
+ MBEDTLS_TEST_MEMORY_UNPOISON(arg1_iv, arg2_iv_length);
+#endif /* defined(MBEDTLS_PSA_COPY_CALLER_BUFFERS) */
return status;
}
@@ -269,7 +295,15 @@
size_t arg4_output_size,
size_t *arg5_output_length)
{
+#if defined(MBEDTLS_PSA_COPY_CALLER_BUFFERS)
+ MBEDTLS_TEST_MEMORY_POISON(arg1_input, arg2_input_length);
+ MBEDTLS_TEST_MEMORY_POISON(arg3_output, arg4_output_size);
+#endif /* defined(MBEDTLS_PSA_COPY_CALLER_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_COPY_CALLER_BUFFERS)
+ MBEDTLS_TEST_MEMORY_UNPOISON(arg1_input, arg2_input_length);
+ MBEDTLS_TEST_MEMORY_UNPOISON(arg3_output, arg4_output_size);
+#endif /* defined(MBEDTLS_PSA_COPY_CALLER_BUFFERS) */
return status;
}
diff --git a/tests/suites/test_suite_psa_crypto_driver_wrappers.function b/tests/suites/test_suite_psa_crypto_driver_wrappers.function
index 75f5490..0394735 100644
--- a/tests/suites/test_suite_psa_crypto_driver_wrappers.function
+++ b/tests/suites/test_suite_psa_crypto_driver_wrappers.function
@@ -983,14 +983,6 @@
/* 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,