Update the main branch from integration

- Corstone1000 updates:
    - Fix psa-crypto-api tests 254 and 243.
    - Integrate PSA-FWU proxy to the proxy SP.
    - Allow compile time configuration of the MHU and RSE buffer size.
    - Align psa-crypto size definitions with TF-M v2.1

- spm-test: allow platform specific configuration of some manifest
  entries.

Change-Id: I8989db768ca36b08530ae211d3757742e3f666cf
Signed-off-by: Gyorgy Szing <gyorgy.szing@arm.com>
diff --git a/components/service/common/include/psa/crypto_sid.h b/components/service/common/include/psa/crypto_sid.h
index 5b05f46..fe057ce 100644
--- a/components/service/common/include/psa/crypto_sid.h
+++ b/components/service/common/include/psa/crypto_sid.h
@@ -18,22 +18,24 @@
  *        nine groups (Random, Key management, Hash, MAC, Cipher, AEAD,
  *        Asym sign, Asym encrypt, Key derivation).
  */
-enum tfm_crypto_group_id {
-    TFM_CRYPTO_GROUP_ID_RANDOM = 0x0,
-    TFM_CRYPTO_GROUP_ID_KEY_MANAGEMENT,
-    TFM_CRYPTO_GROUP_ID_HASH,
-    TFM_CRYPTO_GROUP_ID_MAC,
-    TFM_CRYPTO_GROUP_ID_CIPHER,
-    TFM_CRYPTO_GROUP_ID_AEAD,
-    TFM_CRYPTO_GROUP_ID_ASYM_SIGN,
-    TFM_CRYPTO_GROUP_ID_ASYM_ENCRYPT,
-    TFM_CRYPTO_GROUP_ID_KEY_DERIVATION,
+enum tfm_crypto_group_id_t {
+    TFM_CRYPTO_GROUP_ID_RANDOM          = UINT8_C(1),
+    TFM_CRYPTO_GROUP_ID_KEY_MANAGEMENT  = UINT8_C(2),
+    TFM_CRYPTO_GROUP_ID_HASH            = UINT8_C(3),
+    TFM_CRYPTO_GROUP_ID_MAC             = UINT8_C(4),
+    TFM_CRYPTO_GROUP_ID_CIPHER          = UINT8_C(5),
+    TFM_CRYPTO_GROUP_ID_AEAD            = UINT8_C(6),
+    TFM_CRYPTO_GROUP_ID_ASYM_SIGN       = UINT8_C(7),
+    TFM_CRYPTO_GROUP_ID_ASYM_ENCRYPT    = UINT8_C(8),
+    TFM_CRYPTO_GROUP_ID_KEY_DERIVATION  = UINT8_C(9)
 };
 
-/* X macro describing each of the available PSA Crypto APIs */
+/* Set of X macros describing each of the available PSA Crypto APIs */
+#define RANDOM_FUNCS                               \
+    X(TFM_CRYPTO_GENERATE_RANDOM)
+
 #define KEY_MANAGEMENT_FUNCS                       \
     X(TFM_CRYPTO_GET_KEY_ATTRIBUTES)               \
-    X(TFM_CRYPTO_RESET_KEY_ATTRIBUTES)             \
     X(TFM_CRYPTO_OPEN_KEY)                         \
     X(TFM_CRYPTO_CLOSE_KEY)                        \
     X(TFM_CRYPTO_IMPORT_KEY)                       \
@@ -89,13 +91,13 @@
     X(TFM_CRYPTO_AEAD_VERIFY)                      \
     X(TFM_CRYPTO_AEAD_ABORT)
 
-#define ASYMMETRIC_SIGN_FUNCS                      \
+#define ASYM_SIGN_FUNCS                            \
     X(TFM_CRYPTO_ASYMMETRIC_SIGN_MESSAGE)          \
     X(TFM_CRYPTO_ASYMMETRIC_VERIFY_MESSAGE)        \
     X(TFM_CRYPTO_ASYMMETRIC_SIGN_HASH)             \
     X(TFM_CRYPTO_ASYMMETRIC_VERIFY_HASH)
 
-#define AYSMMETRIC_ENCRYPT_FUNCS                   \
+#define ASYM_ENCRYPT_FUNCS                         \
     X(TFM_CRYPTO_ASYMMETRIC_ENCRYPT)               \
     X(TFM_CRYPTO_ASYMMETRIC_DECRYPT)
 
@@ -106,133 +108,55 @@
     X(TFM_CRYPTO_KEY_DERIVATION_SET_CAPACITY)      \
     X(TFM_CRYPTO_KEY_DERIVATION_INPUT_BYTES)       \
     X(TFM_CRYPTO_KEY_DERIVATION_INPUT_KEY)         \
+    X(TFM_CRYPTO_KEY_DERIVATION_INPUT_INTEGER)     \
     X(TFM_CRYPTO_KEY_DERIVATION_KEY_AGREEMENT)     \
     X(TFM_CRYPTO_KEY_DERIVATION_OUTPUT_BYTES)      \
     X(TFM_CRYPTO_KEY_DERIVATION_OUTPUT_KEY)        \
     X(TFM_CRYPTO_KEY_DERIVATION_ABORT)
 
-#define RANDOM_FUNCS                               \
-    X(TFM_CRYPTO_GENERATE_RANDOM)
+#define BASE__VALUE(x) ((uint16_t)((((uint16_t)(x)) << 8) & 0xFF00))
 
-/*
- * Define function IDs in each group. The function ID will be encoded into
- * tfm_crypto_func_sid below.
- * Each group is defined as a dedicated enum in case the total number of
- * PSA Crypto APIs exceeds 256.
+/**
+ * \brief This type defines numerical progressive values identifying a function API
+ *        exposed through the interfaces (S or NS). It's used to dispatch the requests
+ *        from S/NS to the corresponding API implementation in the Crypto service backend.
+ *
+ * \note Each function SID is encoded as uint16_t.
+ *        +------------+------------+
+ *        |  Group ID  |  Func ID   |
+ *        +------------+------------+
+ *   (MSB)15         8 7          0(LSB)
+ *
  */
-#define X(func_id)    func_id,
-enum tfm_crypto_key_management_func_id {
-    KEY_MANAGEMENT_FUNCS
-};
-enum tfm_crypto_hash_func_id {
-    HASH_FUNCS
-};
-enum tfm_crypto_mac_func_id {
-    MAC_FUNCS
-};
-enum tfm_crypto_cipher_func_id {
-    CIPHER_FUNCS
-};
-enum tfm_crypto_aead_func_id {
-    AEAD_FUNCS
-};
-enum tfm_crypto_asym_sign_func_id {
-    ASYMMETRIC_SIGN_FUNCS
-};
-enum tfm_crypto_asym_encrypt_func_id {
-    AYSMMETRIC_ENCRYPT_FUNCS
-};
-enum tfm_crypto_key_derivation_func_id {
-    KEY_DERIVATION_FUNCS
-};
-enum tfm_crypto_random_func_id {
+enum tfm_crypto_func_sid_t {
+#define X(FUNCTION_NAME) FUNCTION_NAME ## _SID,
+    BASE__RANDOM         = BASE__VALUE(TFM_CRYPTO_GROUP_ID_RANDOM) - 1,
     RANDOM_FUNCS
-};
-#undef X
-
-#define FUNC_ID(func_id)    (((func_id) & 0xFF) << 8)
-
-/*
- * Numerical progressive value identifying a function API exposed through
- * the interfaces (S or NS). It's used to dispatch the requests from S/NS
- * to the corresponding API implementation in the Crypto service backend.
- *
- * Each function SID is encoded as uint16_t.
- *     |  Func ID  |  Group ID |
- *     15         8 7          0
- * Func ID is defined in each group func_id enum above
- * Group ID is defined in tfm_crypto_group_id.
- */
-enum tfm_crypto_func_sid {
-
-#define X(func_id)      func_id ## _SID = (uint16_t)((FUNC_ID(func_id)) | \
-                                   (TFM_CRYPTO_GROUP_ID_KEY_MANAGEMENT & 0xFF)),
-
+    BASE__KEY_MANAGEMENT = BASE__VALUE(TFM_CRYPTO_GROUP_ID_KEY_MANAGEMENT) - 1,
     KEY_MANAGEMENT_FUNCS
-
-#undef X
-#define X(func_id)      func_id ## _SID = (uint16_t)((FUNC_ID(func_id)) | \
-                                            (TFM_CRYPTO_GROUP_ID_HASH & 0xFF)),
+    BASE__HASH           = BASE__VALUE(TFM_CRYPTO_GROUP_ID_HASH) - 1,
     HASH_FUNCS
-
-#undef X
-#define X(func_id)      func_id ## _SID = (uint16_t)((FUNC_ID(func_id)) | \
-                                            (TFM_CRYPTO_GROUP_ID_MAC & 0xFF)),
+    BASE__MAC            = BASE__VALUE(TFM_CRYPTO_GROUP_ID_MAC) - 1,
     MAC_FUNCS
