Crypto: psa_aead_verify()/finish() can have NULL pointer outputs

The psa_aead_verify() and psa_aead_finish() APIs can have cases
where the output pointers for plaintext and ciphertext are NULL
or zero-length hence need to be handled accordingly by the
interface as the IPC framework would result in error in these
cases.

Signed-off-by: Antonio de Angelis <antonio.deangelis@arm.com>
Change-Id: Ic1885d130c8e7eae1a928623153a93a43b280292
diff --git a/interface/src/tfm_crypto_ipc_api.c b/interface/src/tfm_crypto_ipc_api.c
index 67842ac..29fbf95 100644
--- a/interface/src/tfm_crypto_ipc_api.c
+++ b/interface/src/tfm_crypto_ipc_api.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2021, Arm Limited. All rights reserved.
+ * Copyright (c) 2018-2022, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  *
@@ -1068,20 +1068,38 @@
         .op_handle = operation->handle,
     };
 
+    /* Sanitize the optional output */
+    if ((ciphertext == NULL) && (ciphertext_size != 0)) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
     psa_invec in_vec[] = {
         {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)},
     };
     psa_outvec out_vec[] = {
         {.base = &(operation->handle), .len = sizeof(uint32_t)},
-        {.base = ciphertext, .len = ciphertext_size},
         {.base = tag, .len = tag_size},
+        {.base = ciphertext, .len = ciphertext_size}
     };
 
-    status = API_DISPATCH(tfm_crypto_aead_finish,
-                          TFM_CRYPTO_AEAD_FINISH);
+    size_t out_len = IOVEC_LEN(out_vec);
+    if (ciphertext == NULL || ciphertext_size == 0) {
+        out_len--;
+    }
+    if ((out_len == 3) && (ciphertext_length == NULL)) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
 
-    *ciphertext_length = out_vec[1].len;
-    *tag_length = out_vec[2].len;
+    status = psa_call(TFM_CRYPTO_HANDLE, PSA_IPC_CALL, in_vec, IOVEC_LEN(in_vec),
+                      out_vec, out_len);
+
+    *tag_length = out_vec[1].len;
+
+    if (out_len == 3) {
+        *ciphertext_length = out_vec[2].len;
+    } else {
+        *ciphertext_length = 0;
+    }
     return status;
 }
 
@@ -1098,6 +1116,11 @@
         .op_handle = operation->handle,
     };
 
+    /* Sanitize the optional output */
+    if ((plaintext == NULL) && (plaintext_size != 0)) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
     psa_invec in_vec[] = {
         {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)},
         {.base = tag, .len = tag_length}
@@ -1107,10 +1130,22 @@
         {.base = plaintext, .len = plaintext_size},
     };
 
-    status = API_DISPATCH(tfm_crypto_aead_verify,
-                          TFM_CRYPTO_AEAD_VERIFY);
+    size_t out_len = IOVEC_LEN(out_vec);
+    if (plaintext == NULL || plaintext_size == 0) {
+        out_len--;
+    }
+    if ((out_len == 2) && (plaintext_length == NULL)) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
 
-    *plaintext_length = out_vec[1].len;
+    status = psa_call(TFM_CRYPTO_HANDLE, PSA_IPC_CALL, in_vec, IOVEC_LEN(in_vec),
+                      out_vec, out_len);
+
+    if (out_len == 2) {
+        *plaintext_length = out_vec[1].len;
+    } else {
+        *plaintext_length = 0;
+    }
     return status;
 }