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/crypto_cipher.c b/secure_fw/partitions/crypto/crypto_cipher.c
index a45d239..70ce182c 100644
--- a/secure_fw/partitions/crypto/crypto_cipher.c
+++ b/secure_fw/partitions/crypto/crypto_cipher.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2021, Arm Limited. All rights reserved.
+ * Copyright (c) 2018-2022, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  *
@@ -12,400 +12,145 @@
 
 #include "tfm_crypto_api.h"
 #include "tfm_crypto_defs.h"
-#include "tfm_crypto_private.h"
 
 /*!
- * \defgroup public_psa Public functions, PSA
+ * \addtogroup tfm_crypto_api_shim_layer
  *
  */
 
 /*!@{*/
-psa_status_t tfm_crypto_cipher_generate_iv(psa_invec in_vec[],
-                                           size_t in_len,
-                                           psa_outvec out_vec[],
-                                           size_t out_len)
+psa_status_t tfm_crypto_cipher_interface(psa_invec in_vec[],
+                                         psa_outvec out_vec[],
+                                         mbedtls_svc_key_id_t *encoded_key)
 {
 #ifdef TFM_CRYPTO_CIPHER_MODULE_DISABLED
     return PSA_ERROR_NOT_SUPPORTED;
-#else
-    psa_status_t status = PSA_SUCCESS;
-    psa_cipher_operation_t *operation = NULL;
-
-    CRYPTO_IN_OUT_LEN_VALIDATE(in_len, 1, 1, out_len, 1, 2);
-
-    if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec)) ||
-        (out_vec[0].len != sizeof(uint32_t))) {
-        return PSA_ERROR_PROGRAMMER_ERROR;
-    }
-
+#endif
     const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
-    uint32_t handle = iov->op_handle;
-    uint32_t *handle_out = out_vec[0].base;
-    unsigned char *iv = out_vec[1].base;
-    size_t iv_size = out_vec[1].len;
-
-    /* Init the handle in the operation with the one passed from the iov */
-    *handle_out = iov->op_handle;
-
-    /* Look up the corresponding operation context */
-    status = tfm_crypto_operation_lookup(TFM_CRYPTO_CIPHER_OPERATION,
-                                         handle,
-                                         (void **)&operation);
-    if (status != PSA_SUCCESS) {
-        return status;
-    }
-
-    *handle_out = handle;
-
-    return psa_cipher_generate_iv(operation, iv, iv_size, &out_vec[1].len);
-#endif /* TFM_CRYPTO_CIPHER_MODULE_DISABLED */
-}
-
-psa_status_t tfm_crypto_cipher_set_iv(psa_invec in_vec[],
-                                      size_t in_len,
-                                      psa_outvec out_vec[],
-                                      size_t out_len)
-{
-#ifdef TFM_CRYPTO_CIPHER_MODULE_DISABLED
-    return PSA_ERROR_NOT_SUPPORTED;
-#else
-    psa_status_t status = PSA_SUCCESS;
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
     psa_cipher_operation_t *operation = NULL;
-
-    CRYPTO_IN_OUT_LEN_VALIDATE(in_len, 1, 2, out_len, 1, 1);
-
-    if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec)) ||
-        (out_vec[0].len != sizeof(uint32_t))) {
-        return PSA_ERROR_PROGRAMMER_ERROR;
-    }
-    const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
     uint32_t handle = iov->op_handle;
-    uint32_t *handle_out = out_vec[0].base;
-    const unsigned char *iv = in_vec[1].base;
-    size_t iv_length = in_vec[1].len;
+    uint32_t *handle_out = NULL;
+    enum tfm_crypto_function_type function_type =
+                        TFM_CRYPTO_GET_FUNCTION_TYPE(iov->function_id);
 
