feat(intel): support SHA-2 hash digest generation on a blob

This command is to request the SHA-2 hash digest on a blob.
If input has a key, the output shall be key-hash digest.

Signed-off-by: Siew Chin Lim <elly.siew.chin.lim@intel.com>
Signed-off-by: Boon Khai Ng <boon.khai.ng@intel.com>
Signed-off-by: Sieu Mun Tang <sieu.mun.tang@intel.com>
Change-Id: I08cb82d89a8e8f7bfe04f5f01e079ea49fe38cf5
diff --git a/plat/intel/soc/common/include/socfpga_fcs.h b/plat/intel/soc/common/include/socfpga_fcs.h
index da982e1..db8f558 100644
--- a/plat/intel/soc/common/include/socfpga_fcs.h
+++ b/plat/intel/soc/common/include/socfpga_fcs.h
@@ -9,61 +9,64 @@
 
 /* FCS Definitions */
 
-#define FCS_RANDOM_WORD_SIZE		8U
-#define FCS_PROV_DATA_WORD_SIZE		44U
-#define FCS_SHA384_WORD_SIZE		12U
+#define FCS_RANDOM_WORD_SIZE			8U
+#define FCS_PROV_DATA_WORD_SIZE			44U
+#define FCS_SHA384_WORD_SIZE			12U
 
-#define FCS_RANDOM_BYTE_SIZE		(FCS_RANDOM_WORD_SIZE * 4U)
-#define FCS_RANDOM_EXT_MAX_WORD_SIZE	1020U
-#define FCS_PROV_DATA_BYTE_SIZE		(FCS_PROV_DATA_WORD_SIZE * 4U)
-#define FCS_SHA384_BYTE_SIZE		(FCS_SHA384_WORD_SIZE * 4U)
+#define FCS_RANDOM_BYTE_SIZE			(FCS_RANDOM_WORD_SIZE * 4U)
+#define FCS_RANDOM_EXT_MAX_WORD_SIZE		1020U
+#define FCS_PROV_DATA_BYTE_SIZE			(FCS_PROV_DATA_WORD_SIZE * 4U)
+#define FCS_SHA384_BYTE_SIZE			(FCS_SHA384_WORD_SIZE * 4U)
 
-#define FCS_RANDOM_EXT_OFFSET		3
+#define FCS_RANDOM_EXT_OFFSET			3
 
-#define FCS_MODE_DECRYPT		0x0
-#define FCS_MODE_ENCRYPT		0x1
-#define FCS_ENCRYPTION_DATA_0		0x10100
-#define FCS_DECRYPTION_DATA_0		0x10102
-#define FCS_OWNER_ID_OFFSET		0xC
+#define FCS_MODE_DECRYPT			0x0
+#define FCS_MODE_ENCRYPT			0x1
+#define FCS_ENCRYPTION_DATA_0			0x10100
+#define FCS_DECRYPTION_DATA_0			0x10102
+#define FCS_OWNER_ID_OFFSET			0xC
 
-#define PSGSIGMA_TEARDOWN_MAGIC		0xB852E2A4
-#define	PSGSIGMA_SESSION_ID_ONE		0x1
-#define PSGSIGMA_UNKNOWN_SESSION	0xFFFFFFFF
+#define PSGSIGMA_TEARDOWN_MAGIC			0xB852E2A4
+#define	PSGSIGMA_SESSION_ID_ONE			0x1
+#define PSGSIGMA_UNKNOWN_SESSION		0xFFFFFFFF
 
-#define	RESERVED_AS_ZERO		0x0
+#define	RESERVED_AS_ZERO			0x0
 /* FCS Single cert */
 
-#define FCS_BIG_CNTR_SEL		0x1
+#define FCS_BIG_CNTR_SEL			0x1
 
-#define FCS_SVN_CNTR_0_SEL		0x2
-#define FCS_SVN_CNTR_1_SEL		0x3
-#define FCS_SVN_CNTR_2_SEL		0x4
-#define FCS_SVN_CNTR_3_SEL		0x5
+#define FCS_SVN_CNTR_0_SEL			0x2
+#define FCS_SVN_CNTR_1_SEL			0x3
+#define FCS_SVN_CNTR_2_SEL			0x4
+#define FCS_SVN_CNTR_3_SEL			0x5
 
-#define FCS_BIG_CNTR_VAL_MAX		495U
-#define FCS_SVN_CNTR_VAL_MAX		64U
+#define FCS_BIG_CNTR_VAL_MAX			495U
+#define FCS_SVN_CNTR_VAL_MAX			64U
 
 /* FCS Attestation Cert Request Parameter */
 
