Merge changes from topic "stm32mp1-trusted-boot" into integration

* changes:
  docs(st): update documentation for TRUSTED_BOARD_BOOT
  fix(build): ensure that the correct rule is called for tools
  feat(stm32mp1): add the platform specific build for tools
  fix(stm32mp13-fdts): remove secure status
  feat(stm32mp1-fdts): add CoT and fuse references for authentication
  feat(stm32mp1): add a check on TRUSTED_BOARD_BOOT with secure chip
  feat(stm32mp1): add the decryption support
  feat(stm32mp1): add the TRUSTED_BOARD_BOOT support
  feat(stm32mp1): update ROM code API for header v2 management
  feat(stm32mp1): remove unused function from boot API
  refactor(stm32mp1): remove authentication using STM32 image mode
  fix(fconf): fix type error displaying disable_auth
  feat(tbbr): increase PK_DER_LEN size
  fix(auth): correct sign-compare warning
  feat(auth): allow to verify PublicKey with platform format PK
  feat(cert-create): update for ECDSA brainpoolP256r/t1 support
  feat(stm32mp1): add RNG initialization in BL2 for STM32MP13
  feat(st-crypto): remove BL32 HASH driver usage
  feat(stm32mp1): add a stm32mp crypto library
  feat(st-crypto): add STM32 RNG driver
  feat(st-crypto): add AES decrypt/auth by SAES IP
  feat(st-crypto): add ECDSA signature check with PKA
  feat(st-crypto): update HASH for new hardware version used in STM32MP13
diff --git a/Makefile b/Makefile
index c1c709d..4f5ec5d 100644
--- a/Makefile
+++ b/Makefile
@@ -1470,7 +1470,7 @@
 certtool: ${CRTTOOL}
 
 ${CRTTOOL}: FORCE
-	${Q}${MAKE} PLAT=${PLAT} USE_TBBR_DEFS=${USE_TBBR_DEFS} COT=${COT} OPENSSL_DIR=${OPENSSL_DIR} CRTTOOL=${CRTTOOL} DEBUG=${DEBUG} V=${V} --no-print-directory -C ${CRTTOOLPATH}
+	${Q}${MAKE} PLAT=${PLAT} USE_TBBR_DEFS=${USE_TBBR_DEFS} COT=${COT} OPENSSL_DIR=${OPENSSL_DIR} CRTTOOL=${CRTTOOL} DEBUG=${DEBUG} V=${V} --no-print-directory -C ${CRTTOOLPATH} all
 	@${ECHO_BLANK_LINE}
 	@echo "Built $@ successfully"
 	@${ECHO_BLANK_LINE}
@@ -1515,7 +1515,7 @@
 
 ${FIPTOOL}: FORCE
 ifdef UNIX_MK
-	${Q}${MAKE} CPPFLAGS="-DVERSION='\"${VERSION_STRING}\"'" FIPTOOL=${FIPTOOL} OPENSSL_DIR=${OPENSSL_DIR} DEBUG=${DEBUG} V=${V} --no-print-directory -C ${FIPTOOLPATH}
+	${Q}${MAKE} CPPFLAGS="-DVERSION='\"${VERSION_STRING}\"'" FIPTOOL=${FIPTOOL} OPENSSL_DIR=${OPENSSL_DIR} DEBUG=${DEBUG} V=${V} --no-print-directory -C ${FIPTOOLPATH} all
 else
 # Clear the MAKEFLAGS as we do not want
 # to pass the gnumake flags to nmake.
@@ -1536,7 +1536,7 @@
 enctool: ${ENCTOOL}
 
 ${ENCTOOL}: FORCE
-	${Q}${MAKE} PLAT=${PLAT} BUILD_INFO=0 OPENSSL_DIR=${OPENSSL_DIR} ENCTOOL=${ENCTOOL} DEBUG=${DEBUG} V=${V} --no-print-directory -C ${ENCTOOLPATH}
+	${Q}${MAKE} PLAT=${PLAT} BUILD_INFO=0 OPENSSL_DIR=${OPENSSL_DIR} ENCTOOL=${ENCTOOL} DEBUG=${DEBUG} V=${V} --no-print-directory -C ${ENCTOOLPATH} all
 	@${ECHO_BLANK_LINE}
 	@echo "Built $@ successfully"
 	@${ECHO_BLANK_LINE}
diff --git a/docs/about/release-information.rst b/docs/about/release-information.rst
index c0875b6..6c05aec 100644
--- a/docs/about/release-information.rst
+++ b/docs/about/release-information.rst
@@ -67,6 +67,11 @@
 +================================+=============+=========+=========================================================+
 | STM32MP_USE_STM32IMAGE macro   |   Dec '21   |   2.7   | FIP is the recommended boot method for STM32MP          |
 +--------------------------------+-------------+---------+---------------------------------------------------------+
+| plat_convert_pk() function     |   Nov'22    | Next    | Platform conversion to manage specific PK hash          |
+|                                |             | release |                                                         |
+|                                |             | after   |                                                         |
+|                                |             | 2.8     |                                                         |
++--------------------------------+-------------+---------+---------------------------------------------------------+
 
 --------------
 
diff --git a/docs/getting_started/build-options.rst b/docs/getting_started/build-options.rst
index 0b42a79..402de13 100644
--- a/docs/getting_started/build-options.rst
+++ b/docs/getting_started/build-options.rst
@@ -610,22 +610,28 @@
 
 -  ``KEY_ALG``: This build flag enables the user to select the algorithm to be
    used for generating the PKCS keys and subsequent signing of the certificate.
-   It accepts 3 values: ``rsa``, ``rsa_1_5`` and ``ecdsa``. The option
-   ``rsa_1_5`` is the legacy PKCS#1 RSA 1.5 algorithm which is not TBBR
-   compliant and is retained only for compatibility. The default value of this
-   flag is ``rsa`` which is the TBBR compliant PKCS#1 RSA 2.1 scheme.
+   It accepts 5 values: ``rsa``, ``rsa_1_5``, ``ecdsa``, ``ecdsa-brainpool-regular``
+   and ``ecdsa-brainpool-twisted``. The option ``rsa_1_5`` is the legacy PKCS#1
+   RSA 1.5 algorithm which is not TBBR compliant and is retained only for
+   compatibility. The default value of this flag is ``rsa`` which is the TBBR
+   compliant PKCS#1 RSA 2.1 scheme.
 
 -  ``KEY_SIZE``: This build flag enables the user to select the key size for
    the algorithm specified by ``KEY_ALG``. The valid values for ``KEY_SIZE``
    depend on the chosen algorithm and the cryptographic module.
 
-   +-----------+------------------------------------+
-   |  KEY_ALG  |        Possible key sizes          |
-   +===========+====================================+
-   |    rsa    | 1024 , 2048 (default), 3072, 4096* |
-   +-----------+------------------------------------+
-   |   ecdsa   |            unavailable             |
-   +-----------+------------------------------------+
+   +---------------------------+------------------------------------+
+   |         KEY_ALG           |        Possible key sizes          |
+   +===========================+====================================+
+   |           rsa             | 1024 , 2048 (default), 3072, 4096* |
+   +---------------------------+------------------------------------+
+   |          ecdsa            |            unavailable             |
+   +---------------------------+------------------------------------+
+   |  ecdsa-brainpool-regular  |            unavailable             |
+   +---------------------------+------------------------------------+
+   |  ecdsa-brainpool-twisted  |            unavailable             |
+   +---------------------------+------------------------------------+
+
 
    * Only 2048 bits size is available with CryptoCell 712 SBROM release 1.
      Only 3072 bits size is available with CryptoCell 712 SBROM release 2.
diff --git a/docs/getting_started/porting-guide.rst b/docs/getting_started/porting-guide.rst
index 9019e83..7f38054 100644
--- a/docs/getting_started/porting-guide.rst
+++ b/docs/getting_started/porting-guide.rst
@@ -809,6 +809,34 @@
 either could not be updated or the authentication image descriptor indicates
 that it is not allowed to be updated.
 
+Function: plat_convert_pk()
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+    Argument : void *, unsigned int, void **, unsigned int *
+    Return   : int
+
+This function is optional when Trusted Board Boot is enabled, and only
+used if the platform saves a hash of the ROTPK.
+First argument is the Distinguished Encoding Rules (DER) ROTPK.
+Second argument is its size.
+Third argument is used to return a pointer to a buffer, which hash should
+be the one saved in OTP.
+Fourth argument is a pointer to return its size.
+
+Most platforms save the hash of the ROTPK, but some may save slightly different
+information - e.g the hash of the ROTPK plus some related information.
+Defining this function allows to transform the ROTPK used to verify
+the signature to the buffer (a platform specific public key) which
+hash is saved in OTP.
+
+The default implementation copies the input key and length to the output without
+modification.
+
+The function returns 0 on success. Any other value means the expected
+public key buffer cannot be extracted.
+
 Dynamic Root of Trust for Measurement support (in BL31)
 -------------------------------------------------------
 
diff --git a/docs/plat/stm32mp1.rst b/docs/plat/stm32mp1.rst
index fff86a8..e3dea76 100644
--- a/docs/plat/stm32mp1.rst
+++ b/docs/plat/stm32mp1.rst
@@ -235,6 +235,40 @@
         BL32_EXTRA2=<optee_directory>/tee-pageable_v2.bin
         fip
 
+Trusted Boot Board
+__________________
+
+.. code:: shell
+
+    tools/cert_create/cert_create -n --rot-key "build/stm32mp1/debug/rot_key.pem" \
+        --tfw-nvctr 0 \
+        --ntfw-nvctr 0 \
+        --key-alg ecdsa --hash-alg sha256 \
+        --trusted-key-cert build/stm32mp1/cert_images/trusted-key-cert.key-crt \
+        --tos-fw <optee_directory>/tee-header_v2.bin \
+        --tos-fw-extra1 <optee_directory>/tee-pager_v2.bin \
+        --tos-fw-extra2 <optee_directory>/tee-pageable_v2.bin \
+        --tos-fw-cert build/stm32mp1/cert_images/tee-header_v2.bin.crt \
+        --tos-fw-key-cert build/stm32mp1/cert_images/tee-header_v2.bin.key-crt \
+        --nt-fw <u-boot_directory>/u-boot-nodtb.bin \
+        --nt-fw-cert build/stm32mp1/cert_images/u-boot.bin.crt \
+        --nt-fw-key-cert build/stm32mp1/cert_images/u-boot.bin.key-crt \
+        --hw-config <u-boot_directory>/u-boot.dtb \
+        --fw-config build/stm32mp1/debug/fdts/fw-config.dtb \
+        --stm32mp-cfg-cert build/stm32mp1/cert_images/stm32mp_cfg_cert.crt
+
+    tools/fiptool/fiptool create --tos-fw <optee_directory>/tee-header_v2.bin \
+        --tos-fw-extra1 <optee_directory>/tee-pager_v2.bin \
+        --tos-fw-extra2 <optee_directory>/tee-pageable_v2.bin \
+        --nt-fw <u-boot_directory>/u-boot-nodtb.bin \
+        --hw-config <u-boot_directory>/u-boot.dtb \
+        --fw-config build/stm32mp1/debug/fdts/fw-config.dtb \
+        --tos-fw-cert build/stm32mp1/cert_images/tee-header_v2.bin.crt \
+        --tos-fw-key-cert build/stm32mp1/cert_images/tee-header_v2.bin.key-crt \
+        --nt-fw-cert build/stm32mp1/cert_images/u-boot.bin.crt \
+        --nt-fw-key-cert build/stm32mp1/cert_images/u-boot.bin.key-crt \
+        --stm32mp-cfg-cert build/stm32mp1/cert_images/stm32mp_cfg_cert.crt stm32mp1.fip
+
 
 STM32IMAGE bootchain
 ~~~~~~~~~~~~~~~~~~~~
diff --git a/drivers/auth/auth_mod.c b/drivers/auth/auth_mod.c
index a99a2c7..fa9509a 100644
--- a/drivers/auth/auth_mod.c
+++ b/drivers/auth/auth_mod.c
@@ -31,6 +31,7 @@
 	} while (0)
 
 #pragma weak plat_set_nv_ctr2
+#pragma weak plat_convert_pk
 
 
 static int cmp_auth_param_type_desc(const auth_param_type_desc_t *a,
@@ -202,6 +203,10 @@
 			NOTICE("ROTPK is not deployed on platform. "
 				"Skipping ROTPK verification.\n");
 		} else {
+			/* platform may store the hash of a prefixed, suffixed or modified pk */
+			rc = plat_convert_pk(pk_ptr, pk_len, &pk_ptr, &pk_len);
+			return_if_error(rc);
+
 			/* Ask the crypto-module to verify the key hash */
 			rc = crypto_mod_verify_hash(pk_ptr, pk_len,
 				    pk_hash_ptr, pk_hash_len);
@@ -301,6 +306,15 @@
 	return plat_set_nv_ctr(cookie, nv_ctr);
 }
 
+int plat_convert_pk(void *full_pk_ptr, unsigned int full_pk_len,
+		    void **hashed_pk_ptr, unsigned int *hashed_pk_len)
+{
+	*hashed_pk_ptr = full_pk_ptr;
+	*hashed_pk_len = full_pk_len;
+
+	return 0;
+}
+
 /*
  * Return the parent id in the output parameter '*parent_id'
  *
diff --git a/drivers/auth/mbedtls/mbedtls_x509_parser.c b/drivers/auth/mbedtls/mbedtls_x509_parser.c
index 129566b..993ef12 100644
--- a/drivers/auth/mbedtls/mbedtls_x509_parser.c
+++ b/drivers/auth/mbedtls/mbedtls_x509_parser.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -114,10 +114,10 @@
 		oid_len = mbedtls_oid_get_numeric_string(oid_str,
 							 MAX_OID_STR_LEN,
 							 &extn_oid);
-		if (oid_len == MBEDTLS_ERR_OID_BUF_TOO_SMALL) {
+		if ((oid_len == MBEDTLS_ERR_OID_BUF_TOO_SMALL) || (oid_len < 0)) {
 			return IMG_PARSER_ERR;
 		}
-		if ((oid_len == strlen(oid_str)) && !strcmp(oid, oid_str)) {
+		if (((size_t)oid_len == strlen(oid_str)) && !strcmp(oid, oid_str)) {
 			*ext = (void *)p;
 			*ext_len = (unsigned int)len;
 			return IMG_PARSER_OK;
diff --git a/drivers/st/crypto/stm32_hash.c b/drivers/st/crypto/stm32_hash.c
index 6a1d476..e92f980 100644
--- a/drivers/st/crypto/stm32_hash.c
+++ b/drivers/st/crypto/stm32_hash.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019-2021, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2019-2022, STMicroelectronics - All Rights Reserved
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -8,10 +8,6 @@
 #include <errno.h>
 #include <stdint.h>
 
-#include <libfdt.h>
-
-#include <platform_def.h>
-
 #include <arch_helpers.h>
 #include <common/debug.h>
 #include <drivers/clk.h>
@@ -20,9 +16,17 @@
 #include <drivers/st/stm32mp_reset.h>
 #include <lib/mmio.h>
 #include <lib/utils.h>
+#include <libfdt.h>
 #include <plat/common/platform.h>
 
+#include <platform_def.h>
+
+#if STM32_HASH_VER == 2
 #define DT_HASH_COMPAT			"st,stm32f756-hash"
+#endif
+#if STM32_HASH_VER == 4
+#define DT_HASH_COMPAT			"st,stm32mp13-hash"
+#endif
 
 #define HASH_CR				0x00U
 #define HASH_DIN			0x04U
@@ -33,11 +37,22 @@
 /* Control Register */
 #define HASH_CR_INIT			BIT(2)
 #define HASH_CR_DATATYPE_SHIFT		U(4)
-
+#if STM32_HASH_VER == 2
 #define HASH_CR_ALGO_SHA1		0x0U
 #define HASH_CR_ALGO_MD5		BIT(7)
 #define HASH_CR_ALGO_SHA224		BIT(18)
 #define HASH_CR_ALGO_SHA256		(BIT(18) | BIT(7))
+#endif
+#if STM32_HASH_VER == 4
+#define HASH_CR_ALGO_SHIFT		U(17)
+#define HASH_CR_ALGO_SHA1		(0x0U << HASH_CR_ALGO_SHIFT)
+#define HASH_CR_ALGO_SHA224		(0x2U << HASH_CR_ALGO_SHIFT)
+#define HASH_CR_ALGO_SHA256		(0x3U << HASH_CR_ALGO_SHIFT)
+#define HASH_CR_ALGO_SHA384		(0xCU << HASH_CR_ALGO_SHIFT)
+#define HASH_CR_ALGO_SHA512_224		(0xDU << HASH_CR_ALGO_SHIFT)
+#define HASH_CR_ALGO_SHA512_256		(0xEU << HASH_CR_ALGO_SHIFT)
+#define HASH_CR_ALGO_SHA512		(0xFU << HASH_CR_ALGO_SHIFT)
+#endif
 
 /* Status Flags */
 #define HASH_SR_DCIS			BIT(1)
@@ -51,6 +66,10 @@
 #define SHA1_DIGEST_SIZE		20U
 #define SHA224_DIGEST_SIZE		28U
 #define SHA256_DIGEST_SIZE		32U
+#define SHA384_DIGEST_SIZE		48U
+#define SHA512_224_DIGEST_SIZE		28U
+#define SHA512_256_DIGEST_SIZE		32U
+#define SHA512_DIGEST_SIZE		64U
 
 #define RESET_TIMEOUT_US_1MS		1000U
 #define HASH_TIMEOUT_US			10000U
@@ -131,10 +150,12 @@
 	reg = HASH_CR_INIT | (HASH_DATA_8_BITS << HASH_CR_DATATYPE_SHIFT);
 
 	switch (mode) {
+#if STM32_HASH_VER == 2
 	case HASH_MD5SUM:
 		reg |= HASH_CR_ALGO_MD5;
 		stm32_hash.digest_size = MD5_DIGEST_SIZE;
 		break;
+#endif
 	case HASH_SHA1:
 		reg |= HASH_CR_ALGO_SHA1;
 		stm32_hash.digest_size = SHA1_DIGEST_SIZE;
@@ -143,6 +164,16 @@
 		reg |= HASH_CR_ALGO_SHA224;
 		stm32_hash.digest_size = SHA224_DIGEST_SIZE;
 		break;
+#if STM32_HASH_VER == 4
+	case HASH_SHA384:
+		reg |= HASH_CR_ALGO_SHA384;
+		stm32_hash.digest_size = SHA384_DIGEST_SIZE;
+		break;
+	case HASH_SHA512:
+		reg |= HASH_CR_ALGO_SHA512;
+		stm32_hash.digest_size = SHA512_DIGEST_SIZE;
+		break;
+#endif
 	/* Default selected algo is SHA256 */
 	case HASH_SHA256:
 	default:
@@ -171,13 +202,12 @@
 		memcpy(digest + (i * sizeof(uint32_t)), &dsg, sizeof(uint32_t));
 	}
 
-#if defined(IMAGE_BL2)
 	/*
 	 * Clean hardware context as HASH could be used later
 	 * by non-secure software
 	 */
 	hash_hw_init(HASH_SHA256);
-#endif
+
 	return 0;
 }
 