-
-#undef X
-#define X(func_id)      func_id ## _SID = (uint16_t)((FUNC_ID(func_id)) | \
-                                           (TFM_CRYPTO_GROUP_ID_CIPHER & 0xFF)),
+    BASE__CIPHER         = BASE__VALUE(TFM_CRYPTO_GROUP_ID_CIPHER) - 1,
     CIPHER_FUNCS
-
-#undef X
-#define X(func_id)      func_id ## _SID = (uint16_t)((FUNC_ID(func_id)) | \
-                                             (TFM_CRYPTO_GROUP_ID_AEAD & 0xFF)),
+    BASE__AEAD           = BASE__VALUE(TFM_CRYPTO_GROUP_ID_AEAD) - 1,
     AEAD_FUNCS
-
-#undef X
-#define X(func_id)      func_id ## _SID = (uint16_t)((FUNC_ID(func_id)) | \
-                                        (TFM_CRYPTO_GROUP_ID_ASYM_SIGN & 0xFF)),
-    ASYMMETRIC_SIGN_FUNCS
-
-#undef X
-#define X(func_id)      func_id ## _SID = (uint16_t)((FUNC_ID(func_id)) | \
-                                     (TFM_CRYPTO_GROUP_ID_ASYM_ENCRYPT & 0xFF)),
-    AYSMMETRIC_ENCRYPT_FUNCS
-
-#undef X
-#define X(func_id)      func_id ## _SID = (uint16_t)((FUNC_ID(func_id)) | \
-                                   (TFM_CRYPTO_GROUP_ID_KEY_DERIVATION & 0xFF)),
+    BASE__ASYM_SIGN      = BASE__VALUE(TFM_CRYPTO_GROUP_ID_ASYM_SIGN) - 1,
+    ASYM_SIGN_FUNCS
+    BASE__ASYM_ENCRYPT   = BASE__VALUE(TFM_CRYPTO_GROUP_ID_ASYM_ENCRYPT) - 1,
+    ASYM_ENCRYPT_FUNCS
+    BASE__KEY_DERIVATION = BASE__VALUE(TFM_CRYPTO_GROUP_ID_KEY_DERIVATION) - 1,
     KEY_DERIVATION_FUNCS