-#define FCS_ALIAS_CERT			0x01
-#define FCS_DEV_ID_SELF_SIGN_CERT	0x02
-#define FCS_DEV_ID_ENROLL_CERT		0x04
-#define FCS_ENROLL_SELF_SIGN_CERT	0x08
-#define FCS_PLAT_KEY_CERT		0x10
+#define FCS_ALIAS_CERT				0x01
+#define FCS_DEV_ID_SELF_SIGN_CERT		0x02
+#define FCS_DEV_ID_ENROLL_CERT			0x04
+#define FCS_ENROLL_SELF_SIGN_CERT		0x08
+#define FCS_PLAT_KEY_CERT			0x10
 
 /* FCS Crypto Service */
 
-#define FCS_CS_KEY_OBJ_MAX_WORD_SIZE	88U
-#define FCS_CS_KEY_INFO_MAX_WORD_SIZE	36U
-#define FCS_CS_KEY_RESP_STATUS_MASK	0xFF
-#define FCS_CS_KEY_RESP_STATUS_OFFSET	16U
+#define FCS_CS_KEY_OBJ_MAX_WORD_SIZE		88U
+#define FCS_CS_KEY_INFO_MAX_WORD_SIZE		36U
+#define FCS_CS_KEY_RESP_STATUS_MASK		0xFF
+#define FCS_CS_KEY_RESP_STATUS_OFFSET		16U
 
-#define FCS_CS_FIELD_SIZE_MASK		0xFFFF
-#define FCS_CS_FIELD_FLAG_OFFSET	24
-#define FCS_CS_FIELD_FLAG_INIT		BIT(0)
-#define FCS_CS_FIELD_FLAG_UPDATE	BIT(1)
-#define FCS_CS_FIELD_FLAG_FINALIZE	BIT(2)
+#define FCS_CS_FIELD_SIZE_MASK			0xFFFF
+#define FCS_CS_FIELD_FLAG_OFFSET		24
+#define FCS_CS_FIELD_FLAG_INIT			BIT(0)
+#define FCS_CS_FIELD_FLAG_UPDATE		BIT(1)
+#define FCS_CS_FIELD_FLAG_FINALIZE		BIT(2)
 
+#define FCS_GET_DIGEST_CMD_MAX_WORD_SIZE	7U
+#define FCS_GET_DIGEST_RESP_MAX_WORD_SIZE	19U
+#define FCS_SHA_HMAC_CRYPTO_PARAM_SIZE_OFFSET	8U
 /* FCS Payload Structure */
 typedef struct fcs_rng_payload_t {
 	uint32_t session_id;
@@ -107,6 +110,14 @@
 	uint32_t key_id;
 } fcs_cs_key_payload;
 
+typedef struct fcs_crypto_service_data_t {
+	uint32_t session_id;
+	uint32_t context_id;
+	uint32_t key_id;
+	uint32_t crypto_param_size;
+	uint64_t crypto_param;
+} fcs_crypto_service_data;
+
 /* Functions Definitions */
 
 uint32_t intel_fcs_random_number_gen(uint64_t addr, uint64_t *ret_size,
@@ -160,4 +171,12 @@
 				uint64_t dst_addr, uint32_t *dst_size,
 				uint32_t *mbox_error);
 
+int intel_fcs_get_digest_init(uint32_t session_id, uint32_t context_id,
+				uint32_t key_id, uint32_t param_size,
+				uint64_t param_data, uint32_t *mbox_error);
+int intel_fcs_get_digest_finalize(uint32_t session_id, uint32_t context_id,
+				uint32_t src_addr, uint32_t src_size,
+				uint64_t dst_addr, uint32_t *dst_size,
+				uint32_t *mbox_error);
+
 #endif /* SOCFPGA_FCS_H */
diff --git a/plat/intel/soc/common/include/socfpga_mailbox.h b/plat/intel/soc/common/include/socfpga_mailbox.h
index f969a35..4984020 100644
--- a/plat/intel/soc/common/include/socfpga_mailbox.h
+++ b/plat/intel/soc/common/include/socfpga_mailbox.h
@@ -75,6 +75,7 @@
 #define MBOX_FCS_ENCRYPT_REQ				0x7E
 #define MBOX_FCS_DECRYPT_REQ				0x7F
 #define MBOX_FCS_RANDOM_GEN				0x80
+#define MBOX_FCS_GET_DIGEST_REQ				0x82
 #define MBOX_FCS_OPEN_CS_SESSION			0xA0
 #define MBOX_FCS_CLOSE_CS_SESSION			0xA1
 #define MBOX_FCS_IMPORT_CS_KEY				0xA5
