feat(rmmd): el3 token sign during attestation

Add required SMCs by RMM to push attestation signing requests to EL3
and get responses. EL3 may then choose to push these requests to a HES
as suitable for a platform. This patch also supports the new
RMM_EL3_FEATURES interface, that RMM can use to query for support for
HES based signing. The new interface exposes a feature register with
different bits defining different discoverable features. This new
interface is available starting the 0.4 version of the RMM-EL3
interface, causing the version to bump up. This patch also adds a
platform port for FVP that implements the platform hooks required to
enable the new SMCs, but it does not push to a HES and instead copies a
zeroed buffer in EL3.

Change-Id: I69c110252835122a9533e71bdcce10b5f2a686b2
Signed-off-by: Raghu Krishnamurthy <raghupathyk@nvidia.com>
diff --git a/include/plat/common/platform.h b/include/plat/common/platform.h
index ae5aa23..118b537 100644
--- a/include/plat/common/platform.h
+++ b/include/plat/common/platform.h
@@ -15,6 +15,7 @@
 #endif
 #if ENABLE_RME
 #include <services/rmm_core_manifest.h>
+#include <services/rmm_el3_token_sign.h>
 #endif
 #include <drivers/fwu/fwu_metadata.h>
 #if TRNG_SUPPORT
@@ -376,6 +377,15 @@
 				   uint64_t *remaining_len);
 int plat_rmmd_get_cca_realm_attest_key(uintptr_t buf, size_t *len,
 				       unsigned int type);
+/* The following 3 functions are to be implement if
+ * RMMD_ENABLE_EL3_TOKEN_SIGN=1.
+ * The following three functions are expected to return E_RMM_* error codes.
+ */
+int plat_rmmd_el3_token_sign_get_rak_pub(uintptr_t buf, size_t *len,
+					   unsigned int type);
+int plat_rmmd_el3_token_sign_push_req(
+				const struct el3_token_sign_request *req);
+int plat_rmmd_el3_token_sign_pull_resp(struct el3_token_sign_response *resp);
 size_t plat_rmmd_get_el3_rmm_shared_mem(uintptr_t *shared);
 int plat_rmmd_load_manifest(struct rmm_manifest *manifest);
 #endif
diff --git a/include/services/rmm_el3_token_sign.h b/include/services/rmm_el3_token_sign.h
new file mode 100644
index 0000000..154940c
--- /dev/null
+++ b/include/services/rmm_el3_token_sign.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2024, NVIDIA Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef RMM_EL3_TOKEN_SIGN_H
+#define RMM_EL3_TOKEN_SIGN_H
+
+#include <stdint.h>
+#include <lib/cassert.h>
+#include <services/rmmd_svc.h>
+
+/*
+ * Defines member of structure and reserves space
+ * for the next member with specified offset.
+ */
+/* cppcheck-suppress [misra-c2012-20.7] */
+#define SET_MEMBER(member, start, end)	\
+	union {				\
+		member;			\
+		unsigned char reserved##end[((end) - (start))];	\
+	}
+
+#define EL3_TOKEN_RESPONSE_MAX_SIG_LEN U(512)
+
+struct el3_token_sign_request {
+	SET_MEMBER(uint32_t sig_alg_id, 0x0, 0x8);
+	SET_MEMBER(uint64_t rec_granule, 0x8, 0x10);
+	SET_MEMBER(uint64_t req_ticket, 0x10, 0x18);
+	SET_MEMBER(uint32_t hash_alg_id, 0x18, 0x20);
+	SET_MEMBER(uint8_t hash_buf[SHA512_DIGEST_SIZE], 0x20, 0x60);
+};
+
+CASSERT(__builtin_offsetof(struct el3_token_sign_request, sig_alg_id) == 0x0U,
+	assert_el3_token_sign_request_sig_alg_mismatch);
+CASSERT(__builtin_offsetof(struct el3_token_sign_request, rec_granule) == 0x8U,
+	assert_el3_token_sign_request_rec_granule_mismatch);
+CASSERT(__builtin_offsetof(struct el3_token_sign_request, req_ticket) == 0x10U,
+	assert_el3_token_sign_request_req_ticket_mismatch);
+CASSERT(__builtin_offsetof(struct el3_token_sign_request, hash_alg_id) == 0x18U,
+	assert_el3_token_sign_request_hash_alg_id_mismatch);
+CASSERT(__builtin_offsetof(struct el3_token_sign_request, hash_buf) == 0x20U,
+	assert_el3_token_sign_request_hash_buf_mismatch);
+
+
+struct el3_token_sign_response {
+	SET_MEMBER(uint64_t rec_granule, 0x0, 0x8);
+	SET_MEMBER(uint64_t req_ticket, 0x8, 0x10);
+	SET_MEMBER(uint16_t sig_len, 0x10, 0x12);
+	SET_MEMBER(uint8_t signature_buf[EL3_TOKEN_RESPONSE_MAX_SIG_LEN], 0x12, 0x212);
+};
+
+CASSERT(__builtin_offsetof(struct el3_token_sign_response, rec_granule) == 0x0U,
+	assert_el3_token_sign_resp_rec_granule_mismatch);
+CASSERT(__builtin_offsetof(struct el3_token_sign_response, req_ticket) == 0x8U,
+	assert_el3_token_sign_resp_req_ticket_mismatch);
+CASSERT(__builtin_offsetof(struct el3_token_sign_response, sig_len) == 0x10U,
+	assert_el3_token_sign_resp_sig_len_mismatch);
+CASSERT(__builtin_offsetof(struct el3_token_sign_response, signature_buf) == 0x12U,
+	assert_el3_token_sign_resp_sig_buf_mismatch);
+
+#endif /* RMM_EL3_TOKEN_SIGN_H */
diff --git a/include/services/rmmd_svc.h b/include/services/rmmd_svc.h
index 635c28e..0cc8628 100644
--- a/include/services/rmmd_svc.h
+++ b/include/services/rmmd_svc.h
@@ -129,8 +129,43 @@
 					/* 0x1B3 */
 #define RMM_ATTEST_GET_PLAT_TOKEN	SMC64_RMMD_EL3_FID(U(3))
 