-
 #undef X
-#define X(func_id)      func_id ## _SID = (uint16_t)((FUNC_ID(func_id)) | \
-                                           (TFM_CRYPTO_GROUP_ID_RANDOM & 0xFF)),
-    RANDOM_FUNCS
-
 };
-#undef X
 
 /**
- * \brief Define an invalid value for an SID
- *
+ * \brief This macro is used to extract the group_id from an encoded function id
+ *        by accessing the upper 8 bits. A \a _function_id is uint16_t type
  */
-#define TFM_CRYPTO_SID_INVALID (~0x0u)
-
-/**
- * \brief This value is used to mark an handle as invalid.
- *
- */
-#define TFM_CRYPTO_INVALID_HANDLE (0x0u)
-
-/**
- * \brief Define miscellaneous literal constants that are used in the service
- *
- */
-enum {
-    TFM_CRYPTO_NOT_IN_USE = 0,
-    TFM_CRYPTO_IN_USE = 1
-};
+#define TFM_CRYPTO_GET_GROUP_ID(_function_id) \
+    ((enum tfm_crypto_group_id_t)(((uint16_t)(_function_id) >> 8) & 0xFF))
 
 #ifdef __cplusplus
 }
diff --git a/components/service/common/include/psa/sid.h b/components/service/common/include/psa/sid.h
index 5aaa659..0235764 100644
--- a/components/service/common/include/psa/sid.h
+++ b/components/service/common/include/psa/sid.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019-2023, Arm Limited. All rights reserved.
+ * Copyright (c) 2019-2024, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  *
@@ -58,6 +58,10 @@
 #define TFM_ATTEST_GET_TOKEN_SIZE  1002
 
 /******** TFM_SP_FWU ********/
+#define TFM_FIRMWARE_UPDATE_SERVICE_SID                            (0x000000A0U)
+#define TFM_FIRMWARE_UPDATE_SERVICE_VERSION                        (1U)
+#define TFM_FIRMWARE_UPDATE_SERVICE_HANDLE                         (0x40000104U)
+
 #define TFM_FWU_WRITE_SID                                          (0x000000A0U)
 #define TFM_FWU_WRITE_VERSION                                      (1U)
 #define TFM_FWU_INSTALL_SID                                        (0x000000A1U)
diff --git a/components/service/crypto/backend/psa_ipc/crypto_ipc_backend.h b/components/service/crypto/backend/psa_ipc/crypto_ipc_backend.h
index f9bbf84..27fe349 100644
--- a/components/service/crypto/backend/psa_ipc/crypto_ipc_backend.h
+++ b/components/service/crypto/backend/psa_ipc/crypto_ipc_backend.h
@@ -30,10 +30,9 @@
 struct psa_ipc_crypto_pack_iovec {
     psa_key_id_t key_id;     /*!< Key id */
     psa_algorithm_t alg;     /*!< Algorithm */
-    uint32_t op_handle;      /*!< Frontend context handle associated to a
+    uint32_t op_handle;      /*!< Client context handle associated to a
                               *   multipart operation
                               */
-    uint32_t capacity;         /*!< Key derivation capacity */
     uint32_t ad_length;        /*!< Additional Data length for multipart AEAD */
     uint32_t plaintext_length; /*!< Plaintext length for multipart AEAD */
 
@@ -44,7 +43,11 @@
                               *   See tfm_crypto_func_sid for detail
                               */
     uint16_t step;           /*!< Key derivation step */
-} __attribute__((__packed__));
+    union {
+        size_t capacity;     /*!< Key derivation capacity */
+        uint64_t value;      /*!< Key derivation integer for update*/
+    };
+};
 
 #define iov_size sizeof(struct psa_ipc_crypto_pack_iovec)
 