diff --git a/plat/intel/soc/common/include/socfpga_sip_svc.h b/plat/intel/soc/common/include/socfpga_sip_svc.h
index e790669..f05e861 100644
--- a/plat/intel/soc/common/include/socfpga_sip_svc.h
+++ b/plat/intel/soc/common/include/socfpga_sip_svc.h
@@ -93,7 +93,12 @@
 #define INTEL_SIP_SMC_FCS_EXPORT_CS_KEY			0xC2000071
 #define INTEL_SIP_SMC_FCS_REMOVE_CS_KEY			0xC2000072
 #define INTEL_SIP_SMC_FCS_GET_CS_KEY_INFO		0xC2000073
+#define INTEL_SIP_SMC_FCS_GET_DIGEST_INIT		0xC2000077
+#define INTEL_SIP_SMC_FCS_GET_DIGEST_FINALIZE		0xC2000079
 
+#define INTEL_SIP_SMC_FCS_SHA_MODE_MASK			0xF
+#define INTEL_SIP_SMC_FCS_DIGEST_SIZE_MASK		0xF
+#define INTEL_SIP_SMC_FCS_DIGEST_SIZE_OFFSET		4U
 /* ECC DBE */
 #define WARM_RESET_WFI_FLAG				BIT(31)
 #define SYSMGR_ECC_DBE_COLD_RST_MASK			(SYSMGR_ECC_OCRAM_MASK |\
diff --git a/plat/intel/soc/common/sip/socfpga_sip_fcs.c b/plat/intel/soc/common/sip/socfpga_sip_fcs.c
index 7b3069b..809037e 100644
--- a/plat/intel/soc/common/sip/socfpga_sip_fcs.c
+++ b/plat/intel/soc/common/sip/socfpga_sip_fcs.c
@@ -11,6 +11,9 @@
 #include "socfpga_mailbox.h"
 #include "socfpga_sip_svc.h"
 
+/* FCS static variables */
+static fcs_crypto_service_data fcs_sha_get_digest_param;
+
 bool is_size_4_bytes_aligned(uint32_t size)
 {
 	if ((size % MBOX_WORD_BYTE) != 0U) {
@@ -18,6 +21,42 @@
 	} else {
 		return true;
 	}
+}
+
+static bool is_8_bytes_aligned(uint32_t data)
+{
+	if ((data % (MBOX_WORD_BYTE * 2U)) != 0U) {
+		return false;
+	} else {
+		return true;
+	}
+}
+
+static int intel_fcs_crypto_service_init(uint32_t session_id,
+			uint32_t context_id, uint32_t key_id,
+			uint32_t param_size, uint64_t param_data,
+			fcs_crypto_service_data *data_addr,
+			uint32_t *mbox_error)
+{
+	if (mbox_error == NULL) {
+		return INTEL_SIP_SMC_STATUS_REJECTED;
+	}
+
+	if (param_size != 4) {
+		return INTEL_SIP_SMC_STATUS_REJECTED;
+	}
+
+	memset(data_addr, 0, sizeof(fcs_crypto_service_data));
+
+	data_addr->session_id = session_id;
+	data_addr->context_id = context_id;
+	data_addr->key_id = key_id;
+	data_addr->crypto_param_size = param_size;
+	data_addr->crypto_param = param_data;
+
+	*mbox_error = 0;
+
+	return INTEL_SIP_SMC_STATUS_OK;
 }
 
 uint32_t intel_fcs_random_number_gen(uint64_t addr, uint64_t *ret_size,
@@ -673,3 +712,88 @@
 
 	return INTEL_SIP_SMC_STATUS_OK;
 }
