All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/3] Enhance Measured Boot
@ 2021-09-15  5:15 Masahisa Kojima
  2021-09-15  5:15 ` [PATCH 1/3] efi_loader: add SMBIOS table measurement Masahisa Kojima
                   ` (2 more replies)
  0 siblings, 3 replies; 10+ messages in thread
From: Masahisa Kojima @ 2021-09-15  5:15 UTC (permalink / raw)
  To: Heinrich Schuchardt, Ilias Apalodimas
  Cc: Alexander Graf, Simon Glass, Bin Meng, Christian Gmeiner, u-boot

This patch series add the following measurement mandated in the
TCG PC Client PFP Specification.
 - SMBIOS tables
 - GPT disk partition topology
 - AuditMode and Deployed mode

Masahisa Kojima (3):
  efi_loader: add SMBIOS table measurement
  efi_loader: add UEFI GPT measurement
  efi_loader: add DeployedMode and AuditMode variable measurement

 include/blk.h                 |   3 +
 include/efi_loader.h          |   4 +-
 include/efi_tcg2.h            |  27 +++
 include/smbios.h              |  13 ++
 lib/efi_loader/Kconfig        |   1 +
 lib/efi_loader/efi_boottime.c |   4 +-
 lib/efi_loader/efi_smbios.c   |   2 -
 lib/efi_loader/efi_tcg2.c     | 306 +++++++++++++++++++++++++++++++++-
 lib/smbios-parser.c           | 127 +++++++++++++-
 9 files changed, 481 insertions(+), 6 deletions(-)

-- 
2.17.1


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 1/3] efi_loader: add SMBIOS table measurement
  2021-09-15  5:15 [PATCH 0/3] Enhance Measured Boot Masahisa Kojima
@ 2021-09-15  5:15 ` Masahisa Kojima
  2021-09-15  8:37   ` Ilias Apalodimas
  2021-09-15  5:15 ` [PATCH 2/3] efi_loader: add UEFI GPT measurement Masahisa Kojima
  2021-09-15  5:15 ` [PATCH 3/3] efi_loader: add DeployedMode and AuditMode variable measurement Masahisa Kojima
  2 siblings, 1 reply; 10+ messages in thread
From: Masahisa Kojima @ 2021-09-15  5:15 UTC (permalink / raw)
  To: Heinrich Schuchardt, Ilias Apalodimas
  Cc: Alexander Graf, Simon Glass, Bin Meng, Christian Gmeiner, u-boot

TCG PC Client spec requires to measure the SMBIOS
table that contain static configuration information
(e.g. Platform Manufacturer Enterprise Number assigned by IANA,
platform model number, Vendor and Device IDs for each SMBIOS table).

The device and environment dependent information such as
serial number is cleared to zero or space character for
the measurement.

This commit also fixes the following compiler warning:

lib/smbios-parser.c:59:39: warning: cast to pointer from integer of
different size [-Wint-to-pointer-cast]
  const struct smbios_header *header = (struct smbios_header *)entry->struct_table_address;

Signed-off-by: Masahisa Kojima <masahisa.kojima@linaro.org>
---
 include/efi_loader.h          |   2 +
 include/efi_tcg2.h            |  15 ++++
 include/smbios.h              |  13 ++++
 lib/efi_loader/Kconfig        |   1 +
 lib/efi_loader/efi_boottime.c |   2 +
 lib/efi_loader/efi_smbios.c   |   2 -
 lib/efi_loader/efi_tcg2.c     |  84 ++++++++++++++++++++++
 lib/smbios-parser.c           | 127 +++++++++++++++++++++++++++++++++-
 8 files changed, 243 insertions(+), 3 deletions(-)

diff --git a/include/efi_loader.h b/include/efi_loader.h
index c440962fe5..13f0c24058 100644
--- a/include/efi_loader.h
+++ b/include/efi_loader.h
@@ -308,6 +308,8 @@ extern const efi_guid_t efi_guid_capsule_report;
 extern const efi_guid_t efi_guid_firmware_management_protocol;
 /* GUID for the ESRT */
 extern const efi_guid_t efi_esrt_guid;
+/* GUID of the SMBIOS table */
+extern const efi_guid_t smbios_guid;
 
 extern char __efi_runtime_start[], __efi_runtime_stop[];
 extern char __efi_runtime_rel_start[], __efi_runtime_rel_stop[];
diff --git a/include/efi_tcg2.h b/include/efi_tcg2.h
index 5a1a36212e..da33f8a1d0 100644
--- a/include/efi_tcg2.h
+++ b/include/efi_tcg2.h
@@ -215,6 +215,21 @@ struct efi_tcg2_uefi_variable_data {
 	u8 variable_data[1];
 };
 
+/**
+ * struct tdUEFI_HANDOFF_TABLE_POINTERS2 - event log structure of SMBOIS tables
+ * @table_description_size:	size of table description
+ * @table_description:		table description
+ * @number_of_tables:		number of uefi configuration table
+ * @table_entry:		uefi configuration table entry
+ */
+#define SMBIOS_HANDOFF_TABLE_DESC  "SmbiosTable"
+struct smbios_handoff_table_pointers2 {
+	u8 table_description_size;
+	u8 table_description[sizeof(SMBIOS_HANDOFF_TABLE_DESC)];
+	u64 number_of_tables;
+	struct efi_configuration_table table_entry[1];
+} __packed;
+
 struct efi_tcg2_protocol {
 	efi_status_t (EFIAPI * get_capability)(struct efi_tcg2_protocol *this,
 					       struct efi_tcg2_boot_service_capability *capability);
diff --git a/include/smbios.h b/include/smbios.h
index aa6b6f3849..0c22c0c489 100644
--- a/include/smbios.h
+++ b/include/smbios.h
@@ -292,4 +292,17 @@ int smbios_update_version(const char *version);
  */
 int smbios_update_version_full(void *smbios_tab, const char *version);
 
+/**
+ * smbios_prepare_measurement() - Update smbios table for the measurement
+ *
+ * TCG specification requires to measure static configuration information.
+ * This function clear the device dependent parameters such as
+ * serial number for the measurement.
+ *
+ * @entry: pointer to a struct smbios_entry
+ * @header: pointer to a struct smbios_header
+ */
+void smbios_prepare_measurement(const struct smbios_entry *entry,
+				struct smbios_header *header);
+
 #endif /* _SMBIOS_H_ */
diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
index dacc3b5881..ac1a281a36 100644
--- a/lib/efi_loader/Kconfig
+++ b/lib/efi_loader/Kconfig
@@ -327,6 +327,7 @@ config EFI_TCG2_PROTOCOL
 	select SHA384
 	select SHA512
 	select HASH
+	select SMBIOS_PARSER
 	help
 	  Provide a EFI_TCG2_PROTOCOL implementation using the TPM hardware
 	  of the platform.
diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
index f0283b539e..701e2212c8 100644
--- a/lib/efi_loader/efi_boottime.c
+++ b/lib/efi_loader/efi_boottime.c
@@ -86,6 +86,8 @@ const efi_guid_t efi_guid_event_group_reset_system =
 /* GUIDs of the Load File and Load File2 protocols */
 const efi_guid_t efi_guid_load_file_protocol = EFI_LOAD_FILE_PROTOCOL_GUID;
 const efi_guid_t efi_guid_load_file2_protocol = EFI_LOAD_FILE2_PROTOCOL_GUID;
+/* GUID of the SMBIOS table */
+const efi_guid_t smbios_guid = SMBIOS_TABLE_GUID;
 
 static efi_status_t EFIAPI efi_disconnect_controller(
 					efi_handle_t controller_handle,
diff --git a/lib/efi_loader/efi_smbios.c b/lib/efi_loader/efi_smbios.c
index 2eb4cb1c1a..fc0b23397c 100644
--- a/lib/efi_loader/efi_smbios.c
+++ b/lib/efi_loader/efi_smbios.c
@@ -13,8 +13,6 @@
 #include <mapmem.h>
 #include <smbios.h>
 
-static const efi_guid_t smbios_guid = SMBIOS_TABLE_GUID;
-
 /*
  * Install the SMBIOS table as a configuration table.
  *
diff --git a/lib/efi_loader/efi_tcg2.c b/lib/efi_loader/efi_tcg2.c
index cb48919223..7f47998a55 100644
--- a/lib/efi_loader/efi_tcg2.c
+++ b/lib/efi_loader/efi_tcg2.c
@@ -14,6 +14,7 @@
 #include <efi_tcg2.h>
 #include <log.h>
 #include <malloc.h>
+#include <smbios.h>
 #include <version.h>
 #include <tpm-v2.h>
 #include <u-boot/hash-checksum.h>
@@ -1449,6 +1450,81 @@ error:
 	return ret;
 }
 
+/**
+ * tcg2_measure_smbios() - measure smbios table
+ *
+ * @dev:	TPM device
+ * @entry:	pointer to the smbios_entry structure
+ *
+ * Return:	status code
+ */
+static efi_status_t
+tcg2_measure_smbios(struct udevice *dev,
+		    const struct smbios_entry *entry)
+{
+	efi_status_t ret;
+	struct smbios_header *smbios_copy;
+	struct smbios_handoff_table_pointers2 *event = NULL;
+	u32 event_size;
+
+	/*
+	 * TCG PC Client PFP Spec says
+	 * "SMBIOS structures that contain static configuration information
+	 * (e.g. Platform Manufacturer Enterprise Number assigned by IANA,
+	 * platform model number, Vendor and Device IDs for each SMBIOS table)
+	 * that is relevant to the security of the platform MUST be measured".
+	 * Device dependent parameters such as serial number are cleared to
+	 * zero or spaces for the measurement.
+	 */
+	event_size = sizeof(struct smbios_handoff_table_pointers2) +
+		     entry->struct_table_length -
+		     FIELD_SIZEOF(struct efi_configuration_table, table);
+	event = calloc(1, event_size);
+	if (!event) {
+		ret = EFI_OUT_OF_RESOURCES;
+		goto out;
+	}
+
+	event->table_description_size = sizeof(SMBIOS_HANDOFF_TABLE_DESC);
+	memcpy(event->table_description, SMBIOS_HANDOFF_TABLE_DESC,
+	       sizeof(SMBIOS_HANDOFF_TABLE_DESC));
+	put_unaligned_le64(1, &event->number_of_tables);
+	guidcpy(&event->table_entry[0].guid, &smbios_guid);
+	smbios_copy = (struct smbios_header *)((uintptr_t)&event->table_entry[0].table);
+	memcpy(&event->table_entry[0].table,
+	       (void *)((uintptr_t)entry->struct_table_address),
+	       entry->struct_table_length);
+
+	smbios_prepare_measurement(entry, smbios_copy);
+
+	ret = tcg2_measure_event(dev, 1, EV_EFI_HANDOFF_TABLES2, event_size,
+				 (u8 *)event);
+	if (ret != EFI_SUCCESS)
+		goto out;
+
+out:
+	free(event);
+
+	return ret;
+}
+
+/**
+ * search_smbios_table() - search smbios table
+ *
+ * Return:	pointer to the smbios table
+ */
+static void *search_smbios_table(void)
+{
+	u32 i;
+
+	for (i = 0; i < systab.nr_tables; i++) {
+		if (!guidcmp(&smbios_guid, &systab.tables[i].guid))
+			return systab.tables[i].table;
+	}
+
+	return NULL;
+}
+
 /**
  * efi_tcg2_measure_efi_app_invocation() - measure efi app invocation
  *
@@ -1460,6 +1536,7 @@ efi_status_t efi_tcg2_measure_efi_app_invocation(void)
 	u32 pcr_index;
 	struct udevice *dev;
 	u32 event = 0;
+	struct smbios_entry *entry;
 
 	if (tcg2_efi_app_invoked)
 		return EFI_SUCCESS;
@@ -1485,6 +1562,13 @@ efi_status_t efi_tcg2_measure_efi_app_invocation(void)
 			goto out;
 	}
 
+	entry = (struct smbios_entry *)search_smbios_table();
+	if (entry) {
+		ret = tcg2_measure_smbios(dev, entry);
+		if (ret != EFI_SUCCESS)
+			goto out;
+	}
+
 	tcg2_efi_app_invoked = true;
 out:
 	return ret;
diff --git a/lib/smbios-parser.c b/lib/smbios-parser.c
index 34203f952c..5e0bd8f4ca 100644
--- a/lib/smbios-parser.c
+++ b/lib/smbios-parser.c
@@ -56,7 +56,7 @@ static const struct smbios_header *next_header(const struct smbios_header *curr)
 const struct smbios_header *smbios_header(const struct smbios_entry *entry, int type)
 {
 	const unsigned int num_header = entry->struct_count;
-	const struct smbios_header *header = (struct smbios_header *)entry->struct_table_address;
+	const struct smbios_header *header = (struct smbios_header *)((uintptr_t)entry->struct_table_address);
 
 	for (unsigned int i = 0; i < num_header; i++) {
 		if (header->type == type)
@@ -132,3 +132,128 @@ int smbios_update_version_full(void *smbios_tab, const char *version)
 
 	return 0;
 }
+
+struct smbios_filter_param {
+	u32 offset;
+	u32 size;
+	bool is_string;
+};
+
+struct smbios_filter_table {
+	int type;
+	struct smbios_filter_param *params;
+	u32 count;
+};
+
+struct smbios_filter_param smbios_type1_filter_params[] = {
+	{offsetof(struct smbios_type1, serial_number),
+	 FIELD_SIZEOF(struct smbios_type1, serial_number), true},
+	{offsetof(struct smbios_type1, uuid),
+	 FIELD_SIZEOF(struct smbios_type1, uuid), false},
+	{offsetof(struct smbios_type1, wakeup_type),
+	 FIELD_SIZEOF(struct smbios_type1, wakeup_type), false},
+};
+
+struct smbios_filter_param smbios_type2_filter_params[] = {
+	{offsetof(struct smbios_type2, serial_number),
+	 FIELD_SIZEOF(struct smbios_type2, serial_number), true},
+	{offsetof(struct smbios_type2, chassis_location),
+	 FIELD_SIZEOF(struct smbios_type2, chassis_location), false},
+};
+
+struct smbios_filter_param smbios_type3_filter_params[] = {
+	{offsetof(struct smbios_type3, serial_number),
+	 FIELD_SIZEOF(struct smbios_type3, serial_number), true},
+	{offsetof(struct smbios_type3, asset_tag_number),
+	 FIELD_SIZEOF(struct smbios_type3, asset_tag_number), true},
+};
+
+struct smbios_filter_param smbios_type4_filter_params[] = {
+	{offsetof(struct smbios_type4, serial_number),
+	 FIELD_SIZEOF(struct smbios_type4, serial_number), true},
+	{offsetof(struct smbios_type4, asset_tag),
+	 FIELD_SIZEOF(struct smbios_type4, asset_tag), true},
+	{offsetof(struct smbios_type4, part_number),
+	 FIELD_SIZEOF(struct smbios_type4, part_number), true},
+	{offsetof(struct smbios_type4, core_count),
+	 FIELD_SIZEOF(struct smbios_type4, core_count), false},
+	{offsetof(struct smbios_type4, core_enabled),
+	 FIELD_SIZEOF(struct smbios_type4, core_enabled), false},
+	{offsetof(struct smbios_type4, thread_count),
+	 FIELD_SIZEOF(struct smbios_type4, thread_count), false},
+	{offsetof(struct smbios_type4, core_count2),
+	 FIELD_SIZEOF(struct smbios_type4, core_count2), false},
+	{offsetof(struct smbios_type4, core_enabled2),
+	 FIELD_SIZEOF(struct smbios_type4, core_enabled2), false},
+	{offsetof(struct smbios_type4, thread_count),
+	 FIELD_SIZEOF(struct smbios_type4, thread_count2), false},
+	{offsetof(struct smbios_type4, voltage),
+	 FIELD_SIZEOF(struct smbios_type4, voltage), false},
+};
+
+struct smbios_filter_table smbios_filter_tables[] = {
+	{SMBIOS_SYSTEM_INFORMATION, smbios_type1_filter_params,
+	 ARRAY_SIZE(smbios_type1_filter_params)},
+	{SMBIOS_BOARD_INFORMATION, smbios_type2_filter_params,
+	 ARRAY_SIZE(smbios_type2_filter_params)},
+	{SMBIOS_SYSTEM_ENCLOSURE, smbios_type3_filter_params,
+	 ARRAY_SIZE(smbios_type3_filter_params)},
+	{SMBIOS_PROCESSOR_INFORMATION, smbios_type4_filter_params,
+	 ARRAY_SIZE(smbios_type4_filter_params)},
+};
+
+static void clear_smbios_table(struct smbios_header *header,
+			       struct smbios_filter_param *filter,
+			       u32 count)
+{
+	u32 i;
+	char *str;
+	u8 string_id;
+
+	for (i = 0; i < count; i++) {
+		if (filter[i].is_string) {
+			string_id = *((u8 *)header + filter[i].offset);
+			if (string_id == 0) /* string is empty */
+				continue;
+			/*
+			 * smbios_string() returns const value, but this
+			 * function needs to clear the string.
+			 */
+			str = (char *)smbios_string(header, string_id);
+			if (!str)
+				continue;
+			/* string is cleared to space */
+			memset(str, ' ', strlen(str));
+
+		} else {
+			memset((void *)((u8 *)header + filter[i].offset),
+			       0, filter[i].size);
+		}
+	}
+}
+
+void smbios_prepare_measurement(const struct smbios_entry *entry,
+				struct smbios_header *smbios_copy)
+{
+	u32 i, j;
+	struct smbios_header *header;
+
+	for (i = 0; i < ARRAY_SIZE(smbios_filter_tables); i++) {
+		header = smbios_copy;
+		for (j = 0; j < entry->struct_count; j++) {
+			if (header->type == smbios_filter_tables[i].type)
+				break;
+			/*
+			 * next_header() returns the const value, but some
+			 * members need to be cleared for the measurement.
+			 */
+			header = (struct smbios_header *)next_header(header);
+		}
+		if (j >= entry->struct_count)
+			continue;
+
+		clear_smbios_table(header,
+				   smbios_filter_tables[i].params,
+				   smbios_filter_tables[i].count);
+	}
+}
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 2/3] efi_loader: add UEFI GPT measurement
  2021-09-15  5:15 [PATCH 0/3] Enhance Measured Boot Masahisa Kojima
  2021-09-15  5:15 ` [PATCH 1/3] efi_loader: add SMBIOS table measurement Masahisa Kojima
@ 2021-09-15  5:15 ` Masahisa Kojima
  2021-09-16  7:24   ` Heinrich Schuchardt
  2021-09-15  5:15 ` [PATCH 3/3] efi_loader: add DeployedMode and AuditMode variable measurement Masahisa Kojima
  2 siblings, 1 reply; 10+ messages in thread
