feat(drtm): add Event Log driver support for DRTM

Added Event Log driver support for DRTM. This driver
is responsible for the doing the hash measurement of
various DRTM components as per [1], and putting these
measurements in the Event Log buffer.

[1]: https://developer.arm.com/documentation/den0113/a, section 3.16

Change-Id: I9892c313cf6640b82e261738116fe00f7975ee12
Signed-off-by: Manish V Badarkhe <Manish.Badarkhe@arm.com>
diff --git a/services/std_svc/drtm/drtm_measurements.c b/services/std_svc/drtm/drtm_measurements.c
new file mode 100644
index 0000000..a8f2b32
--- /dev/null
+++ b/services/std_svc/drtm/drtm_measurements.c
@@ -0,0 +1,214 @@
+/*
+ * Copyright (c) 2022 Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier:    BSD-3-Clause
+ *
+ * DRTM measurements into TPM PCRs.
+ *
+ * Authors:
+ *      Lucian Paul-Trifu <lucian.paultrifu@gmail.com>
+ *
+ */
+#include <assert.h>
+
+#include <common/debug.h>
+#include <drivers/auth/crypto_mod.h>
+#include <drivers/measured_boot/event_log/event_log.h>
+#include "drtm_main.h"
+#include "drtm_measurements.h"
+#include <lib/xlat_tables/xlat_tables_v2.h>
+
+/* Event Log buffer */
+static uint8_t drtm_event_log[PLAT_DRTM_EVENT_LOG_MAX_SIZE];
+
+/*
+ * Calculate and write hash of various payloads as per DRTM specification
+ * to Event Log.
+ *
+ * @param[in] data_base         Address of data
+ * @param[in] data_size         Size of data
+ * @param[in] event_type        Type of Event
+ * @param[in] event_name        Name of the Event
+ * @return:
+ *      0 = success
+ *    < 0 = error
+ */
+static int drtm_event_log_measure_and_record(uintptr_t data_base,
+					     uint32_t data_size,
+					     uint32_t event_type,
+					     const char *event_name,
+					     unsigned int pcr)
+{
+	int rc;
+	unsigned char hash_data[CRYPTO_MD_MAX_SIZE];
+	event_log_metadata_t metadata = {0};
+
+	metadata.name = event_name;
+	metadata.pcr = pcr;
+
+	/*
+	 * Measure the payloads requested by D-CRTM and DCE commponents
+	 * Hash algorithm decided by the Event Log driver at build-time
+	 */
+	rc = event_log_measure(data_base, data_size, hash_data);
+	if (rc != 0) {
+		return rc;
+	}
+
+	/* Record the mesasurement in the EventLog buffer */
+	event_log_record(hash_data, event_type, &metadata);
+
+	return 0;
+}
+
+/*
+ * Initialise Event Log global variables, used during the recording
+ * of various payload measurements into the Event Log buffer
+ *
+ * @param[in] event_log_start           Base address of Event Log buffer
+ * @param[in] event_log_finish          End address of Event Log buffer,
+ *                                      it is a first byte past end of the
+ *                                      buffer
+ */
+static void drtm_event_log_init(uint8_t *event_log_start,
+				uint8_t *event_log_finish)
+{
+	event_log_buf_init(event_log_start, event_log_finish);
+	event_log_write_specid_event();
+}
+
+enum drtm_retc drtm_take_measurements(const struct_drtm_dl_args *a)
+{
+	int rc;
+	uintptr_t dlme_img_mapping;
+	uint64_t dlme_img_ep;
+	size_t dlme_img_mapping_bytes;
+	uint8_t drtm_null_data = 0U;
+	uint8_t pcr_schema = DL_ARGS_GET_PCR_SCHEMA(a);
+	const char *drtm_event_arm_sep_data = "ARM_DRTM";
+
+	/* Initialise the EventLog driver */
+	drtm_event_log_init(drtm_event_log, drtm_event_log +
+			    sizeof(drtm_event_log));
+
+	/**
+	 * Measurements extended into PCR-17.
+	 *
+	 * PCR-17: Measure the DCE image.  Extend digest of (char)0 into PCR-17
+	 * since the D-CRTM and the DCE are not separate.
+	 */
+	rc = drtm_event_log_measure_and_record((uintptr_t)&drtm_null_data,
+					       sizeof(drtm_null_data),
+					       DRTM_EVENT_ARM_DCE, NULL,
+					       PCR_17);
+	CHECK_RC(rc, drtm_event_log_measure_and_record(DRTM_EVENT_ARM_DCE));
+
+	/* PCR-17: Measure the PCR schema DRTM launch argument. */
+	rc = drtm_event_log_measure_and_record((uintptr_t)&pcr_schema,
+					       sizeof(pcr_schema),
+					       DRTM_EVENT_ARM_PCR_SCHEMA,
+					       NULL, PCR_17);
+	CHECK_RC(rc,
+		 drtm_event_log_measure_and_record(DRTM_EVENT_ARM_PCR_SCHEMA));
+
+	/* PCR-17: Measure the enable state of external-debug, and trace. */
+	/*
+	 * TODO: Measure the enable state of external-debug and trace.  This should
+	 * be returned through a platform-specific hook.
+	 */
+
+	/* PCR-17: Measure the security lifecycle state. */
+	/*
+	 * TODO: Measure the security lifecycle state.  This is an implementation-
+	 * defined value, retrieved through an implementation-defined mechanisms.
+	 */
+
+	/*
+	 * PCR-17: Optionally measure the NWd DCE.
+	 * It is expected that such subsequent DCE stages are signed and verified.
+	 * Whether they are measured in addition to signing is implementation
+	 * -defined.
+	 * Here the choice is to not measure any NWd DCE, in favour of PCR value
+	 * resilience to any NWd DCE updates.
+	 */
+
+	/* PCR-17: End of DCE measurements. */
+	rc = drtm_event_log_measure_and_record((uintptr_t)drtm_event_arm_sep_data,
+					       strlen(drtm_event_arm_sep_data),
+					       DRTM_EVENT_ARM_SEPARATOR, NULL,
+					       PCR_17);
+	CHECK_RC(rc, drtm_event_log_measure_and_record(DRTM_EVENT_ARM_SEPARATOR));
+
+	/**
+	 * Measurements extended into PCR-18.
+	 *
+	 * PCR-18: Measure the PCR schema DRTM launch argument.
+	 */
+	rc = drtm_event_log_measure_and_record((uintptr_t)&pcr_schema,
+					       sizeof(pcr_schema),
+					       DRTM_EVENT_ARM_PCR_SCHEMA,
+					       NULL, PCR_18);
+	CHECK_RC(rc,
+		 drtm_event_log_measure_and_record(DRTM_EVENT_ARM_PCR_SCHEMA));
+
+	/*
+	 * PCR-18: Measure the public key used to verify DCE image(s) signatures.
+	 * Extend digest of (char)0, since we do not expect the NWd DCE to be
+	 * present.
+	 */
+	assert(a->dce_nwd_size == 0);
+	rc = drtm_event_log_measure_and_record((uintptr_t)&drtm_null_data,
+					       sizeof(drtm_null_data),
+					       DRTM_EVENT_ARM_DCE_PUBKEY,
+					       NULL, PCR_18);
+	CHECK_RC(rc,
+		 drtm_event_log_measure_and_record(DRTM_EVENT_ARM_DCE_PUBKEY));
+
+	/* PCR-18: Measure the DLME image. */
+	dlme_img_mapping_bytes = page_align(a->dlme_img_size, UP);
+	rc = mmap_add_dynamic_region_alloc_va(a->dlme_paddr + a->dlme_img_off,
+					      &dlme_img_mapping,
+					      dlme_img_mapping_bytes, MT_RO_DATA | MT_NS);
+	if (rc) {
+		WARN("DRTM: %s: mmap_add_dynamic_region() failed rc=%d\n",
+		     __func__, rc);
+		return INTERNAL_ERROR;
+	}
+
+	rc = drtm_event_log_measure_and_record(dlme_img_mapping, a->dlme_img_size,
+					       DRTM_EVENT_ARM_DLME, NULL,
+					       PCR_18);
+	CHECK_RC(rc, drtm_event_log_measure_and_record(DRTM_EVENT_ARM_DLME));
+
+	rc = mmap_remove_dynamic_region(dlme_img_mapping, dlme_img_mapping_bytes);
+	CHECK_RC(rc, mmap_remove_dynamic_region);
+
+	/* PCR-18: Measure the DLME image entry point. */
+	dlme_img_ep = DL_ARGS_GET_DLME_ENTRY_POINT(a);
+	drtm_event_log_measure_and_record((uintptr_t)&dlme_img_ep,
+					  sizeof(dlme_img_ep),
+					  DRTM_EVENT_ARM_DLME_EP, NULL,
+					  PCR_18);
+	CHECK_RC(rc, drtm_event_log_measure_and_record(DRTM_EVENT_ARM_DLME_EP));
+
+	/* PCR-18: End of DCE measurements. */
+	rc = drtm_event_log_measure_and_record((uintptr_t)drtm_event_arm_sep_data,
+					       strlen(drtm_event_arm_sep_data),
+					       DRTM_EVENT_ARM_SEPARATOR, NULL,
+					       PCR_18);
+	CHECK_RC(rc,
+		 drtm_event_log_measure_and_record(DRTM_EVENT_ARM_SEPARATOR));
+	/*
+	 * If the DCE is unable to log a measurement because there is no available
+	 * space in the event log region, the DCE must extend a hash of the value
+	 * 0xFF (1 byte in size) into PCR[17] and PCR[18] and enter remediation.
+	 */
+
+	return SUCCESS;
+}
+
+void drtm_serialise_event_log(uint8_t *dst, size_t *event_log_size_out)
+{
+	*event_log_size_out = event_log_get_cur_size(drtm_event_log);
+	memcpy(dst, drtm_event_log, *event_log_size_out);
+}