linux-integrity.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH V7 0/4] Add support for crypto agile logs
@ 2019-05-20 20:54 Matthew Garrett
  2019-05-20 20:54 ` [PATCH V7 1/4] tpm: Abstract crypto agile event size calculations Matthew Garrett
                   ` (7 more replies)
  0 siblings, 8 replies; 17+ messages in thread
From: Matthew Garrett @ 2019-05-20 20:54 UTC (permalink / raw)
  To: linux-integrity
  Cc: peterhuewe, jarkko.sakkinen, jgg, roberto.sassu, linux-efi,
	linux-security-module, linux-kernel, tweek, bsz

Identical to previous version except without the KSAN workaround - Ard
has a better solution for that.



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

* [PATCH V7 1/4] tpm: Abstract crypto agile event size calculations
  2019-05-20 20:54 [PATCH V7 0/4] Add support for crypto agile logs Matthew Garrett
@ 2019-05-20 20:54 ` Matthew Garrett
  2019-05-20 20:54 ` [PATCH V7 2/4] tpm: Reserve the TPM final events table Matthew Garrett
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 17+ messages in thread
From: Matthew Garrett @ 2019-05-20 20:54 UTC (permalink / raw)
  To: linux-integrity
  Cc: peterhuewe, jarkko.sakkinen, jgg, roberto.sassu, linux-efi,
	linux-security-module, linux-kernel, tweek, bsz, Matthew Garrett

From: Matthew Garrett <mjg59@google.com>

We need to calculate the size of crypto agile events in multiple
locations, including in the EFI boot stub. The easiest way to do this is
to put it in a header file as an inline and leave a wrapper to ensure we
don't end up with multiple copies of it embedded in the existing code.

Signed-off-by: Matthew Garrett <mjg59@google.com>
---
 drivers/char/tpm/eventlog/tpm2.c | 47 +---------------------
 include/linux/tpm_eventlog.h     | 68 ++++++++++++++++++++++++++++++++
 2 files changed, 69 insertions(+), 46 deletions(-)

diff --git a/drivers/char/tpm/eventlog/tpm2.c b/drivers/char/tpm/eventlog/tpm2.c
index f824563fc28d..1a977bdd3bd2 100644
--- a/drivers/char/tpm/eventlog/tpm2.c
+++ b/drivers/char/tpm/eventlog/tpm2.c
@@ -40,52 +40,7 @@
 static size_t calc_tpm2_event_size(struct tcg_pcr_event2_head *event,
 				   struct tcg_pcr_event *event_header)
 {
-	struct tcg_efi_specid_event_head *efispecid;
-	struct tcg_event_field *event_field;
-	void *marker;
-	void *marker_start;
-	u32 halg_size;
-	size_t size;
-	u16 halg;
-	int i;
-	int j;
-
-	marker = event;
-	marker_start = marker;
-	marker = marker + sizeof(event->pcr_idx) + sizeof(event->event_type)
-		+ sizeof(event->count);
-
-	efispecid = (struct tcg_efi_specid_event_head *)event_header->event;
-
-	/* Check if event is malformed. */
-	if (event->count > efispecid->num_algs)
-		return 0;
-
-	for (i = 0; i < event->count; i++) {
-		halg_size = sizeof(event->digests[i].alg_id);
-		memcpy(&halg, marker, halg_size);
-		marker = marker + halg_size;
-		for (j = 0; j < efispecid->num_algs; j++) {
-			if (halg == efispecid->digest_sizes[j].alg_id) {
-				marker +=
-					efispecid->digest_sizes[j].digest_size;
-				break;
-			}
-		}
-		/* Algorithm without known length. Such event is unparseable. */
-		if (j == efispecid->num_algs)
-			return 0;
-	}
-
-	event_field = (struct tcg_event_field *)marker;
-	marker = marker + sizeof(event_field->event_size)
-		+ event_field->event_size;
-	size = marker - marker_start;
-
-	if ((event->event_type == 0) && (event_field->event_size == 0))
-		return 0;
-
-	return size;
+	return __calc_tpm2_event_size(event, event_header);
 }
 
 static void *tpm2_bios_measurements_start(struct seq_file *m, loff_t *pos)
diff --git a/include/linux/tpm_eventlog.h b/include/linux/tpm_eventlog.h
index 81519f163211..6a86144e13f1 100644
--- a/include/linux/tpm_eventlog.h
+++ b/include/linux/tpm_eventlog.h
@@ -112,4 +112,72 @@ struct tcg_pcr_event2_head {
 	struct tpm_digest digests[];
 } __packed;
 
+/**
+ * __calc_tpm2_event_size - calculate the size of a TPM2 event log entry
+ * @event:        Pointer to the event whose size should be calculated
+ * @event_header: Pointer to the initial event containing the digest lengths
+ *
+ * The TPM2 event log format can contain multiple digests corresponding to
+ * separate PCR banks, and also contains a variable length of the data that
+ * was measured. This requires knowledge of how long each digest type is,
+ * and this information is contained within the first event in the log.
+ *
+ * We calculate the length by examining the number of events, and then looking
+ * at each event in turn to determine how much space is used for events in
+ * total. Once we've done this we know the offset of the data length field,
+ * and can calculate the total size of the event.
+ *
+ * Return: size of the event on success, <0 on failure
+ */
+
+static inline int __calc_tpm2_event_size(struct tcg_pcr_event2_head *event,
+					 struct tcg_pcr_event *event_header)
+{
+	struct tcg_efi_specid_event_head *efispecid;
+	struct tcg_event_field *event_field;
+	void *marker;
+	void *marker_start;
+	u32 halg_size;
+	size_t size;
+	u16 halg;
+	int i;
+	int j;
+
+	marker = event;
+	marker_start = marker;
+	marker = marker + sizeof(event->pcr_idx) + sizeof(event->event_type)
+		+ sizeof(event->count);
+
+	efispecid = (struct tcg_efi_specid_event_head *)event_header->event;
+
+	/* Check if event is malformed. */
+	if (event->count > efispecid->num_algs)
+		return 0;
+
+	for (i = 0; i < event->count; i++) {
+		halg_size = sizeof(event->digests[i].alg_id);
+		memcpy(&halg, marker, halg_size);
+		marker = marker + halg_size;
+		for (j = 0; j < efispecid->num_algs; j++) {
+			if (halg == efispecid->digest_sizes[j].alg_id) {
+				marker +=
+					efispecid->digest_sizes[j].digest_size;
+				break;
+			}
+		}
+		/* Algorithm without known length. Such event is unparseable. */
+		if (j == efispecid->num_algs)
+			return 0;
+	}
+
+	event_field = (struct tcg_event_field *)marker;
+	marker = marker + sizeof(event_field->event_size)
+		+ event_field->event_size;
+	size = marker - marker_start;
+
+	if ((event->event_type == 0) && (event_field->event_size == 0))
+		return 0;
+
+	return size;
+}
 #endif
-- 
2.21.0.1020.gf2820cf01a-goog


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

* [PATCH V7 2/4] tpm: Reserve the TPM final events table
  2019-05-20 20:54 [PATCH V7 0/4] Add support for crypto agile logs Matthew Garrett
  2019-05-20 20:54 ` [PATCH V7 1/4] tpm: Abstract crypto agile event size calculations Matthew Garrett
@ 2019-05-20 20:54 ` Matthew Garrett
  2019-05-21  9:29   ` Ard Biesheuvel
  2019-05-31  8:24   ` Joe Richey
  2019-05-20 20:55 ` [PATCH V7 3/4] tpm: Append the final event log to the TPM event log Matthew Garrett
                   ` (5 subsequent siblings)
  7 siblings, 2 replies; 17+ messages in thread
From: Matthew Garrett @ 2019-05-20 20:54 UTC (permalink / raw)
  To: linux-integrity
  Cc: peterhuewe, jarkko.sakkinen, jgg, roberto.sassu, linux-efi,
	linux-security-module, linux-kernel, tweek, bsz, Matthew Garrett

From: Matthew Garrett <mjg59@google.com>

UEFI systems provide a boot services protocol for obtaining the TPM
event log, but this is unusable after ExitBootServices() is called.
Unfortunately ExitBootServices() itself triggers additional TPM events
that then can't be obtained using this protocol. The platform provides a
mechanism for the OS to obtain these events by recording them to a
separate UEFI configuration table which the OS can then map.

Unfortunately this table isn't self describing in terms of providing its
length, so we need to parse the events inside it to figure out how long
it is. Since the table isn't mapped at this point, we need to extend the
length calculation function to be able to map the event as it goes
along.

(Fixes by Bartosz Szczepanek <bsz@semihalf.com>)

Signed-off-by: Matthew Garrett <mjg59@google.com>
---
 drivers/char/tpm/eventlog/tpm2.c |   2 +-
 drivers/firmware/efi/efi.c       |   2 +
 drivers/firmware/efi/tpm.c       |  62 ++++++++++++++++++-
 include/linux/efi.h              |   9 +++
 include/linux/tpm_eventlog.h     | 102 ++++++++++++++++++++++++++++---
 5 files changed, 164 insertions(+), 13 deletions(-)

diff --git a/drivers/char/tpm/eventlog/tpm2.c b/drivers/char/tpm/eventlog/tpm2.c
index 1a977bdd3bd2..de1d9f7e5a92 100644
--- a/drivers/char/tpm/eventlog/tpm2.c
+++ b/drivers/char/tpm/eventlog/tpm2.c
@@ -40,7 +40,7 @@
 static size_t calc_tpm2_event_size(struct tcg_pcr_event2_head *event,
 				   struct tcg_pcr_event *event_header)
 {
-	return __calc_tpm2_event_size(event, event_header);
+	return __calc_tpm2_event_size(event, event_header, false);
 }
 
 static void *tpm2_bios_measurements_start(struct seq_file *m, loff_t *pos)
diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
index 55b77c576c42..6b11c41e0575 100644
--- a/drivers/firmware/efi/efi.c
+++ b/drivers/firmware/efi/efi.c
@@ -53,6 +53,7 @@ struct efi __read_mostly efi = {
 	.mem_attr_table		= EFI_INVALID_TABLE_ADDR,
 	.rng_seed		= EFI_INVALID_TABLE_ADDR,
 	.tpm_log		= EFI_INVALID_TABLE_ADDR,
+	.tpm_final_log		= EFI_INVALID_TABLE_ADDR,
 	.mem_reserve		= EFI_INVALID_TABLE_ADDR,
 };
 EXPORT_SYMBOL(efi);