From: Masahisa Kojima @ 2021-09-15  5:15 UTC (permalink / raw)
  To: Heinrich Schuchardt, Ilias Apalodimas
  Cc: Alexander Graf, Simon Glass, Bin Meng, Christian Gmeiner, u-boot

This commit adds the UEFI GPT disk partition topology
measurement required in TCG PC Client PFP Spec.

Signed-off-by: Masahisa Kojima <masahisa.kojima@linaro.org>
---
 include/blk.h                 |   3 +
 include/efi_loader.h          |   2 +-
 include/efi_tcg2.h            |  12 +++
 lib/efi_loader/efi_boottime.c |   2 +-
 lib/efi_loader/efi_tcg2.c     | 175 +++++++++++++++++++++++++++++++++-
 5 files changed, 191 insertions(+), 3 deletions(-)

diff --git a/include/blk.h b/include/blk.h
index 19bab081c2..f0cc7ca1a2 100644
--- a/include/blk.h
+++ b/include/blk.h
@@ -45,6 +45,9 @@ enum if_type {
 #define BLK_PRD_SIZE		20
 #define BLK_REV_SIZE		8
 
+#define PART_FORMAT_PCAT	0x1
+#define PART_FORMAT_GPT		0x2
+
 /*
  * Identifies the partition table type (ie. MBR vs GPT GUID) signature
  */
diff --git a/include/efi_loader.h b/include/efi_loader.h
index 13f0c24058..dbcc296e01 100644
--- a/include/efi_loader.h
+++ b/include/efi_loader.h
@@ -503,7 +503,7 @@ efi_status_t efi_init_variables(void);
 void efi_variables_boot_exit_notify(void);
 efi_status_t efi_tcg2_notify_exit_boot_services_failed(void);
 /* Measure efi application invocation */
-efi_status_t efi_tcg2_measure_efi_app_invocation(void);
+efi_status_t efi_tcg2_measure_efi_app_invocation(struct efi_loaded_image_obj *handle);
 /* Measure efi application exit */
 efi_status_t efi_tcg2_measure_efi_app_exit(void);
 /* Called by bootefi to initialize root node */
diff --git a/include/efi_tcg2.h b/include/efi_tcg2.h
index da33f8a1d0..33257fa96b 100644
--- a/include/efi_tcg2.h
+++ b/include/efi_tcg2.h
@@ -230,6 +230,18 @@ struct smbios_handoff_table_pointers2 {
 	struct efi_configuration_table table_entry[1];
 } __packed;
 
+/**
+ * struct tdUEFI_GPT_DATA - event log structure of industry standard tables
+ * @uefi_partition_header:	gpt partition header
+ * @number_of_partitions:	the number of partition
+ * @partitions:			partition entries
+ */
+struct efi_gpt_data {
+	gpt_header uefi_partition_header;
+	u64 number_of_partitions;
+	gpt_entry partitions[];
+} __packed;
+
 struct efi_tcg2_protocol {
 	efi_status_t (EFIAPI * get_capability)(struct efi_tcg2_protocol *this,
 					       struct efi_tcg2_boot_service_capability *capability);
diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
index 701e2212c8..bf5661e1ee 100644
--- a/lib/efi_loader/efi_boottime.c
+++ b/lib/efi_loader/efi_boottime.c
@@ -3003,7 +3003,7 @@ efi_status_t EFIAPI efi_start_image(efi_handle_t image_handle,
 
 	if (IS_ENABLED(CONFIG_EFI_TCG2_PROTOCOL)) {
 		if (image_obj->image_type == IMAGE_SUBSYSTEM_EFI_APPLICATION) {
-			ret = efi_tcg2_measure_efi_app_invocation();
+			ret = efi_tcg2_measure_efi_app_invocation(image_obj);
 			if (ret != EFI_SUCCESS) {
 				log_warning("tcg2 measurement fails(0x%lx)\n",
 					    ret);
diff --git a/lib/efi_loader/efi_tcg2.c b/lib/efi_loader/efi_tcg2.c
index 7f47998a55..35810615ed 100644
--- a/lib/efi_loader/efi_tcg2.c
+++ b/lib/efi_loader/efi_tcg2.c
@@ -1525,12 +1525,181 @@ static void *search_smbios_table(void)
 	return NULL;
 }
 
+/**
+ * search_gpt_dp_node() - search gpt device path node
+ *
+ * @device_path:	device path
+ *
+ * Return:	pointer to the gpt device path node
+ */
+static struct
+efi_device_path *search_gpt_dp_node(struct efi_device_path *device_path)
+{
+	struct efi_device_path *dp = device_path;
+
+	while (dp) {
+		if (dp->type == DEVICE_PATH_TYPE_MEDIA_DEVICE &&
+		    dp->sub_type == DEVICE_PATH_SUB_TYPE_HARD_DRIVE_PATH) {
+			struct efi_device_path_hard_drive_path *hd_dp =
+				(struct efi_device_path_hard_drive_path *)dp;
+
+			if (hd_dp->partmap_type == PART_FORMAT_GPT &&
+			    hd_dp->signature_type == SIG_TYPE_GUID)
+				return dp;
+		}
+		dp = efi_dp_next(dp);
+	}
+
+	return NULL;
+}
+
+/**
+ * tcg2_measure_gpt_table() - measure gpt table
+ *
+ * @dev:		TPM device
+ * @loaded_image:	handle to the loaded image
+ *
+ * Return:	status code
+ */
+static efi_status_t
+tcg2_measure_gpt_data(struct udevice *dev,
+		      struct efi_loaded_image_obj *loaded_image)
+{
+	efi_status_t ret;
+	efi_handle_t handle;
+	struct efi_handler *dp_handler;
+	struct efi_device_path *orig_device_path;
+	struct efi_device_path *device_path;
+	struct efi_device_path *dp;
+	struct efi_block_io *block_io;
+	struct efi_gpt_data *event = NULL;
+	efi_guid_t null_guid = NULL_GUID;
+	gpt_header *orig_gpt_h = NULL;
+	gpt_entry *orig_gpt_e = NULL;
+	gpt_header *gpt_h = NULL;
+	gpt_entry *entry = NULL;
+	gpt_entry *gpt_e;
+	u32 num_of_valid_entry = 0;
+	u32 event_size;
+	u32 i;
+	u32 total_gpt_entry_size;
+
+	ret = efi_search_protocol(&loaded_image->header,
+				  &efi_guid_loaded_image_device_path,
+				  &dp_handler);
+	if (ret != EFI_SUCCESS)
+		return ret;
+
+	orig_device_path = dp_handler->protocol_interface;
+	device_path = efi_dp_dup(orig_device_path);
+	if (!device_path)
+		return EFI_OUT_OF_RESOURCES;
+
+	dp = search_gpt_dp_node(device_path);
+	if (!dp) {
+		/* no GPT device path node found, skip GPT measurement */
+		ret = EFI_SUCCESS;
+		goto out1;
+	}
+
+	/* read GPT header */
+	dp->type = DEVICE_PATH_TYPE_END;
+	dp->sub_type = DEVICE_PATH_SUB_TYPE_END;
+	dp = device_path;
+	ret = EFI_CALL(systab.boottime->locate_device_path(&efi_block_io_guid,
+							   &dp, &handle));
+	if (ret != EFI_SUCCESS)
+		goto out1;
+
+	ret = EFI_CALL(efi_handle_protocol(handle,
+					   &efi_block_io_guid, (void **)&block_io));
+	if (ret != EFI_SUCCESS)
+		goto out1;
+
+	orig_gpt_h = calloc(1, (block_io->media->block_size + block_io->media->io_align));
+	if (!orig_gpt_h) {
+		ret = EFI_OUT_OF_RESOURCES;
+		goto out2;
+	}
+
+	gpt_h = (gpt_header *)ALIGN((uintptr_t)orig_gpt_h, block_io->media->io_align);
+	ret = block_io->read_blocks(block_io, block_io->media->media_id, 1,
+				    block_io->media->block_size, gpt_h);
+	if (ret != EFI_SUCCESS)
+		goto out2;
+
+	/* read GPT entry */
+	total_gpt_entry_size = gpt_h->num_partition_entries *
+			       gpt_h->sizeof_partition_entry;
+	orig_gpt_e = calloc(1, total_gpt_entry_size + block_io->media->io_align);
+	entry = (void *)ALIGN((uintptr_t)orig_gpt_e, block_io->media->io_align);
+	if (!entry) {
+		ret = EFI_OUT_OF_RESOURCES;
+		goto out2;
+	}
+
+	ret = block_io->read_blocks(block_io, block_io->media->media_id,
+				    gpt_h->partition_entry_lba,
+				    total_gpt_entry_size, entry);
+	if (ret != EFI_SUCCESS)
+		goto out2;
+
+	/* count valid GPT entry */
+	gpt_e = entry;
+	for (i = 0; i < gpt_h->num_partition_entries; i++) {
+		if (guidcmp(&null_guid, &gpt_e->partition_type_guid))
+			num_of_valid_entry++;
+
+		gpt_e = (gpt_entry *)((u8 *)gpt_e + gpt_h->sizeof_partition_entry);
+	}
+
+	/* prepare event data for measurement */
+	event_size = sizeof(struct efi_gpt_data) +
+		(num_of_valid_entry * gpt_h->sizeof_partition_entry);
+	event = calloc(1, event_size);
+	if (!event) {
+		ret = EFI_OUT_OF_RESOURCES;
+		goto out2;
+	}
+	memcpy(event, gpt_h, sizeof(gpt_header));
+	put_unaligned_le64(num_of_valid_entry, &event->number_of_partitions);
+
+	/* copy valid GPT entry */
+	gpt_e = entry;
+	num_of_valid_entry = 0;
+	for (i = 0; i < gpt_h->num_partition_entries; i++) {
+		if (guidcmp(&null_guid, &gpt_e->partition_type_guid)) {
+			memcpy((u8 *)event->partitions +
+			       (num_of_valid_entry * gpt_h->sizeof_partition_entry),
+			       gpt_e, gpt_h->sizeof_partition_entry);
+			num_of_valid_entry++;
+		}
+
+		gpt_e = (gpt_entry *)((u8 *)gpt_e + gpt_h->sizeof_partition_entry);
+	}
+
+	ret = tcg2_measure_event(dev, 5, EV_EFI_GPT_EVENT, event_size, (u8 *)event);
+	if (ret != EFI_SUCCESS)
+		goto out2;
+
+out2:
+	EFI_CALL(efi_close_protocol((efi_handle_t)block_io, &efi_block_io_guid,
+				    NULL, NULL));
+	free(orig_gpt_h);
+	free(orig_gpt_e);
+	free(event);
+out1:
+	efi_free_pool(device_path);
+
+	return ret;
+}
+
 /**
  * efi_tcg2_measure_efi_app_invocation() - measure efi app invocation
  *
  * Return:	status code
  */
-efi_status_t efi_tcg2_measure_efi_app_invocation(void)
+efi_status_t efi_tcg2_measure_efi_app_invocation(struct efi_loaded_image_obj *handle)
 {
 	efi_status_t ret;
 	u32 pcr_index;
@@ -1569,6 +1738,10 @@ efi_status_t efi_tcg2_measure_efi_app_invocation(void)
 			goto out;
 	}
 
+	ret = tcg2_measure_gpt_data(dev, handle);
+	if (ret != EFI_SUCCESS)
+		goto out;
+
 	tcg2_efi_app_invoked = true;
 out:
 	return ret;
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 3/3] efi_loader: add DeployedMode and AuditMode variable measurement
  2021-09-15  5:15 [PATCH 0/3] Enhance Measured Boot Masahisa Kojima
  2021-09-15  5:15 ` [PATCH 1/3] efi_loader: add SMBIOS table measurement Masahisa Kojima
  2021-09-15  5:15 ` [PATCH 2/3] efi_loader: add UEFI GPT measurement Masahisa Kojima
@ 2021-09-15  5:15 ` Masahisa Kojima
  2021-09-16  6:57   ` Heinrich Schuchardt
  2 siblings, 1 reply; 10+ messages in thread
From: Masahisa Kojima @ 2021-09-15  5:15 UTC (permalink / raw)
  To: Heinrich Schuchardt, Ilias Apalodimas
  Cc: Alexander Graf, Simon Glass, Bin Meng, Christian Gmeiner, u-boot

This commit adds the DeployedMode and AuditMode variable
measurement required in TCG PC Client PFP Spec.

Signed-off-by: Masahisa Kojima <masahisa.kojima@linaro.org>
---
 lib/efi_loader/efi_tcg2.c | 47 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 47 insertions(+)

diff --git a/lib/efi_loader/efi_tcg2.c b/lib/efi_loader/efi_tcg2.c
index 35810615ed..427d6e22b1 100644
--- a/lib/efi_loader/efi_tcg2.c
+++ b/lib/efi_loader/efi_tcg2.c
@@ -12,6 +12,7 @@
 #include <dm.h>
 #include <efi_loader.h>
 #include <efi_tcg2.h>
+#include <efi_variable.h>
 #include <log.h>
 #include <malloc.h>
 #include <smbios.h>
@@ -1828,6 +1829,50 @@ out:
 	return ret;
 }
 
+/**
+ * tcg2_measure_deployed_audit_mode() - measure deployedmode and auditmode
+ *
+ * @dev:	TPM device
+ *
+ * Return:	status code
+ */
+static efi_status_t tcg2_measure_deployed_audit_mode(struct udevice *dev)
+{
+	u8 deployed_mode;
+	u8 audit_mode;
+	efi_uintn_t size;
+	efi_status_t ret;
+	u32 pcr_index;
+
+	size = sizeof(deployed_mode);
+	ret = efi_get_variable_int(L"DeployedMode", &efi_global_variable_guid,
+				   NULL, &size, &deployed_mode, NULL);
+	if (ret != EFI_SUCCESS)
+		return ret;
+
+	pcr_index = (deployed_mode ? 1 : 7);
+
+	ret = tcg2_measure_variable(dev, pcr_index,
+				    EV_EFI_VARIABLE_DRIVER_CONFIG,
+				    L"DeployedMode",
+				    &efi_global_variable_guid,
+				    size, &deployed_mode);
+
+	size = sizeof(audit_mode);
+	ret = efi_get_variable_int(L"AuditMode", &efi_global_variable_guid,
+				   NULL, &size, &audit_mode, NULL);
+	if (ret != EFI_SUCCESS)
+		return ret;
+
+	ret = tcg2_measure_variable(dev, pcr_index,
+				    EV_EFI_VARIABLE_DRIVER_CONFIG,
+				    L"AuditMode",
+				    &efi_global_variable_guid,
+				    size, &audit_mode);
+
+	return ret;
+}
+
 /**
  * tcg2_measure_secure_boot_variable() - measure secure boot variables
  *
@@ -1891,6 +1936,8 @@ static efi_status_t tcg2_measure_secure_boot_variable(struct udevice *dev)
 		free(data);
 	}
 
+	ret = tcg2_measure_deployed_audit_mode(dev);
+
 error:
 	return ret;
 }
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH 1/3] efi_loader: add SMBIOS table measurement
  2021-09-15  5:15 ` [PATCH 1/3] efi_loader: add SMBIOS table measurement Masahisa Kojima
@ 2021-09-15  8:37   ` Ilias Apalodimas
  2021-09-15 12:59     ` Masahisa Kojima
  0 siblings, 1 reply; 10+ messages in thread
From: Ilias Apalodimas @ 2021-09-15  8:37 UTC (permalink / raw)
  To: Masahisa Kojima
  Cc: Heinrich Schuchardt, Alexander Graf, Simon Glass, Bin Meng,
	Christian Gmeiner, u-boot

Hi Kojima-san,

On Wed, Sep 15, 2021 at 02:15:44PM +0900, Masahisa Kojima wrote:
> TCG PC Client spec requires to measure the SMBIOS
> table that contain static configuration information
> (e.g. Platform Manufacturer Enterprise Number assigned by IANA,
> platform model number, Vendor and Device IDs for each SMBIOS table).
> 
> The device and environment dependent information such as
> serial number is cleared to zero or space character for
> the measurement.
> 
> This commit also fixes the following compiler warning:
> 
> lib/smbios-parser.c:59:39: warning: cast to pointer from integer of
> different size [-Wint-to-pointer-cast]
>   const struct smbios_header *header = (struct smbios_header *)entry->struct_table_address;
> 
> Signed-off-by: Masahisa Kojima <masahisa.kojima@linaro.org>
> ---
>  include/efi_loader.h          |   2 +
>  include/efi_tcg2.h            |  15 ++++
>  include/smbios.h              |  13 ++++
>  lib/efi_loader/Kconfig        |   1 +
>  lib/efi_loader/efi_boottime.c |   2 +
>  lib/efi_loader/efi_smbios.c   |   2 -
>  lib/efi_loader/efi_tcg2.c     |  84 ++++++++++++++++++++++
>  lib/smbios-parser.c           | 127 +++++++++++++++++++++++++++++++++-
>  8 files changed, 243 insertions(+), 3 deletions(-)
> 
> diff --git a/include/efi_loader.h b/include/efi_loader.h
> index c440962fe5..13f0c24058 100644
> --- a/include/efi_loader.h
> +++ b/include/efi_loader.h
> @@ -308,6 +308,8 @@ extern const efi_guid_t efi_guid_capsule_report;
>  extern const efi_guid_t efi_guid_firmware_management_protocol;
>  /* GUID for the ESRT */
>  extern const efi_guid_t efi_esrt_guid;
> +/* GUID of the SMBIOS table */
> +extern const efi_guid_t smbios_guid;
>  
>  extern char __efi_runtime_start[], __efi_runtime_stop[];
>  extern char __efi_runtime_rel_start[], __efi_runtime_rel_stop[];
> diff --git a/include/efi_tcg2.h b/include/efi_tcg2.h
> index 5a1a36212e..da33f8a1d0 100644
> --- a/include/efi_tcg2.h
> +++ b/include/efi_tcg2.h
> @@ -215,6 +215,21 @@ struct efi_tcg2_uefi_variable_data {
>  	u8 variable_data[1];
>  };
>  
> +/**
> + * struct tdUEFI_HANDOFF_TABLE_POINTERS2 - event log structure of SMBOIS tables
> + * @table_description_size:	size of table description
> + * @table_description:		table description
> + * @number_of_tables:		number of uefi configuration table
> + * @table_entry:		uefi configuration table entry
> + */
> +#define SMBIOS_HANDOFF_TABLE_DESC  "SmbiosTable"
> +struct smbios_handoff_table_pointers2 {
> +	u8 table_description_size;
> +	u8 table_description[sizeof(SMBIOS_HANDOFF_TABLE_DESC)];
> +	u64 number_of_tables;
> +	struct efi_configuration_table table_entry[1];
> +} __packed;

Is this included in any other struct or array? If not the last member could
be a flexible array member?

> +
>  struct efi_tcg2_protocol {
>  	efi_status_t (EFIAPI * get_capability)(struct efi_tcg2_protocol *this,
>  					       struct efi_tcg2_boot_service_capability *capability);
> diff --git a/include/smbios.h b/include/smbios.h
> index aa6b6f3849..0c22c0c489 100644
> --- a/include/smbios.h
> +++ b/include/smbios.h
> @@ -292,4 +292,17 @@ int smbios_update_version(const char *version);
>   */
>  int smbios_update_version_full(void *smbios_tab, const char *version);
>  
> +/**
> + * smbios_prepare_measurement() - Update smbios table for the measurement
> + *
> + * TCG specification requires to measure static configuration information.
> + * This function clear the device dependent parameters such as
> + * serial number for the measurement.
> + *
> + * @entry: pointer to a struct smbios_entry
> + * @header: pointer to a struct smbios_header
> + */
> +void smbios_prepare_measurement(const struct smbios_entry *entry,
> +				struct smbios_header *header);
> +
>  #endif /* _SMBIOS_H_ */
> diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
> index dacc3b5881..ac1a281a36 100644
> --- a/lib/efi_loader/Kconfig
> +++ b/lib/efi_loader/Kconfig
> @@ -327,6 +327,7 @@ config EFI_TCG2_PROTOCOL
>  	select SHA384
>  	select SHA512
>  	select HASH
> +	select SMBIOS_PARSER
>  	help
>  	  Provide a EFI_TCG2_PROTOCOL implementation using the TPM hardware
>  	  of the platform.
> diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
> index f0283b539e..701e2212c8 100644
> --- a/lib/efi_loader/efi_boottime.c
> +++ b/lib/efi_loader/efi_boottime.c
> @@ -86,6 +86,8 @@ const efi_guid_t efi_guid_event_group_reset_system =
>  /* GUIDs of the Load File and Load File2 protocols */
>  const efi_guid_t efi_guid_load_file_protocol = EFI_LOAD_FILE_PROTOCOL_GUID;
>  const efi_guid_t efi_guid_load_file2_protocol = EFI_LOAD_FILE2_PROTOCOL_GUID;
> +/* GUID of the SMBIOS table */
> +const efi_guid_t smbios_guid = SMBIOS_TABLE_GUID;
>  
>  static efi_status_t EFIAPI efi_disconnect_controller(
>  					efi_handle_t controller_handle,
> diff --git a/lib/efi_loader/efi_smbios.c b/lib/efi_loader/efi_smbios.c
> index 2eb4cb1c1a..fc0b23397c 100644
> --- a/lib/efi_loader/efi_smbios.c
> +++ b/lib/efi_loader/efi_smbios.c
> @@ -13,8 +13,6 @@
>  #include <mapmem.h>
>  #include <smbios.h>
>  
> -static const efi_guid_t smbios_guid = SMBIOS_TABLE_GUID;
> -
>  /*
>   * Install the SMBIOS table as a configuration table.
>   *
> diff --git a/lib/efi_loader/efi_tcg2.c b/lib/efi_loader/efi_tcg2.c
> index cb48919223..7f47998a55 100644
> --- a/lib/efi_loader/efi_tcg2.c
> +++ b/lib/efi_loader/efi_tcg2.c
> @@ -14,6 +14,7 @@
>  #include <efi_tcg2.h>
>  #include <log.h>
>  #include <malloc.h>
> +#include <smbios.h>
>  #include <version.h>
>  #include <tpm-v2.h>
>  #include <u-boot/hash-checksum.h>
> @@ -1449,6 +1450,81 @@ error:
>  	return ret;
>  }
>  
> +/**
> + * tcg2_measure_smbios() - measure smbios table
> + *
> + * @dev:	TPM device
> + * @entry:	pointer to the smbios_entry structure
> + *
> + * Return:	status code
> + */
> +static efi_status_t
> +tcg2_measure_smbios(struct udevice *dev,
> +		    const struct smbios_entry *entry)
> +{
> +	efi_status_t ret;
> +	struct smbios_header *smbios_copy;
> +	struct smbios_handoff_table_pointers2 *event = NULL;
> +	u32 event_size;
> +
> +	/*
> +	 * TCG PC Client PFP Spec says
> +	 * "SMBIOS structures that contain static configuration information
> +	 * (e.g. Platform Manufacturer Enterprise Number assigned by IANA,
> +	 * platform model number, Vendor and Device IDs for each SMBIOS table)
> +	 * that is relevant to the security of the platform MUST be measured".
> +	 * Device dependent parameters such as serial number are cleared to
> +	 * zero or spaces for the measurement.
> +	 */
> +	event_size = sizeof(struct smbios_handoff_table_pointers2) +
> +		     entry->struct_table_length -
> +		     FIELD_SIZEOF(struct efi_configuration_table, table);

Why do we have to subtract the efi_config_table table field here?

> +	event = calloc(1, event_size);
> +	if (!event) {
> +		ret = EFI_OUT_OF_RESOURCES;
> +		goto out;
> +	}
> +
> +	event->table_description_size = sizeof(SMBIOS_HANDOFF_TABLE_DESC);
> +	memcpy(event->table_description, SMBIOS_HANDOFF_TABLE_DESC,
> +	       sizeof(SMBIOS_HANDOFF_TABLE_DESC));
> +	put_unaligned_le64(1, &event->number_of_tables);
> +	guidcpy(&event->table_entry[0].guid, &smbios_guid);
> +	smbios_copy = (struct smbios_header *)((uintptr_t)&event->table_entry[0].table);
> +	memcpy(&event->table_entry[0].table,
> +	       (void *)((uintptr_t)entry->struct_table_address),
> +	       entry->struct_table_length);
> +
> +	smbios_prepare_measurement(entry, smbios_copy);
> +
> +	ret = tcg2_measure_event(dev, 1, EV_EFI_HANDOFF_TABLES2, event_size,
> +				 (u8 *)event);
> +	if (ret != EFI_SUCCESS)
> +		goto out;
> +
> +out:
> +	free(event);
> +
> +	return ret;
> +}
> +
> +/**
> + * search_smbios_table() - search smbios table
> + *
> + * Return:	pointer to the smbios table
> + */
> +static void *search_smbios_table(void)

Isn't find_smbios_table a better name? 

> +{
> +	u32 i;
> +
> +	for (i = 0; i < systab.nr_tables; i++) {
> +		if (!guidcmp(&smbios_guid, &systab.tables[i].guid))
> +			return systab.tables[i].table;
> +	}
> +
> +	return NULL;
> +}
> +
>  /**
>   * efi_tcg2_measure_efi_app_invocation() - measure efi app invocation
>   *
> @@ -1460,6 +1536,7 @@ efi_status_t efi_tcg2_measure_efi_app_invocation(void)
>  	u32 pcr_index;
>  	struct udevice *dev;
>  	u32 event = 0;
> +	struct smbios_entry *entry;
>  
>  	if (tcg2_efi_app_invoked)
>  		return EFI_SUCCESS;
> @@ -1485,6 +1562,13 @@ efi_status_t efi_tcg2_measure_efi_app_invocation(void)
>  			goto out;
>  	}
>  
> +	entry = (struct smbios_entry *)search_smbios_table();
> +	if (entry) {
> +		ret = tcg2_measure_smbios(dev, entry);
> +		if (ret != EFI_SUCCESS)
> +			goto out;
> +	}
> +
>  	tcg2_efi_app_invoked = true;
>  out:
>  	return ret;
> diff --git a/lib/smbios-parser.c b/lib/smbios-parser.c
> index 34203f952c..5e0bd8f4ca 100644
> --- a/lib/smbios-parser.c
> +++ b/lib/smbios-parser.c
> @@ -56,7 +56,7 @@ static const struct smbios_header *next_header(const struct smbios_header *curr)
>  const struct smbios_header *smbios_header(const struct smbios_entry *entry, int type)
>  {
>  	const unsigned int num_header = entry->struct_count;
> -	const struct smbios_header *header = (struct smbios_header *)entry->struct_table_address;
> +	const struct smbios_header *header = (struct smbios_header *)((uintptr_t)entry->struct_table_address);
>  
>  	for (unsigned int i = 0; i < num_header; i++) {
>  		if (header->type == type)
> @@ -132,3 +132,128 @@ int smbios_update_version_full(void *smbios_tab, const char *version)
>  
>  	return 0;
>  }
> +
> +struct smbios_filter_param {
> +	u32 offset;
> +	u32 size;
> +	bool is_string;
> +};
> +
> +struct smbios_filter_table {
> +	int type;
> +	struct smbios_filter_param *params;
> +	u32 count;
> +};
> +
> +struct smbios_filter_param smbios_type1_filter_params[] = {
> +	{offsetof(struct smbios_type1, serial_number),
> +	 FIELD_SIZEOF(struct smbios_type1, serial_number), true},
> +	{offsetof(struct smbios_type1, uuid),
> +	 FIELD_SIZEOF(struct smbios_type1, uuid), false},
> +	{offsetof(struct smbios_type1, wakeup_type),
> +	 FIELD_SIZEOF(struct smbios_type1, wakeup_type), false},
> +};
> +
> +struct smbios_filter_param smbios_type2_filter_params[] = {
> +	{offsetof(struct smbios_type2, serial_number),
> +	 FIELD_SIZEOF(struct smbios_type2, serial_number), true},
> +	{offsetof(struct smbios_type2, chassis_location),
> +	 FIELD_SIZEOF(struct smbios_type2, chassis_location), false},
> +};
> +
> +struct smbios_filter_param smbios_type3_filter_params[] = {
> +	{offsetof(struct smbios_type3, serial_number),
> +	 FIELD_SIZEOF(struct smbios_type3, serial_number), true},
> +	{offsetof(struct smbios_type3, asset_tag_number),
> +	 FIELD_SIZEOF(struct smbios_type3, asset_tag_number), true},
> +};
> +
> +struct smbios_filter_param smbios_type4_filter_params[] = {
> +	{offsetof(struct smbios_type4, serial_number),
> +	 FIELD_SIZEOF(struct smbios_type4, serial_number), true},
> +	{offsetof(struct smbios_type4, asset_tag),
> +	 FIELD_SIZEOF(struct smbios_type4, asset_tag), true},
> +	{offsetof(struct smbios_type4, part_number),
> +	 FIELD_SIZEOF(struct smbios_type4, part_number), true},
> +	{offsetof(struct smbios_type4, core_count),
> +	 FIELD_SIZEOF(struct smbios_type4, core_count), false},
> +	{offsetof(struct smbios_type4, core_enabled),
> +	 FIELD_SIZEOF(struct smbios_type4, core_enabled), false},
> +	{offsetof(struct smbios_type4, thread_count),
> +	 FIELD_SIZEOF(struct smbios_type4, thread_count), false},
> +	{offsetof(struct smbios_type4, core_count2),
> +	 FIELD_SIZEOF(struct smbios_type4, core_count2), false},
> +	{offsetof(struct smbios_type4, core_enabled2),
> +	 FIELD_SIZEOF(struct smbios_type4, core_enabled2), false},
> +	{offsetof(struct smbios_type4, thread_count),
> +	 FIELD_SIZEOF(struct smbios_type4, thread_count2), false},
> +	{offsetof(struct smbios_type4, voltage),
> +	 FIELD_SIZEOF(struct smbios_type4, voltage), false},
> +};
> +
> +struct smbios_filter_table smbios_filter_tables[] = {
> +	{SMBIOS_SYSTEM_INFORMATION, smbios_type1_filter_params,
> +	 ARRAY_SIZE(smbios_type1_filter_params)},
> +	{SMBIOS_BOARD_INFORMATION, smbios_type2_filter_params,
> +	 ARRAY_SIZE(smbios_type2_filter_params)},
> +	{SMBIOS_SYSTEM_ENCLOSURE, smbios_type3_filter_params,
> +	 ARRAY_SIZE(smbios_type3_filter_params)},
> +	{SMBIOS_PROCESSOR_INFORMATION, smbios_type4_filter_params,
> +	 ARRAY_SIZE(smbios_type4_filter_params)},
> +};
> +
> +static void clear_smbios_table(struct smbios_header *header,
> +			       struct smbios_filter_param *filter,
> +			       u32 count)
> +{
> +	u32 i;
> +	char *str;
> +	u8 string_id;
> +
> +	for (i = 0; i < count; i++) {
> +		if (filter[i].is_string) {
> +			string_id = *((u8 *)header + filter[i].offset);
> +			if (string_id == 0) /* string is empty */
> +				continue;
> +			/*
> +			 * smbios_string() returns const value, but this
> +			 * function needs to clear the string.
> +			 */
> +			str = (char *)smbios_string(header, string_id);
> +			if (!str)
> +				continue;
> +			/* string is cleared to space */
> +			memset(str, ' ', strlen(str));

Isn't this undefined behavior ? If the area pointed to by whatever
smbios_string() is ro that will crash?

> +
> +		} else {
> +			memset((void *)((u8 *)header + filter[i].offset),
> +			       0, filter[i].size);
> +		}
> +	}
> +}
> +
> +void smbios_prepare_measurement(const struct smbios_entry *entry,
> +				struct smbios_header *smbios_copy)
> +{
> +	u32 i, j;
> +	struct smbios_header *header;
> +
> +	for (i = 0; i < ARRAY_SIZE(smbios_filter_tables); i++) {
> +		header = smbios_copy;
> +		for (j = 0; j < entry->struct_count; j++) {
> +			if (header->type == smbios_filter_tables[i].type)
> +				break;
> +			/*
> +			 * next_header() returns the const value, but some
> +			 * members need to be cleared for the measurement.
> +			 */
> +			header = (struct smbios_header *)next_header(header);
> +		}
> +		if (j >= entry->struct_count)
> +			continue;
> +
> +		clear_smbios_table(header,
> +				   smbios_filter_tables[i].params,
> +				   smbios_filter_tables[i].count);
> +	}
> +}
> -- 
> 2.17.1
> 

Regards
/Ilias

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 1/3] efi_loader: add SMBIOS table measurement
  2021-09-15  8:37   ` Ilias Apalodimas
@ 2021-09-15 12:59     ` Masahisa Kojima
  0 siblings, 0 replies; 10+ messages in thread
From: Masahisa Kojima @ 2021-09-15 12:59 UTC (permalink / raw)
  To: Ilias Apalodimas
  Cc: Heinrich Schuchardt, Alexander Graf, Simon Glass, Bin Meng,
	Christian Gmeiner, U-Boot Mailing List

Hi Ilias,

Thank you for the review.

On Wed, 15 Sept 2021 at 17:37, Ilias Apalodimas
<ilias.apalodimas@linaro.org> wrote:
>
> Hi Kojima-san,
>
> On Wed, Sep 15, 2021 at 02:15:44PM +0900, Masahisa Kojima wrote:
> > TCG PC Client spec requires to measure the SMBIOS
> > table that contain static configuration information
> > (e.g. Platform Manufacturer Enterprise Number assigned by IANA,
> > platform model number, Vendor and Device IDs for each SMBIOS table).
> >
> > The device and environment dependent information such as
> > serial number is cleared to zero or space character for
> > the measurement.
> >
> > This commit also fixes the following compiler warning:
> >
> > lib/smbios-parser.c:59:39: warning: cast to pointer from integer of
> > different size [-Wint-to-pointer-cast]
> >   const struct smbios_header *header = (struct smbios_header *)entry->struct_table_address;
> >
> > Signed-off-by: Masahisa Kojima <masahisa.kojima@linaro.org>
> > ---
> >  include/efi_loader.h          |   2 +
> >  include/efi_tcg2.h            |  15 ++++
> >  include/smbios.h              |  13 ++++
> >  lib/efi_loader/Kconfig        |   1 +
> >  lib/efi_loader/efi_boottime.c |   2 +
> >  lib/efi_loader/efi_smbios.c   |   2 -
> >  lib/efi_loader/efi_tcg2.c     |  84 ++++++++++++++++++++++
> >  lib/smbios-parser.c           | 127 +++++++++++++++++++++++++++++++++-
> >  8 files changed, 243 insertions(+), 3 deletions(-)
> >
> > diff --git a/include/efi_loader.h b/include/efi_loader.h
> > index c440962fe5..13f0c24058 100644
> > --- a/include/efi_loader.h
> > +++ b/include/efi_loader.h
> > @@ -308,6 +308,8 @@ extern const efi_guid_t efi_guid_capsule_report;
> >  extern const efi_guid_t efi_guid_firmware_management_protocol;
> >  /* GUID for the ESRT */
> >  extern const efi_guid_t efi_esrt_guid;
> > +/* GUID of the SMBIOS table */
> > +extern const efi_guid_t smbios_guid;
> >
> >  extern char __efi_runtime_start[], __efi_runtime_stop[];
> >  extern char __efi_runtime_rel_start[], __efi_runtime_rel_stop[];
> > diff --git a/include/efi_tcg2.h b/include/efi_tcg2.h
> > index 5a1a36212e..da33f8a1d0 100644
> > --- a/include/efi_tcg2.h
> > +++ b/include/efi_tcg2.h
> > @@ -215,6 +215,21 @@ struct efi_tcg2_uefi_variable_data {
> >       u8 variable_data[1];
> >  };
> >
> > +/**
> > + * struct tdUEFI_HANDOFF_TABLE_POINTERS2 - event log structure of SMBOIS tables
> > + * @table_description_size:  size of table description
> > + * @table_description:               table description
> > + * @number_of_tables:                number of uefi configuration table
> > + * @table_entry:             uefi configuration table entry
> > + */
> > +#define SMBIOS_HANDOFF_TABLE_DESC  "SmbiosTable"
> > +struct smbios_handoff_table_pointers2 {
> > +     u8 table_description_size;
> > +     u8 table_description[sizeof(SMBIOS_HANDOFF_TABLE_DESC)];
> > +     u64 number_of_tables;
> > +     struct efi_configuration_table table_entry[1];
> > +} __packed;
>
> Is this included in any other struct or array? If not the last member could
> be a flexible array member?

Yes, it can be a flexible array.

>
> > +
> >  struct efi_tcg2_protocol {
> >       efi_status_t (EFIAPI * get_capability)(struct efi_tcg2_protocol *this,
> >                                              struct efi_tcg2_boot_service_capability *capability);
> > diff --git a/include/smbios.h b/include/smbios.h
> > index aa6b6f3849..0c22c0c489 100644
> > --- a/include/smbios.h
> > +++ b/include/smbios.h
> > @@ -292,4 +292,17 @@ int smbios_update_version(const char *version);
> >   */
> >  int smbios_update_version_full(void *smbios_tab, const char *version);
> >
> > +/**
> > + * smbios_prepare_measurement() - Update smbios table for the measurement
> > + *
> > + * TCG specification requires to measure static configuration information.
> > + * This function clear the device dependent parameters such as
> > + * serial number for the measurement.
> > + *
> > + * @entry: pointer to a struct smbios_entry
> > + * @header: pointer to a struct smbios_header
> > + */
> > +void smbios_prepare_measurement(const struct smbios_entry *entry,
> > +                             struct smbios_header *header);
> > +
> >  #endif /* _SMBIOS_H_ */
> > diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
> > index dacc3b5881..ac1a281a36 100644
> > --- a/lib/efi_loader/Kconfig
> > +++ b/lib/efi_loader/Kconfig
> > @@ -327,6 +327,7 @@ config EFI_TCG2_PROTOCOL
> >       select SHA384
> >       select SHA512
> >       select HASH
> > +     select SMBIOS_PARSER
> >       help
> >         Provide a EFI_TCG2_PROTOCOL implementation using the TPM hardware
> >         of the platform.
> > diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
> > index f0283b539e..701e2212c8 100644
> > --- a/lib/efi_loader/efi_boottime.c
> > +++ b/lib/efi_loader/efi_boottime.c
> > @@ -86,6 +86,8 @@ const efi_guid_t efi_guid_event_group_reset_system =
> >  /* GUIDs of the Load File and Load File2 protocols */
> >  const efi_guid_t efi_guid_load_file_protocol = EFI_LOAD_FILE_PROTOCOL_GUID;
> >  const efi_guid_t efi_guid_load_file2_protocol = EFI_LOAD_FILE2_PROTOCOL_GUID;
> > +/* GUID of the SMBIOS table */
> > +const efi_guid_t smbios_guid = SMBIOS_TABLE_GUID;
> >
> >  static efi_status_t EFIAPI efi_disconnect_controller(
> >                                       efi_handle_t controller_handle,
> > diff --git a/lib/efi_loader/efi_smbios.c b/lib/efi_loader/efi_smbios.c
> > index 2eb4cb1c1a..fc0b23397c 100644
> > --- a/lib/efi_loader/efi_smbios.c
> > +++ b/lib/efi_loader/efi_smbios.c
> > @@ -13,8 +13,6 @@
> >  #include <mapmem.h>
> >  #include <smbios.h>
> >
> > -static const efi_guid_t smbios_guid = SMBIOS_TABLE_GUID;
> > -
> >  /*
> >   * Install the SMBIOS table as a configuration table.
> >   *
> > diff --git a/lib/efi_loader/efi_tcg2.c b/lib/efi_loader/efi_tcg2.c
> > index cb48919223..7f47998a55 100644
> > --- a/lib/efi_loader/efi_tcg2.c
> > +++ b/lib/efi_loader/efi_tcg2.c
> > @@ -14,6 +14,7 @@
> >  #include <efi_tcg2.h>
> >  #include <log.h>
> >  #include <malloc.h>
> > +#include <smbios.h>
> >  #include <version.h>
> >  #include <tpm-v2.h>
> >  #include <u-boot/hash-checksum.h>
> > @@ -1449,6 +1450,81 @@ error:
> >       return ret;
> >  }
> >
> > +/**
> > + * tcg2_measure_smbios() - measure smbios table
> > + *
> > + * @dev:     TPM device
> > + * @entry:   pointer to the smbios_entry structure
> > + *
> > + * Return:   status code
> > + */
> > +static efi_status_t
> > +tcg2_measure_smbios(struct udevice *dev,
> > +                 const struct smbios_entry *entry)
> > +{
> > +     efi_status_t ret;
> > +     struct smbios_header *smbios_copy;
> > +     struct smbios_handoff_table_pointers2 *event = NULL;
> > +     u32 event_size;
> > +
> > +     /*
> > +      * TCG PC Client PFP Spec says
> > +      * "SMBIOS structures that contain static configuration information
> > +      * (e.g. Platform Manufacturer Enterprise Number assigned by IANA,
> > +      * platform model number, Vendor and Device IDs for each SMBIOS table)
> > +      * that is relevant to the security of the platform MUST be measured".
> > +      * Device dependent parameters such as serial number are cleared to
> > +      * zero or spaces for the measurement.
> > +      */
> > +     event_size = sizeof(struct smbios_handoff_table_pointers2) +
> > +                  entry->struct_table_length -
> > +                  FIELD_SIZEOF(struct efi_configuration_table, table);
>
> Why do we have to subtract the efi_config_table table field here?

efi_config_table *table field is used to point the address of
smbios table data, actual smbios table size is indicated by
entry->struct_table_length.
efi_config_table *table field itself is not used and we need to substract it.

>
> > +     event = calloc(1, event_size);
> > +     if (!event) {
> > +             ret = EFI_OUT_OF_RESOURCES;
> > +             goto out;
> > +     }
> > +
> > +     event->table_description_size = sizeof(SMBIOS_HANDOFF_TABLE_DESC);
> > +     memcpy(event->table_description, SMBIOS_HANDOFF_TABLE_DESC,
> > +            sizeof(SMBIOS_HANDOFF_TABLE_DESC));
> > +     put_unaligned_le64(1, &event->number_of_tables);
> > +     guidcpy(&event->table_entry[0].guid, &smbios_guid);
> > +     smbios_copy = (struct smbios_header *)((uintptr_t)&event->table_entry[0].table);
> > +     memcpy(&event->table_entry[0].table,
> > +            (void *)((uintptr_t)entry->struct_table_address),
> > +            entry->struct_table_length);
> > +
> > +     smbios_prepare_measurement(entry, smbios_copy);
> > +
> > +     ret = tcg2_measure_event(dev, 1, EV_EFI_HANDOFF_TABLES2, event_size,
> > +                              (u8 *)event);
> > +     if (ret != EFI_SUCCESS)
> > +             goto out;
> > +
> > +out:
> > +     free(event);
> > +
> > +     return ret;
> > +}
> > +
> > +/**
> > + * search_smbios_table() - search smbios table
> > + *
> > + * Return:   pointer to the smbios table
> > + */
> > +static void *search_smbios_table(void)
>
> Isn't find_smbios_table a better name?

I agree, my first choice was "find", but I finally chose "search".
I will replace with "find".

>
> > +{
> > +     u32 i;
> > +
> > +     for (i = 0; i < systab.nr_tables; i++) {
> > +             if (!guidcmp(&smbios_guid, &systab.tables[i].guid))
> > +                     return systab.tables[i].table;
> > +     }
> > +
> > +     return NULL;
> > +}
> > +
> >  /**
> >   * efi_tcg2_measure_efi_app_invocation() - measure efi app invocation
> >   *
> > @@ -1460,6 +1536,7 @@ efi_status_t efi_tcg2_measure_efi_app_invocation(void)
> >       u32 pcr_index;
> >       struct udevice *dev;
> >       u32 event = 0;
> > +     struct smbios_entry *entry;
> >
> >       if (tcg2_efi_app_invoked)
> >               return EFI_SUCCESS;
> > @@ -1485,6 +1562,13 @@ efi_status_t efi_tcg2_measure_efi_app_invocation(void)
> >                       goto out;
> >       }
> >
> > +     entry = (struct smbios_entry *)search_smbios_table();
> > +     if (entry) {
> > +             ret = tcg2_measure_smbios(dev, entry);
> > +             if (ret != EFI_SUCCESS)
> > +                     goto out;
> > +     }
> > +
> >       tcg2_efi_app_invoked = true;
> >  out:
> >       return ret;
> > diff --git a/lib/smbios-parser.c b/lib/smbios-parser.c
> > index 34203f952c..5e0bd8f4ca 100644
> > --- a/lib/smbios-parser.c
> > +++ b/lib/smbios-parser.c
> > @@ -56,7 +56,7 @@ static const struct smbios_header *next_header(const struct smbios_header *curr)
> >  const struct smbios_header *smbios_header(const struct smbios_entry *entry, int type)
> >  {
> >       const unsigned int num_header = entry->struct_count;
> > -     const struct smbios_header *header = (struct smbios_header *)entry->struct_table_address;
> > +     const struct smbios_header *header = (struct smbios_header *)((uintptr_t)entry->struct_table_address);
> >
> >       for (unsigned int i = 0; i < num_header; i++) {
> >               if (header->type == type)
> > @@ -132,3 +132,128 @@ int smbios_update_version_full(void *smbios_tab, const char *version)
> >
> >       return 0;
> >  }
> > +
> > +struct smbios_filter_param {
> > +     u32 offset;
> > +     u32 size;
> > +     bool is_string;
> > +};
> > +
> > +struct smbios_filter_table {
> > +     int type;
> > +     struct smbios_filter_param *params;
> > +     u32 count;
> > +};
> > +
> > +struct smbios_filter_param smbios_type1_filter_params[] = {
> > +     {offsetof(struct smbios_type1, serial_number),
> > +      FIELD_SIZEOF(struct smbios_type1, serial_number), true},
> > +     {offsetof(struct smbios_type1, uuid),
> > +      FIELD_SIZEOF(struct smbios_type1, uuid), false},
> > +     {offsetof(struct smbios_type1, wakeup_type),
> > +      FIELD_SIZEOF(struct smbios_type1, wakeup_type), false},
> > +};
> > +
> > +struct smbios_filter_param smbios_type2_filter_params[] = {
> > +     {offsetof(struct smbios_type2, serial_number),
> > +      FIELD_SIZEOF(struct smbios_type2, serial_number), true},
> > +     {offsetof(struct smbios_type2, chassis_location),
> > +      FIELD_SIZEOF(struct smbios_type2, chassis_location), false},
> > +};
> > +
> > +struct smbios_filter_param smbios_type3_filter_params[] = {
> > +     {offsetof(struct smbios_type3, serial_number),
> > +      FIELD_SIZEOF(struct smbios_type3, serial_number), true},
> > +     {offsetof(struct smbios_type3, asset_tag_number),
> > +      FIELD_SIZEOF(struct smbios_type3, asset_tag_number), true},
> > +};
> > +
> > +struct smbios_filter_param smbios_type4_filter_params[] = {
> > +     {offsetof(struct smbios_type4, serial_number),
> > +      FIELD_SIZEOF(struct smbios_type4, serial_number), true},
> > +     {offsetof(struct smbios_type4, asset_tag),
> > +      FIELD_SIZEOF(struct smbios_type4, asset_tag), true},
> > +     {offsetof(struct smbios_type4, part_number),
> > +      FIELD_SIZEOF(struct smbios_type4, part_number), true},
> > +     {offsetof(struct smbios_type4, core_count),
> > +      FIELD_SIZEOF(struct smbios_type4, core_count), false},
> > +     {offsetof(struct smbios_type4, core_enabled),
> > +      FIELD_SIZEOF(struct smbios_type4, core_enabled), false},
> > +     {offsetof(struct smbios_type4, thread_count),
> > +      FIELD_SIZEOF(struct smbios_type4, thread_count), false},
> > +     {offsetof(struct smbios_type4, core_count2),
> > +      FIELD_SIZEOF(struct smbios_type4, core_count2), false},
> > +     {offsetof(struct smbios_type4, core_enabled2),
> > +      FIELD_SIZEOF(struct smbios_type4, core_enabled2), false},
> > +     {offsetof(struct smbios_type4, thread_count),
> > +      FIELD_SIZEOF(struct smbios_type4, thread_count2), false},
> > +     {offsetof(struct smbios_type4, voltage),
> > +      FIELD_SIZEOF(struct smbios_type4, voltage), false},
> > +};
> > +
> > +struct smbios_filter_table smbios_filter_tables[] = {
> > +     {SMBIOS_SYSTEM_INFORMATION, smbios_type1_filter_params,
> > +      ARRAY_SIZE(smbios_type1_filter_params)},
> > +     {SMBIOS_BOARD_INFORMATION, smbios_type2_filter_params,
> > +      ARRAY_SIZE(smbios_type2_filter_params)},
> > +     {SMBIOS_SYSTEM_ENCLOSURE, smbios_type3_filter_params,
> > +      ARRAY_SIZE(smbios_type3_filter_params)},
> > +     {SMBIOS_PROCESSOR_INFORMATION, smbios_type4_filter_params,
> > +      ARRAY_SIZE(smbios_type4_filter_params)},
> > +};
> > +
> > +static void clear_smbios_table(struct smbios_header *header,
> > +                            struct smbios_filter_param *filter,
> > +                            u32 count)
> > +{
> > +     u32 i;
> > +     char *str;
> > +     u8 string_id;
> > +
> > +     for (i = 0; i < count; i++) {
> > +             if (filter[i].is_string) {
> > +                     string_id = *((u8 *)header + filter[i].offset);
> > +                     if (string_id == 0) /* string is empty */
> > +                             continue;
> > +                     /*
> > +                      * smbios_string() returns const value, but this
> > +                      * function needs to clear the string.
> > +                      */
> > +                     str = (char *)smbios_string(header, string_id);
> > +                     if (!str)
> > +                             continue;
> > +                     /* string is cleared to space */
> > +                     memset(str, ' ', strlen(str));
>
> Isn't this undefined behavior ? If the area pointed to by whatever
> smbios_string() is ro that will crash?

Yes, this code is not good, I will fix.
Same instance exists in smbios_prepare_measurement().

Thanks,
Masahisa Kojima

>
> > +
> > +             } else {
> > +                     memset((void *)((u8 *)header + filter[i].offset),
> > +                            0, filter[i].size);
> > +             }
> > +     }
> > +}
> > +
> > +void smbios_prepare_measurement(const struct smbios_entry *entry,
> > +                             struct smbios_header *smbios_copy)
> > +{
> > +     u32 i, j;
> > +     struct smbios_header *header;
> > +
> > +     for (i = 0; i < ARRAY_SIZE(smbios_filter_tables); i++) {
> > +             header = smbios_copy;
> > +             for (j = 0; j < entry->struct_count; j++) {
> > +                     if (header->type == smbios_filter_tables[i].type)
> > +                             break;
> > +                     /*
> > +                      * next_header() returns the const value, but some
> > +                      * members need to be cleared for the measurement.
> > +                      */
> > +                     header = (struct smbios_header *)next_header(header);
> > +             }
> > +             if (j >= entry->struct_count)
> > +                     continue;
> > +
> > +             clear_smbios_table(header,
> > +                                smbios_filter_tables[i].params,
> > +                                smbios_filter_tables[i].count);
> > +     }
> > +}
> > --
> > 2.17.1
> >
>
> Regards
> /Ilias

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 3/3] efi_loader: add DeployedMode and AuditMode variable measurement
  2021-09-15  5:15 ` [PATCH 3/3] efi_loader: add DeployedMode and AuditMode variable measurement Masahisa Kojima
@ 2021-09-16  6:57   ` Heinrich Schuchardt
  2021-09-16  7:31     ` Masahisa Kojima
  0 siblings, 1 reply; 10+ messages in thread
From: Heinrich Schuchardt @ 2021-09-16  6:57 UTC (permalink / raw)
  To: Masahisa Kojima, Ilias Apalodimas
  Cc: Alexander Graf, Simon Glass, Bin Meng, Christian Gmeiner, u-boot



On 9/15/21 7:15 AM, Masahisa Kojima wrote:
> This commit adds the DeployedMode and AuditMode variable
> measurement required in TCG PC Client PFP Spec.
>
> Signed-off-by: Masahisa Kojima <masahisa.kojima@linaro.org>
> ---
>   lib/efi_loader/efi_tcg2.c | 47 +++++++++++++++++++++++++++++++++++++++
>   1 file changed, 47 insertions(+)
>
> diff --git a/lib/efi_loader/efi_tcg2.c b/lib/efi_loader/efi_tcg2.c
> index 35810615ed..427d6e22b1 100644
> --- a/lib/efi_loader/efi_tcg2.c
> +++ b/lib/efi_loader/efi_tcg2.c
> @@ -12,6 +12,7 @@
>   #include <dm.h>
>   #include <efi_loader.h>
>   #include <efi_tcg2.h>
> +#include <efi_variable.h>
>   #include <log.h>
>   #include <malloc.h>
>   #include <smbios.h>
> @@ -1828,6 +1829,50 @@ out:
>   	return ret;
>   }
>
> +/**
> + * tcg2_measure_deployed_audit_mode() - measure deployedmode and auditmode
> + *
> + * @dev:	TPM device
> + *
> + * Return:	status code
> + */
> +static efi_status_t tcg2_measure_deployed_audit_mode(struct udevice *dev)
> +{
> +	u8 deployed_mode;
> +	u8 audit_mode;
> +	efi_uintn_t size;
> +	efi_status_t ret;
> +	u32 pcr_index;
> +
> +	size = sizeof(deployed_mode);
> +	ret = efi_get_variable_int(L"DeployedMode", &efi_global_variable_guid,
> +				   NULL, &size, &deployed_mode, NULL);
> +	if (ret != EFI_SUCCESS)
> +		return ret;

Why should AuditMode not be measured if DeployedMode does not exist?

Could we handle these variables in a loop over an array containing dbt
and dbr reduce code duplication?

Best regards

Heinrich

> +
> +	pcr_index = (deployed_mode ? 1 : 7);
> +
> +	ret = tcg2_measure_variable(dev, pcr_index,
> +				    EV_EFI_VARIABLE_DRIVER_CONFIG,
> +				    L"DeployedMode",
> +				    &efi_global_variable_guid,
> +				    size, &deployed_mode);
> +
> +	size = sizeof(audit_mode);
> +	ret = efi_get_variable_int(L"AuditMode", &efi_global_variable_guid,
> +				   NULL, &size, &audit_mode, NULL);
> +	if (ret != EFI_SUCCESS)
> +		return ret;
> +
> +	ret = tcg2_measure_variable(dev, pcr_index,
> +				    EV_EFI_VARIABLE_DRIVER_CONFIG,
> +				    L"AuditMode",
> +				    &efi_global_variable_guid,
> +				    size, &audit_mode);
> +
> +	return ret;
> +}
> +
>   /**
>    * tcg2_measure_secure_boot_variable() - measure secure boot variables
>    *
> @@ -1891,6 +1936,8 @@ static efi_status_t tcg2_measure_secure_boot_variable(struct udevice *dev)
>   		free(data);
>   	}
>
> +	ret = tcg2_measure_deployed_audit_mode(dev);
> +
>   error:
>   	return ret;
>   }
>

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 2/3] efi_loader: add UEFI GPT measurement
  2021-09-15  5:15 ` [PATCH 2/3] efi_loader: add UEFI GPT measurement Masahisa Kojima
