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/interface/include/crypto_psa_wrappers.h b/interface/include/crypto_psa_wrappers.h
index c337962..c34f828 100644
--- a/interface/include/crypto_psa_wrappers.h
+++ b/interface/include/crypto_psa_wrappers.h
@@ -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
*
@@ -50,6 +50,90 @@
struct psa_cipher_update_input *input_s,
struct psa_cipher_update_output *output_s);
+/*!
+ * \struct psa_aead_encrypt_input
+ *
+ * \brief Input structure for the tfm_crypto_aead_encrypt_wrapper function
+ *
+ */
+struct psa_aead_encrypt_input {
+ psa_key_slot_t key; /*!< Key slot */
+ psa_algorithm_t alg; /*!< Algorithm type */
+ const uint8_t *nonce; /*!< Nonce or IV to be used */
+ size_t nonce_length; /*!< Size in bytes of the nonce buffer */
+ const uint8_t *additional_data; /*!< Additional data to be authenticated */
+ size_t additional_data_length; /*!< Size in bytes of additional_data */
+ const uint8_t *plaintext; /*!< Buffer holding data for encryption */
+ size_t plaintext_length; /*!< Size in bytes of plaintext */
+};
+
+/*!
+ * \struct psa_aead_encrypt_output
+ *
+ * \brief Output structure for the tfm_crypto_aead_encrypt_wrapper function
+ *
+ */
+struct psa_aead_encrypt_output {
+ uint8_t *ciphertext; /*!< Pointer for the buffer to hold ciphertext */
+ size_t ciphertext_size; /*!< Size in bytes of the ciphertext buffer */
+ size_t *ciphertext_length; /*!< Actual size in bytes of ciphertext */
+};
+
+/*!
+ * \struct psa_aead_decrypt_input
+ *
+ * \brief Input structure for the tfm_crypto_aead_decrypt_wrapper function
+ *
+ */
+struct psa_aead_decrypt_input {
+ psa_key_slot_t key; /*!< Key slot */
+ psa_algorithm_t alg; /*!< Algorithm type */
+ const uint8_t *nonce; /*!< Nonce or IV to be used */
+ size_t nonce_length; /*!< Size in bytes of the nonce buffer */
+ const uint8_t *additional_data; /*!< Original data that was authenticated */
+ size_t additional_data_length; /*!< Size in bytes of additional_data */
+ const uint8_t *ciphertext; /*!< Buffer holding data for decryption */
+ size_t ciphertext_length; /*!< Size in bytes of ciphertext */
+};
+
+/*!
+ * \struct psa_aead_decrypt_output
+ *
+ * \brief Output structure for the tfm_crypto_aead_decrypt_wrapper function
+ *
+ */
+struct psa_aead_decrypt_output {
+ uint8_t *plaintext; /*!< Pointer for the buffer to hold plaintext */
+ size_t plaintext_size; /*!< Size in bytes of the plaintext buffer */
+ size_t *plaintext_length; /*!< Actual size in bytes of plaintext */
+};
+
+/*!
+ * \brief This function is a TF-M compatible wrapper for the
+ * \ref tfm_crypto_aead_encrypt implemented in the Crypto service
+ *
+ * \param[in] input_s Pointer to the structure containing input parameters
+ * associated with \ref psa_aead_encrypt_input
+ * \param[out] output_s Pointer to the structure containing output parameters
+ * associated with \ref psa_aead_encrypt_output
+ *
+ */
+enum tfm_crypto_err_t tfm_crypto_aead_encrypt_wrapper(
+ struct psa_aead_encrypt_input *input_s,
+ struct psa_aead_encrypt_output *output_s);
+/*!
+ * \brief This function is a TF-M compatible wrapper for the
+ * \ref tfm_crypto_aead_decrypt implemented in the Crypto service
+ *
+ * \param[in] input_s Pointer to the structure containing input parameters
+ * associated with \ref psa_aead_decrypt_input
+ * \param[out] output_s Pointer to the structure containing output parameters
+ * associated with \ref psa_aead_decrypt_output
+ *
+ */
+enum tfm_crypto_err_t tfm_crypto_aead_decrypt_wrapper(
+ struct psa_aead_decrypt_input *input_s,
+ struct psa_aead_decrypt_output *output_s);
#ifdef __cplusplus
}
#endif
diff --git a/interface/include/psa_crypto_sizes.h b/interface/include/psa_crypto_sizes.h
index 07b52e4..e21c130 100644
--- a/interface/include/psa_crypto_sizes.h
+++ b/interface/include/psa_crypto_sizes.h
@@ -156,7 +156,7 @@
*/
#define PSA_AEAD_DECRYPT_OUTPUT_SIZE(alg, ciphertext_length) \
(PSA_AEAD_TAG_SIZE(alg) != 0 ? \
- (plaintext_length) - PSA_AEAD_TAG_SIZE(alg) : \
+ (ciphertext_length) - PSA_AEAD_TAG_SIZE(alg) : \
0)
/** Safe signature buffer size for psa_asymmetric_sign().
diff --git a/interface/include/tfm_crypto_veneers.h b/interface/include/tfm_crypto_veneers.h
index 312c2c3..83ab510 100644
--- a/interface/include/tfm_crypto_veneers.h
+++ b/interface/include/tfm_crypto_veneers.h
@@ -242,7 +242,6 @@
*/
enum tfm_crypto_err_t tfm_crypto_veneer_hash_abort(
psa_hash_operation_t *operation);
-
/**
* \brief Start a MAC operation with the provided algorithm (for signing)
* (veneer function)
@@ -342,6 +341,33 @@
*/
enum tfm_crypto_err_t tfm_crypto_veneer_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 (veneer function)
+ *
+ * \param[in] input_s Pointer to the struct containing input parameters
+ * \param[out] output_s Pointer to the struct containing output parameters
+ *
+ * \return Return values as described in \ref tfm_crypto_err_t
+ */
+enum tfm_crypto_err_t tfm_crypto_veneer_aead_encrypt(
+ struct psa_aead_encrypt_input *input_s,
+ struct psa_aead_encrypt_output *output_s);
+/**
+ * \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 (veneer
+ * function)
+ *
+ * \param[in] input_s Pointer to the struct containing input parameters
+ * \param[out] output_s Pointer to the struct containing output parameters
+ *
+ * \return Return values as described in \ref tfm_crypto_err_t
+ */
+enum tfm_crypto_err_t tfm_crypto_veneer_aead_decrypt(
+ struct psa_aead_decrypt_input *input_s,
+ struct psa_aead_decrypt_output *output_s);
#ifdef __cplusplus
}
diff --git a/interface/src/tfm_crypto_api.c b/interface/src/tfm_crypto_api.c
index a1bf389..8069934 100644
--- a/interface/src/tfm_crypto_api.c
+++ b/interface/src/tfm_crypto_api.c
@@ -352,3 +352,86 @@
return TFM_CRYPTO_ERR_TO_PSA_STATUS(err);
}
+
+psa_status_t psa_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)
+{
+ enum tfm_crypto_err_t err;
+
+ /* Packing in structures is needed to overcome the 4 parameters
+ * per call limit
+ */
+ struct psa_aead_encrypt_input input_s = {.key = key,
+ .alg = alg,
+ .nonce = nonce,
+ .nonce_length = nonce_length,
+ .additional_data = additional_data,
+ .additional_data_length =
+ additional_data_length,
+ .plaintext = plaintext,
+ .plaintext_length =
+ plaintext_length};
+ struct psa_aead_encrypt_output output_s = {.ciphertext = ciphertext,
+ .ciphertext_size =
+ ciphertext_size,
+ .ciphertext_length =
+ ciphertext_length};
+
+ err = tfm_ns_lock_dispatch((veneer_fn)tfm_crypto_veneer_aead_encrypt,
+ (uint32_t)&input_s,
+ (uint32_t)&output_s,
+ 0,
+ 0);
+
+ return TFM_CRYPTO_ERR_TO_PSA_STATUS(err);
+}
+
+psa_status_t psa_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)
+{
+ enum tfm_crypto_err_t err;
+
+ /* Packing in structures is needed to overcome the 4 parameters
+ * per call limit
+ */
+ struct psa_aead_decrypt_input input_s = {.key = key,
+ .alg = alg,
+ .nonce = nonce,
+ .nonce_length = nonce_length,
+ .additional_data = additional_data,
+ .additional_data_length =
+ additional_data_length,
+ .ciphertext = ciphertext,
+ .ciphertext_length =
+ ciphertext_length};
+ struct psa_aead_decrypt_output output_s = {.plaintext = plaintext,
+ .plaintext_size = plaintext_size,
+ .plaintext_length =
+ plaintext_length};
+
+ err = tfm_ns_lock_dispatch((veneer_fn)tfm_crypto_veneer_aead_decrypt,
+ (uint32_t)&input_s,
+ (uint32_t)&output_s,
+ 0,
+ 0);
+
+ return TFM_CRYPTO_ERR_TO_PSA_STATUS(err);
+}