-    /* Init the handle in the operation with the one passed from the iov */
-    *handle_out = iov->op_handle;
-
-    /* Look up the corresponding operation context */
-    status = tfm_crypto_operation_lookup(TFM_CRYPTO_CIPHER_OPERATION,
-                                         handle,
-                                         (void **)&operation);
-    if (status != PSA_SUCCESS) {
-        return status;
+    if (function_type != TFM_CRYPTO_FUNCTION_TYPE_NON_MULTIPART) {
+        handle_out = (out_vec && out_vec[0].base != NULL) ?
+                                                out_vec[0].base : &handle;
+        *handle_out = handle;
+        status = tfm_crypto_operation_handling(TFM_CRYPTO_CIPHER_OPERATION,
+                                               function_type,
+                                               handle_out,
+                                               (void **)&operation);
+        if (status != PSA_SUCCESS) {
+            return (iov->function_id == TFM_CRYPTO_CIPHER_ABORT_SID) ?
+                    PSA_SUCCESS : status;
+        }
     }
 
-    return psa_cipher_set_iv(operation, iv, iv_length);
-#endif /* TFM_CRYPTO_CIPHER_MODULE_DISABLED */
-}
+    switch (iov->function_id) {
+    case TFM_CRYPTO_CIPHER_GENERATE_IV_SID:
+    {
+        unsigned char *iv = out_vec[0].base;
+        size_t iv_size = out_vec[0].len;
 
-psa_status_t tfm_crypto_cipher_encrypt_setup(psa_invec in_vec[],
-                                             size_t in_len,
-                                             psa_outvec out_vec[],
-                                             size_t out_len)
-{
-#ifdef TFM_CRYPTO_CIPHER_MODULE_DISABLED
-    return PSA_ERROR_NOT_SUPPORTED;
-#else
-    psa_status_t status = PSA_SUCCESS;
-    psa_cipher_operation_t *operation = NULL;
-
-    CRYPTO_IN_OUT_LEN_VALIDATE(in_len, 1, 1, out_len, 1, 1);
-
-    if ((out_vec[0].len != sizeof(uint32_t)) ||
-        (in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec))) {
-        return PSA_ERROR_PROGRAMMER_ERROR;
+        status = psa_cipher_generate_iv(operation,
+                                        iv, iv_size, &out_vec[0].len);
     }
-    const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
-    uint32_t handle = iov->op_handle;
-    uint32_t *handle_out = out_vec[0].base;
-    psa_key_id_t key_id = iov->key_id;
-    psa_algorithm_t alg = iov->alg;
-    mbedtls_svc_key_id_t encoded_key;
+    break;
+    case TFM_CRYPTO_CIPHER_SET_IV_SID:
+    {
+        const unsigned char *iv = in_vec[1].base;
+        size_t iv_length = in_vec[1].len;
 
-    /* Allocate the operation context in the secure world */
-    status = tfm_crypto_operation_alloc(TFM_CRYPTO_CIPHER_OPERATION,
-                                        &handle,
-                                        (void **)&operation);
-    if (status != PSA_SUCCESS) {
-        return status;
+        status = psa_cipher_set_iv(operation, iv, iv_length);
     }
-    *handle_out = handle;
-
-    status = tfm_crypto_encode_id_and_owner(key_id, &encoded_key);
-    if (status != PSA_SUCCESS) {
-        goto exit;
+    break;
+    case TFM_CRYPTO_CIPHER_ENCRYPT_SETUP_SID:
+    {
+        status = psa_cipher_encrypt_setup(operation, *encoded_key, iov->alg);
+        if (status != PSA_SUCCESS) {
+            goto release_operation_and_return;
+        }
     }
+    break;
+    case TFM_CRYPTO_CIPHER_DECRYPT_SETUP_SID:
+    {
+        status = psa_cipher_decrypt_setup(operation, *encoded_key, iov->alg);
+        if (status != PSA_SUCCESS) {
+            goto release_operation_and_return;
+        }
+    }
+    break;
+    case TFM_CRYPTO_CIPHER_UPDATE_SID:
+    {
+        const uint8_t *input = in_vec[1].base;
+        size_t input_length = in_vec[1].len;
+        unsigned char *output = out_vec[0].base;
+        size_t output_size = out_vec[0].len;
+        /* Initialise the output_length to zero */
+        out_vec[0].len = 0;
 
-    status = psa_cipher_encrypt_setup(operation, encoded_key, alg);
-    if (status != PSA_SUCCESS) {
-        goto exit;
+        status = psa_cipher_update(operation, input, input_length,
+                                   output, output_size, &out_vec[0].len);
+    }
+    break;
+    case TFM_CRYPTO_CIPHER_FINISH_SID:
+    {
+        uint8_t *output = out_vec[1].base;
+        size_t output_size = out_vec[1].len;
+        /* Initialise the output_length to zero */
+        out_vec[1].len = 0;
+
+        status = psa_cipher_finish(operation,
+                                   output, output_size, &out_vec[1].len);
+        if (status == PSA_SUCCESS) {
+            /* In case of success automatically release the operation */
+            goto release_operation_and_return;
+        }
+    }
+    break;
+    case TFM_CRYPTO_CIPHER_ABORT_SID:
+    {
+        status = psa_cipher_abort(operation);
+
+        if (status != PSA_SUCCESS) {
+            goto release_operation_and_return;
+        } else {
+            status = tfm_crypto_operation_release(handle_out);
+        }
+    }
+    break;
+    case TFM_CRYPTO_CIPHER_ENCRYPT_SID:
+    {
+        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;
+
+        status = psa_cipher_encrypt(*encoded_key, iov->alg, input, input_length,
+                                    output, output_size, &out_vec[0].len);
+    }
+    break;
+    case TFM_CRYPTO_CIPHER_DECRYPT_SID:
+    {
+        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;
+
+        status = psa_cipher_decrypt(*encoded_key, iov->alg, input, input_length,
+                                    output, output_size, &out_vec[0].len);
+    }
+    break;
+    default:
+        status = PSA_ERROR_NOT_SUPPORTED;
     }
 
     return status;
-
-exit:
+release_operation_and_return:
     /* Release the operation context, ignore if the operation fails. */
     (void)tfm_crypto_operation_release(handle_out);
     return status;
-#endif /* TFM_CRYPTO_CIPHER_MODULE_DISABLED */
-}
-
-psa_status_t tfm_crypto_cipher_decrypt_setup(psa_invec in_vec[],
-                                             size_t in_len,
-                                             psa_outvec out_vec[],
-                                             size_t out_len)
-{
-#ifdef TFM_CRYPTO_CIPHER_MODULE_DISABLED
-    return PSA_ERROR_NOT_SUPPORTED;
-#else
-    psa_status_t status = PSA_SUCCESS;
-    psa_cipher_operation_t *operation = NULL;
-
-    CRYPTO_IN_OUT_LEN_VALIDATE(in_len, 1, 1, out_len, 1, 1);
-
-    if ((out_vec[0].len != sizeof(uint32_t)) ||
-        (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;
-    uint32_t handle = iov->op_handle;
-    uint32_t *handle_out = out_vec[0].base;
-    psa_key_id_t key_id = iov->key_id;
-    psa_algorithm_t alg = iov->alg;
-    mbedtls_svc_key_id_t encoded_key;
-
-    /* Allocate the operation context in the secure world */
-    status = tfm_crypto_operation_alloc(TFM_CRYPTO_CIPHER_OPERATION,
-                                        &handle,
-                                        (void **)&operation);
-    if (status != PSA_SUCCESS) {
-        return status;
-    }
-
-    *handle_out = handle;
-    status = tfm_crypto_encode_id_and_owner(key_id, &encoded_key);
-    if (status != PSA_SUCCESS) {
-        goto exit;
-    }
-
-    status = psa_cipher_decrypt_setup(operation, encoded_key, alg);
-    if (status != PSA_SUCCESS) {
-        goto exit;
-    }
-
-    return status;
-
-exit:
-    /* Release the operation context, ignore if the operation fails. */
-    (void)tfm_crypto_operation_release(handle_out);
-    return status;
-#endif /* TFM_CRYPTO_CIPHER_MODULE_DISABLED */
-}
-
-psa_status_t tfm_crypto_cipher_update(psa_invec in_vec[],
-                                      size_t in_len,
-                                      psa_outvec out_vec[],
-                                      size_t out_len)
-{
-#ifdef TFM_CRYPTO_CIPHER_MODULE_DISABLED
-    return PSA_ERROR_NOT_SUPPORTED;
-#else
-    psa_status_t status = PSA_SUCCESS;
-    psa_cipher_operation_t *operation = NULL;
-
-    CRYPTO_IN_OUT_LEN_VALIDATE(in_len, 1, 2, out_len, 1, 2);
-
-    if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec)) ||
-        (out_vec[0].len != sizeof(uint32_t))) {
-        return PSA_ERROR_PROGRAMMER_ERROR;
-    }
-
-    const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
-    uint32_t handle = iov->op_handle;
-    uint32_t *handle_out = out_vec[0].base;
-    const uint8_t *input = in_vec[1].base;
-    size_t input_length = in_vec[1].len;
-    unsigned char *output = out_vec[1].base;
-    size_t output_size = out_vec[1].len;
-
-    /* Init the handle in the operation with the one passed from the iov */
-    *handle_out = iov->op_handle;
-
-    /* Initialise the output_length to zero */
-    out_vec[1].len = 0;
-
-    /* Look up the corresponding operation context */
-    status = tfm_crypto_operation_lookup(TFM_CRYPTO_CIPHER_OPERATION,
-                                         handle,
-                                         (void **)&operation);
-    if (status != PSA_SUCCESS) {
-        return status;
-    }
-
-    return psa_cipher_update(operation, input, input_length,
-                             output, output_size, &out_vec[1].len);
-#endif /* TFM_CRYPTO_CIPHER_MODULE_DISABLED */
-}
-
-psa_status_t tfm_crypto_cipher_finish(psa_invec in_vec[],
-                                      size_t in_len,
-                                      psa_outvec out_vec[],
-                                      size_t out_len)
-{
-#ifdef TFM_CRYPTO_CIPHER_MODULE_DISABLED
-    return PSA_ERROR_NOT_SUPPORTED;
-#else
-    psa_status_t status = PSA_SUCCESS;
-    psa_cipher_operation_t *operation = NULL;
-
-    CRYPTO_IN_OUT_LEN_VALIDATE(in_len, 1, 1, out_len, 1, 2);
-
-    if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec)) ||
-        (out_vec[0].len != sizeof(uint32_t))) {
-        return PSA_ERROR_PROGRAMMER_ERROR;
-    }
-    const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
-    uint32_t handle = iov->op_handle;
-    uint32_t *handle_out = out_vec[0].base;
-    unsigned char *output = out_vec[1].base;
-    size_t output_size = out_vec[1].len;
-
-    /* Init the handle in the operation with the one passed from the iov */
-    *handle_out = iov->op_handle;
-
-    /* Initialise the output_length to zero */
-    out_vec[1].len = 0;
-
-    /* Look up the corresponding operation context */
-    status = tfm_crypto_operation_lookup(TFM_CRYPTO_CIPHER_OPERATION,
-                                         handle,
-                                         (void **)&operation);
-    if (status != PSA_SUCCESS) {
-        return status;
-    }
-
-    status = psa_cipher_finish(operation, output, output_size, &out_vec[1].len);
-    if (status == PSA_SUCCESS) {
-        /* Release the operation context, ignore if the operation fails. */
-        (void)tfm_crypto_operation_release(handle_out);
-    }
-
-    return status;
-#endif /* TFM_CRYPTO_CIPHER_MODULE_DISABLED */
-}
-
-psa_status_t tfm_crypto_cipher_abort(psa_invec in_vec[],
-                                     size_t in_len,
-                                     psa_outvec out_vec[],
-                                     size_t out_len)
-{
-#ifdef TFM_CRYPTO_CIPHER_MODULE_DISABLED
-    return PSA_ERROR_NOT_SUPPORTED;
-#else
-    psa_status_t status = PSA_SUCCESS;
-    psa_cipher_operation_t *operation = NULL;
-
-    CRYPTO_IN_OUT_LEN_VALIDATE(in_len, 1, 1, out_len, 1, 1);
-
-    if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec)) ||
-        (out_vec[0].len != sizeof(uint32_t))) {
-        return PSA_ERROR_PROGRAMMER_ERROR;
-    }
-    const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
-    uint32_t handle = iov->op_handle;
-    uint32_t *handle_out = out_vec[0].base;
-
-    /* Init the handle in the operation with the one passed from the iov */
-    *handle_out = iov->op_handle;
-
-    /* Look up the corresponding operation context */
-    status = tfm_crypto_operation_lookup(TFM_CRYPTO_CIPHER_OPERATION,
-                                         handle,
-                                         (void **)&operation);
-    if (status != PSA_SUCCESS) {
-        /* Operation does not exist, so abort has no effect */
-        return PSA_SUCCESS;
-    }
-
-    status = psa_cipher_abort(operation);
-
-    if (status != PSA_SUCCESS) {
-        /* Release the operation context, ignore if the operation fails. */
-        (void)tfm_crypto_operation_release(handle_out);
-        return status;
-    }
-
-    return tfm_crypto_operation_release(handle_out);
-#endif /* TFM_CRYPTO_CIPHER_MODULE_DISABLED */
-}
-
-psa_status_t tfm_crypto_cipher_encrypt(psa_invec in_vec[],
-                                       size_t in_len,
-                                       psa_outvec out_vec[],
-                                       size_t out_len)
-{
-#ifdef TFM_CRYPTO_CIPHER_MODULE_DISABLED
-    return PSA_ERROR_NOT_SUPPORTED;
-#else
-    psa_status_t status = PSA_SUCCESS;
-
-    CRYPTO_IN_OUT_LEN_VALIDATE(in_len, 1, 2, out_len, 1, 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_key_id_t key_id = iov->key_id;
-    psa_algorithm_t alg = iov->alg;
-    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;
-    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_cipher_encrypt(encoded_key, alg, input, input_length, output,
-                              output_size, &out_vec[0].len);
-#endif /* TFM_CRYPTO_CIPHER_MODULE_DISABLED */
-}
-
-psa_status_t tfm_crypto_cipher_decrypt(psa_invec in_vec[],
-                                       size_t in_len,
-                                       psa_outvec out_vec[],
-                                       size_t out_len)
-{
-#ifdef TFM_CRYPTO_CIPHER_MODULE_DISABLED
-    return PSA_ERROR_NOT_SUPPORTED;
-#else
-    psa_status_t status = PSA_SUCCESS;
-
-    CRYPTO_IN_OUT_LEN_VALIDATE(in_len, 1, 2, out_len, 1, 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_key_id_t key_id = iov->key_id;
-    psa_algorithm_t alg = iov->alg;
-    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;
-    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_cipher_decrypt(encoded_key, alg, input, input_length, output,
-                              output_size, &out_vec[0].len);
-#endif /* TFM_CRYPTO_CIPHER_MODULE_DISABLED */
 }
 /*!@}*/