Crypto: Add support for HMAC functionalities

This patch introduces support for the HMAC functionalities.
The HMAC construction procedure is as described by RFC-2104.
It also adds the related Regression test suite to validate
the API implementation.

Change-Id: I622d866b34ba7e3a3e61e1a28d43fb80e49fd8ec
Signed-off-by: Louis Mayencourt <louis.mayencourt@arm.com>
diff --git a/interface/include/tfm_crypto_defs.h b/interface/include/tfm_crypto_defs.h
index 391df84..ed85dc8 100644
--- a/interface/include/tfm_crypto_defs.h
+++ b/interface/include/tfm_crypto_defs.h
@@ -25,7 +25,13 @@
  * \brief This defines the maximum supported key length in bytes
  *
  */
-#define TFM_CRYPTO_MAX_KEY_LENGTH (16)
+#define TFM_CRYPTO_MAX_KEY_LENGTH (32)
+
+/**
+ * \brief This value is used to mark an handle as invalid.
+ *
+ */
+#define TFM_CRYPTO_INVALID_HANDLE (0xFFFFFFFF)
 
 /**
  * \brief Define miscellaneous literal constants that are used in the module
diff --git a/interface/include/tfm_crypto_veneers.h b/interface/include/tfm_crypto_veneers.h
index 5079901..312c2c3 100644
--- a/interface/include/tfm_crypto_veneers.h
+++ b/interface/include/tfm_crypto_veneers.h
@@ -243,6 +243,106 @@
 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)
+ *
+ * \note A successful call to this function initialises a MAC operation
+ *       context which will be referred using the operation parameter
+ *
+ * \param[out] operation MAC operation context
+ * \param[in]  key       Key slot to bind to the MAC context
+ * \param[in]  alg       Algorithm chosen as MAC
+ *
+ * \return Return values as described in \ref tfm_crypto_err_t
+ */
+enum tfm_crypto_err_t tfm_crypto_veneer_mac_sign_setup(
+                                                 psa_mac_operation_t *operation,
+                                                 psa_key_slot_t key,
+                                                 psa_algorithm_t alg);
+/**
+ * \brief Start a MAC operation with the provided algorithm (for verifying)
+ *        (veneer function)
+ *
+ * \note A successful call to this function initialises a MAC operation
+ *       context which will be referred using the operation parameter
+ *
+ * \param[out] operation MAC operation context
+ * \param[in]  key       Key slot to bind to the MAC context
+ * \param[in]  alg       Algorithm chosen as MAC
+ *
+ * \return Return values as described in \ref tfm_crypto_err_t
+ */
+enum tfm_crypto_err_t tfm_crypto_veneer_mac_verify_setup(
+                                                 psa_mac_operation_t *operation,
+                                                 psa_key_slot_t key,
+                                                 psa_algorithm_t alg);
+/**
+ * \brief Adds a new input chunk to the data for which the final MAC value
+ *        will be computed (veneer function)
+ *
+ * \param[in/out] operation    MAC operation context
+ * \param[in]     input        Buffer containing the input data
+ * \param[in]     input_length Size of the provided input data
+ *
+ * \return Return values as described in \ref tfm_crypto_err_t
+ */
+enum tfm_crypto_err_t tfm_crypto_veneer_mac_update(
+                                                 psa_mac_operation_t *operation,
+                                                 const uint8_t *input,
+                                                 size_t input_length);
+
+/**
+ * \brief Finalises a MAC context operation producing the final MAC value
+ *        (veneer function)
+ *
+ * \note A successful call to this function releases the MAC operation
+ *       context provided as parameter
+ *
+ * \param[in/out] operation   MAC operation context
+ * \param[out]    mac         Buffer containing MAC data
+ * \param[in]     mac_size    Size of the MAC buffer
+ * \param[out]    mac_length  Size of the produced MAC
+ *
+ * \return Return values as described in \ref tfm_crypto_err_t
+ */
+enum tfm_crypto_err_t tfm_crypto_veneer_mac_sign_finish(
+                                                 psa_mac_operation_t *operation,
+                                                 uint8_t *mac,
+                                                 size_t mac_size,
+                                                 size_t *mac_length);
+/**
+ * \brief Finalise a MAC context operation, verifying that the final MAC value
+ *        matches the one provided as input (veneer function)
+ *
+ * \note A successful call to this function releases the MAC operation
+ *       context provided as parameter. The MAC operation is released
+ *       also in case TFM_CRYPTO_ERR_PSA_ERROR_INVALID_SIGNATURE is returned
+ *
+ * \param[in/out] operation   MAC operation context
+ * \param[in]     mac         Buffer containing the provided MAC value
+ * \param[in]     mac_length  Size of the provided MAC value
+ *
+ * \return Return values as described in \ref tfm_crypto_err_t
+ */
+enum tfm_crypto_err_t tfm_crypto_veneer_mac_verify_finish(
+                                                 psa_mac_operation_t *operation,
+                                                 const uint8_t *mac,
+                                                 size_t mac_length);
+/**
+ * \brief Abort a MAC operation, clear the operation context provided
+ *        (veneer function)
+ *
+ * \note A successful call to this function releases the MAC operation
+ *       context provided as parameter
+ *
+ * \param[in/out] operation MAC operation context
+ *
+ * \return Return values as described in \ref tfm_crypto_err_t
+ */
+enum tfm_crypto_err_t tfm_crypto_veneer_mac_abort(
+                                                psa_mac_operation_t *operation);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/interface/src/tfm_crypto_api.c b/interface/src/tfm_crypto_api.c
index 7eb0669..a1bf389 100644
--- a/interface/src/tfm_crypto_api.c
+++ b/interface/src/tfm_crypto_api.c
@@ -263,3 +263,92 @@
 
     return TFM_CRYPTO_ERR_TO_PSA_STATUS(err);
 }
