diff mbox series

[v4,08/33] tpm: Implement measurements of the master boot record

Message ID 20191211202728.127996-9-stefanb@linux.vnet.ibm.com
State Superseded
Headers show
Series Add vTPM support to SLOF | expand

Commit Message

Stefan Berger Dec. 11, 2019, 8:27 p.m. UTC
This patch adds support for measuring the boot block of the MBR and logging the
measurement. It also puts an 'event' separator into the log that can then be
seen in Linux's /sys/kernel/security/tpm0/ascii_bios_measurements. More
low-level C functions are added for measuring and logging of disk related data,
along with their FORTH-level counterparts.

Logging follows the specifications found on the following page:

http://www.trustedcomputinggroup.org/resources/pc_client_work_group_specific_implementation_specification_for_conventional_bios

Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
---
 board-qemu/slof/vtpm-sml.fs    |  23 +++++++
 lib/libtpm/tcgbios.c           | 107 +++++++++++++++++++++++++++++++++
 lib/libtpm/tcgbios.h           |   6 ++
 lib/libtpm/tpm.code            |  23 +++++++
 lib/libtpm/tpm.in              |   2 +
 slof/fs/packages/disk-label.fs |  10 ++-
 6 files changed, 170 insertions(+), 1 deletion(-)
diff mbox series

Patch

diff --git a/board-qemu/slof/vtpm-sml.fs b/board-qemu/slof/vtpm-sml.fs
index 557aa62..b4a0fc1 100644
--- a/board-qemu/slof/vtpm-sml.fs
+++ b/board-qemu/slof/vtpm-sml.fs
@@ -88,6 +88,29 @@  log-base LOG-SIZE tpm-set-log-parameters
 \ internal API calls
 \
 
+: separator-event ( start-pcr end-pcr -- )
+    tpm-add-event-separators                          ( errcode )
+    dup 0<> IF
+        ." VTPM: Error code from tpm-add-event-separators: " . cr
+    ELSE
+        drop
+    THEN
+;
+
+80 CONSTANT BCV_DEVICE_HDD
+
+: measure-hdd-mbr ( addr -- )
+    4 5 separator-event
+    200 BCV_DEVICE_HDD                         ( addr length bootdrv )
+    -rot                                       ( bootdrv addr length )
+    tpm-measure-bcv-mbr                        ( errcode )
+    dup 0<> IF
+        ." VTPM: Error code from tpm-measure-hdd: " . cr
+    ELSE
+        drop
+    THEN
+;
+
 : unassert-physical-presence ( -- )
     tpm-unassert-physical-presence                    ( errcode )
     dup 0<> IF
diff --git a/lib/libtpm/tcgbios.c b/lib/libtpm/tcgbios.c
index d655ae1..401bb1c 100644
--- a/lib/libtpm/tcgbios.c
+++ b/lib/libtpm/tcgbios.c
@@ -421,6 +421,35 @@  static uint32_t hash_log_extend(struct pcpes *pcpes,
 	return 0;
 }
 
+/*
+ * Add a measurement to the log;
+ *
+ * Input parameters:
+ *  @pcrindex : PCR to extend
+ *  @event_type : type of event
+ *  @info : pointer to info (i.e., string) to be added to the log as-is
+ *  @info_length: length of the info
+ *  @hashdata : pointer to data to be hashed
+ *  @hashdata_length: length of the data
+ *
+ */
+static uint32_t tpm_add_measurement_to_log(uint32_t pcrindex,
+					   uint32_t eventtype,
+					   const char *info,
+					   uint32_t infolen,
+					   const uint8_t *hashdata,
+					   uint32_t hashdatalen)
+{
+	struct pcpes pcpes;
+
+	pcpes.pcrindex	= pcrindex;
+	pcpes.eventtype = eventtype;
+	memset(&pcpes.digest, 0, sizeof(pcpes.digest));
+
+	return hash_log_extend(&pcpes, hashdata, hashdatalen,
+			       info, infolen, true);
+}
+
 /*
  * tpm_hash_log_extend_event: Function for interfacing with the firmware API
  */
@@ -439,3 +468,81 @@  uint32_t tpm_hash_log_extend_event(struct pcpes *pcpes)
 			       &pcpes->event, pcpes->eventdatasize,
 			       event, event_length, true);
 }