@ 2021-09-16  7:24   ` Heinrich Schuchardt
  2021-09-16  8:32     ` Masahisa Kojima
  0 siblings, 1 reply; 10+ messages in thread
From: Heinrich Schuchardt @ 2021-09-16  7:24 UTC (permalink / raw)
  To: Masahisa Kojima
  Cc: Alexander Graf, Simon Glass, Bin Meng, Christian Gmeiner, u-boot,
	Ilias Apalodimas



On 9/15/21 7:15 AM, Masahisa Kojima wrote:
> This commit adds the UEFI GPT disk partition topology
> measurement required in TCG PC Client PFP Spec.

Thanks for looking into the missing parts of TCG measurement in U-Boot.

The requirements in the TCG PC Client PFP Spec are strange. It does not
explicitly say how to handle multiple block devices. Did the authors
never enjoy the pleasure of a second disk drive?

With your implementation you would measure the GPT table of the SD-card
from which you load Shim or GRUB but would not care about the GPT of the
NVMe drive with your OS.

A clarification by the TCG standards committee would be helpful.

After this series "10.2.7 DEVICE_SECURITY_EVENT_DATA Structure" still
needs to be covered.

Best regards

Heinrich

>
> Signed-off-by: Masahisa Kojima <masahisa.kojima@linaro.org>
> ---
>   include/blk.h                 |   3 +
>   include/efi_loader.h          |   2 +-
>   include/efi_tcg2.h            |  12 +++
>   lib/efi_loader/efi_boottime.c |   2 +-
>   lib/efi_loader/efi_tcg2.c     | 175 +++++++++++++++++++++++++++++++++-
>   5 files changed, 191 insertions(+), 3 deletions(-)
>
> diff --git a/include/blk.h b/include/blk.h
> index 19bab081c2..f0cc7ca1a2 100644
> --- a/include/blk.h
> +++ b/include/blk.h
> @@ -45,6 +45,9 @@ enum if_type {
>   #define BLK_PRD_SIZE		20
>   #define BLK_REV_SIZE		8
>
> +#define PART_FORMAT_PCAT	0x1
> +#define PART_FORMAT_GPT		0x2
> +
>   /*
>    * Identifies the partition table type (ie. MBR vs GPT GUID) signature
>    */
> diff --git a/include/efi_loader.h b/include/efi_loader.h
> index 13f0c24058..dbcc296e01 100644
> --- a/include/efi_loader.h
> +++ b/include/efi_loader.h
> @@ -503,7 +503,7 @@ efi_status_t efi_init_variables(void);
>   void efi_variables_boot_exit_notify(void);
>   efi_status_t efi_tcg2_notify_exit_boot_services_failed(void);
>   /* Measure efi application invocation */
> -efi_status_t efi_tcg2_measure_efi_app_invocation(void);
> +efi_status_t efi_tcg2_measure_efi_app_invocation(struct efi_loaded_image_obj *handle);
>   /* Measure efi application exit */
>   efi_status_t efi_tcg2_measure_efi_app_exit(void);
>   /* Called by bootefi to initialize root node */
> diff --git a/include/efi_tcg2.h b/include/efi_tcg2.h
> index da33f8a1d0..33257fa96b 100644
> --- a/include/efi_tcg2.h
> +++ b/include/efi_tcg2.h
> @@ -230,6 +230,18 @@ struct smbios_handoff_table_pointers2 {
>   	struct efi_configuration_table table_entry[1];
>   } __packed;
>
> +/**
> + * struct tdUEFI_GPT_DATA - event log structure of industry standard tables
> + * @uefi_partition_header:	gpt partition header
> + * @number_of_partitions:	the number of partition
> + * @partitions:			partition entries
> + */
> +struct efi_gpt_data {
> +	gpt_header uefi_partition_header;
> +	u64 number_of_partitions;
> +	gpt_entry partitions[];
> +} __packed;
> +
>   struct efi_tcg2_protocol {
>   	efi_status_t (EFIAPI * get_capability)(struct efi_tcg2_protocol *this,
>   					       struct efi_tcg2_boot_service_capability *capability);
> diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
> index 701e2212c8..bf5661e1ee 100644
> --- a/lib/efi_loader/efi_boottime.c
> +++ b/lib/efi_loader/efi_boottime.c
> @@ -3003,7 +3003,7 @@ efi_status_t EFIAPI efi_start_image(efi_handle_t image_handle,
>
>   	if (IS_ENABLED(CONFIG_EFI_TCG2_PROTOCOL)) {
>   		if (image_obj->image_type == IMAGE_SUBSYSTEM_EFI_APPLICATION) {
> -			ret = efi_tcg2_measure_efi_app_invocation();
> +			ret = efi_tcg2_measure_efi_app_invocation(image_obj);
>   			if (ret != EFI_SUCCESS) {
>   				log_warning("tcg2 measurement fails(0x%lx)\n",
>   					    ret);
> diff --git a/lib/efi_loader/efi_tcg2.c b/lib/efi_loader/efi_tcg2.c
> index 7f47998a55..35810615ed 100644
> --- a/lib/efi_loader/efi_tcg2.c
> +++ b/lib/efi_loader/efi_tcg2.c
> @@ -1525,12 +1525,181 @@ static void *search_smbios_table(void)
>   	return NULL;
>   }
>
> +/**
> + * search_gpt_dp_node() - search gpt device path node
> + *
> + * @device_path:	device path
> + *
> + * Return:	pointer to the gpt device path node
> + */
> +static struct
> +efi_device_path *search_gpt_dp_node(struct efi_device_path *device_path)
> +{
> +	struct efi_device_path *dp = device_path;
> +
> +	while (dp) {
> +		if (dp->type == DEVICE_PATH_TYPE_MEDIA_DEVICE &&
> +		    dp->sub_type == DEVICE_PATH_SUB_TYPE_HARD_DRIVE_PATH) {
> +			struct efi_device_path_hard_drive_path *hd_dp =
> +				(struct efi_device_path_hard_drive_path *)dp;
> +
> +			if (hd_dp->partmap_type == PART_FORMAT_GPT &&
> +			    hd_dp->signature_type == SIG_TYPE_GUID)
> +				return dp;
> +		}
> +		dp = efi_dp_next(dp);
> +	}
> +
> +	return NULL;
> +}
> +
> +/**
> + * tcg2_measure_gpt_table() - measure gpt table
> + *
> + * @dev:		TPM device
> + * @loaded_image:	handle to the loaded image
> + *
> + * Return:	status code
> + */
> +static efi_status_t
> +tcg2_measure_gpt_data(struct udevice *dev,
> +		      struct efi_loaded_image_obj *loaded_image)
> +{
> +	efi_status_t ret;
> +	efi_handle_t handle;
> +	struct efi_handler *dp_handler;
> +	struct efi_device_path *orig_device_path;
> +	struct efi_device_path *device_path;
> +	struct efi_device_path *dp;
> +	struct efi_block_io *block_io;
> +	struct efi_gpt_data *event = NULL;
> +	efi_guid_t null_guid = NULL_GUID;
> +	gpt_header *orig_gpt_h = NULL;
> +	gpt_entry *orig_gpt_e = NULL;
> +	gpt_header *gpt_h = NULL;
> +	gpt_entry *entry = NULL;
> +	gpt_entry *gpt_e;
> +	u32 num_of_valid_entry = 0;
> +	u32 event_size;
> +	u32 i;
> +	u32 total_gpt_entry_size;
> +
> +	ret = efi_search_protocol(&loaded_image->header,
> +				  &efi_guid_loaded_image_device_path,
> +				  &dp_handler);
> +	if (ret != EFI_SUCCESS)
> +		return ret;
> +
> +	orig_device_path = dp_handler->protocol_interface;
> +	device_path = efi_dp_dup(orig_device_path);
> +	if (!device_path)
> +		return EFI_OUT_OF_RESOURCES;
> +
> +	dp = search_gpt_dp_node(device_path);
> +	if (!dp) {
> +		/* no GPT device path node found, skip GPT measurement */
> +		ret = EFI_SUCCESS;
> +		goto out1;
> +	}
> +
> +	/* read GPT header */
> +	dp->type = DEVICE_PATH_TYPE_END;
> +	dp->sub_type = DEVICE_PATH_SUB_TYPE_END;
> +	dp = device_path;
> +	ret = EFI_CALL(systab.boottime->locate_device_path(&efi_block_io_guid,
> +							   &dp, &handle));
> +	if (ret != EFI_SUCCESS)
> +		goto out1;
> +
> +	ret = EFI_CALL(efi_handle_protocol(handle,
> +					   &efi_block_io_guid, (void **)&block_io));
> +	if (ret != EFI_SUCCESS)
> +		goto out1;
> +
> +	orig_gpt_h = calloc(1, (block_io->media->block_size + block_io->media->io_align));
> +	if (!orig_gpt_h) {
> +		ret = EFI_OUT_OF_RESOURCES;
> +		goto out2;
> +	}
> +
> +	gpt_h = (gpt_header *)ALIGN((uintptr_t)orig_gpt_h, block_io->media->io_align);
> +	ret = block_io->read_blocks(block_io, block_io->media->media_id, 1,
> +				    block_io->media->block_size, gpt_h);
> +	if (ret != EFI_SUCCESS)
> +		goto out2;
> +
> +	/* read GPT entry */
> +	total_gpt_entry_size = gpt_h->num_partition_entries *
> +			       gpt_h->sizeof_partition_entry;
> +	orig_gpt_e = calloc(1, total_gpt_entry_size + block_io->media->io_align);
> +	entry = (void *)ALIGN((uintptr_t)orig_gpt_e, block_io->media->io_align);
> +	if (!entry) {
> +		ret = EFI_OUT_OF_RESOURCES;
> +		goto out2;
> +	}
> +
> +	ret = block_io->read_blocks(block_io, block_io->media->media_id,
> +				    gpt_h->partition_entry_lba,
> +				    total_gpt_entry_size, entry);
> +	if (ret != EFI_SUCCESS)
> +		goto out2;
> +
> +	/* count valid GPT entry */
> +	gpt_e = entry;
> +	for (i = 0; i < gpt_h->num_partition_entries; i++) {
> +		if (guidcmp(&null_guid, &gpt_e->partition_type_guid))
> +			num_of_valid_entry++;
> +
> +		gpt_e = (gpt_entry *)((u8 *)gpt_e + gpt_h->sizeof_partition_entry);
> +	}
> +
> +	/* prepare event data for measurement */
> +	event_size = sizeof(struct efi_gpt_data) +
> +		(num_of_valid_entry * gpt_h->sizeof_partition_entry);
> +	event = calloc(1, event_size);
> +	if (!event) {
> +		ret = EFI_OUT_OF_RESOURCES;
> +		goto out2;
> +	}
> +	memcpy(event, gpt_h, sizeof(gpt_header));
> +	put_unaligned_le64(num_of_valid_entry, &event->number_of_partitions);
> +
> +	/* copy valid GPT entry */
> +	gpt_e = entry;
> +	num_of_valid_entry = 0;
> +	for (i = 0; i < gpt_h->num_partition_entries; i++) {
> +		if (guidcmp(&null_guid, &gpt_e->partition_type_guid)) {
> +			memcpy((u8 *)event->partitions +
> +			       (num_of_valid_entry * gpt_h->sizeof_partition_entry),
> +			       gpt_e, gpt_h->sizeof_partition_entry);
> +			num_of_valid_entry++;
> +		}
> +
> +		gpt_e = (gpt_entry *)((u8 *)gpt_e + gpt_h->sizeof_partition_entry);
> +	}
> +
> +	ret = tcg2_measure_event(dev, 5, EV_EFI_GPT_EVENT, event_size, (u8 *)event);
> +	if (ret != EFI_SUCCESS)
> +		goto out2;
> +
> +out2:
> +	EFI_CALL(efi_close_protocol((efi_handle_t)block_io, &efi_block_io_guid,
> +				    NULL, NULL));
> +	free(orig_gpt_h);
> +	free(orig_gpt_e);
> +	free(event);
> +out1:
> +	efi_free_pool(device_path);
> +
> +	return ret;
> +}
> +
>   /**
>    * efi_tcg2_measure_efi_app_invocation() - measure efi app invocation
>    *
>    * Return:	status code
>    */
> -efi_status_t efi_tcg2_measure_efi_app_invocation(void)
> +efi_status_t efi_tcg2_measure_efi_app_invocation(struct efi_loaded_image_obj *handle)
>   {
>   	efi_status_t ret;
>   	u32 pcr_index;
> @@ -1569,6 +1738,10 @@ efi_status_t efi_tcg2_measure_efi_app_invocation(void)
>   			goto out;
>   	}
>
> +	ret = tcg2_measure_gpt_data(dev, handle);
> +	if (ret != EFI_SUCCESS)
> +		goto out;
> +
>   	tcg2_efi_app_invoked = true;
>   out:
>   	return ret;
>

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 3/3] efi_loader: add DeployedMode and AuditMode variable measurement
  2021-09-16  6:57   ` Heinrich Schuchardt
@ 2021-09-16  7:31     ` Masahisa Kojima
  0 siblings, 0 replies; 10+ messages in thread
From: Masahisa Kojima @ 2021-09-16  7:31 UTC (permalink / raw)
  To: Heinrich Schuchardt
  Cc: Ilias Apalodimas, Alexander Graf, Simon Glass, Bin Meng,
	Christian Gmeiner, U-Boot Mailing List

Hi Heinrich,

On Thu, 16 Sept 2021 at 16:02, Heinrich Schuchardt <xypron.glpk@gmx.de> wrote:
>
>
>
> On 9/15/21 7:15 AM, Masahisa Kojima wrote:
> > This commit adds the DeployedMode and AuditMode variable
> > measurement required in TCG PC Client PFP Spec.
> >
> > Signed-off-by: Masahisa Kojima <masahisa.kojima@linaro.org>
> > ---
> >   lib/efi_loader/efi_tcg2.c | 47 +++++++++++++++++++++++++++++++++++++++
> >   1 file changed, 47 insertions(+)
> >
> > diff --git a/lib/efi_loader/efi_tcg2.c b/lib/efi_loader/efi_tcg2.c
> > index 35810615ed..427d6e22b1 100644
> > --- a/lib/efi_loader/efi_tcg2.c
> > +++ b/lib/efi_loader/efi_tcg2.c
> > @@ -12,6 +12,7 @@
> >   #include <dm.h>
> >   #include <efi_loader.h>
> >   #include <efi_tcg2.h>
> > +#include <efi_variable.h>
> >   #include <log.h>
> >   #include <malloc.h>
> >   #include <smbios.h>
> > @@ -1828,6 +1829,50 @@ out:
> >       return ret;
> >   }
> >
> > +/**
> > + * tcg2_measure_deployed_audit_mode() - measure deployedmode and auditmode
> > + *
> > + * @dev:     TPM device
> > + *
> > + * Return:   status code
> > + */
> > +static efi_status_t tcg2_measure_deployed_audit_mode(struct udevice *dev)
> > +{
> > +     u8 deployed_mode;
> > +     u8 audit_mode;
> > +     efi_uintn_t size;
> > +     efi_status_t ret;
> > +     u32 pcr_index;
> > +
> > +     size = sizeof(deployed_mode);
> > +     ret = efi_get_variable_int(L"DeployedMode", &efi_global_variable_guid,
> > +                                NULL, &size, &deployed_mode, NULL);
> > +     if (ret != EFI_SUCCESS)
> > +             return ret;
>
> Why should AuditMode not be measured if DeployedMode does not exist?

TCG spec says that PCR index is different depending on the DeployedMode value.

--- PCR[1]
If the system supports UEFI 2.5 or later and DeployedMode is enabled,
the following additional variables MUST
be measured into PCR[1]:
a. The DeployedMode variable value. The Event Type SHALL be
EV_EFI_VARIABLE_DRIVER_CONFIG and
the Event value shall be the value of the UEFI_VARIABLE data structure.
b. The AuditMode variable value. The Event Type SHALL be
EV_EFI_VARIABLE_DRIVER_CONFIG and the
Event value shall be the value of the UEFI_VARIABLE data structure.
---

--- PCR[7]
If the system supports UEFI 2.5 or later and DeployedMode is NOT
enabled, the following additional
variables MUST be measured into PCR[7]:
a. The contents of the AuditMode variable
b. The contents of the DeployedMode variable
---

If DeployedMode does not exist, we can not decide which PCR to be extended.

Thanks,
Masahisa Kojima

>
> Could we handle these variables in a loop over an array containing dbt
> and dbr reduce code duplication?
>
> Best regards
>
> Heinrich
>
> > +
> > +     pcr_index = (deployed_mode ? 1 : 7);
> > +
> > +     ret = tcg2_measure_variable(dev, pcr_index,
> > +                                 EV_EFI_VARIABLE_DRIVER_CONFIG,
> > +                                 L"DeployedMode",
> > +                                 &efi_global_variable_guid,
> > +                                 size, &deployed_mode);
> > +
> > +     size = sizeof(audit_mode);
> > +     ret = efi_get_variable_int(L"AuditMode", &efi_global_variable_guid,
> > +                                NULL, &size, &audit_mode, NULL);
> > +     if (ret != EFI_SUCCESS)
> > +             return ret;
> > +
> > +     ret = tcg2_measure_variable(dev, pcr_index,
> > +                                 EV_EFI_VARIABLE_DRIVER_CONFIG,
> > +                                 L"AuditMode",
> > +                                 &efi_global_variable_guid,
> > +                                 size, &audit_mode);
> > +
> > +     return ret;
> > +}
> > +
> >   /**
> >    * tcg2_measure_secure_boot_variable() - measure secure boot variables
> >    *
> > @@ -1891,6 +1936,8 @@ static efi_status_t tcg2_measure_secure_boot_variable(struct udevice *dev)
> >               free(data);
> >       }
> >
> > +     ret = tcg2_measure_deployed_audit_mode(dev);
> > +
> >   error:
> >       return ret;
> >   }
> >

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 2/3] efi_loader: add UEFI GPT measurement
  2021-09-16  7:24   ` Heinrich Schuchardt
@ 2021-09-16  8:32     ` Masahisa Kojima
  0 siblings, 0 replies; 10+ messages in thread
From: Masahisa Kojima @ 2021-09-16  8:32 UTC (permalink / raw)
  To: Heinrich Schuchardt
  Cc: Alexander Graf, Simon Glass, Bin Meng, Christian Gmeiner,
	U-Boot Mailing List, Ilias Apalodimas

On Thu, 16 Sept 2021 at 16:29, Heinrich Schuchardt <xypron.glpk@gmx.de> wrote:
>
>
>
> On 9/15/21 7:15 AM, Masahisa Kojima wrote:
> > This commit adds the UEFI GPT disk partition topology
> > measurement required in TCG PC Client PFP Spec.
>
> Thanks for looking into the missing parts of TCG measurement in U-Boot.
>
> The requirements in the TCG PC Client PFP Spec are strange. It does not
> explicitly say how to handle multiple block devices. Did the authors
> never enjoy the pleasure of a second disk drive?

Yes, I had same question of this GPT measurement required in TCG spec.
I refer EDK2 implementation, GPT is measured only once[*1].

[*1] https://github.com/tianocore/edk2/blob/master/SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.c#L46

>
> With your implementation you would measure the GPT table of the SD-card
> from which you load Shim or GRUB but would not care about the GPT of the
> NVMe drive with your OS.
>
> A clarification by the TCG standards committee would be helpful.

We need to find the right person to access.

>
> After this series "10.2.7 DEVICE_SECURITY_EVENT_DATA Structure" still
> needs to be covered.

I'm trying to cover all "MUST" and non-platform specific requirement,
and this is completed with this patch series.
DEVICE_SECURITY_EVENT_DATA is "should" requirement.
In addition, DEVICE_SECURITY_EVENT_DATA is not implemented
in EDK2(but it is not the reason u-boot will not support this event anyway).

Thanks,
Masahisa Kojima

>
> Best regards
>
> Heinrich
>
> >
> > Signed-off-by: Masahisa Kojima <masahisa.kojima@linaro.org>
> > ---
> >   include/blk.h                 |   3 +
> >   include/efi_loader.h          |   2 +-
> >   include/efi_tcg2.h            |  12 +++
> >   lib/efi_loader/efi_boottime.c |   2 +-
> >   lib/efi_loader/efi_tcg2.c     | 175 +++++++++++++++++++++++++++++++++-
> >   5 files changed, 191 insertions(+), 3 deletions(-)
> >
> > diff --git a/include/blk.h b/include/blk.h
> > index 19bab081c2..f0cc7ca1a2 100644
> > --- a/include/blk.h
> > +++ b/include/blk.h
> > @@ -45,6 +45,9 @@ enum if_type {
> >   #define BLK_PRD_SIZE                20
> >   #define BLK_REV_SIZE                8
> >
> > +#define PART_FORMAT_PCAT     0x1
> > +#define PART_FORMAT_GPT              0x2
> > +
> >   /*
> >    * Identifies the partition table type (ie. MBR vs GPT GUID) signature
> >    */
> > diff --git a/include/efi_loader.h b/include/efi_loader.h
> > index 13f0c24058..dbcc296e01 100644
> > --- a/include/efi_loader.h
> > +++ b/include/efi_loader.h
> > @@ -503,7 +503,7 @@ efi_status_t efi_init_variables(void);
> >   void efi_variables_boot_exit_notify(void);
> >   efi_status_t efi_tcg2_notify_exit_boot_services_failed(void);
> >   /* Measure efi application invocation */
> > -efi_status_t efi_tcg2_measure_efi_app_invocation(void);
> > +efi_status_t efi_tcg2_measure_efi_app_invocation(struct efi_loaded_image_obj *handle);
> >   /* Measure efi application exit */
> >   efi_status_t efi_tcg2_measure_efi_app_exit(void);
> >   /* Called by bootefi to initialize root node */
> > diff --git a/include/efi_tcg2.h b/include/efi_tcg2.h
> > index da33f8a1d0..33257fa96b 100644
> > --- a/include/efi_tcg2.h
> > +++ b/include/efi_tcg2.h
> > @@ -230,6 +230,18 @@ struct smbios_handoff_table_pointers2 {
> >       struct efi_configuration_table table_entry[1];
> >   } __packed;
> >
> > +/**
> > + * struct tdUEFI_GPT_DATA - event log structure of industry standard tables
> > + * @uefi_partition_header:   gpt partition header
> > + * @number_of_partitions:    the number of partition
> > + * @partitions:                      partition entries
> > + */
> > +struct efi_gpt_data {
> > +     gpt_header uefi_partition_header;
> > +     u64 number_of_partitions;
> > +     gpt_entry partitions[];
> > +} __packed;
> > +
> >   struct efi_tcg2_protocol {
> >       efi_status_t (EFIAPI * get_capability)(struct efi_tcg2_protocol *this,
> >                                              struct efi_tcg2_boot_service_capability *capability);
> > diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
> > index 701e2212c8..bf5661e1ee 100644
> > --- a/lib/efi_loader/efi_boottime.c
> > +++ b/lib/efi_loader/efi_boottime.c
> > @@ -3003,7 +3003,7 @@ efi_status_t EFIAPI efi_start_image(efi_handle_t image_handle,
> >
> >       if (IS_ENABLED(CONFIG_EFI_TCG2_PROTOCOL)) {
> >               if (image_obj->image_type == IMAGE_SUBSYSTEM_EFI_APPLICATION) {
> > -                     ret = efi_tcg2_measure_efi_app_invocation();
> > +                     ret = efi_tcg2_measure_efi_app_invocation(image_obj);
> >                       if (ret != EFI_SUCCESS) {
> >                               log_warning("tcg2 measurement fails(0x%lx)\n",
> >                                           ret);
> > diff --git a/lib/efi_loader/efi_tcg2.c b/lib/efi_loader/efi_tcg2.c
> > index 7f47998a55..35810615ed 100644
> > --- a/lib/efi_loader/efi_tcg2.c
> > +++ b/lib/efi_loader/efi_tcg2.c
> > @@ -1525,12 +1525,181 @@ static void *search_smbios_table(void)
> >       return NULL;
> >   }
> >
> > +/**
> > + * search_gpt_dp_node() - search gpt device path node
> > + *
> > + * @device_path:     device path
> > + *
> > + * Return:   pointer to the gpt device path node
> > + */
> > +static struct
> > +efi_device_path *search_gpt_dp_node(struct efi_device_path *device_path)
> > +{
> > +     struct efi_device_path *dp = device_path;
> > +
> > +     while (dp) {
> > +             if (dp->type == DEVICE_PATH_TYPE_MEDIA_DEVICE &&
> > +                 dp->sub_type == DEVICE_PATH_SUB_TYPE_HARD_DRIVE_PATH) {
> > +                     struct efi_device_path_hard_drive_path *hd_dp =
> > +                             (struct efi_device_path_hard_drive_path *)dp;
> > +
> > +                     if (hd_dp->partmap_type == PART_FORMAT_GPT &&
> > +                         hd_dp->signature_type == SIG_TYPE_GUID)
> > +                             return dp;
> > +             }
> > +             dp = efi_dp_next(dp);
> > +     }
> > +
> > +     return NULL;
> > +}
> > +
> > +/**
> > + * tcg2_measure_gpt_table() - measure gpt table
> > + *
> > + * @dev:             TPM device
> > + * @loaded_image:    handle to the loaded image
> > + *
> > + * Return:   status code
> > + */
> > +static efi_status_t
> > +tcg2_measure_gpt_data(struct udevice *dev,
> > +                   struct efi_loaded_image_obj *loaded_image)
> > +{
> > +     efi_status_t ret;
> > +     efi_handle_t handle;
> > +     struct efi_handler *dp_handler;
> > +     struct efi_device_path *orig_device_path;
> > +     struct efi_device_path *device_path;
> > +     struct efi_device_path *dp;
> > +     struct efi_block_io *block_io;
> > +     struct efi_gpt_data *event = NULL;
> > +     efi_guid_t null_guid = NULL_GUID;
> > +     gpt_header *orig_gpt_h = NULL;
> > +     gpt_entry *orig_gpt_e = NULL;
> > +     gpt_header *gpt_h = NULL;
> > +     gpt_entry *entry = NULL;
> > +     gpt_entry *gpt_e;
> > +     u32 num_of_valid_entry = 0;
> > +     u32 event_size;
> > +     u32 i;
> > +     u32 total_gpt_entry_size;
> > +
> > +     ret = efi_search_protocol(&loaded_image->header,
> > +                               &efi_guid_loaded_image_device_path,
> > +                               &dp_handler);
> > +     if (ret != EFI_SUCCESS)
> > +             return ret;
> > +
> > +     orig_device_path = dp_handler->protocol_interface;
> > +     device_path = efi_dp_dup(orig_device_path);
> > +     if (!device_path)
> > +             return EFI_OUT_OF_RESOURCES;
> > +
> > +     dp = search_gpt_dp_node(device_path);
> > +     if (!dp) {
> > +             /* no GPT device path node found, skip GPT measurement */
> > +             ret = EFI_SUCCESS;
> > +             goto out1;
> > +     }
> > +
> > +     /* read GPT header */
> > +     dp->type = DEVICE_PATH_TYPE_END;
> > +     dp->sub_type = DEVICE_PATH_SUB_TYPE_END;
> > +     dp = device_path;
> > +     ret = EFI_CALL(systab.boottime->locate_device_path(&efi_block_io_guid,
> > +                                                        &dp, &handle));
> > +     if (ret != EFI_SUCCESS)
> > +             goto out1;
> > +
> > +     ret = EFI_CALL(efi_handle_protocol(handle,
> > +                                        &efi_block_io_guid, (void **)&block_io));
> > +     if (ret != EFI_SUCCESS)
> > +             goto out1;
> > +
> > +     orig_gpt_h = calloc(1, (block_io->media->block_size + block_io->media->io_align));
> > +     if (!orig_gpt_h) {
> > +             ret = EFI_OUT_OF_RESOURCES;
> > +             goto out2;
> > +     }
> > +
> > +     gpt_h = (gpt_header *)ALIGN((uintptr_t)orig_gpt_h, block_io->media->io_align);
> > +     ret = block_io->read_blocks(block_io, block_io->media->media_id, 1,
> > +                                 block_io->media->block_size, gpt_h);
> > +     if (ret != EFI_SUCCESS)
> > +             goto out2;
> > +
> > +     /* read GPT entry */
> > +     total_gpt_entry_size = gpt_h->num_partition_entries *
> > +                            gpt_h->sizeof_partition_entry;
> > +     orig_gpt_e = calloc(1, total_gpt_entry_size + block_io->media->io_align);
> > +     entry = (void *)ALIGN((uintptr_t)orig_gpt_e, block_io->media->io_align);
> > +     if (!entry) {
> > +             ret = EFI_OUT_OF_RESOURCES;
> > +             goto out2;
> > +     }
> > +
> > +     ret = block_io->read_blocks(block_io, block_io->media->media_id,
> > +                                 gpt_h->partition_entry_lba,
> > +                                 total_gpt_entry_size, entry);
> > +     if (ret != EFI_SUCCESS)
> > +             goto out2;
> > +
> > +     /* count valid GPT entry */
> > +     gpt_e = entry;
> > +     for (i = 0; i < gpt_h->num_partition_entries; i++) {
> > +             if (guidcmp(&null_guid, &gpt_e->partition_type_guid))
> > +                     num_of_valid_entry++;
> > +
> > +             gpt_e = (gpt_entry *)((u8 *)gpt_e + gpt_h->sizeof_partition_entry);
> > +     }
> > +
> > +     /* prepare event data for measurement */
> > +     event_size = sizeof(struct efi_gpt_data) +
> > +             (num_of_valid_entry * gpt_h->sizeof_partition_entry);
> > +     event = calloc(1, event_size);
> > +     if (!event) {
> > +             ret = EFI_OUT_OF_RESOURCES;
> > +             goto out2;
> > +     }
> > +     memcpy(event, gpt_h, sizeof(gpt_header));
> > +     put_unaligned_le64(num_of_valid_entry, &event->number_of_partitions);
> > +
> > +     /* copy valid GPT entry */
> > +     gpt_e = entry;
> > +     num_of_valid_entry = 0;
> > +     for (i = 0; i < gpt_h->num_partition_entries; i++) {
> > +             if (guidcmp(&null_guid, &gpt_e->partition_type_guid)) {
> > +                     memcpy((u8 *)event->partitions +
> > +                            (num_of_valid_entry * gpt_h->sizeof_partition_entry),
> > +                            gpt_e, gpt_h->sizeof_partition_entry);
> > +                     num_of_valid_entry++;
> > +             }
> > +
> > +             gpt_e = (gpt_entry *)((u8 *)gpt_e + gpt_h->sizeof_partition_entry);
> > +     }
> > +
> > +     ret = tcg2_measure_event(dev, 5, EV_EFI_GPT_EVENT, event_size, (u8 *)event);
> > +     if (ret != EFI_SUCCESS)
> > +             goto out2;
> > +
> > +out2:
> > +     EFI_CALL(efi_close_protocol((efi_handle_t)block_io, &efi_block_io_guid,
> > +                                 NULL, NULL));
> > +     free(orig_gpt_h);
> > +     free(orig_gpt_e);
> > +     free(event);
> > +out1:
> > +     efi_free_pool(device_path);
> > +
> > +     return ret;
> > +}
> > +
> >   /**
> >    * efi_tcg2_measure_efi_app_invocation() - measure efi app invocation
> >    *
> >    * Return:  status code
> >    */
> > -efi_status_t efi_tcg2_measure_efi_app_invocation(void)
> > +efi_status_t efi_tcg2_measure_efi_app_invocation(struct efi_loaded_image_obj *handle)
> >   {
> >       efi_status_t ret;
> >       u32 pcr_index;
> > @@ -1569,6 +1738,10 @@ efi_status_t efi_tcg2_measure_efi_app_invocation(void)
> >                       goto out;
> >       }
> >
> > +     ret = tcg2_measure_gpt_data(dev, handle);
> > +     if (ret != EFI_SUCCESS)
> > +             goto out;
> > +
> >       tcg2_efi_app_invoked = true;
> >   out:
> >       return ret;
> >

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2021-09-16  8:33 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-09-15  5:15 [PATCH 0/3] Enhance Measured Boot Masahisa Kojima
2021-09-15  5:15 ` [PATCH 1/3] efi_loader: add SMBIOS table measurement Masahisa Kojima
2021-09-15  8:37   ` Ilias Apalodimas
2021-09-15 12:59     ` Masahisa Kojima
2021-09-15  5:15 ` [PATCH 2/3] efi_loader: add UEFI GPT measurement Masahisa Kojima
2021-09-16  7:24   ` Heinrich Schuchardt
2021-09-16  8:32     ` Masahisa Kojima
2021-09-15  5:15 ` [PATCH 3/3] efi_loader: add DeployedMode and AuditMode variable measurement Masahisa Kojima
2021-09-16  6:57   ` Heinrich Schuchardt
2021-09-16  7:31     ` Masahisa Kojima

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.