Merge changes from topic "bk/context_refactor" into integration

* changes:
  refactor(cm): enable S-EL2 globally for all contexts
  refactor(cm): remove world differentiation for EL2 context restore
  fix(cm): make ICC_SRE_EL2 fixup generic to all worlds
  refactor(cm): clean up SCR_EL3 and CPTR_EL3 initialization
diff --git a/.versionrc.js b/.versionrc.js
index 3a21ded..c7ee4a2 100644
--- a/.versionrc.js
+++ b/.versionrc.js
@@ -129,16 +129,19 @@
                 "readVersion": function (contents) {
                     const major = contents.match(/^VERSION_MAJOR\s*:=\s*(\d+?)$/m)[1];
                     const minor = contents.match(/^VERSION_MINOR\s*:=\s*(\d+?)$/m)[1];
+                    const patch = contents.match(/^VERSION_PATCH\s*:=\s*(\d+?)$/m)[1];
 
-                    return `${major}.${minor}.0`;
+                    return `${major}.${minor}.${patch}`;
                 },
 
                 "writeVersion": function (contents, version) {
                     const major = version.split(".")[0];
                     const minor = version.split(".")[1];
+                    const patch = version.split(".")[2];
 
                     contents = contents.replace(/^(VERSION_MAJOR\s*:=\s*)(\d+?)$/m, `$1${major}`);
                     contents = contents.replace(/^(VERSION_MINOR\s*:=\s*)(\d+?)$/m, `$1${minor}`);
+                    contents = contents.replace(/^(VERSION_PATCH\s*:=\s*)(\d+?)$/m, `$1${patch}`);
 
                     return contents;
                 }
diff --git a/Makefile b/Makefile
index 8e8fba9..464544f 100644
--- a/Makefile
+++ b/Makefile
@@ -9,7 +9,8 @@
 #
 VERSION_MAJOR			:= 2
 VERSION_MINOR			:= 9
-VERSION				:= ${VERSION_MAJOR}.${VERSION_MINOR}
+VERSION_PATCH			:= 0
+VERSION				:= ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}
 
 # Default goal is build all images
 .DEFAULT_GOAL			:= all
@@ -1036,6 +1037,10 @@
 # Determine if FEAT_SB is supported
 ENABLE_FEAT_SB		=	$(if $(findstring sb,${arch-features}),1,0)
 
+ifeq ($(PSA_CRYPTO),1)
+        $(info PSA_CRYPTO is an experimental feature)
+endif
+
 ################################################################################
 # Process platform overrideable behaviour
 ################################################################################
@@ -1217,6 +1222,7 @@
 	ERRATA_NON_ARM_INTERCONNECT \
 	CONDITIONAL_CMO \
 	RAS_FFH_SUPPORT \
+	PSA_CRYPTO	\
 )))
 
 # Numeric_Flags
@@ -1407,6 +1413,7 @@
 	IMPDEF_SYSREG_TRAP \
 	SVE_VECTOR_LEN \
 	ENABLE_SPMD_LP \
+	PSA_CRYPTO	\
 )))
 
 ifeq (${SANITIZE_UB},trap)
diff --git a/changelog.yaml b/changelog.yaml
index 3f7979e..2d6986b 100644
--- a/changelog.yaml
+++ b/changelog.yaml
@@ -809,6 +809,9 @@
           - title: mbedTLS
             scope: mbedtls
 
+          - title: mbedTLS-PSA
+            scope: mbedtls-psa
+
       - title: Console
         scope: console
 
diff --git a/docs/design/cpu-specific-build-macros.rst b/docs/design/cpu-specific-build-macros.rst
index bf04558..ad05a50 100644
--- a/docs/design/cpu-specific-build-macros.rst
+++ b/docs/design/cpu-specific-build-macros.rst
@@ -726,6 +726,10 @@
 
 For Cortex-X3, the following errata build flags are defined :
 
+- ``ERRATA_X3_2070301``: This applies errata 2070301 workaround to the Cortex-X3
+  CPU. This needs to be enabled only for revisions r0p0, r1p0, r1p1 and r1p2 of
+  the CPU and is still open.
+
 - ``ERRATA_X3_2313909``: This applies errata 2313909 workaround to
   Cortex-X3 CPU. This needs to be enabled only for revisions r0p0 and r1p0
   of the CPU, it is fixed in r1p1.
