Crypto: Add support for AEAD operations

This patch introduces support for the AEAD (authenticated
encryption with associated data) operations in the context
of the Crypto service. It also adds two functional test
cases to the NS suite to showcase AEAD in GCM and CCM mode
using AES-128.

Change-Id: I42ca3b27c68cb95dcddaf525d5a7ff53f92e911c
Signed-off-by: Antonio de Angelis <antonio.deangelis@arm.com>
diff --git a/secure_fw/ns_callable/tfm_crypto_veneers.c b/secure_fw/ns_callable/tfm_crypto_veneers.c
index 7f8208d..a3ecc8d 100644
--- a/secure_fw/ns_callable/tfm_crypto_veneers.c
+++ b/secure_fw/ns_callable/tfm_crypto_veneers.c
@@ -218,3 +218,21 @@
     TFM_CORE_SFN_REQUEST(TFM_SP_CRYPTO_ID, tfm_crypto_mac_abort,
                          operation, 0, 0, 0);
 }
+
+__tfm_secure_gateway_attributes__
+enum tfm_crypto_err_t tfm_crypto_veneer_aead_encrypt(
+                                      struct psa_aead_encrypt_input *input_s,
+                                      struct psa_aead_encrypt_output *output_s)
+{
+    TFM_CORE_SFN_REQUEST(TFM_SP_CRYPTO_ID, tfm_crypto_aead_encrypt_wrapper,
+                         input_s, output_s, 0, 0);
+}
+
+__tfm_secure_gateway_attributes__
+enum tfm_crypto_err_t tfm_crypto_veneer_aead_decrypt(
+                                      struct psa_aead_decrypt_input *input_s,
+                                      struct psa_aead_decrypt_output *output_s)
+{
+    TFM_CORE_SFN_REQUEST(TFM_SP_CRYPTO_ID, tfm_crypto_aead_decrypt_wrapper,
+                         input_s, output_s, 0, 0);
+}
diff --git a/secure_fw/services/crypto/CMakeLists.inc b/secure_fw/services/crypto/CMakeLists.inc
index 18dcbb0..4b572eb 100644
--- a/secure_fw/services/crypto/CMakeLists.inc
+++ b/secure_fw/services/crypto/CMakeLists.inc
@@ -50,6 +50,7 @@
                     "${CRYPTO_DIR}/crypto_wrappers.c"
                     "${CRYPTO_DIR}/crypto_utils.c"
                     "${CRYPTO_DIR}/crypto_engine.c"
+                    "${CRYPTO_DIR}/crypto_aead.c"
       )
 
   #Append all our source files to global lists.
