diff --git a/library/psa_crypto.c b/library/psa_crypto.c index 8c9f9de4de..3b3c116252 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -186,6 +186,23 @@ mbedtls_psa_drbg_context_t *const mbedtls_psa_random_state = } \ 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. * @@ -8703,6 +8720,39 @@ psa_status_t psa_crypto_local_output_alloc(uint8_t *output, size_t output_len, 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 a15f1dfab5..1b117f5b79 100644 --- a/library/psa_crypto_core.h +++ b/library/psa_crypto_core.h @@ -906,6 +906,25 @@ typedef struct psa_crypto_local_output_s { 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. *