diff --git a/docs/getting_started/build-options.rst b/docs/getting_started/build-options.rst
index 7c84ef1..34d83f2 100644
--- a/docs/getting_started/build-options.rst
+++ b/docs/getting_started/build-options.rst
@@ -1185,6 +1185,12 @@
   errata mitigation for platforms with a non-arm interconnect using the errata
   ABI. By default its disabled (``0``).
 
+- ``PSA_CRYPTO``: Boolean option for enabling MbedTLS PSA crypto APIs support.
+  The platform will use PSA compliant Crypto APIs during authentication and
+  image measurement process by enabling this option. It uses APIs defined as
+  per the `PSA Crypto API specification`_. This feature is only supported if
+  using MbedTLS 3.x version. By default it is disabled (``0``).
+
 GICv3 driver options
 --------------------
 
@@ -1306,3 +1312,4 @@
 .. _GCC: https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html
 .. _Clang: https://clang.llvm.org/docs/DiagnosticsReference.html
 .. _Firmware Handoff specification: https://github.com/FirmwareHandoff/firmware_handoff/releases/tag/v0.9
+.. _PSA Crypto API specification: https://armmbed.github.io/mbed-crypto/html/
diff --git a/docs/process/faq.rst b/docs/process/faq.rst
index daab198..0f33bc0 100644
--- a/docs/process/faq.rst
+++ b/docs/process/faq.rst
@@ -67,9 +67,11 @@
 What are these strange comments in my changes?
 ----------------------------------------------
 
-All the comments from ``ci-bot-user`` are associated with Continuous Integration
-infrastructure. The links published on the comment are not currently accessible,
-but would be after the CI has been transitioned to `trustedfirmware.org`_.
+All the comments from ``TrustedFirmware Code Review`` user (email:
+``ci@trustedfirmware.org``) are associated with Continuous Integration (CI)
+infrastructure. The links published on the comments redirect to the CI web
+interface at http://ci.trustedfirmware.org, where details of the tests failures,
+if any, can be examined.
 
 --------------
 
@@ -77,4 +79,3 @@
 
 .. _Gerrit Upload Patch Set documentation: https://review.trustedfirmware.org/Documentation/intro-user.html#upload-patch-set
 .. _Gerrit Replace Changes documentation: https://review.trustedfirmware.org/Documentation/user-upload.html#push_replace
-.. _trustedfirmware.org: https://www.trustedfirmware.org/
diff --git a/drivers/auth/mbedtls/mbedtls_common.mk b/drivers/auth/mbedtls/mbedtls_common.mk
index 79c4512..376b6b7 100644
--- a/drivers/auth/mbedtls/mbedtls_common.mk
+++ b/drivers/auth/mbedtls/mbedtls_common.mk
@@ -23,7 +23,11 @@
 ifeq (${MBEDTLS_MAJOR}, 2)
 	MBEDTLS_CONFIG_FILE	?=	"<drivers/auth/mbedtls/mbedtls_config-2.h>"
 else ifeq (${MBEDTLS_MAJOR}, 3)
-	MBEDTLS_CONFIG_FILE	?=	"<drivers/auth/mbedtls/mbedtls_config-3.h>"
+	ifeq (${PSA_CRYPTO},1)
+		MBEDTLS_CONFIG_FILE     ?=      "<drivers/auth/mbedtls/psa_mbedtls_config.h>"
+	else
+		MBEDTLS_CONFIG_FILE	?=	"<drivers/auth/mbedtls/mbedtls_config-3.h>"
+	endif
 endif
 
 $(eval $(call add_define,MBEDTLS_CONFIG_FILE))
@@ -77,6 +81,18 @@
 	LIBMBEDTLS_CFLAGS += -Wno-error=redundant-decls
 endif
 
+ifeq (${PSA_CRYPTO},1)
+LIBMBEDTLS_SRCS         += $(addprefix ${MBEDTLS_DIR}/library/,    	\
+					psa_crypto.c                   	\
+					psa_crypto_client.c            	\
+					psa_crypto_driver_wrappers.c   	\
+					psa_crypto_hash.c              	\
+					psa_crypto_rsa.c               	\
+					psa_crypto_ecp.c               	\
+					psa_crypto_slot_management.c   	\
+					)
+endif
+
 # The platform may define the variable 'TF_MBEDTLS_KEY_ALG' to select the key
 # algorithm to use. If the variable is not defined, select it based on
 # algorithm used for key generation `KEY_ALG`. If `KEY_ALG` is not defined,