+
+psa_status_t psa_mac_sign_setup(psa_mac_operation_t *operation,
+                                psa_key_slot_t key,
+                                psa_algorithm_t alg)
+{
+    enum tfm_crypto_err_t err;
+
+    err = tfm_ns_lock_dispatch((veneer_fn)tfm_crypto_veneer_mac_sign_setup,
+                               (uint32_t)operation,
+                               (uint32_t)key,
+                               (uint32_t)alg,
+                               0);
+
+    return TFM_CRYPTO_ERR_TO_PSA_STATUS(err);
+}
+
+psa_status_t psa_mac_verify_setup(psa_mac_operation_t *operation,
+                                  psa_key_slot_t key,
+                                  psa_algorithm_t alg)
+{
+    enum tfm_crypto_err_t err;
+
+    err = tfm_ns_lock_dispatch((veneer_fn)tfm_crypto_veneer_mac_verify_setup,
+                               (uint32_t)operation,
+                               (uint32_t)key,
+                               (uint32_t)alg,
+                               0);
+
+    return TFM_CRYPTO_ERR_TO_PSA_STATUS(err);
+}
+
+psa_status_t psa_mac_update(psa_mac_operation_t *operation,
+                            const uint8_t *input,
+                            size_t input_length)
+{
+    enum tfm_crypto_err_t err;
+
+    err = tfm_ns_lock_dispatch((veneer_fn)tfm_crypto_veneer_mac_update,
+                               (uint32_t)operation,
+                               (uint32_t)input,
+                               (uint32_t)input_length,
+                               0);
+
+    return TFM_CRYPTO_ERR_TO_PSA_STATUS(err);
+}
+
+psa_status_t psa_mac_sign_finish(psa_mac_operation_t *operation,
+                                 uint8_t *mac,
+                                 size_t mac_size,
+                                 size_t *mac_length)
+{
+    enum tfm_crypto_err_t err;
+
+    err = tfm_ns_lock_dispatch((veneer_fn)tfm_crypto_veneer_mac_sign_finish,
+                               (uint32_t)operation,
+                               (uint32_t)mac,
+                               (uint32_t)mac_size,
+                               (uint32_t)mac_length);
+
+    return TFM_CRYPTO_ERR_TO_PSA_STATUS(err);
+}
+
+psa_status_t psa_mac_verify_finish(psa_mac_operation_t *operation,
+                                   const uint8_t *mac,
+                                   size_t mac_length)
+{
+    enum tfm_crypto_err_t err;
+
+    err = tfm_ns_lock_dispatch((veneer_fn)tfm_crypto_veneer_mac_verify_finish,
+                               (uint32_t)operation,
+                               (uint32_t)mac,
+                               (uint32_t)mac_length,
+                               0);
+
+    return TFM_CRYPTO_ERR_TO_PSA_STATUS(err);
+}
+
+psa_status_t psa_mac_abort(psa_mac_operation_t *operation)
+{
+    enum tfm_crypto_err_t err;
+
+    err = tfm_ns_lock_dispatch((veneer_fn)tfm_crypto_veneer_mac_abort,
+                               (uint32_t)operation,
+                               0,
+                               0,
+                               0);
+
+    return TFM_CRYPTO_ERR_TO_PSA_STATUS(err);
+}