@@ -298,17 +328,9 @@
 	for (node = dt_get_node(&hash_info, -1, DT_HASH_COMPAT);
 	     node != -FDT_ERR_NOTFOUND;
 	     node = dt_get_node(&hash_info, node, DT_HASH_COMPAT)) {
-#if defined(IMAGE_BL2)
 		if (hash_info.status != DT_DISABLED) {
 			break;
 		}
-#else
-		/* BL32 uses hash if it is assigned only to secure world */
-		if (hash_info.status == DT_SECURE) {
-			stm32mp_register_secure_periph_iomem(hash_info.base);
-			break;
-		}
-#endif
 	}
 
 	if (node == -FDT_ERR_NOTFOUND) {
diff --git a/drivers/st/crypto/stm32_pka.c b/drivers/st/crypto/stm32_pka.c
new file mode 100644
index 0000000..e03cf0f
--- /dev/null
+++ b/drivers/st/crypto/stm32_pka.c
@@ -0,0 +1,707 @@
+/*
+ * Copyright (c) 2022, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <stdint.h>
+
+#include <drivers/clk.h>
+#include <drivers/delay_timer.h>
+#include <drivers/st/stm32_pka.h>
+#include <drivers/st/stm32mp_reset.h>
+#include <lib/mmio.h>
+#include <lib/utils.h>
+#include <libfdt.h>
+#include <plat/common/platform.h>
+
+#include <platform_def.h>
+
+/*
+ * For our comprehension in this file
+ *  _len are in BITs
+ *  _size are in BYTEs
+ *  _nbw are in number of PKA_word (PKA_word = u64)
+ */
+
+#define UINT8_LEN			8U
+#define UINT64_LEN			(UINT8_LEN * sizeof(uint64_t))
+#define WORD_SIZE			(sizeof(uint64_t))
+#define OP_NBW_FROM_LEN(len)		(DIV_ROUND_UP_2EVAL((len), UINT64_LEN) + 1)
+#define OP_NBW_FROM_SIZE(s)		OP_NBW_FROM_LEN((s) * UINT8_LEN)
+#define OP_SIZE_FROM_SIZE(s)		(OP_NBW_FROM_SIZE(s) * WORD_SIZE)
+
+#define DT_PKA_COMPAT			"st,stm32-pka64"
+
+#define MAX_ECC_SIZE_LEN		640U
+#define MAX_EO_NBW			OP_NBW_FROM_LEN(MAX_ECC_SIZE_LEN)
+
+/* PKA registers */
+/* PKA control register */
+#define _PKA_CR				0x0U
+/* PKA status register */
+#define _PKA_SR				0x4U
+/* PKA clear flag register */
+#define _PKA_CLRFR			0x8U
+/* PKA version register */
+#define _PKA_VERR			0x1FF4U
+/* PKA identification register */
+#define _PKA_IPIDR			0x1FF8U
+
+/* PKA control register fields */
+#define _PKA_CR_MODE_MASK		GENMASK(13, 8)
+#define _PKA_CR_MODE_SHIFT		8U
+#define _PKA_CR_MODE_ADD		0x9U
+#define _PKA_CR_MODE_ECDSA_VERIF	0x26U
+#define _PKA_CR_START			BIT(1)
+#define _PKA_CR_EN			BIT(0)
+
+/* PKA status register fields */
+#define _PKA_SR_BUSY			BIT(16)
+#define _PKA_SR_LMF			BIT(1)
+#define _PKA_SR_INITOK			BIT(0)
+
+/* PKA it flag fields (used in CR, SR and CLRFR) */
+#define _PKA_IT_MASK			(GENMASK(21, 19) | BIT(17))
+#define _PKA_IT_SHIFT			17U
+#define _PKA_IT_OPERR			BIT(21)
+#define _PKA_IT_ADDRERR			BIT(20)
+#define _PKA_IT_RAMERR			BIT(19)
+#define _PKA_IT_PROCEND			BIT(17)
+
+/* PKA version register fields */
+#define _PKA_VERR_MAJREV_MASK		GENMASK(7, 4)
+#define _PKA_VERR_MAJREV_SHIFT		4U
+#define _PKA_VERR_MINREV_MASK		GENMASK(3, 0)
+#define _PKA_VERR_MINREV_SHIFT		0U
+
+/* RAM magic offset */
+#define _PKA_RAM_START			0x400U
+#define _PKA_RAM_SIZE			5336U
+
+/* ECDSA verification */
+#define _PKA_RAM_N_LEN			0x408U /* 64 */
+#define _PKA_RAM_P_LEN			0x4C8U /* 64 */
+#define _PKA_RAM_A_SIGN			0x468U /* 64 */
+#define _PKA_RAM_A			0x470U /* EOS */
+#define _PKA_RAM_P			0x4D0U /* EOS */
+#define _PKA_RAM_XG			0x678U /* EOS */
+#define _PKA_RAM_YG			0x6D0U /* EOS */
+#define _PKA_RAM_XQ			0x12F8U /* EOS */
+#define _PKA_RAM_YQ			0x1350U /* EOS */
+#define _PKA_RAM_SIGN_R			0x10E0U /* EOS */
+#define _PKA_RAM_SIGN_S			0xC68U /* EOS */
+#define _PKA_RAM_HASH_Z			0x13A8U /* EOS */
+#define _PKA_RAM_PRIME_N		0x1088U /* EOS */
+#define _PKA_RAM_ECDSA_VERIFY		0x5D0U /* 64 */
+#define _PKA_RAM_ECDSA_VERIFY_VALID	0xD60DULL
+#define _PKA_RAM_ECDSA_VERIFY_INVALID	0xA3B7ULL
+
+#define PKA_TIMEOUT_US			1000000U
+#define TIMEOUT_US_1MS			1000U
+#define PKA_RESET_DELAY			20U
+
+struct curve_parameters {
+	uint32_t a_sign;  /* 0 positive, 1 negative */
+	uint8_t *a;    /* Curve coefficient |a| */
+	size_t a_size;
+	uint8_t *p;    /* Curve modulus value */
+	uint32_t p_len;
+	uint8_t *xg;   /* Curve base point G coordinate x */
+	size_t xg_size;
+	uint8_t *yg;   /* Curve base point G coordinate y */
+	size_t yg_size;
+	uint8_t *n;    /* Curve prime order n */
+	uint32_t n_len;
+};
+
+static const struct curve_parameters curve_def[] = {
+#if PKA_USE_NIST_P256
+	[PKA_NIST_P256] = {
+		.p_len = 256U,
+		.n_len = 256U,
+		.p  = (uint8_t[]){0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01,
+				  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+				  0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
+				  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
+		.n  = (uint8_t[]){0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
+				  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+				  0xBC, 0xE6, 0xFA, 0xAD, 0xA7, 0x17, 0x9E, 0x84,
+				  0xF3, 0xB9, 0xCA, 0xC2, 0xFC, 0x63, 0x25, 0x51},
+		.a_sign = 1U,
+		.a = (uint8_t[]){0x03},
+		.a_size = 1U,
+		.xg = (uint8_t[]){0x6B, 0x17, 0xD1, 0xF2, 0xE1, 0x2C, 0x42, 0x47,
+				  0xF8, 0xBC, 0xE6, 0xE5, 0x63, 0xA4, 0x40, 0xF2,
+				  0x77, 0x03, 0x7D, 0x81, 0x2D, 0xEB, 0x33, 0xA0,
+				  0xF4, 0xA1, 0x39, 0x45, 0xD8, 0x98, 0xC2, 0x96},
+		.xg_size = 32U,
+		.yg = (uint8_t[]){0x4F, 0xE3, 0x42, 0xE2, 0xFE, 0x1A, 0x7F, 0x9B,
+				  0x8E, 0xE7, 0xEB, 0x4A, 0x7C, 0x0F, 0x9E, 0x16,
+				  0x2B, 0xCE, 0x33, 0x57, 0x6B, 0x31, 0x5E, 0xCE,
+				  0xCB, 0xB6, 0x40, 0x68, 0x37, 0xBF, 0x51, 0xF5},
+		.yg_size = 32U,
+	},
+#endif
+#if PKA_USE_BRAINPOOL_P256R1
+	[PKA_BRAINPOOL_P256R1] = {
+		.p_len = 256,
+		.n_len = 256,
+		.p  = (uint8_t[]){0xA9, 0xFB, 0x57, 0xDB, 0xA1, 0xEE, 0xA9, 0xBC,
+				  0x3E, 0x66, 0x0A, 0x90, 0x9D, 0x83, 0x8D, 0x72,
+				  0x6E, 0x3B, 0xF6, 0x23, 0xD5, 0x26, 0x20, 0x28,
+				  0x20, 0x13, 0x48, 0x1D, 0x1F, 0x6E, 0x53, 0x77},
+		.n  = (uint8_t[]){0xA9, 0xFB, 0x57, 0xDB, 0xA1, 0xEE, 0xA9, 0xBC,
+				  0x3E, 0x66, 0x0A, 0x90, 0x9D, 0x83, 0x8D, 0x71,
+				  0x8C, 0x39, 0x7A, 0xA3, 0xB5, 0x61, 0xA6, 0xF7,
+				  0x90, 0x1E, 0x0E, 0x82, 0x97, 0x48, 0x56, 0xA7},
+		.a  = (uint8_t[]){0x7D, 0x5A, 0x09, 0x75, 0xFC, 0x2C, 0x30, 0x57,
+				  0xEE, 0xF6, 0x75, 0x30, 0x41, 0x7A, 0xFF, 0xE7,
+				  0xFB, 0x80, 0x55, 0xC1, 0x26, 0xDC, 0x5C, 0x6C,
+				  0xE9, 0x4A, 0x4B, 0x44, 0xF3, 0x30, 0xB5, 0xD9},
+		.a_size = 32U,
+		.xg = (uint8_t[]){0x8B, 0xD2, 0xAE, 0xB9, 0xCB, 0x7E, 0x57, 0xCB,
+				  0x2C, 0x4B, 0x48, 0x2F, 0xFC, 0x81, 0xB7, 0xAF,
+				  0xB9, 0xDE, 0x27, 0xE1, 0xE3, 0xBD, 0x23, 0xC2,
+				  0x3A, 0x44, 0x53, 0xBD, 0x9A, 0xCE, 0x32, 0x62},
+		.xg_size = 32U,
+		.yg = (uint8_t[]){0x54, 0x7E, 0xF8, 0x35, 0xC3, 0xDA, 0xC4, 0xFD,
+				  0x97, 0xF8, 0x46, 0x1A, 0x14, 0x61, 0x1D, 0xC9,
+				  0xC2, 0x77, 0x45, 0x13, 0x2D, 0xED, 0x8E, 0x54,
+				  0x5C, 0x1D, 0x54, 0xC7, 0x2F, 0x04, 0x69, 0x97},
+		.yg_size = 32U,
+	},
+#endif
+#if PKA_USE_BRAINPOOL_P256T1
+	[PKA_BRAINPOOL_P256T1] = {
+		.p_len = 256,
+		.n_len = 256,
+		.p  = (uint8_t[]){0xA9, 0xFB, 0x57, 0xDB, 0xA1, 0xEE, 0xA9, 0xBC,
+				  0x3E, 0x66, 0x0A, 0x90, 0x9D, 0x83, 0x8D, 0x72,
+				  0x6E, 0x3B, 0xF6, 0x23, 0xD5, 0x26, 0x20, 0x28,
+				  0x20, 0x13, 0x48, 0x1D, 0x1F, 0x6E, 0x53, 0x77},
+		.n  = (uint8_t[]){0xA9, 0xFB, 0x57, 0xDB, 0xA1, 0xEE, 0xA9, 0xBC,
+				  0x3E, 0x66, 0x0A, 0x90, 0x9D, 0x83, 0x8D, 0x71,
+				  0x8C, 0x39, 0x7A, 0xA3, 0xB5, 0x61, 0xA6, 0xF7,
+				  0x90, 0x1E, 0x0E, 0x82, 0x97, 0x48, 0x56, 0xA7},
+		.a  = (uint8_t[]){0xA9, 0xFB, 0x57, 0xDB, 0xA1, 0xEE, 0xA9, 0xBC,
+				  0x3E, 0x66, 0x0A, 0x90, 0x9D, 0x83, 0x8D, 0x72,
+				  0x6E, 0x3B, 0xF6, 0x23, 0xD5, 0x26, 0x20, 0x28,
+				  0x20, 0x13, 0x48, 0x1D, 0x1F, 0x6E, 0x53, 0x74},
+		.a_size = 32U,
+		.xg = (uint8_t[]){0xA3, 0xE8, 0xEB, 0x3C, 0xC1, 0xCF, 0xE7, 0xB7,
+				  0x73, 0x22, 0x13, 0xB2, 0x3A, 0x65, 0x61, 0x49,
+				  0xAF, 0xA1, 0x42, 0xC4, 0x7A, 0xAF, 0xBC, 0x2B,
+				  0x79, 0xA1, 0x91, 0x56, 0x2E, 0x13, 0x05, 0xF4},
+		.xg_size = 32U,
+		.yg = (uint8_t[]){0x2D, 0x99, 0x6C, 0x82, 0x34, 0x39, 0xC5, 0x6D,
+				  0x7F, 0x7B, 0x22, 0xE1, 0x46, 0x44, 0x41, 0x7E,
+				  0x69, 0xBC, 0xB6, 0xDE, 0x39, 0xD0, 0x27, 0x00,
+				  0x1D, 0xAB, 0xE8, 0xF3, 0x5B, 0x25, 0xC9, 0xBE},
+		.yg_size = 32U,
+	},
+#endif
+#if PKA_USE_NIST_P521
+	[PKA_NIST_P521] = {
+		.p_len = 521,
+		.n_len = 521,
+		.p  = (uint8_t[]){                                    0x01, 0xff,
+				  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+				  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+				  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+				  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+				  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+				  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+				  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+				  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+		.n  = (uint8_t[]){                                    0x01, 0xff,
+				  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+				  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+				  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+				  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa,
+				  0x51, 0x86, 0x87, 0x83, 0xbf, 0x2f, 0x96, 0x6b,
+				  0x7f, 0xcc, 0x01, 0x48, 0xf7, 0x09, 0xa5, 0xd0,
+				  0x3b, 0xb5, 0xc9, 0xb8, 0x89, 0x9c, 0x47, 0xae,
+				  0xbb, 0x6f, 0xb7, 0x1e, 0x91, 0x38, 0x64, 0x09},
+		.a_sign = 1,
+		.a  = (uint8_t[]){0x03},
+		.a_size = 1U,
+		.xg = (uint8_t[]){                                          0xc6,
+				  0x85, 0x8e, 0x06, 0xb7, 0x04, 0x04, 0xe9, 0xcd,
+				  0x9e, 0x3e, 0xcb, 0x66, 0x23, 0x95, 0xb4, 0x42,
+				  0x9c, 0x64, 0x81, 0x39, 0x05, 0x3f, 0xb5, 0x21,
+				  0xf8, 0x28, 0xaf, 0x60, 0x6b, 0x4d, 0x3d, 0xba,
+				  0xa1, 0x4b, 0x5e, 0x77, 0xef, 0xe7, 0x59, 0x28,
+				  0xfe, 0x1d, 0xc1, 0x27, 0xa2, 0xff, 0xa8, 0xde,
+				  0x33, 0x48, 0xb3, 0xc1, 0x85, 0x6a, 0x42, 0x9b,
+				  0xf9, 0x7e, 0x7e, 0x31, 0xc2, 0xe5, 0xbd, 0x66},
+		.xg_size = 65U,
+		.yg = (uint8_t[]){                                    0x01, 0x18,
+				  0x39, 0x29, 0x6a, 0x78, 0x9a, 0x3b, 0xc0, 0x04,
+				  0x5c, 0x8a, 0x5f, 0xb4, 0x2c, 0x7d, 0x1b, 0xd9,
+				  0x98, 0xf5, 0x44, 0x49, 0x57, 0x9b, 0x44, 0x68,
+				  0x17, 0xaf, 0xbd, 0x17, 0x27, 0x3e, 0x66, 0x2c,
+				  0x97, 0xee, 0x72, 0x99, 0x5e, 0xf4, 0x26, 0x40,
+				  0xc5, 0x50, 0xb9, 0x01, 0x3f, 0xad, 0x07, 0x61,
+				  0x35, 0x3c, 0x70, 0x86, 0xa2, 0x72, 0xc2, 0x40,
+				  0x88, 0xbe, 0x94, 0x76, 0x9f, 0xd1, 0x66, 0x50},
+		.yg_size = 66U,
+	},
+#endif
+};
+
+static struct stm32_pka_platdata pka_pdata;
+
+#pragma weak stm32_pka_get_platdata
+
+int stm32_pka_get_platdata(struct stm32_pka_platdata *pdata)
+{
+	return -ENODEV;
+}
+
+static int stm32_pka_parse_fdt(void)
+{
+	int node;
+	struct dt_node_info info;
+	void *fdt;
+
+	if (fdt_get_address(&fdt) == 0) {
+		return -FDT_ERR_NOTFOUND;
+	}
+
+	node = dt_get_node(&info, -1, DT_PKA_COMPAT);
+	if (node < 0) {
+		ERROR("No PKA entry in DT\n");
+		return -FDT_ERR_NOTFOUND;
+	}
+
+	if (info.status == DT_DISABLED) {
+		return -FDT_ERR_NOTFOUND;
+	}
+
+	if ((info.base == 0) || (info.clock < 0) || (info.reset < 0)) {
+		return -FDT_ERR_BADVALUE;
+	}
+
+	pka_pdata.base = (uintptr_t)info.base;
+	pka_pdata.clock_id = (unsigned long)info.clock;
+	pka_pdata.reset_id = (unsigned int)info.reset;
+
+	return 0;
+}
+
+static int pka_wait_bit(uintptr_t base, uint32_t bit)
+{
+	uint64_t timeout = timeout_init_us(PKA_TIMEOUT_US);
+
+	while ((mmio_read_32(base + _PKA_SR) & bit) != bit) {
+		if (timeout_elapsed(timeout)) {
+			WARN("timeout waiting %x\n", bit);
+			return -ETIMEDOUT;
+		}
+	}
+
+	return 0;
+
+}
+
+static void pka_disable(uintptr_t base)
+{
+	mmio_clrbits_32(base + _PKA_CR, _PKA_CR_EN);
+}
+
+static int pka_enable(uintptr_t base, uint32_t mode)
+{
+	/* Set mode and disable interrupts */
+	mmio_clrsetbits_32(base + _PKA_CR, _PKA_IT_MASK | _PKA_CR_MODE_MASK,
+			   _PKA_CR_MODE_MASK & (mode << _PKA_CR_MODE_SHIFT));
+
+	mmio_setbits_32(base + _PKA_CR, _PKA_CR_EN);
+
+	return pka_wait_bit(base, _PKA_SR_INITOK);
+}
+
+/*
+ * Data are already loaded in PKA internal RAM
+ * MODE is set
+ * We start process, and wait for its end.
+ */
+static int stm32_pka_process(uintptr_t base)
+{
+	mmio_setbits_32(base + _PKA_CR, _PKA_CR_START);
+
+	return pka_wait_bit(base, _PKA_IT_PROCEND);
+}
+
+/**
+ * @brief Write ECC operand to PKA RAM.
+ * @note  PKA expect to write u64 word, each u64 are: the least significant bit is
+ *        bit 0; the most significant bit is bit 63.
+ *        We write eo_nbw (ECC operand Size) u64, value that depends of the chosen
+ *        prime modulus length in bits.
+ *        First less signicant u64 is written to low address
+ *        Most significant u64 to higher address.
+ *        And at last address we write a u64(0x0)
+ * @note  This function doesn't only manage endianness (as bswap64 do), but also
+ *        complete most significant incomplete u64 with 0 (if data is not a u64
+ *        multiple), and fill u64 last address with 0.
+ * @param addr: PKA_RAM address to write the buffer 'data'
+ * @param data: is a BYTE list with most significant bytes first
+ * @param data_size: nb of byte in data
+ * @param eo_nbw: is ECC Operand size in 64bits word (including the extra 0)
+ *                (note it depends of the prime modulus length, not the data size)
+ * @retval 0 if OK.
+ *         -EINVAL if data_size and eo_nbw are inconsistent, ie data doesn't
+ *         fit in defined eo_nbw, or eo_nbw bigger than hardware limit.
+ */
+static int write_eo_data(uintptr_t addr, uint8_t *data, unsigned int data_size,
+			 unsigned int eo_nbw)
+{
+	uint32_t word_index;
+	int data_index;
+
+	if ((eo_nbw < OP_NBW_FROM_SIZE(data_size)) || (eo_nbw > MAX_EO_NBW)) {
+		return -EINVAL;
+	}
+
+	/* Fill value */
+	data_index = (int)data_size - 1;
+	for (word_index = 0U; word_index < eo_nbw; word_index++) {
+		uint64_t tmp = 0ULL;
+		unsigned int i = 0U;  /* index in the tmp U64 word */
+
+		/* Stop if end of tmp or end of data */
+		while ((i < sizeof(tmp)) && (data_index >= 0)) {
+			tmp |= (uint64_t)(data[data_index]) << (UINT8_LEN * i);
+			i++; /* Move byte index in current (u64)tmp */
+			data_index--; /* Move to just next most significat byte */
+		}
+
+		mmio_write_64(addr + word_index * sizeof(tmp), tmp);
+	}
+
+	return 0;
+}
+
+static unsigned int get_ecc_op_nbword(enum stm32_pka_ecdsa_curve_id cid)
+{
+	if (cid >= ARRAY_SIZE(curve_def)) {
+		ERROR("CID %u is out of boundaries\n", cid);
+		panic();
+	}
+
+	return OP_NBW_FROM_LEN(curve_def[cid].n_len);
+}
+
+static int stm32_pka_ecdsa_verif_configure_curve(uintptr_t base, enum stm32_pka_ecdsa_curve_id cid)
+{
+	int ret;
+	unsigned int eo_nbw = get_ecc_op_nbword(cid);
+
+	mmio_write_64(base + _PKA_RAM_N_LEN, curve_def[cid].n_len);
+	mmio_write_64(base + _PKA_RAM_P_LEN, curve_def[cid].p_len);
+	mmio_write_64(base + _PKA_RAM_A_SIGN, curve_def[cid].a_sign);
+
+	ret = write_eo_data(base + _PKA_RAM_A, curve_def[cid].a, curve_def[cid].a_size, eo_nbw);
+	if (ret < 0) {
+		return ret;
+	}
+
+	ret = write_eo_data(base + _PKA_RAM_PRIME_N,
+			    curve_def[cid].n, div_round_up(curve_def[cid].n_len, UINT8_LEN),
+			    eo_nbw);
+	if (ret < 0) {
+		return ret;
+	}
+
+	ret = write_eo_data(base + _PKA_RAM_P, curve_def[cid].p,
+			    div_round_up(curve_def[cid].p_len, UINT8_LEN), eo_nbw);
+	if (ret < 0) {
+		return ret;
+	}
+
+	ret = write_eo_data(base + _PKA_RAM_XG, curve_def[cid].xg, curve_def[cid].xg_size, eo_nbw);
+	if (ret < 0) {
+		return ret;
+	}
+
+	ret = write_eo_data(base + _PKA_RAM_YG, curve_def[cid].yg, curve_def[cid].yg_size, eo_nbw);
+	if (ret < 0) {
+		return ret;
+	}
+
+	return 0;
+}
+
+static int stm32_pka_ecdsa_verif_check_return(uintptr_t base)
+{
+	uint64_t value;
+	uint32_t sr;
+
+	sr = mmio_read_32(base + _PKA_SR);
+	if ((sr & (_PKA_IT_OPERR | _PKA_IT_ADDRERR | _PKA_IT_RAMERR)) != 0) {
+		WARN("Detected error(s): %s%s%s\n",
+		     (sr & _PKA_IT_OPERR) ? "Operation " : "",
+		     (sr & _PKA_IT_ADDRERR) ? "Address " : "",
+		     (sr & _PKA_IT_RAMERR) ? "RAM" : "");
+		return -EINVAL;
+	}
+
+	value = mmio_read_64(base + _PKA_RAM_ECDSA_VERIFY);
+	if (value == _PKA_RAM_ECDSA_VERIFY_VALID) {
+		return 0;
+	}
+
+	if (value == _PKA_RAM_ECDSA_VERIFY_INVALID) {
+		return -EAUTH;
+	}
+
+	return -EINVAL;
+}
+
+/**
+ * @brief Check if BigInt stored in data is 0
+ *
+ * @param data: a BYTE array with most significant bytes first
+ * @param size: data size
+ *
+ * @retval: true: if data represents a 0 value (ie all bytes == 0)
+ *          false: if data represents a non-zero value.
+ */
+static bool is_zero(uint8_t *data, unsigned int size)
+{
+	unsigned int i;
+
+	for (i = 0U; i < size; i++) {
+		if (data[i] != 0U) {
+			return false;
+		}
+	}
+
+	return true;
+}
+
+/**
+ * @brief Compare two BigInt:
+ * @param xdata_a: a BYTE array with most significant bytes first
+ * @param size_a: nb of Byte of 'a'
+ * @param data_b: a BYTE array with most significant bytes first
+ * @param size_b: nb of Byte of 'b'
+ *
+ * @retval: true if data_a < data_b
+ *          false if data_a >= data_b
+ */
+static bool is_smaller(uint8_t *data_a, unsigned int size_a,
+		       uint8_t *data_b, unsigned int size_b)
+{
+	unsigned int i;
+
+	i = MAX(size_a, size_b) + 1U;
+	do {
+		uint8_t a, b;
+
+		i--;
+		if (size_a < i) {
+			a = 0U;
+		} else {
+			a = data_a[size_a - i];
+		}
+
+		if (size_b < i) {
+			b = 0U;
+		} else {
+			b = data_b[size_b - i];
+		}
+
+		if (a < b) {
+			return true;
+		}
+
+		if (a > b) {
+			return false;
+		}
+	} while (i != 0U);
+
+	return false;
+}
+
+static int stm32_pka_ecdsa_check_param(void *sig_r_ptr, unsigned int sig_r_size,
+				       void *sig_s_ptr, unsigned int sig_s_size,
+				       void *pk_x_ptr, unsigned int pk_x_size,
+				       void *pk_y_ptr, unsigned int pk_y_size,
+				       enum stm32_pka_ecdsa_curve_id cid)
+{
+	/* Public Key check */
+	/* Check Xq < p */
+	if (!is_smaller(pk_x_ptr, pk_x_size,
+			curve_def[cid].p, div_round_up(curve_def[cid].p_len, UINT8_LEN))) {
+		WARN("%s Xq < p inval\n", __func__);
+		return -EINVAL;
+	}
+
+	/* Check Yq < p */
+	if (!is_smaller(pk_y_ptr, pk_y_size,
+			curve_def[cid].p, div_round_up(curve_def[cid].p_len, UINT8_LEN))) {
+		WARN("%s Yq < p inval\n", __func__);
+		return -EINVAL;
+	}
+
+	/* Signature check */
+	/* Check 0 < r < n */
+	if (!is_smaller(sig_r_ptr, sig_r_size,
+			curve_def[cid].n, div_round_up(curve_def[cid].n_len, UINT8_LEN)) &&
+	    !is_zero(sig_r_ptr, sig_r_size)) {
+		WARN("%s 0< r < n inval\n", __func__);
+		return -EINVAL;
+	}
+
+	/* Check 0 < s < n */
+	if (!is_smaller(sig_s_ptr, sig_s_size,
+			curve_def[cid].n, div_round_up(curve_def[cid].n_len, UINT8_LEN)) &&
+	    !is_zero(sig_s_ptr, sig_s_size)) {
+		WARN("%s 0< s < n inval\n", __func__);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/*
+ * @brief  Initialize the PKA driver.
+ * @param  None.
+ * @retval 0 if OK, negative value else.
+ */
+int stm32_pka_init(void)
+{
+	int err;
+#if LOG_LEVEL >= LOG_LEVEL_VERBOSE
+	uint32_t ver;
+	uint32_t id;
+#endif
+
+	err = stm32_pka_parse_fdt();
+	if (err != 0) {
+		err = stm32_pka_get_platdata(&pka_pdata);
+		if (err != 0) {
+			return err;
+		}
+	}
+
+	clk_enable(pka_pdata.clock_id);
+
+	if (stm32mp_reset_assert((unsigned long)pka_pdata.reset_id, TIMEOUT_US_1MS) != 0) {
+		panic();
+	}
+
+	udelay(PKA_RESET_DELAY);
+	if (stm32mp_reset_deassert((unsigned long)pka_pdata.reset_id, TIMEOUT_US_1MS) != 0) {
+		panic();
+	}
+
+#if LOG_LEVEL >= LOG_LEVEL_VERBOSE
+	id = mmio_read_32(pka_pdata.base + _PKA_IPIDR);
+	ver = mmio_read_32(pka_pdata.base + _PKA_VERR);
+
+	VERBOSE("STM32 PKA[%x] V%u.%u\n", id,
+		(ver & _PKA_VERR_MAJREV_MASK) >> _PKA_VERR_MAJREV_SHIFT,
+		(ver & _PKA_VERR_MINREV_MASK) >> _PKA_VERR_MINREV_SHIFT);
+#endif
+	return 0;
+}
+
+int stm32_pka_ecdsa_verif(void *hash, unsigned int hash_size,
+			  void *sig_r_ptr, unsigned int sig_r_size,
+			  void *sig_s_ptr, unsigned int sig_s_size,
+			  void *pk_x_ptr, unsigned int pk_x_size,
+			  void *pk_y_ptr, unsigned int pk_y_size,
+			  enum stm32_pka_ecdsa_curve_id cid)
+{
+	int ret;
+	uintptr_t base = pka_pdata.base;
+	unsigned int eo_nbw = get_ecc_op_nbword(cid);
+
+	if ((hash == NULL) || (sig_r_ptr == NULL) || (sig_s_ptr == NULL) ||
+	    (pk_x_ptr == NULL) || (pk_y_ptr == NULL)) {
+		INFO("%s invalid input param\n", __func__);
+		return -EINVAL;
+	}
+
+	ret = stm32_pka_ecdsa_check_param(sig_r_ptr, sig_r_size,
+					  sig_s_ptr, sig_s_size,
+					  pk_x_ptr, pk_x_size,
+					  pk_y_ptr, pk_y_size,
+					  cid);
+	if (ret < 0) {
+		INFO("%s check param error %d\n", __func__, ret);
+		goto out;
+	}
+
+	if ((mmio_read_32(base + _PKA_SR) & _PKA_SR_BUSY) == _PKA_SR_BUSY) {
+		INFO("%s busy\n", __func__);
+		ret = -EBUSY;
+		goto out;
+	}
+
+	/* Fill PKA RAM */
+	/* With curve id values */
+	ret = stm32_pka_ecdsa_verif_configure_curve(base, cid);
+	if (ret < 0) {
+		goto out;
+	}
+
+	/* With pubkey */
+	ret = write_eo_data(base + _PKA_RAM_XQ, pk_x_ptr, pk_x_size, eo_nbw);
+	if (ret < 0) {
+		goto out;
+	}
+
+	ret = write_eo_data(base + _PKA_RAM_YQ, pk_y_ptr, pk_y_size, eo_nbw);
+	if (ret < 0) {
+		goto out;
+	}
+
+	/* With hash */
+	ret = write_eo_data(base + _PKA_RAM_HASH_Z, hash, hash_size, eo_nbw);
+	if (ret < 0) {
+		goto out;
+	}
+
+	/* With signature */
+	ret = write_eo_data(base + _PKA_RAM_SIGN_R, sig_r_ptr, sig_r_size, eo_nbw);
+	if (ret < 0) {
+		goto out;
+	}
+
+	ret = write_eo_data(base + _PKA_RAM_SIGN_S, sig_s_ptr, sig_s_size, eo_nbw);
+	if (ret < 0) {
+		goto out;
+	}
+
+	/* Set mode to ecdsa signature verification */
+	ret = pka_enable(base, _PKA_CR_MODE_ECDSA_VERIF);
+	if (ret < 0) {
+		WARN("%s set mode pka error %d\n", __func__, ret);
+		goto out;
+	}
+
+	/* Start processing and wait end */
+	ret = stm32_pka_process(base);
+	if (ret < 0) {
+		WARN("%s process error %d\n", __func__, ret);
+		goto out;
+	}
+
+	/* Check return status */
+	ret = stm32_pka_ecdsa_verif_check_return(base);
+
+	/* Unset end proc */
+	mmio_setbits_32(base + _PKA_CLRFR, _PKA_IT_PROCEND);
+
+out:
+	/* Disable PKA (will stop all pending proccess and reset RAM) */
+	pka_disable(base);
+
+	return ret;
+}
diff --git a/drivers/st/crypto/stm32_rng.c b/drivers/st/crypto/stm32_rng.c
new file mode 100644
index 0000000..a9dc43f
--- /dev/null
+++ b/drivers/st/crypto/stm32_rng.c
@@ -0,0 +1,269 @@
+/*
+ * Copyright (c) 2022, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <stdbool.h>
+
+#include <arch_helpers.h>
+#include <drivers/clk.h>
+#include <drivers/delay_timer.h>
+#include <drivers/st/stm32_rng.h>
+#include <drivers/st/stm32mp_reset.h>
+#include <lib/mmio.h>
+#include <libfdt.h>
+
+#include <platform_def.h>
+
+#if STM32_RNG_VER == 2
+#define DT_RNG_COMPAT		"st,stm32-rng"
+#endif
+#if STM32_RNG_VER == 4
+#define DT_RNG_COMPAT		"st,stm32mp13-rng"
+#endif
+#define RNG_CR			0x00U
+#define RNG_SR			0x04U
+#define RNG_DR			0x08U
+
+#define RNG_CR_RNGEN		BIT(2)
+#define RNG_CR_IE		BIT(3)
+#define RNG_CR_CED		BIT(5)
+#define RNG_CR_CLKDIV		GENMASK(19, 16)
+#define RNG_CR_CLKDIV_SHIFT	16U
+#define RNG_CR_CONDRST		BIT(30)
+
+#define RNG_SR_DRDY		BIT(0)
+#define RNG_SR_CECS		BIT(1)
+#define RNG_SR_SECS		BIT(2)
+#define RNG_SR_CEIS		BIT(5)
+#define RNG_SR_SEIS		BIT(6)
+
+#define RNG_TIMEOUT_US		100000U
+#define RNG_TIMEOUT_STEP_US	10U
+
+#define TIMEOUT_US_1MS		1000U
+
+#define RNG_NIST_CONFIG_A	0x00F40F00U
+#define RNG_NIST_CONFIG_B	0x01801000U
+#define RNG_NIST_CONFIG_C	0x00F00D00U
+#define RNG_NIST_CONFIG_MASK	GENMASK(25, 8)
+
+#define RNG_MAX_NOISE_CLK_FREQ	48000000U
+
+struct stm32_rng_instance {
+	uintptr_t base;
+	unsigned long clock;
+};
+
+static struct stm32_rng_instance stm32_rng;
+
+static void seed_error_recovery(void)
+{
+	uint8_t i __maybe_unused;
+
+	/* Recommended by the SoC reference manual */
+	mmio_clrbits_32(stm32_rng.base + RNG_SR, RNG_SR_SEIS);
+	dmbsy();
+
+#if STM32_RNG_VER == 2
+	/* No Auto-reset on version 2, need to clean FIFO */
+	for (i = 12U; i != 0U; i--) {
+		(void)mmio_read_32(stm32_rng.base + RNG_DR);
+	}
+
+	dmbsy();
+#endif
+
+	if ((mmio_read_32(stm32_rng.base + RNG_SR) & RNG_SR_SEIS) != 0U) {
+		ERROR("RNG noise\n");
+		panic();
+	}
+}
+
+static uint32_t stm32_rng_clock_freq_restrain(void)
+{
+	unsigned long clock_rate;
+	uint32_t clock_div = 0U;
+
+	clock_rate = clk_get_rate(stm32_rng.clock);
+
+	/*
+	 * Get the exponent to apply on the CLKDIV field in RNG_CR register
+	 * No need to handle the case when clock-div > 0xF as it is physically
+	 * impossible
+	 */
+	while ((clock_rate >> clock_div) > RNG_MAX_NOISE_CLK_FREQ) {
+		clock_div++;
+	}
+
+	VERBOSE("RNG clk rate : %lu\n", clk_get_rate(stm32_rng.clock) >> clock_div);
+
+	return clock_div;
+}
+
+static int stm32_rng_enable(void)
+{
+	uint32_t sr;
+	uint64_t timeout;
+	uint32_t clock_div __maybe_unused;
+
+#if STM32_RNG_VER == 2
+	mmio_write_32(stm32_rng.base + RNG_CR, RNG_CR_RNGEN | RNG_CR_CED);
+#endif
+#if STM32_RNG_VER == 4
+	/* Reset internal block and disable CED bit */
+	clock_div = stm32_rng_clock_freq_restrain();
+
+	/* Update configuration fields */
+	mmio_clrsetbits_32(stm32_rng.base + RNG_CR, RNG_NIST_CONFIG_MASK,
+			   RNG_NIST_CONFIG_A | RNG_CR_CONDRST | RNG_CR_CED);
+
+	mmio_clrsetbits_32(stm32_rng.base + RNG_CR, RNG_CR_CLKDIV,
+			   (clock_div << RNG_CR_CLKDIV_SHIFT));
+
+	mmio_clrsetbits_32(stm32_rng.base + RNG_CR, RNG_CR_CONDRST, RNG_CR_RNGEN);
+#endif
+	timeout = timeout_init_us(RNG_TIMEOUT_US);
+	sr = mmio_read_32(stm32_rng.base + RNG_SR);
+	while ((sr & RNG_SR_DRDY) == 0U) {
+		if (timeout_elapsed(timeout)) {
+			WARN("Timeout waiting\n");
+			return -ETIMEDOUT;
+		}
+
+		if ((sr & (RNG_SR_SECS | RNG_SR_SEIS)) != 0U) {
+			seed_error_recovery();
+			timeout = timeout_init_us(RNG_TIMEOUT_US);
+		}
+
+		udelay(RNG_TIMEOUT_STEP_US);
+		sr = mmio_read_32(stm32_rng.base + RNG_SR);
+	}
+
+	VERBOSE("Init RNG done\n");
+
+	return 0;
+}
+
+/*
+ * stm32_rng_read - Read a number of random bytes from RNG
+ * out: pointer to the output buffer
+ * size: number of bytes to be read
+ * Return 0 on success, non-0 on failure
+ */
+int stm32_rng_read(uint8_t *out, uint32_t size)
+{
+	uint8_t *buf = out;
+	size_t len = size;
+	int nb_tries;
+	uint32_t data32;
+	int rc = 0;
+	unsigned int count;
+
+	if (stm32_rng.base == 0U) {
+		return -EPERM;
+	}
+
+	while (len != 0U) {
+		nb_tries = RNG_TIMEOUT_US / RNG_TIMEOUT_STEP_US;
+		do {
+			uint32_t status = mmio_read_32(stm32_rng.base + RNG_SR);
+
+			if ((status & (RNG_SR_SECS | RNG_SR_SEIS)) != 0U) {
+				seed_error_recovery();
+			}
+
+			udelay(RNG_TIMEOUT_STEP_US);
+			nb_tries--;
+			if (nb_tries == 0) {
+				rc = -ETIMEDOUT;
+				goto bail;
+			}
+		} while ((mmio_read_32(stm32_rng.base + RNG_SR) &
+			  RNG_SR_DRDY) == 0U);
+
+		count = 4U;
+		while (len != 0U) {
+			data32 = mmio_read_32(stm32_rng.base + RNG_DR);
+			count--;
+
+			memcpy(buf, &data32, MIN(len, sizeof(uint32_t)));
+			buf += MIN(len, sizeof(uint32_t));
+			len -= MIN(len, sizeof(uint32_t));
+
+			if (count == 0U) {
+				break;
+			}
+		}
+	}
+
+bail:
+	if (rc != 0) {
+		memset(out, 0, buf - out);
+	}
+
+	return rc;
+}
+
+/*
+ * stm32_rng_init: Initialize rng from DT
+ * return 0 on success, negative value on failure
+ */
+int stm32_rng_init(void)
+{
+	void *fdt;
+	struct dt_node_info dt_rng;
+	int node;
+
+	if (stm32_rng.base != 0U) {
+		/* Driver is already initialized */
+		return 0;
+	}
+
+	if (fdt_get_address(&fdt) == 0) {
+		panic();
+	}
+
+	node = dt_get_node(&dt_rng, -1, DT_RNG_COMPAT);
+	if (node < 0) {
+		return 0;
+	}
+
+	if (dt_rng.status == DT_DISABLED) {
+		return 0;
+	}
+
+	assert(dt_rng.base != 0U);
+
+	stm32_rng.base = dt_rng.base;
+
+	if (dt_rng.clock < 0) {
+		panic();
+	}
+
+	stm32_rng.clock = (unsigned long)dt_rng.clock;
+	clk_enable(stm32_rng.clock);
+
+	if (dt_rng.reset >= 0) {
+		int ret;
+
+		ret = stm32mp_reset_assert((unsigned long)dt_rng.reset,
+					   TIMEOUT_US_1MS);
+		if (ret != 0) {
+			panic();
+		}
+
+		udelay(20);
+
+		ret = stm32mp_reset_deassert((unsigned long)dt_rng.reset,
+					     TIMEOUT_US_1MS);
+		if (ret != 0) {
+			panic();
+		}
+	}
+
+	return stm32_rng_enable();
+}
diff --git a/drivers/st/crypto/stm32_saes.c b/drivers/st/crypto/stm32_saes.c
new file mode 100644
index 0000000..02baf21
--- /dev/null
+++ b/drivers/st/crypto/stm32_saes.c
@@ -0,0 +1,913 @@
+/*
+ * Copyright (c) 2022, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <assert.h>
+#include <endian.h>
+#include <errno.h>
+#include <stdint.h>
+
+#include <drivers/clk.h>
+#include <drivers/delay_timer.h>
+#include <drivers/st/stm32_saes.h>
+#include <drivers/st/stm32mp_reset.h>
+#include <lib/mmio.h>
+#include <lib/utils_def.h>
+#include <libfdt.h>
+
+#include <platform_def.h>
+
+#define UINT8_BIT			8U
+#define AES_BLOCK_SIZE_BIT		128U
+#define AES_BLOCK_SIZE			(AES_BLOCK_SIZE_BIT / UINT8_BIT)
+
+#define AES_KEYSIZE_128			16U
+#define AES_KEYSIZE_256			32U
+#define AES_IVSIZE			16U
+
+/* SAES control register */
+#define _SAES_CR			0x0U
+/* SAES status register */
+#define _SAES_SR			0x04U
+/* SAES data input register */
+#define _SAES_DINR			0x08U
+/* SAES data output register */
+#define _SAES_DOUTR			0x0CU
+/* SAES key registers [0-3] */
+#define _SAES_KEYR0			0x10U
+#define _SAES_KEYR1			0x14U
+#define _SAES_KEYR2			0x18U
+#define _SAES_KEYR3			0x1CU
+/* SAES initialization vector registers [0-3] */
+#define _SAES_IVR0			0x20U
+#define _SAES_IVR1			0x24U
+#define _SAES_IVR2			0x28U
+#define _SAES_IVR3			0x2CU
+/* SAES key registers [4-7] */
+#define _SAES_KEYR4			0x30U
+#define _SAES_KEYR5			0x34U
+#define _SAES_KEYR6			0x38U
+#define _SAES_KEYR7			0x3CU
+/* SAES suspend registers [0-7] */
+#define _SAES_SUSPR0			0x40U
+#define _SAES_SUSPR1			0x44U
+#define _SAES_SUSPR2			0x48U
+#define _SAES_SUSPR3			0x4CU
+#define _SAES_SUSPR4			0x50U
+#define _SAES_SUSPR5			0x54U
+#define _SAES_SUSPR6			0x58U
+#define _SAES_SUSPR7			0x5CU
+/* SAES Interrupt Enable Register */
+#define _SAES_IER			0x300U
+/* SAES Interrupt Status Register */
+#define _SAES_ISR			0x304U
+/* SAES Interrupt Clear Register */
+#define _SAES_ICR			0x308U
+
+/* SAES control register fields */
+#define _SAES_CR_RESET_VALUE		0x0U
+#define _SAES_CR_IPRST			BIT(31)
+#define _SAES_CR_KEYSEL_MASK		GENMASK(30, 28)
+#define _SAES_CR_KEYSEL_SHIFT		28U
+#define _SAES_CR_KEYSEL_SOFT		0x0U
+#define _SAES_CR_KEYSEL_DHUK		0x1U
+#define _SAES_CR_KEYSEL_BHK		0x2U
+#define _SAES_CR_KEYSEL_BHU_XOR_BH_K	0x4U
+#define _SAES_CR_KEYSEL_TEST		0x7U
+#define _SAES_CR_KSHAREID_MASK		GENMASK(27, 26)
+#define _SAES_CR_KSHAREID_SHIFT		26U
+#define _SAES_CR_KSHAREID_CRYP		0x0U
+#define _SAES_CR_KEYMOD_MASK		GENMASK(25, 24)
+#define _SAES_CR_KEYMOD_SHIFT		24U
+#define _SAES_CR_KEYMOD_NORMAL		0x0U
+#define _SAES_CR_KEYMOD_WRAPPED		0x1U
+#define _SAES_CR_KEYMOD_SHARED		0x2U
+#define _SAES_CR_NPBLB_MASK		GENMASK(23, 20)
+#define _SAES_CR_NPBLB_SHIFT		20U
+#define _SAES_CR_KEYPROT		BIT(19)
+#define _SAES_CR_KEYSIZE		BIT(18)
+#define _SAES_CR_GCMPH_MASK		GENMASK(14, 13)
+#define _SAES_CR_GCMPH_SHIFT		13U
+#define _SAES_CR_GCMPH_INIT		0U
+#define _SAES_CR_GCMPH_HEADER		1U
+#define _SAES_CR_GCMPH_PAYLOAD		2U
+#define _SAES_CR_GCMPH_FINAL		3U
+#define _SAES_CR_DMAOUTEN		BIT(12)
+#define _SAES_CR_DMAINEN		BIT(11)
+#define _SAES_CR_CHMOD_MASK		(BIT(16) | GENMASK(6, 5))
+#define _SAES_CR_CHMOD_SHIFT		5U
+#define _SAES_CR_CHMOD_ECB		0x0U
+#define _SAES_CR_CHMOD_CBC		0x1U
+#define _SAES_CR_CHMOD_CTR		0x2U
+#define _SAES_CR_CHMOD_GCM		0x3U
+#define _SAES_CR_CHMOD_GMAC		0x3U
+#define _SAES_CR_CHMOD_CCM		0x800U
+#define _SAES_CR_MODE_MASK		GENMASK(4, 3)
+#define _SAES_CR_MODE_SHIFT		3U
+#define _SAES_CR_MODE_ENC		0U
+#define _SAES_CR_MODE_KEYPREP		1U
+#define _SAES_CR_MODE_DEC		2U
+#define _SAES_CR_DATATYPE_MASK		GENMASK(2, 1)
+#define _SAES_CR_DATATYPE_SHIFT		1U
+#define _SAES_CR_DATATYPE_NONE		0U
+#define _SAES_CR_DATATYPE_HALF_WORD	1U
+#define _SAES_CR_DATATYPE_BYTE		2U
+#define _SAES_CR_DATATYPE_BIT		3U
+#define _SAES_CR_EN			BIT(0)
+
+/* SAES status register fields */
+#define _SAES_SR_KEYVALID		BIT(7)
+#define _SAES_SR_BUSY			BIT(3)
+#define _SAES_SR_WRERR			BIT(2)
+#define _SAES_SR_RDERR			BIT(1)
+#define _SAES_SR_CCF			BIT(0)
+
+/* SAES interrupt registers fields */
+#define _SAES_I_RNG_ERR			BIT(3)
+#define _SAES_I_KEY_ERR			BIT(2)
+#define _SAES_I_RW_ERR			BIT(1)
+#define _SAES_I_CC			BIT(0)
+
+#define SAES_TIMEOUT_US			100000U
+#define TIMEOUT_US_1MS			1000U
+#define SAES_RESET_DELAY		20U
+
+#define IS_CHAINING_MODE(mod, cr) \
+	(((cr) & _SAES_CR_CHMOD_MASK) == (_SAES_CR_CHMOD_##mod << _SAES_CR_CHMOD_SHIFT))
+
+#define SET_CHAINING_MODE(mod, cr) \
+	mmio_clrsetbits_32((cr), _SAES_CR_CHMOD_MASK, _SAES_CR_CHMOD_##mod << _SAES_CR_CHMOD_SHIFT)
+
+#define pragma weak stm32_saes_get_platdata
+
+static struct stm32_saes_platdata saes_pdata;
+
+int stm32_saes_get_platdata(struct stm32_saes_platdata *pdata)
+{
+	return -ENODEV;
+}
+
+static int stm32_saes_parse_fdt(struct stm32_saes_platdata *pdata)
+{
+	int node;
+	struct dt_node_info info;
+	void *fdt;
+
+	if (fdt_get_address(&fdt) == 0) {
+		return -FDT_ERR_NOTFOUND;
+	}
+
+	node = dt_get_node(&info, -1, DT_SAES_COMPAT);
+	if (node < 0) {
+		ERROR("No SAES entry in DT\n");
+		return -FDT_ERR_NOTFOUND;
+	}
+
+	if (info.status == DT_DISABLED) {
+		return -FDT_ERR_NOTFOUND;
+	}
+
+	if ((info.base == 0U) || (info.clock < 0) || (info.reset < 0)) {
+		return -FDT_ERR_BADVALUE;
+	}
+
+	pdata->base = (uintptr_t)info.base;
+	pdata->clock_id = (unsigned long)info.clock;
+	pdata->reset_id = (unsigned int)info.reset;
+
+	return 0;
+}
+
+static bool does_chaining_mode_need_iv(uint32_t cr)
+{
+	return !(IS_CHAINING_MODE(ECB, cr));
+}
+
+static bool is_encrypt(uint32_t cr)
+{
+	return (cr & _SAES_CR_MODE_MASK) == (_SAES_CR_MODE_ENC << _SAES_CR_MODE_SHIFT);
+}
+
+static bool is_decrypt(uint32_t cr)
+{
+	return (cr & _SAES_CR_MODE_MASK) == (_SAES_CR_MODE_DEC << _SAES_CR_MODE_SHIFT);
+}
+
+static int wait_computation_completed(uintptr_t base)
+{
+	uint64_t timeout = timeout_init_us(SAES_TIMEOUT_US);
+
+	while ((mmio_read_32(base + _SAES_SR) & _SAES_SR_CCF) != _SAES_SR_CCF) {
+		if (timeout_elapsed(timeout)) {
+			WARN("%s: timeout\n", __func__);
+			return -ETIMEDOUT;
+		}
+	}
+
+	return 0;
+}
+
+static void clear_computation_completed(uintptr_t base)
+{
+	mmio_setbits_32(base + _SAES_ICR, _SAES_I_CC);
+}
+
+static int saes_start(struct stm32_saes_context *ctx)
+{
+	uint64_t timeout;
+
+	/* Reset IP */
+	mmio_setbits_32(ctx->base + _SAES_CR, _SAES_CR_IPRST);
+	udelay(SAES_RESET_DELAY);
+	mmio_clrbits_32(ctx->base + _SAES_CR, _SAES_CR_IPRST);
+
+	timeout = timeout_init_us(SAES_TIMEOUT_US);
+	while ((mmio_read_32(ctx->base + _SAES_SR) & _SAES_SR_BUSY) == _SAES_SR_BUSY) {
+		if (timeout_elapsed(timeout)) {
+			WARN("%s: timeout\n", __func__);
+			return -ETIMEDOUT;
+		}
+	}
+
+	return 0;
+}
+
+static void saes_end(struct stm32_saes_context *ctx, int prev_error)
+{
+	if (prev_error != 0) {
+		/* Reset IP */
+		mmio_setbits_32(ctx->base + _SAES_CR, _SAES_CR_IPRST);
+		udelay(SAES_RESET_DELAY);
+		mmio_clrbits_32(ctx->base + _SAES_CR, _SAES_CR_IPRST);
+	}
+
+	/* Disable the SAES peripheral */
+	mmio_clrbits_32(ctx->base + _SAES_CR, _SAES_CR_EN);
+}
+
+static void saes_write_iv(struct stm32_saes_context *ctx)
+{
+	/* If chaining mode need to restore IV */
+	if (does_chaining_mode_need_iv(ctx->cr)) {
+		uint8_t i;
+
+		/* Restore the _SAES_IVRx */
+		for (i = 0U; i < AES_IVSIZE / sizeof(uint32_t); i++) {
+			mmio_write_32(ctx->base + _SAES_IVR0 + i * sizeof(uint32_t), ctx->iv[i]);
+		}
+	}
+
+}
+
+static void saes_write_key(struct stm32_saes_context *ctx)
+{
+	/* Restore the _SAES_KEYRx if SOFTWARE key */
+	if ((ctx->cr & _SAES_CR_KEYSEL_MASK) == (_SAES_CR_KEYSEL_SOFT << _SAES_CR_KEYSEL_SHIFT)) {
+		uint8_t i;
+
+		for (i = 0U; i < AES_KEYSIZE_128 / sizeof(uint32_t); i++) {
+			mmio_write_32(ctx->base + _SAES_KEYR0 + i * sizeof(uint32_t), ctx->key[i]);
+		}
+
+		if ((ctx->cr & _SAES_CR_KEYSIZE) == _SAES_CR_KEYSIZE) {
+			for (i = 0U; i < (AES_KEYSIZE_256 / 2U) / sizeof(uint32_t); i++) {
+				mmio_write_32(ctx->base + _SAES_KEYR4 + i * sizeof(uint32_t),
+					      ctx->key[i + 4U]);
+			}
+		}
+	}
+}
+
+static int saes_prepare_key(struct stm32_saes_context *ctx)
+{
+	/* Disable the SAES peripheral */
+	mmio_clrbits_32(ctx->base + _SAES_CR, _SAES_CR_EN);
+
+	/* Set key size */
+	if ((ctx->cr & _SAES_CR_KEYSIZE) != 0U) {
+		mmio_setbits_32(ctx->base + _SAES_CR, _SAES_CR_KEYSIZE);
+	} else {
+		mmio_clrbits_32(ctx->base + _SAES_CR, _SAES_CR_KEYSIZE);
+	}
+
+	saes_write_key(ctx);
+
+	/* For ECB/CBC decryption, key preparation mode must be selected to populate the key */
+	if ((IS_CHAINING_MODE(ECB, ctx->cr) || IS_CHAINING_MODE(CBC, ctx->cr)) &&
+	    is_decrypt(ctx->cr)) {
+		int ret;
+
+		/* Select Mode 2 */
+		mmio_clrsetbits_32(ctx->base + _SAES_CR, _SAES_CR_MODE_MASK,
+				   _SAES_CR_MODE_KEYPREP << _SAES_CR_MODE_SHIFT);
+
+		/* Enable SAES */
+		mmio_setbits_32(ctx->base + _SAES_CR, _SAES_CR_EN);
+
+		/* Wait Computation completed */
+		ret = wait_computation_completed(ctx->base);
+		if (ret != 0) {
+			return ret;
+		}
+
+		clear_computation_completed(ctx->base);
+
+		/* Set Mode 3 */
+		mmio_clrsetbits_32(ctx->base + _SAES_CR, _SAES_CR_MODE_MASK,
+				   _SAES_CR_MODE_DEC << _SAES_CR_MODE_SHIFT);
+	}
+
+	return 0;
+}
+
+static int save_context(struct stm32_saes_context *ctx)
+{
+	if ((mmio_read_32(ctx->base + _SAES_SR) & _SAES_SR_CCF) != 0U) {
+		/* Device should not be in a processing phase */
+		return -EINVAL;
+	}
+
+	/* Save CR */
+	ctx->cr = mmio_read_32(ctx->base + _SAES_CR);
+
+	/* If chaining mode need to save current IV */
+	if (does_chaining_mode_need_iv(ctx->cr)) {
+		uint8_t i;
+
+		/* Save IV */
+		for (i = 0U; i < AES_IVSIZE / sizeof(uint32_t); i++) {
+			ctx->iv[i] = mmio_read_32(ctx->base + _SAES_IVR0 + i * sizeof(uint32_t));
+		}
+	}
+
+	/* Disable the SAES peripheral */
+	mmio_clrbits_32(ctx->base + _SAES_CR, _SAES_CR_EN);
+
+	return 0;
+}
+
+/* To resume the processing of a message */
+static int restore_context(struct stm32_saes_context *ctx)
+{
+	int ret;
+
+	/* IP should be disabled */
+	if ((mmio_read_32(ctx->base + _SAES_CR) & _SAES_CR_EN) != 0U) {
+		VERBOSE("%s: Device is still enabled\n", __func__);
+		return -EINVAL;
+	}
+
+	/* Reset internal state */
+	mmio_setbits_32(ctx->base + _SAES_CR, _SAES_CR_IPRST);
+
+	/* Restore the _SAES_CR */
+	mmio_write_32(ctx->base + _SAES_CR, ctx->cr);
+
+	/* Preparation decrypt key */
+	ret = saes_prepare_key(ctx);
+	if (ret != 0) {
+		return ret;
+	}
+
+	saes_write_iv(ctx);
+
+	/* Enable the SAES peripheral */
+	mmio_setbits_32(ctx->base + _SAES_CR, _SAES_CR_EN);
+
+	return 0;
+}
+
+/**
+ * @brief Initialize SAES driver.
+ * @param None.
+ * @retval 0 if OK; negative value else.
+ */
+int stm32_saes_driver_init(void)
+{
+	int err;
+
+	err = stm32_saes_parse_fdt(&saes_pdata);
+	if (err != 0) {
+		err = stm32_saes_get_platdata(&saes_pdata);
+		if (err != 0) {
+			return err;
+		}
+	}
+
+	clk_enable(saes_pdata.clock_id);
+	if (stm32mp_reset_assert(saes_pdata.reset_id, TIMEOUT_US_1MS) != 0) {
+		panic();
+	}
+
+	udelay(SAES_RESET_DELAY);
+	if (stm32mp_reset_deassert(saes_pdata.reset_id, TIMEOUT_US_1MS) != 0) {
+		panic();
+	}
+
+	return 0;
+}
+
+/**
+ * @brief Start a AES computation.
+ * @param ctx: SAES process context
+ * @param is_dec: true if decryption, false if encryption
+ * @param ch_mode: define the chaining mode
+ * @param key_select: define where the key comes from.
+ * @param key: pointer to key (if key_select is KEY_SOFT, else unused)
+ * @param key_size: key size
+ * @param iv: pointer to initialization vectore (unsed if ch_mode is ECB)
+ * @param iv_size: iv size
+ * @note this function doesn't access to hardware but store in ctx the values
+ *
+ * @retval 0 if OK; negative value else.
+ */
+int stm32_saes_init(struct stm32_saes_context *ctx, bool is_dec,
+		    enum stm32_saes_chaining_mode ch_mode, enum stm32_saes_key_selection key_select,
+		    const void *key, size_t key_size, const void *iv, size_t iv_size)
+{
+	unsigned int i;
+	const uint32_t *iv_u32;
+	const uint32_t *key_u32;
+
+	ctx->assoc_len = 0U;
+	ctx->load_len = 0U;
+
+	ctx->base = saes_pdata.base;
+	ctx->cr = _SAES_CR_RESET_VALUE;
+
+	/* We want buffer to be u32 aligned */
+	assert((uintptr_t)key % __alignof__(uint32_t) == 0);
+	assert((uintptr_t)iv % __alignof__(uint32_t) == 0);
+
+	iv_u32 = iv;
+	key_u32 = key;
+
+	if (is_dec) {
+		/* Save Mode 3 = decrypt */
+		mmio_clrsetbits_32((uintptr_t)&(ctx->cr), _SAES_CR_MODE_MASK,
+				   _SAES_CR_MODE_DEC << _SAES_CR_MODE_SHIFT);
+	} else {
+		/* Save Mode 1 = crypt */
+		mmio_clrsetbits_32((uintptr_t)&(ctx->cr), _SAES_CR_MODE_MASK,
+				   _SAES_CR_MODE_ENC << _SAES_CR_MODE_SHIFT);
+	}
+
+	/* Save chaining mode */
+	switch (ch_mode) {
+	case STM32_SAES_MODE_ECB:
+		SET_CHAINING_MODE(ECB, (uintptr_t)&(ctx->cr));
+		break;
+	case STM32_SAES_MODE_CBC:
+		SET_CHAINING_MODE(CBC, (uintptr_t)&(ctx->cr));
+		break;
+	case STM32_SAES_MODE_CTR:
+		SET_CHAINING_MODE(CTR, (uintptr_t)&(ctx->cr));
+		break;
+	case STM32_SAES_MODE_GCM:
+		SET_CHAINING_MODE(GCM, (uintptr_t)&(ctx->cr));
+		break;
+	case STM32_SAES_MODE_CCM:
+		SET_CHAINING_MODE(CCM, (uintptr_t)&(ctx->cr));
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/* We will use HW Byte swap (_SAES_CR_DATATYPE_BYTE) for data.
+	 * so we won't need to
+	 * htobe32(data) before write to DINR
+	 * nor
+	 * be32toh after reading from DOUTR
+	 *
+	 * But note that wrap key only accept _SAES_CR_DATATYPE_NONE
+	 */
+	mmio_clrsetbits_32((uintptr_t)&(ctx->cr), _SAES_CR_DATATYPE_MASK,
+			   _SAES_CR_DATATYPE_BYTE << _SAES_CR_DATATYPE_SHIFT);
+
+	/* Configure keysize */
+	switch (key_size) {
+	case AES_KEYSIZE_128:
+		mmio_clrbits_32((uintptr_t)&(ctx->cr), _SAES_CR_KEYSIZE);
+		break;
+	case AES_KEYSIZE_256:
+		mmio_setbits_32((uintptr_t)&(ctx->cr), _SAES_CR_KEYSIZE);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/* Configure key */
+	switch (key_select) {
+	case STM32_SAES_KEY_SOFT:
+		mmio_clrsetbits_32((uintptr_t)&(ctx->cr), _SAES_CR_KEYSEL_MASK,
+				   _SAES_CR_KEYSEL_SOFT << _SAES_CR_KEYSEL_SHIFT);
+		/* Save key */
+		switch (key_size) {
+		case AES_KEYSIZE_128:
+			/* First 16 bytes == 4 u32 */
+			for (i = 0U; i < AES_KEYSIZE_128 / sizeof(uint32_t); i++) {
+				mmio_write_32((uintptr_t)(ctx->key + i), htobe32(key_u32[3 - i]));
+				/* /!\ we save the key in HW byte order
+				 * and word order : key[i] is for _SAES_KEYRi
+				 */
+			}
+			break;
+		case AES_KEYSIZE_256:
+			for (i = 0U; i < AES_KEYSIZE_256 / sizeof(uint32_t); i++) {
+				mmio_write_32((uintptr_t)(ctx->key + i), htobe32(key_u32[7 - i]));
+				/* /!\ we save the key in HW byte order
+				 * and word order : key[i] is for _SAES_KEYRi
+				 */
+			}
+			break;
+		default:
+			return -EINVAL;
+		}
+
+		break;
+	case STM32_SAES_KEY_DHU:
+		mmio_clrsetbits_32((uintptr_t)&(ctx->cr), _SAES_CR_KEYSEL_MASK,
+				   _SAES_CR_KEYSEL_DHUK << _SAES_CR_KEYSEL_SHIFT);
+		break;
+	case STM32_SAES_KEY_BH:
+		mmio_clrsetbits_32((uintptr_t)&(ctx->cr), _SAES_CR_KEYSEL_MASK,
+				   _SAES_CR_KEYSEL_BHK << _SAES_CR_KEYSEL_SHIFT);
+		break;
+	case STM32_SAES_KEY_BHU_XOR_BH:
+		mmio_clrsetbits_32((uintptr_t)&(ctx->cr), _SAES_CR_KEYSEL_MASK,
+				   _SAES_CR_KEYSEL_BHU_XOR_BH_K << _SAES_CR_KEYSEL_SHIFT);
+		break;
+	case STM32_SAES_KEY_WRAPPED:
+		mmio_clrsetbits_32((uintptr_t)&(ctx->cr), _SAES_CR_KEYSEL_MASK,
+				   _SAES_CR_KEYSEL_SOFT << _SAES_CR_KEYSEL_SHIFT);
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	/* Save IV */
+	if (ch_mode != STM32_SAES_MODE_ECB) {
+		if ((iv == NULL) || (iv_size != AES_IVSIZE)) {
+			return -EINVAL;
+		}
+
+		for (i = 0U; i < AES_IVSIZE / sizeof(uint32_t); i++) {
+			mmio_write_32((uintptr_t)(ctx->iv + i), htobe32(iv_u32[3 - i]));
+			/* /!\ We save the iv in HW byte order */
+		}
+	}
+
+	return saes_start(ctx);
+}
+
+/**
+ * @brief Update (or start) a AES authentificate process of associated data (CCM or GCM).
+ * @param ctx: SAES process context
+ * @param last_block: true if last assoc data block
+ * @param data: pointer to associated data
+ * @param data_size: data size
+ *
+ * @retval 0 if OK; negative value else.
+ */
+int stm32_saes_update_assodata(struct stm32_saes_context *ctx, bool last_block,
+			       uint8_t *data, size_t data_size)
+{
+	int ret;
+	uint32_t *data_u32;
+	unsigned int i = 0U;
+
+	/* We want buffers to be u32 aligned */
+	assert((uintptr_t)data % __alignof__(uint32_t) == 0);
+	data_u32 = (uint32_t *)data;
+
+	/* Init phase */
+	ret = restore_context(ctx);
+	if (ret != 0) {
+		goto out;
+	}
+
+	ret = wait_computation_completed(ctx->base);
+	if (ret != 0) {
+		return ret;
+	}
+
+	clear_computation_completed(ctx->base);
+
+	if ((data == NULL) || (data_size == 0U)) {
+		/* No associated data */
+		/* ret already = 0 */
+		goto out;
+	}
+
+	/* There is an header/associated data phase */
+	mmio_clrsetbits_32(ctx->base + _SAES_CR, _SAES_CR_GCMPH_MASK,
+			   _SAES_CR_GCMPH_HEADER << _SAES_CR_GCMPH_SHIFT);
+
+	/* Enable the SAES peripheral */
+	mmio_setbits_32(ctx->base + _SAES_CR, _SAES_CR_EN);
+
+	while (i < round_down(data_size, AES_BLOCK_SIZE)) {
+		unsigned int w; /* Word index */
+
+		w = i / sizeof(uint32_t);
+		/* No need to htobe() as we configure the HW to swap bytes */
+		mmio_write_32(ctx->base + _SAES_DINR, data_u32[w + 0U]);
+		mmio_write_32(ctx->base + _SAES_DINR, data_u32[w + 1U]);
+		mmio_write_32(ctx->base + _SAES_DINR, data_u32[w + 2U]);
+		mmio_write_32(ctx->base + _SAES_DINR, data_u32[w + 3U]);
+
+		ret = wait_computation_completed(ctx->base);
+		if (ret != 0) {
+			goto out;
+		}
+
+		clear_computation_completed(ctx->base);
+
+		/* Process next block */
+		i += AES_BLOCK_SIZE;
+		ctx->assoc_len += AES_BLOCK_SIZE_BIT;
+	}
+
+	/* Manage last block if not a block size multiple */
+	if ((last_block) && (i < data_size)) {
+		/* We don't manage unaligned last block yet */
+		ret = -ENODEV;
+		goto out;
+	}
+
+out:
+	if (ret != 0) {
+		saes_end(ctx, ret);
+	}
+
+	return ret;
+}
+
+/**
+ * @brief Update (or start) a AES authenticate and de/encrypt with payload data (CCM or GCM).
+ * @param ctx: SAES process context
+ * @param last_block: true if last payload data block
+ * @param data_in: pointer to payload
+ * @param data_out: pointer where to save de/encrypted payload
+ * @param data_size: payload size
+ *
+ * @retval 0 if OK; negative value else.
+ */
+int stm32_saes_update_load(struct stm32_saes_context *ctx, bool last_block,
+			   uint8_t *data_in, uint8_t *data_out, size_t data_size)
+{
+	int ret = 0;
+	uint32_t *data_in_u32;
+	uint32_t *data_out_u32;
+	unsigned int i = 0U;
+	uint32_t prev_cr;
+
+	/* We want buffers to be u32 aligned */
+	assert((uintptr_t)data_in % __alignof__(uint32_t) == 0);
+	assert((uintptr_t)data_out % __alignof__(uint32_t) == 0);
+	data_in_u32 = (uint32_t *)data_in;
+	data_out_u32 = (uint32_t *)data_out;
+
+	prev_cr = mmio_read_32(ctx->base + _SAES_CR);
+
+	if ((data_in == NULL) || (data_size == 0U)) {
+		/* there is no data */
+		goto out;
+	}
+
+	/* There is a load phase */
+	mmio_clrsetbits_32(ctx->base + _SAES_CR, _SAES_CR_GCMPH_MASK,
+			   _SAES_CR_GCMPH_PAYLOAD << _SAES_CR_GCMPH_SHIFT);
+
+	if ((prev_cr & _SAES_CR_GCMPH_MASK) ==
+	    (_SAES_CR_GCMPH_INIT << _SAES_CR_GCMPH_SHIFT)) {
+		/* Still in initialization phase, no header
+		 * We need to enable the SAES peripheral
+		 */
+		mmio_setbits_32(ctx->base + _SAES_CR, _SAES_CR_EN);
+	}
+
+	while (i < round_down(data_size, AES_BLOCK_SIZE)) {
+		unsigned int w; /* Word index */
+
+		w = i / sizeof(uint32_t);
+		/* No need to htobe() as we configure the HW to swap bytes */
+		mmio_write_32(ctx->base + _SAES_DINR, data_in_u32[w + 0U]);
+		mmio_write_32(ctx->base + _SAES_DINR, data_in_u32[w + 1U]);
+		mmio_write_32(ctx->base + _SAES_DINR, data_in_u32[w + 2U]);
+		mmio_write_32(ctx->base + _SAES_DINR, data_in_u32[w + 3U]);
+
+		ret = wait_computation_completed(ctx->base);
+		if (ret != 0) {
+			goto out;
+		}
+
+		/* No need to htobe() as we configure the HW to swap bytes */
+		data_out_u32[w + 0U] = mmio_read_32(ctx->base + _SAES_DOUTR);
+		data_out_u32[w + 1U] = mmio_read_32(ctx->base + _SAES_DOUTR);
+		data_out_u32[w + 2U] = mmio_read_32(ctx->base + _SAES_DOUTR);
+		data_out_u32[w + 3U] = mmio_read_32(ctx->base + _SAES_DOUTR);
+
+		clear_computation_completed(ctx->base);
+
+		/* Process next block */
+		i += AES_BLOCK_SIZE;
+		ctx->load_len += AES_BLOCK_SIZE_BIT;
+	}
+	/* Manage last block if not a block size multiple */
+	if ((last_block) && (i < data_size)) {
+		uint32_t block_in[AES_BLOCK_SIZE / sizeof(uint32_t)] = {0};
+		uint32_t block_out[AES_BLOCK_SIZE / sizeof(uint32_t)] = {0};
+
+		memcpy(block_in, data_in + i, data_size - i);
+
+		/* No need to htobe() as we configure the HW to swap bytes */
+		mmio_write_32(ctx->base + _SAES_DINR, block_in[0U]);
+		mmio_write_32(ctx->base + _SAES_DINR, block_in[1U]);
+		mmio_write_32(ctx->base + _SAES_DINR, block_in[2U]);
+		mmio_write_32(ctx->base + _SAES_DINR, block_in[3U]);
+
+		ret = wait_computation_completed(ctx->base);
+		if (ret != 0) {
+			VERBOSE("%s %d\n", __func__, __LINE__);
+			goto out;
+		}
+
+		/* No need to htobe() as we configure the HW to swap bytes */
+		block_out[0U] = mmio_read_32(ctx->base + _SAES_DOUTR);
+		block_out[1U] = mmio_read_32(ctx->base + _SAES_DOUTR);
+		block_out[2U] = mmio_read_32(ctx->base + _SAES_DOUTR);
+		block_out[3U] = mmio_read_32(ctx->base + _SAES_DOUTR);
+
+		clear_computation_completed(ctx->base);
+
+		memcpy(data_out + i, block_out, data_size - i);
+
+		ctx->load_len += (data_size - i) * UINT8_BIT;
+	}
+
+out:
+	if (ret != 0) {
+		saes_end(ctx, ret);
+	}
+
+	return ret;
+}
+
+/**
+ * @brief Get authentication tag for AES authenticated algorithms (CCM or GCM).
+ * @param ctx: SAES process context
+ * @param tag: pointer where to save the tag
+ * @param data_size: tag size
+ *
+ * @retval 0 if OK; negative value else.
+ */
+int stm32_saes_final(struct stm32_saes_context *ctx, uint8_t *tag,
+		     size_t tag_size)
+{
+	int ret;
+	uint32_t tag_u32[4];
+	uint32_t prev_cr;
+
+	prev_cr = mmio_read_32(ctx->base + _SAES_CR);
+
+	mmio_clrsetbits_32(ctx->base + _SAES_CR, _SAES_CR_GCMPH_MASK,
+			   _SAES_CR_GCMPH_FINAL << _SAES_CR_GCMPH_SHIFT);
+
+	if ((prev_cr & _SAES_CR_GCMPH_MASK) == (_SAES_CR_GCMPH_INIT << _SAES_CR_GCMPH_SHIFT)) {
+		/* Still in initialization phase, no header
+		 * We need to enable the SAES peripheral
+		 */
+		mmio_setbits_32(ctx->base + _SAES_CR, _SAES_CR_EN);
+	}
+
+	/* No need to htobe() as we configure the HW to swap bytes */
+	mmio_write_32(ctx->base + _SAES_DINR, 0);
+	mmio_write_32(ctx->base + _SAES_DINR, ctx->assoc_len);
+	mmio_write_32(ctx->base + _SAES_DINR, 0);
+	mmio_write_32(ctx->base + _SAES_DINR, ctx->load_len);
+
+	ret = wait_computation_completed(ctx->base);
+	if (ret != 0) {
+		goto out;
+	}
+
+	/* No need to htobe() as we configure the HW to swap bytes */
+	tag_u32[0] = mmio_read_32(ctx->base + _SAES_DOUTR);
+	tag_u32[1] = mmio_read_32(ctx->base + _SAES_DOUTR);
+	tag_u32[2] = mmio_read_32(ctx->base + _SAES_DOUTR);
+	tag_u32[3] = mmio_read_32(ctx->base + _SAES_DOUTR);
+
+	clear_computation_completed(ctx->base);
+
+	memcpy(tag, tag_u32, MIN(sizeof(tag_u32), tag_size));
+
+out:
+	saes_end(ctx, ret);
+
+	return ret;
+}
+
+/**
+ * @brief Update (or start) a AES de/encrypt process (ECB, CBC or CTR).
+ * @param ctx: SAES process context
+ * @param last_block: true if last payload data block
+ * @param data_in: pointer to payload
+ * @param data_out: pointer where to save de/encrypted payload
+ * @param data_size: payload size
+ *
+ * @retval 0 if OK; negative value else.
+ */
+int stm32_saes_update(struct stm32_saes_context *ctx, bool last_block,
+		      uint8_t *data_in, uint8_t *data_out, size_t data_size)
+{
+	int ret;
+	uint32_t *data_in_u32;
+	uint32_t *data_out_u32;
+	unsigned int i = 0U;
+
+	/* We want buffers to be u32 aligned */
+	assert((uintptr_t)data_in % __alignof__(uint32_t) == 0);
+	assert((uintptr_t)data_out % __alignof__(uint32_t) == 0);
+	data_in_u32 = (uint32_t *)data_in;
+	data_out_u32 = (uint32_t *)data_out;
+
+	if ((!last_block) &&
+	    (round_down(data_size, AES_BLOCK_SIZE) != data_size)) {
+		ERROR("%s: non last block must be multiple of 128 bits\n",
+		      __func__);
+		ret = -EINVAL;
+		goto out;
+	}
+
+	/* In CBC encryption we need to manage specifically last 2 128bits
+	 * blocks if total size in not a block size aligned
+	 * work TODO. Currently return ENODEV.
+	 * Morevoer as we need to know last 2 block, if unaligned and
+	 * call with less than two block, return -EINVAL.
+	 */
+	if (last_block && IS_CHAINING_MODE(CBC, ctx->cr) && is_encrypt(ctx->cr) &&
+	    (round_down(data_size, AES_BLOCK_SIZE) != data_size)) {
+		if (data_size < AES_BLOCK_SIZE * 2U) {
+			ERROR("if CBC, last part size should be at least 2 * AES_BLOCK_SIZE\n");
+			ret = -EINVAL;
+			goto out;
+		}
+		/* Moreover the CBC specific padding for encrypt is not yet implemented */
+		ret = -ENODEV;
+		goto out;
+	}
+
+	ret = restore_context(ctx);
+	if (ret != 0) {
+		goto out;
+	}
+
+	while (i < round_down(data_size, AES_BLOCK_SIZE)) {
+		unsigned int w; /* Word index */
+
+		w = i / sizeof(uint32_t);
+		/* No need to htobe() as we configure the HW to swap bytes */
+		mmio_write_32(ctx->base + _SAES_DINR, data_in_u32[w + 0U]);
+		mmio_write_32(ctx->base + _SAES_DINR, data_in_u32[w + 1U]);
+		mmio_write_32(ctx->base + _SAES_DINR, data_in_u32[w + 2U]);
+		mmio_write_32(ctx->base + _SAES_DINR, data_in_u32[w + 3U]);
+
+		ret = wait_computation_completed(ctx->base);
+		if (ret != 0) {
+			goto out;
+		}
+
+		/* No need to htobe() as we configure the HW to swap bytes */
+		data_out_u32[w + 0U] = mmio_read_32(ctx->base + _SAES_DOUTR);
+		data_out_u32[w + 1U] = mmio_read_32(ctx->base + _SAES_DOUTR);
+		data_out_u32[w + 2U] = mmio_read_32(ctx->base + _SAES_DOUTR);
+		data_out_u32[w + 3U] = mmio_read_32(ctx->base + _SAES_DOUTR);
+
+		clear_computation_completed(ctx->base);
+
+		/* Process next block */
+		i += AES_BLOCK_SIZE;
+	}
+	/* Manage last block if not a block size multiple */
+
+	if ((last_block) && (i < data_size)) {
+		/* In and out buffer have same size so should be AES_BLOCK_SIZE multiple */
+		ret = -ENODEV;
+		goto out;
+	}
+
+	if (!last_block) {
+		ret = save_context(ctx);
+	}
+
+out:
+	/* If last block or error, end of SAES process */
+	if (last_block || (ret != 0)) {
+		saes_end(ctx, ret);
+	}
+
+	return ret;
+}
diff --git a/drivers/st/io/io_stm32image.c b/drivers/st/io/io_stm32image.c
index 9fa0c50..c33a2fe 100644
--- a/drivers/st/io/io_stm32image.c
+++ b/drivers/st/io/io_stm32image.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2021, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2022, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -333,19 +333,6 @@
 			continue;
 		}
 
-		result = stm32mp_check_header(header, buffer);
-		if (result != 0) {
-			ERROR("Header check failed\n");
-			*length_read = 0;
-			header->magic = 0;
-		}
-
-		result = stm32mp_auth_image(header, buffer);
-		if (result != 0) {
-			ERROR("Authentication Failed (%i)\n", result);
-			return result;
-		}
-
 		inv_dcache_range(round_up((uintptr_t)(local_buffer + length - hdr_sz),
 					  CACHE_WRITEBACK_GRANULE), *length_read - length + hdr_sz);
 
diff --git a/fdts/stm32mp1-cot-descriptors.dtsi b/fdts/stm32mp1-cot-descriptors.dtsi
new file mode 100644
index 0000000..eb632ff
--- /dev/null
+++ b/fdts/stm32mp1-cot-descriptors.dtsi
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2020-2022, ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/nv_cntr_ids.h>
+#include <common/tbbr/tbbr_img_def.h>
+#include <tools_share/tbbr_oid.h>
+
+cot {
+	manifests {
+		compatible = "arm, cert-descs";
+
+		stm32mp_cfg_cert: stm32mp_cfg_cert {
+			root-certificate;
+			image-id = <STM32MP_CONFIG_CERT_ID>;
+			antirollback-counter = <&trusted_nv_counter>;
+
+			hw_config_hash: hw_config_hash {
+				oid = HW_CONFIG_HASH_OID;
+			};
+
+			fw_config_hash: fw_config_hash {
+				oid = FW_CONFIG_HASH_OID;
+			};
+		};
+
+		trusted_key_cert: trusted_key_cert {
+			root-certificate;
+			image-id = <TRUSTED_KEY_CERT_ID>;
+			antirollback-counter = <&trusted_nv_counter>;
+
+			trusted_world_pk: trusted_world_pk {
+				oid = TRUSTED_WORLD_PK_OID;
+			};
+			non_trusted_world_pk: non_trusted_world_pk {
+				oid = NON_TRUSTED_WORLD_PK_OID;
+			};
+		};
+
+		trusted_os_fw_key_cert: trusted_os_fw_key_cert {
+			image-id = <TRUSTED_OS_FW_KEY_CERT_ID>;
+			parent = <&trusted_key_cert>;
+			signing-key = <&trusted_world_pk>;
+			antirollback-counter = <&trusted_nv_counter>;
+
+			tos_fw_content_pk: tos_fw_content_pk {
+				oid = TRUSTED_OS_FW_CONTENT_CERT_PK_OID;
+			};
+		};
+
+		trusted_os_fw_content_cert: trusted_os_fw_content_cert {
+			image-id = <TRUSTED_OS_FW_CONTENT_CERT_ID>;
+			parent = <&trusted_os_fw_key_cert>;
+			signing-key = <&tos_fw_content_pk>;
+			antirollback-counter = <&trusted_nv_counter>;
+
+			tos_fw_hash: tos_fw_hash {
+				oid = TRUSTED_OS_FW_HASH_OID;
+			};
+			tos_fw_extra1_hash: tos_fw_extra1_hash {
+				oid = TRUSTED_OS_FW_EXTRA1_HASH_OID;
+			};
+			tos_fw_extra2_hash: tos_fw_extra2_hash {
+				oid = TRUSTED_OS_FW_EXTRA2_HASH_OID;
+			};
+			tos_fw_config_hash: tos_fw_config_hash {
+				oid = TRUSTED_OS_FW_CONFIG_HASH_OID;
+			};
+		};
+
+		non_trusted_fw_key_cert: non_trusted_fw_key_cert {
+			image-id = <NON_TRUSTED_FW_KEY_CERT_ID>;
+			parent = <&trusted_key_cert>;
+			signing-key = <&non_trusted_world_pk>;
+			antirollback-counter = <&non_trusted_nv_counter>;
+
+			nt_fw_content_pk: nt_fw_content_pk {
+				oid = NON_TRUSTED_FW_CONTENT_CERT_PK_OID;
+			};
+		};
+
+		non_trusted_fw_content_cert: non_trusted_fw_content_cert {
+			image-id = <NON_TRUSTED_FW_CONTENT_CERT_ID>;
+			parent = <&non_trusted_fw_key_cert>;
+			signing-key = <&nt_fw_content_pk>;
+			antirollback-counter = <&non_trusted_nv_counter>;
+
+			nt_world_bl_hash: nt_world_bl_hash {
+				oid = NON_TRUSTED_WORLD_BOOTLOADER_HASH_OID;
+			};
+		};
+	};
+
+	images {
+		compatible = "arm, img-descs";
+
+		hw_config {
+			image-id = <HW_CONFIG_ID>;
+			parent = <&stm32mp_cfg_cert>;
+			hash = <&hw_config_hash>;
+		};
+
+		fw_config {
+			image-id = <FW_CONFIG_ID>;
+			parent = <&stm32mp_cfg_cert>;
+			hash = <&fw_config_hash>;
+		};
+
+		bl32_image {
+			image-id = <BL32_IMAGE_ID>;
+			parent = <&trusted_os_fw_content_cert>;
+			hash = <&tos_fw_hash>;
+		};
+
+		bl32_extra1_image {
+			image-id = <BL32_EXTRA1_IMAGE_ID>;
+			parent = <&trusted_os_fw_content_cert>;
+			hash = <&tos_fw_extra1_hash>;
+		};
+
+		bl32_extra2_image {
+			image-id = <BL32_EXTRA2_IMAGE_ID>;
+			parent = <&trusted_os_fw_content_cert>;
+			hash = <&tos_fw_extra2_hash>;
+		};
+
+		tos_fw_config {
+			image-id = <TOS_FW_CONFIG_ID>;
+			parent = <&trusted_os_fw_content_cert>;
+			hash = <&tos_fw_config_hash>;
+		};
+
+		bl33_image {
+			image-id = <BL33_IMAGE_ID>;
+			parent = <&non_trusted_fw_content_cert>;
+			hash = <&nt_world_bl_hash>;
+		};
+	};
+};
+
+non_volatile_counters: non_volatile_counters {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	trusted_nv_counter: trusted_nv_counter {
+		id  = <TRUSTED_NV_CTR_ID>;
+		oid = TRUSTED_FW_NVCOUNTER_OID;
+	};
+
+	non_trusted_nv_counter: non_trusted_nv_counter {
+		id  = <NON_TRUSTED_NV_CTR_ID>;
+		oid = NON_TRUSTED_FW_NVCOUNTER_OID;
+	};
+};
diff --git a/fdts/stm32mp13-bl2.dtsi b/fdts/stm32mp13-bl2.dtsi
index 4e3701c..836e9ae 100644
--- a/fdts/stm32mp13-bl2.dtsi
+++ b/fdts/stm32mp13-bl2.dtsi
@@ -56,7 +56,30 @@
 			bl33_uuid = "d6d0eea7-fcea-d54b-9782-9934f234b6e4";
 			hw_cfg_uuid = "08b8f1d9-c9cf-9349-a962-6fbc6b7265cc";
 			tos_fw_cfg_uuid = "26257c1a-dbc6-7f47-8d96-c4c4b0248021";
-			nt_fw_cfg_uuid = "28da9815-93e8-7e44-ac66-1aaf801550f9";
+#if TRUSTED_BOARD_BOOT
+			stm32mp_cfg_cert_uuid = "501d8dd2-8bce-49a5-84eb-559a9f2eaeaf";
+			t_key_cert_uuid = "827ee890-f860-e411-a1b4-777a21b4f94c";
+			tos_fw_key_cert_uuid = "9477d603-fb60-e411-85dd-b7105b8cee04";
+			nt_fw_key_cert_uuid = "8ad5832a-fb60-e411-8aaf-df30bbc49859";
+			tos_fw_content_cert_uuid = "a49f4411-5e63-e411-8728-3f05722af33d";
+			nt_fw_content_cert_uuid = "8ec4c1f3-5d63-e411-a7a9-87ee40b23fa7";
+#endif
 		};
 	};
+
+#if TRUSTED_BOARD_BOOT
+	tb_fw-config {
+		compatible = "arm,tb_fw";
+
+		/* Disable authentication for development */
+		disable_auth = <0x0>;
+
+		/* Use SRAM2 to manage the mbedTLS heap */
+		mbedtls_heap_addr = <0x0 0x30004000>; /* SRAM2_BASE */
+		mbedtls_heap_size = <0x2000>; /* SRAM2_SIZE */
+	};
+
+#include "stm32mp1-cot-descriptors.dtsi"
+#endif
+
 };
diff --git a/fdts/stm32mp131.dtsi b/fdts/stm32mp131.dtsi
index 2c62408..543afa5 100644
--- a/fdts/stm32mp131.dtsi
+++ b/fdts/stm32mp131.dtsi
@@ -455,6 +455,9 @@
 				reg = <0xe4 0xc>;
 				st,non-secure-otp;
 			};
+			enckey_otp: enckey_otp@170 {
+				reg = <0x170 0x10>;
+			};
 		};
 		/*
 		 * Break node order to solve dependency probe issue between
diff --git a/fdts/stm32mp135f-dk.dts b/fdts/stm32mp135f-dk.dts
index aa1dd01..0f06b67 100644
--- a/fdts/stm32mp135f-dk.dts
+++ b/fdts/stm32mp135f-dk.dts
@@ -176,7 +176,7 @@
 };
 
 &pka {
-	secure-status = "okay";
+	status = "okay";
 };
 
 &pwr_regulators {
@@ -298,7 +298,7 @@
 };
 
 &saes {
-	secure-status = "okay";
+	status = "okay";
 };
 
 &sdmmc1 {
diff --git a/fdts/stm32mp15-bl2.dtsi b/fdts/stm32mp15-bl2.dtsi
index 501b092..b2d0ba6 100644
--- a/fdts/stm32mp15-bl2.dtsi
+++ b/fdts/stm32mp15-bl2.dtsi
@@ -85,8 +85,33 @@
 			bl33_uuid = "d6d0eea7-fcea-d54b-9782-9934f234b6e4";
 			hw_cfg_uuid = "08b8f1d9-c9cf-9349-a962-6fbc6b7265cc";
 			tos_fw_cfg_uuid = "26257c1a-dbc6-7f47-8d96-c4c4b0248021";
-			nt_fw_cfg_uuid = "28da9815-93e8-7e44-ac66-1aaf801550f9";
+#if TRUSTED_BOARD_BOOT
+			stm32mp_cfg_cert_uuid = "501d8dd2-8bce-49a5-84eb-559a9f2eaeaf";
+			t_key_cert_uuid = "827ee890-f860-e411-a1b4-777a21b4f94c";
+			tos_fw_key_cert_uuid = "9477d603-fb60-e411-85dd-b7105b8cee04";
+			nt_fw_key_cert_uuid = "8ad5832a-fb60-e411-8aaf-df30bbc49859";
+			tos_fw_content_cert_uuid = "a49f4411-5e63-e411-8728-3f05722af33d";
+			nt_fw_content_cert_uuid = "8ec4c1f3-5d63-e411-a7a9-87ee40b23fa7";
+#endif
 		};
 	};
+
+#if TRUSTED_BOARD_BOOT
+	tb_fw-config {
+		compatible = "arm,tb_fw";
+
+		/* Disable authentication for development */
+		disable_auth = <0x0>;
+
+		/*
+		 * The following two entries are placeholders for Mbed TLS
+		 * heap information.
+		 */
+		mbedtls_heap_addr = <0x0 0x0>;
+		mbedtls_heap_size = <0x0>;
+	};
+
+#include "stm32mp1-cot-descriptors.dtsi"
+#endif
 #endif /* !STM32MP_USE_STM32IMAGE */
 };
diff --git a/fdts/stm32mp151.dtsi b/fdts/stm32mp151.dtsi
index bb16fda..a938edc 100644
--- a/fdts/stm32mp151.dtsi
+++ b/fdts/stm32mp151.dtsi
@@ -487,6 +487,9 @@
 			ts_cal2: calib@5e {
 				reg = <0x5e 0x2>;
 			};
+			pkh_otp: pkh_otp@60 {
+				reg = <0x60 0x20>;
+			};
 			mac_addr: mac_addr@e4 {
 				reg = <0xe4 0x8>;
 				st,non-secure-otp;
diff --git a/include/common/tbbr/cot_def.h b/include/common/tbbr/cot_def.h
index e0c2212..60dfb8a 100644
--- a/include/common/tbbr/cot_def.h
+++ b/include/common/tbbr/cot_def.h
@@ -41,7 +41,7 @@
 #error "Invalid value for TF_MBEDTLS_KEY_SIZE"
 #endif
 #else /* Only using ECDSA keys. */
-#define PK_DER_LEN                      91
+#define PK_DER_LEN                      92
 #endif
 
 #if TF_MBEDTLS_HASH_ALG_ID == TF_MBEDTLS_SHA256
diff --git a/include/drivers/st/stm32_hash.h b/include/drivers/st/stm32_hash.h
index df04730..bebb4af 100644
--- a/include/drivers/st/stm32_hash.h
+++ b/include/drivers/st/stm32_hash.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2019-2022, STMicroelectronics - All Rights Reserved
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -7,11 +7,19 @@
 #ifndef STM32_HASH_H
 #define STM32_HASH_H
 
+#include <stdint.h>
+
 enum stm32_hash_algo_mode {
+#if STM32_HASH_VER == 2
 	HASH_MD5SUM,
+#endif
 	HASH_SHA1,
 	HASH_SHA224,
-	HASH_SHA256
+	HASH_SHA256,
+#if STM32_HASH_VER == 4
+	HASH_SHA384,
+	HASH_SHA512,
+#endif
 };
 
 int stm32_hash_update(const uint8_t *buffer, size_t length);
diff --git a/include/drivers/st/stm32_pka.h b/include/drivers/st/stm32_pka.h
new file mode 100644
index 0000000..ad4690a
--- /dev/null
+++ b/include/drivers/st/stm32_pka.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2022, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef STM32_PKA_H
+#define STM32_PKA_H
+
+#include <stdint.h>
+
+#if !PKA_USE_NIST_P256 && !PKA_USE_BRAINPOOL_P256R1 && !PKA_USE_BRAINPOOL_P256T1 && \
+	!PKA_USE_NIST_P521
+#error "At least one ECDSA curve needs to be selected"
+#endif
+
+enum stm32_pka_ecdsa_curve_id {
+#if PKA_USE_NIST_P256
+	PKA_NIST_P256,
+#endif
+#if PKA_USE_BRAINPOOL_P256R1
+	PKA_BRAINPOOL_P256R1,
+#endif
+#if PKA_USE_BRAINPOOL_P256T1
+	PKA_BRAINPOOL_P256T1,
+#endif
+#if PKA_USE_NIST_P521
+	PKA_NIST_P521,
+#endif
+};
+
+struct stm32_pka_platdata {
+	uintptr_t base;
+	unsigned long clock_id;
+	unsigned int reset_id;
+};
+
+int stm32_pka_init(void);
+int stm32_pka_ecdsa_verif(void *hash, unsigned int hash_size,
+			  void *sig_r_ptr, unsigned int sig_r_size,
+			  void *sig_s_ptr, unsigned int sig_s_size,
+			  void *pk_x_ptr, unsigned int pk_x_size,
+			  void *pk_y_ptr, unsigned int pk_y_size,
+			  enum stm32_pka_ecdsa_curve_id cid);
+
+#endif /* STM32_PKA_H */
diff --git a/include/drivers/st/stm32_rng.h b/include/drivers/st/stm32_rng.h
new file mode 100644
index 0000000..6ac064d
--- /dev/null
+++ b/include/drivers/st/stm32_rng.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2022, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef STM32_RNG_H
+#define STM32_RNG_H
+
+#include <stdint.h>
+
+int stm32_rng_read(uint8_t *out, uint32_t size);
+int stm32_rng_init(void);
+
+#endif /* STM32_RNG_H */
diff --git a/include/drivers/st/stm32_saes.h b/include/drivers/st/stm32_saes.h
new file mode 100644
index 0000000..0a50438
--- /dev/null
+++ b/include/drivers/st/stm32_saes.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2022, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef STM32_SAES_H
+#define STM32_SAES_H
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#define DT_SAES_COMPAT		"st,stm32-saes"
+
+struct stm32_saes_platdata {
+	uintptr_t base;
+	unsigned long clock_id;
+	unsigned int reset_id;
+};
+
+enum stm32_saes_chaining_mode {
+	STM32_SAES_MODE_ECB,
+	STM32_SAES_MODE_CBC,
+	STM32_SAES_MODE_CTR,
+	STM32_SAES_MODE_GCM,
+	STM32_SAES_MODE_CCM, /* Not use in TF-A */
+};
+
+enum stm32_saes_key_selection {
+	STM32_SAES_KEY_SOFT,
+	STM32_SAES_KEY_DHU,           /* Derived HW unique key */
+	STM32_SAES_KEY_BH,            /* Boot HW key */
+	STM32_SAES_KEY_BHU_XOR_BH,    /* XOR of DHUK and BHK */
+	STM32_SAES_KEY_WRAPPED
+};
+
+struct stm32_saes_context {
+	uintptr_t base;
+	uint32_t cr;
+	uint32_t assoc_len;
+	uint32_t load_len;
+	uint32_t key[8]; /* In HW byte order */
+	uint32_t iv[4];  /* In HW byte order */
+};
+
+int stm32_saes_driver_init(void);
+
+int stm32_saes_init(struct stm32_saes_context *ctx, bool is_decrypt,
+		    enum stm32_saes_chaining_mode ch_mode, enum stm32_saes_key_selection key_select,
+		    const void *key, size_t key_len, const void *iv, size_t iv_len);
+int stm32_saes_update(struct stm32_saes_context *ctx, bool last_block,
+		      uint8_t *data_in, uint8_t *data_out, size_t data_len);
+int stm32_saes_update_assodata(struct stm32_saes_context *ctx, bool last_block,
+			       uint8_t *data, size_t data_len);
+int stm32_saes_update_load(struct stm32_saes_context *ctx, bool last_block,
+			   uint8_t *data_in, uint8_t *data_out, size_t data_len);
+int stm32_saes_final(struct stm32_saes_context *ctx, uint8_t *tag, size_t tag_len);
+#endif
diff --git a/include/plat/common/platform.h b/include/plat/common/platform.h
index c7b7908..8407bbd 100644
--- a/include/plat/common/platform.h
+++ b/include/plat/common/platform.h
@@ -344,6 +344,8 @@
 int plat_set_nv_ctr(void *cookie, unsigned int nv_ctr);
 int plat_set_nv_ctr2(void *cookie, const struct auth_img_desc_s *img_desc,
 		unsigned int nv_ctr);
+int plat_convert_pk(void *full_pk_ptr, unsigned int full_pk_len,
+		    void **hashed_pk_ptr, unsigned int *hash_pk_len);
 int get_mbedtls_heap_helper(void **heap_addr, size_t *heap_size);
 int plat_get_enc_key_info(enum fw_enc_status_t fw_enc_status, uint8_t *key,
 			  size_t *key_len, unsigned int *flags,
diff --git a/lib/fconf/fconf_tbbr_getter.c b/lib/fconf/fconf_tbbr_getter.c
index 6f043e6..c3b4b7e 100644
--- a/lib/fconf/fconf_tbbr_getter.c
+++ b/lib/fconf/fconf_tbbr_getter.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019-2021, Arm Limited. All rights reserved.
+ * Copyright (c) 2019-2022, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -44,8 +44,8 @@
 	/* Check if the value is boolean */
 	if ((tbbr_dyn_config.disable_auth != 0U) &&
 	    (tbbr_dyn_config.disable_auth != 1U)) {
-		WARN("Invalid value for `%s` cell %d\n",
-			"disable_auth", tbbr_dyn_config.disable_auth);
+		WARN("Invalid value for `%s` cell %u\n",
+		     "disable_auth", tbbr_dyn_config.disable_auth);
 		return -1;
 	}
 
@@ -71,7 +71,7 @@
 	}
 	tbbr_dyn_config.mbedtls_heap_size = val32;
 
-	VERBOSE("%s%s%s %d\n", "FCONF: `tbbr.", "disable_auth",
+	VERBOSE("%s%s%s %u\n", "FCONF: `tbbr.", "disable_auth",
 		"` cell found with value =", tbbr_dyn_config.disable_auth);
 	VERBOSE("%s%s%s %p\n", "FCONF: `tbbr.", "mbedtls_heap_addr",
 		"` cell found with value =", tbbr_dyn_config.mbedtls_heap_addr);
diff --git a/plat/st/common/bl2_io_storage.c b/plat/st/common/bl2_io_storage.c
index 7222584..b271ed6 100644
--- a/plat/st/common/bl2_io_storage.c
+++ b/plat/st/common/bl2_io_storage.c
@@ -14,6 +14,7 @@
 #include <drivers/fwu/fwu_metadata.h>
 #include <drivers/io/io_block.h>
 #include <drivers/io/io_driver.h>
+#include <drivers/io/io_encrypted.h>
 #include <drivers/io/io_fip.h>
 #include <drivers/io/io_memmap.h>
 #include <drivers/io/io_mtd.h>
@@ -48,6 +49,11 @@
 
 static const io_dev_connector_t *fip_dev_con;
 
+#ifndef DECRYPTION_SUPPORT_none
+static const io_dev_connector_t *enc_dev_con;
+uintptr_t enc_dev_handle;
+#endif
+
 #if STM32MP_SDMMC || STM32MP_EMMC
 static struct mmc_device_info mmc_info;
 
@@ -118,6 +124,29 @@
 	return io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_ID);
 }
 
+#ifndef DECRYPTION_SUPPORT_none
+int open_enc_fip(const uintptr_t spec)
+{
+	int result;
+	uintptr_t local_image_handle;
+
+	result = io_dev_init(enc_dev_handle, (uintptr_t)ENC_IMAGE_ID);
+	if (result != 0) {
+		return result;
+	}
+
+	result = io_open(enc_dev_handle, spec, &local_image_handle);
+	if (result != 0) {
+		return result;
+	}
+
+	VERBOSE("Using encrypted FIP\n");
+	io_close(local_image_handle);
+
+	return 0;
+}
+#endif
+
 int open_storage(const uintptr_t spec)
 {
 	return io_dev_init(storage_dev_handle, 0);
@@ -383,6 +412,15 @@
 	io_result = io_dev_open(fip_dev_con, (uintptr_t)NULL,
 				&fip_dev_handle);
 
+#ifndef DECRYPTION_SUPPORT_none
+	io_result = register_io_dev_enc(&enc_dev_con);
+	assert(io_result == 0);
+
+	io_result = io_dev_open(enc_dev_con, (uintptr_t)NULL,
+				&enc_dev_handle);
+	assert(io_result == 0);
+#endif
+
 	switch (boot_context->boot_interface_selected) {
 #if STM32MP_SDMMC
 	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_SD:
diff --git a/plat/st/common/include/stm32mp_auth.h b/plat/st/common/include/stm32mp_auth.h
deleted file mode 100644
index 3075d18..0000000
--- a/plat/st/common/include/stm32mp_auth.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#ifndef STM32MP_AUTH_H
-#define STM32MP_AUTH_H
-
-struct stm32mp_auth_ops {
-	uint32_t (*check_key)(uint8_t *pubkey_in, uint8_t *pubkey_out);
-	uint32_t (*verify_signature)(uint8_t *hash_in, uint8_t *pubkey_in,
-				     uint8_t *signature, uint32_t ecc_algo);
-};
-
-void stm32mp_init_auth(struct stm32mp_auth_ops *init_ptr);
-int stm32mp_auth_image(boot_api_image_header_t *header, uintptr_t buffer);
-
-#endif /* STM32MP_AUTH_H */
diff --git a/plat/st/common/include/stm32mp_common.h b/plat/st/common/include/stm32mp_common.h
index 79f81db..b8f6daf 100644
--- a/plat/st/common/include/stm32mp_common.h
+++ b/plat/st/common/include/stm32mp_common.h
@@ -109,16 +109,6 @@
 /* Initialise the IO layer and register platform IO devices */
 void stm32mp_io_setup(void);
 
-#if STM32MP_USE_STM32IMAGE
-/*
- * Check that the STM32 header of a .stm32 binary image is valid
- * @param header: pointer to the stm32 image header
- * @param buffer: address of the binary image (payload)
- * @return: 0 on success, negative value in case of error
- */
-int stm32mp_check_header(boot_api_image_header_t *header, uintptr_t buffer);
-#endif /* STM32MP_USE_STM32IMAGE */
-
 /* Functions to map DDR in MMU with non-cacheable attribute, and unmap it */
 int stm32mp_map_ddr_non_cacheable(void);
 int stm32mp_unmap_ddr(void);
diff --git a/plat/st/common/include/stm32mp_io_storage.h b/plat/st/common/include/stm32mp_io_storage.h
index 989c890..3c04c47 100644
--- a/plat/st/common/include/stm32mp_io_storage.h
+++ b/plat/st/common/include/stm32mp_io_storage.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2021-2022, STMicroelectronics - All Rights Reserved
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -13,11 +13,15 @@
 /* IO devices handle */
 extern uintptr_t storage_dev_handle;
 extern uintptr_t fip_dev_handle;
+extern uintptr_t enc_dev_handle;
 
 extern io_block_spec_t image_block_spec;
 
 /* Function declarations */
 int open_fip(const uintptr_t spec);
+#ifndef DECRYPTION_SUPPORT_none
+int open_enc_fip(const uintptr_t spec);
+#endif
 int open_storage(const uintptr_t spec);
 
 #endif /* STM32MP_IO_STORAGE_H */
diff --git a/plat/st/common/stm32mp_auth.c b/plat/st/common/stm32mp_auth.c
deleted file mode 100644
index 97fbffa..0000000
--- a/plat/st/common/stm32mp_auth.c
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright (c) 2019-2022, STMicroelectronics - All Rights Reserved
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#include <errno.h>
-
-#include <common/debug.h>
-#include <drivers/io/io_storage.h>
-#include <drivers/st/bsec.h>
-#include <drivers/st/stm32_hash.h>
-#include <lib/xlat_tables/xlat_tables_v2.h>
-#include <plat/common/platform.h>
-
-#include <platform_def.h>
-
-static const struct stm32mp_auth_ops *auth_ops;
-
-void stm32mp_init_auth(struct stm32mp_auth_ops *init_ptr)
-{
-	if ((init_ptr == NULL) ||
-	    (init_ptr->check_key == NULL) ||
-	    (init_ptr->verify_signature == NULL) ||
-	    (stm32_hash_register() != 0)) {
-		panic();
-	}
-
-	auth_ops = init_ptr;
-}
-
-int stm32mp_auth_image(boot_api_image_header_t *header, uintptr_t buffer)
-{
-	int ret;
-	uint8_t image_hash[BOOT_API_SHA256_DIGEST_SIZE_IN_BYTES];
-	uint32_t header_skip_cksum = sizeof(header->magic) +
-				     sizeof(header->image_signature) +
-				     sizeof(header->payload_checksum);
-
-	/* Check Security Status */
-	if (!stm32mp_is_closed_device()) {
-		if (header->option_flags != 0U) {
-			WARN("Skip signature check (header option)\n");
-			return 0;
-		}
-		INFO("Check signature on Open device\n");
-	}
-
-	if (auth_ops == NULL) {
-		ERROR("Device doesn't support image authentication\n");
-		return -EOPNOTSUPP;
-	}
-
-	ret = mmap_add_dynamic_region(STM32MP_ROM_BASE, STM32MP_ROM_BASE,
-				      STM32MP_ROM_SIZE_2MB_ALIGNED, MT_CODE | MT_SECURE);
-	if (ret != 0) {
-		return ret;
-	}
-
-	/* Check Public Key */
-	if (auth_ops->check_key(header->ecc_pubk, NULL) != BOOT_API_RETURN_OK) {
-		ret = -EINVAL;
-		goto err;
-	}
-
-	/* Compute end of header hash and payload hash */
-	stm32_hash_init(HASH_SHA256);
-
-	ret = stm32_hash_update((uint8_t *)&header->header_version,
-				sizeof(boot_api_image_header_t) -
-				header_skip_cksum);
-	if (ret != 0) {
-		ERROR("Hash of header failed, %i\n", ret);
-		goto err;
-	}
-
-	ret = stm32_hash_final_update((uint8_t *)buffer,
-			       header->image_length, image_hash);
-	if (ret != 0) {
-		ERROR("Hash of payload failed\n");
-		goto err;
-	}
-
-	/* Verify signature */
-	if (auth_ops->verify_signature(image_hash, header->ecc_pubk,
-				       header->image_signature,
-				       header->ecc_algo_type) !=
-	    BOOT_API_RETURN_OK) {
-		ret = -EINVAL;
-	}
-
-err:
-	mmap_remove_dynamic_region(STM32MP_ROM_BASE, STM32MP_ROM_SIZE_2MB_ALIGNED);
-	return ret;
-}
diff --git a/plat/st/common/stm32mp_crypto_lib.c b/plat/st/common/stm32mp_crypto_lib.c
new file mode 100644
index 0000000..d644242
--- /dev/null
+++ b/plat/st/common/stm32mp_crypto_lib.c
@@ -0,0 +1,661 @@
+/*
+ * Copyright (c) 2022, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <endian.h>
+#include <errno.h>
+
+#include <common/debug.h>
+#include <drivers/auth/crypto_mod.h>
+#include <drivers/io/io_storage.h>
+#include <drivers/st/bsec.h>
+#include <drivers/st/stm32_hash.h>
+#include <drivers/st/stm32_pka.h>
+#include <drivers/st/stm32_rng.h>
+#include <drivers/st/stm32_saes.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+#include <mbedtls/asn1.h>
+#include <mbedtls/md.h>
+#include <mbedtls/oid.h>
+#include <mbedtls/platform.h>
+#include <mbedtls/x509.h>
+#include <plat/common/platform.h>
+#include <tools_share/firmware_encrypted.h>
+
+#include <platform_def.h>
+
+#define CRYPTO_HASH_MAX_SIZE	32U
+#define CRYPTO_SIGN_MAX_SIZE	64U
+#define CRYPTO_PUBKEY_MAX_SIZE	64U
+#define CRYPTO_MAX_TAG_SIZE	16U
+
+/* brainpoolP256t1 OID is not defined in mbedTLS */
+#define OID_EC_GRP_BP256T1          MBEDTLS_OID_EC_BRAINPOOL_V1 "\x08"
+
+#if STM32MP_CRYPTO_ROM_LIB
+struct stm32mp_auth_ops {
+	uint32_t (*verify_signature)(uint8_t *hash_in, uint8_t *pubkey_in,
+				     uint8_t *signature, uint32_t ecc_algo);
+};
+
+static struct stm32mp_auth_ops auth_ops;
+#endif
+
+static void crypto_lib_init(void)
+{
+	boot_api_context_t *boot_context __maybe_unused;
+	int ret;
+
+	NOTICE("TRUSTED_BOARD_BOOT support enabled\n");
+
+	ret = stm32_hash_register();
+	if (ret != 0) {
+		ERROR("HASH init (%d)\n", ret);
+		panic();
+	}
+
+	if (stm32mp_is_closed_device() || stm32mp_is_auth_supported()) {
+#if STM32MP_CRYPTO_ROM_LIB
+		boot_context = (boot_api_context_t *)stm32mp_get_boot_ctx_address();
+		auth_ops.verify_signature = boot_context->bootrom_ecdsa_verify_signature;
+#else
+		/* Use hardware peripherals */
+		if (stm32_rng_init() != 0) {
+			panic();
+		}
+
+		if (stm32_saes_driver_init() != 0) {
+			panic();
+		}
+
+		if (stm32_pka_init() != 0) {
+			panic();
+		}
+#endif
+	}
+}
+
+int get_plain_pk_from_asn1(void *pk_ptr, unsigned int pk_len, void **plain_pk,
+			   unsigned int *len, int *pk_alg)
+{
+	int ret;
+	mbedtls_pk_context mbedtls_pk = {0};
+	unsigned char *p, *end;
+	mbedtls_asn1_buf alg_params = {0};
+	mbedtls_asn1_buf alg_oid = {0};
+
+	*plain_pk = NULL;
+	*len = 0U;
+
+	/* Parse the public key */
+	mbedtls_pk_init(&mbedtls_pk);
+	p = (unsigned char *)pk_ptr;
+	end = (unsigned char *)(p + pk_len);
+
+	ret =  mbedtls_asn1_get_tag(&p, end, len,
+				    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
+	if (ret != 0) {
+		return -EINVAL;
+	}
+
+	end = p + *len;
+	ret = mbedtls_asn1_get_alg(&p, end, &alg_oid, &alg_params);
+	if (ret != 0) {
+		VERBOSE("%s: mbedtls_asn1_get_alg (%d)\n", __func__, ret);
+		return -EINVAL;
+	}
+
+	if (pk_alg != NULL) {
+		if ((strlen(MBEDTLS_OID_EC_GRP_SECP256R1) == alg_params.len) &&
+		    (memcmp(MBEDTLS_OID_EC_GRP_SECP256R1, alg_params.p, alg_params.len) == 0)) {
+			*pk_alg = BOOT_API_ECDSA_ALGO_TYPE_P256NIST;
+		} else if ((strlen(OID_EC_GRP_BP256T1) == alg_params.len) &&
+		    (memcmp(OID_EC_GRP_BP256T1, alg_params.p, alg_params.len) == 0)) {
+			*pk_alg = BOOT_API_ECDSA_ALGO_TYPE_BRAINPOOL256;
+		} else {
+			ERROR("%s: Algorithm is not supported\n", __func__);
+			return -EINVAL;
+		}
+	}
+
+	ret = mbedtls_asn1_get_bitstring_null(&p, end, len);
+	if (ret != 0) {
+		VERBOSE("%s: mbedtls_asn1_get_bitstring_null (%d)\n", __func__, ret);
+		return -EINVAL;
+	}
+
+	/* We remove the ident (0x04) first byte. */
+	if ((*len < 1U) || (p[0] !=  MBEDTLS_ASN1_OCTET_STRING)) {
+		VERBOSE("%s: not expected len or tag\n", __func__);
+		return -EINVAL;
+	}
+
+	*len = *len - 1U;
+	*plain_pk = p + 1U;
+
+	return 0;
+}
+
+#if STM32MP_CRYPTO_ROM_LIB
+uint32_t verify_signature(uint8_t *hash_in, uint8_t *pubkey_in,
+			  uint8_t *signature, uint32_t ecc_algo)
+{
+	int ret;
+
+	ret = mmap_add_dynamic_region(STM32MP_ROM_BASE, STM32MP_ROM_BASE,
+				      STM32MP_ROM_SIZE_2MB_ALIGNED, MT_CODE | MT_SECURE);
+	if (ret != 0) {
+		VERBOSE("%s: mmap_add_dynamic_region (%d)\n", __func__, ret);
+		return CRYPTO_ERR_SIGNATURE;
+	}
+
+	ret = auth_ops.verify_signature(hash_in, pubkey_in, signature, ecc_algo);
+
+	if (ret != BOOT_API_RETURN_OK) {
+		VERBOSE("%s: auth_ops.verify_sign (%d)\n", __func__, ret);
+		ret = CRYPTO_ERR_SIGNATURE;
+	} else {
+		ret = 0;
+	}
+
+	mmap_remove_dynamic_region(STM32MP_ROM_BASE, STM32MP_ROM_SIZE_2MB_ALIGNED);
+
+	return ret;
+}
+
+int plat_convert_pk(void *full_pk_ptr, unsigned int full_pk_len,
+		    void **hashed_pk_ptr, unsigned int *hashed_pk_len)
+{
+	return get_plain_pk_from_asn1(full_pk_ptr, full_pk_len, hashed_pk_ptr, hashed_pk_len, NULL);
+}
+#else /* STM32MP_CRYPTO_ROM_LIB*/
+static uint32_t verify_signature(uint8_t *hash_in, uint8_t *pubkey_in,
+				 uint8_t *signature, uint32_t ecc_algo)
+{
+	int ret = -1;
+	enum stm32_pka_ecdsa_curve_id cid;
+
+	switch (ecc_algo) {
+	case BOOT_API_ECDSA_ALGO_TYPE_P256NIST:
+#if PKA_USE_NIST_P256
+		cid = PKA_NIST_P256;
+		ret = 0;
+#else
+		WARN("%s nist_p256 requested but not included\n", __func__);
+#endif
+		break;
+	case BOOT_API_ECDSA_ALGO_TYPE_BRAINPOOL256:
+#if PKA_USE_BRAINPOOL_P256T1
+		cid = PKA_BRAINPOOL_P256T1;
+		ret = 0;
+#else
+		WARN("%s brainpool_p256t1 requested but not included\n", __func__);
+#endif
+		break;
+	default:
+		WARN("%s unexpected ecc_algo(%u)\n", __func__, ecc_algo);
+		break;
+	}
+
+	if (ret < 0) {
+		return CRYPTO_ERR_SIGNATURE;
+	}
+
+	ret = stm32_pka_ecdsa_verif(hash_in,
+				    BOOT_API_SHA256_DIGEST_SIZE_IN_BYTES,
+				    signature, BOOT_API_ECDSA_SIGNATURE_LEN_IN_BYTES / 2U,
+				    signature + BOOT_API_ECDSA_SIGNATURE_LEN_IN_BYTES / 2U,
+				    BOOT_API_ECDSA_SIGNATURE_LEN_IN_BYTES / 2U,
+				    pubkey_in, BOOT_API_ECDSA_PUB_KEY_LEN_IN_BYTES / 2U,
+				    pubkey_in + BOOT_API_ECDSA_PUB_KEY_LEN_IN_BYTES / 2U,
+				    BOOT_API_ECDSA_PUB_KEY_LEN_IN_BYTES / 2U, cid);
+	if (ret < 0) {
+		return CRYPTO_ERR_SIGNATURE;
+	}
+
+	return 0;
+}
+
+int plat_convert_pk(void *full_pk_ptr, unsigned int full_pk_len,
+		    void **hashed_pk_ptr, unsigned int *hashed_pk_len)
+{
+	static uint8_t st_pk[CRYPTO_PUBKEY_MAX_SIZE + sizeof(uint32_t)];
+	int ret;
+	void *plain_pk;
+	unsigned int len;
+	int curve_id;
+	uint32_t cid;
+
+	ret = get_plain_pk_from_asn1(full_pk_ptr, full_pk_len, &plain_pk, &len, &curve_id);
+	if ((ret != 0) || (len > CRYPTO_PUBKEY_MAX_SIZE))  {
+		return -EINVAL;
+	}
+
+	cid = curve_id; /* we want value of curve_id (1 or 2) in a uint32_t */
+
+	memcpy(st_pk, &cid, sizeof(cid));
+	memcpy(st_pk + sizeof(cid), plain_pk, len);
+
+	*hashed_pk_ptr = st_pk;
+	*hashed_pk_len = len + sizeof(cid);
+
+	return 0;
+}
+#endif /* STM32MP_CRYPTO_ROM_LIB */
+
+static int get_plain_digest_from_asn1(void *digest_ptr, unsigned int digest_len,
+				      uint8_t **out, size_t *out_len, mbedtls_md_type_t *md_alg)
+{
+	int ret;
+	mbedtls_asn1_buf hash_oid, params;
+	size_t len;
+	unsigned char *p, *end;
+
+	*out = NULL;
+	*out_len = 0U;
+
+	/* Digest info should be an MBEDTLS_ASN1_SEQUENCE */
+	p = (unsigned char *)digest_ptr;
+	end = p + digest_len;
+	ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED |
+				   MBEDTLS_ASN1_SEQUENCE);
+	if (ret != 0) {
+		return ret;
+	}
+
+	/* Get the hash algorithm */
+	ret = mbedtls_asn1_get_alg(&p, end, &hash_oid, &params);
+	if (ret != 0) {
+		return ret;
+	}
+
+	ret = mbedtls_oid_get_md_alg(&hash_oid, md_alg);
+	if (ret != 0) {
+		return ret;
+	}
+
+	ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING);
+	if (ret != 0) {
+		return ret;
+	}
+
+	/* Length of hash must match the algorithm's size */
+	if (len != BOOT_API_SHA256_DIGEST_SIZE_IN_BYTES) {
+		return -1;
+	}
+
+	*out = p;
+	*out_len = len;
+
+	return 0;
+}
+
+static int crypto_verify_signature(void *data_ptr, unsigned int data_len,
+				   void *sig_ptr, unsigned int sig_len,
+				   void *sig_alg, unsigned int sig_alg_len,
+				   void *pk_ptr, unsigned int pk_len)
+{
+	uint8_t image_hash[CRYPTO_HASH_MAX_SIZE] = {0};
+	uint8_t sig[CRYPTO_SIGN_MAX_SIZE];
+	uint8_t my_pk[CRYPTO_PUBKEY_MAX_SIZE];
+	int ret;
+	size_t len;
+	mbedtls_asn1_sequence seq;
+	mbedtls_asn1_sequence *cur;
+	unsigned char *p, *end;
+	int curve_id;
+	mbedtls_asn1_buf sig_oid, sig_params;
+	mbedtls_md_type_t md_alg;
+	mbedtls_pk_type_t pk_alg;
+	size_t bignum_len = sizeof(sig) / 2U;
+	unsigned int seq_num = 0U;
+
+	if (!stm32mp_is_closed_device() && !stm32mp_is_auth_supported()) {
+		return CRYPTO_SUCCESS;
+	}
+
+	/* Get pointers to signature OID and parameters */
+	p = (unsigned char *)sig_alg;
+	end = (unsigned char *)(p + sig_alg_len);
+	ret = mbedtls_asn1_get_alg(&p, end, &sig_oid, &sig_params);
+	if (ret != 0) {
+		VERBOSE("%s: mbedtls_asn1_get_alg (%d)\n", __func__, ret);
+		return CRYPTO_ERR_SIGNATURE;
+	}
+
+	/* Get the actual signature algorithm (MD + PK) */
+	ret = mbedtls_oid_get_sig_alg(&sig_oid, &md_alg, &pk_alg);
+	if (ret != 0) {
+		VERBOSE("%s: mbedtls_oid_get_sig_alg (%d)\n", __func__, ret);
+		return CRYPTO_ERR_SIGNATURE;
+	}
+
+	if ((md_alg != MBEDTLS_MD_SHA256) || (pk_alg != MBEDTLS_PK_ECDSA)) {
+		VERBOSE("%s: md_alg=%u pk_alg=%u\n", __func__, md_alg, pk_alg);
+		return CRYPTO_ERR_SIGNATURE;
+	}
+
+	ret = get_plain_pk_from_asn1(pk_ptr, pk_len, &pk_ptr, &pk_len, &curve_id);
+	if (ret != 0) {
+		VERBOSE("%s: get_plain_pk_from_asn1 (%d)\n", __func__, ret);
+		return CRYPTO_ERR_SIGNATURE;
+	}
+
+	/* We expect a known pk_len */
+	if (pk_len != sizeof(my_pk)) {
+		VERBOSE("%s: pk_len=%u sizeof(my_pk)=%zu)\n", __func__, pk_len, sizeof(my_pk));
+		return CRYPTO_ERR_SIGNATURE;
+	}
+
+	/* Need to copy as auth_ops.verify_signature
+	 * expects aligned public key.
+	 */
+	memcpy(my_pk, pk_ptr, sizeof(my_pk));
+
+	/* Get the signature (bitstring) */
+	p = (unsigned char *)sig_ptr;
+	end = (unsigned char *)(p + sig_len);
+	ret = mbedtls_asn1_get_bitstring_null(&p, end, &len);
+	if (ret != 0) {
+		VERBOSE("%s: mbedtls_asn1_get_bitstring_null (%d)\n", __func__, ret);
+		return CRYPTO_ERR_SIGNATURE;
+	}
+
+	/* Get r and s from sequence */
+	ret = mbedtls_asn1_get_sequence_of(&p, end, &seq, MBEDTLS_ASN1_INTEGER);
+	if (ret != 0) {
+		VERBOSE("%s: mbedtls_asn1_get_sequence_of (%d)\n", __func__, ret);
+		return CRYPTO_ERR_SIGNATURE;
+	}
+
+	/* We expect only 2 integers (r and s) from the sequence */
+	if (seq.next->next != NULL) {
+		cur = seq.next;
+		mbedtls_asn1_sequence *next;
+
+		VERBOSE("%s: nb seq != 2\n", __func__);
+		/* Free all the sequences */
+		while (cur != NULL) {
+			next = cur->next;
+			mbedtls_free(cur);
+			cur = next;
+		}
+
+		return CRYPTO_ERR_SIGNATURE;
+	}
+
+	/*
+	 * ECDSA signatures are composed of a tuple (R,S) where R and S are between 0 and n.
+	 * This means that the R and S can have a maximum of 32 each, but can also be smaller.
+	 * Also seen the integer sequence may (sometime) start with 0x00 as MSB, but we can only
+	 * manage exactly 2*32 bytes, we remove this higher byte if there are not 00,
+	 * we will fail either.
+	 */
+	cur = &seq;
+	memset(sig, 0U, sizeof(sig));
+
+	while (cur != NULL) {
+		size_t skip = 0U;
+		size_t seek = seq_num * bignum_len;
+
+		if (cur->buf.len > bignum_len) {
+			/* Remove extra 0x00 bytes */
+			skip = cur->buf.len - bignum_len;
+		} else if (cur->buf.len < bignum_len) {
+			/* Add padding to match HW required size */
+			seek += (bignum_len % cur->buf.len);
+		}
+
+		if (seek + cur->buf.len > sizeof(sig) + skip) {
+			panic();
+		}
+
+		memcpy(sig + seek, cur->buf.p + skip, cur->buf.len - skip);
+		cur = cur->next;
+		seq_num++;
+	}
+
+	/* Need to free allocated 'next' in mbedtls_asn1_get_sequence_of */
+	mbedtls_free(seq.next);
+
+	/* Compute hash for the data covered by the signature */
+	stm32_hash_init(HASH_SHA256);
+
+	ret = stm32_hash_final_update((uint8_t *)data_ptr, data_len, image_hash);
+	if (ret != 0) {
+		VERBOSE("%s: stm32_hash_final_update (%d)\n", __func__, ret);
+		return CRYPTO_ERR_SIGNATURE;
+	}
+
+	return verify_signature(image_hash, my_pk, sig, curve_id);
+}
+
+static int crypto_verify_hash(void *data_ptr, unsigned int data_len,
+			      void *digest_info_ptr,
+			      unsigned int digest_info_len)
+{
+	int ret;
+	uint8_t calc_hash[BOOT_API_SHA256_DIGEST_SIZE_IN_BYTES];
+	unsigned char *p;
+	mbedtls_md_type_t md_alg;
+	size_t len;
+
+	/* we receive an asn1 encapsulated digest, we flatten it */
+	ret = get_plain_digest_from_asn1(digest_info_ptr,
+					 digest_info_len, &p, &len,
+					 &md_alg);
+	if ((ret != 0) || (md_alg != MBEDTLS_MD_SHA256) || (len != sizeof(calc_hash))) {
+		return CRYPTO_ERR_HASH;
+	}
+
+	digest_info_ptr = p;
+	digest_info_len = len;
+
+	stm32_hash_init(HASH_SHA256);
+
+	ret = stm32_hash_final_update(data_ptr, data_len, calc_hash);
+	if (ret != 0) {
+		VERBOSE("%s: hash failed\n", __func__);
+		return CRYPTO_ERR_HASH;
+	}
+
+	ret = memcmp(calc_hash, digest_info_ptr, digest_info_len);
+	if (ret != 0) {
+		VERBOSE("%s: not expected digest\n", __func__);
+		ret = CRYPTO_ERR_HASH;
+	}
+
+	return ret;
+}
+
+#if !defined(DECRYPTION_SUPPORT_none)
+static int derive_key(uint8_t *key, size_t *key_len, size_t len,
+		      unsigned int *flags, const uint8_t *img_id, size_t img_id_len)
+{
+	size_t i, j;
+
+	assert(*key_len >= 32U);
+
+	/*
+	 * Not a real derivation yet
+	 *
+	 * But we expect a 32 bytes key, and OTP is only 16 bytes
+	 *   => duplicate.
+	 */
+	for (i = 0U, j = len; j < 32U;
+	     i += sizeof(uint32_t), j += sizeof(uint32_t)) {
+		memcpy(key + j, key + i, sizeof(uint32_t));
+	}
+
+	*key_len = 32U;
+	/* Variable 'key' store a real key */
+	*flags = 0U;
+
+	return 0;
+}
+
+int plat_get_enc_key_info(enum fw_enc_status_t fw_enc_status, uint8_t *key,
+			  size_t *key_len, unsigned int *flags,
+			  const uint8_t *img_id, size_t img_id_len)
+{
+	uint32_t otp_idx;
+	uint32_t otp_len;
+	size_t read_len;
+	size_t i;
+
+	if (fw_enc_status == FW_ENC_WITH_BSSK) {
+		return -EINVAL;
+	}
+
+	if (stm32_get_otp_index(ENCKEY_OTP, &otp_idx, &otp_len) != 0) {
+		VERBOSE("%s: get %s index error\n", __func__, ENCKEY_OTP);
+		return -EINVAL;
+	}
+
+	if (otp_len > (*key_len * CHAR_BIT)) {
+		VERBOSE("%s: length Error otp_len=%u key_len=%u\n", __func__,
+			otp_len, *key_len * CHAR_BIT);
+		return -EINVAL;
+	}
+
+	read_len = otp_len / CHAR_BIT;
+	assert(read_len % sizeof(uint32_t) == 0);
+
+	for (i = 0U; i < read_len / sizeof(uint32_t); i++) {
+		uint32_t tmp;
+		uint32_t otp_val;
+
+		if (stm32_get_otp_value_from_idx(otp_idx + i, &otp_val) != 0) {
+			zeromem(key, *key_len);
+			VERBOSE("%s: unable to read from otp\n", __func__);
+			return -EINVAL;
+		}
+
+		tmp = bswap32(otp_val);
+		memcpy(key + i * sizeof(uint32_t), &tmp, sizeof(tmp));
+	}
+
+	/* Now we have the OTP values in key till read_len */
+
+	if (derive_key(key, key_len, read_len, flags, img_id,
+		       img_id_len) != 0) {
+		zeromem(key, *key_len);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static enum stm32_saes_key_selection select_key(unsigned int key_flags)
+{
+	if ((key_flags & ENC_KEY_IS_IDENTIFIER) != 0U) {
+		panic();
+	}
+
+	/* Use the provided key buffer */
+	return STM32_SAES_KEY_SOFT;
+}
+
+static int stm32_decrypt_aes_gcm(void *data, size_t data_len,
+				 const void *key, unsigned int key_len,
+				 unsigned int key_flags,
+				 const void *iv, unsigned int iv_len,
+				 const void *tag, unsigned int tag_len)
+{
+	int ret;
+	struct stm32_saes_context ctx;
+	unsigned char tag_buf[CRYPTO_MAX_TAG_SIZE];
+	enum stm32_saes_key_selection key_mode;
+	unsigned int diff = 0U;
+	unsigned int i;
+
+	key_mode = select_key(key_flags);
+
+	ret = stm32_saes_init(&ctx, true, STM32_SAES_MODE_GCM, key_mode, key,
+			      key_len, iv, iv_len);
+	if (ret != 0) {
+		return CRYPTO_ERR_INIT;
+	}
+
+	ret = stm32_saes_update_assodata(&ctx, true, NULL, 0U);
+	if (ret != 0) {
+		return CRYPTO_ERR_DECRYPTION;
+	}
+
+	ret = stm32_saes_update_load(&ctx, true, data, data, data_len);
+	if (ret != 0) {
+		return CRYPTO_ERR_DECRYPTION;
+	}
+
+	ret = stm32_saes_final(&ctx, tag_buf, sizeof(tag_buf));
+	if (ret != 0) {
+		return CRYPTO_ERR_DECRYPTION;
+	}
+
+	/* Check tag in "constant-time" */
+	for (i = 0U; i < tag_len; i++) {
+		diff |= ((const unsigned char *)tag)[i] ^ tag_buf[i];
+	}
+
+	if (diff != 0U) {
+		return CRYPTO_ERR_DECRYPTION;
+	}
+
+	return CRYPTO_SUCCESS;
+}
+
+/*
+ * Authenticated decryption of an image
+ *
+ */
+static int crypto_auth_decrypt(enum crypto_dec_algo dec_algo, void *data_ptr, size_t len,
+			       const void *key, unsigned int key_len, unsigned int key_flags,
+			       const void *iv, unsigned int iv_len, const void *tag,
+			       unsigned int tag_len)
+{
+	int rc = -1;
+	uint32_t real_iv[4];
+
+	switch (dec_algo) {
+	case CRYPTO_GCM_DECRYPT:
+		/*
+		 * GCM expect a Nonce
+		 * The AES IV is the nonce (a uint32_t[3])
+		 * then a counter (a uint32_t big endian)
+		 * The counter starts at 2.
+		 */
+		memcpy(real_iv, iv, iv_len);
+		real_iv[3] = htobe32(0x2U);
+
+		rc = stm32_decrypt_aes_gcm(data_ptr, len, key, key_len, key_flags,
+					   real_iv, sizeof(real_iv), tag, tag_len);
+		break;
+	default:
+		rc = CRYPTO_ERR_DECRYPTION;
+		break;
+	}
+
+	if (rc != 0) {
+		return rc;
+	}
+
+	return CRYPTO_SUCCESS;
+}
+
+REGISTER_CRYPTO_LIB("stm32_crypto_lib",
+		    crypto_lib_init,
+		    crypto_verify_signature,
+		    crypto_verify_hash,
+		    crypto_auth_decrypt);
+
+#else /* No decryption support */
+REGISTER_CRYPTO_LIB("stm32_crypto_lib",
+		    crypto_lib_init,
+		    crypto_verify_signature,
+		    crypto_verify_hash,
+		    NULL);
+
+#endif
diff --git a/plat/st/common/stm32mp_fconf_io.c b/plat/st/common/stm32mp_fconf_io.c
index ca71958..0b6cc78 100644
--- a/plat/st/common/stm32mp_fconf_io.c
+++ b/plat/st/common/stm32mp_fconf_io.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2021-2022, STMicroelectronics - All Rights Reserved
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -42,6 +42,14 @@
 		.img_type_guid = STM32MP_FIP_GUID,
 		.check = open_storage
 	},
+#ifndef DECRYPTION_SUPPORT_none
+	[ENC_IMAGE_ID] = {
+		.dev_handle = &fip_dev_handle,
+		.image_spec = (uintptr_t)NULL,
+		.img_type_guid = NULL_GUID,
+		.check = open_fip
+	},
+#endif
 #if STM32MP_SDMMC || STM32MP_EMMC
 	[GPT_IMAGE_ID] = {
 		.dev_handle = &storage_dev_handle,
@@ -66,7 +74,16 @@
 #endif /* (STM32MP_SDMMC || STM32MP_EMMC) && PSA_FWU_SUPPORT */
 };
 
+#define DEFAULT_UUID_NUMBER	U(7)
+
-#define FCONF_ST_IO_UUID_NUMBER	U(8)
+#if TRUSTED_BOARD_BOOT
+#define TBBR_UUID_NUMBER	U(6)
+#else
+#define TBBR_UUID_NUMBER	U(0)
+#endif
+
+#define FCONF_ST_IO_UUID_NUMBER	(DEFAULT_UUID_NUMBER + \
+				 TBBR_UUID_NUMBER)
 
 static io_uuid_spec_t fconf_stm32mp_uuids[FCONF_ST_IO_UUID_NUMBER];
 static OBJECT_POOL_ARRAY(fconf_stm32mp_uuids_pool, fconf_stm32mp_uuids);
@@ -85,7 +102,14 @@
 	{BL33_IMAGE_ID, "bl33_uuid"},
 	{HW_CONFIG_ID, "hw_cfg_uuid"},
 	{TOS_FW_CONFIG_ID, "tos_fw_cfg_uuid"},
-	{NT_FW_CONFIG_ID, "nt_fw_cfg_uuid"},
+#if TRUSTED_BOARD_BOOT
+	{STM32MP_CONFIG_CERT_ID, "stm32mp_cfg_cert_uuid"},
+	{TRUSTED_KEY_CERT_ID, "t_key_cert_uuid"},
+	{TRUSTED_OS_FW_KEY_CERT_ID, "tos_fw_key_cert_uuid"},
+	{NON_TRUSTED_FW_KEY_CERT_ID, "nt_fw_key_cert_uuid"},
+	{TRUSTED_OS_FW_CONTENT_CERT_ID, "tos_fw_content_cert_uuid"},
+	{NON_TRUSTED_FW_CONTENT_CERT_ID, "nt_fw_content_cert_uuid"},
+#endif /* TRUSTED_BOARD_BOOT */
 };
 
 int fconf_populate_stm32mp_io_policies(uintptr_t config)
@@ -135,8 +159,20 @@
 
 		uuid_ptr->uuid = uuid_helper.uuid_struct;
 		policies[load_info[i].image_id].image_spec = (uintptr_t)uuid_ptr;
-		policies[load_info[i].image_id].dev_handle = &fip_dev_handle;
-		policies[load_info[i].image_id].check = open_fip;
+		switch (load_info[i].image_id) {
+#if ENCRYPT_BL32 && !defined(DECRYPTION_SUPPORT_none)
+		case BL32_IMAGE_ID:
+		case BL32_EXTRA1_IMAGE_ID:
+		case BL32_EXTRA2_IMAGE_ID:
+			policies[load_info[i].image_id].dev_handle = &enc_dev_handle;
+			policies[load_info[i].image_id].check = open_enc_fip;
+			break;
+#endif
+		default:
+			policies[load_info[i].image_id].dev_handle = &fip_dev_handle;
+			policies[load_info[i].image_id].check = open_fip;
+			break;
+		}
 	}
 
 	return 0;
diff --git a/plat/st/common/stm32mp_trusted_boot.c b/plat/st/common/stm32mp_trusted_boot.c
new file mode 100644
index 0000000..051d6fc
--- /dev/null
+++ b/plat/st/common/stm32mp_trusted_boot.c
@@ -0,0 +1,204 @@
+/*
+ * Copyright (c) 2022, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <endian.h>
+#include <errno.h>
+#include <limits.h>
+
+#include <common/debug.h>
+#include <common/tbbr/cot_def.h>
+#include <drivers/st/stm32_hash.h>
+#include <lib/fconf/fconf.h>
+#include <lib/fconf/fconf_dyn_cfg_getter.h>
+#include <lib/fconf/fconf_tbbr_getter.h>
+#include <lib/mmio.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+#include <plat/common/platform.h>
+
+#include <boot_api.h>
+#include <platform_def.h>
+
+#define HEADER_AND_EXT_TOTAL_SIZE 512
+
+static uint8_t der_sha256_header[] = {0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60,
+	0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20};
+static uint8_t root_pk_hash[HASH_DER_LEN];
+
+static int copy_hash_from_otp(const char *otp_name, uint8_t *hash, size_t len)
+{
+	uint32_t otp_idx;
+	uint32_t otp_len;
+	size_t i;
+	bool valid = false;
+
+	assert(len % sizeof(uint32_t) == 0);
+
+	if (stm32_get_otp_index(otp_name, &otp_idx, &otp_len) != 0) {
+		VERBOSE("%s: get %s index error\n", __func__, otp_name);
+		return -EINVAL;
+	}
+	if (otp_len != (len * CHAR_BIT)) {
+		VERBOSE("%s: length Error\n", __func__);
+		return -EINVAL;
+	}
+
+	for (i = 0U; i < len / sizeof(uint32_t); i++) {
+		uint32_t tmp;
+		uint32_t otp_val;
+		uint32_t first;
+
+		if (stm32_get_otp_value_from_idx(otp_idx + i, &otp_val) != 0) {
+			VERBOSE("%s: unable to read from otp\n", __func__);
+			return -EINVAL;
+		}
+
+		tmp = bswap32(otp_val);
+		memcpy(hash + i * sizeof(uint32_t), &tmp, sizeof(tmp));
+
+		if (i == 0U) {
+			first = tmp;
+		}
+
+		/*
+		 * Check if key hash values in OTP are 0 or 0xFFFFFFFFF
+		 * programmed : Invalid Key
+		 */
+		if (!stm32mp_is_closed_device() && !valid) {
+			if ((tmp != 0U) && (tmp != 0xFFFFFFFFU) && (tmp != first)) {
+				valid = true;
+			}
+		}
+	}
+
+	if (!stm32mp_is_closed_device() && !valid) {
+		return 0;
+	}
+
+	return len;
+}
+
+#if STM32_HEADER_VERSION_MAJOR == 1
+static int get_rotpk_hash(void *cookie, uint8_t *hash, size_t len)
+{
+	if (cookie != NULL) {
+		return -EINVAL;
+	}
+
+	return copy_hash_from_otp(PKH_OTP, hash, len);
+}
+#else
+static int get_rotpk_hash(void *cookie, uint8_t *hash, size_t len)
+{
+	int ret;
+	uint32_t pk_idx = 0U;
+	uint8_t calc_hash[BOOT_API_SHA256_DIGEST_SIZE_IN_BYTES];
+	uint8_t otp_hash[BOOT_API_SHA256_DIGEST_SIZE_IN_BYTES];
+	boot_api_image_header_t *hdr = (boot_api_image_header_t *)(SRAM3_BASE + SRAM3_SIZE -
+								   HEADER_AND_EXT_TOTAL_SIZE);
+	boot_extension_header_t *ext_header = (boot_extension_header_t *)hdr->ext_header;
+	boot_ext_header_params_authentication_t *param;
+
+	if (cookie != NULL) {
+		return -EINVAL;
+	}
+
+	if (hdr->header_version != BOOT_API_HEADER_VERSION) {
+		VERBOSE("%s: unexpected header_version\n", __func__);
+		return -EINVAL;
+	}
+
+	param = (boot_ext_header_params_authentication_t *)ext_header->params;
+
+	pk_idx = param->pk_idx;
+
+	stm32_hash_init(HASH_SHA256);
+	ret = stm32_hash_final_update((uint8_t *)param->pk_hashes,
+				      param->nb_pk * sizeof(boot_api_sha256_t), calc_hash);
+	if (ret != 0) {
+		VERBOSE("%s: hash failed\n", __func__);
+		return -EINVAL;
+	}
+
+	ret = copy_hash_from_otp(PKH_OTP, otp_hash, len);
+	if (ret < 0) {
+		return -EINVAL;
+	}
+
+	if (ret != 0) {
+		ret = memcmp(calc_hash, otp_hash, sizeof(calc_hash));
+		if (ret != 0) {
+			VERBOSE("%s: not expected digest\n", __func__);
+			return -EINVAL;
+		}
+
+		ret = sizeof(otp_hash);
+	}
+
+	memcpy(hash, param->pk_hashes[pk_idx], sizeof(otp_hash));
+
+	return ret;
+}
+#endif
+
+int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len,
+			unsigned int *flags)
+{
+	size_t start_copy_idx = 0U;
+	int res;
+
+	memcpy(root_pk_hash, der_sha256_header, sizeof(der_sha256_header));
+	start_copy_idx = sizeof(der_sha256_header);
+
+	res = get_rotpk_hash(cookie, root_pk_hash + start_copy_idx,
+			     BOOT_API_SHA256_DIGEST_SIZE_IN_BYTES);
+	if (res < 0) {
+		return -EINVAL;
+	}
+
+	*key_len = HASH_DER_LEN;
+	*key_ptr = &root_pk_hash;
+	*flags = ROTPK_IS_HASH;
+
+	if ((res == 0) && !stm32mp_is_closed_device()) {
+		*flags |= ROTPK_NOT_DEPLOYED;
+	}
+
+	return 0;
+}
+
+int plat_get_nv_ctr(void *cookie, unsigned int *nv_ctr)
+{
+	*nv_ctr = mmio_read_32(TAMP_BASE + TAMP_COUNTR);
+
+	return 0;
+}
+
+int plat_set_nv_ctr(void *cookie, unsigned int nv_ctr)
+{
+	while (mmio_read_32(TAMP_BASE + TAMP_COUNTR) != nv_ctr) {
+		mmio_write_32(TAMP_BASE + TAMP_COUNTR, 1U);
+	}
+
+	return 0;
+}
+
+int plat_get_mbedtls_heap(void **heap_addr, size_t *heap_size)
+{
+	assert(heap_addr != NULL);
+	assert(heap_size != NULL);
+
+#if STM32MP_USE_EXTERNAL_HEAP
+	/* Retrieve the already allocated heap's info from DTB */
+	*heap_addr = FCONF_GET_PROPERTY(tbbr, dyn_config, mbedtls_heap_addr);
+	*heap_size = FCONF_GET_PROPERTY(tbbr, dyn_config, mbedtls_heap_size);
+
+	/* We expect heap already statically mapped */
+
+	return 0;
+#else
+	return get_mbedtls_heap_helper(heap_addr, heap_size);
+#endif
+}
diff --git a/plat/st/stm32mp1/bl2_plat_setup.c b/plat/st/stm32mp1/bl2_plat_setup.c
index 5015f7d..c64a618 100644
--- a/plat/st/stm32mp1/bl2_plat_setup.c
+++ b/plat/st/stm32mp1/bl2_plat_setup.c
@@ -17,6 +17,7 @@
 #include <drivers/st/bsec.h>
 #include <drivers/st/regulator_fixed.h>
 #include <drivers/st/stm32_iwdg.h>