diff --git a/components/service/crypto/include/psa/crypto_client_struct.h b/components/service/crypto/include/psa/crypto_client_struct.h
index 1f68aba..7e907fa 100644
--- a/components/service/crypto/include/psa/crypto_client_struct.h
+++ b/components/service/crypto/include/psa/crypto_client_struct.h
@@ -34,12 +34,14 @@
     uint16_t type;
     uint16_t bits;
     uint32_t lifetime;
-    psa_key_id_t id;
     uint32_t usage;
     uint32_t alg;
+    uint32_t alg2;
+    uint32_t id;
+    int32_t owner_id;
 };
 
-#define PSA_CLIENT_KEY_ATTRIBUTES_INIT {0, 0, 0, 0, 0, 0}
+#define PSA_CLIENT_KEY_ATTRIBUTES_INIT {0}
 
 #ifdef __cplusplus
 }
diff --git a/components/service/crypto/include/psa/crypto_sizes.h b/components/service/crypto/include/psa/crypto_sizes.h
index 30aa102..c8592e2 100644
--- a/components/service/crypto/include/psa/crypto_sizes.h
+++ b/components/service/crypto/include/psa/crypto_sizes.h
@@ -351,7 +351,7 @@
  *       just the largest size that may be generated by
  *       #psa_aead_generate_nonce().
  */
