From 8e26f638e099284b10973c0d72d8614eb2366bdfd2fecb27b84ce710e1b40bfb Mon Sep 17 00:00:00 2001 From: Michael Chang Date: Thu, 9 Mar 2017 06:19:36 +0000 Subject: [PATCH] Accepting request 477882 from home:michael-chang:devel:tpm - TPM Support (FATE#315831) * 0001-tpm-Core-TPM-support.patch * 0002-tpm-Measure-kernel-initrd.patch * 0003-tpm-Add-BIOS-boot-measurement.patch * 0004-tpm-Rework-linux-command.patch * 0005-tpm-Rework-linux16-command.patch * 0006-tpm-Measure-kernel-and-initrd-on-BIOS-systems.patch * 0007-tpm-Measure-the-kernel-commandline.patch * 0008-tpm-Measure-commands.patch * 0009-tpm-Measure-multiboot-images-and-modules.patch * 0010-tpm-Fix-boot-when-there-s-no-TPM.patch * 0011-tpm-Fix-build-error.patch * 0012-tpm-Build-tpm-as-module.patch - grub2.spec : Add grub-tpm.efi for Secure Boot OBS-URL: https://build.opensuse.org/request/show/477882 OBS-URL: https://build.opensuse.org/package/show/Base:System/grub2?expand=0&rev=263 --- 0001-tpm-Core-TPM-support.patch | 785 ++++++++++++++++++ 0002-tpm-Measure-kernel-initrd.patch | 39 + 0003-tpm-Add-BIOS-boot-measurement.patch | 179 ++++ 0004-tpm-Rework-linux-command.patch | 104 +++ 0005-tpm-Rework-linux16-command.patch | 101 +++ ...re-kernel-and-initrd-on-BIOS-systems.patch | 84 ++ 0007-tpm-Measure-the-kernel-commandline.patch | 43 + 0008-tpm-Measure-commands.patch | 60 ++ ...Measure-multiboot-images-and-modules.patch | 73 ++ 0010-tpm-Fix-boot-when-there-s-no-TPM.patch | 29 + 0011-tpm-Fix-build-error.patch | 74 ++ 0012-tpm-Build-tpm-as-module.patch | 505 +++++++++++ grub2.changes | 18 + grub2.spec | 32 +- 14 files changed, 2124 insertions(+), 2 deletions(-) create mode 100644 0001-tpm-Core-TPM-support.patch create mode 100644 0002-tpm-Measure-kernel-initrd.patch create mode 100644 0003-tpm-Add-BIOS-boot-measurement.patch create mode 100644 0004-tpm-Rework-linux-command.patch create mode 100644 0005-tpm-Rework-linux16-command.patch create mode 100644 0006-tpm-Measure-kernel-and-initrd-on-BIOS-systems.patch create mode 100644 0007-tpm-Measure-the-kernel-commandline.patch create mode 100644 0008-tpm-Measure-commands.patch create mode 100644 0009-tpm-Measure-multiboot-images-and-modules.patch create mode 100644 0010-tpm-Fix-boot-when-there-s-no-TPM.patch create mode 100644 0011-tpm-Fix-build-error.patch create mode 100644 0012-tpm-Build-tpm-as-module.patch diff --git a/0001-tpm-Core-TPM-support.patch b/0001-tpm-Core-TPM-support.patch new file mode 100644 index 0000000..103b6cf --- /dev/null +++ b/0001-tpm-Core-TPM-support.patch @@ -0,0 +1,785 @@ +From 866eb2103187d84f2e02c262cfdd1a388acfec15 Mon Sep 17 00:00:00 2001 +From: Matthew Garrett +Date: Tue, 14 Jul 2015 17:06:35 -0700 +Subject: [PATCH 01/11] Core TPM support + +Add support for performing basic TPM measurements. Right now this only +supports extending PCRs statically and only on UEFI and BIOS systems, but +will measure all modules as they're loaded. +--- + grub-core/Makefile.am | 1 + + grub-core/Makefile.core.def | 3 + + grub-core/kern/dl.c | 3 + + grub-core/kern/efi/tpm.c | 282 +++++++++++++++++++++++++++++++++++++++++++ + grub-core/kern/i386/pc/tpm.c | 132 ++++++++++++++++++++ + grub-core/kern/tpm.c | 19 +++ + include/grub/efi/tpm.h | 153 +++++++++++++++++++++++ + include/grub/tpm.h | 89 ++++++++++++++ + 8 files changed, 682 insertions(+) + create mode 100644 grub-core/kern/efi/tpm.c + create mode 100644 grub-core/kern/i386/pc/tpm.c + create mode 100644 grub-core/kern/tpm.c + create mode 100644 include/grub/efi/tpm.h + create mode 100644 include/grub/tpm.h + +Index: grub-2.02~beta3/grub-core/Makefile.am +=================================================================== +--- grub-2.02~beta3.orig/grub-core/Makefile.am ++++ grub-2.02~beta3/grub-core/Makefile.am +@@ -92,6 +92,7 @@ KERNEL_HEADER_FILES += $(top_srcdir)/inc + KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/time.h + KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/mm_private.h + KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/net.h ++KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/tpm.h + KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/memory.h + + if COND_i386_pc +Index: grub-2.02~beta3/grub-core/Makefile.core.def +=================================================================== +--- grub-2.02~beta3.orig/grub-core/Makefile.core.def ++++ grub-2.02~beta3/grub-core/Makefile.core.def +@@ -126,6 +126,7 @@ kernel = { + common = kern/rescue_parser.c; + common = kern/rescue_reader.c; + common = kern/term.c; ++ common = kern/tpm.c; + + noemu = kern/compiler-rt.c; + noemu = kern/mm.c; +@@ -173,6 +174,7 @@ kernel = { + efi = term/efi/console.c; + efi = kern/acpi.c; + efi = kern/efi/acpi.c; ++ efi = kern/efi/tpm.c; + i386_coreboot = kern/i386/pc/acpi.c; + i386_multiboot = kern/i386/pc/acpi.c; + i386_coreboot = kern/acpi.c; +@@ -217,6 +219,7 @@ 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; +Index: grub-2.02~beta3/grub-core/kern/dl.c +=================================================================== +--- grub-2.02~beta3.orig/grub-core/kern/dl.c ++++ grub-2.02~beta3/grub-core/kern/dl.c +@@ -32,6 +32,7 @@ + #include + #include + #include ++#include + + /* Platforms where modules are in a readonly area of memory. */ + #if defined(GRUB_MACHINE_QEMU) +@@ -729,6 +730,8 @@ grub_dl_load_file (const char *filename) + opens of the same device. */ + grub_file_close (file); + ++ grub_tpm_measure(core, size, GRUB_BINARY_PCR, "grub_module", filename); ++ + mod = grub_dl_load_core (core, size); + grub_free (core); + if (! mod) +Index: grub-2.02~beta3/grub-core/kern/efi/tpm.c +=================================================================== +--- /dev/null ++++ grub-2.02~beta3/grub-core/kern/efi/tpm.c +@@ -0,0 +1,282 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static grub_efi_guid_t tpm_guid = EFI_TPM_GUID; ++static grub_efi_guid_t tpm2_guid = EFI_TPM2_GUID; ++ ++static grub_efi_boolean_t grub_tpm_present(grub_efi_tpm_protocol_t *tpm) ++{ ++ grub_efi_status_t status; ++ TCG_EFI_BOOT_SERVICE_CAPABILITY caps; ++ grub_uint32_t flags; ++ grub_efi_physical_address_t eventlog, lastevent; ++ ++ caps.Size = (grub_uint8_t)sizeof(caps); ++ ++ status = efi_call_5(tpm->status_check, tpm, &caps, &flags, &eventlog, ++ &lastevent); ++ ++ if (status != GRUB_EFI_SUCCESS || caps.TPMDeactivatedFlag ++ || !caps.TPMPresentFlag) ++ return 0; ++ ++ return 1; ++} ++ ++static grub_efi_boolean_t grub_tpm2_present(grub_efi_tpm2_protocol_t *tpm) ++{ ++ grub_efi_status_t status; ++ EFI_TCG2_BOOT_SERVICE_CAPABILITY caps; ++ ++ caps.Size = (grub_uint8_t)sizeof(caps); ++ ++ status = efi_call_2(tpm->get_capability, tpm, &caps); ++ ++ if (status != GRUB_EFI_SUCCESS || !caps.TPMPresentFlag) ++ return 0; ++ ++ return 1; ++} ++ ++static grub_efi_boolean_t grub_tpm_handle_find(grub_efi_handle_t *tpm_handle, ++ grub_efi_uint8_t *protocol_version) ++{ ++ grub_efi_handle_t *handles; ++ grub_efi_uintn_t num_handles; ++ ++ handles = grub_efi_locate_handle (GRUB_EFI_BY_PROTOCOL, &tpm_guid, NULL, ++ &num_handles); ++ if (handles && num_handles > 0) { ++ *tpm_handle = handles[0]; ++ *protocol_version = 1; ++ return 1; ++ } ++ ++ handles = grub_efi_locate_handle (GRUB_EFI_BY_PROTOCOL, &tpm2_guid, NULL, ++ &num_handles); ++ if (handles && num_handles > 0) { ++ *tpm_handle = handles[0]; ++ *protocol_version = 2; ++ return 1; ++ } ++ ++ return 0; ++} ++ ++static grub_err_t ++grub_tpm1_execute(grub_efi_handle_t tpm_handle, ++ PassThroughToTPM_InputParamBlock *inbuf, ++ PassThroughToTPM_OutputParamBlock *outbuf) ++{ ++ grub_efi_status_t status; ++ grub_efi_tpm_protocol_t *tpm; ++ grub_uint32_t inhdrsize = sizeof(*inbuf) - sizeof(inbuf->TPMOperandIn); ++ grub_uint32_t outhdrsize = sizeof(*outbuf) - sizeof(outbuf->TPMOperandOut); ++ ++ tpm = grub_efi_open_protocol (tpm_handle, &tpm_guid, ++ GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL); ++ ++ if (!grub_tpm_present(tpm)) ++ return 0; ++ ++ /* UEFI TPM protocol takes the raw operand block, no param block header */ ++ status = efi_call_5 (tpm->pass_through_to_tpm, tpm, ++ inbuf->IPBLength - inhdrsize, inbuf->TPMOperandIn, ++ outbuf->OPBLength - outhdrsize, outbuf->TPMOperandOut); ++ ++ switch (status) { ++ case GRUB_EFI_SUCCESS: ++ return 0; ++ case GRUB_EFI_DEVICE_ERROR: ++ return grub_error (GRUB_ERR_IO, N_("Command failed")); ++ case GRUB_EFI_INVALID_PARAMETER: ++ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("Invalid parameter")); ++ case GRUB_EFI_BUFFER_TOO_SMALL: ++ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("Output buffer too small")); ++ case GRUB_EFI_NOT_FOUND: ++ return grub_error (GRUB_ERR_UNKNOWN_DEVICE, N_("TPM unavailable")); ++ default: ++ return grub_error (GRUB_ERR_UNKNOWN_DEVICE, N_("Unknown TPM error")); ++ } ++} ++ ++static grub_err_t ++grub_tpm2_execute(grub_efi_handle_t tpm_handle, ++ PassThroughToTPM_InputParamBlock *inbuf, ++ PassThroughToTPM_OutputParamBlock *outbuf) ++{ ++ grub_efi_status_t status; ++ grub_efi_tpm2_protocol_t *tpm; ++ grub_uint32_t inhdrsize = sizeof(*inbuf) - sizeof(inbuf->TPMOperandIn); ++ grub_uint32_t outhdrsize = sizeof(*outbuf) - sizeof(outbuf->TPMOperandOut); ++ ++ tpm = grub_efi_open_protocol (tpm_handle, &tpm2_guid, ++ GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL); ++ ++ if (!grub_tpm2_present(tpm)) ++ return 0; ++ ++ /* UEFI TPM protocol takes the raw operand block, no param block header */ ++ status = efi_call_5 (tpm->submit_command, tpm, ++ inbuf->IPBLength - inhdrsize, inbuf->TPMOperandIn, ++ outbuf->OPBLength - outhdrsize, outbuf->TPMOperandOut); ++ ++ switch (status) { ++ case GRUB_EFI_SUCCESS: ++ return 0; ++ case GRUB_EFI_DEVICE_ERROR: ++ return grub_error (GRUB_ERR_IO, N_("Command failed")); ++ case GRUB_EFI_INVALID_PARAMETER: ++ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("Invalid parameter")); ++ case GRUB_EFI_BUFFER_TOO_SMALL: ++ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("Output buffer too small")); ++ case GRUB_EFI_NOT_FOUND: ++ return grub_error (GRUB_ERR_UNKNOWN_DEVICE, N_("TPM unavailable")); ++ default: ++ return grub_error (GRUB_ERR_UNKNOWN_DEVICE, N_("Unknown TPM error")); ++ } ++} ++ ++grub_err_t ++grub_tpm_execute(PassThroughToTPM_InputParamBlock *inbuf, ++ PassThroughToTPM_OutputParamBlock *outbuf) ++{ ++ grub_efi_handle_t tpm_handle; ++ grub_uint8_t protocol_version; ++ ++ /* It's not a hard failure for there to be no TPM */ ++ if (!grub_tpm_handle_find(&tpm_handle, &protocol_version)) ++ return 0; ++ ++ if (protocol_version == 1) { ++ return grub_tpm1_execute(tpm_handle, inbuf, outbuf); ++ } else { ++ return grub_tpm2_execute(tpm_handle, inbuf, outbuf); ++ } ++} ++ ++typedef struct { ++ grub_uint32_t pcrindex; ++ grub_uint32_t eventtype; ++ grub_uint8_t digest[20]; ++ grub_uint32_t eventsize; ++ grub_uint8_t event[1]; ++} Event; ++ ++ ++static grub_err_t ++grub_tpm1_log_event(grub_efi_handle_t tpm_handle, unsigned char *buf, ++ grub_size_t size, grub_uint8_t pcr, ++ const char *description) ++{ ++ Event *event; ++ grub_efi_status_t status; ++ grub_efi_tpm_protocol_t *tpm; ++ grub_efi_physical_address_t lastevent; ++ grub_uint32_t algorithm; ++ grub_uint32_t eventnum = 0; ++ ++ tpm = grub_efi_open_protocol (tpm_handle, &tpm_guid, ++ GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL); ++ ++ if (!grub_tpm_present(tpm)) ++ return 0; ++ ++ event = grub_zalloc(sizeof (Event) + grub_strlen(description) + 1); ++ if (!event) ++ return grub_error (GRUB_ERR_OUT_OF_MEMORY, ++ N_("cannot allocate TPM event buffer")); ++ ++ event->pcrindex = pcr; ++ event->eventtype = EV_IPL; ++ event->eventsize = grub_strlen(description) + 1; ++ grub_memcpy(event->event, description, event->eventsize); ++ ++ algorithm = TCG_ALG_SHA; ++ status = efi_call_7 (tpm->log_extend_event, tpm, buf, (grub_uint64_t) size, ++ algorithm, event, &eventnum, &lastevent); ++ ++ switch (status) { ++ case GRUB_EFI_SUCCESS: ++ return 0; ++ case GRUB_EFI_DEVICE_ERROR: ++ return grub_error (GRUB_ERR_IO, N_("Command failed")); ++ case GRUB_EFI_INVALID_PARAMETER: ++ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("Invalid parameter")); ++ case GRUB_EFI_BUFFER_TOO_SMALL: ++ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("Output buffer too small")); ++ case GRUB_EFI_NOT_FOUND: ++ return grub_error (GRUB_ERR_UNKNOWN_DEVICE, N_("TPM unavailable")); ++ default: ++ return grub_error (GRUB_ERR_UNKNOWN_DEVICE, N_("Unknown TPM error")); ++ } ++} ++ ++static grub_err_t ++grub_tpm2_log_event(grub_efi_handle_t tpm_handle, unsigned char *buf, ++ grub_size_t size, grub_uint8_t pcr, ++ const char *description) ++{ ++ EFI_TCG2_EVENT *event; ++ grub_efi_status_t status; ++ grub_efi_tpm2_protocol_t *tpm; ++ ++ tpm = grub_efi_open_protocol (tpm_handle, &tpm2_guid, ++ GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL); ++ ++ if (!grub_tpm2_present(tpm)) ++ return 0; ++ ++ event = grub_zalloc(sizeof (EFI_TCG2_EVENT) + grub_strlen(description) + 1); ++ if (!event) ++ return grub_error (GRUB_ERR_OUT_OF_MEMORY, ++ N_("cannot allocate TPM event buffer")); ++ ++ event->Header.HeaderSize = sizeof(EFI_TCG2_EVENT_HEADER); ++ event->Header.HeaderVersion = 1; ++ event->Header.PCRIndex = pcr; ++ event->Header.EventType = EV_IPL; ++ event->Size = sizeof(*event) - sizeof(event->Event) + grub_strlen(description) + 1; ++ grub_memcpy(event->Event, description, grub_strlen(description) + 1); ++ ++ status = efi_call_5 (tpm->hash_log_extend_event, tpm, 0, buf, ++ (grub_uint64_t) size, event); ++ ++ switch (status) { ++ case GRUB_EFI_SUCCESS: ++ return 0; ++ case GRUB_EFI_DEVICE_ERROR: ++ return grub_error (GRUB_ERR_IO, N_("Command failed")); ++ case GRUB_EFI_INVALID_PARAMETER: ++ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("Invalid parameter")); ++ case GRUB_EFI_BUFFER_TOO_SMALL: ++ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("Output buffer too small")); ++ case GRUB_EFI_NOT_FOUND: ++ return grub_error (GRUB_ERR_UNKNOWN_DEVICE, N_("TPM unavailable")); ++ default: ++ return grub_error (GRUB_ERR_UNKNOWN_DEVICE, N_("Unknown TPM error")); ++ } ++} ++ ++grub_err_t ++grub_tpm_log_event(unsigned char *buf, grub_size_t size, grub_uint8_t pcr, ++ const char *description) ++{ ++ grub_efi_handle_t tpm_handle; ++ grub_efi_uint8_t protocol_version; ++ ++ if (!grub_tpm_handle_find(&tpm_handle, &protocol_version)) ++ return 0; ++ ++ if (protocol_version == 1) { ++ return grub_tpm1_log_event(tpm_handle, buf, size, pcr, description); ++ } else { ++ return grub_tpm2_log_event(tpm_handle, buf, size, pcr, description); ++ } ++} +Index: grub-2.02~beta3/grub-core/kern/i386/pc/tpm.c +=================================================================== +--- /dev/null ++++ grub-2.02~beta3/grub-core/kern/i386/pc/tpm.c +@@ -0,0 +1,132 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define TCPA_MAGIC 0x41504354 ++ ++int tpm_present(void); ++ ++int tpm_present(void) ++{ ++ struct grub_bios_int_registers regs; ++ ++ regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT; ++ regs.eax = 0xbb00; ++ regs.ebx = TCPA_MAGIC; ++ grub_bios_interrupt (0x1a, ®s); ++ ++ if (regs.eax == 0) ++ return 1; ++ ++ return 0; ++} ++ ++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, ®s); ++ ++ if (regs.eax) ++ return grub_error (GRUB_ERR_IO, N_("TPM error %x\n"), 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, ®s); ++ ++ grub_free(event); ++ ++ if (regs.eax) ++ return grub_error (GRUB_ERR_IO, N_("TPM error %x\n"), regs.eax); ++ ++ return 0; ++} +Index: grub-2.02~beta3/grub-core/kern/tpm.c +=================================================================== +--- /dev/null ++++ grub-2.02~beta3/grub-core/kern/tpm.c +@@ -0,0 +1,19 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++grub_err_t ++grub_tpm_measure (unsigned char *buf, grub_size_t size, grub_uint8_t pcr, ++ const char *kind, const char *description) ++{ ++ grub_err_t ret; ++ char *desc = grub_xasprintf("%s %s", kind, description); ++ if (!desc) ++ return GRUB_ERR_OUT_OF_MEMORY; ++ ret = grub_tpm_log_event(buf, size, pcr, description); ++ grub_free(desc); ++ return ret; ++} +Index: grub-2.02~beta3/include/grub/efi/tpm.h +=================================================================== +--- /dev/null ++++ grub-2.02~beta3/include/grub/efi/tpm.h +@@ -0,0 +1,153 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2015 Free Software Foundation, Inc. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#ifndef GRUB_EFI_TPM_HEADER ++#define GRUB_EFI_TPM_HEADER 1 ++ ++#define EFI_TPM_GUID {0xf541796d, 0xa62e, 0x4954, {0xa7, 0x75, 0x95, 0x84, 0xf6, 0x1b, 0x9c, 0xdd }}; ++#define EFI_TPM2_GUID {0x607f766c, 0x7455, 0x42be, {0x93, 0x0b, 0xe4, 0xd7, 0x6d, 0xb2, 0x72, 0x0f }}; ++ ++typedef struct { ++ grub_efi_uint8_t Major; ++ grub_efi_uint8_t Minor; ++ grub_efi_uint8_t RevMajor; ++ grub_efi_uint8_t RevMinor; ++} TCG_VERSION; ++ ++typedef struct _TCG_EFI_BOOT_SERVICE_CAPABILITY { ++ grub_efi_uint8_t Size; /// Size of this structure. ++ TCG_VERSION StructureVersion; ++ TCG_VERSION ProtocolSpecVersion; ++ grub_efi_uint8_t HashAlgorithmBitmap; /// Hash algorithms . ++ char TPMPresentFlag; /// 00h = TPM not present. ++ char TPMDeactivatedFlag; /// 01h = TPM currently deactivated. ++} TCG_EFI_BOOT_SERVICE_CAPABILITY; ++ ++typedef struct { ++ grub_efi_uint32_t PCRIndex; ++ grub_efi_uint32_t EventType; ++ grub_efi_uint8_t digest[20]; ++ grub_efi_uint32_t EventSize; ++ grub_efi_uint8_t Event[1]; ++} TCG_PCR_EVENT; ++ ++struct grub_efi_tpm_protocol ++{ ++ grub_efi_status_t (*status_check) (struct grub_efi_tpm_protocol *this, ++ TCG_EFI_BOOT_SERVICE_CAPABILITY *ProtocolCapability, ++ grub_efi_uint32_t *TCGFeatureFlags, ++ grub_efi_physical_address_t *EventLogLocation, ++ grub_efi_physical_address_t *EventLogLastEntry); ++ grub_efi_status_t (*hash_all) (struct grub_efi_tpm_protocol *this, ++ grub_efi_uint8_t *HashData, ++ grub_efi_uint64_t HashLen, ++ grub_efi_uint32_t AlgorithmId, ++ grub_efi_uint64_t *HashedDataLen, ++ grub_efi_uint8_t **HashedDataResult); ++ grub_efi_status_t (*log_event) (struct grub_efi_tpm_protocol *this, ++ TCG_PCR_EVENT *TCGLogData, ++ grub_efi_uint32_t *EventNumber, ++ grub_efi_uint32_t Flags); ++ grub_efi_status_t (*pass_through_to_tpm) (struct grub_efi_tpm_protocol *this, ++ grub_efi_uint32_t TpmInputParameterBlockSize, ++ grub_efi_uint8_t *TpmInputParameterBlock, ++ grub_efi_uint32_t TpmOutputParameterBlockSize, ++ grub_efi_uint8_t *TpmOutputParameterBlock); ++ grub_efi_status_t (*log_extend_event) (struct grub_efi_tpm_protocol *this, ++ grub_efi_physical_address_t HashData, ++ grub_efi_uint64_t HashDataLen, ++ grub_efi_uint32_t AlgorithmId, ++ TCG_PCR_EVENT *TCGLogData, ++ grub_efi_uint32_t *EventNumber, ++ grub_efi_physical_address_t *EventLogLastEntry); ++}; ++ ++typedef struct grub_efi_tpm_protocol grub_efi_tpm_protocol_t; ++ ++typedef grub_efi_uint32_t EFI_TCG2_EVENT_LOG_BITMAP; ++typedef grub_efi_uint32_t EFI_TCG2_EVENT_LOG_FORMAT; ++typedef grub_efi_uint32_t EFI_TCG2_EVENT_ALGORITHM_BITMAP; ++ ++typedef struct tdEFI_TCG2_VERSION { ++ grub_efi_uint8_t Major; ++ grub_efi_uint8_t Minor; ++} GRUB_PACKED EFI_TCG2_VERSION; ++ ++typedef struct tdEFI_TCG2_BOOT_SERVICE_CAPABILITY { ++ grub_efi_uint8_t Size; ++ EFI_TCG2_VERSION StructureVersion; ++ EFI_TCG2_VERSION ProtocolVersion; ++ EFI_TCG2_EVENT_ALGORITHM_BITMAP HashAlgorithmBitmap; ++ EFI_TCG2_EVENT_LOG_BITMAP SupportedEventLogs; ++ grub_efi_boolean_t TPMPresentFlag; ++ grub_efi_uint16_t MaxCommandSize; ++ grub_efi_uint16_t MaxResponseSize; ++ grub_efi_uint32_t ManufacturerID; ++ grub_efi_uint32_t NumberOfPcrBanks; ++ EFI_TCG2_EVENT_ALGORITHM_BITMAP ActivePcrBanks; ++} EFI_TCG2_BOOT_SERVICE_CAPABILITY; ++ ++typedef grub_efi_uint32_t TCG_PCRINDEX; ++typedef grub_efi_uint32_t TCG_EVENTTYPE; ++ ++typedef struct tdEFI_TCG2_EVENT_HEADER { ++ grub_efi_uint32_t HeaderSize; ++ grub_efi_uint16_t HeaderVersion; ++ TCG_PCRINDEX PCRIndex; ++ TCG_EVENTTYPE EventType; ++} GRUB_PACKED EFI_TCG2_EVENT_HEADER; ++ ++typedef struct tdEFI_TCG2_EVENT { ++ grub_efi_uint32_t Size; ++ EFI_TCG2_EVENT_HEADER Header; ++ grub_efi_uint8_t Event[1]; ++} GRUB_PACKED EFI_TCG2_EVENT; ++ ++struct grub_efi_tpm2_protocol ++{ ++ grub_efi_status_t (*get_capability) (struct grub_efi_tpm2_protocol *this, ++ EFI_TCG2_BOOT_SERVICE_CAPABILITY *ProtocolCapability); ++ grub_efi_status_t (*get_event_log) (struct grub_efi_tpm2_protocol *this, ++ EFI_TCG2_EVENT_LOG_FORMAT EventLogFormat, ++ grub_efi_physical_address_t *EventLogLocation, ++ grub_efi_physical_address_t *EventLogLastEntry, ++ grub_efi_boolean_t *EventLogTruncated); ++ grub_efi_status_t (*hash_log_extend_event) (struct grub_efi_tpm2_protocol *this, ++ grub_efi_uint64_t Flags, ++ grub_efi_physical_address_t *DataToHash, ++ grub_efi_uint64_t DataToHashLen, ++ EFI_TCG2_EVENT *EfiTcgEvent); ++ grub_efi_status_t (*submit_command) (struct grub_efi_tpm2_protocol *this, ++ grub_efi_uint32_t InputParameterBlockSize, ++ grub_efi_uint8_t *InputParameterBlock, ++ grub_efi_uint32_t OutputParameterBlockSize, ++ grub_efi_uint8_t *OutputParameterBlock); ++ grub_efi_status_t (*get_active_pcr_blanks) (struct grub_efi_tpm2_protocol *this, ++ grub_efi_uint32_t *ActivePcrBanks); ++ grub_efi_status_t (*set_active_pcr_banks) (struct grub_efi_tpm2_protocol *this, ++ grub_efi_uint32_t ActivePcrBanks); ++ grub_efi_status_t (*get_result_of_set_active_pcr_banks) (struct grub_efi_tpm2_protocol *this, ++ grub_efi_uint32_t *OperationPresent, ++ grub_efi_uint32_t *Response); ++}; ++ ++typedef struct grub_efi_tpm2_protocol grub_efi_tpm2_protocol_t; ++ ++#define TCG_ALG_SHA 0x00000004 ++ ++#endif +Index: grub-2.02~beta3/include/grub/tpm.h +=================================================================== +--- /dev/null ++++ grub-2.02~beta3/include/grub/tpm.h +@@ -0,0 +1,89 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2015 Free Software Foundation, Inc. ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#ifndef GRUB_TPM_HEADER ++#define GRUB_TPM_HEADER 1 ++ ++#define SHA1_DIGEST_SIZE 20 ++ ++#define TPM_BASE 0x0 ++#define TPM_SUCCESS TPM_BASE ++#define TPM_AUTHFAIL (TPM_BASE + 0x1) ++#define TPM_BADINDEX (TPM_BASE + 0x2) ++ ++#define GRUB_ASCII_PCR 8 ++#define GRUB_BINARY_PCR 9 ++ ++#define TPM_TAG_RQU_COMMAND 0x00C1 ++#define TPM_ORD_Extend 0x14 ++ ++#define EV_IPL 0x0d ++ ++/* TCG_PassThroughToTPM Input Parameter Block */ ++typedef struct { ++ grub_uint16_t IPBLength; ++ grub_uint16_t Reserved1; ++ grub_uint16_t OPBLength; ++ grub_uint16_t Reserved2; ++ grub_uint8_t TPMOperandIn[1]; ++} GRUB_PACKED PassThroughToTPM_InputParamBlock; ++ ++/* TCG_PassThroughToTPM Output Parameter Block */ ++typedef struct { ++ grub_uint16_t OPBLength; ++ grub_uint16_t Reserved; ++ grub_uint8_t TPMOperandOut[1]; ++} GRUB_PACKED PassThroughToTPM_OutputParamBlock; ++ ++typedef struct { ++ grub_uint16_t tag; ++ grub_uint32_t paramSize; ++ grub_uint32_t ordinal; ++ grub_uint32_t pcrNum; ++ grub_uint8_t inDigest[SHA1_DIGEST_SIZE]; /* The 160 bit value representing the event to be recorded. */ ++} GRUB_PACKED ExtendIncoming; ++ ++/* TPM_Extend Outgoing Operand */ ++typedef struct { ++ grub_uint16_t tag; ++ grub_uint32_t paramSize; ++ grub_uint32_t returnCode; ++ grub_uint8_t outDigest[SHA1_DIGEST_SIZE]; /* The PCR value after execution of the command. */ ++} GRUB_PACKED ExtendOutgoing; ++ ++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) ++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, ++ grub_uint8_t pcr, const char *description); ++#else ++static inline grub_err_t grub_tpm_execute(PassThroughToTPM_InputParamBlock *inbuf, ++ PassThroughToTPM_OutputParamBlock *outbuf) { return 0; }; ++static inline grub_err_t grub_tpm_log_event(unsigned char *buf, ++ grub_size_t size, ++ grub_uint8_t pcr, ++ const char *description) ++{ ++ return 0; ++}; ++#endif ++ ++#endif diff --git a/0002-tpm-Measure-kernel-initrd.patch b/0002-tpm-Measure-kernel-initrd.patch new file mode 100644 index 0000000..c865b07 --- /dev/null +++ b/0002-tpm-Measure-kernel-initrd.patch @@ -0,0 +1,39 @@ +From b3afe6ad07192d3f38875e30b57a785ac3b1ea27 Mon Sep 17 00:00:00 2001 +From: Matthew Garrett +Date: Thu, 16 Jul 2015 15:22:34 -0700 +Subject: [PATCH 02/11] Measure kernel + initrd + +Measure the kernel and initrd when loaded on UEFI systems +--- + grub-core/loader/i386/efi/linux.c | 4 ++++ + 1 file changed, 4 insertions(+) + +Index: grub-2.02~beta3/grub-core/loader/i386/efi/linux.c +=================================================================== +--- grub-2.02~beta3.orig/grub-core/loader/i386/efi/linux.c ++++ grub-2.02~beta3/grub-core/loader/i386/efi/linux.c +@@ -26,6 +26,7 @@ + #include + #include + #include ++#include + + GRUB_MOD_LICENSE ("GPLv3+"); + +@@ -162,6 +163,7 @@ grub_cmd_initrd (grub_command_t cmd __at + argv[i]); + goto fail; + } ++ grub_tpm_measure (ptr, cursize, GRUB_BINARY_PCR, "grub_linuxefi", "Initrd"); + ptr += cursize; + grub_memset (ptr, 0, ALIGN_UP_OVERHEAD (cursize, 4)); + ptr += ALIGN_UP_OVERHEAD (cursize, 4); +@@ -217,6 +219,8 @@ grub_cmd_linux (grub_command_t cmd __att + goto fail; + } + ++ grub_tpm_measure (kernel, filelen, GRUB_BINARY_PCR, "grub_linuxefi", "Kernel"); ++ + if (! grub_linuxefi_secure_validate (kernel, filelen)) + { + grub_error (GRUB_ERR_INVALID_COMMAND, N_("%s has invalid signature"), argv[0]); diff --git a/0003-tpm-Add-BIOS-boot-measurement.patch b/0003-tpm-Add-BIOS-boot-measurement.patch new file mode 100644 index 0000000..21ce113 --- /dev/null +++ b/0003-tpm-Add-BIOS-boot-measurement.patch @@ -0,0 +1,179 @@ +From e12373683b894f22c2e35dc3732440a4e9053d61 Mon Sep 17 00:00:00 2001 +From: Matthew Garrett +Date: Sun, 9 Aug 2015 15:48:51 -0700 +Subject: [PATCH 03/11] Add BIOS boot measurement + +Measure the on-disk grub core on BIOS systems - unlike UEFI, the firmware +can't do this stage for us. +--- + grub-core/boot/i386/pc/boot.S | 30 +++++++++++++++++++++++++- + grub-core/boot/i386/pc/diskboot.S | 44 +++++++++++++++++++++++++++++++++++++++ + 2 files changed, 73 insertions(+), 1 deletion(-) + +diff --git a/grub-core/boot/i386/pc/boot.S b/grub-core/boot/i386/pc/boot.S +index 2bd0b2d..4c63247 100644 +--- a/grub-core/boot/i386/pc/boot.S ++++ b/grub-core/boot/i386/pc/boot.S +@@ -24,11 +24,14 @@ + * 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): +@@ -85,6 +88,7 @@ fd_probe_error_string: .asciz "Floppy" + movb MACRO_DOLLAR(79), %ch + + jmp LOCAL(final_init) ++#endif + .endm + + .macro scratch +@@ -255,6 +259,7 @@ 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 +@@ -274,6 +279,7 @@ real_start: + + andw $1, %cx + jz LOCAL(chs_mode) ++#endif + + LOCAL(lba_mode): + xorw %ax, %ax +@@ -317,6 +323,9 @@ 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. +@@ -428,7 +437,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 +@@ -451,6 +460,25 @@ 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 ++ ++ popa ++#endif ++boot: + /* 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 1ee4cf5..3a324ea 100644 +--- a/grub-core/boot/i386/pc/diskboot.S ++++ b/grub-core/boot/i386/pc/diskboot.S +@@ -19,6 +19,8 @@ + #include + #include + ++#define TPM 1 ++ + /* + * defines for the code go here + */ +@@ -58,6 +60,21 @@ _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 + +@@ -295,6 +312,29 @@ 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 */ +@@ -329,6 +369,10 @@ 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 + * +-- +1.8.5.6 + diff --git a/0004-tpm-Rework-linux-command.patch b/0004-tpm-Rework-linux-command.patch new file mode 100644 index 0000000..d92c325 --- /dev/null +++ b/0004-tpm-Rework-linux-command.patch @@ -0,0 +1,104 @@ +From 9f12cf163e56d3b5f03c8a5da94dc501032312eb Mon Sep 17 00:00:00 2001 +From: Matthew Garrett +Date: Sun, 9 Aug 2015 16:12:39 -0700 +Subject: [PATCH 04/11] Rework linux command + +We want a single buffer that contains the entire kernel image in order to +perform a TPM measurement. Allocate one and copy the entire kernel into it +before pulling out the individual blocks later on. +--- + grub-core/loader/i386/linux.c | 34 +++++++++++++++++++++------------- + 1 file changed, 21 insertions(+), 13 deletions(-) + +Index: grub-2.02~beta3/grub-core/loader/i386/linux.c +=================================================================== +--- grub-2.02~beta3.orig/grub-core/loader/i386/linux.c ++++ grub-2.02~beta3/grub-core/loader/i386/linux.c +@@ -680,12 +680,13 @@ grub_cmd_linux (grub_command_t cmd __att + grub_file_t file = 0; + struct linux_kernel_header lh; + grub_uint8_t setup_sects; +- grub_size_t real_size, prot_size, prot_file_size; ++ grub_size_t real_size, prot_size, prot_file_size, kernel_offset; + grub_ssize_t len; + int i; + grub_size_t align, min_align; + int relocatable; + grub_uint64_t preferred_address = GRUB_LINUX_BZIMAGE_ADDR; ++ grub_uint8_t *kernel = NULL; + + grub_dl_ref (my_mod); + +@@ -699,7 +700,15 @@ grub_cmd_linux (grub_command_t cmd __att + if (! file) + goto fail; + +- if (grub_file_read (file, &lh, sizeof (lh)) != sizeof (lh)) ++ len = grub_file_size (file); ++ kernel = grub_malloc (len); ++ if (!kernel) ++ { ++ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("cannot allocate kernel buffer")); ++ goto fail; ++ } ++ ++ if (grub_file_read (file, kernel, len) != len) + { + if (!grub_errno) + grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), +@@ -707,6 +716,9 @@ grub_cmd_linux (grub_command_t cmd __att + goto fail; + } + ++ grub_memcpy (&lh, kernel, sizeof (lh)); ++ kernel_offset = sizeof (lh); ++ + if (lh.boot_flag != grub_cpu_to_le16_compile_time (0xaa55)) + { + grub_error (GRUB_ERR_BAD_OS, "invalid magic number"); +@@ -806,13 +818,9 @@ grub_cmd_linux (grub_command_t cmd __att + linux_params.ps_mouse = linux_params.padding10 = 0; + + len = sizeof (linux_params) - sizeof (lh); +- if (grub_file_read (file, (char *) &linux_params + sizeof (lh), len) != len) +- { +- if (!grub_errno) +- grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), +- argv[0]); +- goto fail; +- } ++ ++ grub_memcpy (&linux_params + sizeof (lh), kernel + kernel_offset, len); ++ kernel_offset += len; + + linux_params.type_of_loader = GRUB_LINUX_BOOT_LOADER_TYPE; + +@@ -871,7 +879,7 @@ grub_cmd_linux (grub_command_t cmd __att + + /* The other parameters are filled when booting. */ + +- grub_file_seek (file, real_size + GRUB_DISK_SECTOR_SIZE); ++ kernel_offset = real_size + GRUB_DISK_SECTOR_SIZE; + + grub_dprintf ("linux", "bzImage, setup=0x%x, size=0x%x\n", + (unsigned) real_size, (unsigned) prot_size); +@@ -1016,9 +1024,7 @@ grub_cmd_linux (grub_command_t cmd __att + - (sizeof (LINUX_IMAGE) - 1)); + + len = prot_file_size; +- if (grub_file_read (file, prot_mode_mem, len) != len && !grub_errno) +- grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), +- argv[0]); ++ grub_memcpy (prot_mode_mem, kernel + kernel_offset, len); + + if (grub_errno == GRUB_ERR_NONE) + { +@@ -1029,6 +1035,8 @@ grub_cmd_linux (grub_command_t cmd __att + + fail: + ++ grub_free (kernel); ++ + if (file) + grub_file_close (file); + diff --git a/0005-tpm-Rework-linux16-command.patch b/0005-tpm-Rework-linux16-command.patch new file mode 100644 index 0000000..d97a195 --- /dev/null +++ b/0005-tpm-Rework-linux16-command.patch @@ -0,0 +1,101 @@ +From f8f66cdcb66dba05353887b3be0d715d54efdea8 Mon Sep 17 00:00:00 2001 +From: Matthew Garrett +Date: Sun, 9 Aug 2015 16:20:58 -0700 +Subject: [PATCH 05/11] Rework linux16 command + +We want a single buffer that contains the entire kernel image in order to +perform a TPM measurement. Allocate one and copy the entire kernel int it +before pulling out the individual blocks later on. +--- + grub-core/loader/i386/pc/linux.c | 34 +++++++++++++++++++++------------- + 1 file changed, 21 insertions(+), 13 deletions(-) + +diff --git a/grub-core/loader/i386/pc/linux.c b/grub-core/loader/i386/pc/linux.c +index a293b17..1ac9cd1 100644 +--- a/grub-core/loader/i386/pc/linux.c ++++ b/grub-core/loader/i386/pc/linux.c +@@ -123,13 +123,14 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + grub_file_t file = 0; + struct linux_kernel_header lh; + grub_uint8_t setup_sects; +- grub_size_t real_size; ++ grub_size_t real_size, kernel_offset = 0; + grub_ssize_t len; + int i; + char *grub_linux_prot_chunk; + int grub_linux_is_bzimage; + grub_addr_t grub_linux_prot_target; + grub_err_t err; ++ grub_uint8_t *kernel = NULL; + + grub_dl_ref (my_mod); + +@@ -143,7 +144,15 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + if (! file) + goto fail; + +- if (grub_file_read (file, &lh, sizeof (lh)) != sizeof (lh)) ++ len = grub_file_size (file); ++ kernel = grub_malloc (len); ++ if (!kernel) ++ { ++ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("cannot allocate kernel buffer")); ++ goto fail; ++ } ++ ++ if (grub_file_read (file, kernel, len) != len) + { + if (!grub_errno) + grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), +@@ -151,6 +160,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + goto fail; + } + ++ grub_memcpy (&lh, kernel, sizeof (lh)); ++ kernel_offset = sizeof (lh); ++ + if (lh.boot_flag != grub_cpu_to_le16_compile_time (0xaa55)) + { + grub_error (GRUB_ERR_BAD_OS, "invalid magic number"); +@@ -314,13 +326,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + grub_memmove (grub_linux_real_chunk, &lh, sizeof (lh)); + + len = real_size + GRUB_DISK_SECTOR_SIZE - sizeof (lh); +- if (grub_file_read (file, grub_linux_real_chunk + sizeof (lh), len) != len) +- { +- if (!grub_errno) +- grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), +- argv[0]); +- goto fail; +- } ++ grub_memcpy (grub_linux_real_chunk + sizeof (lh), kernel + kernel_offset, ++ len); ++ kernel_offset += len; + + if (lh.header != grub_cpu_to_le32_compile_time (GRUB_LINUX_MAGIC_SIGNATURE) + || grub_le_to_cpu16 (lh.version) < 0x0200) +@@ -355,10 +363,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + } + + len = grub_linux16_prot_size; +- if (grub_file_read (file, grub_linux_prot_chunk, grub_linux16_prot_size) +- != (grub_ssize_t) grub_linux16_prot_size && !grub_errno) +- grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), +- argv[0]); ++ grub_memcpy (grub_linux_prot_chunk, kernel + kernel_offset, len); ++ kernel_offset += len; + + if (grub_errno == GRUB_ERR_NONE) + { +@@ -368,6 +374,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + + fail: + ++ grub_free (kernel); ++ + if (file) + grub_file_close (file); + +-- +1.8.5.6 + diff --git a/0006-tpm-Measure-kernel-and-initrd-on-BIOS-systems.patch b/0006-tpm-Measure-kernel-and-initrd-on-BIOS-systems.patch new file mode 100644 index 0000000..9148a83 --- /dev/null +++ b/0006-tpm-Measure-kernel-and-initrd-on-BIOS-systems.patch @@ -0,0 +1,84 @@ +From f0b411214ccc309f2f126d558e2777469d538ca2 Mon Sep 17 00:00:00 2001 +From: Matthew Garrett +Date: Sun, 9 Aug 2015 16:28:29 -0700 +Subject: [PATCH 06/11] Measure kernel and initrd on BIOS systems + +Measure the kernel and initrd when loaded on BIOS systems +--- + grub-core/loader/i386/linux.c | 5 +++++ + grub-core/loader/i386/pc/linux.c | 3 +++ + grub-core/loader/linux.c | 2 ++ + 3 files changed, 10 insertions(+) + +Index: grub-2.02~beta3/grub-core/loader/i386/linux.c +=================================================================== +--- grub-2.02~beta3.orig/grub-core/loader/i386/linux.c ++++ grub-2.02~beta3/grub-core/loader/i386/linux.c +@@ -35,6 +35,7 @@ + #include + #include + #include ++#include + + GRUB_MOD_LICENSE ("GPLv3+"); + +@@ -716,7 +717,10 @@ grub_cmd_linux (grub_command_t cmd __att + goto fail; + } + ++ grub_tpm_measure (kernel, len, GRUB_BINARY_PCR, "grub_linux", "Kernel"); ++ + grub_memcpy (&lh, kernel, sizeof (lh)); ++ + kernel_offset = sizeof (lh); + + if (lh.boot_flag != grub_cpu_to_le16_compile_time (0xaa55)) +@@ -1025,6 +1029,7 @@ grub_cmd_linux (grub_command_t cmd __att + + len = prot_file_size; + grub_memcpy (prot_mode_mem, kernel + kernel_offset, len); ++ kernel_offset += len; + + if (grub_errno == GRUB_ERR_NONE) + { +Index: grub-2.02~beta3/grub-core/loader/i386/pc/linux.c +=================================================================== +--- grub-2.02~beta3.orig/grub-core/loader/i386/pc/linux.c ++++ grub-2.02~beta3/grub-core/loader/i386/pc/linux.c +@@ -35,6 +35,7 @@ + #include + #include + #include ++#include + + GRUB_MOD_LICENSE ("GPLv3+"); + +@@ -160,6 +161,8 @@ grub_cmd_linux (grub_command_t cmd __att + goto fail; + } + ++ grub_tpm_measure (kernel, len, GRUB_BINARY_PCR, "grub_linux16", "Kernel"); ++ + grub_memcpy (&lh, kernel, sizeof (lh)); + kernel_offset = sizeof (lh); + +Index: grub-2.02~beta3/grub-core/loader/linux.c +=================================================================== +--- grub-2.02~beta3.orig/grub-core/loader/linux.c ++++ grub-2.02~beta3/grub-core/loader/linux.c +@@ -4,6 +4,7 @@ + #include + #include + #include ++#include + + struct newc_head + { +@@ -288,6 +289,7 @@ grub_initrd_load (struct grub_linux_init + grub_initrd_close (initrd_ctx); + return grub_errno; + } ++ grub_tpm_measure (ptr, cursize, GRUB_BINARY_PCR, "grub_initrd", "Initrd"); + ptr += cursize; + } + if (newc) diff --git a/0007-tpm-Measure-the-kernel-commandline.patch b/0007-tpm-Measure-the-kernel-commandline.patch new file mode 100644 index 0000000..87e0056 --- /dev/null +++ b/0007-tpm-Measure-the-kernel-commandline.patch @@ -0,0 +1,43 @@ +From aa88827e5b6ca073d0a67e86c5d6581445de988b Mon Sep 17 00:00:00 2001 +From: Matthew Garrett +Date: Sun, 9 Aug 2015 16:32:29 -0700 +Subject: [PATCH 07/11] Measure the kernel commandline + +Measure the kernel commandline to ensure that it hasn't been modified +--- + grub-core/lib/cmdline.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/grub-core/lib/cmdline.c b/grub-core/lib/cmdline.c +index d5e10ee..3791f3a 100644 +--- a/grub-core/lib/cmdline.c ++++ b/grub-core/lib/cmdline.c +@@ -19,6 +19,7 @@ + + #include + #include ++#include + + static unsigned int check_arg (char *c, int *has_space) + { +@@ -67,7 +68,7 @@ int grub_create_loader_cmdline (int argc, char *argv[], char *buf, + { + int i, space; + unsigned int arg_size; +- char *c; ++ char *c, *orig = buf; + + for (i = 0; i < argc; i++) + { +@@ -104,5 +105,8 @@ int grub_create_loader_cmdline (int argc, char *argv[], char *buf, + + *buf = 0; + ++ grub_tpm_measure ((void *)orig, grub_strlen (orig), GRUB_ASCII_PCR, ++ "grub_kernel_cmdline", orig); ++ + return i; + } +-- +1.8.5.6 + diff --git a/0008-tpm-Measure-commands.patch b/0008-tpm-Measure-commands.patch new file mode 100644 index 0000000..607b0b3 --- /dev/null +++ b/0008-tpm-Measure-commands.patch @@ -0,0 +1,60 @@ +From 959e235378adef1477d14d7546c549b7619eb5f1 Mon Sep 17 00:00:00 2001 +From: Matthew Garrett +Date: Mon, 10 Aug 2015 15:27:12 -0700 +Subject: [PATCH 08/11] Measure commands + +Measure each command executed by grub, which includes script execution. +--- + grub-core/script/execute.c | 25 +++++++++++++++++++++++-- + 1 file changed, 23 insertions(+), 2 deletions(-) + +Index: grub-2.02~beta3/grub-core/script/execute.c +=================================================================== +--- grub-2.02~beta3.orig/grub-core/script/execute.c ++++ grub-2.02~beta3/grub-core/script/execute.c +@@ -30,6 +30,7 @@ + #ifdef GRUB_MACHINE_IEEE1275 + #include + #endif ++#include + + /* Max digits for a char is 3 (0xFF is 255), similarly for an int it + is sizeof (int) * 3, and one extra for a possible -ve sign. */ +@@ -936,8 +937,9 @@ grub_script_execute_cmdline (struct grub + grub_err_t ret = 0; + grub_script_function_t func = 0; + char errnobuf[18]; +- char *cmdname; +- int argc; ++ char *cmdname, *cmdstring; ++ int argc, offset = 0, cmdlen = 0; ++ unsigned int i; + char **args; + int invert; + struct grub_script_argv argv = { 0, 0, 0 }; +@@ -946,6 +948,25 @@ grub_script_execute_cmdline (struct grub + if (grub_script_arglist_to_argv (cmdline->arglist, &argv) || ! argv.args[0]) + return grub_errno; + ++ for (i = 0; i < argv.argc; i++) { ++ cmdlen += grub_strlen (argv.args[i]) + 1; ++ } ++ ++ cmdstring = grub_malloc (cmdlen); ++ if (!cmdstring) ++ { ++ return grub_error (GRUB_ERR_OUT_OF_MEMORY, ++ N_("cannot allocate command buffer")); ++ } ++ ++ for (i = 0; i < argv.argc; i++) { ++ offset += grub_snprintf (cmdstring + offset, cmdlen - offset, "%s ", ++ argv.args[i]); ++ } ++ cmdstring[cmdlen-1]= '\0'; ++ grub_tpm_measure ((unsigned char *)cmdstring, cmdlen, GRUB_ASCII_PCR, ++ "grub_cmd", cmdstring); ++ grub_free(cmdstring); + invert = 0; + argc = argv.argc - 1; + args = argv.args + 1; diff --git a/0009-tpm-Measure-multiboot-images-and-modules.patch b/0009-tpm-Measure-multiboot-images-and-modules.patch new file mode 100644 index 0000000..293fd0d --- /dev/null +++ b/0009-tpm-Measure-multiboot-images-and-modules.patch @@ -0,0 +1,73 @@ +From fd82340829d9fce685f80163ddb6ee3399929c3c Mon Sep 17 00:00:00 2001 +From: Matthew Garrett +Date: Tue, 1 Sep 2015 16:02:55 -0700 +Subject: [PATCH 09/11] Measure multiboot images and modules + +--- + grub-core/loader/i386/multiboot_mbi.c | 3 +++ + grub-core/loader/multiboot.c | 2 ++ + grub-core/loader/multiboot_mbi2.c | 3 +++ + 3 files changed, 8 insertions(+) + +Index: grub-2.02~rc1/grub-core/loader/i386/multiboot_mbi.c +=================================================================== +--- grub-2.02~rc1.orig/grub-core/loader/i386/multiboot_mbi.c ++++ grub-2.02~rc1/grub-core/loader/i386/multiboot_mbi.c +@@ -36,6 +36,7 @@ + #include + #include + #include ++#include + + #ifdef GRUB_MACHINE_EFI + #include +@@ -173,6 +174,8 @@ grub_multiboot_load (grub_file_t file, c + return grub_errno; + } + ++ grub_tpm_measure((unsigned char*)buffer, len, GRUB_BINARY_PCR, "grub_multiboot", filename); ++ + header = find_header (buffer, len); + + if (header == 0) +Index: grub-2.02~rc1/grub-core/loader/multiboot.c +=================================================================== +--- grub-2.02~rc1.orig/grub-core/loader/multiboot.c ++++ grub-2.02~rc1/grub-core/loader/multiboot.c +@@ -42,6 +42,7 @@ + #include + #include + #include ++#include + + GRUB_MOD_LICENSE ("GPLv3+"); + +@@ -424,6 +425,7 @@ grub_cmd_module (grub_command_t cmd __at + } + + grub_file_close (file); ++ grub_tpm_measure (module, size, GRUB_BINARY_PCR, "grub_multiboot", argv[0]); + return GRUB_ERR_NONE; + } + +Index: grub-2.02~rc1/grub-core/loader/multiboot_mbi2.c +=================================================================== +--- grub-2.02~rc1.orig/grub-core/loader/multiboot_mbi2.c ++++ grub-2.02~rc1/grub-core/loader/multiboot_mbi2.c +@@ -36,6 +36,7 @@ + #include + #include + #include ++#include + + #if defined (GRUB_MACHINE_EFI) + #include +@@ -131,6 +132,8 @@ grub_multiboot_load (grub_file_t file, c + + COMPILE_TIME_ASSERT (MULTIBOOT_HEADER_ALIGN % 4 == 0); + ++ grub_tpm_measure ((unsigned char *)mld.buffer, len, GRUB_BINARY_PCR, "grub_multiboot", filename); ++ + header = find_header (mld.buffer, len); + + if (header == 0) diff --git a/0010-tpm-Fix-boot-when-there-s-no-TPM.patch b/0010-tpm-Fix-boot-when-there-s-no-TPM.patch new file mode 100644 index 0000000..d10fd00 --- /dev/null +++ b/0010-tpm-Fix-boot-when-there-s-no-TPM.patch @@ -0,0 +1,29 @@ +From c9016d2ae0abc5edcb4dcf4b1ce04f138f6e5a67 Mon Sep 17 00:00:00 2001 +From: Matthew Garrett +Date: Wed, 23 Mar 2016 16:49:42 -0700 +Subject: [PATCH 10/11] Fix boot when there's no TPM + +If the firmware has TPM support but has no TPM, we're jumping to core.img +without popping the registers back onto the stack. Fix that. +--- + grub-core/boot/i386/pc/boot.S | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/grub-core/boot/i386/pc/boot.S b/grub-core/boot/i386/pc/boot.S +index 4c63247..47a461e 100644 +--- a/grub-core/boot/i386/pc/boot.S ++++ b/grub-core/boot/i386/pc/boot.S +@@ -476,9 +476,9 @@ LOCAL(copy_buffer): + movl $0x8, %edx /* PCR 8 */ + int $0x1A + ++boot: + popa + #endif +-boot: + /* boot kernel */ + jmp *(LOCAL(kernel_address)) + +-- +1.8.5.6 + diff --git a/0011-tpm-Fix-build-error.patch b/0011-tpm-Fix-build-error.patch new file mode 100644 index 0000000..41542c9 --- /dev/null +++ b/0011-tpm-Fix-build-error.patch @@ -0,0 +1,74 @@ +Index: grub-2.02~rc1/grub-core/kern/efi/tpm.c +=================================================================== +--- grub-2.02~rc1.orig/grub-core/kern/efi/tpm.c ++++ grub-2.02~rc1/grub-core/kern/efi/tpm.c +@@ -161,21 +161,12 @@ grub_tpm_execute(PassThroughToTPM_InputP + } + } + +-typedef struct { +- grub_uint32_t pcrindex; +- grub_uint32_t eventtype; +- grub_uint8_t digest[20]; +- grub_uint32_t eventsize; +- grub_uint8_t event[1]; +-} Event; +- +- + static grub_err_t + grub_tpm1_log_event(grub_efi_handle_t tpm_handle, unsigned char *buf, + grub_size_t size, grub_uint8_t pcr, + const char *description) + { +- Event *event; ++ TCG_PCR_EVENT *event; + grub_efi_status_t status; + grub_efi_tpm_protocol_t *tpm; + grub_efi_physical_address_t lastevent; +@@ -188,18 +179,18 @@ grub_tpm1_log_event(grub_efi_handle_t tp + if (!grub_tpm_present(tpm)) + return 0; + +- event = grub_zalloc(sizeof (Event) + grub_strlen(description) + 1); ++ event = grub_zalloc(sizeof (TCG_PCR_EVENT) + grub_strlen(description) + 1); + if (!event) + return grub_error (GRUB_ERR_OUT_OF_MEMORY, + N_("cannot allocate TPM event buffer")); + +- event->pcrindex = pcr; +- event->eventtype = EV_IPL; +- event->eventsize = grub_strlen(description) + 1; +- grub_memcpy(event->event, description, event->eventsize); ++ event->PCRIndex = pcr; ++ event->EventType = EV_IPL; ++ event->EventSize = grub_strlen(description) + 1; ++ grub_memcpy(event->Event, description, event->EventSize); + + algorithm = TCG_ALG_SHA; +- status = efi_call_7 (tpm->log_extend_event, tpm, buf, (grub_uint64_t) size, ++ status = efi_call_7 (tpm->log_extend_event, tpm, (grub_efi_physical_address_t)(grub_addr_t) buf, (grub_uint64_t) size, + algorithm, event, &eventnum, &lastevent); + + switch (status) { +@@ -245,7 +236,7 @@ grub_tpm2_log_event(grub_efi_handle_t tp + event->Size = sizeof(*event) - sizeof(event->Event) + grub_strlen(description) + 1; + grub_memcpy(event->Event, description, grub_strlen(description) + 1); + +- status = efi_call_5 (tpm->hash_log_extend_event, tpm, 0, buf, ++ status = efi_call_5 (tpm->hash_log_extend_event, tpm, 0, (grub_efi_physical_address_t)(grub_addr_t) buf, + (grub_uint64_t) size, event); + + switch (status) { +Index: grub-2.02~rc1/include/grub/efi/tpm.h +=================================================================== +--- grub-2.02~rc1.orig/include/grub/efi/tpm.h ++++ grub-2.02~rc1/include/grub/efi/tpm.h +@@ -129,7 +129,7 @@ struct grub_efi_tpm2_protocol + grub_efi_boolean_t *EventLogTruncated); + grub_efi_status_t (*hash_log_extend_event) (struct grub_efi_tpm2_protocol *this, + grub_efi_uint64_t Flags, +- grub_efi_physical_address_t *DataToHash, ++ grub_efi_physical_address_t DataToHash, + grub_efi_uint64_t DataToHashLen, + EFI_TCG2_EVENT *EfiTcgEvent); + grub_efi_status_t (*submit_command) (struct grub_efi_tpm2_protocol *this, diff --git a/0012-tpm-Build-tpm-as-module.patch b/0012-tpm-Build-tpm-as-module.patch new file mode 100644 index 0000000..d95d9c3 --- /dev/null +++ b/0012-tpm-Build-tpm-as-module.patch @@ -0,0 +1,505 @@ +From 54b6ba5f27dd9eb9ec2f1a41e7160964ab94451c Mon Sep 17 00:00:00 2001 +From: Michael Chang +Date: Wed, 23 Nov 2016 16:52:16 +0800 +Subject: [PATCH 11/11] Build tpm as module + +Rather than having tpm as permanent kernel feature that gets enabled and active +unconditionally, it's more applicable to have it as external module that can be +installed with --suse-enable-tpm option to grub2-install. + +This can provide some enhancement. First the core image size can be nearly the +same when you don't need TPM, as it's controllable option now. Second the TPM +device can be tested upon loading the module instead of on every measurement. +Third is not to potentially break running system by forcing into the TPM after +update, as it's still bleeding edge feature that could have side effect. + +--- + grub-core/Makefile.core.def | 24 +++- + grub-core/boot/i386/pc/boot.S | 1 - + grub-core/kern/efi/tpm.c | 282 ----------------------------------------- + grub-core/kern/i386/pc/tpm.c | 132 -------------------- + grub-core/kern/tpm.c | 11 +- + grub-core/tpm/efi/tpm.c | 283 ++++++++++++++++++++++++++++++++++++++++++ + grub-core/tpm/i386/pc/tpm.c | 144 +++++++++++++++++++++ + include/grub/tpm.h | 23 ++-- + util/grub-install.c | 16 ++- + 9 files changed, 479 insertions(+), 437 deletions(-) + delete mode 100644 grub-core/kern/efi/tpm.c + delete mode 100644 grub-core/kern/i386/pc/tpm.c + create mode 100644 grub-core/tpm/efi/tpm.c + create mode 100644 grub-core/tpm/i386/pc/tpm.c + +Index: grub-2.02~rc1/grub-core/Makefile.core.def +=================================================================== +--- grub-2.02~rc1.orig/grub-core/Makefile.core.def ++++ grub-2.02~rc1/grub-core/Makefile.core.def +@@ -174,7 +174,6 @@ kernel = { + efi = term/efi/console.c; + efi = kern/acpi.c; + efi = kern/efi/acpi.c; +- efi = kern/efi/tpm.c; + i386_coreboot = kern/i386/pc/acpi.c; + i386_multiboot = kern/i386/pc/acpi.c; + i386_coreboot = kern/acpi.c; +@@ -221,7 +220,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; +@@ -395,6 +393,19 @@ image = { + }; + + image = { ++ name = boot_tpm; ++ i386_pc = boot/i386/pc/boot.S; ++ ++ cppflags = '-DTPM=1'; ++ ++ i386_pc_ldflags = '$(TARGET_IMG_LDFLAGS)'; ++ i386_pc_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x7C00'; ++ ++ objcopyflags = '-O binary'; ++ enable = i386_pc; ++}; ++ ++image = { + name = cdboot; + + i386_pc = boot/i386/pc/cdboot.S; +@@ -2369,3 +2380,12 @@ module = { + common = loader/i386/xen_file64.c; + extra_dist = loader/i386/xen_fileXX.c; + }; ++ ++module = { ++ name = tpm; ++ i386_pc = kern/i386/pc/tpm.c; ++ efi = kern/efi/tpm.c; ++ ++ enable = i386_pc; ++ enable = efi; ++}; +Index: grub-2.02~rc1/grub-core/boot/i386/pc/boot.S +=================================================================== +--- grub-2.02~rc1.orig/grub-core/boot/i386/pc/boot.S ++++ grub-2.02~rc1/grub-core/boot/i386/pc/boot.S +@@ -24,7 +24,6 @@ + * defines for the code go here + */ + +-#define TPM 1 + + /* Print message string */ + #define MSG(x) movw $x, %si; call LOCAL(message) +Index: grub-2.02~rc1/grub-core/kern/efi/tpm.c +=================================================================== +--- grub-2.02~rc1.orig/grub-core/kern/efi/tpm.c ++++ grub-2.02~rc1/grub-core/kern/efi/tpm.c +@@ -7,6 +7,8 @@ + #include + #include + ++GRUB_MOD_LICENSE ("GPLv3+"); ++ + static grub_efi_guid_t tpm_guid = EFI_TPM_GUID; + static grub_efi_guid_t tpm2_guid = EFI_TPM2_GUID; + +@@ -70,21 +72,14 @@ static grub_efi_boolean_t grub_tpm_handl + } + + static grub_err_t +-grub_tpm1_execute(grub_efi_handle_t tpm_handle, ++grub_tpm1_execute(grub_efi_tpm_protocol_t *tpm, + PassThroughToTPM_InputParamBlock *inbuf, + PassThroughToTPM_OutputParamBlock *outbuf) + { + grub_efi_status_t status; +- grub_efi_tpm_protocol_t *tpm; + grub_uint32_t inhdrsize = sizeof(*inbuf) - sizeof(inbuf->TPMOperandIn); + grub_uint32_t outhdrsize = sizeof(*outbuf) - sizeof(outbuf->TPMOperandOut); + +- tpm = grub_efi_open_protocol (tpm_handle, &tpm_guid, +- GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL); +- +- if (!grub_tpm_present(tpm)) +- return 0; +- + /* UEFI TPM protocol takes the raw operand block, no param block header */ + status = efi_call_5 (tpm->pass_through_to_tpm, tpm, + inbuf->IPBLength - inhdrsize, inbuf->TPMOperandIn, +@@ -107,21 +102,14 @@ grub_tpm1_execute(grub_efi_handle_t tpm_ + } + + static grub_err_t +-grub_tpm2_execute(grub_efi_handle_t tpm_handle, ++grub_tpm2_execute(grub_efi_tpm2_protocol_t *tpm, + PassThroughToTPM_InputParamBlock *inbuf, + PassThroughToTPM_OutputParamBlock *outbuf) + { + grub_efi_status_t status; +- grub_efi_tpm2_protocol_t *tpm; + grub_uint32_t inhdrsize = sizeof(*inbuf) - sizeof(inbuf->TPMOperandIn); + grub_uint32_t outhdrsize = sizeof(*outbuf) - sizeof(outbuf->TPMOperandOut); + +- tpm = grub_efi_open_protocol (tpm_handle, &tpm2_guid, +- GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL); +- +- if (!grub_tpm2_present(tpm)) +- return 0; +- + /* UEFI TPM protocol takes the raw operand block, no param block header */ + status = efi_call_5 (tpm->submit_command, tpm, + inbuf->IPBLength - inhdrsize, inbuf->TPMOperandIn, +@@ -143,42 +131,17 @@ grub_tpm2_execute(grub_efi_handle_t tpm_ + } + } + +-grub_err_t +-grub_tpm_execute(PassThroughToTPM_InputParamBlock *inbuf, +- PassThroughToTPM_OutputParamBlock *outbuf) +-{ +- grub_efi_handle_t tpm_handle; +- grub_uint8_t protocol_version; +- +- /* It's not a hard failure for there to be no TPM */ +- if (!grub_tpm_handle_find(&tpm_handle, &protocol_version)) +- return 0; +- +- if (protocol_version == 1) { +- return grub_tpm1_execute(tpm_handle, inbuf, outbuf); +- } else { +- return grub_tpm2_execute(tpm_handle, inbuf, outbuf); +- } +-} +- + static grub_err_t +-grub_tpm1_log_event(grub_efi_handle_t tpm_handle, unsigned char *buf, ++grub_tpm1_log_event(grub_efi_tpm_protocol_t *tpm, unsigned char *buf, + grub_size_t size, grub_uint8_t pcr, + const char *description) + { + TCG_PCR_EVENT *event; + grub_efi_status_t status; +- grub_efi_tpm_protocol_t *tpm; + grub_efi_physical_address_t lastevent; + grub_uint32_t algorithm; + grub_uint32_t eventnum = 0; + +- tpm = grub_efi_open_protocol (tpm_handle, &tpm_guid, +- GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL); +- +- if (!grub_tpm_present(tpm)) +- return 0; +- + event = grub_zalloc(sizeof (TCG_PCR_EVENT) + grub_strlen(description) + 1); + if (!event) + return grub_error (GRUB_ERR_OUT_OF_MEMORY, +@@ -210,19 +173,12 @@ grub_tpm1_log_event(grub_efi_handle_t tp + } + + static grub_err_t +-grub_tpm2_log_event(grub_efi_handle_t tpm_handle, unsigned char *buf, ++grub_tpm2_log_event(grub_efi_tpm2_protocol_t *tpm, unsigned char *buf, + grub_size_t size, grub_uint8_t pcr, + const char *description) + { + EFI_TCG2_EVENT *event; + grub_efi_status_t status; +- grub_efi_tpm2_protocol_t *tpm; +- +- tpm = grub_efi_open_protocol (tpm_handle, &tpm2_guid, +- GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL); +- +- if (!grub_tpm2_present(tpm)) +- return 0; + + event = grub_zalloc(sizeof (EFI_TCG2_EVENT) + grub_strlen(description) + 1); + if (!event) +@@ -255,19 +211,64 @@ grub_tpm2_log_event(grub_efi_handle_t tp + } + } + +-grub_err_t ++static grub_efi_tpm_protocol_t *tpm; ++static grub_efi_tpm2_protocol_t *tpm2; ++ ++static grub_err_t ++grub_tpm_execute(PassThroughToTPM_InputParamBlock *inbuf, ++ PassThroughToTPM_OutputParamBlock *outbuf) ++{ ++ if (tpm) ++ return grub_tpm1_execute(tpm, inbuf, outbuf); ++ else if (tpm2) ++ return grub_tpm2_execute(tpm2, inbuf, outbuf); ++ return GRUB_ERR_NONE; ++} ++ ++static grub_err_t + grub_tpm_log_event(unsigned char *buf, grub_size_t size, grub_uint8_t pcr, + const char *description) + { ++ if (tpm) ++ return grub_tpm1_log_event(tpm, buf, size, pcr, description); ++ else if (tpm2) ++ return grub_tpm2_log_event(tpm2, buf, size, pcr, description); ++ return GRUB_ERR_NONE; ++} ++ ++static struct grub_tpm grub_efi_tpm = ++{ ++ .log_event = grub_tpm_log_event, ++ .execute = grub_tpm_execute ++}; ++ ++GRUB_MOD_INIT (tpm) ++{ + grub_efi_handle_t tpm_handle; + grub_efi_uint8_t protocol_version; + +- if (!grub_tpm_handle_find(&tpm_handle, &protocol_version)) +- return 0; ++ if (!grub_tpm_handle_find (&tpm_handle, &protocol_version)) ++ return ; + +- if (protocol_version == 1) { +- return grub_tpm1_log_event(tpm_handle, buf, size, pcr, description); +- } else { +- return grub_tpm2_log_event(tpm_handle, buf, size, pcr, description); +- } ++ if (protocol_version == 1) ++ { ++ tpm = grub_efi_open_protocol (tpm_handle, &tpm_guid, ++ GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL); ++ if (tpm && grub_tpm_present(tpm)) ++ grub_tpm = &grub_efi_tpm; ++ } ++ else ++ { ++ tpm2 = grub_efi_open_protocol (tpm_handle, &tpm2_guid, ++ GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL); ++ if (tpm2 && grub_tpm2_present(tpm2)) ++ grub_tpm = &grub_efi_tpm; ++ } ++} ++ ++GRUB_MOD_FINI (tpm) ++{ ++ grub_tpm = NULL; ++ tpm = NULL; ++ tpm2 = NULL; + } +Index: grub-2.02~rc1/grub-core/kern/i386/pc/tpm.c +=================================================================== +--- grub-2.02~rc1.orig/grub-core/kern/i386/pc/tpm.c ++++ grub-2.02~rc1/grub-core/kern/i386/pc/tpm.c +@@ -4,12 +4,14 @@ + #include + #include + #include ++#include + +-#define TCPA_MAGIC 0x41504354 ++GRUB_MOD_LICENSE ("GPLv3+"); + +-int tpm_present(void); ++#define TCPA_MAGIC 0x41504354 + +-int tpm_present(void) ++static int ++tpm_present(void) + { + struct grub_bios_int_registers regs; + +@@ -24,16 +26,13 @@ int tpm_present(void) + return 0; + } + +-grub_err_t ++static 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; +@@ -80,7 +79,7 @@ typedef struct { + grub_uint8_t hashvalue[20]; + } GRUB_PACKED EventOutgoing; + +-grub_err_t ++static grub_err_t + grub_tpm_log_event(unsigned char *buf, grub_size_t size, grub_uint8_t pcr, + const char *description) + { +@@ -90,9 +89,6 @@ grub_tpm_log_event(unsigned char *buf, g + Event *event; + grub_uint32_t datalength; + +- if (!tpm_present()) +- return 0; +- + datalength = grub_strlen(description); + event = grub_zalloc(datalength + sizeof(Event)); + if (!event) +@@ -130,3 +126,19 @@ grub_tpm_log_event(unsigned char *buf, g + + return 0; + } ++static struct grub_tpm grub_pc_tpm = ++{ ++ .log_event = grub_tpm_log_event, ++ .execute = grub_tpm_execute ++}; ++ ++GRUB_MOD_INIT (tpm) ++{ ++ if (tpm_present()) ++ grub_tpm = &grub_pc_tpm; ++} ++ ++GRUB_MOD_FINI (tpm) ++{ ++ grub_tpm = NULL; ++} +Index: grub-2.02~rc1/grub-core/kern/tpm.c +=================================================================== +--- grub-2.02~rc1.orig/grub-core/kern/tpm.c ++++ grub-2.02~rc1/grub-core/kern/tpm.c +@@ -5,15 +5,22 @@ + #include + #include + ++grub_tpm_t grub_tpm = NULL; ++ + grub_err_t + grub_tpm_measure (unsigned char *buf, grub_size_t size, grub_uint8_t pcr, + const char *kind, const char *description) + { + grub_err_t ret; +- char *desc = grub_xasprintf("%s %s", kind, description); ++ char *desc; ++ ++ if (!grub_tpm) ++ return GRUB_ERR_NONE; ++ ++ desc = grub_xasprintf("%s %s", kind, description); + if (!desc) + return GRUB_ERR_OUT_OF_MEMORY; +- ret = grub_tpm_log_event(buf, size, pcr, description); ++ ret = grub_tpm->log_event(buf, size, pcr, desc); + grub_free(desc); + return ret; + } +Index: grub-2.02~rc1/include/grub/tpm.h +=================================================================== +--- grub-2.02~rc1.orig/include/grub/tpm.h ++++ grub-2.02~rc1/include/grub/tpm.h +@@ -69,21 +69,14 @@ 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) +-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, +- grub_uint8_t pcr, const char *description); +-#else +-static inline grub_err_t grub_tpm_execute(PassThroughToTPM_InputParamBlock *inbuf, +- PassThroughToTPM_OutputParamBlock *outbuf) { return 0; }; +-static inline grub_err_t grub_tpm_log_event(unsigned char *buf, +- grub_size_t size, +- grub_uint8_t pcr, +- const char *description) ++typedef struct grub_tpm + { +- return 0; +-}; +-#endif ++ grub_err_t (*log_event)(unsigned char *buf, grub_size_t size, ++ grub_uint8_t pcr, const char *description); ++ grub_err_t (*execute)(PassThroughToTPM_InputParamBlock *inbuf, ++ PassThroughToTPM_OutputParamBlock *outbuf); ++} *grub_tpm_t; ++ ++extern grub_tpm_t EXPORT_VAR(grub_tpm); + + #endif +Index: grub-2.02~rc1/util/grub-install.c +=================================================================== +--- grub-2.02~rc1.orig/util/grub-install.c ++++ grub-2.02~rc1/util/grub-install.c +@@ -80,6 +80,7 @@ static char *label_color; + static char *label_bgcolor; + static char *product_version; + static int add_rs_codes = 1; ++static int suse_enable_tpm = 0; + + enum + { +@@ -106,6 +107,7 @@ enum + OPTION_DISK_MODULE, + OPTION_NO_BOOTSECTOR, + OPTION_NO_RS_CODES, ++ OPTION_SUSE_ENABLE_TPM, + OPTION_MACPPC_DIRECTORY, + OPTION_ZIPL_DIRECTORY, + OPTION_LABEL_FONT, +@@ -231,6 +233,10 @@ argp_parser (int key, char *arg, struct + add_rs_codes = 0; + return 0; + ++ case OPTION_SUSE_ENABLE_TPM: ++ suse_enable_tpm = 1; ++ return 0; ++ + case OPTION_DEBUG: + verbosity++; + return 0; +@@ -292,6 +298,7 @@ static struct argp_option options[] = { + {"no-rs-codes", OPTION_NO_RS_CODES, 0, 0, + N_("Do not apply any reed-solomon codes when embedding core.img. " + "This option is only available on x86 BIOS targets."), 0}, ++ {"suse-enable-tpm", OPTION_SUSE_ENABLE_TPM, 0, 0, N_("install TPM modules"), 0}, + + {"debug", OPTION_DEBUG, 0, OPTION_HIDDEN, 0, 2}, + {"no-floppy", OPTION_NO_FLOPPY, 0, OPTION_HIDDEN, 0, 2}, +@@ -1322,6 +1329,9 @@ main (int argc, char *argv[]) + else if (disk_module && disk_module[0]) + grub_install_push_module (disk_module); + ++ if (suse_enable_tpm && (is_efi || platform == GRUB_INSTALL_PLATFORM_I386_PC)) ++ grub_install_push_module ("tpm"); ++ + relative_grubdir = grub_make_system_path_relative_to_its_root (grubdir); + if (relative_grubdir[0] == '\0') + { +@@ -1742,9 +1752,9 @@ main (int argc, char *argv[]) + { + char *boot_img_src = grub_util_path_concat (2, + grub_install_source_directory, +- "boot.img"); ++ suse_enable_tpm ? "boot_tpm.img" : "boot.img"); + char *boot_img = grub_util_path_concat (2, platdir, +- "boot.img"); ++ suse_enable_tpm ? "boot_tpm.img" : "boot.img"); + grub_install_copy_file (boot_img_src, boot_img, 1); + + grub_util_info ("%sgrub-bios-setup %s %s %s %s %s --directory='%s' --device-map='%s' '%s'", +@@ -1762,7 +1772,7 @@ main (int argc, char *argv[]) + + /* Now perform the installation. */ + if (install_bootsector) +- grub_util_bios_setup (platdir, "boot.img", "core.img", ++ grub_util_bios_setup (platdir, suse_enable_tpm ? "boot_tpm.img" : "boot.img", "core.img", + install_drive, force, + fs_probe, allow_floppy, add_rs_codes); + break; diff --git a/grub2.changes b/grub2.changes index f607edf..ac951aa 100644 --- a/grub2.changes +++ b/grub2.changes @@ -1,3 +1,21 @@ +------------------------------------------------------------------- +Mon Mar 6 06:34:01 UTC 2017 - mchang@suse.com + +- TPM Support (FATE#315831) + * 0001-tpm-Core-TPM-support.patch + * 0002-tpm-Measure-kernel-initrd.patch + * 0003-tpm-Add-BIOS-boot-measurement.patch + * 0004-tpm-Rework-linux-command.patch + * 0005-tpm-Rework-linux16-command.patch + * 0006-tpm-Measure-kernel-and-initrd-on-BIOS-systems.patch + * 0007-tpm-Measure-the-kernel-commandline.patch + * 0008-tpm-Measure-commands.patch + * 0009-tpm-Measure-multiboot-images-and-modules.patch + * 0010-tpm-Fix-boot-when-there-s-no-TPM.patch + * 0011-tpm-Fix-build-error.patch + * 0012-tpm-Build-tpm-as-module.patch +- grub2.spec : Add grub-tpm.efi for Secure Boot + ------------------------------------------------------------------- Fri Mar 3 10:26:10 UTC 2017 - mchang@suse.com diff --git a/grub2.spec b/grub2.spec index 87ebbd2..9a2100d 100644 --- a/grub2.spec +++ b/grub2.spec @@ -249,6 +249,19 @@ Patch286: 0007-efinet-Setting-network-from-UEFI-device-path.patch Patch287: 0008-efinet-Setting-DNS-server-from-UEFI-protocol.patch # Fix GOP BLT support (FATE#322332) Patch311: grub2-efi-gop-add-blt.patch +# TPM Support (FATE#315831) +Patch400: 0001-tpm-Core-TPM-support.patch +Patch401: 0002-tpm-Measure-kernel-initrd.patch +Patch402: 0003-tpm-Add-BIOS-boot-measurement.patch +Patch403: 0004-tpm-Rework-linux-command.patch +Patch404: 0005-tpm-Rework-linux16-command.patch +Patch405: 0006-tpm-Measure-kernel-and-initrd-on-BIOS-systems.patch +Patch406: 0007-tpm-Measure-the-kernel-commandline.patch +Patch407: 0008-tpm-Measure-commands.patch +Patch408: 0009-tpm-Measure-multiboot-images-and-modules.patch +Patch409: 0010-tpm-Fix-boot-when-there-s-no-TPM.patch +Patch410: 0011-tpm-Fix-build-error.patch +Patch411: 0012-tpm-Build-tpm-as-module.patch Requires: gettext-runtime %if 0%{?suse_version} >= 1140 @@ -490,6 +503,18 @@ swap partition while in resuming %patch286 -p1 %patch287 -p1 %patch311 -p1 +%patch400 -p1 +%patch401 -p1 +%patch402 -p1 +%patch403 -p1 +%patch404 -p1 +%patch405 -p1 +%patch406 -p1 +%patch407 -p1 +%patch408 -p1 +%patch409 -p1 +%patch410 -p1 +%patch411 -p1 # This simplifies patch handling without need to use git to create patch # that renames file @@ -600,6 +625,8 @@ CD_MODULES="${CD_MODULES} linux" GRUB_MODULES="${CD_MODULES} ${FS_MODULES} ${PXE_MODULES} ${CRYPTO_MODULES} mdraid09 mdraid1x lvm serial" ./grub-mkimage -O %{grubefiarch} -o grub.efi --prefix= \ -d grub-core ${GRUB_MODULES} +./grub-mkimage -O %{grubefiarch} -o grub-tpm.efi --prefix= \ + -d grub-core ${GRUB_MODULES} tpm #./grub-mkimage -O %{grubefiarch} -o grub.efi -d grub-core part_gpt hfsplus fat \ # ext2 btrfs normal chain boot configfile linux appleldr minicmd \ # loadbios reboot halt search font gfxterm @@ -673,7 +700,7 @@ cd .. cd build-efi make DESTDIR=$RPM_BUILD_ROOT install -install -m 644 grub.efi $RPM_BUILD_ROOT%{_libdir}/%{name}/%{grubefiarch}/. +install -m 644 grub.efi grub-tpm.efi $RPM_BUILD_ROOT%{_libdir}/%{name}/%{grubefiarch}/. # Create grub.efi link to system efi directory # This is for tools like kiwi not fiddling with the path @@ -687,7 +714,7 @@ ln -sf ../../../%{_libdir}/%{name}/%{grubefiarch}/grub.efi $RPM_BUILD_ROOT%{syse %ifarch x86_64 %if 0%{?suse_version} >= 1230 || 0%{?suse_version} == 1110 -export BRP_PESIGN_FILES="%{_libdir}/%{name}/%{grubefiarch}/grub.efi" +export BRP_PESIGN_FILES="%{_libdir}/%{name}/%{grubefiarch}/grub.efi %{_libdir}/%{name}/%{grubefiarch}/grub-tpm.efi" install -m 444 grub.der $RPM_BUILD_ROOT%{sysefidir}/ %endif %endif @@ -1077,6 +1104,7 @@ fi %defattr(-,root,root,-) %dir %{_libdir}/%{name}/%{grubefiarch} %{_libdir}/%{name}/%{grubefiarch}/grub.efi +%{_libdir}/%{name}/%{grubefiarch}/grub-tpm.efi %{_libdir}/%{name}/%{grubefiarch}/*.img %{_libdir}/%{name}/%{grubefiarch}/*.lst %{_libdir}/%{name}/%{grubefiarch}/*.mod