+#include <drivers/st/stm32_rng.h>
 #include <drivers/st/stm32_uart.h>
 #include <drivers/st/stm32mp1_clk.h>
 #include <drivers/st/stm32mp1_pwr.h>
@@ -47,10 +48,6 @@
 };
 #endif
 
-#if STM32MP15
-static struct stm32mp_auth_ops stm32mp1_auth_ops;
-#endif
-
 static void print_reset_reason(void)
 {
 	uint32_t rstsr = mmio_read_32(stm32mp_rcc_base() + RCC_MP_RSTSCLRR);
@@ -344,6 +341,14 @@
 	}
 
 skip_console_init:
+#if !TRUSTED_BOARD_BOOT
+	if (stm32mp_is_closed_device()) {
+		/* Closed chip mandates authentication */
+		ERROR("Secure chip: TRUSTED_BOARD_BOOT must be enabled\n");
+		panic();
+	}
+#endif
+
 	if (fixed_regulator_register() != 0) {
 		panic();
 	}
@@ -375,14 +380,9 @@
 		}
 	}
 
-#if STM32MP15
-	if (stm32mp_is_auth_supported()) {
-		stm32mp1_auth_ops.check_key =
-			boot_context->bootrom_ecdsa_check_key;
-		stm32mp1_auth_ops.verify_signature =
-			boot_context->bootrom_ecdsa_verify_signature;
-
-		stm32mp_init_auth(&stm32mp1_auth_ops);
+#if STM32MP13
+	if (stm32_rng_init() != 0) {
+		panic();
 	}
 #endif
 
diff --git a/plat/st/stm32mp1/cert_create_tbbr.mk b/plat/st/stm32mp1/cert_create_tbbr.mk
new file mode 100644
index 0000000..5b1a3ed
--- /dev/null
+++ b/plat/st/stm32mp1/cert_create_tbbr.mk
@@ -0,0 +1,19 @@
+#
+# Copyright (c) 2022, STMicroelectronics - All Rights Reserved
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# Override TBBR Cert to update generic certificate
+
+$(eval $(call add_define,PDEF_CERTS))
+
+PLAT_INCLUDE	+= -I${PLAT_DIR}include
+
+src/stm32mp1_tbb_cert.o: ${PLAT_DIR}stm32mp1_tbb_cert.c
+	${Q}${HOSTCC} -c ${HOSTCCFLAGS} ${INC_DIR} $< -o $@
+
+PLAT_OBJECTS	= src/stm32mp1_tbb_cert.o
+
+OBJECTS		+= $(PLAT_OBJECTS)
+
diff --git a/plat/st/stm32mp1/include/boot_api.h b/plat/st/stm32mp1/include/boot_api.h
index 7638418..1054609 100644
--- a/plat/st/stm32mp1/include/boot_api.h
+++ b/plat/st/stm32mp1/include/boot_api.h
@@ -232,21 +232,14 @@
 #if STM32MP15
 	/*
 	 * Pointers to bootROM External Secure Services
-	 * - ECDSA check key
 	 * - ECDSA verify signature
-	 * - ECDSA verify signature and go
 	 */
-	uint32_t (*bootrom_ecdsa_check_key)(uint8_t *pubkey_in,
-					    uint8_t *pubkey_out);
+	uint32_t reserved3;
 	uint32_t (*bootrom_ecdsa_verify_signature)(uint8_t *hash_in,
 						   uint8_t *pubkey_in,
 						   uint8_t *signature,
 						   uint32_t ecc_algo);
-	uint32_t (*bootrom_ecdsa_verify_and_go)(uint8_t *hash_in,
-						uint8_t *pub_key_in,
-						uint8_t *signature,
-						uint32_t ecc_algo,
-						uint32_t *entry_in);
+	uint32_t reserved4;
 #endif
 	/*
 	 * Information specific to an SD boot
@@ -340,6 +333,8 @@
 	uint32_t binary_type;
 	/* Pad up to 128 byte total size */
 	uint8_t pad[16];
+	/* Followed by extension header */
+	uint8_t ext_header[];
 #endif
 #if STM32MP15
 	/*
@@ -370,4 +365,45 @@
 #endif
 } __packed boot_api_image_header_t;
 
+typedef uint8_t boot_api_sha256_t[BOOT_API_SHA256_DIGEST_SIZE_IN_BYTES];
+
+typedef struct {
+	/* Extension header type:
+	 * BOOT_API_FSBL_DECRYPTION_HEADER_MAGIC_NB or
+	 * BOOT_API_AUTHENTICATION_HEADER_MAGIC_NB
+	 * BOOT_API_PADDING_HEADER_MAGIC_NB
+	 */
+	uint32_t type;
+	/* Extension header len in byte */
+	uint32_t len;
+	/* parameters of this extension */
+	uint8_t  params[];
+} __packed boot_extension_header_t;
+
+typedef struct {
+	/* Idx of ECDSA public key to be used in table */
+	uint32_t pk_idx;
+	/* Number of ECDSA public key in table */
+	uint32_t nb_pk;
+	/*
+	 * Type of ECC algorithm to use  :
+	 * value 1 : for P-256 NIST algorithm
+	 * value 2 : for Brainpool 256 algorithm
+	 * See definitions 'BOOT_API_ECDSA_ALGO_TYPE_XXX' above.
+	 */
+	uint32_t ecc_algo_type;
+	/* ECDSA public key to be used to check signature. */
+	uint8_t ecc_pubk[BOOT_API_ECDSA_PUB_KEY_LEN_IN_BYTES];
+	/* table of Hash of Algo+ECDSA public key */
+	boot_api_sha256_t pk_hashes[];
+} __packed boot_ext_header_params_authentication_t;
+
+typedef struct {
+	/* Size of encryption key (128 or 256) */
+	uint32_t key_size;
+	uint32_t derivation_cont;
+	/* 128 msb bits of plain payload SHA256 */
+	uint32_t hash[4];
+} __packed boot_ext_header_params_encrypted_fsbl_t;
+
 #endif /* BOOT_API_H */