diff --git a/secure_fw/services/crypto/crypto_aead.c b/secure_fw/services/crypto/crypto_aead.c
new file mode 100644
index 0000000..a0e2a5c
--- /dev/null
+++ b/secure_fw/services/crypto/crypto_aead.c
@@ -0,0 +1,236 @@
+/*
+ * Copyright (c) 2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <limits.h>
+
+#include "tfm_crypto_defs.h"
+
+#include "crypto_engine.h"
+
+#include "psa_crypto.h"
+
+#include "tfm_crypto_api.h"
+#include "crypto_utils.h"
+
+/*!
+ * \defgroup public_psa Public functions, PSA
+ *
+ */
+
+/*!@{*/
+enum tfm_crypto_err_t tfm_crypto_aead_encrypt(psa_key_slot_t key,
+                                              psa_algorithm_t alg,
+                                              const uint8_t *nonce,
+                                              size_t nonce_length,
+                                              const uint8_t *additional_data,
+                                              size_t additional_data_length,
+                                              const uint8_t *plaintext,
+                                              size_t plaintext_length,
+                                              uint8_t *ciphertext,
+                                              size_t ciphertext_size,
+                                              size_t *ciphertext_length)
+{
+    psa_status_t status = PSA_SUCCESS;
+    enum tfm_crypto_err_t err;
+    uint8_t key_data[TFM_CRYPTO_MAX_KEY_LENGTH];
+    uint32_t key_size;
+    psa_key_type_t key_type;
+
+    if (PSA_ALG_IS_AEAD(alg) == 0) {
+        return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    if (PSA_AEAD_TAG_SIZE(alg) == 0) {
+        return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    if (PSA_AEAD_ENCRYPT_OUTPUT_SIZE(alg, plaintext_length) > ciphertext_size) {
+        return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    if ((nonce_length == 0) ||
+        ((additional_data_length == 0) && (additional_data != NULL))) {
+        return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    /* Validate pointers */
+    err = tfm_crypto_memory_check((void *)nonce,
+                                  nonce_length,
+                                  TFM_MEMORY_ACCESS_RO);
+    if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
+        return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    if ((additional_data != NULL) || (additional_data_length != 0)) {
+        err = tfm_crypto_memory_check((void *)additional_data,
+                                      additional_data_length,
+                                      TFM_MEMORY_ACCESS_RO);
+        if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
+            return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
+        }
+    }
+
+    err = tfm_crypto_memory_check((void *)plaintext,
+                                  plaintext_length,
+                                  TFM_MEMORY_ACCESS_RO);
+    if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
+        return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    err = tfm_crypto_memory_check((void *)ciphertext,
+                                  ciphertext_size,
+                                  TFM_MEMORY_ACCESS_RW);
+    if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
+        return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    err = tfm_crypto_memory_check((void *)ciphertext_length,
+                                  sizeof(size_t),
+                                  TFM_MEMORY_ACCESS_RW);
+    if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
+        return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    /* Access the key data */
+    err = tfm_crypto_get_key_information(key, &key_type, (size_t *)&key_size);
+    if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
+        return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    /* Access the crypto service key module to retrieve key data */
+    err = tfm_crypto_export_key(key,
+                                &key_data[0],
+                                TFM_CRYPTO_MAX_KEY_LENGTH,
+                                (size_t *)&key_size);
+    if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
+        return err;
+    }
+
+    /* Request AEAD encryption on the crypto engine */
+    status = tfm_crypto_engine_aead_encrypt(key_type,
+                                            alg,
+                                            key_data,
+                                            key_size,
+                                            nonce,
+                                            nonce_length,
+                                            additional_data,
+                                            additional_data_length,
+                                            plaintext,
+                                            plaintext_length,
+                                            ciphertext,
+                                            ciphertext_size,
+                                            (uint32_t *)ciphertext_length);
+
+    return PSA_STATUS_TO_TFM_CRYPTO_ERR(status);
+}
+
+enum tfm_crypto_err_t tfm_crypto_aead_decrypt(psa_key_slot_t key,
+                                              psa_algorithm_t alg,
+                                              const uint8_t *nonce,
+                                              size_t nonce_length,
+                                              const uint8_t *additional_data,
+                                              size_t additional_data_length,
+                                              const uint8_t *ciphertext,
+                                              size_t ciphertext_length,
+                                              uint8_t *plaintext,
+                                              size_t plaintext_size,
+                                              size_t *plaintext_length)
+{
+    psa_status_t status = PSA_SUCCESS;
+    enum tfm_crypto_err_t err;
+    uint8_t key_data[TFM_CRYPTO_MAX_KEY_LENGTH];
+    uint32_t key_size;
+    psa_key_type_t key_type;
+
+    if (PSA_ALG_IS_AEAD(alg) == 0) {
+        return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    if (PSA_AEAD_TAG_SIZE(alg) == 0) {
+        return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    if (PSA_AEAD_DECRYPT_OUTPUT_SIZE(alg, ciphertext_length) > plaintext_size) {
+        return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    if ((nonce_length == 0) ||
+        ((additional_data_length == 0) && (additional_data != NULL))) {
+        return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    /* Validate pointers */
+    err = tfm_crypto_memory_check((void *)nonce,
+                                  nonce_length,
+                                  TFM_MEMORY_ACCESS_RO);
+    if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
+        return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    if ((additional_data != NULL) || (additional_data_length != 0)) {
+        err = tfm_crypto_memory_check((void *)additional_data,
+                                      additional_data_length,
+                                      TFM_MEMORY_ACCESS_RO);
+        if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
+            return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
+        }
+    }
+
+    err = tfm_crypto_memory_check((void *)ciphertext,
+                                  ciphertext_length,
+                                  TFM_MEMORY_ACCESS_RO);
+    if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
+        return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    err = tfm_crypto_memory_check((void *)plaintext,
+                                  plaintext_size,
+                                  TFM_MEMORY_ACCESS_RW);
+    if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
+        return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    err = tfm_crypto_memory_check((void *)plaintext_length,
+                                  sizeof(size_t),
+                                  TFM_MEMORY_ACCESS_RW);
+    if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
+        return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    /* Access the key data */
+    err = tfm_crypto_get_key_information(key, &key_type, (size_t *)&key_size);
+    if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
+        return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    /* Access the crypto service key module to retrieve key data */
+    err = tfm_crypto_export_key(key,
+                                &key_data[0],
+                                TFM_CRYPTO_MAX_KEY_LENGTH,
+                                (size_t *)&key_size);
+    if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
+        return err;
+    }
+
+    /* Request AEAD decryption on the crypto engine */
+    status = tfm_crypto_engine_aead_decrypt(key_type,
+                                            alg,
+                                            key_data,
+                                            key_size,
+                                            nonce,
+                                            nonce_length,
+                                            additional_data,
+                                            additional_data_length,
+                                            ciphertext,
+                                            ciphertext_length,
+                                            plaintext,
+                                            plaintext_size,
+                                            (uint32_t *)plaintext_length);
+
+    return PSA_STATUS_TO_TFM_CRYPTO_ERR(status);
+}
+/*!@}*/
diff --git a/secure_fw/services/crypto/crypto_engine.c b/secure_fw/services/crypto/crypto_engine.c
index e1fdb17..f9fe896 100644
--- a/secure_fw/services/crypto/crypto_engine.c
+++ b/secure_fw/services/crypto/crypto_engine.c
@@ -537,3 +537,149 @@
 
     return return_value;
 }
+
+psa_status_t tfm_crypto_engine_aead_encrypt(psa_key_type_t key_type,
+                                            psa_algorithm_t alg,
+                                            const uint8_t *key_data,
+                                            uint32_t key_size,
+                                            const uint8_t *nonce,
+                                            uint32_t nonce_length,
+                                            const uint8_t *additional_data,
+                                            uint32_t additional_data_length,
+                                            const uint8_t *plaintext,
+                                            uint32_t plaintext_length,
+                                            uint8_t *ciphertext,
+                                            uint32_t ciphertext_size,
+                                            uint32_t *ciphertext_length)
+{
+    psa_status_t return_value = PSA_ERROR_NOT_SUPPORTED;
+
+#if defined(TFM_CRYPTO_ENGINE_MBEDTLS)
+    int ret;
+    mbedtls_cipher_context_t aead_ctx;
+    const uint32_t key_size_bits = PSA_BYTES_TO_BITS(key_size);
+
+    const mbedtls_cipher_info_t *info = get_mbedtls_cipher_info(key_type,
+                                                                alg,
+                                                                key_size_bits);
+    const uint32_t encrypted_message_length =
+                           PSA_AEAD_ENCRYPT_OUTPUT_SIZE(alg, plaintext_length) -
+                                                         PSA_AEAD_TAG_SIZE(alg);
+    if (info == NULL) {
+        /* The combination of key_type, alg and key_size is not a valid Mbed TLS
+         * cipher configuration.
+         */
+        return_value = PSA_ERROR_NOT_SUPPORTED;
+    } else {
+        /* Init the mbedTLS context */
+        mbedtls_cipher_init(&aead_ctx);
+
+        /* Setup the mbedTLS context */
+        ret = mbedtls_cipher_setup(&aead_ctx, info);
+        if (ret != 0) {
+            return_value = mbedtls_to_psa_return(ret);
+        } else {
+            /* Set the key on the Mbed TLS context */
+            ret = mbedtls_cipher_setkey(&aead_ctx,
+                                        key_data,
+                                        key_size_bits,
+                                        MBEDTLS_ENCRYPT);
+            if (ret != 0) {
+                return_value = mbedtls_to_psa_return(ret);
+            } else {
+                /* Perform the AEAD operation on the Mbed TLS context */
+                ret = mbedtls_cipher_auth_encrypt(&aead_ctx,
+                                                  nonce, nonce_length,
+                                                  additional_data,
+                                                  additional_data_length,
+                                                  plaintext,
+                                                  plaintext_length,
+                                                  ciphertext,
+                                                  (size_t *)ciphertext_length,
+                                                  ciphertext +
+                                                      encrypted_message_length,
+                                                  PSA_AEAD_TAG_SIZE(alg));
+
+                /* Clear the Mbed TLS context */
+                mbedtls_cipher_free(&aead_ctx);
+                return_value = mbedtls_to_psa_return(ret);
+            }
+        }
+    }
+#endif /* TFM_CRYPTO_ENGINE_MBEDTLS */
+
+    return return_value;
+}
+
+psa_status_t tfm_crypto_engine_aead_decrypt(psa_key_type_t key_type,
+                                            psa_algorithm_t alg,
+                                            const uint8_t *key_data,
+                                            uint32_t key_size,
+                                            const uint8_t *nonce,
+                                            uint32_t nonce_length,
+                                            const uint8_t *additional_data,
+                                            uint32_t additional_data_length,
+                                            const uint8_t *ciphertext,
+                                            uint32_t ciphertext_length,
+                                            uint8_t *plaintext,
+                                            uint32_t plaintext_size,
+                                            uint32_t *plaintext_length)
+{
+    psa_status_t return_value = PSA_ERROR_NOT_SUPPORTED;
+
+#if defined(TFM_CRYPTO_ENGINE_MBEDTLS)
+    int ret;
+    mbedtls_cipher_context_t aead_ctx;
+    const uint32_t key_size_bits = PSA_BYTES_TO_BITS(key_size);
+
+    const mbedtls_cipher_info_t *info = get_mbedtls_cipher_info(key_type,
+                                                                alg,
+                                                                key_size_bits);
+
+    const uint32_t encrypted_message_length =
+                           PSA_AEAD_DECRYPT_OUTPUT_SIZE(alg, ciphertext_length);
+    if (info == NULL) {
+        /* The combination of key_type, alg and key_size is not a valid Mbed TLS
+         * cipher configuration.
+         */
+        return_value = PSA_ERROR_NOT_SUPPORTED;
+    } else {
+        /* Init the mbedTLS context */
+        mbedtls_cipher_init(&aead_ctx);
+
+        /* Setup the mbedTLS context */
+        ret = mbedtls_cipher_setup(&aead_ctx, info);
+        if (ret != 0) {
+            return_value = mbedtls_to_psa_return(ret);
+        } else {
+             /* Set the key on the Mbed TLS context */
+            ret = mbedtls_cipher_setkey(&aead_ctx,
+                                        key_data,
+                                        key_size_bits,
+                                        MBEDTLS_DECRYPT);
+            if (ret != 0) {
+                return_value = mbedtls_to_psa_return(ret);
+            } else {
+                /* Perform the AEAD operation on the Mbed TLS context */
+                ret = mbedtls_cipher_auth_decrypt(&aead_ctx,
+                                                  nonce, nonce_length,
+                                                  additional_data,
+                                                  additional_data_length,
+                                                  ciphertext,
+                                                  encrypted_message_length,
+                                                  plaintext,
+                                                  (size_t *)plaintext_length,
+                                                  ciphertext +
+                                                      encrypted_message_length,
+                                                  PSA_AEAD_TAG_SIZE(alg));
+
+                /* Clear the Mbed TLS context */
+                mbedtls_cipher_free(&aead_ctx);
+                return_value = mbedtls_to_psa_return(ret);
+            }
+        }
+    }
+#endif /* TFM_CRYPTO_ENGINE_MBEDTLS */
+
+    return return_value;
+}
diff --git a/secure_fw/services/crypto/crypto_engine.h b/secure_fw/services/crypto/crypto_engine.h
index a4e388d..c5771bf 100644
--- a/secure_fw/services/crypto/crypto_engine.h
+++ b/secure_fw/services/crypto/crypto_engine.h
@@ -302,6 +302,82 @@
  * \return Return values as specified by \ref psa_status_t
  */
 psa_status_t tfm_crypto_engine_cipher_release(union engine_cipher_context *cp);
+
+/**
+ * \brief This function performs an AEAD encryption on the provided data
+ *
+ * \param[in]  key_type               Key type of the key that will be used
+ * \param[in]  alg                    Algorithm to be used
+ * \param[in]  key_data               Pointer to the buffer containing key
+ *                                    material
+ * \param[in]  key_size               Size in bytes of the key pointed to by
+ *                                    key_data
+ * \param[in]  nonce                  Pointer to a buffer holding a nonce or IV
+ *                                    to use
+ * \param[in]  nonce_length           Size in bytes of the nonce or IV data
+ * \param[in]  additional_data        Additional information to be authenticated
+ * \param[in]  additional_data_length Size in bytes of the additional data
+ * \param[in]  plaintext              Buffer pointing to data to be encrypted
+ * \param[in]  plaintext_length       Size in bytes of the plain text buffer
+ * \param[out] ciphertext             Output encrypted data, with the
+ *                                    authentication tag appended
+ * \param[in]  ciphertext_size        Size in bytes of the buffer to hold the
+ *                                    cipher text plus authentication tag
+ * \param[out] ciphertext_length      Size of the ciphertext plus tag produced
+ *                                    as output
+ *
+ * \return Return values as specified by \ref psa_status_t
+ */
+psa_status_t tfm_crypto_engine_aead_encrypt(psa_key_type_t key_type,
+                                            psa_algorithm_t alg,
+                                            const uint8_t *key_data,
+                                            uint32_t key_size,
+                                            const uint8_t *nonce,
+                                            uint32_t nonce_length,
+                                            const uint8_t *additional_data,
+                                            uint32_t additional_data_length,
+                                            const uint8_t *plaintext,
+                                            uint32_t plaintext_length,
+                                            uint8_t *ciphertext,
+                                            uint32_t ciphertext_size,
+                                            uint32_t *ciphertext_length);
+/**
+ * \brief This function performs an AEAD decryption on the provided data
+ *
+ * \param[in]  key_type               Key type of the key that will be used
+ * \param[in]  alg                    Algorithm to be used
+ * \param[in]  key_data               Pointer to the buffer containing key
+ *                                    material
+ * \param[in]  key_size               Size in bytes of the key pointed to by
+ *                                    key_data
+ * \param[in]  nonce                  Pointer to a buffer holding a nonce or IV
+ *                                    to use
+ * \param[in]  nonce_length           Size in bytes of the nonce or IV data
+ * \param[in]  additional_data        Additional information which was
+ *                                    authenticated but not encrypted
+ * \param[in]  additional_data_length Size in bytes of the additional data
+ * \param[in]  ciphertext             Buffer pointing to data be decrypted
+ * \param[in]  ciphertext_length      Size in bytes of the cipher text buffer
+ * \param[out] plaintext              Buffer for decrypted output data
+ * \param[in]  plaintext_size         Size in bytes of the buffer to hold the
+ *                                    plain text
+ * \param[out] plaintext_length       Size of the plain text actually produced
+ *
+ * \return Return values as specified by \ref psa_status_t
+ */
+psa_status_t tfm_crypto_engine_aead_decrypt(psa_key_type_t key_type,
+                                            psa_algorithm_t alg,
+                                            const uint8_t *key_data,
+                                            uint32_t key_size,
+                                            const uint8_t *nonce,
+                                            uint32_t nonce_length,
+                                            const uint8_t *additional_data,
+                                            uint32_t additional_data_length,
+                                            const uint8_t *ciphertext,
+                                            uint32_t ciphertext_length,
+                                            uint8_t *plaintext,
+                                            uint32_t plaintext_size,
+                                            uint32_t *plaintext_length);
 #ifdef __cplusplus
 }
 #endif
diff --git a/secure_fw/services/crypto/crypto_wrappers.c b/secure_fw/services/crypto/crypto_wrappers.c
index cb68600..40e08ce 100644
--- a/secure_fw/services/crypto/crypto_wrappers.c
+++ b/secure_fw/services/crypto/crypto_wrappers.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, Arm Limited. All rights reserved.
+ * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  *
@@ -24,7 +24,6 @@
                                       struct psa_cipher_update_output *output_s)
 {
     /* Extract the following fields from the input and output structures */
-
     const uint8_t *input = input_s->input;
     size_t input_length = input_s->input_length;
 
@@ -35,4 +34,52 @@
     return tfm_crypto_cipher_update(operation, input, input_length,
                                     output, output_size, output_length);
 }
+
+enum tfm_crypto_err_t tfm_crypto_aead_encrypt_wrapper(
+                                        struct psa_aead_encrypt_input *input_s,
+                                      struct psa_aead_encrypt_output *output_s)
+{
+    /* Extract the following fields from the input and output structures */
+    psa_key_slot_t key = input_s->key;
+    psa_algorithm_t alg = input_s->alg;
+    const uint8_t *nonce = input_s->nonce;
+    size_t nonce_length = input_s->nonce_length;
+    const uint8_t *additional_data = input_s->additional_data;
+    size_t additional_data_length = input_s->additional_data_length;
+    const uint8_t *plaintext = input_s->plaintext;
+    size_t plaintext_length = input_s->plaintext_length;
+
+    uint8_t *ciphertext = output_s->ciphertext;
+    size_t ciphertext_size = output_s->ciphertext_size;
+    size_t *ciphertext_length = output_s->ciphertext_length;
+
+    return tfm_crypto_aead_encrypt(key, alg, nonce, nonce_length,
+                                   additional_data, additional_data_length,
+                                   plaintext, plaintext_length, ciphertext,
+                                   ciphertext_size, ciphertext_length);
+}
+
+enum tfm_crypto_err_t tfm_crypto_aead_decrypt_wrapper(
+                                        struct psa_aead_decrypt_input *input_s,
+                                      struct psa_aead_decrypt_output *output_s)
+{
+    /* Extract the following fields from the input and output structures */
+    psa_key_slot_t key = input_s->key;
+    psa_algorithm_t alg = input_s->alg;
+    const uint8_t *nonce = input_s->nonce;
+    size_t nonce_length = input_s->nonce_length;
+    const uint8_t *additional_data = input_s->additional_data;
+    size_t additional_data_length = input_s->additional_data_length;
+    const uint8_t *ciphertext = input_s->ciphertext;
+    size_t ciphertext_length = input_s->ciphertext_length;
+
+    uint8_t *plaintext = output_s->plaintext;
+    size_t plaintext_size = output_s->plaintext_size;
+    size_t *plaintext_length = output_s->plaintext_length;
+
+    return tfm_crypto_aead_decrypt(key, alg, nonce, nonce_length,
+                                   additional_data, additional_data_length,
+                                   ciphertext, ciphertext_length, plaintext,
+                                   plaintext_size, plaintext_length);
+}
 /*!@}*/
diff --git a/secure_fw/services/crypto/manifest.yaml b/secure_fw/services/crypto/manifest.yaml
index c6037a9..dae7a12 100644
--- a/secure_fw/services/crypto/manifest.yaml
+++ b/secure_fw/services/crypto/manifest.yaml
@@ -185,6 +185,22 @@
       "minor_version": 1,
       "minor_policy": "strict"
     },