diff --git a/drivers/auth/mbedtls/mbedtls_crypto.mk b/drivers/auth/mbedtls/mbedtls_crypto.mk
index 2a9fbbf..bd36730 100644
--- a/drivers/auth/mbedtls/mbedtls_crypto.mk
+++ b/drivers/auth/mbedtls/mbedtls_crypto.mk
@@ -1,11 +1,16 @@
 #
-# Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2015-2023, Arm Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
 
 include drivers/auth/mbedtls/mbedtls_common.mk
 
-MBEDTLS_SOURCES	+=		drivers/auth/mbedtls/mbedtls_crypto.c
-
-
+ifeq (${PSA_CRYPTO},1)
+	# Some of the PSA functions are declared in multiple header files
+	# that triggers this warning.
+	TF_CFLAGS      	+=     	-Wno-error=redundant-decls
+	MBEDTLS_SOURCES +=	drivers/auth/mbedtls/mbedtls_psa_crypto.c
+else
+	MBEDTLS_SOURCES +=	drivers/auth/mbedtls/mbedtls_crypto.c
+endif
diff --git a/drivers/auth/mbedtls/mbedtls_psa_crypto.c b/drivers/auth/mbedtls/mbedtls_psa_crypto.c
new file mode 100644
index 0000000..2fa8e63
--- /dev/null
+++ b/drivers/auth/mbedtls/mbedtls_psa_crypto.c
@@ -0,0 +1,499 @@
+/*
+ * Copyright (c) 2023, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <stddef.h>
+#include <string.h>
+
+/* mbed TLS headers */
+#include <mbedtls/gcm.h>
+#include <mbedtls/md.h>
+#include <mbedtls/memory_buffer_alloc.h>
+#include <mbedtls/oid.h>
+#include <mbedtls/platform.h>
+#include <mbedtls/version.h>
+#include <mbedtls/x509.h>
+#include <psa/crypto.h>
+#include <psa/crypto_platform.h>
+#include <psa/crypto_types.h>
+#include <psa/crypto_values.h>
+
+#include <common/debug.h>
+#include <drivers/auth/crypto_mod.h>
+#include <drivers/auth/mbedtls/mbedtls_common.h>
+#include <plat/common/platform.h>
+
+#define LIB_NAME		"mbed TLS PSA"
+
+#if CRYPTO_SUPPORT == CRYPTO_HASH_CALC_ONLY || \
+CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC
+/*
+ * CRYPTO_MD_MAX_SIZE value is as per current stronger algorithm available
+ * so make sure that mbed TLS MD maximum size must be lesser than this.
+ */
+CASSERT(CRYPTO_MD_MAX_SIZE >= MBEDTLS_MD_MAX_SIZE,
+	assert_mbedtls_md_size_overflow);
+
+#endif /*
+	* CRYPTO_SUPPORT == CRYPTO_HASH_CALC_ONLY || \
+	* CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC
+	*/
+
+static inline psa_algorithm_t mbedtls_md_psa_alg_from_type(
+						mbedtls_md_type_t md_type)
+{
+	assert((md_type == MBEDTLS_MD_SHA256) ||
+	       (md_type == MBEDTLS_MD_SHA384) ||
+	       (md_type == MBEDTLS_MD_SHA512));
+
+	return PSA_ALG_CATEGORY_HASH | (psa_algorithm_t) (md_type + 0x5);
+}
+
+/*
+ * AlgorithmIdentifier  ::=  SEQUENCE  {
+ *     algorithm               OBJECT IDENTIFIER,
+ *     parameters              ANY DEFINED BY algorithm OPTIONAL
+ * }
+ *
+ * SubjectPublicKeyInfo  ::=  SEQUENCE  {
+ *     algorithm            AlgorithmIdentifier,
+ *     subjectPublicKey     BIT STRING
+ * }
+ *
+ * DigestInfo ::= SEQUENCE {
+ *     digestAlgorithm AlgorithmIdentifier,
+ *     digest OCTET STRING
+ * }
+ */
+
+/*
+ * We pretend using an external RNG (through MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG
+ * mbedTLS config option) so we need to provide an implementation of
+ * mbedtls_psa_external_get_random(). Provide a fake one, since we do not
+ * actually have any external RNG and TF-A itself doesn't engage in
+ * cryptographic operations that demands randomness.
+ */
+psa_status_t mbedtls_psa_external_get_random(
+			mbedtls_psa_external_random_context_t *context,
+			uint8_t *output, size_t output_size,
+			size_t *output_length)
+{
+	return PSA_ERROR_INSUFFICIENT_ENTROPY;
+}
+
+/*
+ * Initialize the library and export the descriptor
+ */
+static void init(void)
+{
+	/* Initialize mbed TLS */
+	mbedtls_init();
+
+	/* Initialise PSA mbedTLS */
+	psa_status_t status = psa_crypto_init();
+
+	if (status != PSA_SUCCESS) {
+		ERROR("Failed to initialize %s crypto (%d).\n", LIB_NAME, status);
+		panic();
+	}
+
+	INFO("PSA crypto initialized successfully!\n");
+}
+
+#if CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_ONLY || \
+CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC
+
+static void construct_psa_key_alg_and_type(mbedtls_pk_type_t pk_alg,
+					   mbedtls_md_type_t md_alg,
+					   psa_algorithm_t *psa_alg,
+					   psa_key_type_t *psa_key_type)
+{
+	psa_algorithm_t psa_md_alg = mbedtls_md_psa_alg_from_type(md_alg);
+
+	switch (pk_alg) {
+	case MBEDTLS_PK_RSASSA_PSS:
+		*psa_alg = PSA_ALG_RSA_PSS(psa_md_alg);
+		*psa_key_type = PSA_KEY_TYPE_RSA_PUBLIC_KEY;
+		break;
+	default:
+		*psa_alg = PSA_ALG_NONE;
+		*psa_key_type = PSA_KEY_TYPE_NONE;
+		break;
+	}
+}
+
+/*
+ * Verify a signature.
+ *
+ * Parameters are passed using the DER encoding format following the ASN.1
+ * structures detailed above.
+ */
+static int 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)
+{
+	mbedtls_asn1_buf sig_oid, sig_params;
+	mbedtls_asn1_buf signature;
+	mbedtls_md_type_t md_alg;
+	mbedtls_pk_type_t pk_alg;
+	int rc;
+	void *sig_opts = NULL;
+	unsigned char *p, *end;
+
+	/* construct PSA key algo and type */
+	psa_status_t status = PSA_SUCCESS;
+	psa_key_attributes_t psa_key_attr = PSA_KEY_ATTRIBUTES_INIT;
+	psa_key_id_t psa_key_id = PSA_KEY_ID_NULL;
+	psa_key_type_t psa_key_type;
+	psa_algorithm_t psa_alg;
+
+	/* Get pointers to signature OID and parameters */
+	p = (unsigned char *)sig_alg;
+	end = (unsigned char *)(p + sig_alg_len);
+	rc = mbedtls_asn1_get_alg(&p, end, &sig_oid, &sig_params);
+	if (rc != 0) {
+		return CRYPTO_ERR_SIGNATURE;
+	}
+
+	/* Get the actual signature algorithm (MD + PK) */
+	rc = mbedtls_x509_get_sig_alg(&sig_oid, &sig_params, &md_alg, &pk_alg, &sig_opts);
+	if (rc != 0) {
+		return CRYPTO_ERR_SIGNATURE;
+	}
+
+	/* Get the signature (bitstring) */
+	p = (unsigned char *)sig_ptr;
+	end = (unsigned char *)(p + sig_len);
+	signature.tag = *p;
+	rc = mbedtls_asn1_get_bitstring_null(&p, end, &signature.len);
+	if ((rc != 0) || ((size_t)(end - p) != signature.len)) {
+		rc = CRYPTO_ERR_SIGNATURE;
+		goto end2;
+	}
+	signature.p = p;
+
+	/* Convert this pk_alg and md_alg to PSA key type and key algorithm */
+	construct_psa_key_alg_and_type(pk_alg, md_alg,
+				       &psa_alg, &psa_key_type);
+
+
+	if ((psa_alg == PSA_ALG_NONE) || (psa_key_type == PSA_KEY_TYPE_NONE)) {
+		rc = CRYPTO_ERR_SIGNATURE;
+		goto end2;
+	}
+
+	/* filled-in key_attributes */
+	psa_set_key_algorithm(&psa_key_attr, psa_alg);
+	psa_set_key_type(&psa_key_attr, psa_key_type);
+	psa_set_key_usage_flags(&psa_key_attr, PSA_KEY_USAGE_VERIFY_MESSAGE);
+
+	/* Get the key_id using import API */
+	status = psa_import_key(&psa_key_attr,
+				pk_ptr,
+				(size_t)pk_len,
+				&psa_key_id);
+
+	if (status != PSA_SUCCESS) {
+		rc = CRYPTO_ERR_SIGNATURE;
+		goto end2;
+	}
+
+	/*
+	 * Hash calculation and Signature verification of the given data payload
+	 * is wrapped under the psa_verify_message function.
+	 */
+	status = psa_verify_message(psa_key_id, psa_alg,
+				    data_ptr, data_len,
+				    signature.p, signature.len);
+
+	if (status != PSA_SUCCESS) {
+		rc = CRYPTO_ERR_SIGNATURE;
+		goto end1;
+	}
+
+	/* Signature verification success */
+	rc = CRYPTO_SUCCESS;
+
+end1:
+	/*
+	 * Destroy the key if it is created successfully
+	 */
+	psa_destroy_key(psa_key_id);
+end2:
+	mbedtls_free(sig_opts);
+	return rc;
+}
+
+/*
+ * Match a hash
+ *
+ * Digest info is passed in DER format following the ASN.1 structure detailed
+ * above.
+ */
+static int verify_hash(void *data_ptr, unsigned int data_len,
+		       void *digest_info_ptr, unsigned int digest_info_len)
+{
+	mbedtls_asn1_buf hash_oid, params;
+	mbedtls_md_type_t md_alg;
+	unsigned char *p, *end, *hash;
+	size_t len;
+	int rc;
+	psa_status_t status;
+	psa_algorithm_t psa_md_alg;
+
+	/*
+	 * Digest info should be an MBEDTLS_ASN1_SEQUENCE, but padding after
+	 * it is allowed.  This is necessary to support multiple hash
+	 * algorithms.
+	 */
+	p = (unsigned char *)digest_info_ptr;
+	end = p + digest_info_len;
+	rc = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED |
+				  MBEDTLS_ASN1_SEQUENCE);
+	if (rc != 0) {
+		return CRYPTO_ERR_HASH;
+	}
+
+	end = p + len;
+
+	/* Get the hash algorithm */
+	rc = mbedtls_asn1_get_alg(&p, end, &hash_oid, &params);
+	if (rc != 0) {
+		return CRYPTO_ERR_HASH;
+	}
+
+	/* Hash should be octet string type and consume all bytes */
+	rc = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING);
+	if ((rc != 0) || ((size_t)(end - p) != len)) {
+		return CRYPTO_ERR_HASH;
+	}
+	hash = p;
+
+	rc = mbedtls_oid_get_md_alg(&hash_oid, &md_alg);
+	if (rc != 0) {
+		return CRYPTO_ERR_HASH;
+	}
+
+	/* convert the md_alg to psa_algo */
+	psa_md_alg = mbedtls_md_psa_alg_from_type(md_alg);
+
+	/* Length of hash must match the algorithm's size */
+	if (len != PSA_HASH_LENGTH(psa_md_alg)) {
+		return CRYPTO_ERR_HASH;
+	}
+
+	/*
+	 * Calculate Hash and compare it against the retrieved hash from
+	 * the certificate (one shot API).
+	 */
+	status = psa_hash_compare(psa_md_alg,
+				  data_ptr, (size_t)data_len,
+				  (const uint8_t *)hash, len);
+
+	if (status != PSA_SUCCESS) {
+		return CRYPTO_ERR_HASH;
+	}
+
+	return CRYPTO_SUCCESS;
+}
+#endif /*
+	* CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_ONLY || \
+	* CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC
+	*/
+
+#if CRYPTO_SUPPORT == CRYPTO_HASH_CALC_ONLY || \
+CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC
+/*
+ * Map a generic crypto message digest algorithm to the corresponding macro used
+ * by Mbed TLS.
+ */
+static inline mbedtls_md_type_t md_type(enum crypto_md_algo algo)
+{
+	switch (algo) {
+	case CRYPTO_MD_SHA512:
+		return MBEDTLS_MD_SHA512;
+	case CRYPTO_MD_SHA384:
+		return MBEDTLS_MD_SHA384;
+	case CRYPTO_MD_SHA256:
+		return MBEDTLS_MD_SHA256;
+	default:
+		/* Invalid hash algorithm. */
+		return MBEDTLS_MD_NONE;
+	}
+}
+
+/*
+ * Calculate a hash
+ *
+ * output points to the computed hash
+ */
+static int calc_hash(enum crypto_md_algo md_algo, void *data_ptr,
+		     unsigned int data_len,
+		     unsigned char output[CRYPTO_MD_MAX_SIZE])
+{
+	size_t hash_length;
+	psa_status_t status;
+	psa_algorithm_t psa_md_alg;
+
+	/* convert the md_alg to psa_algo */
+	psa_md_alg = mbedtls_md_psa_alg_from_type(md_type(md_algo));
+
+	/*
+	 * Calculate the hash of the data, it is safe to pass the
+	 * 'output' hash buffer pointer considering its size is always
+	 * bigger than or equal to MBEDTLS_MD_MAX_SIZE.
+	 */
+	status = psa_hash_compute(psa_md_alg, data_ptr, (size_t)data_len,
+				  (uint8_t *)output, CRYPTO_MD_MAX_SIZE,
+				  &hash_length);
+	if (status != PSA_SUCCESS) {
+		return CRYPTO_ERR_HASH;
+	}
+
+	return CRYPTO_SUCCESS;
+}
+#endif /*
+	* CRYPTO_SUPPORT == CRYPTO_HASH_CALC_ONLY || \
+	* CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC
+	*/
+
+#if TF_MBEDTLS_USE_AES_GCM
+/*
+ * Stack based buffer allocation for decryption operation. It could
+ * be configured to balance stack usage vs execution speed.
+ */
+#define DEC_OP_BUF_SIZE		128
+
+static int aes_gcm_decrypt(void *data_ptr, size_t len, const void *key,
+			   unsigned int key_len, const void *iv,
+			   unsigned int iv_len, const void *tag,
+			   unsigned int tag_len)
+{
+	mbedtls_gcm_context ctx;
+	mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES;
+	unsigned char buf[DEC_OP_BUF_SIZE];
+	unsigned char tag_buf[CRYPTO_MAX_TAG_SIZE];
+	unsigned char *pt = data_ptr;
+	size_t dec_len;
+	int diff, i, rc;
+	size_t output_length __unused;
+
+	mbedtls_gcm_init(&ctx);
+
+	rc = mbedtls_gcm_setkey(&ctx, cipher, key, key_len * 8);
+	if (rc != 0) {
+		rc = CRYPTO_ERR_DECRYPTION;
+		goto exit_gcm;
+	}
+
+#if (MBEDTLS_VERSION_MAJOR < 3)
+	rc = mbedtls_gcm_starts(&ctx, MBEDTLS_GCM_DECRYPT, iv, iv_len, NULL, 0);
+#else
+	rc = mbedtls_gcm_starts(&ctx, MBEDTLS_GCM_DECRYPT, iv, iv_len);
+#endif
+	if (rc != 0) {
+		rc = CRYPTO_ERR_DECRYPTION;
+		goto exit_gcm;
+	}
+
+	while (len > 0) {
+		dec_len = MIN(sizeof(buf), len);
+
+#if (MBEDTLS_VERSION_MAJOR < 3)
+		rc = mbedtls_gcm_update(&ctx, dec_len, pt, buf);
+#else
+		rc = mbedtls_gcm_update(&ctx, pt, dec_len, buf, sizeof(buf), &output_length);
+#endif
+
+		if (rc != 0) {
+			rc = CRYPTO_ERR_DECRYPTION;
+			goto exit_gcm;
+		}
+
+		memcpy(pt, buf, dec_len);
+		pt += dec_len;
+		len -= dec_len;
+	}
+
+#if (MBEDTLS_VERSION_MAJOR < 3)
+	rc = mbedtls_gcm_finish(&ctx, tag_buf, sizeof(tag_buf));
+#else
+	rc = mbedtls_gcm_finish(&ctx, NULL, 0, &output_length, tag_buf, sizeof(tag_buf));
+#endif
+
+	if (rc != 0) {
+		rc = CRYPTO_ERR_DECRYPTION;
+		goto exit_gcm;
+	}
+
+	/* Check tag in "constant-time" */
+	for (diff = 0, i = 0; i < tag_len; i++)
+		diff |= ((const unsigned char *)tag)[i] ^ tag_buf[i];
+
+	if (diff != 0) {
+		rc = CRYPTO_ERR_DECRYPTION;
+		goto exit_gcm;
+	}
+
+	/* GCM decryption success */
+	rc = CRYPTO_SUCCESS;
+
+exit_gcm:
+	mbedtls_gcm_free(&ctx);
+	return rc;
+}
+
+/*
+ * Authenticated decryption of an image
+ */
+static int 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;
+
+	assert((key_flags & ENC_KEY_IS_IDENTIFIER) == 0);
+
+	switch (dec_algo) {
+	case CRYPTO_GCM_DECRYPT:
+		rc = aes_gcm_decrypt(data_ptr, len, key, key_len, iv, iv_len,
+				     tag, tag_len);
+		if (rc != 0)
+			return rc;
+		break;
+	default:
+		return CRYPTO_ERR_DECRYPTION;
+	}
+
+	return CRYPTO_SUCCESS;
+}
+#endif /* TF_MBEDTLS_USE_AES_GCM */
+
+/*
+ * Register crypto library descriptor
+ */
+#if CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC
+#if TF_MBEDTLS_USE_AES_GCM
+REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, calc_hash,
+		    auth_decrypt, NULL);
+#else
+REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, calc_hash,
+		    NULL, NULL);
+#endif
+#elif CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_ONLY
+#if TF_MBEDTLS_USE_AES_GCM
+REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, NULL,
+		    auth_decrypt, NULL);
+#else
+REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, NULL,
+		    NULL, NULL);
+#endif
+#elif CRYPTO_SUPPORT == CRYPTO_HASH_CALC_ONLY
+REGISTER_CRYPTO_LIB(LIB_NAME, init, NULL, NULL, calc_hash, NULL, NULL);
+#endif /* CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC */
diff --git a/include/drivers/auth/mbedtls/psa_mbedtls_config.h b/include/drivers/auth/mbedtls/psa_mbedtls_config.h
new file mode 100644
index 0000000..ad825f0
--- /dev/null
+++ b/include/drivers/auth/mbedtls/psa_mbedtls_config.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2023, Arm Ltd. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PSA_MBEDTLS_CONFIG_H
+#define PSA_MBEDTLS_CONFIG_H
+
+#include "mbedtls_config-3.h"
+
+#define MBEDTLS_PSA_CRYPTO_C
+
+/*
+ * Using PSA crypto API requires an RNG right now. If we don't define the macro
+ * below then we get build errors.
+ *
+ * This is a functionality gap in mbedTLS. The technical limitation is that
+ * psa_crypto_init() is all-or-nothing, and fixing that would require separate
+ * initialization of the keystore, the RNG, etc.
+ *
+ * By defining MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG, we pretend using an external
+ * RNG. As a result, the PSA crypto init code does nothing when it comes to
+ * initializing the RNG, as we are supposed to take care of that ourselves.
+ */
+#define MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG
+
+#endif /* PSA_MBEDTLS_CONFIG_H */
diff --git a/include/lib/cpus/aarch64/cortex_x3.h b/include/lib/cpus/aarch64/cortex_x3.h
index e648734..04548ea 100644
--- a/include/lib/cpus/aarch64/cortex_x3.h
+++ b/include/lib/cpus/aarch64/cortex_x3.h
@@ -38,4 +38,13 @@
 #define CORTEX_X3_CPUACTLR5_EL1_BIT_55		(ULL(1) << 55)
 #define CORTEX_X3_CPUACTLR5_EL1_BIT_56		(ULL(1) << 56)
 