diff --git a/plat/st/stm32mp1/include/plat_def_fip_uuid.h b/plat/st/stm32mp1/include/plat_def_fip_uuid.h
new file mode 100644
index 0000000..e5fbc2d
--- /dev/null
+++ b/plat/st/stm32mp1/include/plat_def_fip_uuid.h
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2021-2022, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_DEF_FIP_UUID_H
+#define PLAT_DEF_FIP_UUID_H
+
+#define UUID_STM32MP_CONFIG_CERT \
+	{{0x50, 0x1d, 0x8d, 0xd2}, {0x8b, 0xce}, {0x49, 0xa5}, 0x84, 0xeb, \
+	 {0x55, 0x9a, 0x9f, 0x2e, 0xae, 0xaf} }
+#endif /* PLAT_DEF_FIP_UUID_H */
+
diff --git a/plat/st/stm32mp1/include/plat_tbbr_img_def.h b/plat/st/stm32mp1/include/plat_tbbr_img_def.h
new file mode 100644
index 0000000..984aae8
--- /dev/null
+++ b/plat/st/stm32mp1/include/plat_tbbr_img_def.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2022, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef STM32MP1_IMG_DEF_H
+#define STM32MP1_IMG_DEF_H
+
+#include <export/common/tbbr/tbbr_img_def_exp.h>
+
+/* Undef the existing values */
+#undef BL32_EXTRA1_IMAGE_ID
+#undef BL32_EXTRA2_IMAGE_ID
+#undef TOS_FW_CONFIG_ID
+#undef TRUSTED_BOOT_FW_CERT_ID
+#undef FWU_METADATA_IMAGE_ID
+#undef BKUP_FWU_METADATA_IMAGE_ID
+#undef FW_CONFIG_ID
+#undef HW_CONFIG_ID
+#undef GPT_IMAGE_ID
+#undef ENC_IMAGE_ID
+
+/* Define the STM32MP1 used ID */
+#define FW_CONFIG_ID			U(1)
+#define HW_CONFIG_ID			U(2)
+#define GPT_IMAGE_ID			U(3)
+#define ENC_IMAGE_ID			U(6)
+#define BL32_EXTRA1_IMAGE_ID		U(8)
+#define BL32_EXTRA2_IMAGE_ID		U(9)
+#define FWU_METADATA_IMAGE_ID		U(12)
+#define BKUP_FWU_METADATA_IMAGE_ID	U(13)
+#define TOS_FW_CONFIG_ID		U(16)
+#define STM32MP_CONFIG_CERT_ID		U(17)
+
+/* Increase the MAX_NUMBER_IDS to match the authentication pool required */
+#define MAX_NUMBER_IDS			U(19)
+
+#endif	/* STM32MP1_IMG_DEF_H */
diff --git a/plat/st/stm32mp1/include/stm32mp1_mbedtls_config.h b/plat/st/stm32mp1/include/stm32mp1_mbedtls_config.h
new file mode 100644
index 0000000..2f07621
--- /dev/null
+++ b/plat/st/stm32mp1/include/stm32mp1_mbedtls_config.h
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2022, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef MBEDTLS_CONFIG_H
+#define MBEDTLS_CONFIG_H
+
+/*
+ * Key algorithms currently supported on mbed TLS libraries
+ */
+#define TF_MBEDTLS_USE_RSA	0
+#define TF_MBEDTLS_USE_ECDSA	1
+
+/*
+ * Hash algorithms currently supported on mbed TLS libraries
+ */
+#define TF_MBEDTLS_SHA256		1
+#define TF_MBEDTLS_SHA384		2
+#define TF_MBEDTLS_SHA512		3
+
+/*
+ * Configuration file to build mbed TLS with the required features for
+ * Trusted Boot
+ */
+
+#define MBEDTLS_PLATFORM_MEMORY
+#define MBEDTLS_PLATFORM_NO_STD_FUNCTIONS
+/* Prevent mbed TLS from using snprintf so that it can use tf_snprintf. */
+#define MBEDTLS_PLATFORM_SNPRINTF_ALT
+
+#define MBEDTLS_PKCS1_V21
+
+#define MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION
+#define MBEDTLS_X509_CHECK_KEY_USAGE
+#define MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE
+
+#define MBEDTLS_ASN1_PARSE_C
+#define MBEDTLS_ASN1_WRITE_C
+
+#define MBEDTLS_BASE64_C
+#define MBEDTLS_BIGNUM_C
+
+#define MBEDTLS_ERROR_C
+#define MBEDTLS_MD_C
+
+#define MBEDTLS_MEMORY_BUFFER_ALLOC_C
+#define MBEDTLS_OID_C
+
+#define MBEDTLS_PK_C
+#define MBEDTLS_PK_PARSE_C
+#define MBEDTLS_PK_WRITE_C
+
+#define MBEDTLS_PLATFORM_C
+
+#if TF_MBEDTLS_USE_ECDSA
+#define MBEDTLS_ECDSA_C
+#define MBEDTLS_ECP_C
+#define MBEDTLS_ECP_DP_SECP256R1_ENABLED
+#define MBEDTLS_ECP_NO_INTERNAL_RNG
+#endif
+#if TF_MBEDTLS_USE_RSA
+#define MBEDTLS_RSA_C
+#define MBEDTLS_X509_RSASSA_PSS_SUPPORT
+#endif
+
+#define MBEDTLS_SHA256_C
+#if (TF_MBEDTLS_HASH_ALG_ID != TF_MBEDTLS_SHA256)
+#define MBEDTLS_SHA512_C
+#endif
+
+#define MBEDTLS_VERSION_C
+
+#define MBEDTLS_X509_USE_C
+#define MBEDTLS_X509_CRT_PARSE_C
+
+#if TF_MBEDTLS_USE_AES_GCM
+#define MBEDTLS_AES_C
+#define MBEDTLS_CIPHER_C
+#define MBEDTLS_GCM_C
+#endif
+
+/* MPI / BIGNUM options */
+#define MBEDTLS_MPI_WINDOW_SIZE			2
+
+#if TF_MBEDTLS_USE_RSA
+#if TF_MBEDTLS_KEY_SIZE <= 2048
+#define MBEDTLS_MPI_MAX_SIZE			256
+#else
+#define MBEDTLS_MPI_MAX_SIZE			512
+#endif
+#else
+#define MBEDTLS_MPI_MAX_SIZE			256
+#endif
+
+/* Memory buffer allocator options */
+#define MBEDTLS_MEMORY_ALIGN_MULTIPLE		8
+
+/*
+ * Prevent the use of 128-bit division which
+ * creates dependency on external libraries.
+ */
+#define MBEDTLS_NO_UDBL_DIVISION
+
+#ifndef __ASSEMBLER__
+/* System headers required to build mbed TLS with the current configuration */
+#include <stdlib.h>
+#include <mbedtls/check_config.h>
+#endif
+
+/*
+ * Mbed TLS heap size is smal as we only use the asn1
+ * parsing functions
+ * digest, signature and crypto algorithm are done by
+ * other library.
+ */
+
+#define TF_MBEDTLS_HEAP_SIZE           U(5120)
+#endif /* MBEDTLS_CONFIG_H */
diff --git a/plat/st/stm32mp1/include/tbbr/stm32mp1_tbb_cert.h b/plat/st/stm32mp1/include/tbbr/stm32mp1_tbb_cert.h
new file mode 100644
index 0000000..2cc1e19
--- /dev/null
+++ b/plat/st/stm32mp1/include/tbbr/stm32mp1_tbb_cert.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef STM32MP1_TBB_CERT_H
+#define STM32MP1_TBB_CERT_H
+
+#include <tbbr/tbb_cert.h>
+
+/*
+ * Enumerate the certificates that are used to establish the chain of trust
+ */
+enum {
+	STM32MP_CONFIG_CERT = FWU_CERT + 1
+};
+
+#endif /* STM32MP1_TBB_CERT_H */
diff --git a/plat/st/stm32mp1/plat_def_uuid_config.c b/plat/st/stm32mp1/plat_def_uuid_config.c
new file mode 100644
index 0000000..efaf567
--- /dev/null
+++ b/plat/st/stm32mp1/plat_def_uuid_config.c
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2022, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <firmware_image_package.h>
+
+#include "tbbr_config.h"
+
+toc_entry_t plat_def_toc_entries[] = {
+	{
+		.name = "STM32MP CONFIG CERT",
+		.uuid = UUID_STM32MP_CONFIG_CERT,
+		.cmdline_name = "stm32mp-cfg-cert"
+	}
+};
+
diff --git a/plat/st/stm32mp1/plat_fiptool.mk b/plat/st/stm32mp1/plat_fiptool.mk
new file mode 100644
index 0000000..00570c2
--- /dev/null
+++ b/plat/st/stm32mp1/plat_fiptool.mk
@@ -0,0 +1,25 @@
+#
+# Copyright (c) 2021-2022, STMicroelectronics - All Rights Reserved
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# Name of the platform defined source file name,
+# which contains platform defined UUID entries populated
+# in the plat_def_toc_entries[].
+PLAT_DEF_UUID_FILE_NAME	:= plat_def_uuid_config
+
+INCLUDE_PATHS		+= -I${PLAT_DIR}/include -I./
+
+PLAT_DEF_UUID		:= yes
+
+ifeq (${PLAT_DEF_UUID},yes)
+HOSTCCFLAGS += -DPLAT_DEF_FIP_UUID
+
+${PLAT_DEF_UUID_FILE_NAME}.o: ${PLAT_DIR}${PLAT_DEF_UUID_FILE_NAME}.c
+	${HOSTCC} -c ${CPPFLAGS} ${HOSTCCFLAGS} ${INCLUDE_PATHS} $< -o $@
+
+PLAT_OBJECTS += ${PLAT_DEF_UUID_FILE_NAME}.o
+endif
+
+OBJECTS += ${PLAT_OBJECTS}
diff --git a/plat/st/stm32mp1/platform.mk b/plat/st/stm32mp1/platform.mk
index def2898..594fe0b 100644
--- a/plat/st/stm32mp1/platform.mk
+++ b/plat/st/stm32mp1/platform.mk
@@ -18,6 +18,12 @@
 # If it is set to 0, then FIP is used
 STM32MP_USE_STM32IMAGE	?=	0
 