-#define PSA_AEAD_NONCE_MAX_SIZE 12
+#define PSA_AEAD_NONCE_MAX_SIZE 13
 
 /** A sufficient output buffer size for psa_aead_update().
  *
diff --git a/components/service/crypto/provider/extension/aead/aead_provider.c b/components/service/crypto/provider/extension/aead/aead_provider.c
index b73d88d..3c593c4 100644
--- a/components/service/crypto/provider/extension/aead/aead_provider.c
+++ b/components/service/crypto/provider/extension/aead/aead_provider.c
@@ -301,6 +301,7 @@
 
 			size_t output_len = 0;
 			size_t output_size = PSA_AEAD_UPDATE_OUTPUT_MAX_SIZE(input_len);
+			/* Always allocate maximum size to be more robust to implementations of psa_aead_update() */
 			uint8_t *output = malloc(output_size);
 
 			if (output) {
diff --git a/components/service/fwu/psa_fwu_m/interface/psa_ipc/component.cmake b/components/service/fwu/psa_fwu_m/interface/psa_ipc/component.cmake
new file mode 100644
index 0000000..cdc653a
--- /dev/null
+++ b/components/service/fwu/psa_fwu_m/interface/psa_ipc/component.cmake
@@ -0,0 +1,13 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-------------------------------------------------------------------------------
+if (NOT DEFINED TGT)
+	message(FATAL_ERROR "mandatory parameter TGT is not defined.")
+endif()
+
+target_sources(${TGT} PRIVATE
+	"${CMAKE_CURRENT_LIST_DIR}/psa_fwu_ipc.c"
+)
diff --git a/components/service/fwu/psa_fwu_m/interface/psa_ipc/psa_fwu_ipc.c b/components/service/fwu/psa_fwu_m/interface/psa_ipc/psa_fwu_ipc.c
new file mode 100644
index 0000000..a47ae53
--- /dev/null
+++ b/components/service/fwu/psa_fwu_m/interface/psa_ipc/psa_fwu_ipc.c
@@ -0,0 +1,253 @@
+/*
+ * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stddef.h>
+#include <string.h>
+#include <trace.h>
+
+#include <protocols/rpc/common/packed-c/status.h>
+#include <psa/client.h>
+#include <psa/sid.h>
+#include <service/common/client/service_client.h>
+#include "service/fwu/psa_fwu_m/interface/psa_ipc/psa_fwu_ipc.h"
+#include "service/fwu/psa_fwu_m/interface/tfm_fwu_defs.h"
+#include "service/fwu/psa_fwu_m/interface/update.h"
+
+/**
+ * @brief      The singleton psa_fwu_ipc instance
+ *
+ * The psa attestation C API assumes a single backend service provider.
+ */
+static struct service_client instance;
+
+psa_status_t psa_fwu_ipc_init(struct rpc_caller_session *session)
+{
+	return service_client_init(&instance, session);
+}
+
+void psa_fwu_ipc_deinit(void)
+{
+	service_client_deinit(&instance);
+}
+
+int psa_fwu_rpc_status(void)
+{
+	return instance.rpc_status;
+}
+
+psa_status_t psa_fwu_query(psa_fwu_component_t component,
+			   psa_fwu_component_info_t *info)
+{
+	if (!instance.session)
+		return PSA_ERROR_BAD_STATE;
+	if (!info)
+		return PSA_ERROR_INVALID_ARGUMENT;
+
+	psa_status_t status = PSA_ERROR_INVALID_ARGUMENT;
+	struct rpc_caller_interface *caller = instance.session->caller;
+	struct psa_invec in_vec[] = {
+		{ .base = psa_ptr_to_u32(&component), .len = sizeof(component) },
+	};
+	struct psa_outvec out_vec[] = {
+		{ .base = psa_ptr_to_u32(info), .len = sizeof(*info) },
+	};
+
+	status = psa_call(caller, TFM_FIRMWARE_UPDATE_SERVICE_HANDLE,
+			  TFM_FWU_QUERY, in_vec, IOVEC_LEN(in_vec),
+			  out_vec, IOVEC_LEN(out_vec));
+	if (status != PSA_SUCCESS)
+		EMSG("failed to psa_call: %d", status);
+
+	return status;
+}
+
+psa_status_t psa_fwu_start(psa_fwu_component_t component,
+			   const void *manifest,
+			   size_t manifest_size)
+{
+	if(manifest_size > UINT32_MAX)
+		return PSA_ERROR_INVALID_ARGUMENT;
+	if (!instance.session)
+		return PSA_ERROR_BAD_STATE;
+
+	psa_status_t status = PSA_ERROR_INVALID_ARGUMENT;
+	struct rpc_caller_interface *caller = instance.session->caller;
+	struct psa_invec in_vec[] = {
+		{ .base = psa_ptr_to_u32(&component), .len = sizeof(component) },
+		{ .base = psa_ptr_const_to_u32(manifest), .len = manifest_size },
+	};
+
+	status = psa_call(caller, TFM_FIRMWARE_UPDATE_SERVICE_HANDLE,
+			  TFM_FWU_START, in_vec, IOVEC_LEN(in_vec),
+			  NULL, 0);
+	if (status != PSA_SUCCESS)
+		EMSG("failed to psa_call: %d", status);
+
+	return status;
+}
+
+psa_status_t psa_fwu_write(psa_fwu_component_t component,
+			   size_t image_offset,
+			   const void *block,
+			   size_t block_size)
+{
+	if (!instance.session)
+		return PSA_ERROR_BAD_STATE;
+	if (!block || !block_size)
+		return PSA_ERROR_INVALID_ARGUMENT;
+	if((image_offset > UINT32_MAX) || (block_size > UINT32_MAX))
+		return PSA_ERROR_INVALID_ARGUMENT;
+
+	psa_status_t status = PSA_ERROR_INVALID_ARGUMENT;
+	struct rpc_caller_interface *caller = instance.session->caller;
+	struct psa_invec in_vec[] = {
+		{ .base = psa_ptr_to_u32(&component), .len = sizeof(component) },
+		{ .base = psa_ptr_to_u32(&image_offset), .len = sizeof(uint32_t) },
+		{ .base = psa_ptr_const_to_u32(block), .len = block_size },
+	};
+
+	status = psa_call(caller, TFM_FIRMWARE_UPDATE_SERVICE_HANDLE,
+			  TFM_FWU_WRITE, in_vec, IOVEC_LEN(in_vec),
+			  NULL, 0);
+	if (status != PSA_SUCCESS)
+		EMSG("failed to psa_call: %d", status);
+
+	return status;
+}
+
+psa_status_t psa_fwu_finish(psa_fwu_component_t component)
+{
+	if (!instance.session)
+		return PSA_ERROR_BAD_STATE;
+
+	psa_status_t status = PSA_ERROR_INVALID_ARGUMENT;
+	struct rpc_caller_interface *caller = instance.session->caller;
+	struct psa_invec in_vec[] = {
+		{ .base = psa_ptr_to_u32(&component), .len = sizeof(component) },
+	};
+
+	status = psa_call(caller, TFM_FIRMWARE_UPDATE_SERVICE_HANDLE,
+			  TFM_FWU_FINISH, in_vec, IOVEC_LEN(in_vec),
+			  NULL, 0);
+	if (status != PSA_SUCCESS)
+		EMSG("failed to psa_call: %d", status);
+
+	return status;
+}
+
+psa_status_t psa_fwu_cancel(psa_fwu_component_t component)
+{
+	if (!instance.session)
+		return PSA_ERROR_BAD_STATE;
+
+	psa_status_t status = PSA_ERROR_INVALID_ARGUMENT;
+	struct rpc_caller_interface *caller = instance.session->caller;
+	struct psa_invec in_vec[] = {
+		{ .base = psa_ptr_to_u32(&component), .len = sizeof(component) },
+	};
+
+	status = psa_call(caller, TFM_FIRMWARE_UPDATE_SERVICE_HANDLE,
+			  TFM_FWU_CANCEL, in_vec, IOVEC_LEN(in_vec),
+			  NULL, 0);
+	if (status != PSA_SUCCESS)
+		EMSG("failed to psa_call: %d", status);
+
+	return status;
+}
+
+psa_status_t psa_fwu_clean(psa_fwu_component_t component)
+{
+	if (!instance.session)
+		return PSA_ERROR_BAD_STATE;
+
+	psa_status_t status = PSA_ERROR_INVALID_ARGUMENT;
+	struct rpc_caller_interface *caller = instance.session->caller;
+	struct psa_invec in_vec[] = {
+		{ .base = psa_ptr_to_u32(&component), .len = sizeof(component) },
+	};
+
+	status = psa_call(caller, TFM_FIRMWARE_UPDATE_SERVICE_HANDLE,
+			  TFM_FWU_CLEAN, in_vec, IOVEC_LEN(in_vec),
+			  NULL, 0);
+	if (status != PSA_SUCCESS)
+		EMSG("failed to psa_call: %d", status);
+
+	return status;
+}
+
+psa_status_t psa_fwu_install(void)
+{
+	if (!instance.session)
+		return PSA_ERROR_BAD_STATE;
+
+	psa_status_t status = PSA_ERROR_INVALID_ARGUMENT;
+	struct rpc_caller_interface *caller = instance.session->caller;
+	struct psa_invec in_vec[] = {};
+
+	status = psa_call(caller, TFM_FIRMWARE_UPDATE_SERVICE_HANDLE,
+			  TFM_FWU_INSTALL, in_vec, 0,
+			  NULL, 0);
+	if (status != PSA_SUCCESS)
+		EMSG("failed to psa_call: %d", status);
+
+	return status;
+}
+
+psa_status_t psa_fwu_request_reboot(void)
+{
+	if (!instance.session)
+		return PSA_ERROR_BAD_STATE;
+
+	psa_status_t status = PSA_ERROR_INVALID_ARGUMENT;
+	struct rpc_caller_interface *caller = instance.session->caller;
+	struct psa_invec in_vec[] = {};
+
+	status = psa_call(caller, TFM_FIRMWARE_UPDATE_SERVICE_HANDLE,
+			  TFM_FWU_REQUEST_REBOOT, in_vec, 0,
+			  NULL, 0);
+	if (status != PSA_SUCCESS)
+		EMSG("failed to psa_call: %d", status);
+
+	return status;
+}
+
+psa_status_t psa_fwu_reject(psa_status_t error)
+{
+	if (!instance.session)
+		return PSA_ERROR_BAD_STATE;
+
+	psa_status_t status = PSA_ERROR_INVALID_ARGUMENT;
+	struct rpc_caller_interface *caller = instance.session->caller;
+	struct psa_invec in_vec[] = {
+		{ .base = psa_ptr_to_u32(&error), .len = sizeof(error) },
+	};
+
+	status = psa_call(caller, TFM_FIRMWARE_UPDATE_SERVICE_HANDLE,
+			  TFM_FWU_REJECT, in_vec, IOVEC_LEN(in_vec),
+			  NULL, 0);
+	if (status != PSA_SUCCESS)
+		EMSG("failed to psa_call: %d", status);
+
+	return status;
+}
+
+psa_status_t psa_fwu_accept(void)
+{
+	if (!instance.session)
+		return PSA_ERROR_BAD_STATE;
+
+	psa_status_t status = PSA_ERROR_INVALID_ARGUMENT;
+	struct rpc_caller_interface *caller = instance.session->caller;
+	struct psa_invec in_vec[] = {};
+
+	status = psa_call(caller, TFM_FIRMWARE_UPDATE_SERVICE_HANDLE,
+			  TFM_FWU_ACCEPT, in_vec, 0,
+			  NULL, 0);
+	if (status != PSA_SUCCESS)
+		EMSG("failed to psa_call: %d", status);
+
+	return status;
+}
diff --git a/components/service/fwu/psa_fwu_m/interface/psa_ipc/psa_fwu_ipc.h b/components/service/fwu/psa_fwu_m/interface/psa_ipc/psa_fwu_ipc.h
new file mode 100644
index 0000000..867a1c9
--- /dev/null
+++ b/components/service/fwu/psa_fwu_m/interface/psa_ipc/psa_fwu_ipc.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PSA_FWU_IPC_H
+#define PSA_FWU_IPC_H
+
+#include <psa/error.h>
+#include "rpc_caller_session.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief      Initialize a PSA FWU ipc client
+ *
+ * A PSA FWU ipc client makes RPC calls to a remote FWU service.
+ *
+ * @param[in]  rpc_caller RPC caller instance
+ *
+ * @return     A status indicating the success/failure of the operation
+ */
+psa_status_t psa_fwu_ipc_init(struct rpc_caller_session *session);
+
+/**
+ * @brief      Deinitialize a PSA FWU ipc client
+ *
+ */
+void psa_fwu_ipc_deinit(void);
+
+/**
+ * @brief      Return the most recent RPC status
+ *
+ * May be used to obtain information about an RPC error that resulted
+ * in an API operation failure
+ *
+ * @return     Most recent RPC operation status
+ */
+int psa_fwu_rpc_status(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PSA_FWU_IPC_H */
+
diff --git a/components/service/spm_test/spm_test.cmake b/components/service/spm_test/spm_test.cmake
index ed81d5f..b99bf10 100644
--- a/components/service/spm_test/spm_test.cmake
+++ b/components/service/spm_test/spm_test.cmake
@@ -61,6 +61,15 @@
 			RUNTIME DESTINATION ${TS_ENV}/bin
 		)
 
+
+# Convert the base address used for memory region testing for the manifest file. The manifest template will use
+# MEM_REG_LO and MEM_REG_HI.
+# This value is either defined in platform.cmake or on the command line.
+if (NOT DEFINED CFG_TEST_MEM_REGION_ADDRESS)
+	message(FATAL_ERROR "Mandatory variable CFG_TEST_MEM_REGION_ADDRESS is not defined.")
+endif()
+uint64_split(VALUE ${CFG_TEST_MEM_REGION_ADDRESS} OUT_PREFIX MEM_REG)
+
 include(${TS_ROOT}/tools/cmake/common/ExportSp.cmake)
 export_sp(
 	SP_FFA_UUID_CANON ${SP_FFA_UUID_CANON}
diff --git a/deployments/se-proxy/infra/corstone1000/infra.cmake b/deployments/se-proxy/infra/corstone1000/infra.cmake
index 3830f9d..2bf6b36 100644
--- a/deployments/se-proxy/infra/corstone1000/infra.cmake
+++ b/deployments/se-proxy/infra/corstone1000/infra.cmake
@@ -26,7 +26,7 @@
 		"components/service/fwu/provider"
 		"components/service/fwu/provider/serializer"
 		"components/service/fwu/psa_fwu_m/agent"
-		"components/service/fwu/psa_fwu_m/interface/stub"
+		"components/service/fwu/psa_fwu_m/interface/psa_ipc"
 		"components/service/secure_storage/backend/secure_storage_ipc"
 )
 
diff --git a/deployments/se-proxy/infra/corstone1000/service_proxy_factory.c b/deployments/se-proxy/infra/corstone1000/service_proxy_factory.c
index 759983b..0e730e7 100644
--- a/deployments/se-proxy/infra/corstone1000/service_proxy_factory.c
+++ b/deployments/se-proxy/infra/corstone1000/service_proxy_factory.c
@@ -14,6 +14,7 @@
 #include <service/crypto/factory/crypto_provider_factory.h>
 #include "service/fwu/psa_fwu_m/agent/psa_fwu_m_update_agent.h"
 #include "service/fwu/provider/fwu_provider.h"
+#include "service/fwu/psa_fwu_m/interface/psa_ipc/psa_fwu_ipc.h"
 #include <service/secure_storage/frontend/secure_storage_provider/secure_storage_provider.h>
 #include "service/secure_storage/frontend/secure_storage_provider/secure_storage_uuid.h"
 #include <trace.h>
@@ -134,10 +135,25 @@
 
 struct rpc_service_interface *fwu_proxy_create(void)
 {
+	rpc_status_t rpc_status = RPC_ERROR_INTERNAL;
 	static struct update_agent *agent;
 	static struct fwu_provider fwu_provider = { 0 };
 
+	/* Static objects for proxy instance */
+	static struct rpc_caller_interface rse_comms = { 0 };
+	static struct rpc_caller_session rpc_session = { 0 };
+
+	rpc_status = rse_comms_caller_init(&rse_comms);
+	if (rpc_status != RPC_SUCCESS)
+		return NULL;
+
+	rpc_status = rpc_caller_session_open(&rpc_session, &rse_comms, &dummy_uuid, 0, 0);
+	if (rpc_status != RPC_SUCCESS)
+		return NULL;
+
 	agent = psa_fwu_m_update_agent_init(NULL, 0, 4096);
+	if (psa_fwu_ipc_init(&rpc_session) != PSA_SUCCESS)
+		return NULL;
 
 	return fwu_provider_init(&fwu_provider, agent);
 }
diff --git a/deployments/spm-test1/opteesp/default_spm_test1.dts.in b/deployments/spm-test1/opteesp/default_spm_test1.dts.in
index 9d1f719..8ade9fd 100644
--- a/deployments/spm-test1/opteesp/default_spm_test1.dts.in
+++ b/deployments/spm-test1/opteesp/default_spm_test1.dts.in
@@ -26,7 +26,7 @@
 
 		test-region {
 			/* Armv8 A Foundation Platform values */
-			base-address = <0x00000000 0x6248000>;
+			base-address = <@MEM_REG_HI@ @MEM_REG_LO@>;
 			pages-count = <1>;
 			attributes = <0x3>; /* read-write */
 		};
diff --git a/platform/providers/arm/corstone1000/platform.cmake b/platform/providers/arm/corstone1000/platform.cmake
index d39b790..2afcdea 100644
--- a/platform/providers/arm/corstone1000/platform.cmake
+++ b/platform/providers/arm/corstone1000/platform.cmake
@@ -9,11 +9,13 @@
 set(SMM_GATEWAY_MAX_UEFI_VARIABLES 80 CACHE STRING "Maximum UEFI variable count")
 set(SMM_RPC_CALLER_SESSION_SHARED_MEMORY_SIZE 4*4096 CACHE STRING "RPC caller buffer size in SMMGW")
 set(SMM_SP_HEAP_SIZE 80*1024 CACHE STRING "SMM gateway SP heap size")
+set(PLAT_RSE_COMMS_PAYLOAD_MAX_SIZE 0x43C0 CACHE STRING "Size of the RSS_COMMS_PAYLOAD buffer")
+set(COMMS_MHU_MSG_SIZE 0x4500 CACHE STRING "Max message size that can be transfered via MHU")
 
 target_compile_definitions(${TGT} PRIVATE
-	SMM_VARIABLE_INDEX_STORAGE_UID=0x787
-	PLAT_RSE_COMMS_PAYLOAD_MAX_SIZE=0x2080
-	COMMS_MHU_MSG_SIZE=0x3500
+	PLAT_RSE_COMMS_PAYLOAD_MAX_SIZE=${PLAT_RSE_COMMS_PAYLOAD_MAX_SIZE}
+	COMMS_MHU_MSG_SIZE=${COMMS_MHU_MSG_SIZE}
+	MBEDTLS_ECP_DP_SECP521R1_ENABLED
 )
 
 get_property(_platform_driver_dependencies TARGET ${TGT}
diff --git a/platform/providers/arm/fvp/fvp_base_revc-2xaemv8a/platform.cmake b/platform/providers/arm/fvp/fvp_base_revc-2xaemv8a/platform.cmake
index 143ea46..c71ed09 100644
--- a/platform/providers/arm/fvp/fvp_base_revc-2xaemv8a/platform.cmake
+++ b/platform/providers/arm/fvp/fvp_base_revc-2xaemv8a/platform.cmake
@@ -15,6 +15,9 @@
 
 set(CFG_SFS_FLASH_AREA_SIZE "32*1024" CACHE STRING "Size of SFS ram store")
 
+# Test memory region base address for manifest testing in spm_test deployments.
+set(CFG_TEST_MEM_REGION_ADDRESS  0x6248000 CACHE STRING "Base address of memory region used to test mainfest processing.")
+
 #-------------------------------------------------------------------------------
 #  Map platform dependencies to suitable drivers for this platform
 #
diff --git a/tools/cmake/common/Utils.cmake b/tools/cmake/common/Utils.cmake
index 256bbf9..6471619 100644
--- a/tools/cmake/common/Utils.cmake
+++ b/tools/cmake/common/Utils.cmake
@@ -106,3 +106,62 @@
 		set_target_properties(${_MY_PARAMS_TGT} PROPERTIES OUTPUT_NAME "${_out_name}")
 	endif()
 endfunction()
+
+#[===[.rst:
+.. cmake:command:: uint64_split
+
+	.. code-block:: cmake
+
+		uint64_split(VALUE 4294967296 OUT_PREFIX RES)
+		message("RES_LO=${RES_LO} RES_HI=${RES_HI}")
+
+		uint64_split(VALUE 0x1122334455667788 OUT_PREFIX RES DECIMAL)
+		message("RES_LO=${RES_LO} RES_HI=${RES_HI}")
+
+	Split an uint64 integer to uint32 integers. The returned values will be hexadecimal unless the 	``DECIMAL``
+	argument is passed.
+	The result is returned in two values <OUT_PREFIX>_LO and <OUT_PREFIX>_HI.
+
+	INPUTS:
+
+	``VALUE``
+	Mandatory. uint64 value to be converted. The value shall either be an integer (e.g. 123) or a string representing
+	an integer (e.g. "123"). Hexadecimal numbers can be specified with "0x" prefix.
+
+	``DECIMAL``
+	Optional. Set the format of the returned values to be decimal instead of hexadecimal.
+
+	OUTPUTS:
+
+	``OUT_PREFIX``
+	Mandatory. The prefix of the output variables. Two variable will be created in the callers scope. <OUT_PREFIX>_LO
+	is the lower 32 bits and <OUT_PREFIX>_HI is the higher 32 bits.
+
+#]===]
+function(uint64_split )
+	set(options DECIMAL)
+	set(oneValueArgs VALUE OUT_PREFIX)
+	set(multiValueArgs)
+	cmake_parse_arguments(_MY_PARAMS "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
+
+	check_args(uint64_split VALUE OUT_PREFIX)
+
+	# Ensure the input is a valid uint64 integer
+	if (NOT "${_MY_PARAMS_VALUE}" MATCHES "^(0x[0-9a-fA-F]+)|([0-9]+)$")
+		message(FATAL_ERROR "${CMAKE_CURRENT_FUNCTION}: Invalid uint64 integer: ${_MY_PARAMS_VALUE}")
+	endif()
+
+	if (_MY_PARAMS_DECIMAL)
+		set(_out_format "DECIMAL")
+	else()
+		set(_out_format "HEXADECIMAL")
+	endif()
+
+	# Split the uint64 integer into two uint32 integers
+	math(EXPR _high_uint32 "(${_MY_PARAMS_VALUE} >> 32) & 0xFFFFFFFF" OUTPUT_FORMAT ${_out_format})
+	math(EXPR _low_uint32 "${_MY_PARAMS_VALUE} & 0xFFFFFFFF" OUTPUT_FORMAT ${_out_format})
+
+	# Return the results
+	set(${_MY_PARAMS_OUT_PREFIX}_LO ${_low_uint32} PARENT_SCOPE)
+	set(${_MY_PARAMS_OUT_PREFIX}_HI ${_high_uint32} PARENT_SCOPE)
+endfunction()