From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Javier Martinez Canillas <javierm@redhat.com>
Date: Fri, 21 Sep 2018 17:51:16 +0200
Subject: [PATCH] drop TPM support for legacy BIOS

Currently there's TPM support for both EFI and legacy BIOS.

A software interrupt call interface is used in legacy BIOS to communicate
with the TPM chips. But with some BIOS firmwares, the machine just hangs
after doing a BIOS interrupt call for the TCG_HashLogExtendEvent command.

It's hard to know what exactly is causing this, but the Trousers project
mentions in their docs that they don't use TCG_HashLogExtendEvent [0] due
the command not working reliable on some BIOS.

The TCG_CompactHashLogExtendEvent is less fragile, since it has a simpler
interface, doesn't require to setup any data structure and doesn't return
anything. So it could be used to do measurements and logs events instead.

But even when using this command can be a workaround on some systems, it
doesn't guarantee that could not fail on others. So since the TPM support
for some legacy BIOS don't work and can lead to machines failing to boot,
let's just drop it and only support TPM for EFI.

[0]: http://trousers.sourceforge.net/grub.html

Resolves: rhbz#1579835

Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
---
 grub-core/Makefile.core.def       |   1 -
 grub-core/kern/i386/pc/tpm.c      | 145 --------------------------------------
 grub-core/loader/i386/pc/linux.c  |   4 --
 include/grub/tpm.h                |   2 +-
 grub-core/boot/i386/pc/boot.S     |  30 +-------
 grub-core/boot/i386/pc/diskboot.S |  44 ------------
 6 files changed, 2 insertions(+), 224 deletions(-)
 delete mode 100644 grub-core/kern/i386/pc/tpm.c

diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index cf3d549d2..fb0a1e0ba 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -246,7 +246,6 @@ kernel = {
 
   i386_pc = kern/i386/pc/init.c;
   i386_pc = kern/i386/pc/mmap.c;
-  i386_pc = kern/i386/pc/tpm.c;
   i386_pc = term/i386/pc/console.c;
 
   i386_qemu = bus/pci.c;
diff --git a/grub-core/kern/i386/pc/tpm.c b/grub-core/kern/i386/pc/tpm.c
deleted file mode 100644
index f6f264aff..000000000
--- a/grub-core/kern/i386/pc/tpm.c
+++ /dev/null
@@ -1,145 +0,0 @@
-#include <grub/err.h>
-#include <grub/i18n.h>
-#include <grub/mm.h>
-#include <grub/tpm.h>
-#include <grub/misc.h>
-#include <grub/i386/pc/int.h>
-
-#define TCPA_MAGIC 0x41504354
-
-static int tpm_presence = -1;
-
-int tpm_present(void);
-
-int tpm_present(void)
-{
-  struct grub_bios_int_registers regs;
-
-  if (tpm_presence != -1)
-    return tpm_presence;
-
-  regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT;
-  regs.eax = 0xbb00;
-  regs.ebx = TCPA_MAGIC;
-  grub_bios_interrupt (0x1a, &regs);
-
-  if (regs.eax == 0)
-    tpm_presence = 1;
-  else
-    tpm_presence = 0;
-
-  return tpm_presence;
-}
-
-grub_err_t
-grub_tpm_execute(PassThroughToTPM_InputParamBlock *inbuf,
-		 PassThroughToTPM_OutputParamBlock *outbuf)
-{
-  struct grub_bios_int_registers regs;
-  grub_addr_t inaddr, outaddr;
-
-  if (!tpm_present())
-    return 0;
-
-  inaddr = (grub_addr_t) inbuf;
-  outaddr = (grub_addr_t) outbuf;
-  regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT;
-  regs.eax = 0xbb02;
-  regs.ebx = TCPA_MAGIC;
-  regs.ecx = 0;
-  regs.edx = 0;
-  regs.es = (inaddr & 0xffff0000) >> 4;
-  regs.edi = inaddr & 0xffff;
-  regs.ds = outaddr >> 4;
-  regs.esi = outaddr & 0xf;
-
-  grub_bios_interrupt (0x1a, &regs);
-
-  if (regs.eax)
-    {
-	tpm_presence = 0;
-	return grub_error (GRUB_ERR_IO, N_("TPM error %x, disabling TPM"), regs.eax);
-    }
-
-  return 0;
-}
-
-typedef struct {
-	grub_uint32_t pcrindex;
-	grub_uint32_t eventtype;
-	grub_uint8_t digest[20];
-	grub_uint32_t eventdatasize;
-	grub_uint8_t event[0];
-} GRUB_PACKED Event;
-
-typedef struct {
-	grub_uint16_t ipblength;
-	grub_uint16_t reserved;
-	grub_uint32_t hashdataptr;
-	grub_uint32_t hashdatalen;
-	grub_uint32_t pcr;
-	grub_uint32_t reserved2;
-	grub_uint32_t logdataptr;
-	grub_uint32_t logdatalen;
-} GRUB_PACKED EventIncoming;
-
-typedef struct {
-	grub_uint16_t opblength;
-	grub_uint16_t reserved;
-	grub_uint32_t eventnum;
-	grub_uint8_t  hashvalue[20];
-} GRUB_PACKED EventOutgoing;
-
-grub_err_t
-grub_tpm_log_event(unsigned char *buf, grub_size_t size, grub_uint8_t pcr,
-		   const char *description)
-{
-	struct grub_bios_int_registers regs;
-	EventIncoming incoming;
-	EventOutgoing outgoing;
-	Event *event;
-	grub_uint32_t datalength;
-
-	if (!tpm_present())
-		return 0;
-
-	datalength = grub_strlen(description);
-	event = grub_zalloc(datalength + sizeof(Event));
-	if (!event)
-		return grub_error (GRUB_ERR_OUT_OF_MEMORY,
-				   N_("cannot allocate TPM event buffer"));
-
-	event->pcrindex = pcr;
-	event->eventtype = 0x0d;
-	event->eventdatasize = grub_strlen(description);
-	grub_memcpy(event->event, description, datalength);
-
-	incoming.ipblength = sizeof(incoming);
-	incoming.hashdataptr = (grub_uint32_t)buf;
-	incoming.hashdatalen = size;
-	incoming.pcr = pcr;
-	incoming.logdataptr = (grub_uint32_t)event;
-	incoming.logdatalen = datalength + sizeof(Event);
-
-	regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT;
-	regs.eax = 0xbb01;
-	regs.ebx = TCPA_MAGIC;
-	regs.ecx = 0;
-	regs.edx = 0;
-	regs.es = (((grub_addr_t) &incoming) & 0xffff0000) >> 4;
-	regs.edi = ((grub_addr_t) &incoming) & 0xffff;
-	regs.ds = (((grub_addr_t) &outgoing) & 0xffff0000) >> 4;
-	regs.esi = ((grub_addr_t) &outgoing) & 0xffff;
-
-	grub_bios_interrupt (0x1a, &regs);
-
-	grub_free(event);
-
-	if (regs.eax)
-	  {
-		tpm_presence = 0;
-		return grub_error (GRUB_ERR_IO, N_("TPM error %x, disabling TPM"), regs.eax);
-	  }
-
-	return 0;
-}
diff --git a/grub-core/loader/i386/pc/linux.c b/grub-core/loader/i386/pc/linux.c
index cfff25c21..783a3cd93 100644
--- a/grub-core/loader/i386/pc/linux.c
+++ b/grub-core/loader/i386/pc/linux.c
@@ -36,7 +36,6 @@
 #include <grub/lib/cmdline.h>
 #include <grub/linux.h>
 #include <grub/efi/sb.h>
-#include <grub/tpm.h>
 
 GRUB_MOD_LICENSE ("GPLv3+");
 
@@ -162,9 +161,6 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
       goto fail;
     }
 