@@ -485,6 +486,7 @@ static __initdata efi_config_table_type_t common_tables[] = {
 	{EFI_MEMORY_ATTRIBUTES_TABLE_GUID, "MEMATTR", &efi.mem_attr_table},
 	{LINUX_EFI_RANDOM_SEED_TABLE_GUID, "RNG", &efi.rng_seed},
 	{LINUX_EFI_TPM_EVENT_LOG_GUID, "TPMEventLog", &efi.tpm_log},
+	{LINUX_EFI_TPM_FINAL_LOG_GUID, "TPMFinalLog", &efi.tpm_final_log},
 	{LINUX_EFI_MEMRESERVE_TABLE_GUID, "MEMRESERVE", &efi.mem_reserve},
 	{NULL_GUID, NULL, NULL},
 };
diff --git a/drivers/firmware/efi/tpm.c b/drivers/firmware/efi/tpm.c
index 3a689b40ccc0..2c912ea08166 100644
--- a/drivers/firmware/efi/tpm.c
+++ b/drivers/firmware/efi/tpm.c
@@ -4,34 +4,90 @@
  *     Thiebaud Weksteen <tweek@google.com>
  */
 
+#define TPM_MEMREMAP(start, size) early_memremap(start, size)
+#define TPM_MEMUNMAP(start, size) early_memunmap(start, size)
+
 #include <linux/efi.h>
 #include <linux/init.h>
 #include <linux/memblock.h>
+#include <linux/tpm_eventlog.h>
 
 #include <asm/early_ioremap.h>
 
+int efi_tpm_final_log_size;
+EXPORT_SYMBOL(efi_tpm_final_log_size);
+
+static int tpm2_calc_event_log_size(void *data, int count, void *size_info)
+{
+	struct tcg_pcr_event2_head *header;
+	int event_size, size = 0;
+
+	while (count > 0) {
+		header = data + size;
+		event_size = __calc_tpm2_event_size(header, size_info, true);
+		if (event_size == 0)
+			return -1;
+		size += event_size;
+		count--;
+	}
+
+	return size;
+}
+
 /*
  * Reserve the memory associated with the TPM Event Log configuration table.
  */
 int __init efi_tpm_eventlog_init(void)
 {
 	struct linux_efi_tpm_eventlog *log_tbl;
+	struct efi_tcg2_final_events_table *final_tbl;
 	unsigned int tbl_size;
+	int ret = 0;
 
-	if (efi.tpm_log == EFI_INVALID_TABLE_ADDR)
+	if (efi.tpm_log == EFI_INVALID_TABLE_ADDR) {
+		/*
+		 * We can't calculate the size of the final events without the
+		 * first entry in the TPM log, so bail here.
+		 */
 		return 0;
+	}
 
 	log_tbl = early_memremap(efi.tpm_log, sizeof(*log_tbl));
 	if (!log_tbl) {
 		pr_err("Failed to map TPM Event Log table @ 0x%lx\n",
-			efi.tpm_log);
+		       efi.tpm_log);
 		efi.tpm_log = EFI_INVALID_TABLE_ADDR;
 		return -ENOMEM;
 	}
 
 	tbl_size = sizeof(*log_tbl) + log_tbl->size;
 	memblock_reserve(efi.tpm_log, tbl_size);
+
+	if (efi.tpm_final_log == EFI_INVALID_TABLE_ADDR)
+		goto out;
+
+	final_tbl = early_memremap(efi.tpm_final_log, sizeof(*final_tbl));
+
+	if (!final_tbl) {
+		pr_err("Failed to map TPM Final Event Log table @ 0x%lx\n",
+		       efi.tpm_final_log);
+		efi.tpm_final_log = EFI_INVALID_TABLE_ADDR;
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	tbl_size = tpm2_calc_event_log_size(efi.tpm_final_log
+					    + sizeof(final_tbl->version)
+					    + sizeof(final_tbl->nr_events),
+					    final_tbl->nr_events,
+					    log_tbl->log);
+	memblock_reserve((unsigned long)final_tbl,
+			 tbl_size + sizeof(*final_tbl));
+	early_memunmap(final_tbl, sizeof(*final_tbl));
+	efi_tpm_final_log_size = tbl_size;
+
+out:
 	early_memunmap(log_tbl, sizeof(*log_tbl));
-	return 0;
+	return ret;
 }
 
diff --git a/include/linux/efi.h b/include/linux/efi.h
index 54357a258b35..e33c70a52a9d 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -689,6 +689,7 @@ void efi_native_runtime_setup(void);
 #define LINUX_EFI_LOADER_ENTRY_GUID		EFI_GUID(0x4a67b082, 0x0a4c, 0x41cf,  0xb6, 0xc7, 0x44, 0x0b, 0x29, 0xbb, 0x8c, 0x4f)
 #define LINUX_EFI_RANDOM_SEED_TABLE_GUID	EFI_GUID(0x1ce1e5bc, 0x7ceb, 0x42f2,  0x81, 0xe5, 0x8a, 0xad, 0xf1, 0x80, 0xf5, 0x7b)
 #define LINUX_EFI_TPM_EVENT_LOG_GUID		EFI_GUID(0xb7799cb0, 0xeca2, 0x4943,  0x96, 0x67, 0x1f, 0xae, 0x07, 0xb7, 0x47, 0xfa)