+    {
+      "sfid": "TFM_CRYPTO_AEAD_DECRYPT_SFID",
+      "signal": "TFM_CRYPTO_AEAD_DECRYPT",
+      "tfm_symbol": "tfm_crypto_aead_decrypt_wrapper",
+      "non_secure_clients": true,
+      "minor_version": 1,
+      "minor_policy": "strict"
+    },
+    {
+      "sfid": "TFM_CRYPTO_AEAD_ENCRYPT_SFID",
+      "signal": "TFM_CRYPTO_AEAD_ENCRYPT",
+      "tfm_symbol": "tfm_crypto_aead_encrypt_wrapper",
+      "non_secure_clients": true,
+      "minor_version": 1,
+      "minor_policy": "strict"
+    },
   ],
   "source_files": [
     "crypto_alloc.c",
@@ -195,7 +211,8 @@
     "crypto_utils.c",
     "crypto_hash.c",
     "crypto_engine.c",
-    "crypto_mac.c"
+    "crypto_mac.c",
+    "crypto_aead.c",
   ],
   "tfm_linker_pattern": [
     "library_list": [
diff --git a/secure_fw/services/crypto/tfm_crypto_api.h b/secure_fw/services/crypto/tfm_crypto_api.h
index 3638885..af8f7fb 100644
--- a/secure_fw/services/crypto/tfm_crypto_api.h
+++ b/secure_fw/services/crypto/tfm_crypto_api.h
@@ -405,6 +405,73 @@
  */
 enum tfm_crypto_err_t tfm_crypto_mac_abort(psa_mac_operation_t *operation);
 
+/**
+ * \brief Perform an AEAD encryption operation on input data with additional
+ *        data to be authenticated, producing ciphertext in output with an
+ *        appended authentication tag
+ *
+ * \param[in]  key                    Key slot for the key
+ * \param[in]  alg                    Algorithm to be used
+ * \param[in]  nonce                  Pointer to a buffer holding a nonce or IV
+ *                                    to use
+ * \param[in]  nonce_length           Size in bytes of the nonce or IV data
+ * \param[in]  additional_data        Additional information to be authenticated
+ * \param[in]  additional_data_length Size in bytes of the additional data
+ * \param[in]  plaintext              Buffer pointing to data to be encrypted
+ * \param[in]  plaintext_length       Size in bytes of the plain text buffer
+ * \param[out] ciphertext             Output encrypted data, with the
+ *                                    authentication tag appended
+ * \param[in]  ciphertext_size        Size in bytes of the buffer to hold the
+ *                                    cipher text plus authentication tag
+ * \param[out] ciphertext_length      Size of the ciphertext plus tag produced
+ *                                    as output
+ *
+ * \return Return values as described in \ref tfm_crypto_err_t
+ */
+enum tfm_crypto_err_t tfm_crypto_aead_encrypt(psa_key_slot_t key,
+                                              psa_algorithm_t alg,
+                                              const uint8_t *nonce,
+                                              size_t nonce_length,
+                                              const uint8_t *additional_data,
+                                              size_t additional_data_length,
+                                              const uint8_t *plaintext,
+                                              size_t plaintext_length,
+                                              uint8_t *ciphertext,
+                                              size_t ciphertext_size,
+                                              size_t *ciphertext_length);
+/**
+ * \brief Perform an AEAD decryption operation on input data with additional
+ *        data to be verified, producing back the original plain text in case
+ *        the verification of the authentication tag is successful
+ *
+ * \param[in]  key                    Key slot for the key
+ * \param[in]  alg                    Algorithm to be used
+ * \param[in]  nonce                  Pointer to a buffer holding a nonce or IV
+ *                                    to use
+ * \param[in]  nonce_length           Size in bytes of the nonce or IV data
+ * \param[in]  additional_data        Additional information which was
+ *                                    authenticated but not encrypted
+ * \param[in]  additional_data_length Size in bytes of the additional data
+ * \param[in]  ciphertext             Buffer pointing to data be decrypted
+ * \param[in]  ciphertext_length      Size in bytes of the cipher text buffer
+ * \param[out] plaintext              Buffer for decrypted output data
+ * \param[in]  plaintext_size         Size in bytes of the buffer to hold the
+ *                                    plain text
+ * \param[out] plaintext_length       Size of the plain text actually produced
+ *
+ * \return Return values as described in \ref tfm_crypto_err_t
+ */
+enum tfm_crypto_err_t tfm_crypto_aead_decrypt(psa_key_slot_t key,
+                                              psa_algorithm_t alg,
+                                              const uint8_t *nonce,
+                                              size_t nonce_length,
+                                              const uint8_t *additional_data,
+                                              size_t additional_data_length,
+                                              const uint8_t *ciphertext,
+                                              size_t ciphertext_length,
+                                              uint8_t *plaintext,
+                                              size_t plaintext_size,
+                                              size_t *plaintext_length);
 #ifdef __cplusplus
 }
 #endif
diff --git a/secure_fw/services/tfm_sfid_list.inc b/secure_fw/services/tfm_sfid_list.inc
index 0a38ac1..f9d0708 100644
--- a/secure_fw/services/tfm_sfid_list.inc
+++ b/secure_fw/services/tfm_sfid_list.inc
@@ -48,6 +48,8 @@
     {tfm_crypto_mac_sign_finish, TFM_CRYPTO_MAC_SIGN_FINISH_SFID},
     {tfm_crypto_mac_verify_finish, TFM_CRYPTO_MAC_VERIFY_FINISH_SFID},
     {tfm_crypto_mac_abort, TFM_CRYPTO_MAC_ABORT_SFID},
+    {tfm_crypto_aead_decrypt_wrapper, TFM_CRYPTO_AEAD_DECRYPT_SFID},
+    {tfm_crypto_aead_encrypt_wrapper, TFM_CRYPTO_AEAD_ENCRYPT_SFID},
 
     /******** TFM_SP_PLATFORM ********/
     {platform_sp_system_reset, TFM_SP_PLATFORM_SYSTEM_RESET_SFID},