+/*******************************************************************************
+ * CPU Extended Control register 2 specific definitions.
+ ******************************************************************************/
+#define CORTEX_X3_CPUECTLR2_EL1			S3_0_C15_C1_5
+
+#define CORTEX_X3_CPUECTLR2_EL1_PF_MODE_LSB	U(11)
+#define CORTEX_X3_CPUECTLR2_EL1_PF_MODE_WIDTH	U(4)
+#define CORTEX_X3_CPUECTLR2_EL1_PF_MODE_CNSRV	ULL(0x9)
+
 #endif /* CORTEX_X3_H */
diff --git a/lib/cpus/aarch64/cortex_x3.S b/lib/cpus/aarch64/cortex_x3.S
index 98d148e..0cb3b97 100644
--- a/lib/cpus/aarch64/cortex_x3.S
+++ b/lib/cpus/aarch64/cortex_x3.S
@@ -26,6 +26,13 @@
 	wa_cve_2022_23960_bhb_vector_table CORTEX_X3_BHB_LOOP_COUNT, cortex_x3
 #endif /* WORKAROUND_CVE_2022_23960 */
 
+workaround_reset_start cortex_x3, ERRATUM(2070301), ERRATA_X3_2070301
+	sysreg_bitfield_insert CORTEX_X3_CPUECTLR2_EL1, CORTEX_X3_CPUECTLR2_EL1_PF_MODE_CNSRV, \
+	CORTEX_X3_CPUECTLR2_EL1_PF_MODE_LSB, CORTEX_X3_CPUECTLR2_EL1_PF_MODE_WIDTH
+workaround_reset_end cortex_x3, ERRATUM(2070301)
+
+check_erratum_ls cortex_x3, ERRATUM(2070301), CPU_REV(1, 2)
+
 workaround_runtime_start cortex_x3, ERRATUM(2313909), ERRATA_X3_2313909
 	sysreg_bit_set	CORTEX_X3_CPUACTLR2_EL1, CORTEX_X3_CPUACTLR2_EL1_BIT_36
 workaround_runtime_end cortex_x3, ERRATUM(2313909), NO_ISB
