diff --git a/library/psa_crypto.c b/library/psa_crypto.c index dbe3338ab8..77c69550e2 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -234,6 +234,8 @@ mbedtls_psa_drbg_context_t *const mbedtls_psa_random_state = 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_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; @@ -4418,33 +4421,40 @@ psa_status_t psa_cipher_generate_iv(psa_cipher_operation_t *operation, goto exit; } - status = psa_generate_random_internal(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; @@ -4460,6 +4470,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); @@ -4470,18 +4482,24 @@ exit: } 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 @@ 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, @@ -4504,16 +4525,21 @@ exit: 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 @@ 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, @@ -4531,13 +4559,15 @@ psa_status_t psa_cipher_finish(psa_cipher_operation_t *operation, exit: if (status == PSA_SUCCESS) { - return psa_cipher_abort(operation); + status = psa_cipher_abort(operation); } else { *output_length = 0; (void) psa_cipher_abort(operation); - - return status; } + + LOCAL_OUTPUT_FREE(output_external, output); + + return status; } psa_status_t psa_cipher_abort(psa_cipher_operation_t *operation) @@ -4576,9 +4606,6 @@ psa_status_t psa_cipher_encrypt(mbedtls_svc_key_id_t key, 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 @@ psa_status_t psa_cipher_encrypt(mbedtls_svc_key_id_t key, } } + 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 @@ exit: 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_status_t psa_cipher_decrypt(mbedtls_svc_key_id_t key, 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 @@ 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, @@ -4693,6 +4729,9 @@ exit: *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 313285480b..d70a27501a 100644 --- a/library/psa_crypto_cipher.c +++ b/library/psa_crypto_cipher.c @@ -532,7 +532,11 @@ psa_status_t mbedtls_psa_cipher_update( output_length); } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING */ - { + if (input_length == 0) { + /* There is no input, nothing to be done */ + *output_length = 0; + status = PSA_SUCCESS; + } else { status = mbedtls_to_psa_error( mbedtls_cipher_update(&operation->ctx.cipher, input, input_length, output, output_length)); diff --git a/tests/scripts/generate_psa_wrappers.py b/tests/scripts/generate_psa_wrappers.py index 6a1f2efd84..fbe7cf17b6 100755 --- a/tests/scripts/generate_psa_wrappers.py +++ b/tests/scripts/generate_psa_wrappers.py @@ -145,7 +145,9 @@ class PSAWrapperGenerator(c_wrapper_generator.Base): #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 4a5de23834..86ab1c3736 100644 --- a/tests/src/psa_test_wrappers.c +++ b/tests/src/psa_test_wrappers.c @@ -329,7 +329,15 @@ psa_status_t mbedtls_test_wrap_psa_cipher_decrypt( 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 @@ psa_status_t mbedtls_test_wrap_psa_cipher_finish( 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 @@ psa_status_t mbedtls_test_wrap_psa_cipher_generate_iv( 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 @@ psa_status_t mbedtls_test_wrap_psa_cipher_set_iv( 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 @@ psa_status_t mbedtls_test_wrap_psa_cipher_update( 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 8e99f6f5c3..4c13b8db1c 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 @@ void cipher_entry_points(int alg_arg, int key_type_arg, 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,