Merge remote-tracking branch 'origin/master' into feature-cc-psa-crypto-drivers

Signed-off-by: Antonio de Angelis <antonio.deangelis@arm.com>
Change-Id: I60c51e7da4ed81437c5dec8ce1a4a4e3f6e74df6
diff --git a/interface/src/tfm_crypto_func_api.c b/interface/src/tfm_crypto_func_api.c
index 6e6c419..5d7826b 100644
--- a/interface/src/tfm_crypto_func_api.c
+++ b/interface/src/tfm_crypto_func_api.c
@@ -887,10 +887,7 @@
     status = API_DISPATCH(tfm_crypto_sign_message,
                           TFM_CRYPTO_SIGN_MESSAGE);
 
-    if (status == PSA_SUCCESS) {
-        *signature_length = out_vec[0].len;
-    }
-
+    *signature_length = out_vec[0].len;
     return status;
 }
 
@@ -1301,10 +1298,7 @@
     status = API_DISPATCH(tfm_crypto_mac_compute,
                           TFM_CRYPTO_MAC_COMPUTE);
 
-    if (status == PSA_SUCCESS) {
-        *mac_length = out_vec[0].len;
-    }
-
+    *mac_length = out_vec[0].len;
     return status;
 }
 
@@ -1342,6 +1336,9 @@
                                 size_t output_size,
                                 size_t *output_length)
 {
+#ifdef TFM_CRYPTO_CIPHER_MODULE_DISABLED
+    return PSA_ERROR_NOT_SUPPORTED;
+#else
     psa_status_t status;
     struct tfm_crypto_pack_iovec iov = {
         .sfn_id = TFM_CRYPTO_CIPHER_ENCRYPT_SID,
@@ -1360,11 +1357,9 @@
     status = API_DISPATCH(tfm_crypto_cipher_encrypt,
                           TFM_CRYPTO_CIPHER_ENCRYPT);
 
-    if (status == PSA_SUCCESS) {
-        *output_length = out_vec[0].len;
-    }
-
+    *output_length = out_vec[0].len;
     return status;
+#endif /* TFM_CRYPTO_CIPHER_MODULE_DISABLED */
 }
 
 psa_status_t psa_cipher_decrypt(psa_key_id_t key,
@@ -1375,6 +1370,9 @@
                                 size_t output_size,
                                 size_t *output_length)
 {
+#ifdef TFM_CRYPTO_CIPHER_MODULE_DISABLED
+    return PSA_ERROR_NOT_SUPPORTED;
+#else
     psa_status_t status;
     struct tfm_crypto_pack_iovec iov = {
         .sfn_id = TFM_CRYPTO_CIPHER_DECRYPT_SID,
@@ -1393,11 +1391,9 @@
     status = API_DISPATCH(tfm_crypto_cipher_decrypt,
                           TFM_CRYPTO_CIPHER_DECRYPT);
 
-    if (status == PSA_SUCCESS) {
-        *output_length = out_vec[0].len;
-    }
-
+    *output_length = out_vec[0].len;
     return status;
+#endif /* TFM_CRYPTO_CIPHER_MODULE_DISABLED */
 }
 
 psa_status_t psa_raw_key_agreement(psa_algorithm_t alg,
diff --git a/interface/src/tfm_crypto_ipc_api.c b/interface/src/tfm_crypto_ipc_api.c
index 9dfa473..a396a27 100644
--- a/interface/src/tfm_crypto_ipc_api.c
+++ b/interface/src/tfm_crypto_ipc_api.c
@@ -905,10 +905,7 @@
     status = API_DISPATCH(tfm_crypto_sign_message,
                           TFM_CRYPTO_SIGN_MESSAGE);
 
-    if (status == PSA_SUCCESS) {
-        *signature_length = out_vec[0].len;
-    }
-
+    *signature_length = out_vec[0].len;
     return status;
 }
 
@@ -1328,10 +1325,7 @@
     status = API_DISPATCH(tfm_crypto_mac_compute,
                           TFM_CRYPTO_MAC_COMPUTE);
 
-    if (status == PSA_SUCCESS) {
-        *mac_length = out_vec[0].len;
-    }
-
+    *mac_length = out_vec[0].len;
     return status;
 }
 
@@ -1369,6 +1363,9 @@
                                 size_t output_size,
                                 size_t *output_length)
 {
+#ifdef TFM_CRYPTO_CIPHER_MODULE_DISABLED
+    return PSA_ERROR_NOT_SUPPORTED;
+#else
     psa_status_t status;
     struct tfm_crypto_pack_iovec iov = {
         .sfn_id = TFM_CRYPTO_CIPHER_ENCRYPT_SID,
@@ -1387,11 +1384,9 @@
     status = API_DISPATCH(tfm_crypto_cipher_encrypt,
                           TFM_CRYPTO_CIPHER_ENCRYPT);
 
-    if (status == PSA_SUCCESS) {
-        *output_length = out_vec[0].len;
-    }
-
+    *output_length = out_vec[0].len;
     return status;
+#endif /* TFM_CRYPTO_CIPHER_MODULE_DISABLED */
 }
 
 psa_status_t psa_cipher_decrypt(psa_key_id_t key,
@@ -1402,6 +1397,9 @@
                                 size_t output_size,
                                 size_t *output_length)
 {
+#ifdef TFM_CRYPTO_CIPHER_MODULE_DISABLED
+    return PSA_ERROR_NOT_SUPPORTED;
+#else
     psa_status_t status;
     struct tfm_crypto_pack_iovec iov = {
         .sfn_id = TFM_CRYPTO_CIPHER_DECRYPT_SID,
@@ -1420,11 +1418,9 @@
     status = API_DISPATCH(tfm_crypto_cipher_decrypt,
                           TFM_CRYPTO_CIPHER_DECRYPT);
 
-    if (status == PSA_SUCCESS) {
-        *output_length = out_vec[0].len;
-    }
-
+    *output_length = out_vec[0].len;
     return status;
+#endif /* TFM_CRYPTO_CIPHER_MODULE_DISABLED */
 }
 
 psa_status_t psa_raw_key_agreement(psa_algorithm_t alg,
diff --git a/lib/ext/cryptocell-312-runtime/codesafe/CMakeLists.txt b/lib/ext/cryptocell-312-runtime/codesafe/CMakeLists.txt
index 04f498e..acfcb47 100644
--- a/lib/ext/cryptocell-312-runtime/codesafe/CMakeLists.txt
+++ b/lib/ext/cryptocell-312-runtime/codesafe/CMakeLists.txt
@@ -1,5 +1,5 @@
 #-------------------------------------------------------------------------------
-# Copyright (c) 2020, Arm Limited. All rights reserved.
+# Copyright (c) 2020-2021, Arm Limited. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -7,4 +7,5 @@
 
 add_subdirectory(src/crypto_api)
 add_subdirectory(src/mbedtls_api)
+add_subdirectory(src/psa_driver_api)
 # add_subdirectory(src/secure_boot_debug)
diff --git a/lib/ext/cryptocell-312-runtime/codesafe/src/crypto_api/CMakeLists.txt b/lib/ext/cryptocell-312-runtime/codesafe/src/crypto_api/CMakeLists.txt
index fcb62d2..aadbc72 100644
--- a/lib/ext/cryptocell-312-runtime/codesafe/src/crypto_api/CMakeLists.txt
+++ b/lib/ext/cryptocell-312-runtime/codesafe/src/crypto_api/CMakeLists.txt
@@ -1,5 +1,5 @@
 #-------------------------------------------------------------------------------
-# Copyright (c) 2020, Arm Limited. All rights reserved.
+# Copyright (c) 2020-2021, Arm Limited. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -8,9 +8,10 @@
 ########################## LIB #################################################
 
 target_include_directories(${CC312_LIB_TARGET}
+    PUBLIC
+        cc3x_sym/driver
     PRIVATE
         common
-        cc3x_sym/driver
         cc3x_sym/api
         pki/poly
         pki/ec_wrst
diff --git a/lib/ext/cryptocell-312-runtime/codesafe/src/psa_driver_api/CMakeLists.txt b/lib/ext/cryptocell-312-runtime/codesafe/src/psa_driver_api/CMakeLists.txt
new file mode 100644
index 0000000..1fddbe5
--- /dev/null
+++ b/lib/ext/cryptocell-312-runtime/codesafe/src/psa_driver_api/CMakeLists.txt
@@ -0,0 +1,28 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2021, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-------------------------------------------------------------------------------
+
+target_include_directories(${CC312_LIB_TARGET}
+    PUBLIC
+        include
+        .
+)
+
+target_sources(${CC312_LIB_TARGET}
+    PRIVATE
+        src/cc3xx_psa_hash.c
+        src/cc3xx_psa_cipher.c
+        src/cc3xx_psa_mac.c
+
+        src/cc3xx_internal_aes.c
+        src/cc3xx_internal_chacha20.c
+)
+
+target_compile_definitions(${CC312_LIB_TARGET}
+    PUBLIC
+        MBEDTLS_PSA_CRYPTO_DRIVERS
+        PSA_CRYPTO_DRIVER_CC3XX
+)
diff --git a/lib/ext/cryptocell-312-runtime/codesafe/src/psa_driver_api/cc3xx.h b/lib/ext/cryptocell-312-runtime/codesafe/src/psa_driver_api/cc3xx.h
new file mode 100644
index 0000000..340d33c
--- /dev/null
+++ b/lib/ext/cryptocell-312-runtime/codesafe/src/psa_driver_api/cc3xx.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef CC3XX_DRIVER_H
+#define CC3XX_DRIVER_H
+
+#include "cc3xx_psa_hash.h"
+#include "cc3xx_psa_cipher.h"
+#include "cc3xx_psa_mac.h"
+
+#endif /* CC3XX_DRIVER_H */
diff --git a/lib/ext/cryptocell-312-runtime/codesafe/src/psa_driver_api/include/cc3xx_crypto_primitives.h b/lib/ext/cryptocell-312-runtime/codesafe/src/psa_driver_api/include/cc3xx_crypto_primitives.h
new file mode 100644
index 0000000..9b93e18
--- /dev/null
+++ b/lib/ext/cryptocell-312-runtime/codesafe/src/psa_driver_api/include/cc3xx_crypto_primitives.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef CC3XX_CRYPTO_PRIMITIVES_H
+#define CC3XX_CRYPTO_PRIMITIVES_H
+
+#include "psa/crypto_driver_common.h"
+#include "psa/crypto_sizes.h"
+#include "psa/crypto_types.h"
+
+#include "hash_driver.h"
+
+#include "aes_driver.h"
+#include "chacha_driver.h"
+
+typedef HashContext_t cc3xx_hash_operation_t;
+
+typedef struct {
+    psa_algorithm_t alg;
+    psa_key_type_t key_type;
+    psa_encrypt_or_decrypt_t dir;
+    size_t block_size;
+
+    psa_status_t(*add_padding)(uint8_t *, size_t, size_t);
+
+    uint8_t unprocessed_data[AES_BLOCK_SIZE];
+    size_t  unprocessed_size;
+    uint8_t iv[AES_IV_SIZE];
+    size_t  iv_size;
+
+    AesContext_t aes_ctx;
+
+    ChachaContext_t chacha_ctx;
+} cc3xx_cipher_operation_t;
+
+typedef struct {
+    psa_algorithm_t alg;
+    union {
+        cc3xx_cipher_operation_t cmac;
+        cc3xx_hash_operation_t hmac;
+    };
+    /* Only for HMAC */
+    uint8_t opad[PSA_HMAC_MAX_HASH_BLOCK_SIZE];
+} cc3xx_mac_operation_t;
+
+#endif /* CC3XX_CRYPTO_PRIMITIVES_H */
diff --git a/lib/ext/cryptocell-312-runtime/codesafe/src/psa_driver_api/include/cc3xx_internal_aes.h b/lib/ext/cryptocell-312-runtime/codesafe/src/psa_driver_api/include/cc3xx_internal_aes.h
new file mode 100644
index 0000000..4dfcd10
--- /dev/null
+++ b/lib/ext/cryptocell-312-runtime/codesafe/src/psa_driver_api/include/cc3xx_internal_aes.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef CC3XX_INTERNAL_AES_H
+#define CC3XX_INTERNAL_AES_H
+
+#include "cc3xx_crypto_primitives.h"
+
+/**
+ * \brief    Initialize the specified AES context.
+ */
+void cc3xx_aes_init(AesContext_t *ctx);
+
+/**
+ * \brief   Release and clear the specified AES context.
+ */
+void cc3xx_aes_free(AesContext_t *ctx);
+
+/**
+ * \brief   Set the encryption key.
+ */
+psa_status_t cc3xx_aes_setkey_enc(
+        AesContext_t *ctx,
+        const uint8_t *key,
+        size_t key_bits);
+
+/**
+ * \brief   Set the decryption key.
+ */
+psa_status_t cc3xx_aes_setkey_dec(
+        AesContext_t *ctx,
+        const uint8_t *key,
+        size_t key_bits);
+
+/**
+ * \brief   AES block encryption/decryption.
+ */
+psa_status_t cc3xx_aes_crypt(
+        AesContext_t *ctx,
+        aesMode_t mode,
+        size_t length,
+        uint8_t iv[AES_IV_SIZE],
+        const uint8_t *input,
+        uint8_t *output);
+
+#endif /* CC3XX_INTERNAL_AES_H */
diff --git a/lib/ext/cryptocell-312-runtime/codesafe/src/psa_driver_api/include/cc3xx_internal_chacha20.h b/lib/ext/cryptocell-312-runtime/codesafe/src/psa_driver_api/include/cc3xx_internal_chacha20.h
new file mode 100644
index 0000000..72625a6
--- /dev/null
+++ b/lib/ext/cryptocell-312-runtime/codesafe/src/psa_driver_api/include/cc3xx_internal_chacha20.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef CC3XX_INTERNAL_CHACHA20_H
+#define CC3XX_INTERNAL_CHACHA20_H
+
+#include "cc3xx_crypto_primitives.h"
+
+/**
+ * \brief   Initialize the specified ChaCha20 context.
+ */
+void cc3xx_chacha20_init(ChachaContext_t *ctx);
+
+/**
+ * \brief   Release and clear the specified ChaCha20 context.
+ */
+void cc3xx_chacha20_free(ChachaContext_t *ctx);
+
+/**
+ * \brief   Set the encryption/decryption key.
+ */
+psa_status_t cc3xx_chacha20_setkey(
+        ChachaContext_t *ctx,
+        const uint8_t key[CHACHA_256_BIT_KEY_SIZE]);
+
+/**
+ * \brief   Set the nonce and initial counter value.
+ */
+psa_status_t cc3xx_chacha20_starts(
+        ChachaContext_t *ctx,
+        const uint8_t nonce[CHACHA_IV_96_SIZE_BYTES],
+        uint32_t counter);
+
+/**
+ * \brief   Encrypt/decrypt data.
+ */
+psa_status_t cc3xx_chacha20_update(
+        ChachaContext_t *ctx,
+        size_t size,
+        const uint8_t *input,
+        unsigned char *output);
+
+#endif /* CC3XX_INTERNAL_CHACHA20_H */
diff --git a/lib/ext/cryptocell-312-runtime/codesafe/src/psa_driver_api/include/cc3xx_psa_cipher.h b/lib/ext/cryptocell-312-runtime/codesafe/src/psa_driver_api/include/cc3xx_psa_cipher.h
new file mode 100644
index 0000000..178184f
--- /dev/null
+++ b/lib/ext/cryptocell-312-runtime/codesafe/src/psa_driver_api/include/cc3xx_psa_cipher.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef CC3XX_PSA_CIPHER_H
+#define CC3XX_PSA_CIPHER_H
+
+#include "psa/crypto.h"
+
+#include "cc3xx_crypto_primitives.h"
+#include "cc3xx_internal_aes.h"
+#include "cc3xx_internal_chacha20.h"
+
+psa_status_t cc3xx_cipher_encrypt_setup(
+        cc3xx_cipher_operation_t *operation,
+        const psa_key_attributes_t *attributes,
+        const uint8_t *key, size_t key_length,
+        psa_algorithm_t alg);
+
+psa_status_t cc3xx_cipher_decrypt_setup(
+        cc3xx_cipher_operation_t *operation,
+        const psa_key_attributes_t *attributes,
+        const uint8_t *key, size_t key_length,
+        psa_algorithm_t alg);
+
+psa_status_t cc3xx_cipher_set_iv(
+        cc3xx_cipher_operation_t *operation,
+        const uint8_t *iv, size_t iv_length);
+
+psa_status_t cc3xx_cipher_update(
+        cc3xx_cipher_operation_t *operation,
+        const uint8_t *input, size_t input_length,
+        uint8_t *output, size_t output_size, size_t *output_length);
+
+psa_status_t cc3xx_cipher_finish(
+        cc3xx_cipher_operation_t *operation,
+        uint8_t *output, size_t output_size, size_t *output_length);
+
+psa_status_t cc3xx_cipher_abort(
+        cc3xx_cipher_operation_t *operation);
+
+psa_status_t cc3xx_psa_cipher_encrypt(
+        const psa_key_attributes_t *attributes,
+        const uint8_t *key_buffer,
+        size_t key_buffer_size,
+        psa_algorithm_t alg,
+        const uint8_t *input,
+        size_t input_length,
+        uint8_t *output,
+        size_t output_size,
+        size_t *output_length);
+
+psa_status_t cc3xx_psa_cipher_decrypt(
+        const psa_key_attributes_t *attributes,
+        const uint8_t *key_buffer,
+        size_t key_buffer_size,
+        psa_algorithm_t alg,
+        const uint8_t *input,
+        size_t input_length,
+        uint8_t *output,
+        size_t output_size,
+        size_t *output_length);
+
+#endif /* CC3XX_PSA_CIPHER_H */
diff --git a/lib/ext/cryptocell-312-runtime/codesafe/src/psa_driver_api/include/cc3xx_psa_hash.h b/lib/ext/cryptocell-312-runtime/codesafe/src/psa_driver_api/include/cc3xx_psa_hash.h
new file mode 100644
index 0000000..a4554de
--- /dev/null
+++ b/lib/ext/cryptocell-312-runtime/codesafe/src/psa_driver_api/include/cc3xx_psa_hash.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef HASH_COMMON_H
+#define HASH_COMMON_H
+
+#include "cc3xx_crypto_primitives.h"
+#include "psa/crypto.h"
+
+#if defined(MBEDTLS_CONFIG_FILE)
+#include MBEDTLS_CONFIG_FILE
+#endif
+
+psa_status_t cc3xx_hash_setup(cc3xx_hash_operation_t *operation,
+                              psa_algorithm_t alg);
+
+psa_status_t cc3xx_hash_clone(const cc3xx_hash_operation_t *source_operation,
+                              cc3xx_hash_operation_t *target_operation);
+
+psa_status_t cc3xx_hash_update(cc3xx_hash_operation_t *operation,
+                               const uint8_t *input, size_t input_length);
+
+psa_status_t cc3xx_hash_finish(cc3xx_hash_operation_t *operation, uint8_t *hash,
+                               size_t hash_size, size_t *hash_length);
+
+psa_status_t cc3xx_hash_abort(cc3xx_hash_operation_t *operation);
+
+psa_status_t cc3xx_hash_compute(psa_algorithm_t alg, const uint8_t *input,
+                                size_t input_length, uint8_t *hash,
+                                size_t hash_size, size_t *hash_length);
+#endif /*HASH_COMMON_H */
diff --git a/lib/ext/cryptocell-312-runtime/codesafe/src/psa_driver_api/include/cc3xx_psa_mac.h b/lib/ext/cryptocell-312-runtime/codesafe/src/psa_driver_api/include/cc3xx_psa_mac.h
new file mode 100644
index 0000000..2a494b5
--- /dev/null
+++ b/lib/ext/cryptocell-312-runtime/codesafe/src/psa_driver_api/include/cc3xx_psa_mac.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef CC3XX_PSA_MAC_H
+#define CC3XX_PSA_MAC_H
+
+#include "cc3xx_crypto_primitives.h"
+#include "psa/crypto.h"
+
+psa_status_t cc3xx_mac_sign_setup(cc3xx_mac_operation_t *operation,
+                                  const psa_key_attributes_t *attributes,
+                                  const uint8_t *key_buffer,
+                                  size_t key_buffer_size, psa_algorithm_t alg);
+
+psa_status_t cc3xx_mac_verify_setup(cc3xx_mac_operation_t *operation,
+                                    const psa_key_attributes_t *attributes,
+                                    const uint8_t *key_buffer,
+                                    size_t key_buffer_size,
+                                    psa_algorithm_t alg);
+
+psa_status_t cc3xx_mac_update(cc3xx_mac_operation_t *operation,
+                              const uint8_t *input, size_t input_length);
+
+psa_status_t cc3xx_mac_sign_finish(cc3xx_mac_operation_t *operation,
+                                   uint8_t *mac, size_t mac_size,
+                                   size_t *mac_length);
+
+psa_status_t cc3xx_mac_verify_finish(cc3xx_mac_operation_t *operation,
+                                     const uint8_t *mac, size_t mac_length);
+
+psa_status_t cc3xx_mac_abort(cc3xx_mac_operation_t *operation);
+
+psa_status_t cc3xx_mac_compute(const psa_key_attributes_t *attributes,
+                               const uint8_t *key_buffer,
+                               size_t key_buffer_size, psa_algorithm_t alg,
+                               const uint8_t *input, size_t input_length,
+                               uint8_t *mac, size_t mac_size,
+                               size_t *mac_length);
+
+#endif /* CC3XX_PSA_MAC_H */
diff --git a/lib/ext/cryptocell-312-runtime/codesafe/src/psa_driver_api/src/cc3xx_internal_aes.c b/lib/ext/cryptocell-312-runtime/codesafe/src/psa_driver_api/src/cc3xx_internal_aes.c
new file mode 100644
index 0000000..69cdf45
--- /dev/null
+++ b/lib/ext/cryptocell-312-runtime/codesafe/src/psa_driver_api/src/cc3xx_internal_aes.c
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include "cc3xx_internal_aes.h"
+
+#include "cc_pal_types.h"
+#include "cc_pal_mem.h"
+#include "cc_pal_abort.h"
+
+void cc3xx_aes_init(AesContext_t *ctx)
+{
+    if (NULL == ctx) {
+        CC_PalAbort("ctx cannot be NULL");
+        return;
+    }
+
+    ctx->padType            = CRYPTO_PADDING_NONE;
+    ctx->dataBlockType      = FIRST_BLOCK;
+    ctx->inputDataAddrType  = DLLI_ADDR;
+    ctx->outputDataAddrType = DLLI_ADDR;
+}
+
+void cc3xx_aes_free(AesContext_t *ctx)
+{
+    if (NULL == ctx) {
+        CC_PAL_LOG_ERR("ctx cannot be NULL\n");
+        return;
+    }
+
+    CC_PalMemSet(ctx, 0, sizeof(AesContext_t));
+}
+
+static psa_status_t aes_setkey(
+        AesContext_t *ctx,
+        const uint8_t *key,
+        size_t key_bits,
+        cryptoDirection_t direction)
+{
+    if (NULL == ctx) {
+        CC_PAL_LOG_ERR("ctx cannot be NULL\n");
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    if (NULL == key) {
+        CC_PAL_LOG_ERR("key cannot be NULL\n");
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    ctx->dir = direction;
+    ctx->cryptoKey = USER_KEY;
+
+    switch (key_bits) {
+    case 128:
+        ctx->keySizeId = KEY_SIZE_128_BIT;
+        break;
+    case 192:
+        ctx->keySizeId = KEY_SIZE_192_BIT;
+        break;
+    case 256:
+        ctx->keySizeId = KEY_SIZE_256_BIT;
+        break;
+    default:
+        CC_PAL_LOG_ERR("key_bits (%d) not supported\n", key_bits);
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    CC_PalMemCopy(ctx->keyBuf, key, key_bits/8);
+
+    return PSA_SUCCESS;
+}
+
+psa_status_t cc3xx_aes_setkey_enc(
+        AesContext_t *ctx,
+        const uint8_t *key,
+        size_t key_bits)
+{
+    return aes_setkey(ctx, key, key_bits, CRYPTO_DIRECTION_ENCRYPT);
+}
+
+psa_status_t cc3xx_aes_setkey_dec(
+        AesContext_t *ctx,
+        const uint8_t *key,
+        size_t key_bits)
+{
+    return aes_setkey(ctx, key, key_bits, CRYPTO_DIRECTION_DECRYPT);
+}
+
+psa_status_t cc3xx_aes_crypt(
+        AesContext_t *ctx,
+        aesMode_t mode,
+        size_t length,
+        uint8_t iv[AES_IV_SIZE],
+        const uint8_t *input,
+        uint8_t *output)
+{
+    drvError_t drvRet;
+    CCBuffInfo_t inBuffInfo;
+    CCBuffInfo_t outBuffInfo;
+
+    if (0 == length) {
+        return PSA_SUCCESS;
+    }
+
+    if (NULL == ctx || NULL == input || NULL == output || NULL == iv) {
+        CC_PAL_LOG_ERR("Null pointer exception\n");
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    if (length % AES_BLOCK_SIZE) {
+        CC_PAL_LOG_ERR("Length not a multiple of the block size %d\n",
+                       AES_BLOCK_SIZE);
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    ctx->mode = mode;
+
+    if (mode != CIPHER_ECB) {
+        CC_PalMemCopy(ctx->ivBuf, iv, AES_IV_SIZE);
+    }
+
+    drvRet = SetDataBuffersInfo(input,  length, &inBuffInfo,
+                                output, length, &outBuffInfo);
+    if (drvRet != 0) {
+        CC_PAL_LOG_ERR("Bad i/o buffers\n");
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    drvRet = ProcessAesDrv(ctx, &inBuffInfo, &outBuffInfo, length);
+    if (drvRet != AES_DRV_OK) {
+        CC_PAL_LOG_ERR("cc3xx_aes_crypt failed: %d\n", drvRet);
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    if (mode != CIPHER_ECB) {
+        CC_PalMemCopy(iv, ctx->ivBuf, AES_IV_SIZE);
+    }
+
+    return PSA_SUCCESS;
+}
diff --git a/lib/ext/cryptocell-312-runtime/codesafe/src/psa_driver_api/src/cc3xx_internal_chacha20.c b/lib/ext/cryptocell-312-runtime/codesafe/src/psa_driver_api/src/cc3xx_internal_chacha20.c
new file mode 100644
index 0000000..954ea05
--- /dev/null
+++ b/lib/ext/cryptocell-312-runtime/codesafe/src/psa_driver_api/src/cc3xx_internal_chacha20.c
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include "cc3xx_internal_chacha20.h"
+
+#include "cc_pal_types.h"
+#include "cc_pal_mem.h"
+#include "cc_pal_abort.h"
+
+void cc3xx_chacha20_init(ChachaContext_t *ctx)
+{
+    if (NULL == ctx) {
+        CC_PalAbort("ctx cannot be NULL");
+        return;
+    }
+
+    ctx->inputDataAddrType  = DLLI_ADDR;
+    ctx->outputDataAddrType = DLLI_ADDR;
+}
+
+void cc3xx_chacha20_free(ChachaContext_t *ctx)
+{
+    if (NULL == ctx) {
+        CC_PAL_LOG_ERR("ctx cannot be NULL\n");
+        return;
+    }
+
+    CC_PalMemSet(ctx, 0, sizeof(AesContext_t));
+}
+
+psa_status_t cc3xx_chacha20_setkey(
+        ChachaContext_t *ctx,
+        const uint8_t key[CHACHA_256_BIT_KEY_SIZE])
+{
+    if (NULL == ctx) {
+        CC_PAL_LOG_ERR("ctx cannot be NULL\n");
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    if (NULL == key) {
+        CC_PAL_LOG_ERR("key cannot be NULL\n");
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    CC_PalMemCopy(ctx->keyBuf, key, CHACHA_256_BIT_KEY_SIZE);
+
+    return PSA_SUCCESS;
+}
+
+psa_status_t cc3xx_chacha20_starts(
+        ChachaContext_t *ctx,
+        const uint8_t nonce[CHACHA_IV_96_SIZE_BYTES],
+        uint32_t counter)
+{
+    if (NULL == ctx) {
+        CC_PAL_LOG_ERR("ctx cannot be NULL\n");
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    if (nonce == NULL) {
+        CC_PAL_LOG_ERR("nonce cannot be NULL\n");
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    ctx->nonceSize = NONCE_SIZE_96;
+
+    CC_PalMemCopy(ctx->nonceBuf, nonce, CHACHA_IV_96_SIZE_BYTES);
+
+    ctx->blockCounterLsb = counter;
+    ctx->blockCounterMsb = 0;
+
+    return PSA_SUCCESS;
+}
+
+psa_status_t cc3xx_chacha20_update(
+        ChachaContext_t *ctx,
+        size_t size,
+        const uint8_t *input,
+        unsigned char *output)
+{
+    drvError_t drvRc;
+    CCBuffInfo_t inBuffInfo;
+    CCBuffInfo_t outBuffInfo;
+
+    if (0 == size) {
+        return PSA_SUCCESS;
+    }
+
+    if (NULL == ctx || NULL == input || NULL == output) {
+        CC_PAL_LOG_ERR("Null pointer exception\n");
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    drvRc = SetDataBuffersInfo( input, size, &inBuffInfo,
+                               output, size, &outBuffInfo);
+    if (drvRc != 0) {
+        CC_PAL_LOG_ERR("Bad i/o buffers\n");
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    drvRc = ProcessChacha(ctx, &inBuffInfo, &outBuffInfo, size);
+    if (drvRc != 0) {
+        CC_PAL_LOG_ERR("cc3xx_chacha20_update failed: %d\n", drvRc);
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    return PSA_SUCCESS;
+}
diff --git a/lib/ext/cryptocell-312-runtime/codesafe/src/psa_driver_api/src/cc3xx_psa_cipher.c b/lib/ext/cryptocell-312-runtime/codesafe/src/psa_driver_api/src/cc3xx_psa_cipher.c
new file mode 100644
index 0000000..19673e2
--- /dev/null
+++ b/lib/ext/cryptocell-312-runtime/codesafe/src/psa_driver_api/src/cc3xx_psa_cipher.c
@@ -0,0 +1,573 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include "cc3xx_psa_cipher.h"
+#include "cc_pal_mem.h"
+
+/* FixMe: implement pkcs#7 padding in HW
+ * The function below was taken from Mbed TLS and implements pkcs#7
+ * padding in software. It might be possible to do this in HW using
+ * CC; however, we will need to modify the SW abstraction function:
+ * ProcessAesDrv, and others.
+ */
+
+static psa_status_t add_pkcs_padding(
+        uint8_t *output,
+        size_t output_size,
+        size_t   data_size)
+{
+    if (NULL == output) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    uint8_t padding_size = output_size - data_size;
+
+    for (size_t i = 0; i < padding_size; i++) {
+        output[data_size + i] = padding_size;
+    }
+
+    return PSA_SUCCESS;
+}
+
+static psa_status_t cipher_setup(
+        cc3xx_cipher_operation_t *operation,
+        const psa_key_attributes_t *attributes,
+        const uint8_t *key, size_t key_length,
+        psa_algorithm_t alg,
+        psa_encrypt_or_decrypt_t dir)
+{
+    psa_status_t ret = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_key_type_t key_type = psa_get_key_type(attributes);
+    size_t key_bits = psa_get_key_bits(attributes);
+
+    (void)key_length;
+
+    if (!PSA_ALG_IS_CIPHER(alg)) {
+        return PSA_ERROR_BAD_STATE;
+    }
+
+    CC_PalMemSetZero(operation, sizeof(cc3xx_cipher_operation_t));
+
+    operation->alg        = alg;
+    operation->key_type   = key_type;
+    operation->dir        = dir;
+    operation->iv_size    =  PSA_CIPHER_IV_LENGTH(key_type, alg);
+    operation->block_size = (PSA_ALG_IS_STREAM_CIPHER(alg) ? 1 :
+                             PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type));
+
+    switch (operation->key_type) {
+    case PSA_KEY_TYPE_AES:
+        cc3xx_aes_init(&operation->aes_ctx);
+
+        switch (operation->dir) {
+        case PSA_CRYPTO_DRIVER_ENCRYPT:
+            if (( ret = cc3xx_aes_setkey_enc(
+                    &operation->aes_ctx,
+                    key,
+                    key_bits) )
+                != PSA_SUCCESS) {
+                return ret;
+            }
+
+            break;
+        case PSA_CRYPTO_DRIVER_DECRYPT:
+            if (( ret = cc3xx_aes_setkey_dec(
+                    &operation->aes_ctx,
+                    key,
+                    key_bits) )
+                != PSA_SUCCESS) {
+                return ret;
+            }
+
+            break;
+        default:
+            return PSA_ERROR_NOT_SUPPORTED;
+        }
+
+        break;
+    case PSA_KEY_TYPE_CHACHA20:
+        cc3xx_chacha20_init(&operation->chacha_ctx);
+
+        if (( ret = cc3xx_chacha20_setkey(
+                &operation->chacha_ctx,
+                key) )
+            != PSA_SUCCESS) {
+            return ret;
+        }
+
+        break;
+    default:
+        // Software fallback
+        return PSA_ERROR_NOT_SUPPORTED;
+    }
+
+    if (operation->alg == PSA_ALG_CBC_PKCS7) {
+        operation->add_padding = add_pkcs_padding;
+    } else {
+        operation->add_padding = NULL;
+    }
+
+    return ret;
+}
+
+psa_status_t cc3xx_cipher_encrypt_setup(
+        cc3xx_cipher_operation_t *operation,
+        const psa_key_attributes_t *attributes,
+        const uint8_t *key, size_t key_length,
+        psa_algorithm_t alg)
+{
+    return cipher_setup(operation,
+                        attributes,
+                        key, key_length,
+                        alg,
+                        PSA_CRYPTO_DRIVER_ENCRYPT);
+}
+
+psa_status_t cc3xx_cipher_decrypt_setup(
+        cc3xx_cipher_operation_t *operation,
+        const psa_key_attributes_t *attributes,
+        const uint8_t *key, size_t key_length,
+        psa_algorithm_t alg)
+{
+    return cipher_setup(operation,
+                        attributes,
+                        key, key_length,
+                        alg,
+                        PSA_CRYPTO_DRIVER_DECRYPT);
+}
+
+psa_status_t cc3xx_cipher_set_iv(
+        cc3xx_cipher_operation_t *operation,
+        const uint8_t *iv, size_t iv_length)
+{
+    psa_status_t ret = PSA_ERROR_CORRUPTION_DETECTED;
+
+    if (iv_length > AES_IV_SIZE) {
+        return PSA_ERROR_NOT_SUPPORTED;
+    }
+
+    if (iv_length != 0) {
+        CC_PalMemCopy(operation->iv, iv, iv_length);
+        operation->iv_size =  iv_length;
+    }
+
+    ret = PSA_SUCCESS;
+
+    if (operation->key_type == PSA_KEY_TYPE_CHACHA20) {
+        if (( ret = cc3xx_chacha20_starts(
+                &operation->chacha_ctx,
+                iv,
+                0U) )
+            != PSA_SUCCESS) {
+            return ret;
+        }
+    }
+
+    return ret;
+}
+
+psa_status_t cc3xx_cipher_update(
+        cc3xx_cipher_operation_t *operation,
+        const uint8_t *input, size_t input_length,
+        uint8_t *output, size_t output_size, size_t *output_length)
+{
+    psa_status_t ret = PSA_ERROR_CORRUPTION_DETECTED;
+    size_t block_size = operation->block_size;
+    size_t expected_output_size;
+
+    if (!PSA_ALG_IS_STREAM_CIPHER(operation->alg)) {
+        expected_output_size =
+                ( operation->unprocessed_size + input_length )
+                / operation->block_size * operation->block_size;
+    } else {
+        expected_output_size = input_length;
+    }
+
+    if (output_size < expected_output_size) {
+        return PSA_ERROR_BUFFER_TOO_SMALL;
+    }
+
+    *output_length = 0;
+
+    size_t copy_len;
+
+    switch (operation->key_type) {
+    case PSA_KEY_TYPE_AES:
+        switch (operation->alg) {
+        case PSA_ALG_CBC_NO_PADDING:
+        case PSA_ALG_CBC_PKCS7:
+            if ((operation->dir == PSA_CRYPTO_DRIVER_DECRYPT &&
+                 NULL != operation->add_padding              &&
+                 input_length   <= block_size -
+                 operation->unprocessed_size)                ||
+                (operation->dir == PSA_CRYPTO_DRIVER_DECRYPT &&
+                 NULL == operation->add_padding              &&
+                 input_length    < block_size -
+                 operation->unprocessed_size)                ||
+                (operation->dir == PSA_CRYPTO_DRIVER_ENCRYPT &&
+                 input_length    < block_size -
+                 operation->unprocessed_size)) {
+                CC_PalMemCopy(&(operation->unprocessed_data
+                [operation->unprocessed_size]),
+                              input,
+                              input_length);
+
+                operation->unprocessed_size += input_length;
+                return PSA_SUCCESS;
+            }
+
+            if (0 != operation->unprocessed_size) {
+                copy_len = block_size
+                           - operation->unprocessed_size;
+
+                CC_PalMemCopy(&(operation->unprocessed_data
+                [operation->unprocessed_size]),
+                              input,
+                              copy_len);
+
+                if (( ret = cc3xx_aes_crypt(
+                        &operation->aes_ctx,
+                        CIPHER_CBC,
+                        block_size,
+                        operation->iv,
+                        operation->unprocessed_data,
+                        output) )
+                    != PSA_SUCCESS) {
+                    return ret;
+                }
+
+                operation->unprocessed_size = 0;
+
+                *output_length = block_size;
+                output       += block_size;
+
+                input         += copy_len;
+                input_length  -= copy_len;
+            }
+
+            if (0 != input_length) {
+                copy_len = input_length % block_size;
+
+                if (copy_len == 0 &&
+                    operation->dir==PSA_CRYPTO_DRIVER_DECRYPT &&
+                    operation->add_padding != NULL) {
+                    copy_len = block_size;
+                }
+
+                CC_PalMemCopy(operation->unprocessed_data,
+                              &(input[copy_len]),
+                              copy_len);
+
+                operation->unprocessed_size += copy_len;
+                input_length  -= copy_len;
+            }
+
+            if (0 != input_length) {
+                if (( ret = cc3xx_aes_crypt(
+                        &operation->aes_ctx,
+                        CIPHER_CBC,
+                        input_length,
+                        operation->iv,
+                        input,
+                        output) )
+                    != PSA_SUCCESS) {
+                    return ret;
+                }
+
+                *output_length = input_length;
+            }
+
+            break;
+        case PSA_ALG_CTR:
+            if (( ret = cc3xx_aes_crypt(
+                    &operation->aes_ctx,
+                    CIPHER_CTR,
+                    input_length,
+                    operation->iv,
+                    input,
+                    output) )
+                != PSA_SUCCESS) {
+                return ret;
+            }
+
+            *output_length = input_length;
+
+            break;
+        case PSA_ALG_OFB:
+            if (( ret = cc3xx_aes_crypt(
+                    &operation->aes_ctx,
+                    CIPHER_OFB,
+                    input_length,
+                    operation->iv,
+                    input,
+                    output) )
+                != PSA_SUCCESS) {
+                return ret;
+            }
+
+            *output_length = input_length;
+
+            break;
+        default:
+            return PSA_ERROR_NOT_SUPPORTED;
+        }
+
+        if (*output_length > output_size) {
+            return PSA_ERROR_CORRUPTION_DETECTED;
+        }
+
+        break;
+    case PSA_KEY_TYPE_CHACHA20:
+        if (( ret = cc3xx_chacha20_update(
+                &operation->chacha_ctx,
+                input_length,
+                input,
+                output) )
+            != PSA_SUCCESS) {
+            return ret;
+        }
+
+        *output_length = input_length;
+
+        break;
+    default:
+        // Software fallback
+        return PSA_ERROR_NOT_SUPPORTED;
+    }
+
+    return ret;
+}
+
+psa_status_t cc3xx_cipher_finish(
+        cc3xx_cipher_operation_t *operation,
+        uint8_t *output,
+        size_t output_size,
+        size_t *output_length)
+{
+    psa_status_t ret = PSA_ERROR_CORRUPTION_DETECTED;
+
+    *output_length = 0;
+
+    switch (operation->key_type) {
+    case PSA_KEY_TYPE_AES:
+        switch (operation->alg) {
+        case PSA_ALG_CBC_NO_PADDING:
+        case PSA_ALG_CBC_PKCS7:
+            if (operation->dir == PSA_CRYPTO_DRIVER_ENCRYPT) {
+                if (operation->add_padding == NULL) {
+                    if (operation->unprocessed_size != 0) {
+                        return PSA_ERROR_GENERIC_ERROR;
+                    }
+
+                    return PSA_SUCCESS;
+                }
+
+                if (( ret = operation->add_padding(
+                        operation->unprocessed_data,
+                        operation->block_size,
+                        operation->unprocessed_size) )
+                    != PSA_SUCCESS) {
+                    return ret;
+                }
+            } else if (operation->block_size !=
+                       operation->unprocessed_size) {
+                if (operation->add_padding == NULL &&
+                    operation->unprocessed_size == 0) {
+                    return PSA_SUCCESS;
+                }
+
+                return PSA_ERROR_GENERIC_ERROR;
+            }
+
+            if (( ret = cc3xx_aes_crypt(
+                    &operation->aes_ctx,
+                    CIPHER_CBC,
+                    output_size,
+                    operation->iv,
+                    operation->unprocessed_data,
+                    output ))
+                != PSA_SUCCESS) {
+                return ret;
+            }
+
+            *output_length = operation->block_size;
+
+            break;
+        case PSA_ALG_CTR:
+        case PSA_ALG_OFB:
+            return PSA_SUCCESS;
+        default:
+            return PSA_ERROR_NOT_SUPPORTED;
+        }
+        break;
+    case PSA_KEY_TYPE_CHACHA20:
+        return PSA_SUCCESS;
+    default:
+        // Software fallback
+        ret = PSA_ERROR_NOT_SUPPORTED;
+    }
+
+    return ret;
+}
+
+psa_status_t cc3xx_cipher_abort(cc3xx_cipher_operation_t *operation)
+{
+    switch (operation->key_type) {
+    case PSA_KEY_TYPE_AES:
+        cc3xx_aes_free(&operation->aes_ctx);
+        break;
+    case PSA_KEY_TYPE_CHACHA20:
+        cc3xx_chacha20_free(&operation->chacha_ctx);
+        return PSA_ERROR_NOT_SUPPORTED;
+    default:
+        // Software fallback
+        return PSA_ERROR_NOT_SUPPORTED;
+    }
+
+    CC_PalMemSetZero(operation, sizeof(cc3xx_cipher_operation_t));
+
+    return PSA_SUCCESS;
+}
+
+psa_status_t cc3xx_psa_cipher_encrypt(
+        const psa_key_attributes_t *attributes,
+        const uint8_t *key_buffer,
+        size_t key_buffer_size,
+        psa_algorithm_t alg,
+        const uint8_t *input,
+        size_t input_length,
+        uint8_t *output,
+        size_t output_size,
+        size_t *output_length)
+{
+    psa_status_t ret = PSA_ERROR_CORRUPTION_DETECTED;
+    cc3xx_cipher_operation_t operation = {0};
+    size_t olength, accumulated_length;
+
+    if ( (ret = cc3xx_cipher_encrypt_setup(
+            &operation,
+            attributes,
+            key_buffer,
+            key_buffer_size,
+            alg) )
+         != PSA_SUCCESS) {
+        cc3xx_cipher_abort(&operation);
+        return ret;
+    }
+
+    accumulated_length = 0;
+    if (operation.iv_size > 0) {
+        if ( (ret = cc3xx_cipher_set_iv(
+                &operation,
+                output,
+                operation.iv_size) )
+             != PSA_SUCCESS) {
+            cc3xx_cipher_abort(&operation);
+            return ret;
+        }
+
+        accumulated_length = operation.iv_size;
+    }
+
+    if ( (ret = cc3xx_cipher_update(
+            &operation,
+            input,
+            input_length,
+            output + operation.iv_size,
+            output_size - operation.iv_size,
+            &olength) )
+         != PSA_SUCCESS) {
+        cc3xx_cipher_abort(&operation);
+        return ret;
+    }
+
+    accumulated_length += olength;
+
+    if ( (ret = cc3xx_cipher_finish(
+            &operation,
+            output + accumulated_length,
+            output_size - accumulated_length,
+            &olength) )
+         != PSA_SUCCESS) {
+        cc3xx_cipher_abort(&operation);
+        return ret;
+    }
+
+    *output_length = accumulated_length + olength;
+
+    ret = cc3xx_cipher_abort(&operation);
+
+    return ret;
+}
+
+psa_status_t cc3xx_psa_cipher_decrypt(
+        const psa_key_attributes_t *attributes,
+        const uint8_t *key_buffer,
+        size_t key_buffer_size,
+        psa_algorithm_t alg,
+        const uint8_t *input,
+        size_t input_length,
+        uint8_t *output,
+        size_t output_size,
+        size_t *output_length)
+{
+    psa_status_t ret = PSA_ERROR_CORRUPTION_DETECTED;
+    cc3xx_cipher_operation_t operation = {0};
+    size_t olength, accumulated_length;
+
+    if ( (ret = cc3xx_cipher_decrypt_setup(
+            &operation,
+            attributes,
+            key_buffer,
+            key_buffer_size,
+            alg) )
+         != PSA_SUCCESS) {
+        cc3xx_cipher_abort(&operation);
+        return ret;
+    }
+
+    if (operation.iv_size > 0) {
+        if ( (ret = cc3xx_cipher_set_iv(
+                &operation,
+                input,
+                operation.iv_size) )
+             != PSA_SUCCESS) {
+            cc3xx_cipher_abort(&operation);
+            return ret;
+        }
+    }
+
+    if ( (ret = cc3xx_cipher_update(
+            &operation,
+            input + operation.iv_size,
+            input_length - operation.iv_size,
+            output,
+            output_size,
+            &olength) )
+         != PSA_SUCCESS) {
+        cc3xx_cipher_abort(&operation);
+        return ret;
+    }
+
+    accumulated_length = olength;
+
+    if ( (ret = cc3xx_cipher_finish(
+            &operation,
+            output + accumulated_length,
+            output_size - accumulated_length,
+            &olength) )
+         != PSA_SUCCESS) {
+        cc3xx_cipher_abort(&operation);
+        return ret;
+    }
+
+    *output_length = accumulated_length + olength;
+
+    ret = cc3xx_cipher_abort(&operation);
+
+    return ret;
+}
diff --git a/lib/ext/cryptocell-312-runtime/codesafe/src/psa_driver_api/src/cc3xx_psa_hash.c b/lib/ext/cryptocell-312-runtime/codesafe/src/psa_driver_api/src/cc3xx_psa_hash.c
new file mode 100644
index 0000000..1e61354
--- /dev/null
+++ b/lib/ext/cryptocell-312-runtime/codesafe/src/psa_driver_api/src/cc3xx_psa_hash.c
@@ -0,0 +1,320 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include "cc3xx_psa_hash.h"
+#include "cc_pal_log.h"
+#include "cc_pal_mem.h"
+
+#define MAX_HASH_CHUNK_SIZE 0xffff
+
+/*!
+ * \defgroup private Private functions
+ *
+ */
+/*!@{*/
+
+/**
+ * \brief  Update a hash operation
+ *
+ * In CC312, DMA (i.e. for hash module input ) needs access to physical and
+ * continues memory. In order to assure the DMA can access the residue data saved
+ * in the hashCtx, it is being to copied to a local stack variable. In case memory
+ * is guaranteed to be DMAable, this copy can be removed, and hashCtx->prevData can
+ * be used.
+ */
+static psa_status_t hashUpdate(cc3xx_hash_operation_t *pHashUserCtx,
+                               uint8_t *pDataIn, size_t dataInSize)
+{
+    uint32_t rc       = 0;
+    size_t bytesToAdd = 0;
+    uint32_t localPrevDataIn[HASH_SHA512_BLOCK_SIZE_IN_WORDS];
+    CCBuffInfo_t inBuffInfo;
+
+    /* If pHashUserCtx->prevDataInSize > 0, fill it with with the current data
+     */
+    bytesToAdd = CC_MIN(
+        ((pHashUserCtx->blockSizeInBytes - pHashUserCtx->prevDataInSize) %
+         pHashUserCtx->blockSizeInBytes),
+        dataInSize);
+    if (bytesToAdd > 0) {
+        /* add the data to the remaining buffer */
+        CC_PalMemCopy(
+            &(((uint8_t *)(pHashUserCtx
+                               ->prevDataIn))[pHashUserCtx->prevDataInSize]),
+            pDataIn, bytesToAdd);
+        pHashUserCtx->prevDataInSize += bytesToAdd;
+        pDataIn += bytesToAdd;
+        dataInSize -= bytesToAdd;
+    }
+
+    /* If the remaining buffer is full, process the block (else, the remaining
+    buffer will be processed in the next update or finish) */
+    if (pHashUserCtx->prevDataInSize == pHashUserCtx->blockSizeInBytes) {
+        /* Copy prevDataIn to stack, in order to ensure continues and physical
+        memory access. That way, DMA will be able to access the data on any
+        platform.*/
+        CC_PalMemCopy(localPrevDataIn, pHashUserCtx->prevDataIn,
+                      CC_MIN(HASH_SHA512_BLOCK_SIZE_IN_WORDS * sizeof(uint32_t),
+                             pHashUserCtx->prevDataInSize));
+
+        rc = SetDataBuffersInfo((uint8_t *)localPrevDataIn,
+                                pHashUserCtx->blockSizeInBytes, &inBuffInfo,
+                                NULL, 0, NULL);
+        if (rc != 0) {
+            CC_PAL_LOG_ERR("illegal data buffers\n");
+            return PSA_ERROR_GENERIC_ERROR;
+        }
+
+        rc = ProcessHashDrv(pHashUserCtx, &inBuffInfo,
+                            pHashUserCtx->blockSizeInBytes);
+        if (rc != CC_OK) {
+            CC_PAL_LOG_ERR("ProcessHashDrv failed, ret = %d\n", rc);
+            return PSA_ERROR_GENERIC_ERROR;
+        }
+        pHashUserCtx->prevDataInSize = 0;
+    }
+
+    /* Process all the blocks that remain in the data */
+    bytesToAdd = (dataInSize / pHashUserCtx->blockSizeInBytes) *
+                 pHashUserCtx->blockSizeInBytes;
+    if (bytesToAdd > 0) {
+
+        rc =
+            SetDataBuffersInfo(pDataIn, bytesToAdd, &inBuffInfo, NULL, 0, NULL);
+        if (rc != 0) {
+            CC_PAL_LOG_ERR("illegal data buffers\n");
+            return PSA_ERROR_GENERIC_ERROR;
+        }
+
+        rc = ProcessHashDrv(pHashUserCtx, &inBuffInfo, bytesToAdd);
+        if (rc != CC_OK) {
+            CC_PAL_LOG_ERR("ProcessHashDrv failed, ret = %d\n", rc);
+            return PSA_ERROR_GENERIC_ERROR;
+        }
+        pDataIn += bytesToAdd;
+        dataInSize -= bytesToAdd;
+    }
+
+    /* Copy the remaining partial block to prevDataIn */
+    bytesToAdd = dataInSize;
+    if (bytesToAdd > 0) {
+        CC_PalMemCopy(
+            (uint8_t *)&(
+                (pHashUserCtx->prevDataIn)[pHashUserCtx->prevDataInSize]),
+            pDataIn, bytesToAdd);
+        pHashUserCtx->prevDataInSize += bytesToAdd;
+    }
+    return PSA_SUCCESS;
+}
+
+/*!@}*/
+
+psa_status_t cc3xx_hash_setup(cc3xx_hash_operation_t *operation,
+                              psa_algorithm_t alg)
+{
+    /* Init context */
+    HashContext_t *pHashCtx = NULL;
+
+    if (NULL == operation) {
+        CC_PAL_LOG_ERR("hash operation is NULL\n");
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    pHashCtx = (HashContext_t *)operation;
+    CC_PalMemSetZero(pHashCtx, sizeof(HashContext_t));
+    switch (alg) {
+#if defined MBEDTLS_SHA1_C
+    case PSA_ALG_SHA_1:
+        pHashCtx->mode = HASH_SHA1;
+        break;
+#endif
+#if defined MBEDTLS_SHA256_C
+    case PSA_ALG_SHA_224:
+        pHashCtx->mode = HASH_SHA224;
+        break;
+    case PSA_ALG_SHA_256:
+        pHashCtx->mode = HASH_SHA256;
+        break;
+#endif
+    default:
+        return PSA_ERROR_NOT_SUPPORTED;
+    }
+    pHashCtx->blockSizeInBytes = HASH_BLOCK_SIZE_IN_BYTES;
+    drvError_t ret             = InitHashDrv(operation);
+    if (ret == HASH_DRV_OK) {
+        return PSA_SUCCESS;
+    } else { /* change PSA error code? */
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+}
+
+psa_status_t cc3xx_hash_clone(const cc3xx_hash_operation_t *source_operation,
+                              cc3xx_hash_operation_t *target_operation)
+{
+    if (source_operation == NULL || target_operation == NULL) {
+        CC_PAL_LOG_ERR("source or target operation is NULL\n");
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+    CC_PalMemCopy(target_operation, source_operation,
+                  sizeof(cc3xx_hash_operation_t));
+    return PSA_SUCCESS;
+}
+
+psa_status_t cc3xx_hash_update(cc3xx_hash_operation_t *operation,
+                               const uint8_t *input, size_t input_length)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    if (NULL == operation) {
+        CC_PAL_LOG_ERR("ctx is NULL\n");
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    if (0 == input_length) {
+        /* This is a valid situation, no need to call hashUpdate.
+        HashFinish will produce the result. */
+        return PSA_SUCCESS;
+    }
+
+    /* if len not zero, but pointer is NULL */
+    if (NULL == input) {
+        CC_PAL_LOG_ERR("input is NULL\n");
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    while (input_length > MAX_HASH_CHUNK_SIZE) {
+        status = hashUpdate(operation, (uint8_t *)input, MAX_HASH_CHUNK_SIZE);
+
+        input_length -= MAX_HASH_CHUNK_SIZE;
+        input += MAX_HASH_CHUNK_SIZE;
+
+        if (status != PSA_SUCCESS) {
+            CC_PAL_LOG_ERR("hashUpdate failed, status = %d\n", status);
+            return status;
+        }
+    }
+
+    status = hashUpdate(operation, (uint8_t *)input, input_length);
+    if (status != PSA_SUCCESS) {
+        CC_PAL_LOG_ERR("hashUpdate failed, status = %d\n", status);
+        return status;
+    }
+
+    return status;
+}
+
+psa_status_t cc3xx_hash_finish(cc3xx_hash_operation_t *operation, uint8_t *hash,
+                               size_t hash_size, size_t *hash_length)
+{
+    uint32_t localPrevDataIn[HASH_SHA512_BLOCK_SIZE_IN_WORDS];
+    size_t dataInSize = 0;
+    drvError_t drvRc  = HASH_DRV_OK;
+    CCBuffInfo_t inBuffInfo;
+    HashContext_t *pHashCtx = NULL;
+
+    if (operation == NULL || hash == NULL) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    pHashCtx = (HashContext_t *)operation;
+    if (pHashCtx->prevDataInSize != 0) {
+        /* Copy prevDataIn to stack, in order to ensure continues and physical
+        memory access. That way, DMA will be able to access the data on any
+        platform.*/
+        CC_PalMemCopy(localPrevDataIn, pHashCtx->prevDataIn,
+                      CC_MIN(HASH_SHA512_BLOCK_SIZE_IN_WORDS * sizeof(uint32_t),
+                             pHashCtx->prevDataInSize));
+        dataInSize = pHashCtx->prevDataInSize;
+    }
+    pHashCtx->isLastBlockProcessed = 1;
+
+    drvRc = SetDataBuffersInfo((uint8_t *)localPrevDataIn, dataInSize,
+                               &inBuffInfo, NULL, 0, NULL);
+    if (drvRc != 0) {
+        CC_PAL_LOG_ERR("illegal data buffers\n");
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    drvRc = ProcessHashDrv(pHashCtx, &inBuffInfo, dataInSize);
+    if (drvRc != HASH_DRV_OK) {
+        CC_PAL_LOG_ERR("ProcessHashDrv failed, ret = %d\n", drvRc);
+        return PSA_ERROR_GENERIC_ERROR;
+    }
+    drvRc = FinishHashDrv(pHashCtx);
+    if (drvRc != HASH_DRV_OK) {
+        CC_PAL_LOG_ERR("FinishHashDrv failed, ret = %d\n", drvRc);
+        return PSA_ERROR_GENERIC_ERROR;
+    }
+    pHashCtx->prevDataInSize = 0;
+
+    /* Copy the result to the user buffer  */
+    switch (pHashCtx->mode) {
+    case HASH_SHA1:
+        if (SHA1_DIGEST_SIZE_IN_BYTES > hash_size) {
+            return PSA_ERROR_BUFFER_TOO_SMALL;
+        }
+        CC_PalMemCopy(hash, pHashCtx->digest, SHA1_DIGEST_SIZE_IN_BYTES);
+        *hash_length = SHA1_DIGEST_SIZE_IN_BYTES;
+        break;
+    case HASH_SHA224:
+        if (SHA224_DIGEST_SIZE_IN_BYTES > hash_size) {
+            return PSA_ERROR_BUFFER_TOO_SMALL;
+        }
+        CC_PalMemCopy(hash, pHashCtx->digest, SHA224_DIGEST_SIZE_IN_BYTES);
+        *hash_length = SHA224_DIGEST_SIZE_IN_BYTES;
+        break;
+    case HASH_SHA256:
+        if (SHA256_DIGEST_SIZE_IN_BYTES > hash_size) {
+            return PSA_ERROR_BUFFER_TOO_SMALL;
+        }
+        CC_PalMemCopy(hash, pHashCtx->digest, SHA256_DIGEST_SIZE_IN_BYTES);
+        *hash_length = SHA256_DIGEST_SIZE_IN_BYTES;
+        break;
+    default:
+        CC_PAL_LOG_ERR("Unsupported HASH type (%d)\n", pHashCtx->mode);
+    }
+    return PSA_SUCCESS;
+}
+
+psa_status_t cc3xx_hash_abort(cc3xx_hash_operation_t *operation)
+{
+    /* The object has not been used yet, there is nothing to do */
+    if (operation->mode == 0) {
+        return PSA_SUCCESS;
+    }
+
+    CC_PalMemSetZero(operation, sizeof(cc3xx_hash_operation_t));
+    return PSA_SUCCESS;
+}
+
+psa_status_t cc3xx_hash_compute(psa_algorithm_t alg, const uint8_t *input,
+                                size_t input_length, uint8_t *hash,
+                                size_t hash_size, size_t *hash_length)
+{
+    psa_status_t status              = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_status_t abort_status        = PSA_ERROR_CORRUPTION_DETECTED;
+    cc3xx_hash_operation_t operation = {0};
+
+    status       = cc3xx_hash_setup(&operation, alg);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+    status = cc3xx_hash_update(&operation, input, input_length);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+    status = cc3xx_hash_finish(&operation, hash, hash_size, hash_length);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+exit:
+    cc3xx_hash_abort(&operation);
+    if (status != PSA_SUCCESS) {
+        *hash_length = 0;
+    }
+    return status;
+}
diff --git a/lib/ext/cryptocell-312-runtime/codesafe/src/psa_driver_api/src/cc3xx_psa_mac.c b/lib/ext/cryptocell-312-runtime/codesafe/src/psa_driver_api/src/cc3xx_psa_mac.c
new file mode 100644
index 0000000..df44f12
--- /dev/null
+++ b/lib/ext/cryptocell-312-runtime/codesafe/src/psa_driver_api/src/cc3xx_psa_mac.c
@@ -0,0 +1,519 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include "cc3xx_psa_mac.h"
+#include "cc3xx_psa_cipher.h"
+#include "cc3xx_psa_hash.h"
+#include "aes_driver.h"
+#include "cc_pal_log.h"
+#include "cc_pal_mem.h"
+
+#if defined(MBEDTLS_CONFIG_FILE)
+#include MBEDTLS_CONFIG_FILE
+#endif
+
+/* SHA512 is not supported, this is the only size we will need */
+#define MD_MAX_SIZE 32
+
+/*!
+ * \defgroup private Private functions
+ *
+ */
+/*!@{*/
+
+static size_t psa_get_hash_block_size(psa_algorithm_t alg)
+{
+    switch (alg) {
+    case PSA_ALG_MD5:
+        return (64);
+    case PSA_ALG_SHA_1:
+        return (64);
+    case PSA_ALG_SHA_224:
+        return (64);
+    case PSA_ALG_SHA_256:
+        return (64);
+    default:
+        return (0);
+    }
+}
+
+/*
+ * Initialize a context
+ */
+static psa_status_t cmac_init(AesContext_t *ctx)
+{
+    if (ctx == NULL) {
+        CC_PAL_LOG_ERR("NULL pointer exception\n");
+        return (PSA_ERROR_INVALID_ARGUMENT);
+    }
+
+    CC_PalMemSetZero(ctx, sizeof(AesContext_t));
+
+    ctx->mode               = CIPHER_CMAC;
+    ctx->padType            = CRYPTO_PADDING_NONE;
+    ctx->dir                = CRYPTO_DIRECTION_ENCRYPT;
+    ctx->inputDataAddrType  = DLLI_ADDR;
+    ctx->outputDataAddrType = DLLI_ADDR;
+    ctx->dataBlockType      = FIRST_BLOCK;
+
+    return PSA_SUCCESS;
+}
+
+static psa_status_t cmac_setkey(AesContext_t *ctx, const unsigned char *key,
+                                unsigned int keybits)
+{
+    if (ctx == NULL || key == NULL) {
+        CC_PAL_LOG_ERR("Null pointer, ctx or key are NULL\n");
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    switch (keybits) {
+    case 128:
+        ctx->keySizeId = KEY_SIZE_128_BIT;
+        break;
+    case 192:
+        ctx->keySizeId = KEY_SIZE_192_BIT;
+        break;
+    case 256:
+        ctx->keySizeId = KEY_SIZE_256_BIT;
+        break;
+    default:
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    /* update key information in the context */
+    ctx->cryptoKey = USER_KEY;
+
+    /* Copy user key to context */
+    CC_PalMemCopy(ctx->keyBuf, key, PSA_BITS_TO_BYTES(keybits));
+
+    return PSA_SUCCESS;
+}
+
+static psa_status_t cmac_setup(cc3xx_cipher_operation_t *cmac,
+                               const psa_key_attributes_t *attributes,
+                               const uint8_t *key_buffer,
+                               size_t key_buffer_size, psa_algorithm_t alg)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+    /* call psa cipher setup */
+    status = cc3xx_cipher_encrypt_setup(cmac, attributes, key_buffer,
+                                        key_buffer_size, alg);
+    if (status != PSA_SUCCESS) {
+        return status;
+    }
+
+    status = cmac_init(&(cmac->aes_ctx));
+    if (status != PSA_SUCCESS) {
+        CC_PAL_LOG_ERR(" 'cmac_init' failed with psa return code %d\n", status);
+        return status;
+    }
+
+    status = cmac_setkey(&(cmac->aes_ctx), key_buffer,
+                         psa_get_key_bits(attributes));
+    if (status != PSA_SUCCESS) {
+        CC_PAL_LOG_ERR(" 'cmac_setkey' failed with psa return code %d\n",
+                       status);
+        return status;
+    }
+    return PSA_SUCCESS;
+}
+
+static psa_status_t cmac_update(cc3xx_cipher_operation_t *cmac_ctx,
+                                const unsigned char *input, size_t ilen)
+{
+    drvError_t ret = 0;
+    unsigned int block_size;
+    size_t blocks_num;
+    size_t main_chunk_in_bytes = 0;
+    CCBuffInfo_t inBuffInfo;
+    CCBuffInfo_t outBuffInfo;
+    block_size = cmac_ctx->block_size;
+
+    if ((cmac_ctx->unprocessed_size > 0) &&
+        (ilen > (block_size - cmac_ctx->unprocessed_size))) {
+        CC_PalMemCopy(
+            &(cmac_ctx)->unprocessed_data[cmac_ctx->unprocessed_size],
+            input, block_size - cmac_ctx->unprocessed_size);
+
+        ret = SetDataBuffersInfo(
+            (const uint8_t *)&(cmac_ctx)->unprocessed_data, block_size,
+            &inBuffInfo, NULL, 0, &outBuffInfo);
+        if (ret != CC_OK) {
+            CC_PAL_LOG_ERR("illegal data buffers\n");
+            return PSA_ERROR_INVALID_ARGUMENT;
+        }
+
+        ret = ProcessAesDrv(&(cmac_ctx->aes_ctx), &inBuffInfo, &outBuffInfo,
+                            block_size);
+
+        if (ret != AES_DRV_OK) {
+            CC_PAL_LOG_ERR("ProcessAesDrv failed with return code %d\n", ret);
+            return PSA_ERROR_GENERIC_ERROR;
+        }
+
+        input += (block_size - cmac_ctx->unprocessed_size);
+        ilen -= (block_size - cmac_ctx->unprocessed_size);
+        cmac_ctx->unprocessed_size = 0;
+    }
+
+    /* blocks_num is the number of blocks including any final partial block */
+    blocks_num = (ilen + block_size - 1) / block_size;
+    if (1 < blocks_num) {
+        main_chunk_in_bytes = (blocks_num - 1) * block_size;
+
+        ret = SetDataBuffersInfo(input, main_chunk_in_bytes, &inBuffInfo, NULL,
+                                 0, &outBuffInfo);
+        if (ret != CC_OK) {
+            CC_PAL_LOG_ERR("illegal data buffers\n");
+            return PSA_ERROR_INVALID_ARGUMENT;
+        }
+
+        /* Process the input data, excluding any final partial or complete block
+         */
+        ret = ProcessAesDrv(&(cmac_ctx->aes_ctx), &inBuffInfo, &outBuffInfo,
+                            main_chunk_in_bytes);
+        if (ret != AES_DRV_OK) {
+            CC_PAL_LOG_ERR("ProcessAesDrv failed with return code %d\n", ret);
+            return PSA_ERROR_GENERIC_ERROR;
+        }
+
+        ilen -= main_chunk_in_bytes;
+        input += main_chunk_in_bytes;
+    }
+
+    /* If there is data left over that wasn't aligned to a block */
+    if (ilen > 0) {
+        CC_PalMemCopy(
+            &(cmac_ctx)->unprocessed_data[cmac_ctx->unprocessed_size],
+            input, ilen);
+        cmac_ctx->unprocessed_size += ilen;
+    }
+
+    return PSA_SUCCESS;
+}
+
+static psa_status_t cmac_finish(cc3xx_cipher_operation_t *cmac_ctx,
+                                unsigned char *output)
+{
+    drvError_t ret = 0;
+    CCBuffInfo_t inBuffInfo;
+    CCBuffInfo_t outBuffInfo;
+
+    if (cmac_ctx == NULL || output == NULL) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    ret = SetDataBuffersInfo((const uint8_t *)&(cmac_ctx)->unprocessed_data,
+                             cmac_ctx->unprocessed_size, &inBuffInfo, NULL,
+                             0, &outBuffInfo);
+    if (ret != CC_OK) {
+        CC_PAL_LOG_ERR("illegal data buffers\n");
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    ret = FinishAesDrv(&(cmac_ctx->aes_ctx), &inBuffInfo, &outBuffInfo,
+                       (uint32_t)(cmac_ctx)->unprocessed_size);
+
+    if (ret != AES_DRV_OK) {
+        CC_PAL_LOG_ERR("FinishAesDrv failed with return code 0x%x\n", ret);
+        return PSA_ERROR_GENERIC_ERROR;
+    }
+
+    CC_PalMemCopy(output, cmac_ctx->aes_ctx.ivBuf, AES_IV_SIZE);
+
+    CC_PalMemSetZero(cmac_ctx, sizeof(cc3xx_cipher_operation_t));
+
+    return PSA_SUCCESS;
+}
+
+static psa_status_t hmac_setup(cc3xx_mac_operation_t *operation,
+                               const uint8_t *key_buffer,
+                               size_t key_buffer_size, psa_algorithm_t hash_alg)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    uint8_t ipad[PSA_HMAC_MAX_HASH_BLOCK_SIZE];
+    size_t i;
+    size_t hash_size  = PSA_HASH_LENGTH(hash_alg);
+    size_t block_size = psa_get_hash_block_size(hash_alg);
+    cc3xx_hash_operation_t *hmac = &(operation->hmac);
+
+    switch (hash_alg) {
+#if defined MBEDTLS_SHA1_C
+    case PSA_ALG_SHA_1:
+        hmac->mode = HASH_SHA1;
+        break;
+#endif
+#if defined MBEDTLS_SHA256_C
+    case PSA_ALG_SHA_224:
+        hmac->mode = HASH_SHA224;
+        break;
+    case PSA_ALG_SHA_256:
+        hmac->mode = HASH_SHA256;
+        break;
+#endif
+    default:
+        return PSA_ERROR_NOT_SUPPORTED;
+    }
+
+    if (block_size > sizeof(ipad)) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+    if (block_size > sizeof(operation->opad)) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+    if (block_size < hash_size) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    if (key_buffer_size > block_size) {
+        status = cc3xx_hash_compute(hash_alg, key_buffer, key_buffer_size, ipad,
+                                    sizeof(ipad), &key_buffer_size);
+        if (status != PSA_SUCCESS) {
+            goto cleanup;
+        }
+    } else if (key_buffer_size != 0) {
+        CC_PalMemCopy(ipad, key_buffer, key_buffer_size);
+    }
+
+    for (i = 0; i < key_buffer_size; i++) {
+        ipad[i] ^= 0x36;
+    }
+    CC_PalMemSet(ipad + key_buffer_size, 0x36, block_size - key_buffer_size);
+
+    for (i = 0; i < key_buffer_size; i++) {
+        operation->opad[i] = ipad[i] ^ 0x36 ^ 0x5C;
+    }
+    CC_PalMemSet(operation->opad + key_buffer_size, 0x5C,
+                 block_size - key_buffer_size);
+
+    status = cc3xx_hash_setup(hmac, hash_alg);
+    if (status != PSA_SUCCESS) {
+        goto cleanup;
+    }
+
+    status = cc3xx_hash_update(hmac, ipad, block_size);
+
+cleanup:
+    CC_PalMemSetZero(ipad, sizeof(ipad));
+
+    return status;
+}
+
+static psa_status_t hmac_finish(cc3xx_mac_operation_t *operation, uint8_t *mac,
+                                size_t mac_size)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    uint8_t tmp[MD_MAX_SIZE];
+    cc3xx_hash_operation_t *hmac = &(operation->hmac);
+    psa_algorithm_t hash_alg;
+    size_t hash_size  = 0;
+    size_t block_size;
+
+    switch (hmac->mode) {
+    case HASH_SHA1:
+        hash_alg = PSA_ALG_SHA_1;
+        break;
+    case HASH_SHA224:
+        hash_alg = PSA_ALG_SHA_224;
+        break;
+    case HASH_SHA256:
+        hash_alg = PSA_ALG_SHA_256;
+        break;
+    default:
+        return PSA_ERROR_BAD_STATE;
+    }
+
+    block_size = psa_get_hash_block_size(hash_alg);
+
+    status = cc3xx_hash_finish(hmac, tmp, sizeof(tmp), &hash_size);
+    if (status != PSA_SUCCESS) {
+        return status;
+    }
+
+    status = cc3xx_hash_setup(hmac, hash_alg);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    status = cc3xx_hash_update(hmac, operation->opad, block_size);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    status = cc3xx_hash_update(hmac, tmp, hash_size);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    status = cc3xx_hash_finish(hmac, tmp, sizeof(tmp), &hash_size);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    CC_PalMemCopy(mac, tmp, mac_size);
+
+exit:
+    CC_PalMemSetZero(tmp, hash_size);
+    return status;
+}
+
+static psa_status_t mac_setup(cc3xx_mac_operation_t *operation,
+                              const psa_key_attributes_t *attributes,
+                              const uint8_t *key_buffer, size_t key_buffer_size,
+                              psa_algorithm_t alg)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    if (operation->alg != 0) {
+        return PSA_ERROR_BAD_STATE;
+    }
+
+    CC_PalMemSetZero(operation, sizeof(cc3xx_mac_operation_t));
+    if (PSA_ALG_FULL_LENGTH_MAC(alg) == PSA_ALG_CMAC) {
+        status = cmac_setup(&(operation->cmac), attributes, key_buffer,
+                            key_buffer_size, alg);
+    } else if (PSA_ALG_IS_HMAC(alg)) {
+        status = hmac_setup(operation, key_buffer, key_buffer_size,
+                            PSA_ALG_HMAC_GET_HASH(alg));
+    } else {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    if (status != PSA_SUCCESS) {
+        CC_PalMemSetZero(operation, sizeof(cc3xx_mac_operation_t));
+    } else {
+        operation->alg = alg;
+    }
+    return status;
+}
+
+/*!@}*/
+
+psa_status_t cc3xx_mac_sign_setup(cc3xx_mac_operation_t *operation,
+                                  const psa_key_attributes_t *attributes,
+                                  const uint8_t *key_buffer,
+                                  size_t key_buffer_size, psa_algorithm_t alg)
+{
+    return mac_setup(operation, attributes, key_buffer, key_buffer_size, alg);
+}
+
+psa_status_t cc3xx_mac_verify_setup(cc3xx_mac_operation_t *operation,
+                                    const psa_key_attributes_t *attributes,
+                                    const uint8_t *key_buffer,
+                                    size_t key_buffer_size, psa_algorithm_t alg)
+{
+    return mac_setup(operation, attributes, key_buffer, key_buffer_size, alg);
+}
+
+psa_status_t cc3xx_mac_update(cc3xx_mac_operation_t *operation,
+                              const uint8_t *input, size_t input_length)
+{
+    if (operation == NULL || input == NULL) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+    if (PSA_ALG_FULL_LENGTH_MAC(operation->alg) == PSA_ALG_CMAC) {
+        return cmac_update(&(operation->cmac), input, input_length);
+    } else if (PSA_ALG_IS_HMAC(operation->alg)) {
+        return cc3xx_hash_update(&(operation->hmac), input, input_length);
+    } else {
+        return PSA_ERROR_BAD_STATE;
+    }
+}
+
+psa_status_t cc3xx_mac_sign_finish(cc3xx_mac_operation_t *operation,
+                                   uint8_t *mac, size_t mac_size,
+                                   size_t *mac_length)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+    if (PSA_ALG_FULL_LENGTH_MAC(operation->alg) == PSA_ALG_CMAC) {
+        status = cmac_finish(&(operation->cmac), mac);
+    } else if (PSA_ALG_IS_HMAC(operation->alg)) {
+        status = hmac_finish(operation, mac, mac_size);
+    } else {
+        return PSA_ERROR_BAD_STATE;
+    }
+
+    if (status != PSA_SUCCESS) {
+        CC_PalMemSetZero(mac, *mac_length);
+        return status;
+    } else {
+        *mac_length = mac_size;
+    }
+    return PSA_SUCCESS;
+}
+
+psa_status_t cc3xx_mac_verify_finish(cc3xx_mac_operation_t *operation,
+                                     const uint8_t *mac, size_t mac_length)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    uint8_t actual_mac[PSA_MAC_MAX_SIZE];
+
+    if (mac_length > sizeof(actual_mac)) {
+        return (PSA_ERROR_INVALID_ARGUMENT);
+    }
+    if (PSA_ALG_FULL_LENGTH_MAC(operation->alg) == PSA_ALG_CMAC) {
+        status = cmac_finish(&(operation->cmac), actual_mac);
+    } else if (PSA_ALG_IS_HMAC(operation->alg)) {
+        status = hmac_finish(operation, actual_mac, mac_length);
+    }
+    if (status != PSA_SUCCESS) {
+        goto cleanup;
+    }
+
+    if (CC_PalMemCmp(mac, actual_mac, mac_length)) {
+        status = PSA_ERROR_INVALID_SIGNATURE;
+    }
+
+cleanup:
+    CC_PalMemSetZero(actual_mac, sizeof(actual_mac));
+    return status;
+}
+
+psa_status_t cc3xx_mac_abort(cc3xx_mac_operation_t *operation)
+{
+    /* if alg is not set the operation has not been setup yet, nothing to do */
+    if (operation->alg == 0) {
+        return PSA_SUCCESS;
+    }
+    CC_PalMemSetZero(operation, sizeof(cc3xx_mac_operation_t));
+    return PSA_SUCCESS;
+}
+
+psa_status_t cc3xx_mac_compute(const psa_key_attributes_t *attributes,
+                               const uint8_t *key_buffer,
+                               size_t key_buffer_size, psa_algorithm_t alg,
+                               const uint8_t *input, size_t input_length,
+                               uint8_t *mac, size_t mac_size,
+                               size_t *mac_length)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    cc3xx_mac_operation_t operation = {0};
+
+    status = cc3xx_mac_sign_setup(&operation, attributes, key_buffer,
+                                  key_buffer_size, alg);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    if (input_length > 0) {
+        status = cc3xx_mac_update(&operation, input, input_length);
+    }
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    status = cc3xx_mac_sign_finish(&operation, mac, mac_size, mac_length);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+exit:
+    cc3xx_mac_abort(&operation);
+    return status;
+}
diff --git a/secure_fw/partitions/crypto/tfm_crypto_secure_api.c b/secure_fw/partitions/crypto/tfm_crypto_secure_api.c
index 1d90e92..b0e27ff 100644
--- a/secure_fw/partitions/crypto/tfm_crypto_secure_api.c
+++ b/secure_fw/partitions/crypto/tfm_crypto_secure_api.c
@@ -1067,10 +1067,7 @@
     status = API_DISPATCH(tfm_crypto_sign_message,
                           TFM_CRYPTO_SIGN_MESSAGE);
 
-    if (status == PSA_SUCCESS) {
-        *signature_length = out_vec[0].len;
-    }
-
+    *signature_length = out_vec[0].len;
     return status;
 #endif /* TFM_CRYPTO_ASYM_SIGN_MODULE_DISABLED */
 }
@@ -1555,10 +1552,7 @@
     status = API_DISPATCH(tfm_crypto_mac_compute,
                           TFM_CRYPTO_MAC_COMPUTE);
 
-    if (status == PSA_SUCCESS) {
-        *mac_length = out_vec[0].len;
-    }
-
+    *mac_length = out_vec[0].len;
     return status;
 #endif /* TFM_CRYPTO_MAC_MODULE_DISABLED */
 }
@@ -1622,10 +1616,7 @@
     status = API_DISPATCH(tfm_crypto_cipher_encrypt,
                           TFM_CRYPTO_CIPHER_ENCRYPT);
 
-    if (status == PSA_SUCCESS) {
-        *output_length = out_vec[0].len;
-    }
-
+    *output_length = out_vec[0].len;
     return status;
 #endif /* TFM_CRYPTO_CIPHER_MODULE_DISABLED */
 }
@@ -1659,10 +1650,7 @@
     status = API_DISPATCH(tfm_crypto_cipher_decrypt,
                           TFM_CRYPTO_CIPHER_DECRYPT);
 
-    if (status == PSA_SUCCESS) {
-        *output_length = out_vec[0].len;
-    }
-
+    *output_length = out_vec[0].len;
     return status;
 #endif /* TFM_CRYPTO_CIPHER_MODULE_DISABLED */
 }