Crypto: Add support for single-shot MAC APIs

This patch introduces support for single-shot MAC
APIs in the TF-M Crypto service. It needs to be
aligned with a version of MbedTLS which is new
enough to have support in the backend for these APIs.

Signed-off-by: Antonio de Angelis <antonio.deangelis@arm.com>
Change-Id: I8aa69b251a701a652f1b8d77b886431bd38681e8
diff --git a/interface/src/tfm_crypto_func_api.c b/interface/src/tfm_crypto_func_api.c
index 6ff25a1..9e015fa 100644
--- a/interface/src/tfm_crypto_func_api.c
+++ b/interface/src/tfm_crypto_func_api.c
@@ -1248,9 +1248,25 @@
                              size_t *mac_length)
 {
     psa_status_t status;
+    struct tfm_crypto_pack_iovec iov = {
+        .sfn_id = TFM_CRYPTO_MAC_COMPUTE_SID,
+        .alg = alg,
+        .key_id = key,
+    };
 
-    status = PSA_ERROR_NOT_SUPPORTED;
+    psa_invec in_vec[] = {
+        {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)},
+        {.base = input, .len = input_length}
+    };
 
+    psa_outvec out_vec[] = {
+        {.base = mac, .len = mac_size}
+    };
+
+    status = API_DISPATCH(tfm_crypto_mac_compute,
+                          TFM_CRYPTO_MAC_COMPUTE);
+
+    *mac_length = out_vec[0].len;
     return status;
 }
 
@@ -1262,8 +1278,20 @@
                             const size_t mac_length)
 {
     psa_status_t status;
+    struct tfm_crypto_pack_iovec iov = {
+        .sfn_id = TFM_CRYPTO_MAC_VERIFY_SID,
+        .alg = alg,
+        .key_id = key,
+    };
 
-    status = PSA_ERROR_NOT_SUPPORTED;
+    psa_invec in_vec[] = {
+        {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)},
+        {.base = input, .len = input_length},
+        {.base = mac, .len = mac_length}
+    };
+
+    status = API_DISPATCH_NO_OUTVEC(tfm_crypto_mac_verify,
+                                    TFM_CRYPTO_MAC_VERIFY);
 
     return status;
 }
diff --git a/interface/src/tfm_crypto_ipc_api.c b/interface/src/tfm_crypto_ipc_api.c
index e925c36..953dd11 100644
--- a/interface/src/tfm_crypto_ipc_api.c
+++ b/interface/src/tfm_crypto_ipc_api.c
@@ -1273,9 +1273,25 @@
                              size_t *mac_length)
 {
     psa_status_t status;
+    struct tfm_crypto_pack_iovec iov = {
+        .sfn_id = TFM_CRYPTO_MAC_COMPUTE_SID,
+        .alg = alg,
+        .key_id = key,
+    };
 
-    status = PSA_ERROR_NOT_SUPPORTED;
+    psa_invec in_vec[] = {
+        {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)},
+        {.base = input, .len = input_length}
+    };
 
+    psa_outvec out_vec[] = {
+        {.base = mac, .len = mac_size}
+    };
+
+    status = API_DISPATCH(tfm_crypto_mac_compute,
+                          TFM_CRYPTO_MAC_COMPUTE);
+
+    *mac_length = out_vec[0].len;
     return status;
 }
 
@@ -1287,8 +1303,20 @@
                             const size_t mac_length)
 {
     psa_status_t status;
+    struct tfm_crypto_pack_iovec iov = {
+        .sfn_id = TFM_CRYPTO_MAC_VERIFY_SID,
+        .alg = alg,
+        .key_id = key,
+    };
 
-    status = PSA_ERROR_NOT_SUPPORTED;
+    psa_invec in_vec[] = {
+        {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)},
+        {.base = input, .len = input_length},
+        {.base = mac, .len = mac_length}
+    };
+
+    status = API_DISPATCH_NO_OUTVEC(tfm_crypto_mac_verify,
+                                    TFM_CRYPTO_MAC_VERIFY);
 
     return status;
 }
