Add allocate and copy style output buffer handling

Add a new macro `LOCAL_OUTPUT_ALLOC_WITH_COPY` to support the output buffer
handling of the multipart operations like `psa_cipher_update`. This will
allocate a local buffer and copy the content of the original buffer.

Signed-off-by: Gabor Mezei <gabor.mezei@arm.com>
diff --git a/library/psa_crypto.c b/library/psa_crypto.c
index 00e4f2a..05467bd 100644
--- a/library/psa_crypto.c
+++ b/library/psa_crypto.c
@@ -182,6 +182,23 @@
     } \
     output_copy = LOCAL_OUTPUT_COPY_OF_##output.buffer;
 
+/* Allocate a copy of the buffer output and set the pointer output_copy to
+ * point to the start of the copy.
+ *
+ * Assumptions:
+ * - psa_status_t status exists
+ * - An exit label is declared
+ * - output is the name of a pointer to the buffer to be copied
+ * - LOCAL_OUTPUT_DECLARE(output, output_copy) has previously been called
+ */
+#define LOCAL_OUTPUT_ALLOC_WITH_COPY(output, length, output_copy) \
+    status = psa_crypto_local_output_alloc_with_copy(output, length, \
+                                                     &LOCAL_OUTPUT_COPY_OF_##output); \
+    if (status != PSA_SUCCESS) { \
+        goto exit; \
+    } \
+    output_copy = LOCAL_OUTPUT_COPY_OF_##output.buffer;
+
 /* Free the local output copy allocated previously by LOCAL_OUTPUT_ALLOC()
  * after first copying back its contents to the original buffer.
  *
@@ -5783,6 +5800,39 @@
     return PSA_SUCCESS;
 }
 
+psa_status_t psa_crypto_local_output_alloc_with_copy(uint8_t *output, size_t output_len,
+                                                     psa_crypto_local_output_t *local_output)
+{
+    psa_status_t status;
+    *local_output = PSA_CRYPTO_LOCAL_OUTPUT_INIT;
+
+    if (output_len == 0) {
+        return PSA_SUCCESS;
+    }
+    local_output->buffer = mbedtls_calloc(output_len, 1);
+    if (local_output->buffer == NULL) {
+        /* Since we dealt with the zero-length case above, we know that
+         * a NULL return value means a failure of allocation. */
+        return PSA_ERROR_INSUFFICIENT_MEMORY;
+    }
+    local_output->length = output_len;
+    local_output->original = output;
+
+    status = psa_crypto_copy_input(output, output_len,
+                                   local_output->buffer, local_output->length);
+    if (status != PSA_SUCCESS) {
+        goto error;
+    }
+
+    return PSA_SUCCESS;
+
+error:
+    mbedtls_free(local_output->buffer);
+    local_output->buffer = NULL;
+    local_output->length = 0;
+    return status;
+}
+
 psa_status_t psa_crypto_local_output_free(psa_crypto_local_output_t *local_output)
 {
     psa_status_t status;
diff --git a/library/psa_crypto_core.h b/library/psa_crypto_core.h
index 4731064..ae8af09 100644
--- a/library/psa_crypto_core.h
+++ b/library/psa_crypto_core.h
@@ -560,6 +560,25 @@
 psa_status_t psa_crypto_local_output_alloc(uint8_t *output, size_t output_len,
                                            psa_crypto_local_output_t *local_output);
 
+/** Allocate a local copy of an output buffer and copy the contents into it.
+ *
+ * \note                        This allocates and copies a buffer
+ *                              whose contents will be copied back to the
+ *                              original in a future call to
+ *                              psa_crypto_local_output_free().
+ *
+ * \param[in] output            Pointer to output buffer.
+ * \param[in] output_len        Length of the output buffer.
+ * \param[out] local_output     Pointer to a psa_crypto_local_output_t struct to
+ *                              populate with the local output copy.
+ * \return                      #PSA_SUCCESS, if the buffer was successfully
+ *                              copied.
+ * \return                      #PSA_ERROR_INSUFFICIENT_MEMORY, if a copy of
+ *                              the buffer cannot be allocated.
+ */
+psa_status_t psa_crypto_local_output_alloc_with_copy(uint8_t *output, size_t output_len,
+                                                     psa_crypto_local_output_t *local_output);
+
 /** Copy from a local copy of an output buffer back to the original, then
  *  free the local copy.
  *