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>
diff --git a/library/psa_crypto.c b/library/psa_crypto.c
index 3a286aa..a8df97f 100644
--- a/library/psa_crypto.c
+++ b/library/psa_crypto.c
@@ -3502,8 +3502,8 @@
     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 ) )
     {
@@ -3521,26 +3521,31 @@
       .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 );
@@ -3548,7 +3553,11 @@
         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;