+#define LINUX_EFI_TPM_FINAL_LOG_GUID		EFI_GUID(0x1e2ed096, 0x30e2, 0x4254,  0xbd, 0x89, 0x86, 0x3b, 0xbe, 0xf8, 0x23, 0x25)
 #define LINUX_EFI_MEMRESERVE_TABLE_GUID		EFI_GUID(0x888eb0c6, 0x8ede, 0x4ff5,  0xa8, 0xf0, 0x9a, 0xee, 0x5c, 0xb9, 0x77, 0xc2)
 
 typedef struct {
@@ -996,6 +997,7 @@ extern struct efi {
 	unsigned long mem_attr_table;	/* memory attributes table */
 	unsigned long rng_seed;		/* UEFI firmware random seed */
 	unsigned long tpm_log;		/* TPM2 Event Log table */
+	unsigned long tpm_final_log;	/* TPM2 Final Events Log table */
 	unsigned long mem_reserve;	/* Linux EFI memreserve table */
 	efi_get_time_t *get_time;
 	efi_set_time_t *set_time;
@@ -1707,6 +1709,13 @@ struct linux_efi_tpm_eventlog {
 
 extern int efi_tpm_eventlog_init(void);
 
+struct efi_tcg2_final_events_table {
+	u64 version;
+	u64 nr_events;
+	u8 events[];
+};
+extern int efi_tpm_final_log_size;
+
 /*
  * efi_runtime_service() function identifiers.
  * "NONE" is used by efi_recover_from_page_fault() to check if the page
diff --git a/include/linux/tpm_eventlog.h b/include/linux/tpm_eventlog.h
index 6a86144e13f1..63238c84dc0b 100644
--- a/include/linux/tpm_eventlog.h
+++ b/include/linux/tpm_eventlog.h
@@ -112,10 +112,35 @@ struct tcg_pcr_event2_head {
 	struct tpm_digest digests[];
 } __packed;
 
+struct tcg_algorithm_size {
+	u16 algorithm_id;
+	u16 algorithm_size;
+};
+
+struct tcg_algorithm_info {
+	u8 signature[16];
+	u32 platform_class;
+	u8 spec_version_minor;
+	u8 spec_version_major;
+	u8 spec_errata;
+	u8 uintn_size;
+	u32 number_of_algorithms;
+	struct tcg_algorithm_size digest_sizes[];
+};
+
+#ifndef TPM_MEMREMAP
+#define TPM_MEMREMAP(start, size) NULL
+#endif
+
+#ifndef TPM_MEMUNMAP
+#define TPM_MEMUNMAP(start, size) do{} while(0)
+#endif
+
 /**
  * __calc_tpm2_event_size - calculate the size of a TPM2 event log entry
  * @event:        Pointer to the event whose size should be calculated
  * @event_header: Pointer to the initial event containing the digest lengths
+ * @do_mapping:   Whether or not the event needs to be mapped
  *
  * The TPM2 event log format can contain multiple digests corresponding to
  * separate PCR banks, and also contains a variable length of the data that
@@ -131,10 +156,13 @@ struct tcg_pcr_event2_head {
  */
 
 static inline int __calc_tpm2_event_size(struct tcg_pcr_event2_head *event,
-					 struct tcg_pcr_event *event_header)
+					 struct tcg_pcr_event *event_header,
+					 bool do_mapping)
 {
 	struct tcg_efi_specid_event_head *efispecid;
 	struct tcg_event_field *event_field;
+	void *mapping = NULL;
+	int mapping_size;
 	void *marker;
 	void *marker_start;
 	u32 halg_size;
@@ -148,16 +176,49 @@ static inline int __calc_tpm2_event_size(struct tcg_pcr_event2_head *event,
 	marker = marker + sizeof(event->pcr_idx) + sizeof(event->event_type)
 		+ sizeof(event->count);
 
+	/* Map the event header */
+	if (do_mapping) {
+		mapping_size = marker - marker_start;
+		mapping = TPM_MEMREMAP((unsigned long)marker_start,
+				       mapping_size);
+		if (!mapping) {
+			size = 0;
+			goto out;
+		}
+	} else {
+		mapping = marker_start;
+	}
+
+	event = (struct tcg_pcr_event2_head *)mapping;
+
 	efispecid = (struct tcg_efi_specid_event_head *)event_header->event;
 
 	/* Check if event is malformed. */
-	if (event->count > efispecid->num_algs)
-		return 0;
+	if (event->count > efispecid->num_algs) {
+		size = 0;
+		goto out;
+	}
 
 	for (i = 0; i < event->count; i++) {
 		halg_size = sizeof(event->digests[i].alg_id);
-		memcpy(&halg, marker, halg_size);
+
+		/* Map the digest's algorithm identifier */
+		if (do_mapping) {
+			TPM_MEMUNMAP(mapping, mapping_size);
+			mapping_size = halg_size;
+			mapping = TPM_MEMREMAP((unsigned long)marker,
+					     mapping_size);
+			if (!mapping) {
+				size = 0;
+				goto out;
+			}
+		} else {
+			mapping = marker;
+		}
+
+		memcpy(&halg, mapping, halg_size);
 		marker = marker + halg_size;
+
 		for (j = 0; j < efispecid->num_algs; j++) {
 			if (halg == efispecid->digest_sizes[j].alg_id) {
 				marker +=
@@ -166,18 +227,41 @@ static inline int __calc_tpm2_event_size(struct tcg_pcr_event2_head *event,
 			}
 		}
 		/* Algorithm without known length. Such event is unparseable. */
-		if (j == efispecid->num_algs)
-			return 0;
+		if (j == efispecid->num_algs) {
+			size = 0;
+			goto out;
+		}
+	}
+
+	/*
+	 * Map the event size - we don't read from the event itself, so
+	 * we don't need to map it
+	 */
+	if (do_mapping) {
+		TPM_MEMUNMAP(mapping, mapping_size);
+		mapping_size += sizeof(event_field->event_size);
+		mapping = TPM_MEMREMAP((unsigned long)marker,
+				       mapping_size);
+		if (!mapping) {
+			size = 0;
+			goto out;
+		}
+	} else {
+		mapping = marker;
 	}
 
-	event_field = (struct tcg_event_field *)marker;
+	event_field = (struct tcg_event_field *)mapping;
+
 	marker = marker + sizeof(event_field->event_size)
 		+ event_field->event_size;
 	size = marker - marker_start;
 
 	if ((event->event_type == 0) && (event_field->event_size == 0))
-		return 0;
-
+		size = 0;
+out:
+	if (do_mapping)
+		TPM_MEMUNMAP(mapping, mapping_size);
 	return size;
 }
+
 #endif
-- 
2.21.0.1020.gf2820cf01a-goog


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

* [PATCH V7 3/4] tpm: Append the final event log to the TPM event log
  2019-05-20 20:54 [PATCH V7 0/4] Add support for crypto agile logs Matthew Garrett
  2019-05-20 20:54 ` [PATCH V7 1/4] tpm: Abstract crypto agile event size calculations Matthew Garrett
  2019-05-20 20:54 ` [PATCH V7 2/4] tpm: Reserve the TPM final events table Matthew Garrett
@ 2019-05-20 20:55 ` Matthew Garrett
  2019-05-20 20:55 ` [PATCH V7 4/4] efi: Attempt to get the TCG2 event log in the boot stub Matthew Garrett
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 17+ messages in thread
From: Matthew Garrett @ 2019-05-20 20:55 UTC (permalink / raw)
  To: linux-integrity
  Cc: peterhuewe, jarkko.sakkinen, jgg, roberto.sassu, linux-efi,
	linux-security-module, linux-kernel, tweek, bsz, Matthew Garrett

From: Matthew Garrett <mjg59@google.com>

Any events that are logged after GetEventsLog() is called are logged to
the EFI Final Events table. These events are defined as being in the
crypto agile log format, so we can just append them directly to the
existing log if it's in the same format. In theory we can also construct
old-style SHA1 log entries for devices that only return logs in that
format, but EDK2 doesn't generate the final event log in that case so
it doesn't seem worth it at the moment.

Signed-off-by: Matthew Garrett <mjg59@google.com>
---
 drivers/char/tpm/eventlog/efi.c | 50 ++++++++++++++++++++++++++++-----
 1 file changed, 43 insertions(+), 7 deletions(-)

diff --git a/drivers/char/tpm/eventlog/efi.c b/drivers/char/tpm/eventlog/efi.c
index 3e673ab22cb4..9179cf6bdee9 100644
--- a/drivers/char/tpm/eventlog/efi.c
+++ b/drivers/char/tpm/eventlog/efi.c
@@ -21,10 +21,13 @@
 int tpm_read_log_efi(struct tpm_chip *chip)
 {
 
+	struct efi_tcg2_final_events_table *final_tbl = NULL;
 	struct linux_efi_tpm_eventlog *log_tbl;
 	struct tpm_bios_log *log;
 	u32 log_size;
 	u8 tpm_log_version;
+	void *tmp;
+	int ret;
 
 	if (!(chip->flags & TPM_CHIP_FLAG_TPM2))
 		return -ENODEV;
@@ -52,15 +55,48 @@ int tpm_read_log_efi(struct tpm_chip *chip)
 
 	/* malloc EventLog space */
 	log->bios_event_log = kmemdup(log_tbl->log, log_size, GFP_KERNEL);
-	if (!log->bios_event_log)
-		goto err_memunmap;
-	log->bios_event_log_end = log->bios_event_log + log_size;
+	if (!log->bios_event_log) {
+		ret = -ENOMEM;
+		goto out;
+	}
 
+	log->bios_event_log_end = log->bios_event_log + log_size;
 	tpm_log_version = log_tbl->version;
-	memunmap(log_tbl);
-	return tpm_log_version;
 
-err_memunmap:
+	ret = tpm_log_version;
+
+	if (efi.tpm_final_log == EFI_INVALID_TABLE_ADDR ||
+	    efi_tpm_final_log_size == 0 ||
+	    tpm_log_version != EFI_TCG2_EVENT_LOG_FORMAT_TCG_2)
+		goto out;
+
+	final_tbl = memremap(efi.tpm_final_log,
+			     sizeof(*final_tbl) + efi_tpm_final_log_size,
+			     MEMREMAP_WB);
+	if (!final_tbl) {
+		pr_err("Could not map UEFI TPM final log\n");
+		kfree(log->bios_event_log);
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	tmp = krealloc(log->bios_event_log,
+		       log_size + efi_tpm_final_log_size,
+		       GFP_KERNEL);
+	if (!tmp) {
+		kfree(log->bios_event_log);
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	log->bios_event_log = tmp;
+	memcpy((void *)log->bios_event_log + log_size,
+	       final_tbl->events, efi_tpm_final_log_size);
+	log->bios_event_log_end = log->bios_event_log +
+		log_size + efi_tpm_final_log_size;
+
+out:
+	memunmap(final_tbl);
 	memunmap(log_tbl);
-	return -ENOMEM;
+	return ret;
 }
-- 
2.21.0.1020.gf2820cf01a-goog


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

* [PATCH V7 4/4] efi: Attempt to get the TCG2 event log in the boot stub
  2019-05-20 20:54 [PATCH V7 0/4] Add support for crypto agile logs Matthew Garrett
                   ` (2 preceding siblings ...)
  2019-05-20 20:55 ` [PATCH V7 3/4] tpm: Append the final event log to the TPM event log Matthew Garrett
@ 2019-05-20 20:55 ` Matthew Garrett
  2019-05-21  9:26   ` Ard Biesheuvel
  2019-05-21 11:45 ` [PATCH V7 0/4] Add support for crypto agile logs Jarkko Sakkinen
                   ` (3 subsequent siblings)
  7 siblings, 1 reply; 17+ messages in thread
From: Matthew Garrett @ 2019-05-20 20:55 UTC (permalink / raw)
  To: linux-integrity
  Cc: peterhuewe, jarkko.sakkinen, jgg, roberto.sassu, linux-efi,
	linux-security-module, linux-kernel, tweek, bsz, Matthew Garrett

From: Matthew Garrett <mjg59@google.com>

Right now we only attempt to obtain the SHA1-only event log. The
protocol also supports a crypto agile log format, which contains digests
for all algorithms in use. Attempt to obtain this first, and fall back
to obtaining the older format if the system doesn't support it. This is
lightly complicated by the event sizes being variable (as we don't know
in advance which algorithms are in use), and the interface giving us
back a pointer to the start of the final entry rather than a pointer to
the end of the log - as a result, we need to parse the final entry to
figure out its length in order to know how much data to copy up to the
OS.

Signed-off-by: Matthew Garrett <mjg59@google.com>
---
 drivers/firmware/efi/libstub/tpm.c | 50 ++++++++++++++++++++----------
 1 file changed, 33 insertions(+), 17 deletions(-)

diff --git a/drivers/firmware/efi/libstub/tpm.c b/drivers/firmware/efi/libstub/tpm.c
index 5bd04f75d8d6..6b3b507a54eb 100644
--- a/drivers/firmware/efi/libstub/tpm.c
+++ b/drivers/firmware/efi/libstub/tpm.c
@@ -57,7 +57,7 @@ void efi_enable_reset_attack_mitigation(efi_system_table_t *sys_table_arg)
 
 #endif
 
-static void efi_retrieve_tpm2_eventlog_1_2(efi_system_table_t *sys_table_arg)
+void efi_retrieve_tpm2_eventlog(efi_system_table_t *sys_table_arg)
 {
 	efi_guid_t tcg2_guid = EFI_TCG2_PROTOCOL_GUID;
 	efi_guid_t linux_eventlog_guid = LINUX_EFI_TPM_EVENT_LOG_GUID;
@@ -67,6 +67,7 @@ static void efi_retrieve_tpm2_eventlog_1_2(efi_system_table_t *sys_table_arg)
 	unsigned long first_entry_addr, last_entry_addr;
 	size_t log_size, last_entry_size;
 	efi_bool_t truncated;
+	int version = EFI_TCG2_EVENT_LOG_FORMAT_TCG_2;
 	void *tcg2_protocol = NULL;
 
 	status = efi_call_early(locate_protocol, &tcg2_guid, NULL,
@@ -74,14 +75,20 @@ static void efi_retrieve_tpm2_eventlog_1_2(efi_system_table_t *sys_table_arg)
 	if (status != EFI_SUCCESS)
 		return;
 
-	status = efi_call_proto(efi_tcg2_protocol, get_event_log, tcg2_protocol,
-				EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2,
-				&log_location, &log_last_entry, &truncated);
-	if (status != EFI_SUCCESS)
-		return;
+	status = efi_call_proto(efi_tcg2_protocol, get_event_log,
+				tcg2_protocol, version, &log_location,
+				&log_last_entry, &truncated);
+
+	if (status != EFI_SUCCESS || !log_location) {
+		version = EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2;
+		status = efi_call_proto(efi_tcg2_protocol, get_event_log,
+					tcg2_protocol, version, &log_location,
+					&log_last_entry, &truncated);
+		if (status != EFI_SUCCESS || !log_location)
+			return;
+
+	}
 
-	if (!log_location)
-		return;
 	first_entry_addr = (unsigned long) log_location;
 
 	/*
@@ -96,8 +103,23 @@ static void efi_retrieve_tpm2_eventlog_1_2(efi_system_table_t *sys_table_arg)
 		 * We need to calculate its size to deduce the full size of
 		 * the logs.
 		 */
-		last_entry_size = sizeof(struct tcpa_event) +
-			((struct tcpa_event *) last_entry_addr)->event_size;
+		if (version == EFI_TCG2_EVENT_LOG_FORMAT_TCG_2) {
+			/*
+			 * The TCG2 log format has variable length entries,
+			 * and the information to decode the hash algorithms
+			 * back into a size is contained in the first entry -
+			 * pass a pointer to the final entry (to calculate its
+			 * size) and the first entry (so we know how long each
+			 * digest is)
+			 */
+			last_entry_size =
+				__calc_tpm2_event_size((void *)last_entry_addr,
+						    (void *)(long)log_location,
+						    false);
+		} else {
+			last_entry_size = sizeof(struct tcpa_event) +
+			   ((struct tcpa_event *) last_entry_addr)->event_size;
+		}
 		log_size = log_last_entry - log_location + last_entry_size;
 	}
 
@@ -114,7 +136,7 @@ static void efi_retrieve_tpm2_eventlog_1_2(efi_system_table_t *sys_table_arg)
 
 	memset(log_tbl, 0, sizeof(*log_tbl) + log_size);
 	log_tbl->size = log_size;
-	log_tbl->version = EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2;
+	log_tbl->version = version;
 	memcpy(log_tbl->log, (void *) first_entry_addr, log_size);
 
 	status = efi_call_early(install_configuration_table,
@@ -126,9 +148,3 @@ static void efi_retrieve_tpm2_eventlog_1_2(efi_system_table_t *sys_table_arg)
 err_free:
 	efi_call_early(free_pool, log_tbl);
 }
-
-void efi_retrieve_tpm2_eventlog(efi_system_table_t *sys_table_arg)
-{
-	/* Only try to retrieve the logs in 1.2 format. */
-	efi_retrieve_tpm2_eventlog_1_2(sys_table_arg);
-}
-- 
2.21.0.1020.gf2820cf01a-goog


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

* Re: [PATCH V7 4/4] efi: Attempt to get the TCG2 event log in the boot stub
  2019-05-20 20:55 ` [PATCH V7 4/4] efi: Attempt to get the TCG2 event log in the boot stub Matthew Garrett
@ 2019-05-21  9:26   ` Ard Biesheuvel
  0 siblings, 0 replies; 17+ messages in thread
From: Ard Biesheuvel @ 2019-05-21  9:26 UTC (permalink / raw)
  To: Matthew Garrett
  Cc: linux-integrity, Peter Hüwe, Jarkko Sakkinen,
	Jason Gunthorpe, Roberto Sassu, linux-efi, linux-security-module,
	Linux Kernel Mailing List, Thiebaud Weksteen, Bartosz Szczepanek,
	Matthew Garrett

On Mon, 20 May 2019 at 21:55, Matthew Garrett <matthewgarrett@google.com> wrote:
>
> From: Matthew Garrett <mjg59@google.com>
>
> Right now we only attempt to obtain the SHA1-only event log. The
> protocol also supports a crypto agile log format, which contains digests
> for all algorithms in use. Attempt to obtain this first, and fall back
> to obtaining the older format if the system doesn't support it. This is
> lightly complicated by the event sizes being variable (as we don't know
> in advance which algorithms are in use), and the interface giving us
> back a pointer to the start of the final entry rather than a pointer to
> the end of the log - as a result, we need to parse the final entry to
> figure out its length in order to know how much data to copy up to the
> OS.
>
> Signed-off-by: Matthew Garrett <mjg59@google.com>

Provided that this gets a tested-by from Bartosz,

Acked-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>

> ---
>  drivers/firmware/efi/libstub/tpm.c | 50 ++++++++++++++++++++----------
>  1 file changed, 33 insertions(+), 17 deletions(-)
>
> diff --git a/drivers/firmware/efi/libstub/tpm.c b/drivers/firmware/efi/libstub/tpm.c
> index 5bd04f75d8d6..6b3b507a54eb 100644
> --- a/drivers/firmware/efi/libstub/tpm.c
> +++ b/drivers/firmware/efi/libstub/tpm.c
> @@ -57,7 +57,7 @@ void efi_enable_reset_attack_mitigation(efi_system_table_t *sys_table_arg)
>
>  #endif
>
> -static void efi_retrieve_tpm2_eventlog_1_2(efi_system_table_t *sys_table_arg)
> +void efi_retrieve_tpm2_eventlog(efi_system_table_t *sys_table_arg)
>  {
>         efi_guid_t tcg2_guid = EFI_TCG2_PROTOCOL_GUID;
>         efi_guid_t linux_eventlog_guid = LINUX_EFI_TPM_EVENT_LOG_GUID;
> @@ -67,6 +67,7 @@ static void efi_retrieve_tpm2_eventlog_1_2(efi_system_table_t *sys_table_arg)
>         unsigned long first_entry_addr, last_entry_addr;
>         size_t log_size, last_entry_size;
>         efi_bool_t truncated;
> +       int version = EFI_TCG2_EVENT_LOG_FORMAT_TCG_2;
>         void *tcg2_protocol = NULL;
>
>         status = efi_call_early(locate_protocol, &tcg2_guid, NULL,
> @@ -74,14 +75,20 @@ static void efi_retrieve_tpm2_eventlog_1_2(efi_system_table_t *sys_table_arg)
>         if (status != EFI_SUCCESS)
>                 return;
>
> -       status = efi_call_proto(efi_tcg2_protocol, get_event_log, tcg2_protocol,
> -                               EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2,
> -                               &log_location, &log_last_entry, &truncated);
> -       if (status != EFI_SUCCESS)
> -               return;
> +       status = efi_call_proto(efi_tcg2_protocol, get_event_log,
> +                               tcg2_protocol, version, &log_location,
> +                               &log_last_entry, &truncated);
> +
> +       if (status != EFI_SUCCESS || !log_location) {
> +               version = EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2;
> +               status = efi_call_proto(efi_tcg2_protocol, get_event_log,
> +                                       tcg2_protocol, version, &log_location,
> +                                       &log_last_entry, &truncated);
> +               if (status != EFI_SUCCESS || !log_location)
> +                       return;
> +
> +       }
>
> -       if (!log_location)
> -               return;
>         first_entry_addr = (unsigned long) log_location;
>
>         /*
> @@ -96,8 +103,23 @@ static void efi_retrieve_tpm2_eventlog_1_2(efi_system_table_t *sys_table_arg)
>                  * We need to calculate its size to deduce the full size of
>                  * the logs.
>                  */
> -               last_entry_size = sizeof(struct tcpa_event) +
> -                       ((struct tcpa_event *) last_entry_addr)->event_size;
> +               if (version == EFI_TCG2_EVENT_LOG_FORMAT_TCG_2) {
> +                       /*
> +                        * The TCG2 log format has variable length entries,
> +                        * and the information to decode the hash algorithms
> +                        * back into a size is contained in the first entry -
> +                        * pass a pointer to the final entry (to calculate its
> +                        * size) and the first entry (so we know how long each
> +                        * digest is)
> +                        */
> +                       last_entry_size =
> +                               __calc_tpm2_event_size((void *)last_entry_addr,
> +                                                   (void *)(long)log_location,
> +                                                   false);
> +               } else {
> +                       last_entry_size = sizeof(struct tcpa_event) +
> +                          ((struct tcpa_event *) last_entry_addr)->event_size;
> +               }
>                 log_size = log_last_entry - log_location + last_entry_size;
>         }
>
> @@ -114,7 +136,7 @@ static void efi_retrieve_tpm2_eventlog_1_2(efi_system_table_t *sys_table_arg)
>
>         memset(log_tbl, 0, sizeof(*log_tbl) + log_size);
>         log_tbl->size = log_size;
> -       log_tbl->version = EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2;
> +       log_tbl->version = version;
>         memcpy(log_tbl->log, (void *) first_entry_addr, log_size);
>
>         status = efi_call_early(install_configuration_table,
> @@ -126,9 +148,3 @@ static void efi_retrieve_tpm2_eventlog_1_2(efi_system_table_t *sys_table_arg)
>  err_free:
>         efi_call_early(free_pool, log_tbl);
>  }
> -
> -void efi_retrieve_tpm2_eventlog(efi_system_table_t *sys_table_arg)
> -{
> -       /* Only try to retrieve the logs in 1.2 format. */
> -       efi_retrieve_tpm2_eventlog_1_2(sys_table_arg);
> -}
> --
> 2.21.0.1020.gf2820cf01a-goog
>

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

* Re: [PATCH V7 2/4] tpm: Reserve the TPM final events table
  2019-05-20 20:54 ` [PATCH V7 2/4] tpm: Reserve the TPM final events table Matthew Garrett
@ 2019-05-21  9:29   ` Ard Biesheuvel
  2019-05-31  8:24   ` Joe Richey
  1 sibling, 0 replies; 17+ messages in thread
From: Ard Biesheuvel @ 2019-05-21  9:29 UTC (permalink / raw)
  To: Matthew Garrett
  Cc: linux-integrity, Peter Hüwe, Jarkko Sakkinen,
	Jason Gunthorpe, Roberto Sassu, linux-efi, linux-security-module,
	Linux Kernel Mailing List, Thiebaud Weksteen, Bartosz Szczepanek,
	Matthew Garrett

On Mon, 20 May 2019 at 21:55, Matthew Garrett <matthewgarrett@google.com> wrote:
>
> From: Matthew Garrett <mjg59@google.com>
>
> UEFI systems provide a boot services protocol for obtaining the TPM
> event log, but this is unusable after ExitBootServices() is called.
> Unfortunately ExitBootServices() itself triggers additional TPM events
> that then can't be obtained using this protocol. The platform provides a
> mechanism for the OS to obtain these events by recording them to a
> separate UEFI configuration table which the OS can then map.
>
> Unfortunately this table isn't self describing in terms of providing its
> length, so we need to parse the events inside it to figure out how long
> it is. Since the table isn't mapped at this point, we need to extend the
> length calculation function to be able to map the event as it goes
> along.
>
> (Fixes by Bartosz Szczepanek <bsz@semihalf.com>)
>
> Signed-off-by: Matthew Garrett <mjg59@google.com>

Acked-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>

> ---
>  drivers/char/tpm/eventlog/tpm2.c |   2 +-
>  drivers/firmware/efi/efi.c       |   2 +
>  drivers/firmware/efi/tpm.c       |  62 ++++++++++++++++++-
>  include/linux/efi.h              |   9 +++
>  include/linux/tpm_eventlog.h     | 102 ++++++++++++++++++++++++++++---
>  5 files changed, 164 insertions(+), 13 deletions(-)
>
> diff --git a/drivers/char/tpm/eventlog/tpm2.c b/drivers/char/tpm/eventlog/tpm2.c
> index 1a977bdd3bd2..de1d9f7e5a92 100644
> --- a/drivers/char/tpm/eventlog/tpm2.c
> +++ b/drivers/char/tpm/eventlog/tpm2.c
> @@ -40,7 +40,7 @@
>  static size_t calc_tpm2_event_size(struct tcg_pcr_event2_head *event,
>                                    struct tcg_pcr_event *event_header)
>  {
> -       return __calc_tpm2_event_size(event, event_header);
> +       return __calc_tpm2_event_size(event, event_header, false);
>  }
>
>  static void *tpm2_bios_measurements_start(struct seq_file *m, loff_t *pos)
> diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
> index 55b77c576c42..6b11c41e0575 100644
> --- a/drivers/firmware/efi/efi.c
> +++ b/drivers/firmware/efi/efi.c
> @@ -53,6 +53,7 @@ struct efi __read_mostly efi = {
>         .mem_attr_table         = EFI_INVALID_TABLE_ADDR,
>         .rng_seed               = EFI_INVALID_TABLE_ADDR,
>         .tpm_log                = EFI_INVALID_TABLE_ADDR,
> +       .tpm_final_log          = EFI_INVALID_TABLE_ADDR,
>         .mem_reserve            = EFI_INVALID_TABLE_ADDR,
>  };
>  EXPORT_SYMBOL(efi);
> @@ -485,6 +486,7 @@ static __initdata efi_config_table_type_t common_tables[] = {
>         {EFI_MEMORY_ATTRIBUTES_TABLE_GUID, "MEMATTR", &efi.mem_attr_table},
>         {LINUX_EFI_RANDOM_SEED_TABLE_GUID, "RNG", &efi.rng_seed},
>         {LINUX_EFI_TPM_EVENT_LOG_GUID, "TPMEventLog", &efi.tpm_log},
> +       {LINUX_EFI_TPM_FINAL_LOG_GUID, "TPMFinalLog", &efi.tpm_final_log},
>         {LINUX_EFI_MEMRESERVE_TABLE_GUID, "MEMRESERVE", &efi.mem_reserve},
>         {NULL_GUID, NULL, NULL},
>  };
> diff --git a/drivers/firmware/efi/tpm.c b/drivers/firmware/efi/tpm.c
> index 3a689b40ccc0..2c912ea08166 100644
> --- a/drivers/firmware/efi/tpm.c
> +++ b/drivers/firmware/efi/tpm.c
> @@ -4,34 +4,90 @@
>   *     Thiebaud Weksteen <tweek@google.com>
>   */
>
> +#define TPM_MEMREMAP(start, size) early_memremap(start, size)
> +#define TPM_MEMUNMAP(start, size) early_memunmap(start, size)
> +
>  #include <linux/efi.h>
>  #include <linux/init.h>
>  #include <linux/memblock.h>
> +#include <linux/tpm_eventlog.h>
>
>  #include <asm/early_ioremap.h>
>
> +int efi_tpm_final_log_size;
> +EXPORT_SYMBOL(efi_tpm_final_log_size);
> +
> +static int tpm2_calc_event_log_size(void *data, int count, void *size_info)
> +{
> +       struct tcg_pcr_event2_head *header;
> +       int event_size, size = 0;
> +
> +       while (count > 0) {
> +               header = data + size;
> +               event_size = __calc_tpm2_event_size(header, size_info, true);
> +               if (event_size == 0)
> +                       return -1;
> +               size += event_size;
> +               count--;
> +       }
> +
> +       return size;
> +}
> +
>  /*
>   * Reserve the memory associated with the TPM Event Log configuration table.
>   */
>  int __init efi_tpm_eventlog_init(void)
>  {
>         struct linux_efi_tpm_eventlog *log_tbl;
> +       struct efi_tcg2_final_events_table *final_tbl;
>         unsigned int tbl_size;
> +       int ret = 0;
>
> -       if (efi.tpm_log == EFI_INVALID_TABLE_ADDR)
> +       if (efi.tpm_log == EFI_INVALID_TABLE_ADDR) {
> +               /*
> +                * We can't calculate the size of the final events without the
> +                * first entry in the TPM log, so bail here.
> +                */
>                 return 0;
> +       }
>
>         log_tbl = early_memremap(efi.tpm_log, sizeof(*log_tbl));
>         if (!log_tbl) {
>                 pr_err("Failed to map TPM Event Log table @ 0x%lx\n",
> -                       efi.tpm_log);
> +                      efi.tpm_log);
>                 efi.tpm_log = EFI_INVALID_TABLE_ADDR;
>                 return -ENOMEM;
>         }
>
>         tbl_size = sizeof(*log_tbl) + log_tbl->size;
>         memblock_reserve(efi.tpm_log, tbl_size);
> +
> +       if (efi.tpm_final_log == EFI_INVALID_TABLE_ADDR)
> +               goto out;
> +
> +       final_tbl = early_memremap(efi.tpm_final_log, sizeof(*final_tbl));
> +
> +       if (!final_tbl) {
> +               pr_err("Failed to map TPM Final Event Log table @ 0x%lx\n",
> +                      efi.tpm_final_log);
> +               efi.tpm_final_log = EFI_INVALID_TABLE_ADDR;
> +               ret = -ENOMEM;
> +               goto out;
> +       }
> +
> +       tbl_size = tpm2_calc_event_log_size(efi.tpm_final_log
> +                                           + sizeof(final_tbl->version)
> +                                           + sizeof(final_tbl->nr_events),
> +                                           final_tbl->nr_events,
> +                                           log_tbl->log);
> +       memblock_reserve((unsigned long)final_tbl,
> +                        tbl_size + sizeof(*final_tbl));
> +       early_memunmap(final_tbl, sizeof(*final_tbl));
> +       efi_tpm_final_log_size = tbl_size;
> +
> +out:
>         early_memunmap(log_tbl, sizeof(*log_tbl));
> -       return 0;
> +       return ret;
>  }
>
> diff --git a/include/linux/efi.h b/include/linux/efi.h
> index 54357a258b35..e33c70a52a9d 100644
> --- a/include/linux/efi.h
> +++ b/include/linux/efi.h
> @@ -689,6 +689,7 @@ void efi_native_runtime_setup(void);
>  #define LINUX_EFI_LOADER_ENTRY_GUID            EFI_GUID(0x4a67b082, 0x0a4c, 0x41cf,  0xb6, 0xc7, 0x44, 0x0b, 0x29, 0xbb, 0x8c, 0x4f)
>  #define LINUX_EFI_RANDOM_SEED_TABLE_GUID       EFI_GUID(0x1ce1e5bc, 0x7ceb, 0x42f2,  0x81, 0xe5, 0x8a, 0xad, 0xf1, 0x80, 0xf5, 0x7b)
>  #define LINUX_EFI_TPM_EVENT_LOG_GUID           EFI_GUID(0xb7799cb0, 0xeca2, 0x4943,  0x96, 0x67, 0x1f, 0xae, 0x07, 0xb7, 0x47, 0xfa)
> +#define LINUX_EFI_TPM_FINAL_LOG_GUID           EFI_GUID(0x1e2ed096, 0x30e2, 0x4254,  0xbd, 0x89, 0x86, 0x3b, 0xbe, 0xf8, 0x23, 0x25)
>  #define LINUX_EFI_MEMRESERVE_TABLE_GUID                EFI_GUID(0x888eb0c6, 0x8ede, 0x4ff5,  0xa8, 0xf0, 0x9a, 0xee, 0x5c, 0xb9, 0x77, 0xc2)
>
>  typedef struct {
> @@ -996,6 +997,7 @@ extern struct efi {
>         unsigned long mem_attr_table;   /* memory attributes table */
>         unsigned long rng_seed;         /* UEFI firmware random seed */
>         unsigned long tpm_log;          /* TPM2 Event Log table */
> +       unsigned long tpm_final_log;    /* TPM2 Final Events Log table */
>         unsigned long mem_reserve;      /* Linux EFI memreserve table */
>         efi_get_time_t *get_time;
>         efi_set_time_t *set_time;
> @@ -1707,6 +1709,13 @@ struct linux_efi_tpm_eventlog {
>
>  extern int efi_tpm_eventlog_init(void);
>
> +struct efi_tcg2_final_events_table {
> +       u64 version;
> +       u64 nr_events;
> +       u8 events[];
> +};
> +extern int efi_tpm_final_log_size;
> +
>  /*
>   * efi_runtime_service() function identifiers.
>   * "NONE" is used by efi_recover_from_page_fault() to check if the page
> diff --git a/include/linux/tpm_eventlog.h b/include/linux/tpm_eventlog.h
> index 6a86144e13f1..63238c84dc0b 100644
> --- a/include/linux/tpm_eventlog.h
> +++ b/include/linux/tpm_eventlog.h
> @@ -112,10 +112,35 @@ struct tcg_pcr_event2_head {
>         struct tpm_digest digests[];
>  } __packed;
>
> +struct tcg_algorithm_size {
> +       u16 algorithm_id;
> +       u16 algorithm_size;
> +};
> +
> +struct tcg_algorithm_info {
> +       u8 signature[16];
> +       u32 platform_class;
> +       u8 spec_version_minor;
> +       u8 spec_version_major;
> +       u8 spec_errata;
> +       u8 uintn_size;
> +       u32 number_of_algorithms;
> +       struct tcg_algorithm_size digest_sizes[];
> +};
> +
> +#ifndef TPM_MEMREMAP
> +#define TPM_MEMREMAP(start, size) NULL
> +#endif
> +
> +#ifndef TPM_MEMUNMAP
> +#define TPM_MEMUNMAP(start, size) do{} while(0)
> +#endif
> +
>  /**
>   * __calc_tpm2_event_size - calculate the size of a TPM2 event log entry
>   * @event:        Pointer to the event whose size should be calculated
>   * @event_header: Pointer to the initial event containing the digest lengths
> + * @do_mapping:   Whether or not the event needs to be mapped
>   *
>   * The TPM2 event log format can contain multiple digests corresponding to
>   * separate PCR banks, and also contains a variable length of the data that
> @@ -131,10 +156,13 @@ struct tcg_pcr_event2_head {
>   */
>
>  static inline int __calc_tpm2_event_size(struct tcg_pcr_event2_head *event,
> -                                        struct tcg_pcr_event *event_header)
> +                                        struct tcg_pcr_event *event_header,
> +                                        bool do_mapping)
>  {
>         struct tcg_efi_specid_event_head *efispecid;
>         struct tcg_event_field *event_field;
> +       void *mapping = NULL;
> +       int mapping_size;
>         void *marker;
>         void *marker_start;
>         u32 halg_size;
> @@ -148,16 +176,49 @@ static inline int __calc_tpm2_event_size(struct tcg_pcr_event2_head *event,
>         marker = marker + sizeof(event->pcr_idx) + sizeof(event->event_type)
>                 + sizeof(event->count);
>
> +       /* Map the event header */
> +       if (do_mapping) {
> +               mapping_size = marker - marker_start;
> +               mapping = TPM_MEMREMAP((unsigned long)marker_start,
> +                                      mapping_size);
> +               if (!mapping) {
> +                       size = 0;
> +                       goto out;
> +               }
> +       } else {
> +               mapping = marker_start;
> +       }
> +
> +       event = (struct tcg_pcr_event2_head *)mapping;
> +
>         efispecid = (struct tcg_efi_specid_event_head *)event_header->event;
>
>         /* Check if event is malformed. */
> -       if (event->count > efispecid->num_algs)
> -               return 0;
> +       if (event->count > efispecid->num_algs) {
> +               size = 0;
> +               goto out;
> +       }
>
>         for (i = 0; i < event->count; i++) {
>                 halg_size = sizeof(event->digests[i].alg_id);
> -               memcpy(&halg, marker, halg_size);
> +
> +               /* Map the digest's algorithm identifier */
> +               if (do_mapping) {
> +                       TPM_MEMUNMAP(mapping, mapping_size);
> +                       mapping_size = halg_size;
> +                       mapping = TPM_MEMREMAP((unsigned long)marker,
> +                                            mapping_size);
> +                       if (!mapping) {
> +                               size = 0;
> +                               goto out;
> +                       }
> +               } else {
> +                       mapping = marker;
> +               }
> +
> +               memcpy(&halg, mapping, halg_size);
>                 marker = marker + halg_size;
> +
>                 for (j = 0; j < efispecid->num_algs; j++) {
>                         if (halg == efispecid->digest_sizes[j].alg_id) {
>                                 marker +=
> @@ -166,18 +227,41 @@ static inline int __calc_tpm2_event_size(struct tcg_pcr_event2_head *event,
>                         }
>                 }
>                 /* Algorithm without known length. Such event is unparseable. */
> -               if (j == efispecid->num_algs)
> -                       return 0;
> +               if (j == efispecid->num_algs) {
> +                       size = 0;
> +                       goto out;
> +               }
> +       }
> +
> +       /*
> +        * Map the event size - we don't read from the event itself, so
> +        * we don't need to map it
> +        */
> +       if (do_mapping) {
> +               TPM_MEMUNMAP(mapping, mapping_size);
> +               mapping_size += sizeof(event_field->event_size);
> +               mapping = TPM_MEMREMAP((unsigned long)marker,
> +                                      mapping_size);
> +               if (!mapping) {
> +                       size = 0;
> +                       goto out;
> +               }
> +       } else {
> +               mapping = marker;
>         }
>
> -       event_field = (struct tcg_event_field *)marker;
> +       event_field = (struct tcg_event_field *)mapping;
> +
>         marker = marker + sizeof(event_field->event_size)
>                 + event_field->event_size;
>         size = marker - marker_start;
>
>         if ((event->event_type == 0) && (event_field->event_size == 0))
> -               return 0;
> -
> +               size = 0;
> +out:
> +       if (do_mapping)
> +               TPM_MEMUNMAP(mapping, mapping_size);
>         return size;
>  }
> +
>  #endif
> --
> 2.21.0.1020.gf2820cf01a-goog
>

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

* Re: [PATCH V7 0/4] Add support for crypto agile logs
  2019-05-20 20:54 [PATCH V7 0/4] Add support for crypto agile logs Matthew Garrett
                   ` (3 preceding siblings ...)
  2019-05-20 20:55 ` [PATCH V7 4/4] efi: Attempt to get the TCG2 event log in the boot stub Matthew Garrett
@ 2019-05-21 11:45 ` Jarkko Sakkinen
  2019-05-23 12:14 ` Jarkko Sakkinen
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 17+ messages in thread
From: Jarkko Sakkinen @ 2019-05-21 11:45 UTC (permalink / raw)
  To: Matthew Garrett
  Cc: linux-integrity, peterhuewe, jgg, roberto.sassu, linux-efi,
	linux-security-module, linux-kernel, tweek, bsz

On Mon, May 20, 2019 at 01:54:57PM -0700, Matthew Garrett wrote:
> Identical to previous version except without the KSAN workaround - Ard
> has a better solution for that.

I'll check in detail through tomorrow but probably will get merged
now that we have Ard's ack's (thanks Ard for all the trouble!) :-)

/Jarkko

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

* Re: [PATCH V7 0/4] Add support for crypto agile logs
  2019-05-20 20:54 [PATCH V7 0/4] Add support for crypto agile logs Matthew Garrett
                   ` (4 preceding siblings ...)
  2019-05-21 11:45 ` [PATCH V7 0/4] Add support for crypto agile logs Jarkko Sakkinen
@ 2019-05-23 12:14 ` Jarkko Sakkinen
  2019-05-23 12:26   ` Jarkko Sakkinen
  2019-05-23 16:15 ` Bartosz Szczepanek
  2019-05-31 18:07 ` Joe Richey
  7 siblings, 1 reply; 17+ messages in thread
From: Jarkko Sakkinen @ 2019-05-23 12:14 UTC (permalink / raw)
  To: Matthew Garrett
  Cc: linux-integrity, peterhuewe, jgg, roberto.sassu, linux-efi,
	linux-security-module, linux-kernel, tweek, bsz

On Mon, May 20, 2019 at 01:54:57PM -0700, Matthew Garrett wrote:
> Identical to previous version except without the KSAN workaround - Ard
> has a better solution for that.


Reviewed-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
Tested-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>

/Jarkko

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

* Re: [PATCH V7 0/4] Add support for crypto agile logs
  2019-05-23 12:14 ` Jarkko Sakkinen
@ 2019-05-23 12:26   ` Jarkko Sakkinen
  2019-05-23 16:54     ` James Morris
  0 siblings, 1 reply; 17+ messages in thread
From: Jarkko Sakkinen @ 2019-05-23 12:26 UTC (permalink / raw)
  To: Matthew Garrett, jmorris
  Cc: linux-integrity, peterhuewe, jgg, roberto.sassu, linux-efi,
	linux-security-module, linux-kernel, tweek, bsz

On Thu, May 23, 2019 at 03:14:49PM +0300, Jarkko Sakkinen wrote:
> On Mon, May 20, 2019 at 01:54:57PM -0700, Matthew Garrett wrote:
> > Identical to previous version except without the KSAN workaround - Ard
> > has a better solution for that.
> 
> 
> Reviewed-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
> Tested-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>

Only applied to my master at this point becaues the patches from
my earlier PRs are not yet mirrored to security/next-general.

/Jarkko

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

* Re: [PATCH V7 0/4] Add support for crypto agile logs
  2019-05-20 20:54 [PATCH V7 0/4] Add support for crypto agile logs Matthew Garrett
                   ` (5 preceding siblings ...)
  2019-05-23 12:14 ` Jarkko Sakkinen
@ 2019-05-23 16:15 ` Bartosz Szczepanek
  2019-05-31 18:07 ` Joe Richey
  7 siblings, 0 replies; 17+ messages in thread
From: Bartosz Szczepanek @ 2019-05-23 16:15 UTC (permalink / raw)
  To: Matthew Garrett
  Cc: linux-integrity, Peter Huewe, Jarkko Sakkinen, Jason Gunthorpe,
	Roberto Sassu, linux-efi, LSM List, Linux Kernel Mailing List,
	Thiébaud Weksteen

On Mon, May 20, 2019 at 10:55 PM Matthew Garrett
<matthewgarrett@google.com> wrote:
>
> Identical to previous version except without the KSAN workaround - Ard
> has a better solution for that.

Just tested the patchset on aarch64, all works fine.

Reviewed-by: Bartosz Szczepanek <bsz@semihalf.com>
Tested-by: Bartosz Szczepanek <bsz@semihalf.com>

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

* Re: [PATCH V7 0/4] Add support for crypto agile logs
  2019-05-23 12:26   ` Jarkko Sakkinen
@ 2019-05-23 16:54     ` James Morris
  2019-05-24 10:38       ` Jarkko Sakkinen
  0 siblings, 1 reply; 17+ messages in thread
From: James Morris @ 2019-05-23 16:54 UTC (permalink / raw)
  To: Jarkko Sakkinen
  Cc: Matthew Garrett, linux-integrity, peterhuewe, jgg, roberto.sassu,
	linux-efi, linux-security-module, linux-kernel, tweek, bsz

On Thu, 23 May 2019, Jarkko Sakkinen wrote:

> On Thu, May 23, 2019 at 03:14:49PM +0300, Jarkko Sakkinen wrote:
> > On Mon, May 20, 2019 at 01:54:57PM -0700, Matthew Garrett wrote:
> > > Identical to previous version except without the KSAN workaround - Ard
> > > has a better solution for that.
> > 
> > 
> > Reviewed-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
> > Tested-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
> 
> Only applied to my master at this point becaues the patches from
> my earlier PRs are not yet mirrored to security/next-general.

Which PRs are these?

btw, Linus wants security subsystem maintainers to submit PRs directly to 
him from now on.

I'll only be carrying patches for the core LSM and new security mechanisms 
before they're merged and have a maintainer assigned.


-- 
James Morris
<jmorris@namei.org>


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

* Re: [PATCH V7 0/4] Add support for crypto agile logs
  2019-05-23 16:54     ` James Morris
@ 2019-05-24 10:38       ` Jarkko Sakkinen
  2019-05-24 19:22         ` James Morris
  0 siblings, 1 reply; 17+ messages in thread
From: Jarkko Sakkinen @ 2019-05-24 10:38 UTC (permalink / raw)
  To: James Morris
  Cc: Matthew Garrett, linux-integrity, peterhuewe, jgg, roberto.sassu,
	linux-efi, linux-security-module, linux-kernel, tweek, bsz

On Fri, May 24, 2019 at 02:54:20AM +1000, James Morris wrote:
> On Thu, 23 May 2019, Jarkko Sakkinen wrote:
> 
> > On Thu, May 23, 2019 at 03:14:49PM +0300, Jarkko Sakkinen wrote:
> > > On Mon, May 20, 2019 at 01:54:57PM -0700, Matthew Garrett wrote:
> > > > Identical to previous version except without the KSAN workaround - Ard
> > > > has a better solution for that.
> > > 
> > > 
> > > Reviewed-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
> > > Tested-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
> > 
> > Only applied to my master at this point becaues the patches from
> > my earlier PRs are not yet mirrored to security/next-general.
> 
> Which PRs are these?
> 
> btw, Linus wants security subsystem maintainers to submit PRs directly to 
> him from now on.
> 
> I'll only be carrying patches for the core LSM and new security mechanisms 
> before they're merged and have a maintainer assigned.

I'm referring to these:

https://lore.kernel.org/linux-integrity/20190329115544.GA27351@linux.intel.com/

I got response from you that those were applied and there is another
response in that thread that they are being sent to Linus. That is why I
haven't done anything since. Most of them are critical fixes to v5.1
changes.

Should I now take the action to send a PR to Linus and tag them to
stable?

/Jarkko

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

* Re: [PATCH V7 0/4] Add support for crypto agile logs
  2019-05-24 10:38       ` Jarkko Sakkinen
@ 2019-05-24 19:22         ` James Morris
  2019-05-27 14:31           ` Jarkko Sakkinen
  0 siblings, 1 reply; 17+ messages in thread
From: James Morris @ 2019-05-24 19:22 UTC (permalink / raw)
  To: Jarkko Sakkinen
  Cc: Matthew Garrett, linux-integrity, peterhuewe, jgg, roberto.sassu,
	linux-efi, linux-security-module, linux-kernel, tweek, bsz,
	Linus Torvalds

On Fri, 24 May 2019, Jarkko Sakkinen wrote:

> I'm referring to these:
> 
> https://lore.kernel.org/linux-integrity/20190329115544.GA27351@linux.intel.com/
> 
> I got response from you that those were applied and there is another
> response in that thread that they are being sent to Linus. That is why I
> haven't done anything since. Most of them are critical fixes to v5.1
> changes.

These are in Linus' tree.  

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=a556810d8e06aa2da8bbe22da3d105eb5a0d0c7d

I initially queued them in the next-tpm branch, but forgot to drop them 
from there after sending them to Linus as a v5.1 fix. Linus was not happy 
to see them again in the v5.2 merge window.

Apologies for the confusion.

-- 
James Morris
<jmorris@namei.org>


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

* Re: [PATCH V7 0/4] Add support for crypto agile logs
  2019-05-24 19:22         ` James Morris
@ 2019-05-27 14:31           ` Jarkko Sakkinen
  0 siblings, 0 replies; 17+ messages in thread
From: Jarkko Sakkinen @ 2019-05-27 14:31 UTC (permalink / raw)
  To: James Morris
  Cc: Matthew Garrett, linux-integrity, peterhuewe, jgg, roberto.sassu,
	linux-efi, linux-security-module, linux-kernel, tweek, bsz,
	Linus Torvalds

On Sat, May 25, 2019 at 05:22:34AM +1000, James Morris wrote:
> On Fri, 24 May 2019, Jarkko Sakkinen wrote:
> 
> > I'm referring to these:
> > 
> > https://lore.kernel.org/linux-integrity/20190329115544.GA27351@linux.intel.com/
> > 
> > I got response from you that those were applied and there is another
> > response in that thread that they are being sent to Linus. That is why I
> > haven't done anything since. Most of them are critical fixes to v5.1
> > changes.
> 
> These are in Linus' tree.  
> 
> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=a556810d8e06aa2da8bbe22da3d105eb5a0d0c7d
> 
> I initially queued them in the next-tpm branch, but forgot to drop them 
> from there after sending them to Linus as a v5.1 fix. Linus was not happy 
> to see them again in the v5.2 merge window.
> 
> Apologies for the confusion.

OK, just to confirm, my next PR will go straight to Linus?

/Jarkko

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

* Re: [PATCH V7 2/4] tpm: Reserve the TPM final events table
  2019-05-20 20:54 ` [PATCH V7 2/4] tpm: Reserve the TPM final events table Matthew Garrett
  2019-05-21  9:29   ` Ard Biesheuvel
@ 2019-05-31  8:24   ` Joe Richey
  1 sibling, 0 replies; 17+ messages in thread
From: Joe Richey @ 2019-05-31  8:24 UTC (permalink / raw)
  To: Matthew Garrett
  Cc: linux-integrity, peterhuewe, jarkko.sakkinen, jgg, roberto.sassu,
	linux-efi, linux-security-module, linux-kernel,
	Thiébaud Weksteen, bsz, Matthew Garrett

[-- Attachment #1: Type: text/plain, Size: 14300 bytes --]

On Mon, May 20, 2019 at 1:55 PM Matthew Garrett
<matthewgarrett@google.com> wrote:
>
> From: Matthew Garrett <mjg59@google.com>
>
> UEFI systems provide a boot services protocol for obtaining the TPM
> event log, but this is unusable after ExitBootServices() is called.
> Unfortunately ExitBootServices() itself triggers additional TPM events
> that then can't be obtained using this protocol. The platform provides a
> mechanism for the OS to obtain these events by recording them to a
> separate UEFI configuration table which the OS can then map.
>
> Unfortunately this table isn't self describing in terms of providing its
> length, so we need to parse the events inside it to figure out how long
> it is. Since the table isn't mapped at this point, we need to extend the
> length calculation function to be able to map the event as it goes
> along.
>
> (Fixes by Bartosz Szczepanek <bsz@semihalf.com>)
>
> Signed-off-by: Matthew Garrett <mjg59@google.com>
> ---
>  drivers/char/tpm/eventlog/tpm2.c |   2 +-
>  drivers/firmware/efi/efi.c       |   2 +
>  drivers/firmware/efi/tpm.c       |  62 ++++++++++++++++++-
>  include/linux/efi.h              |   9 +++
>  include/linux/tpm_eventlog.h     | 102 ++++++++++++++++++++++++++++---
>  5 files changed, 164 insertions(+), 13 deletions(-)
>
> diff --git a/drivers/char/tpm/eventlog/tpm2.c b/drivers/char/tpm/eventlog/tpm2.c
> index 1a977bdd3bd2..de1d9f7e5a92 100644
> --- a/drivers/char/tpm/eventlog/tpm2.c
> +++ b/drivers/char/tpm/eventlog/tpm2.c
> @@ -40,7 +40,7 @@
>  static size_t calc_tpm2_event_size(struct tcg_pcr_event2_head *event,
>                                    struct tcg_pcr_event *event_header)
>  {
> -       return __calc_tpm2_event_size(event, event_header);
> +       return __calc_tpm2_event_size(event, event_header, false);
>  }
>
>  static void *tpm2_bios_measurements_start(struct seq_file *m, loff_t *pos)
> diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
> index 55b77c576c42..6b11c41e0575 100644
> --- a/drivers/firmware/efi/efi.c
> +++ b/drivers/firmware/efi/efi.c
> @@ -53,6 +53,7 @@ struct efi __read_mostly efi = {
>         .mem_attr_table         = EFI_INVALID_TABLE_ADDR,
>         .rng_seed               = EFI_INVALID_TABLE_ADDR,
>         .tpm_log                = EFI_INVALID_TABLE_ADDR,
> +       .tpm_final_log          = EFI_INVALID_TABLE_ADDR,
>         .mem_reserve            = EFI_INVALID_TABLE_ADDR,
>  };
>  EXPORT_SYMBOL(efi);
> @@ -485,6 +486,7 @@ static __initdata efi_config_table_type_t common_tables[] = {
>         {EFI_MEMORY_ATTRIBUTES_TABLE_GUID, "MEMATTR", &efi.mem_attr_table},
>         {LINUX_EFI_RANDOM_SEED_TABLE_GUID, "RNG", &efi.rng_seed},
>         {LINUX_EFI_TPM_EVENT_LOG_GUID, "TPMEventLog", &efi.tpm_log},
> +       {LINUX_EFI_TPM_FINAL_LOG_GUID, "TPMFinalLog", &efi.tpm_final_log},
>         {LINUX_EFI_MEMRESERVE_TABLE_GUID, "MEMRESERVE", &efi.mem_reserve},
>         {NULL_GUID, NULL, NULL},
>  };
> diff --git a/drivers/firmware/efi/tpm.c b/drivers/firmware/efi/tpm.c
> index 3a689b40ccc0..2c912ea08166 100644
> --- a/drivers/firmware/efi/tpm.c
> +++ b/drivers/firmware/efi/tpm.c
> @@ -4,34 +4,90 @@
>   *     Thiebaud Weksteen <tweek@google.com>
>   */
>
> +#define TPM_MEMREMAP(start, size) early_memremap(start, size)
> +#define TPM_MEMUNMAP(start, size) early_memunmap(start, size)
> +
>  #include <linux/efi.h>
>  #include <linux/init.h>
>  #include <linux/memblock.h>
> +#include <linux/tpm_eventlog.h>
>
>  #include <asm/early_ioremap.h>
>
> +int efi_tpm_final_log_size;
> +EXPORT_SYMBOL(efi_tpm_final_log_size);
> +
> +static int tpm2_calc_event_log_size(void *data, int count, void *size_info)
> +{
> +       struct tcg_pcr_event2_head *header;
> +       int event_size, size = 0;
> +
> +       while (count > 0) {
> +               header = data + size;
> +               event_size = __calc_tpm2_event_size(header, size_info, true);
> +               if (event_size == 0)
> +                       return -1;
> +               size += event_size;
> +               count--;
> +       }
> +
> +       return size;
> +}
> +
>  /*
>   * Reserve the memory associated with the TPM Event Log configuration table.
>   */
>  int __init efi_tpm_eventlog_init(void)
>  {
>         struct linux_efi_tpm_eventlog *log_tbl;
> +       struct efi_tcg2_final_events_table *final_tbl;
>         unsigned int tbl_size;
> +       int ret = 0;
>
> -       if (efi.tpm_log == EFI_INVALID_TABLE_ADDR)
> +       if (efi.tpm_log == EFI_INVALID_TABLE_ADDR) {
> +               /*
> +                * We can't calculate the size of the final events without the
> +                * first entry in the TPM log, so bail here.
> +                */
>                 return 0;
> +       }
>
>         log_tbl = early_memremap(efi.tpm_log, sizeof(*log_tbl));
>         if (!log_tbl) {
>                 pr_err("Failed to map TPM Event Log table @ 0x%lx\n",
> -                       efi.tpm_log);
> +                      efi.tpm_log);
>                 efi.tpm_log = EFI_INVALID_TABLE_ADDR;
>                 return -ENOMEM;
>         }
>
>         tbl_size = sizeof(*log_tbl) + log_tbl->size;
>         memblock_reserve(efi.tpm_log, tbl_size);
> +
> +       if (efi.tpm_final_log == EFI_INVALID_TABLE_ADDR)
> +               goto out;
> +
> +       final_tbl = early_memremap(efi.tpm_final_log, sizeof(*final_tbl));
> +
> +       if (!final_tbl) {
> +               pr_err("Failed to map TPM Final Event Log table @ 0x%lx\n",
> +                      efi.tpm_final_log);
> +               efi.tpm_final_log = EFI_INVALID_TABLE_ADDR;
> +               ret = -ENOMEM;
> +               goto out;
> +       }
> +
> +       tbl_size = tpm2_calc_event_log_size(efi.tpm_final_log
> +                                           + sizeof(final_tbl->version)
> +                                           + sizeof(final_tbl->nr_events),
This line causes:
warning: passing argument 1 of ‘tpm2_calc_event_log_size’ makes
pointer from integer without a cast

> +                                           final_tbl->nr_events,
> +                                           log_tbl->log);
> +       memblock_reserve((unsigned long)final_tbl,
> +                        tbl_size + sizeof(*final_tbl));
> +       early_memunmap(final_tbl, sizeof(*final_tbl));
> +       efi_tpm_final_log_size = tbl_size;
> +
> +out:
>         early_memunmap(log_tbl, sizeof(*log_tbl));
> -       return 0;
> +       return ret;
>  }
>
> diff --git a/include/linux/efi.h b/include/linux/efi.h
> index 54357a258b35..e33c70a52a9d 100644
> --- a/include/linux/efi.h
> +++ b/include/linux/efi.h
> @@ -689,6 +689,7 @@ void efi_native_runtime_setup(void);
>  #define LINUX_EFI_LOADER_ENTRY_GUID            EFI_GUID(0x4a67b082, 0x0a4c, 0x41cf,  0xb6, 0xc7, 0x44, 0x0b, 0x29, 0xbb, 0x8c, 0x4f)
>  #define LINUX_EFI_RANDOM_SEED_TABLE_GUID       EFI_GUID(0x1ce1e5bc, 0x7ceb, 0x42f2,  0x81, 0xe5, 0x8a, 0xad, 0xf1, 0x80, 0xf5, 0x7b)
>  #define LINUX_EFI_TPM_EVENT_LOG_GUID           EFI_GUID(0xb7799cb0, 0xeca2, 0x4943,  0x96, 0x67, 0x1f, 0xae, 0x07, 0xb7, 0x47, 0xfa)
> +#define LINUX_EFI_TPM_FINAL_LOG_GUID           EFI_GUID(0x1e2ed096, 0x30e2, 0x4254,  0xbd, 0x89, 0x86, 0x3b, 0xbe, 0xf8, 0x23, 0x25)
>  #define LINUX_EFI_MEMRESERVE_TABLE_GUID                EFI_GUID(0x888eb0c6, 0x8ede, 0x4ff5,  0xa8, 0xf0, 0x9a, 0xee, 0x5c, 0xb9, 0x77, 0xc2)
>
>  typedef struct {
> @@ -996,6 +997,7 @@ extern struct efi {
>         unsigned long mem_attr_table;   /* memory attributes table */
>         unsigned long rng_seed;         /* UEFI firmware random seed */
>         unsigned long tpm_log;          /* TPM2 Event Log table */
> +       unsigned long tpm_final_log;    /* TPM2 Final Events Log table */
>         unsigned long mem_reserve;      /* Linux EFI memreserve table */
>         efi_get_time_t *get_time;
>         efi_set_time_t *set_time;
> @@ -1707,6 +1709,13 @@ struct linux_efi_tpm_eventlog {
>
>  extern int efi_tpm_eventlog_init(void);
>
> +struct efi_tcg2_final_events_table {
> +       u64 version;
> +       u64 nr_events;
> +       u8 events[];
> +};
> +extern int efi_tpm_final_log_size;
> +
>  /*
>   * efi_runtime_service() function identifiers.
>   * "NONE" is used by efi_recover_from_page_fault() to check if the page
> diff --git a/include/linux/tpm_eventlog.h b/include/linux/tpm_eventlog.h
> index 6a86144e13f1..63238c84dc0b 100644
> --- a/include/linux/tpm_eventlog.h
> +++ b/include/linux/tpm_eventlog.h
> @@ -112,10 +112,35 @@ struct tcg_pcr_event2_head {
>         struct tpm_digest digests[];
>  } __packed;
>
> +struct tcg_algorithm_size {
> +       u16 algorithm_id;
> +       u16 algorithm_size;
> +};
> +
> +struct tcg_algorithm_info {
> +       u8 signature[16];
> +       u32 platform_class;
> +       u8 spec_version_minor;
> +       u8 spec_version_major;
> +       u8 spec_errata;
> +       u8 uintn_size;
> +       u32 number_of_algorithms;
> +       struct tcg_algorithm_size digest_sizes[];
> +};
> +
> +#ifndef TPM_MEMREMAP
> +#define TPM_MEMREMAP(start, size) NULL
> +#endif
> +
> +#ifndef TPM_MEMUNMAP
> +#define TPM_MEMUNMAP(start, size) do{} while(0)
> +#endif
> +
>  /**
>   * __calc_tpm2_event_size - calculate the size of a TPM2 event log entry
>   * @event:        Pointer to the event whose size should be calculated
>   * @event_header: Pointer to the initial event containing the digest lengths
> + * @do_mapping:   Whether or not the event needs to be mapped
>   *
>   * The TPM2 event log format can contain multiple digests corresponding to
>   * separate PCR banks, and also contains a variable length of the data that
> @@ -131,10 +156,13 @@ struct tcg_pcr_event2_head {
>   */
>
>  static inline int __calc_tpm2_event_size(struct tcg_pcr_event2_head *event,
> -                                        struct tcg_pcr_event *event_header)
> +                                        struct tcg_pcr_event *event_header,
> +                                        bool do_mapping)
>  {
>         struct tcg_efi_specid_event_head *efispecid;
>         struct tcg_event_field *event_field;
> +       void *mapping = NULL;
> +       int mapping_size;
>         void *marker;
>         void *marker_start;
>         u32 halg_size;
> @@ -148,16 +176,49 @@ static inline int __calc_tpm2_event_size(struct tcg_pcr_event2_head *event,
>         marker = marker + sizeof(event->pcr_idx) + sizeof(event->event_type)
>                 + sizeof(event->count);
>
> +       /* Map the event header */
> +       if (do_mapping) {
> +               mapping_size = marker - marker_start;
> +               mapping = TPM_MEMREMAP((unsigned long)marker_start,
> +                                      mapping_size);
> +               if (!mapping) {
> +                       size = 0;
> +                       goto out;
> +               }
> +       } else {
> +               mapping = marker_start;
> +       }
> +
> +       event = (struct tcg_pcr_event2_head *)mapping;
> +
>         efispecid = (struct tcg_efi_specid_event_head *)event_header->event;
>
>         /* Check if event is malformed. */
> -       if (event->count > efispecid->num_algs)
> -               return 0;
> +       if (event->count > efispecid->num_algs) {
> +               size = 0;
> +               goto out;
> +       }
>
>         for (i = 0; i < event->count; i++) {
>                 halg_size = sizeof(event->digests[i].alg_id);
> -               memcpy(&halg, marker, halg_size);
> +
> +               /* Map the digest's algorithm identifier */
> +               if (do_mapping) {
> +                       TPM_MEMUNMAP(mapping, mapping_size);
> +                       mapping_size = halg_size;
> +                       mapping = TPM_MEMREMAP((unsigned long)marker,
> +                                            mapping_size);
> +                       if (!mapping) {
> +                               size = 0;
> +                               goto out;
> +                       }
> +               } else {
> +                       mapping = marker;
> +               }
> +
> +               memcpy(&halg, mapping, halg_size);
>                 marker = marker + halg_size;
> +
>                 for (j = 0; j < efispecid->num_algs; j++) {
>                         if (halg == efispecid->digest_sizes[j].alg_id) {
>                                 marker +=
> @@ -166,18 +227,41 @@ static inline int __calc_tpm2_event_size(struct tcg_pcr_event2_head *event,
>                         }
>                 }
>                 /* Algorithm without known length. Such event is unparseable. */
> -               if (j == efispecid->num_algs)
> -                       return 0;
> +               if (j == efispecid->num_algs) {
> +                       size = 0;
> +                       goto out;
> +               }
> +       }
> +
> +       /*
> +        * Map the event size - we don't read from the event itself, so
> +        * we don't need to map it
> +        */
> +       if (do_mapping) {
> +               TPM_MEMUNMAP(mapping, mapping_size);
> +               mapping_size += sizeof(event_field->event_size);
> +               mapping = TPM_MEMREMAP((unsigned long)marker,
> +                                      mapping_size);
> +               if (!mapping) {
> +                       size = 0;
> +                       goto out;
> +               }
> +       } else {
> +               mapping = marker;
>         }
>
> -       event_field = (struct tcg_event_field *)marker;
> +       event_field = (struct tcg_event_field *)mapping;
> +
>         marker = marker + sizeof(event_field->event_size)
>                 + event_field->event_size;
>         size = marker - marker_start;
>
>         if ((event->event_type == 0) && (event_field->event_size == 0))
> -               return 0;
> -
> +               size = 0;
> +out:
> +       if (do_mapping)
> +               TPM_MEMUNMAP(mapping, mapping_size);
>         return size;
>  }
> +
>  #endif
> --
> 2.21.0.1020.gf2820cf01a-goog
>

[-- Attachment #2: S/MIME Cryptographic Signature --]
[-- Type: application/pkcs7-signature, Size: 4849 bytes --]

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

* Re: [PATCH V7 0/4] Add support for crypto agile logs
  2019-05-20 20:54 [PATCH V7 0/4] Add support for crypto agile logs Matthew Garrett
                   ` (6 preceding siblings ...)
  2019-05-23 16:15 ` Bartosz Szczepanek
@ 2019-05-31 18:07 ` Joe Richey
  7 siblings, 0 replies; 17+ messages in thread
From: Joe Richey @ 2019-05-31 18:07 UTC (permalink / raw)
  To: Matthew Garrett
  Cc: linux-integrity, peterhuewe, jarkko.sakkinen, jgg, roberto.sassu,
	linux-efi, linux-security-module, linux-kernel,
	Thiébaud Weksteen, bsz

[-- Attachment #1: Type: text/plain, Size: 1275 bytes --]

On Mon, May 20, 2019 at 1:56 PM Matthew Garrett
<matthewgarrett@google.com> wrote:
>
> Identical to previous version except without the KSAN workaround - Ard
> has a better solution for that.

I just tested this on x86_64 with the systemd-boot (previously gummiboot)
bootloader. For context, this bootloader is essentially just an EFI
chainloader. This bootloader measures the kernel cmdline into PCR 8.
However, it calls GetEventLog before calling HashLogExtendEvent, intending
to have the log entry written to the "EFI TCG 2.0 final events table". See:
    https://github.com/systemd/systemd/blob/75e40119a471454516ad0acc96f6f4094e7fb652/src/boot/efi/measure.c#L212-L227

With the current patchset, this log entry appears _twice_ in the sysfs file.
This is caused by the fact that the sysfs event log unconditionally appends
the entire final event log to the output of GetEventLog. However, the correct
behavior would be to append only the _new_ entries that appear in the final
event log to the output of GetEventLog.

This could be done by first calculating the length of the final events log
table, then recalculating the length of the final events log after the
kernel calls ExitBootServices. This would let us know for sure that we are
only appending new log entries.

[-- Attachment #2: S/MIME Cryptographic Signature --]
[-- Type: application/pkcs7-signature, Size: 4849 bytes --]

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

end of thread, other threads:[~2019-05-31 18:07 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-05-20 20:54 [PATCH V7 0/4] Add support for crypto agile logs Matthew Garrett
2019-05-20 20:54 ` [PATCH V7 1/4] tpm: Abstract crypto agile event size calculations Matthew Garrett
2019-05-20 20:54 ` [PATCH V7 2/4] tpm: Reserve the TPM final events table Matthew Garrett
2019-05-21  9:29   ` Ard Biesheuvel
2019-05-31  8:24   ` Joe Richey
2019-05-20 20:55 ` [PATCH V7 3/4] tpm: Append the final event log to the TPM event log Matthew Garrett
2019-05-20 20:55 ` [PATCH V7 4/4] efi: Attempt to get the TCG2 event log in the boot stub Matthew Garrett
2019-05-21  9:26   ` Ard Biesheuvel
2019-05-21 11:45 ` [PATCH V7 0/4] Add support for crypto agile logs Jarkko Sakkinen
2019-05-23 12:14 ` Jarkko Sakkinen
2019-05-23 12:26   ` Jarkko Sakkinen
2019-05-23 16:54     ` James Morris
2019-05-24 10:38       ` Jarkko Sakkinen
2019-05-24 19:22         ` James Morris
2019-05-27 14:31           ` Jarkko Sakkinen
2019-05-23 16:15 ` Bartosz Szczepanek
2019-05-31 18:07 ` Joe Richey

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).