+TRUSTED_BOARD_BOOT	?=	0
+STM32MP_USE_EXTERNAL_HEAP ?=	0
+
+# Use secure library from the ROM code for authentication
+STM32MP_CRYPTO_ROM_LIB	?=	0
+
 # Please don't increment this value without good understanding of
 # the monotonic counter
 STM32_TF_VERSION	?=	0
@@ -49,10 +55,19 @@
 endif
 
 ifeq ($(STM32MP13),1)
+# Will use SRAM2 as mbedtls heap
+STM32MP_USE_EXTERNAL_HEAP :=	1
+
 # DDR controller with single AXI port and 16-bit interface
 STM32MP_DDR_DUAL_AXI_PORT:=	0
 STM32MP_DDR_32BIT_INTERFACE:=	0
 
+ifeq (${TRUSTED_BOARD_BOOT},1)
+# PKA algo to include
+PKA_USE_NIST_P256	:=	1
+PKA_USE_BRAINPOOL_P256T1:=	1
+endif
+
 # STM32 image header version v2.0
 STM32_HEADER_VERSION_MAJOR:=	2
 STM32_HEADER_VERSION_MINOR:=	0
@@ -70,6 +85,13 @@
 # Add OP-TEE reserved shared memory area in mapping
 STM32MP15_OPTEE_RSV_SHM	:=	1
 $(eval $(call add_defines,STM32MP15_OPTEE_RSV_SHM))