diff --git a/secure_fw/partitions/crypto/crypto_mac.c b/secure_fw/partitions/crypto/crypto_mac.c
index 1c4beae..3580826 100644
--- a/secure_fw/partitions/crypto/crypto_mac.c
+++ b/secure_fw/partitions/crypto/crypto_mac.c
@@ -321,8 +321,35 @@
                                     psa_outvec out_vec[],
                                     size_t out_len)
 {
-    /* FixMe: To be implemented */
+#ifdef TFM_CRYPTO_MAC_MODULE_DISABLED
     return PSA_ERROR_NOT_SUPPORTED;
+#else
+
+    CRYPTO_IN_OUT_LEN_VALIDATE(in_len, 1, 2, out_len, 0, 1);
+
+    if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec))) {
+         return PSA_ERROR_PROGRAMMER_ERROR;
+    }
+
+    const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
+    psa_algorithm_t alg = iov->alg;
+    psa_key_id_t key_id = iov->key_id;
+    const uint8_t *input = in_vec[1].base;
+    size_t input_length = in_vec[1].len;
+    uint8_t *output = out_vec[0].base;
+    size_t output_size = out_vec[0].len;
+    psa_status_t status;
+    mbedtls_svc_key_id_t encoded_key;
+
+    status = tfm_crypto_encode_id_and_owner(key_id, &encoded_key);
+    if (status != PSA_SUCCESS) {
+        return status;
+    }
+
+    return psa_mac_compute(encoded_key, alg, input, input_length,
+                          output, output_size, &out_vec[0].len);
+
+#endif /* TFM_CRYPTO_MAC_MODULE_DISABLED */
 }
 
 psa_status_t tfm_crypto_mac_verify(psa_invec in_vec[],
@@ -330,7 +357,35 @@
                                    psa_outvec out_vec[],
                                    size_t out_len)
 {
-    /* FixMe: To be implemented */
+#ifdef TFM_CRYPTO_MAC_MODULE_DISABLED
     return PSA_ERROR_NOT_SUPPORTED;
+#else
+
+    CRYPTO_IN_OUT_LEN_VALIDATE(in_len, 1, 3, out_len, 0, 0);
+
+    if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec))) {
+         return PSA_ERROR_PROGRAMMER_ERROR;
+    }
+
+    const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
+    psa_algorithm_t alg = iov->alg;
+    psa_key_id_t key_id = iov->key_id;
+    const uint8_t *input = in_vec[1].base;
+    size_t input_length = in_vec[1].len;
+    const uint8_t *mac = in_vec[2].base;
+    size_t mac_length = in_vec[2].len;
+    mbedtls_svc_key_id_t encoded_key;
+    psa_status_t status;
+
+    status = tfm_crypto_encode_id_and_owner(key_id, &encoded_key);
+    if (status != PSA_SUCCESS) {
+        return status;
+    }
+
+    return psa_mac_verify(encoded_key, alg,
+                          input, input_length,
+                          mac, mac_length);
+
+#endif /* TFM_CRYPTO_MAC_MODULE_DISABLED */
 }
 /*!@}*/
diff --git a/secure_fw/partitions/crypto/tfm_crypto_secure_api.c b/secure_fw/partitions/crypto/tfm_crypto_secure_api.c
index be1d0ba..7f57fea 100644
--- a/secure_fw/partitions/crypto/tfm_crypto_secure_api.c
+++ b/secure_fw/partitions/crypto/tfm_crypto_secure_api.c
@@ -1482,7 +1482,7 @@
     return status;
 }
 
-psa_status_t psa_mac_compute(psa_key_id_t key_id,
+psa_status_t psa_mac_compute(psa_key_id_t key,
                              psa_algorithm_t alg,
                              const uint8_t *input,
                              size_t input_length,
@@ -1491,13 +1491,29 @@
                              size_t *mac_length)
 {
     psa_status_t status;
+    struct tfm_crypto_pack_iovec iov = {
+        .sfn_id = TFM_CRYPTO_MAC_COMPUTE_SID,
+        .alg = alg,
+        .key_id = key,
+    };
 
-    status = PSA_ERROR_NOT_SUPPORTED;
+    psa_invec in_vec[] = {
+        {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)},
+        {.base = input, .len = input_length}
+    };
 
+    psa_outvec out_vec[] = {
+        {.base = mac, .len = mac_size}
+    };
+
+    status = API_DISPATCH(tfm_crypto_mac_compute,
+                          TFM_CRYPTO_MAC_COMPUTE);
+
+    *mac_length = out_vec[0].len;
     return status;
 }
 
-psa_status_t psa_mac_verify(psa_key_id_t key_id,
+psa_status_t psa_mac_verify(psa_key_id_t key,
                             psa_algorithm_t alg,
                             const uint8_t *input,
                             size_t input_length,
@@ -1505,8 +1521,20 @@
                             const size_t mac_length)
 {
     psa_status_t status;
+    struct tfm_crypto_pack_iovec iov = {
+        .sfn_id = TFM_CRYPTO_MAC_VERIFY_SID,
+        .alg = alg,
+        .key_id = key,
+    };
 
-    status = PSA_ERROR_NOT_SUPPORTED;
+    psa_invec in_vec[] = {
+        {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)},
+        {.base = input, .len = input_length},
+        {.base = mac, .len = mac_length}
+    };
+
+    status = API_DISPATCH_NO_OUTVEC(tfm_crypto_mac_verify,
+                                    TFM_CRYPTO_MAC_VERIFY);
 
     return status;
 }