-  grub_tpm_measure (kernel, len, GRUB_BINARY_PCR, "grub_linux16", "Kernel");
-  grub_print_error();
-
   grub_memcpy (&lh, kernel, sizeof (lh));
   kernel_offset = sizeof (lh);
 
diff --git a/include/grub/tpm.h b/include/grub/tpm.h
index 972a5edc8..ce52be4ff 100644
--- a/include/grub/tpm.h
+++ b/include/grub/tpm.h
@@ -69,7 +69,7 @@ typedef struct {
 grub_err_t EXPORT_FUNC(grub_tpm_measure) (unsigned char *buf, grub_size_t size,
 					  grub_uint8_t pcr, const char *kind,
 					  const char *description);
-#if defined (GRUB_MACHINE_EFI) || defined (GRUB_MACHINE_PCBIOS)
+#if defined (GRUB_MACHINE_EFI)
 grub_err_t grub_tpm_execute(PassThroughToTPM_InputParamBlock *inbuf,
 			    PassThroughToTPM_OutputParamBlock *outbuf);
 grub_err_t grub_tpm_log_event(unsigned char *buf, grub_size_t size,
diff --git a/grub-core/boot/i386/pc/boot.S b/grub-core/boot/i386/pc/boot.S
index acab37369..ea167fe12 100644
--- a/grub-core/boot/i386/pc/boot.S
+++ b/grub-core/boot/i386/pc/boot.S
@@ -24,14 +24,11 @@
  *  defines for the code go here
  */
 
-#define TPM 1
-
 	/* Print message string */
 #define MSG(x)	movw $x, %si; call LOCAL(message)
 #define ERR(x)	movw $x, %si; jmp LOCAL(error_message)
 
 	.macro floppy
-#ifndef TPM
 part_start:
 
 LOCAL(probe_values):
@@ -88,7 +85,6 @@ fd_probe_error_string:	.asciz "Floppy"
 	movb	MACRO_DOLLAR(79), %ch
 
 	jmp	LOCAL(final_init)
-#endif
 	.endm
 
 	.macro scratch
@@ -256,7 +252,6 @@ real_start:
 	/* set %si to the disk address packet */
 	movw	$disk_address_packet, %si
 
-#ifndef TPM
 	/* check if LBA is supported */
 	movb	$0x41, %ah
 	movw	$0x55aa, %bx
@@ -276,7 +271,6 @@ real_start:
 
 	andw	$1, %cx
 	jz	LOCAL(chs_mode)
-#endif
 
 LOCAL(lba_mode):
 	xorw	%ax, %ax
@@ -320,9 +314,6 @@ LOCAL(lba_mode):
 	jmp	LOCAL(copy_buffer)
 
 LOCAL(chs_mode):
-#ifdef TPM
-	jmp	LOCAL(general_error)
-#else
 	/*
 	 *  Determine the hard disk geometry from the BIOS!
 	 *  We do this first, so that LS-120 IDE floppies work correctly.
@@ -434,7 +425,7 @@ setup_sectors:
 	jc	LOCAL(read_error)
 
 	movw	%es, %bx
-#endif /* TPM */
+
 LOCAL(copy_buffer):
 	/*
 	 * We need to save %cx and %si because the startup code in
@@ -457,25 +448,6 @@ LOCAL(copy_buffer):
 	popw	%ds
 	popa
 
-#ifdef TPM
-	pusha
-
-	movw	$0xBB00, %ax		/* TCG_StatusCheck */
-	int	$0x1A
-	test	%eax, %eax
-	jnz	boot			/* No TPM or TPM deactivated */
-
-	movw	$0xBB07, %ax		/* TCG_CompactHashLogExtendEvent */
-	movw	$GRUB_BOOT_MACHINE_KERNEL_ADDR, %di
-	xorl	%esi, %esi
-	movl	$0x41504354, %ebx	/* TCPA */
-	movl	$0x200, %ecx		/* Measure 512 bytes */
-	movl	$0x8, %edx		/* PCR 8 */
-	int	$0x1A
-
-boot:
-	popa
-#endif
 	/* boot kernel */
 	jmp	*(LOCAL(kernel_address))
 
diff --git a/grub-core/boot/i386/pc/diskboot.S b/grub-core/boot/i386/pc/diskboot.S
index f4744ec6f..68d31de0c 100644
--- a/grub-core/boot/i386/pc/diskboot.S
+++ b/grub-core/boot/i386/pc/diskboot.S
@@ -19,8 +19,6 @@
 #include <grub/symbol.h>
 #include <grub/machine/boot.h>
 
-#define TPM 1
-
 /*
  *  defines for the code go here
  */
@@ -55,21 +53,6 @@ _start:
 	/* this sets up for the first run through "bootloop" */
 	movw	$LOCAL(firstlist), %di
 
-#ifdef TPM
-        /* clear EAX to remove potential garbage */
-	xorl    %eax, %eax
-	/* 8(%di) = number of sectors to read */
-	movw    8(%di), %ax
-
-	/* Multiply number of sectors to read with 512 bytes. EAX is 32bit
-	* which is large enough to hold values of up to 4GB. I doubt there
-	* will ever be a core.img larger than that. ;-) */
-	shll    $9, %eax
-
-	/* write result to bytes_to_measure var */
-	movl    %eax, bytes_to_measure
-#endif
-
 	/* save the sector number of the second sector in %ebp */
 	movl	(%di), %ebp
 
@@ -307,29 +290,6 @@ LOCAL(copy_buffer):
 /* END OF MAIN LOOP */
 
 LOCAL(bootit):
-#ifdef TPM
-	pusha
-	movw	$0xBB07, %ax		/* TCG_CompactHashLogExtendEvent */
-
-	movw	$0x0, %bx
-	movw	%bx, %es
-
-	/* We've already measured the first 512 bytes, now measure the rest */
-	xorl	%edi, %edi
-	movw	$(GRUB_BOOT_MACHINE_KERNEL_ADDR + 0x200), %di
-
-	movl	$0x41504354, %ebx	/* EBX = "TCPA" */
-
-	/* %ecx = The length, in bytes, of the buffer to measure  */
-	movl	$bytes_to_measure, %esi
-	movl	(%esi), %ecx
-	xorl	%esi, %esi
-	movl	$0x9, %edx		/* PCR 9 */
-
-	int	$0x1A
-
-	popa
-#endif
 	/* print a newline */
 	MSG(notification_done)
 	popw	%dx	/* this makes sure %dl is our "boot" drive */
@@ -364,10 +324,6 @@ geometry_error_string:	.asciz "Geom"
 read_error_string:	.asciz "Read"
 general_error_string:	.asciz " Error"
 
-#ifdef TPM
-bytes_to_measure:	.long 0
-#endif
-
 /*
  * message: write the string pointed to by %si
  *