+
+STM32MP_CRYPTO_ROM_LIB :=	1
+
+# Decryption support
+ifneq ($(DECRYPTION_SUPPORT),none)
+$(error "DECRYPTION_SUPPORT not supported on STM32MP15")
+endif
 endif
 
 # STM32 image header binary type for BL2
@@ -110,6 +132,14 @@
 endif
 endif
 
+ifeq ($(STM32MP13),1)
+STM32_HASH_VER		:=	4
+STM32_RNG_VER		:=	4
+else # Assuming STM32MP15
+STM32_HASH_VER		:=	2
+STM32_RNG_VER		:=	2
+endif
+
 # Boot devices
 STM32MP_EMMC		?=	0
 STM32MP_SDMMC		?=	0
@@ -184,6 +214,11 @@
 $(eval $(call TOOL_ADD_PAYLOAD,${STM32MP_FW_CONFIG},--fw-config))
 # Add the HW_CONFIG to FIP and specify the same to certtool
 $(eval $(call TOOL_ADD_PAYLOAD,${STM32MP_HW_CONFIG},--hw-config))
+ifeq ($(GENERATE_COT),1)
+STM32MP_CFG_CERT	:=	$(BUILD_PLAT)/stm32mp_cfg_cert.crt
+# Add the STM32MP_CFG_CERT to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${STM32MP_CFG_CERT},--stm32mp-cfg-cert))
+endif
 ifeq ($(AARCH32_SP),sp_min)
 STM32MP_TOS_FW_CONFIG	:= $(addprefix ${BUILD_PLAT}/fdts/, $(patsubst %.dtb,%-bl32.dtb,$(DTB_FILE_NAME)))
 $(eval $(call TOOL_ADD_PAYLOAD,${STM32MP_TOS_FW_CONFIG},--tos-fw-config))
