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 <ronald.cron@arm.com>
This commit is contained in:
Ronald Cron 2021-07-09 18:44:58 +02:00
parent 732a6e250d
commit 4c224fe3cc

View file

@ -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 status = PSA_ERROR_CORRUPTION_DETECTED;
psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;
psa_key_slot_t *slot = NULL; psa_key_slot_t *slot = NULL;
psa_key_type_t key_type; uint8_t local_iv[PSA_CIPHER_IV_MAX_SIZE];
size_t iv_length; size_t default_iv_length = 0;
if( ! PSA_ALG_IS_CIPHER( alg ) ) 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 .core = slot->attr
}; };
key_type = slot->attr.type; default_iv_length = PSA_CIPHER_IV_LENGTH( slot->attr.type, alg );
iv_length = PSA_CIPHER_IV_LENGTH( key_type, alg ); if( default_iv_length > PSA_CIPHER_IV_MAX_SIZE )
if( iv_length > 0 )
{ {
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; status = PSA_ERROR_BUFFER_TOO_SMALL;
goto exit; goto exit;
} }
status = psa_generate_random( output, iv_length ); status = psa_generate_random( local_iv, default_iv_length );
if( status != PSA_SUCCESS ) if( status != PSA_SUCCESS )
goto exit; goto exit;
} }
status = psa_driver_wrapper_cipher_encrypt( status = psa_driver_wrapper_cipher_encrypt(
&attributes, slot->key.data, slot->key.bytes, &attributes, slot->key.data, slot->key.bytes,
alg, output, iv_length, input, input_length, alg, local_iv, default_iv_length, input, input_length,
output + iv_length, output_size - iv_length, output_length ); output + default_iv_length, output_size - default_iv_length,
output_length );
exit: exit:
unlock_status = psa_unlock_key_slot( slot ); unlock_status = psa_unlock_key_slot( slot );
@ -3613,7 +3618,11 @@ exit:
status = unlock_status; status = unlock_status;
if( status == PSA_SUCCESS ) 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 else
*output_length = 0; *output_length = 0;