+
+int intel_fcs_get_digest_init(uint32_t session_id, uint32_t context_id,
+				uint32_t key_id, uint32_t param_size,
+				uint64_t param_data, uint32_t *mbox_error)
+{
+	return intel_fcs_crypto_service_init(session_id, context_id,
+				key_id, param_size, param_data,
+				(void *) &fcs_sha_get_digest_param,
+				mbox_error);
+}
+
+int intel_fcs_get_digest_finalize(uint32_t session_id, uint32_t context_id,
+				uint32_t src_addr, uint32_t src_size,
+				uint64_t dst_addr, uint32_t *dst_size,
+				uint32_t *mbox_error)
+{
+	int status;
+	uint32_t i;
+	uint32_t resp_len = *dst_size / MBOX_WORD_BYTE;
+	uint32_t payload[FCS_GET_DIGEST_CMD_MAX_WORD_SIZE] = {0U};
+
+	if (dst_size == NULL || mbox_error == NULL) {
+		return INTEL_SIP_SMC_STATUS_REJECTED;
+	}
+
+	if (fcs_sha_get_digest_param.session_id != session_id ||
+	    fcs_sha_get_digest_param.context_id != context_id) {
+		return INTEL_SIP_SMC_STATUS_REJECTED;
+	}
+
+	/* Source data must be 8 bytes aligned */
+	if (!is_8_bytes_aligned(src_size)) {
+		return INTEL_SIP_SMC_STATUS_REJECTED;
+	}
+
+	if (!is_address_in_ddr_range(src_addr, src_size) ||
+		 !is_address_in_ddr_range(dst_addr, *dst_size)) {
+		return INTEL_SIP_SMC_STATUS_REJECTED;
+	}
+
+	/* Prepare command payload */
+	i = 0;
+	/* Crypto header */
+	payload[i] = fcs_sha_get_digest_param.session_id;
+	i++;
+	payload[i] = fcs_sha_get_digest_param.context_id;
+	i++;
+	payload[i] = fcs_sha_get_digest_param.crypto_param_size
+			& FCS_CS_FIELD_SIZE_MASK;
+	payload[i] |= (FCS_CS_FIELD_FLAG_INIT | FCS_CS_FIELD_FLAG_UPDATE
+			| FCS_CS_FIELD_FLAG_FINALIZE)
+			<< FCS_CS_FIELD_FLAG_OFFSET;
+	i++;
+	payload[i] = fcs_sha_get_digest_param.key_id;
+	i++;
+	/* Crypto parameters */
+	payload[i] = fcs_sha_get_digest_param.crypto_param
+			& INTEL_SIP_SMC_FCS_SHA_MODE_MASK;
+	payload[i] |= ((fcs_sha_get_digest_param.crypto_param
+			>> INTEL_SIP_SMC_FCS_DIGEST_SIZE_OFFSET)
+			& INTEL_SIP_SMC_FCS_DIGEST_SIZE_MASK)
+			<< FCS_SHA_HMAC_CRYPTO_PARAM_SIZE_OFFSET;
+	i++;
+	/* Data source address and size */
+	payload[i] = src_addr;
+	i++;
+	payload[i] = src_size;
+	i++;
+
+	status = mailbox_send_cmd(MBOX_JOB_ID, MBOX_FCS_GET_DIGEST_REQ,
+				payload, i, CMD_CASUAL,
+				(uint32_t *) dst_addr, &resp_len);
+
+	memset((void *)&fcs_sha_get_digest_param, 0, sizeof(fcs_crypto_service_data));
+
+	if (status < 0) {
+		*mbox_error = -status;
+		return INTEL_SIP_SMC_STATUS_ERROR;
+	}
+
+	*dst_size = resp_len * MBOX_WORD_BYTE;
+	flush_dcache_range(dst_addr, *dst_size);
+
+	return INTEL_SIP_SMC_STATUS_OK;
+}
diff --git a/plat/intel/soc/common/socfpga_sip_svc.c b/plat/intel/soc/common/socfpga_sip_svc.c
index 24683ea..f9a376e 100644
--- a/plat/intel/soc/common/socfpga_sip_svc.c
+++ b/plat/intel/soc/common/socfpga_sip_svc.c
@@ -867,6 +867,19 @@
 					(uint32_t *) &x4, &mbox_error);
 		SMC_RET4(handle, status, mbox_error, x3, x4);
 
+	case INTEL_SIP_SMC_FCS_GET_DIGEST_INIT:
+		x5 = SMC_GET_GP(handle, CTX_GPREG_X5);
+		status = intel_fcs_get_digest_init(x1, x2, x3,
+					x4, x5, &mbox_error);
+		SMC_RET2(handle, status, mbox_error);
+
+	case INTEL_SIP_SMC_FCS_GET_DIGEST_FINALIZE:
+		x5 = SMC_GET_GP(handle, CTX_GPREG_X5);
+		x6 = SMC_GET_GP(handle, CTX_GPREG_X6);
+		status = intel_fcs_get_digest_finalize(x1, x2, x3,
+					 x4, x5, (uint32_t *) &x6, &mbox_error);
+		SMC_RET4(handle, status, mbox_error, x5, x6);
+
 	case INTEL_SIP_SMC_GET_ROM_PATCH_SHA384:
 		status = intel_fcs_get_rom_patch_sha384(x1, &retval64,
 							&mbox_error);