@@ -191,10 +226,10 @@
 # Add the build options to pack Trusted OS Extra1 and Trusted OS Extra2 images
 # in the FIP if the platform requires.
 ifneq ($(BL32_EXTRA1),)
-$(eval $(call TOOL_ADD_IMG,BL32_EXTRA1,--tos-fw-extra1))
+$(eval $(call TOOL_ADD_IMG,BL32_EXTRA1,--tos-fw-extra1,,$(ENCRYPT_BL32)))
 endif
 ifneq ($(BL32_EXTRA2),)
-$(eval $(call TOOL_ADD_IMG,BL32_EXTRA2,--tos-fw-extra2))
+$(eval $(call TOOL_ADD_IMG,BL32_EXTRA2,--tos-fw-extra2,,$(ENCRYPT_BL32)))
 endif
 endif
 endif
@@ -202,7 +237,11 @@
 # Enable flags for C files
 $(eval $(call assert_booleans,\
 	$(sort \
+		PKA_USE_BRAINPOOL_P256T1 \
+		PKA_USE_NIST_P256 \
+		PLAT_TBBR_IMG_DEF \
 		PLAT_XLAT_TABLES_DYNAMIC \
+		STM32MP_CRYPTO_ROM_LIB \
 		STM32MP_DDR_32BIT_INTERFACE \
 		STM32MP_DDR_DUAL_AXI_PORT \
 		STM32MP_EARLY_CONSOLE \
@@ -215,6 +254,7 @@
 		STM32MP_SPI_NOR \
 		STM32MP_UART_PROGRAMMER \
 		STM32MP_USB_PROGRAMMER \
+		STM32MP_USE_EXTERNAL_HEAP \
 		STM32MP_USE_STM32IMAGE \
 		STM32MP13 \
 		STM32MP15 \
@@ -223,6 +263,9 @@
 $(eval $(call assert_numerics,\
 	$(sort \
 		PLAT_PARTITION_MAX_ENTRIES \
+		STM32_HASH_VER \
+		STM32_HEADER_VERSION_MAJOR \
+		STM32_RNG_VER \
 		STM32_TF_A_COPIES \
 		STM32_TF_VERSION \
 		STM32MP_UART_BAUDRATE \
@@ -231,10 +274,17 @@
 $(eval $(call add_defines,\
 	$(sort \
 		DWL_BUFFER_BASE \
+		PKA_USE_BRAINPOOL_P256T1 \
+		PKA_USE_NIST_P256 \
 		PLAT_PARTITION_MAX_ENTRIES \
+		PLAT_TBBR_IMG_DEF \
 		PLAT_XLAT_TABLES_DYNAMIC \
+		STM32_HASH_VER \
+		STM32_HEADER_VERSION_MAJOR \
+		STM32_RNG_VER \
 		STM32_TF_A_COPIES \
 		STM32_TF_VERSION \
+		STM32MP_CRYPTO_ROM_LIB \
 		STM32MP_DDR_32BIT_INTERFACE \
 		STM32MP_DDR_DUAL_AXI_PORT \
 		STM32MP_EARLY_CONSOLE \
@@ -248,6 +298,7 @@
 		STM32MP_UART_BAUDRATE \
 		STM32MP_UART_PROGRAMMER \
 		STM32MP_USB_PROGRAMMER \
+		STM32MP_USE_EXTERNAL_HEAP \
 		STM32MP_USE_STM32IMAGE \
 		STM32MP13 \
 		STM32MP15 \
@@ -302,7 +353,8 @@
 
 ifeq ($(STM32MP13),1)
 PLAT_BL_COMMON_SOURCES	+=	drivers/st/clk/clk-stm32-core.c				\
-				drivers/st/clk/clk-stm32mp13.c
+				drivers/st/clk/clk-stm32mp13.c				\
+				drivers/st/crypto/stm32_rng.c
 else
 PLAT_BL_COMMON_SOURCES	+=	drivers/st/clk/stm32mp1_clk.c
 endif
@@ -340,9 +392,47 @@
 				drivers/st/crypto/stm32_hash.c				\
 				plat/st/stm32mp1/bl2_plat_setup.c
 
+ifneq (${DECRYPTION_SUPPORT},none)
+BL2_SOURCES		+=	drivers/io/io_encrypted.c
+endif
 
-ifeq ($(STM32MP15),1)
-BL2_SOURCES		+=	plat/st/common/stm32mp_auth.c
+ifeq (${TRUSTED_BOARD_BOOT},1)
+AUTH_SOURCES		:=	drivers/auth/auth_mod.c					\
+				drivers/auth/crypto_mod.c				\
+				drivers/auth/img_parser_mod.c
+
+ifeq (${GENERATE_COT},1)
+TFW_NVCTR_VAL		:=	0
+NTFW_NVCTR_VAL		:=	0
+KEY_SIZE		:=
+KEY_ALG			:=	ecdsa
+HASH_ALG		:=	sha256
+
+ifeq (${SAVE_KEYS},1)
+TRUSTED_WORLD_KEY	?=	${BUILD_PLAT}/trusted.pem
+NON_TRUSTED_WORLD_KEY	?=	${BUILD_PLAT}/non-trusted.pem
+BL32_KEY		?=	${BUILD_PLAT}/trusted_os.pem
+BL33_KEY		?=	${BUILD_PLAT}/non-trusted_os.pem
+endif
+
+endif
+TF_MBEDTLS_KEY_ALG 	:=	ecdsa
+MBEDTLS_CONFIG_FILE	?=	"<stm32mp1_mbedtls_config.h>"
+
+include drivers/auth/mbedtls/mbedtls_x509.mk
+
+COT_DESC_IN_DTB		:=	1
+AUTH_SOURCES		+=	lib/fconf/fconf_cot_getter.c				\
+				lib/fconf/fconf_tbbr_getter.c				\
+				plat/st/common/stm32mp_crypto_lib.c
+
+ifeq ($(STM32MP13),1)
+AUTH_SOURCES		+=	drivers/st/crypto/stm32_pka.c
+AUTH_SOURCES		+=	drivers/st/crypto/stm32_saes.c
+endif
+
+BL2_SOURCES		+=	$(AUTH_SOURCES)						\
+				plat/st/common/stm32mp_trusted_boot.c
 endif
 
 ifneq ($(filter 1,${STM32MP_EMMC} ${STM32MP_SDMMC}),)
diff --git a/plat/st/stm32mp1/stm32mp1_def.h b/plat/st/stm32mp1/stm32mp1_def.h
index a74d58c..5d7c2ff 100644
--- a/plat/st/stm32mp1/stm32mp1_def.h
+++ b/plat/st/stm32mp1/stm32mp1_def.h
@@ -19,7 +19,6 @@
 #include <drivers/st/stm32mp1_clk.h>
 
 #include <boot_api.h>
-#include <stm32mp_auth.h>
 #include <stm32mp_common.h>
 #include <stm32mp_dt.h>
 #include <stm32mp1_dbgmcu.h>
@@ -451,6 +450,8 @@
 #endif
 #define MONOTONIC_OTP			"monotonic_otp"
 #define UID_OTP				"uid_otp"
+#define PKH_OTP				"pkh_otp"
+#define ENCKEY_OTP			"enckey_otp"
 #define BOARD_ID_OTP			"board_id"
 
 /* OTP mask */
@@ -551,6 +552,7 @@
  ******************************************************************************/
 #define TAMP_BASE			U(0x5C00A000)
 #define TAMP_BKP_REGISTER_BASE		(TAMP_BASE + U(0x100))
+#define TAMP_COUNTR			U(0x40)
 
 #if !(defined(__LINKER__) || defined(__ASSEMBLER__))
 static inline uintptr_t tamp_bkpr(uint32_t idx)
diff --git a/plat/st/stm32mp1/stm32mp1_fip_def.h b/plat/st/stm32mp1/stm32mp1_fip_def.h
index 5652597..4098386 100644
--- a/plat/st/stm32mp1/stm32mp1_fip_def.h
+++ b/plat/st/stm32mp1/stm32mp1_fip_def.h
@@ -15,14 +15,36 @@
 #define STM32MP_DDR_SHMEM_SIZE		U(0)		/* empty */
 #endif
 
+#if TRUSTED_BOARD_BOOT && !STM32MP_USE_EXTERNAL_HEAP
+#if STM32MP15
+#define STM32MP_BL2_RO_SIZE		U(0x00014000)	/* 80 KB */
+#define STM32MP_BL2_SIZE		U(0x0001B000)	/* 108 KB for BL2 */
+#endif /* STM32MP15 */
+#else /* TRUSTED_BOARD_BOOT && !STM32MP_USE_EXTERNAL_HEAP */
 #if STM32MP13
+#if BL2_IN_XIP_MEM
 #define STM32MP_BL2_RO_SIZE		U(0x00015000)	/* 84 KB */
 #define STM32MP_BL2_SIZE		U(0x00017000)	/* 92 KB for BL2 */
-#define STM32MP_BL2_DTB_SIZE		U(0x00004000)	/* 16 KB for DTB */
+#else
+/* STM32MP_BL2_RO_SIZE not used if !BL2_IN_XIP_MEM */
+#define STM32MP_BL2_SIZE		U(0x0001B000)	/* 108KB for BL2 */
+					/* with 20KB for DTB, SYSRAM is full */
+#endif
 #endif /* STM32MP13 */
 #if STM32MP15
 #define STM32MP_BL2_RO_SIZE		U(0x00011000)	/* 68 KB */
 #define STM32MP_BL2_SIZE		U(0x00016000)	/* 88 KB for BL2 */
+#endif /* STM32MP15 */
+#endif /* TRUSTED_BOARD_BOOT && !STM32MP_USE_EXTERNAL_HEAP */
+
+#if STM32MP13
+#if TRUSTED_BOARD_BOOT
+#define STM32MP_BL2_DTB_SIZE		U(0x00005000)	/* 20 KB for DTB */
+#else /* TRUSTED_BOARD_BOOT */
+#define STM32MP_BL2_DTB_SIZE		U(0x00004000)	/* 16 KB for DTB */
+#endif /* TRUSTED_BOARD_BOOT */
+#endif /* STM32MP13 */
+#if STM32MP15
 #define STM32MP_BL2_DTB_SIZE		U(0x00007000)	/* 28 KB for DTB */
 #endif /* STM32MP15 */
 #define STM32MP_BL32_SIZE		U(0x0001B000)	/* 108 KB for BL32 */
diff --git a/plat/st/stm32mp1/stm32mp1_tbb_cert.c b/plat/st/stm32mp1/stm32mp1_tbb_cert.c
new file mode 100644
index 0000000..0e77397
--- /dev/null
+++ b/plat/st/stm32mp1/stm32mp1_tbb_cert.c
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "tbbr/tbb_ext.h"
+#include "tbbr/tbb_key.h"
+
+#include "tbbr/stm32mp1_tbb_cert.h"
+
+/*
+ * Certificates used in the chain of trust
+ *
+ * The order of the certificates must follow the enumeration specified in
+ * stm32mp1_tbb_cert.h. All certificates are self-signed, so the issuer certificate
+ * field points to itself.
+ */
+static cert_t stm32mp1_tbb_certs[] = {
+	[0] = {
+		.id = STM32MP_CONFIG_CERT,
+		.opt = "stm32mp-cfg-cert",
+		.help_msg = "STM32MP Config Certificate (output file)",
+		.fn = NULL,
+		.cn = "STM32MP config FW Certificate",
+		.key = ROT_KEY,
+		.issuer = STM32MP_CONFIG_CERT,
+		.ext = {
+			TRUSTED_FW_NVCOUNTER_EXT,
+			HW_CONFIG_HASH_EXT,
+			FW_CONFIG_HASH_EXT
+		},
+		.num_ext = 3
+	},
+};
+
+PLAT_REGISTER_COT(stm32mp1_tbb_certs);
diff --git a/tools/cert_create/include/key.h b/tools/cert_create/include/key.h
index 0ef046b..312575b 100644
--- a/tools/cert_create/include/key.h
+++ b/tools/cert_create/include/key.h
@@ -22,7 +22,9 @@
 enum {
 	KEY_ALG_RSA,		/* RSA PSS as defined by PKCS#1 v2.1 (default) */
 #ifndef OPENSSL_NO_EC
-	KEY_ALG_ECDSA,
+	KEY_ALG_ECDSA_NIST,
+	KEY_ALG_ECDSA_BRAINPOOL_R,
+	KEY_ALG_ECDSA_BRAINPOOL_T,
 #endif /* OPENSSL_NO_EC */
 	KEY_ALG_MAX_NUM
 };
@@ -42,7 +44,9 @@
 static const unsigned int KEY_SIZES[KEY_ALG_MAX_NUM][KEY_SIZE_MAX_NUM] = {
 	{ 2048, 1024, 3072, 4096 },	/* KEY_ALG_RSA */
 #ifndef OPENSSL_NO_EC
-	{}				/* KEY_ALG_ECDSA */
+	{},				/* KEY_ALG_ECDSA_NIST */
+	{},				/* KEY_ALG_ECDSA_BRAINPOOL_R */
+	{}				/* KEY_ALG_ECDSA_BRAINPOOL_T */
 #endif /* OPENSSL_NO_EC */
 };
 
diff --git a/tools/cert_create/src/key.c b/tools/cert_create/src/key.c
index 0061b8a..487777b 100644
--- a/tools/cert_create/src/key.c
+++ b/tools/cert_create/src/key.c
@@ -93,20 +93,39 @@
 }
 
 #ifndef OPENSSL_NO_EC
-static int key_create_ecdsa(key_t *key, int key_bits)
-{
 #if USING_OPENSSL3
-	EVP_PKEY *ec = EVP_EC_gen("prime256v1");
+static int key_create_ecdsa(key_t *key, int key_bits, const char *curve)
+{
+	EVP_PKEY *ec = EVP_EC_gen(curve);
 	if (ec == NULL) {
 		printf("Cannot generate EC key\n");
 		return 0;
 	}
+
 	key->key = ec;
 	return 1;
+}
+
+static int key_create_ecdsa_nist(key_t *key, int key_bits)
+{
+	return key_create_ecdsa(key, key_bits, "prime256v1");
+}
+
+static int key_create_ecdsa_brainpool_r(key_t *key, int key_bits)
+{
+	return key_create_ecdsa(key, key_bits, "brainpoolP256r1");
+}
+
+static int key_create_ecdsa_brainpool_t(key_t *key, int key_bits)
+{
+	return key_create_ecdsa(key, key_bits, "brainpoolP256t1");
+}
 #else
+static int key_create_ecdsa(key_t *key, int key_bits, const int curve_id)
+{
 	EC_KEY *ec;
 
-	ec = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
+	ec = EC_KEY_new_by_curve_name(curve_id);
 	if (ec == NULL) {
 		printf("Cannot create EC key\n");
 		return 0;
@@ -127,15 +146,32 @@
 err:
 	EC_KEY_free(ec);
 	return 0;
-#endif
+}
+
+static int key_create_ecdsa_nist(key_t *key, int key_bits)
+{
+	return key_create_ecdsa(key, key_bits, NID_X9_62_prime256v1);
+}
+
+static int key_create_ecdsa_brainpool_r(key_t *key, int key_bits)
+{
+	return key_create_ecdsa(key, key_bits, NID_brainpoolP256r1);
+}
+
+static int key_create_ecdsa_brainpool_t(key_t *key, int key_bits)
+{
+	return key_create_ecdsa(key, key_bits, NID_brainpoolP256t1);
 }
+#endif /* USING_OPENSSL3 */
 #endif /* OPENSSL_NO_EC */
 
 typedef int (*key_create_fn_t)(key_t *key, int key_bits);
 static const key_create_fn_t key_create_fn[KEY_ALG_MAX_NUM] = {
-	key_create_rsa, 	/* KEY_ALG_RSA */
+	[KEY_ALG_RSA] = key_create_rsa,
 #ifndef OPENSSL_NO_EC
-	key_create_ecdsa, 	/* KEY_ALG_ECDSA */
+	[KEY_ALG_ECDSA_NIST] = key_create_ecdsa_nist,
+	[KEY_ALG_ECDSA_BRAINPOOL_R] = key_create_ecdsa_brainpool_r,
+	[KEY_ALG_ECDSA_BRAINPOOL_T] = key_create_ecdsa_brainpool_t,
 #endif /* OPENSSL_NO_EC */
 };
 
diff --git a/tools/cert_create/src/main.c b/tools/cert_create/src/main.c
index fe386b7..2ab6bcf 100644
--- a/tools/cert_create/src/main.c
+++ b/tools/cert_create/src/main.c
@@ -84,7 +84,9 @@
 static const char *key_algs_str[] = {
 	[KEY_ALG_RSA] = "rsa",
 #ifndef OPENSSL_NO_EC
-	[KEY_ALG_ECDSA] = "ecdsa"
+	[KEY_ALG_ECDSA_NIST] = "ecdsa",
+	[KEY_ALG_ECDSA_BRAINPOOL_R] = "ecdsa-brainpool-regular",
+	[KEY_ALG_ECDSA_BRAINPOOL_T] = "ecdsa-brainpool-twisted",
 #endif /* OPENSSL_NO_EC */
 };
 
@@ -106,7 +108,7 @@
 
 	printf("\n\n");
 	printf("The certificate generation tool loads the binary images and\n"
-	       "optionally the RSA keys, and outputs the key and content\n"
+	       "optionally the RSA or ECC keys, and outputs the key and content\n"
 	       "certificates properly signed to implement the chain of trust.\n"
 	       "If keys are provided, they must be in PEM format.\n"
 	       "Certificates are generated in DER format.\n");
@@ -267,7 +269,8 @@
 	},
 	{
 		{ "key-alg", required_argument, NULL, 'a' },
-		"Key algorithm: 'rsa' (default)- RSAPSS scheme as per PKCS#1 v2.1, 'ecdsa'"
+		"Key algorithm: 'rsa' (default)- RSAPSS scheme as per PKCS#1 v2.1, " \
+		"'ecdsa', 'ecdsa-brainpool-regular', 'ecdsa-brainpool-twisted'"
 	},
 	{
 		{ "key-size", required_argument, NULL, 'b' },