Crypto: Modularise the interaction with crypto primitives
This patch creates an engine layer inside the service to
modularise all the operations that involve cryptography
primitives.
It also updates the service documentation, fixes some minor
issues in the NS crypto interface test suite, and updates the
manifest file for the crypto service removing outdated functions.
Change-Id: Id2d0e2140741debd22c145f816a4df2ab0351b58
Signed-off-by: Antonio de Angelis <antonio.deangelis@arm.com>
diff --git a/secure_fw/services/crypto/crypto_cipher.c b/secure_fw/services/crypto/crypto_cipher.c
index be2ac5d..ca78e8a 100644
--- a/secure_fw/services/crypto/crypto_cipher.c
+++ b/secure_fw/services/crypto/crypto_cipher.c
@@ -9,18 +9,7 @@
#include "tfm_crypto_defs.h"
-/* Pre include Mbed TLS headers */
-#define LIB_PREFIX_NAME __tfm_crypto__
-#include "mbedtls_global_symbols.h"
-
-/* Include the Mbed TLS configuration file, the way Mbed TLS does it
- * in each of its header files.
- */
-#if !defined(MBEDTLS_CONFIG_FILE)
-#include "platform/ext/common/tfm_mbedtls_config.h"
-#else
-#include MBEDTLS_CONFIG_FILE
-#endif
+#include "crypto_engine.h"
#include "psa_crypto.h"
@@ -29,33 +18,19 @@
#include "tfm_crypto_api.h"
#include "crypto_utils.h"
-/**
- * \brief For a TFM_CRYPTO_CIPHER_OPERATION, define the possible
- * modes of configuration.
- *
- */
-enum tfm_crypto_cipher_mode_t {
- TFM_CRYPTO_CIPHER_MODE_DECRYPT = 0,
- TFM_CRYPTO_CIPHER_MODE_ENCRYPT = 1,
-};
-
static enum tfm_crypto_err_t tfm_crypto_cipher_setup(
psa_cipher_operation_t *operation,
psa_key_slot_t key,
psa_algorithm_t alg,
- enum tfm_crypto_cipher_mode_t c_mode)
+ enum engine_cipher_mode_t c_mode)
{
- const mbedtls_cipher_info_t *info = NULL;
- psa_algorithm_t padding_mode = PSA_ALG_BLOCK_CIPHER_PAD_NONE;
- psa_key_type_t key_type;
- size_t key_size;
- enum tfm_crypto_err_t err;
uint8_t key_data[TFM_CRYPTO_MAX_KEY_LENGTH];
- uint32_t ret;
- mbedtls_cipher_type_t type = MBEDTLS_CIPHER_NONE;
- mbedtls_cipher_padding_t mbedtls_padding_mode = MBEDTLS_PADDING_NONE;
-
+ size_t key_size;
+ psa_key_type_t key_type = PSA_KEY_TYPE_NONE;
+ psa_status_t status = PSA_SUCCESS;
+ enum tfm_crypto_err_t err;
struct tfm_cipher_operation_s *ctx = NULL;
+ struct cipher_engine_info engine_info;
/* Validate pointers */
err = tfm_crypto_memory_check(operation,
@@ -66,38 +41,26 @@
}
if (!PSA_ALG_IS_CIPHER(alg)) {
- return TFM_CRYPTO_ERR_PSA_ERROR_NOT_SUPPORTED;
+ return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
}
- /* FIXME: Check that key is compatible with alg */
+ /* Access the key module to retrieve key related information */
err = tfm_crypto_get_key_information(key, &key_type, &key_size);
if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
- return err;
+ return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
}
- err = tfm_crypto_export_key(key, &key_data[0], TFM_CRYPTO_MAX_KEY_LENGTH,
- &key_size);
- if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
- return err;
+ /* Setup the algorithm on the crypto engine */
+ status = tfm_crypto_engine_cipher_setup(alg,
+ (const psa_key_type_t)key_type,
+ (const uint32_t)key_size,
+ c_mode,
+ &engine_info);
+ if (status != PSA_SUCCESS) {
+ return PSA_STATUS_TO_TFM_CRYPTO_ERR(status);
}
- /* Mbed TLS cipher setup */
- if (PSA_BYTES_TO_BITS(key_size) == 128) {
- if (alg == PSA_ALG_CBC_BASE) {
- type = MBEDTLS_CIPHER_AES_128_CBC;
- } else if (alg == PSA_ALG_CFB_BASE) {
- if (c_mode == TFM_CRYPTO_CIPHER_MODE_ENCRYPT) {
- type = MBEDTLS_CIPHER_AES_128_CFB128;
- }
- }
- }
-
- /* The requested alg/key/mode is not supported */
- if (type == MBEDTLS_CIPHER_NONE) {
- return TFM_CRYPTO_ERR_PSA_ERROR_NOT_SUPPORTED;
- }
-
- /* Allocate the operation context in the TFM space */
+ /* Allocate the operation context in the secure world */
err = tfm_crypto_operation_alloc(TFM_CRYPTO_CIPHER_OPERATION,
&(operation->handle));
if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
@@ -109,81 +72,67 @@
operation->handle,
(void **)&ctx);
if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
+ /* Release the operation context */
+ tfm_crypto_operation_release(&(operation->handle));
return err;
}
+ /* Set the proper cipher mode (encrypt/decrypt) in the operation context */
+ ctx->cipher_mode = (uint8_t) c_mode;
+
/* Bind the algorithm to the cipher operation */
ctx->alg = alg;
- /* Mbed TLS cipher init */
- mbedtls_cipher_init(&(ctx->cipher));
- info = mbedtls_cipher_info_from_type(type);
- ret = mbedtls_cipher_setup(&(ctx->cipher), info);
- if (ret != 0) {
+ /* Start the crypto engine */
+ status = tfm_crypto_engine_cipher_start(&(ctx->engine_ctx), &engine_info);
+ if (status != PSA_SUCCESS) {
/* Release the operation context */
tfm_crypto_operation_release(&(operation->handle));
- return TFM_CRYPTO_ERR_PSA_ERROR_COMMUNICATION_FAILURE;
+ return PSA_STATUS_TO_TFM_CRYPTO_ERR(status);
}
- /* FIXME: Check based on the algorithm, if we need to have an IV */
- ctx->iv_required = 1;
+ /* Access the crypto service key module to retrieve key data */
+ err = tfm_crypto_export_key(key,
+ &key_data[0],
+ TFM_CRYPTO_MAX_KEY_LENGTH,
+ &key_size);
+ if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
+ /* Release the operation context */
+ tfm_crypto_operation_release(&(operation->handle));
+ return err;
+ }
+
+ /* Set the key on the engine */
+ status = tfm_crypto_engine_cipher_set_key(&(ctx->engine_ctx),
+ key_data,
+ key_size,
+ &engine_info);
+ if (status != PSA_SUCCESS) {
+ /* Release the operation context */
+ tfm_crypto_operation_release(&(operation->handle));
+ return PSA_STATUS_TO_TFM_CRYPTO_ERR(status);
+ }
/* Bind the key to the cipher operation */
ctx->key = key;
ctx->key_set = 1;
- /* Mbed TLS cipher set key */
- if (c_mode == TFM_CRYPTO_CIPHER_MODE_ENCRYPT) {
-
- ret = mbedtls_cipher_setkey(&(ctx->cipher),
- &key_data[0],
- PSA_BYTES_TO_BITS(key_size),
- MBEDTLS_ENCRYPT);
-
- } else if (c_mode == TFM_CRYPTO_CIPHER_MODE_DECRYPT) {
-
- ret = mbedtls_cipher_setkey(&(ctx->cipher),
- &key_data[0],
- PSA_BYTES_TO_BITS(key_size),
- MBEDTLS_DECRYPT);
- } else {
- /* Release the operation context */
- tfm_crypto_operation_release(&(operation->handle));
- return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
- }
-
- if (ret != 0) {
- /* Release the operation context */
- tfm_crypto_operation_release(&(operation->handle));
- return TFM_CRYPTO_ERR_PSA_ERROR_COMMUNICATION_FAILURE;
- }
-
- /* Mbed TLS cipher set padding mode in case of CBC */
+ /* Set padding mode on engine in case of CBC */
if ((alg & ~PSA_ALG_BLOCK_CIPHER_PADDING_MASK) == PSA_ALG_CBC_BASE) {
- /* Check the value of padding field */
- padding_mode = alg & PSA_ALG_BLOCK_CIPHER_PADDING_MASK;
-
- switch (padding_mode) {
- case PSA_ALG_BLOCK_CIPHER_PAD_PKCS7:
- mbedtls_padding_mode = MBEDTLS_PADDING_PKCS7;
- break;
- case PSA_ALG_BLOCK_CIPHER_PAD_NONE:
- mbedtls_padding_mode = MBEDTLS_PADDING_NONE;
- break;
- default:
- return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
- }
-
- ret = mbedtls_cipher_set_padding_mode(&(ctx->cipher),
- mbedtls_padding_mode);
- if (ret != 0) {
+ status = tfm_crypto_engine_cipher_set_padding_mode(&(ctx->engine_ctx),
+ &engine_info);
+ if (status != PSA_SUCCESS) {
/* Release the operation context */
tfm_crypto_operation_release(&(operation->handle));
- return TFM_CRYPTO_ERR_PSA_ERROR_COMMUNICATION_FAILURE;
+ return PSA_STATUS_TO_TFM_CRYPTO_ERR(status);
}
}
+ /* FIXME: Check based on the algorithm, if we need to have an IV */
+ ctx->iv_required = 1;
+ ctx->block_size = PSA_BLOCK_CIPHER_BLOCK_SIZE(key_type);
+
return TFM_CRYPTO_ERR_PSA_SUCCESS;
}
@@ -198,7 +147,7 @@
const unsigned char *iv,
size_t iv_length)
{
- int ret;
+ psa_status_t status = PSA_SUCCESS;
enum tfm_crypto_err_t err;
struct tfm_cipher_operation_s *ctx = NULL;
@@ -222,36 +171,25 @@
return err;
}
- if (ctx->iv_required == 0) {
- /* Release the operation context */
- tfm_crypto_operation_release(&(operation->handle));
- return TFM_CRYPTO_ERR_PSA_ERROR_NOT_PERMITTED;
+ if ((iv_length != ctx->block_size) || (iv_length > TFM_CIPHER_IV_MAX_SIZE)){
+ return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
}
- if (iv_length > PSA_CIPHER_IV_MAX_SIZE) {
- /* Release the operation context */
- tfm_crypto_operation_release(&(operation->handle));
- return TFM_CRYPTO_ERR_PSA_ERROR_NOT_SUPPORTED;
+ if ((ctx->iv_set == 1) || (ctx->iv_required == 0)) {
+ return TFM_CRYPTO_ERR_PSA_ERROR_BAD_STATE;
}
- /* Bind the IV to the cipher operation */
- ret = mbedtls_cipher_set_iv(&(ctx->cipher), iv, iv_length);
- if (ret != 0) {
- /* Release the operation context */
- tfm_crypto_operation_release(&(operation->handle));
- return TFM_CRYPTO_ERR_PSA_ERROR_COMMUNICATION_FAILURE;
+ /* Set the IV on the crypto engine */
+ status = tfm_crypto_engine_cipher_set_iv(&(ctx->engine_ctx),
+ iv,
+ iv_length);
+ if (status != PSA_SUCCESS) {
+ return PSA_STATUS_TO_TFM_CRYPTO_ERR(status);
}
+
ctx->iv_set = 1;
ctx->iv_size = iv_length;
- /* Reset the context after IV is set */
- ret = mbedtls_cipher_reset(&(ctx->cipher));
- if (ret != 0) {
- /* Release the operation context */
- tfm_crypto_operation_release(&(operation->handle));
- return TFM_CRYPTO_ERR_PSA_ERROR_COMMUNICATION_FAILURE;
- }
-
return TFM_CRYPTO_ERR_PSA_SUCCESS;
}
@@ -263,7 +201,7 @@
return tfm_crypto_cipher_setup(operation,
key,
alg,
- TFM_CRYPTO_CIPHER_MODE_ENCRYPT);
+ ENGINE_CIPHER_MODE_ENCRYPT);
}
enum tfm_crypto_err_t tfm_crypto_cipher_decrypt_setup(
@@ -274,7 +212,7 @@
return tfm_crypto_cipher_setup(operation,
key,
alg,
- TFM_CRYPTO_CIPHER_MODE_DECRYPT);
+ ENGINE_CIPHER_MODE_DECRYPT);
}
enum tfm_crypto_err_t tfm_crypto_cipher_update(
@@ -285,9 +223,8 @@
size_t output_size,
size_t *output_length)
{
- int ret;
+ psa_status_t status = PSA_SUCCESS;
enum tfm_crypto_err_t err;
- size_t olen;
struct tfm_cipher_operation_s *ctx = NULL;
/* Validate pointers */
@@ -327,9 +264,7 @@
/* If the IV is required and it's not been set yet */
if ((ctx->iv_required == 1) && (ctx->iv_set == 0)) {
- if (ctx->cipher.operation != MBEDTLS_DECRYPT) {
- /* Release the operation context */
- tfm_crypto_operation_release(&(operation->handle));
+ if (ctx->cipher_mode != ENGINE_CIPHER_MODE_DECRYPT) {
return TFM_CRYPTO_ERR_PSA_ERROR_BAD_STATE;
}
@@ -343,24 +278,19 @@
/* If the key is not set, setup phase has not been completed */
if (ctx->key_set == 0) {
- /* Release the operation context */
- tfm_crypto_operation_release(&(operation->handle));
return TFM_CRYPTO_ERR_PSA_ERROR_BAD_STATE;
}
- *output_length = 0;
-
- ret = mbedtls_cipher_update(&(ctx->cipher), input, input_length,
- output, &olen);
- if ((ret != 0) || (olen == 0)) {
- /* Release the operation context */
- tfm_crypto_operation_release(&(operation->handle));
- return TFM_CRYPTO_ERR_PSA_ERROR_COMMUNICATION_FAILURE;
+ /* Update the cipher output with the input chunk on the engine */
+ status = tfm_crypto_engine_cipher_update(&(ctx->engine_ctx),
+ input,
+ input_length,
+ output,
+ (uint32_t *)output_length);
+ if (status != PSA_SUCCESS) {
+ return PSA_STATUS_TO_TFM_CRYPTO_ERR(status);
}
- /* Assign the output buffer length */
- *output_length = olen;
-
return TFM_CRYPTO_ERR_PSA_SUCCESS;
}
@@ -370,9 +300,8 @@
size_t output_size,
size_t *output_length)
{
- int ret;
+ psa_status_t status = PSA_SUCCESS;
enum tfm_crypto_err_t err;
- size_t olen;
struct tfm_cipher_operation_s *ctx = NULL;
/* Validate pointers */
@@ -395,8 +324,6 @@
return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
}
- *output_length = 0;
-
/* Look up the corresponding operation context */
err = tfm_crypto_operation_lookup(TFM_CRYPTO_CIPHER_OPERATION,
operation->handle,
@@ -405,17 +332,20 @@
return err;
}
- ret = mbedtls_cipher_finish(&(ctx->cipher), output, &olen);
- if (ret != 0) {
- /* Release the operation context */
- tfm_crypto_operation_release(&(operation->handle));
- return TFM_CRYPTO_ERR_PSA_ERROR_COMMUNICATION_FAILURE;
+ /* Finalise the operation on the crypto engine */
+ status = tfm_crypto_engine_cipher_finish(&(ctx->engine_ctx),
+ output,
+ (uint32_t *)output_length);
+ if (status != PSA_SUCCESS) {
+ *output_length = 0;
+ return PSA_STATUS_TO_TFM_CRYPTO_ERR(status);
}
- *output_length = olen;
-
- /* Clear the Mbed TLS context */
- mbedtls_cipher_free(&(ctx->cipher));
+ /* Release resources on the crypto engine */
+ status = tfm_crypto_engine_cipher_release(&(ctx->engine_ctx));
+ if (status != PSA_SUCCESS) {
+ return PSA_STATUS_TO_TFM_CRYPTO_ERR(status);
+ }
/* Release the operation context */
err = tfm_crypto_operation_release(&(operation->handle));
@@ -428,6 +358,7 @@
enum tfm_crypto_err_t tfm_crypto_cipher_abort(psa_cipher_operation_t *operation)
{
+ psa_status_t status = PSA_SUCCESS;
enum tfm_crypto_err_t err;
struct tfm_cipher_operation_s *ctx = NULL;
@@ -447,8 +378,11 @@
return err;
}
- /* Clear the Mbed TLS context */
- mbedtls_cipher_free(&(ctx->cipher));
+ /* Release resources on the engine */
+ status = tfm_crypto_engine_cipher_release(&(ctx->engine_ctx));
+ if (status != PSA_SUCCESS) {
+ return PSA_STATUS_TO_TFM_CRYPTO_ERR(status);
+ }
/* Release the operation context */
err = tfm_crypto_operation_release(&(operation->handle));