+
+/*
+ * Add an EV_ACTION measurement to the list of measurements
+ */
+static uint32_t tpm_add_action(uint32_t pcrIndex, const char *string)
+{
+	uint32_t len = strlen(string);
+
+	return tpm_add_measurement_to_log(pcrIndex, EV_ACTION,
+					  string, len, (uint8_t *)string, len);
+}
+
+/*
+ * Add event separators for a range of PCRs
+ */
+uint32_t tpm_add_event_separators(uint32_t start_pcr, uint32_t end_pcr)
+{
+	static const uint8_t evt_separator[] = {0xff,0xff,0xff,0xff};
+	uint32_t rc = 0;
+	uint32_t pcrIndex;
+
+	if (!tpm_is_working())
+		return TCGBIOS_GENERAL_ERROR;
+
+	if (start_pcr >= 24 || start_pcr > end_pcr)
+		return TCGBIOS_INVALID_INPUT_PARA;
+
+	/* event separators need to be extended and logged for PCRs 0-7 */
+	for (pcrIndex = start_pcr; pcrIndex <= end_pcr; pcrIndex++) {
+		rc = tpm_add_measurement_to_log(pcrIndex, EV_SEPARATOR,
+						NULL, 0,
+						evt_separator,
+						sizeof(evt_separator));
+		if (rc)
+			break;
+	}
+
+	return rc;
+}
+
+uint32_t tpm_measure_bcv_mbr(uint32_t bootdrv, const uint8_t *addr,
+			     uint32_t length)
+{
+	uint32_t rc;
+	const char *string;
+
+	if (!tpm_is_working())
+		return TCGBIOS_GENERAL_ERROR;
+
+	if (length < 0x200)
+		return TCGBIOS_INVALID_INPUT_PARA;
+
+	string = "Booting BCV device 00h (Floppy)";
+	if (bootdrv == BCV_DEVICE_HDD)
+		string = "Booting BCV device 80h (HDD)";
+
+	rc = tpm_add_action(4, string);
+	if (rc)
+		return rc;
+
+	/*
+	 * equivalent to: dd if=/dev/hda ibs=1 count=440 | sha1sum
+	 */
+	string = "MBR";
+	rc = tpm_add_measurement_to_log(4, EV_IPL,
+					string, strlen(string),
+					addr, 0x1b8);
+	if (rc)
+		return rc;
+
+	/*
+	 * equivalent to: dd if=/dev/hda ibs=1 count=72 skip=440 | sha1sum
+	 */
+	string = "MBR PARTITION TABLE";
+	return tpm_add_measurement_to_log(5, EV_IPL_PARTITION_DATA,
+					  string, strlen(string),
+					  addr + 0x1b8, 0x48);
+}
diff --git a/lib/libtpm/tcgbios.h b/lib/libtpm/tcgbios.h
index 592ae6d..3ccfca5 100644
--- a/lib/libtpm/tcgbios.h
+++ b/lib/libtpm/tcgbios.h
@@ -16,6 +16,9 @@ 
 #include <stdint.h>
 #include <stdbool.h>
 
+#define BCV_DEVICE_FLOPPY  0x0
+#define BCV_DEVICE_HDD     0x80
+
 struct pcpes;
 
 uint32_t tpm_start(void);
@@ -26,5 +29,8 @@  uint32_t tpm_get_logsize(void);
 uint32_t tpm_hash_log_extend_event(struct pcpes *pcpes);
 bool tpm_log_event(struct pcpes *pcpes);
 uint32_t tpm_hash_all(const void *data, uint32_t datalen, void *hashptr);
+uint32_t tpm_measure_bcv_mbr(uint32_t bootdrv, const uint8_t *addr,
+                             uint32_t length);
+uint32_t tpm_add_event_separators(uint32_t start_pcr, uint32_t end_pcr);
 
 #endif /* TCGBIOS_H */
diff --git a/lib/libtpm/tpm.code b/lib/libtpm/tpm.code
index eed9fbf..d4a1a72 100644
--- a/lib/libtpm/tpm.code
+++ b/lib/libtpm/tpm.code
@@ -97,3 +97,26 @@  PRIM(tpm_X2d_get_X2d_logsize)
 	PUSH;
 	TOS.n = tpm_get_logsize();
 MIRP
+
+/**********************************************************************/
+/* Measure and log event separators                                   */
+/* SLOF:   tpm-add-event-separators  ( start-pcr end-pcr -- errcode)  */
+/* LIBTPM: errcode = tpm_add_event_separators(start_pcr, end_pcr)     */
+/**********************************************************************/
+PRIM(tpm_X2d_add_X2d_event_X2d_separators)
+	int end_pcr = TOS.u; POP;
+	int start_pcr = TOS.u;
+	TOS.n = tpm_add_event_separators(start_pcr, end_pcr);
+MIRP
+
+/*************************************************************************/
+/* Measure and log boot connect vector (bcv) device's master boot record */
+/* SLOF:   tpm-measure-bcv-mbr  ( bootdrv addr length -- errcode )       */
+/* LIBTPM: errcode = tpm_measure_bcv_mbr(bbotdrv, addr, length)          */
+/*************************************************************************/
+PRIM(tpm_X2d_measure_X2d_bcv_X2d_mbr)
+	int length = TOS.u; POP;
+	void *addr = TOS.a; POP;
+	int bootdrv = TOS.u;
+	TOS.n = tpm_measure_bcv_mbr(bootdrv, addr, length);
+MIRP
diff --git a/lib/libtpm/tpm.in b/lib/libtpm/tpm.in
index 1e8ffc1..2d3d75e 100644
--- a/lib/libtpm/tpm.in
+++ b/lib/libtpm/tpm.in
@@ -21,3 +21,5 @@  cod(tpm-get-logsize)
 cod(tpm-log-event)
 cod(tpm-hash-log-extend-event)
 cod(tpm-hash-all)
+cod(tpm-add-event-separators)
+cod(tpm-measure-bcv-mbr)
diff --git a/slof/fs/packages/disk-label.fs b/slof/fs/packages/disk-label.fs
index 8859fb0..b130743 100644
--- a/slof/fs/packages/disk-label.fs
+++ b/slof/fs/packages/disk-label.fs
@@ -550,7 +550,15 @@  B9E5                CONSTANT GPT-BASIC-DATA-PARTITION-2
 \ load from a bootable partition
 : load-from-boot-partition ( addr -- size )
    debug-disk-label? IF ." Trying DOS boot " .s cr THEN
-   dup load-from-dos-boot-partition ?dup 0 <> IF nip EXIT THEN
+   dup load-from-dos-boot-partition ?dup 0 <> IF
+      nip
+      block s" /ibm,vtpm" find-node dup IF
+         s" measure-hdd-mbr" rot $call-static
+      ELSE
+         2drop
+      THEN
+      EXIT
+   THEN
 
    debug-disk-label? IF ." Trying CHRP boot " .s cr THEN
    1 disk-chrp-boot !