feat(drtm): validate launch features in DRTM parameters

Perform sanity checks on the launch features received via DRTM parameters.
Return INVALID_PARAMETERS if they are incorrect.

Change-Id: I7e8068154028d1c8f6b6b45449616bb5711ea76e
Signed-off-by: Manish V Badarkhe <Manish.Badarkhe@arm.com>
diff --git a/include/services/drtm_svc.h b/include/services/drtm_svc.h
index 3503fa4..86110db 100644
--- a/include/services/drtm_svc.h
+++ b/include/services/drtm_svc.h
@@ -14,6 +14,8 @@
 #ifndef ARM_DRTM_SVC_H
 #define ARM_DRTM_SVC_H
 
+#include <lib/utils_def.h>
+
 /*
  * SMC function IDs for DRTM Service
  * Upper word bits set: Fast call, SMC64, Standard Secure Svc. Call (OEN = 4)
@@ -239,6 +241,21 @@
 		<< ARM_DRTM_REGION_SIZE_TYPE_4K_PAGE_NUM_SHIFT));	\
 	} while (false)
 
+#define DRTM_LAUNCH_FEAT_DLME_IMG_AUTH_SHIFT		U(6)
+#define DRTM_LAUNCH_FEAT_MEM_PROTECTION_TYPE_SHIFT	U(3)
+#define DRTM_LAUNCH_FEAT_PCR_USAGE_SCHEMA_SHIFT		U(1)
+#define DRTM_LAUNCH_FEAT_HASHING_TYPE_SHIFT		U(0)
+
+#define DRTM_LAUNCH_FEAT_DLME_IMG_AUTH_MASK      	U(0x1)
+#define DRTM_LAUNCH_FEAT_MEM_PROTECTION_TYPE_MASK 	U(0x7)
+#define DRTM_LAUNCH_FEAT_PCR_USAGE_SCHEMA_MASK   	U(0x3)
+#define DRTM_LAUNCH_FEAT_HASHING_TYPE_MASK       	U(0x1)
+
+#define DLME_IMG_AUTH					U(0x1)
+#define REG_MEM_PROTECTION_TYPE				U(0x1)
+#define DLME_AUTH_SCHEMA				U(0x1)
+#define TPM_BASED_HASHING				U(0x1)
+
 /* Initialization routine for the DRTM service */
 int drtm_setup(void);
 
diff --git a/services/std_svc/drtm/drtm_main.c b/services/std_svc/drtm/drtm_main.c
index 117934f..c302863 100644
--- a/services/std_svc/drtm/drtm_main.c
+++ b/services/std_svc/drtm/drtm_main.c
@@ -34,6 +34,8 @@
 
 /* DRTM-formatted memory map. */
 static drtm_memory_region_descriptor_table_t *plat_drtm_mem_map;
+static const plat_drtm_dma_prot_features_t *plat_dma_prot_feat;
+static const plat_drtm_tpm_features_t *plat_tpm_feat;
 
 /* DLME header */
 struct_dlme_data_header dlme_data_hdr_init;
@@ -44,8 +46,6 @@
 int drtm_setup(void)
 {
 	bool rc;
-	const plat_drtm_tpm_features_t *plat_tpm_feat;
-	const plat_drtm_dma_prot_features_t *plat_dma_prot_feat;
 
 	INFO("DRTM service setup\n");
 
@@ -322,6 +322,43 @@
 	return SUCCESS;
 }
 
+/* Function to check if the value is valid for each bit field */
+static int drtm_dl_check_features_sanity(uint32_t val)
+{
+	/**
+	 * Ensure that if DLME Authorities Schema (Bits [2:1]) is set, then
+	 * DLME image authentication (Bit[6]) must also be set
+	 */
+	if ((EXTRACT_FIELD(val, DRTM_LAUNCH_FEAT_PCR_USAGE_SCHEMA_MASK,
+			   DRTM_LAUNCH_FEAT_PCR_USAGE_SCHEMA_SHIFT) == DLME_AUTH_SCHEMA) &&
+	    (EXTRACT_FIELD(val, DRTM_LAUNCH_FEAT_DLME_IMG_AUTH_MASK,
+			    DRTM_LAUNCH_FEAT_DLME_IMG_AUTH_SHIFT) != DLME_IMG_AUTH)) {
+		return INVALID_PARAMETERS;
+	}
+
+	/**
+	 * Check if Bits [5:3] (Memory protection type) matches with platform's
+	 * memory protection type
+	 */
+	if (EXTRACT_FIELD(val, DRTM_LAUNCH_FEAT_MEM_PROTECTION_TYPE_MASK,
+			  DRTM_LAUNCH_FEAT_MEM_PROTECTION_TYPE_SHIFT) !=
+	    __builtin_ctz(plat_dma_prot_feat->dma_protection_support)) {
+		return INVALID_PARAMETERS;
+	}
+
+	/**
+	 * Check if Bits [0] (Type of hashing) matches with platform's
+	 * supported hash type.
+	 */
+	if (EXTRACT_FIELD(val, DRTM_LAUNCH_FEAT_HASHING_TYPE_MASK,
+			  DRTM_LAUNCH_FEAT_HASHING_TYPE_SHIFT) !=
+	    plat_tpm_feat->tpm_based_hash_support) {
+		return INVALID_PARAMETERS;
+	}
+
+	return 0;
+}
+
 /*
  * Note: accesses to the dynamic launch args, and to the DLME data are
  * little-endian as required, thanks to TF-A BL31 init requirements.
@@ -369,7 +406,7 @@
 	args_buf = *a;
 
 	rc = mmap_remove_dynamic_region(va_mapping, va_mapping_size);
-	if (rc) {
+	if (rc != 0) {
 		ERROR("%s(): mmap_remove_dynamic_region() failed unexpectedly"
 		      " rc=%d\n", __func__, rc);
 		panic();
@@ -383,6 +420,13 @@
 		return NOT_SUPPORTED;
 	}
 
+	rc = drtm_dl_check_features_sanity(a->features);
+	if (rc != 0) {
+		ERROR("%s(): drtm_dl_check_features_sanity() failed.\n"
+				" rc=%d\n", __func__, rc);
+		return rc;
+	}
+
 	if (!(a->dlme_img_off < a->dlme_size &&
 	      a->dlme_data_off < a->dlme_size)) {
 		ERROR("DRTM: argument offset is outside of the DLME region\n");