Merge branch 'development-restricted' into 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 dbe3338..f2502e7 100644
--- a/library/psa_crypto.c
+++ b/library/psa_crypto.c
@@ -234,6 +234,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 */
@@ -4389,14 +4391,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;
@@ -4418,33 +4421,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;
@@ -4460,6 +4470,8 @@
goto exit;
}
+ LOCAL_INPUT_ALLOC(iv_external, iv_length, iv);
+
status = psa_driver_wrapper_cipher_set_iv(operation,
iv,
iv_length);
@@ -4470,18 +4482,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;
@@ -4492,6 +4510,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,
@@ -4504,16 +4525,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;
@@ -4524,6 +4550,8 @@
goto exit;
}
+ LOCAL_OUTPUT_ALLOC(output_external, output_size, output);
+
status = psa_driver_wrapper_cipher_finish(operation,
output,
output_size,
@@ -4531,13 +4559,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)
@@ -4576,9 +4606,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;
@@ -4613,6 +4640,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,
@@ -4642,9 +4672,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)
{
@@ -4653,6 +4683,9 @@
psa_key_slot_t *slot = NULL;
psa_key_attributes_t attributes;
+ 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;
@@ -4678,6 +4711,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,
@@ -4693,6 +4729,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 3132854..d70a275 100644
--- a/library/psa_crypto_cipher.c
+++ b/library/psa_crypto_cipher.c
@@ -532,7 +532,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 6a1f2ef..fbe7cf1 100755
--- a/tests/scripts/generate_psa_wrappers.py
+++ b/tests/scripts/generate_psa_wrappers.py
@@ -145,7 +145,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 4a5de23..86ab1c3 100644
--- a/tests/src/psa_test_wrappers.c
+++ b/tests/src/psa_test_wrappers.c
@@ -329,7 +329,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;
}
@@ -382,7 +390,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;
}
@@ -393,7 +407,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;
}
@@ -403,7 +423,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;
}
@@ -416,7 +442,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 8e99f6f..4c13b8d 100644
--- a/tests/suites/test_suite_psa_crypto_driver_wrappers.function
+++ b/tests/suites/test_suite_psa_crypto_driver_wrappers.function
@@ -1559,14 +1559,6 @@
TEST_EQUAL(mbedtls_test_driver_cipher_hooks.hits_set_iv, 1);
TEST_EQUAL(status, mbedtls_test_driver_cipher_hooks.forced_status_set_iv);
mbedtls_test_driver_cipher_hooks.forced_status_set_iv = PSA_SUCCESS;
- /*
- * 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,