Crypto: Refactor the API dispatcher interface to reduce code size

This patch restructures the way the underlying APIs that
implements the PSA Crypto APIs are interfaced to the TF-M
Crypto service through a thin shim layer. The size of this
layer is reduced by nearly 45% on the default configuration.
Also, it removes the check for parameter number and size on
each function call as that is a redundant check as per the
overall threat model of the interaction between the crypto
service and the partition manager.

Signed-off-by: Antonio de Angelis <antonio.deangelis@arm.com>
Change-Id: I07165bad00346cd12cf63620532f55da0c5d1262
diff --git a/secure_fw/partitions/crypto/tfm_crypto_api.h b/secure_fw/partitions/crypto/tfm_crypto_api.h
index 42c643b..ef26901 100644
--- a/secure_fw/partitions/crypto/tfm_crypto_api.h
+++ b/secure_fw/partitions/crypto/tfm_crypto_api.h
@@ -14,21 +14,8 @@
 
 #include <stdint.h>
 #include "tfm_crypto_defs.h"
-#ifdef TFM_PSA_API
-#include "psa/service.h"
-
-/**
- * \brief This define is a function pointer type to the Uniform Signature API
- *        prototype.
- */
-typedef psa_status_t (*tfm_crypto_us_t)(psa_invec[],size_t,psa_outvec[],size_t);
-#endif
-
 #include "psa/crypto_client_struct.h"
 
-#define UNIFORM_SIGNATURE_API(api_name) \
-    psa_status_t api_name(psa_invec[], size_t, psa_outvec[], size_t)
-
 /**
  * \brief List of possible operation types supported by the TFM based
  *        implementation. This type is needed by the operation allocation,
@@ -48,6 +35,68 @@
 };
 
 /**
+ * \brief Type associated to a function for the TF-M Crypto service
+ *        API. It describes if an API is multipart related or not, i.e. and
+ *        which multipart operation it requires (i.e. setup or lookup)
+ */
+enum tfm_crypto_function_type {
+    TFM_CRYPTO_FUNCTION_TYPE_NON_MULTIPART = 0x0,
+    TFM_CRYPTO_FUNCTION_TYPE_SETUP,
+    TFM_CRYPTO_FUNCTION_TYPE_LOOKUP
+};
+
+/**
+ * \brief Type associated to the group of a function encoding. There can be
+ *        nine groups (Random, Key management, Hash, MAC, Cipher, AEAD,
+ *        Asym sign, Asym encrypt, Key derivation).
+ */
+enum tfm_crypto_group_id {
+    TFM_CRYPTO_GROUP_ID_RANDOM = 0x0,
+    TFM_CRYPTO_GROUP_ID_KEY_MANAGEMENT,
+    TFM_CRYPTO_GROUP_ID_HASH,
+    TFM_CRYPTO_GROUP_ID_MAC,
+    TFM_CRYPTO_GROUP_ID_CIPHER,
+    TFM_CRYPTO_GROUP_ID_AEAD,
+    TFM_CRYPTO_GROUP_ID_ASYM_SIGN,
+    TFM_CRYPTO_GROUP_ID_ASYM_ENCRYPT,
+    TFM_CRYPTO_GROUP_ID_KEY_DERIVATION,
+};
+
+/**
+ * \brief Accessor to the API descriptor table that returns function_type of the API
+ *
+ * \param[in] func Function ID for the API to retrieve the associated group
+ *
+ * \return Return values as described in \ref enum tfm_crypto_function_type
+ */
+enum tfm_crypto_function_type
+    get_function_type_from_descriptor(enum tfm_crypto_function_id func);
+
+/**
+ * \brief Accessor to the API descriptor table that returns function_type of the API
+ *
+ * \param[in] id Pointer to hold the ID of the caller
+ *
+ * \return Return values as described in \ref enum tfm_crypto_group_id
+ */
+enum tfm_crypto_group_id
+    get_group_id_from_descriptor(enum tfm_crypto_function_id func);
+
+/**
+ * \brief Macro to determine the group_id corresponding to a function_id by
+ *        accessing the tfm_crypto_api_descriptor table
+ */
+#define TFM_CRYPTO_IS_GROUP_ID(_function_id, _group_id) \
+    (get_group_id_from_descriptor((_function_id)) == (_group_id))
+
+/**
+ * \brief Macro to get the function_type associated to a function_id by
+ *        accessing the tfm_crypto_api_descriptor table
+ */
+#define TFM_CRYPTO_GET_FUNCTION_TYPE(_function_id) \
+    (get_function_type_from_descriptor((_function_id)))
+
+/**
  * \brief Initialise the service
  *
  * \return Return values as described in \ref psa_status_t
@@ -130,86 +179,131 @@
                                          uint32_t handle,
                                          void **ctx);
 /**
- * \brief Encodes the input key id and owner to output key
+ * \brief This function handles the operations to allocate or retrieve a
+ *        multipart context. It receives a operation and function type as
+ *        inputs and then returns the looked or allocated context using
+ *        the provided handle. If a context is allocated in a setup call
+ *        the returned handle is then updated with the allocated value
  *
- * \param[in]  key_id       Id of the key to encode
- * \param[out] enc_key_ptr  Pointer to encoded key with id and owner
+ * \param[in]      type          Type of the operation context to look up
+ * \param[in]      function_type Type of the function
+ * \param[in, out] handle        Pointer to the handle
+ * \param[out]     ctx           Double pointer to the context
  *
  * \return Return values as described in \ref psa_status_t
  */