diff --git a/lib/cpus/cpu-ops.mk b/lib/cpus/cpu-ops.mk
index 77cc41e..e12795f 100644
--- a/lib/cpus/cpu-ops.mk
+++ b/lib/cpus/cpu-ops.mk
@@ -734,6 +734,11 @@
 # still open.
 CPU_FLAG_LIST += ERRATA_X2_2768515
 
+# Flag to apply erratum 2070301 workaround on reset. This erratum applies
+# to revisions r0p0, r1p0, r1p1 and r1p2 of the Cortex-X3 cpu and is
+# still open.
+CPU_FLAG_LIST += ERRATA_X3_2070301
+
 # Flag to apply erratum 2313909 workaround on powerdown. This erratum applies
 # to revisions r0p0 and r1p0 of the Cortex-X3 cpu, it is fixed in r1p1.
 CPU_FLAG_LIST += ERRATA_X3_2313909
diff --git a/make_helpers/defaults.mk b/make_helpers/defaults.mk
index b7e6f99..321ae9f 100644
--- a/make_helpers/defaults.mk
+++ b/make_helpers/defaults.mk
@@ -359,3 +359,6 @@
 
 # By default, disable SPMD Logical partitions
 ENABLE_SPMD_LP			:= 0
+
+# By default, disable PSA crypto (use MbedTLS legacy crypto API).
+PSA_CRYPTO			:= 0
diff --git a/services/std_svc/errata_abi/errata_abi_main.c b/services/std_svc/errata_abi/errata_abi_main.c
index ca66396..c0a089b 100644
--- a/services/std_svc/errata_abi/errata_abi_main.c
+++ b/services/std_svc/errata_abi/errata_abi_main.c
@@ -428,10 +428,11 @@
 {
 	.cpu_partnumber = CORTEX_X3_MIDR,
 	.cpu_errata_list = {
-		[0] = {2313909, 0x00, 0x10, ERRATA_X3_2313909},
-		[1] = {2615812, 0x00, 0x11, ERRATA_X3_2615812},
-		[2] = {2742421, 0x00, 0x11, ERRATA_X3_2742421},
-		[3 ... ERRATA_LIST_END] = UNDEF_ERRATA,
+		[0] = {2070301, 0x00, 0x12, ERRATA_X3_2070301},
+		[1] = {2313909, 0x00, 0x10, ERRATA_X3_2313909},
+		[2] = {2615812, 0x00, 0x11, ERRATA_X3_2615812},
+		[3] = {2742421, 0x00, 0x11, ERRATA_X3_2742421},
+		[4 ... ERRATA_LIST_END] = UNDEF_ERRATA,
 	}
 },
 #endif /* CORTEX_X3_H_INC */