From 4c224fe3ccbe527a2b7d55a927f1f09511ff1b83 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Fri, 9 Jul 2021 18:44:58 +0200 Subject: [PATCH] psa: cipher: Fix invalid output buffer usage in psa_cipher_encrypt() Don't use the output buffer in psa_cipher_encrypt() to pass the generated IV to the driver as local attacker could potentially control it. Signed-off-by: Ronald Cron --- library/psa_crypto.c | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/library/psa_crypto.c b/library/psa_crypto.c index 028eafcaa..3bf470b2f 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -3567,8 +3567,8 @@ psa_status_t psa_cipher_encrypt( mbedtls_svc_key_id_t key, psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_slot_t *slot = NULL; - psa_key_type_t key_type; - size_t iv_length; + uint8_t local_iv[PSA_CIPHER_IV_MAX_SIZE]; + size_t default_iv_length = 0; if( ! PSA_ALG_IS_CIPHER( alg ) ) { @@ -3586,26 +3586,31 @@ psa_status_t psa_cipher_encrypt( mbedtls_svc_key_id_t key, .core = slot->attr }; - key_type = slot->attr.type; - iv_length = PSA_CIPHER_IV_LENGTH( key_type, alg ); - - if( iv_length > 0 ) + default_iv_length = PSA_CIPHER_IV_LENGTH( slot->attr.type, alg ); + if( default_iv_length > PSA_CIPHER_IV_MAX_SIZE ) { - if( output_size < iv_length ) + status = PSA_ERROR_GENERIC_ERROR; + goto exit; + } + + if( default_iv_length > 0 ) + { + if( output_size < default_iv_length ) { status = PSA_ERROR_BUFFER_TOO_SMALL; goto exit; } - status = psa_generate_random( output, iv_length ); + status = psa_generate_random( local_iv, default_iv_length ); if( status != PSA_SUCCESS ) goto exit; } status = psa_driver_wrapper_cipher_encrypt( &attributes, slot->key.data, slot->key.bytes, - alg, output, iv_length, input, input_length, - output + iv_length, output_size - iv_length, output_length ); + alg, local_iv, default_iv_length, input, input_length, + output + default_iv_length, output_size - default_iv_length, + output_length ); exit: unlock_status = psa_unlock_key_slot( slot ); @@ -3613,7 +3618,11 @@ exit: status = unlock_status; if( status == PSA_SUCCESS ) - *output_length += iv_length; + { + if( default_iv_length > 0 ) + memcpy( output, local_iv, default_iv_length ); + *output_length += default_iv_length; + } else *output_length = 0;