+/* Starting RMM-EL3 interface version 0.4 */
+#define RMM_EL3_FEATURES				SMC64_RMMD_EL3_FID(U(4))
+#define RMM_EL3_FEAT_REG_0_IDX				U(0)
+/* Bit 0 of FEAT_REG_0 */
+/* 1 - the feature is present in EL3 , 0 - the feature is absent */
+#define RMM_EL3_FEAT_REG_0_EL3_TOKEN_SIGN_MASK		U(0x1)
+
+/*
+ * Function codes to support attestation where EL3 is used to sign
+ * realm attestation tokens. In this model, the private key is not
+ * exposed to the RMM.
+ * The arguments to this SMC are:
+ *     arg0 - Function ID.
+ *     arg1 - Opcode, one of:
+ *               RMM_EL3_TOKEN_SIGN_PUSH_REQ_OP,
+ *               RMM_EL3_TOKEN_SIGN_PULL_RESP_OP,
+ *               RMM_EL3_TOKEN_SIGN_GET_RAK_PUB_OP
+ *     arg2 - Pointer to buffer with request/response structures,
+ *            which is in the RMM<->EL3 shared buffer.
+ *     arg3 - Buffer size of memory pointed by arg2.
+ *     arg4 - ECC Curve, when opcode is RMM_EL3_TOKEN_SIGN_GET_RAK_PUB_OP
+ * The return arguments are:
+ *     ret0 - Status/Error
+ *     ret1 - Size of public key if opcode is RMM_EL3_TOKEN_SIGN_GET_RAK_PUB_OP
+ */
+#define RMM_EL3_TOKEN_SIGN			SMC64_RMMD_EL3_FID(U(5))
+
+/* Opcodes for RMM_EL3_TOKEN_SIGN  */
+#define RMM_EL3_TOKEN_SIGN_PUSH_REQ_OP          U(1)
+#define RMM_EL3_TOKEN_SIGN_PULL_RESP_OP         U(2)
+#define RMM_EL3_TOKEN_SIGN_GET_RAK_PUB_OP       U(3)
+
 /* ECC Curve types for attest key generation */
-#define ATTEST_KEY_CURVE_ECC_SECP384R1		0
+#define ATTEST_KEY_CURVE_ECC_SECP384R1		U(0)
+
+/* Identifier for the hash algorithm used for attestation signing */
+#define EL3_TOKEN_SIGN_HASH_ALG_SHA384		U(1)
 
 /*
  * RMM_BOOT_COMPLETE originates on RMM when the boot finishes (either cold
@@ -153,7 +188,7 @@
  * Increase this when a bug is fixed, or a feature is added without
  * breaking compatibility.
  */
-#define RMM_EL3_IFC_VERSION_MINOR	(U(3))
+#define RMM_EL3_IFC_VERSION_MINOR	(U(4))
 
 #define RMM_EL3_INTERFACE_VERSION				\
 	(((RMM_EL3_IFC_VERSION_MAJOR << 16) & 0x7FFFF) |	\