-psa_status_t tfm_crypto_encode_id_and_owner(psa_key_id_t key_id,
-                                            mbedtls_svc_key_id_t *enc_key_ptr);
-
-#define LIST_TFM_CRYPTO_UNIFORM_SIGNATURE_API \
-    X(tfm_crypto_get_key_attributes)          \
-    X(tfm_crypto_reset_key_attributes)        \
-    X(tfm_crypto_open_key)                    \
-    X(tfm_crypto_close_key)                   \
-    X(tfm_crypto_import_key)                  \
-    X(tfm_crypto_destroy_key)                 \
-    X(tfm_crypto_export_key)                  \
-    X(tfm_crypto_export_public_key)           \
-    X(tfm_crypto_purge_key)                   \
-    X(tfm_crypto_copy_key)                    \
-    X(tfm_crypto_hash_compute)                \
-    X(tfm_crypto_hash_compare)                \
-    X(tfm_crypto_hash_setup)                  \
-    X(tfm_crypto_hash_update)                 \
-    X(tfm_crypto_hash_finish)                 \
-    X(tfm_crypto_hash_verify)                 \
-    X(tfm_crypto_hash_abort)                  \
-    X(tfm_crypto_hash_clone)                  \
-    X(tfm_crypto_mac_compute)                 \
-    X(tfm_crypto_mac_verify)                  \
-    X(tfm_crypto_mac_sign_setup)              \
-    X(tfm_crypto_mac_verify_setup)            \
-    X(tfm_crypto_mac_update)                  \
-    X(tfm_crypto_mac_sign_finish)             \
-    X(tfm_crypto_mac_verify_finish)           \
-    X(tfm_crypto_mac_abort)                   \
-    X(tfm_crypto_cipher_encrypt)              \
-    X(tfm_crypto_cipher_decrypt)              \
-    X(tfm_crypto_cipher_encrypt_setup)        \
-    X(tfm_crypto_cipher_decrypt_setup)        \
-    X(tfm_crypto_cipher_generate_iv)          \
-    X(tfm_crypto_cipher_set_iv)               \
-    X(tfm_crypto_cipher_update)               \
-    X(tfm_crypto_cipher_finish)               \
-    X(tfm_crypto_cipher_abort)                \
-    X(tfm_crypto_aead_encrypt)                \
-    X(tfm_crypto_aead_decrypt)                \
-    X(tfm_crypto_aead_encrypt_setup)          \
-    X(tfm_crypto_aead_decrypt_setup)          \
-    X(tfm_crypto_aead_generate_nonce)         \
-    X(tfm_crypto_aead_set_nonce)              \
-    X(tfm_crypto_aead_set_lengths)            \
-    X(tfm_crypto_aead_update_ad)              \
-    X(tfm_crypto_aead_update)                 \
-    X(tfm_crypto_aead_finish)                 \
-    X(tfm_crypto_aead_verify)                 \
-    X(tfm_crypto_aead_abort)                  \
-    X(tfm_crypto_sign_message)                \
-    X(tfm_crypto_verify_message)              \
-    X(tfm_crypto_sign_hash)                   \
-    X(tfm_crypto_verify_hash)                 \
-    X(tfm_crypto_asymmetric_encrypt)          \
-    X(tfm_crypto_asymmetric_decrypt)          \
-    X(tfm_crypto_key_derivation_setup)        \
-    X(tfm_crypto_key_derivation_get_capacity) \
-    X(tfm_crypto_key_derivation_set_capacity) \
-    X(tfm_crypto_key_derivation_input_bytes)  \
-    X(tfm_crypto_key_derivation_input_key)    \
-    X(tfm_crypto_key_derivation_key_agreement)\
-    X(tfm_crypto_key_derivation_output_bytes) \
-    X(tfm_crypto_key_derivation_output_key)   \
-    X(tfm_crypto_key_derivation_abort)        \
-    X(tfm_crypto_raw_key_agreement)           \
-    X(tfm_crypto_generate_random)             \
-    X(tfm_crypto_generate_key)                \
-
-#define X(api_name) UNIFORM_SIGNATURE_API(api_name);
-LIST_TFM_CRYPTO_UNIFORM_SIGNATURE_API
-#undef X
+psa_status_t tfm_crypto_operation_handling(enum tfm_crypto_operation_type type,
+                                    enum tfm_crypto_function_type function_type,
+                                    uint32_t *handle,
+                                    void **ctx);
+/**
+ * \brief This function acts as interface from the framework dispatching
+ *        calls to the set of functions that implement the PSA Crypto APIs.
+ *        It is based on the Uniform Signatures prototype.
+ *
+ * \param[in]  in_vec   Array of invec parameters
+ * \param[in]  in_len   Length of the valid entries in in_vec
+ * \param[out] out_vec  Array of outvec parameters
+ * \param[in]  out_len  Length of the valid entries in out_vec
+ *
+ * \return Return values as described in \ref psa_status_t
+ */
+psa_status_t tfm_crypto_api_dispatcher(psa_invec in_vec[],
+                                       size_t in_len,
+                                       psa_outvec out_vec[],
+                                       size_t out_len);
+/**
+ * \brief This function acts as interface for the Key management module
+ *
+ * \param[in]  in_vec   Array of invec parameters
+ * \param[out] out_vec  Array of outvec parameters
+ * \param[in]  encoded_key Key encoded with partition_id and key_id
+ *
+ * \return Return values as described in \ref psa_status_t
+ */
+psa_status_t tfm_crypto_key_management_interface(psa_invec in_vec[],
+                                            psa_outvec out_vec[],
+                                            mbedtls_svc_key_id_t *encoded_key);
+/**
+ * \brief This function acts as interface for the MAC module
+ *
+ * \param[in]  in_vec   Array of invec parameters
+ * \param[out] out_vec  Array of outvec parameters
+ * \param[in]  encoded_key Key encoded with partition_id and key_id
+ *
+ * \return Return values as described in \ref psa_status_t
+ */
+psa_status_t tfm_crypto_mac_interface(psa_invec in_vec[],
+                                      psa_outvec out_vec[],
+                                      mbedtls_svc_key_id_t *encoded_key);
+/**
+ * \brief This function acts as interface for the Cipher module
+ *
+ * \param[in]  in_vec   Array of invec parameters
+ * \param[out] out_vec  Array of outvec parameters
+ * \param[in]  encoded_key Key encoded with partition_id and key_id
+ *
+ * \return Return values as described in \ref psa_status_t
+ */
+psa_status_t tfm_crypto_cipher_interface(psa_invec in_vec[],
+                                         psa_outvec out_vec[],
+                                         mbedtls_svc_key_id_t *encoded_key);
+/**
+ * \brief This function acts as interface for the AEAD module
+ *
+ * \param[in]  in_vec   Array of invec parameters
+ * \param[out] out_vec  Array of outvec parameters
+ * \param[in]  encoded_key Key encoded with partition_id and key_id
+ *
+ * \return Return values as described in \ref psa_status_t
+ */
+psa_status_t tfm_crypto_aead_interface(psa_invec in_vec[],
+                                       psa_outvec out_vec[],
+                                       mbedtls_svc_key_id_t *encoded_key);
+/**
+ * \brief This function acts as interface for the Asymmetric module
+ *
+ * \param[in]  in_vec   Array of invec parameters
+ * \param[out] out_vec  Array of outvec parameters
+ * \param[in]  encoded_key Key encoded with partition_id and key_id
+ *
+ * \return Return values as described in \ref psa_status_t
+ */
+psa_status_t tfm_crypto_asymmetric_interface(psa_invec in_vec[],
+                                             psa_outvec out_vec[],
+                                             mbedtls_svc_key_id_t *encoded_key);
+/**
+ * \brief This function acts as interface for the Key derivation module
+ *
+ * \param[in]  in_vec   Array of invec parameters
+ * \param[out] out_vec  Array of outvec parameters
+ * \param[in]  encoded_key Key encoded with partition_id and key_id
+ *
+ * \return Return values as described in \ref psa_status_t
+ */
+psa_status_t tfm_crypto_key_derivation_interface(psa_invec in_vec[],
+                                            psa_outvec out_vec[],
+                                            mbedtls_svc_key_id_t *encoded_key);
+/**
+ * \brief This function acts as interface for the Random module
+ *
+ * \param[in]  in_vec   Array of invec parameters
+ * \param[out] out_vec  Array of outvec parameters
+ *
+ * \return Return values as described in \ref psa_status_t
+ */
+psa_status_t tfm_crypto_random_interface(psa_invec in_vec[],
+                                         psa_outvec out_vec[]);
+/**
+ * \brief This function acts as interface for the Hash module
+ *
+ * \param[in]  in_vec   Array of invec parameters
+ * \param[out] out_vec  Array of outvec parameters
+ *
+ * \return Return values as described in \ref psa_status_t
+ */
+psa_status_t tfm_crypto_hash_interface(psa_invec in_vec[],
+                                       psa_outvec out_vec[]);
 
 #ifdef __cplusplus
 }