Merge pull request #20 from mjg59/master

Add TPM measurement support
This commit is contained in:
mjg59 2016-01-05 15:32:28 -08:00
commit d4bc2bf02f
19 changed files with 854 additions and 63 deletions

View file

@ -88,6 +88,7 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/term.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/time.h 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/mm_private.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/net.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 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/memory.h
if COND_i386_pc if COND_i386_pc

View file

@ -126,6 +126,7 @@ kernel = {
common = kern/rescue_parser.c; common = kern/rescue_parser.c;
common = kern/rescue_reader.c; common = kern/rescue_reader.c;
common = kern/term.c; common = kern/term.c;
common = kern/tpm.c;
noemu = kern/compiler-rt.c; noemu = kern/compiler-rt.c;
noemu = kern/mm.c; noemu = kern/mm.c;
@ -173,6 +174,7 @@ kernel = {
efi = term/efi/console.c; efi = term/efi/console.c;
efi = kern/acpi.c; efi = kern/acpi.c;
efi = kern/efi/acpi.c; efi = kern/efi/acpi.c;
efi = kern/efi/tpm.c;
i386_coreboot = kern/i386/pc/acpi.c; i386_coreboot = kern/i386/pc/acpi.c;
i386_multiboot = kern/i386/pc/acpi.c; i386_multiboot = kern/i386/pc/acpi.c;
i386_coreboot = kern/acpi.c; i386_coreboot = kern/acpi.c;
@ -217,6 +219,7 @@ kernel = {
i386_pc = kern/i386/pc/init.c; i386_pc = kern/i386/pc/init.c;
i386_pc = kern/i386/pc/mmap.c; i386_pc = kern/i386/pc/mmap.c;
i386_pc = kern/i386/pc/tpm.c;
i386_pc = term/i386/pc/console.c; i386_pc = term/i386/pc/console.c;
i386_qemu = bus/pci.c; i386_qemu = bus/pci.c;

View file

@ -24,11 +24,14 @@
* defines for the code go here * defines for the code go here
*/ */
#define TPM 1
/* Print message string */ /* Print message string */
#define MSG(x) movw $x, %si; call LOCAL(message) #define MSG(x) movw $x, %si; call LOCAL(message)
#define ERR(x) movw $x, %si; jmp LOCAL(error_message) #define ERR(x) movw $x, %si; jmp LOCAL(error_message)
.macro floppy .macro floppy
#ifndef TPM
part_start: part_start:
LOCAL(probe_values): LOCAL(probe_values):
@ -85,6 +88,7 @@ fd_probe_error_string: .asciz "Floppy"
movb MACRO_DOLLAR(79), %ch movb MACRO_DOLLAR(79), %ch
jmp LOCAL(final_init) jmp LOCAL(final_init)
#endif
.endm .endm
.macro scratch .macro scratch
@ -255,6 +259,7 @@ real_start:
/* set %si to the disk address packet */ /* set %si to the disk address packet */
movw $disk_address_packet, %si movw $disk_address_packet, %si
#ifndef TPM
/* check if LBA is supported */ /* check if LBA is supported */
movb $0x41, %ah movb $0x41, %ah
movw $0x55aa, %bx movw $0x55aa, %bx
@ -274,6 +279,7 @@ real_start:
andw $1, %cx andw $1, %cx
jz LOCAL(chs_mode) jz LOCAL(chs_mode)
#endif
LOCAL(lba_mode): LOCAL(lba_mode):
xorw %ax, %ax xorw %ax, %ax
@ -317,6 +323,9 @@ LOCAL(lba_mode):
jmp LOCAL(copy_buffer) jmp LOCAL(copy_buffer)
LOCAL(chs_mode): LOCAL(chs_mode):
#ifdef TPM
jmp LOCAL(general_error)
#else
/* /*
* Determine the hard disk geometry from the BIOS! * Determine the hard disk geometry from the BIOS!
* We do this first, so that LS-120 IDE floppies work correctly. * We do this first, so that LS-120 IDE floppies work correctly.
@ -428,7 +437,7 @@ setup_sectors:
jc LOCAL(read_error) jc LOCAL(read_error)
movw %es, %bx movw %es, %bx
#endif /* TPM */
LOCAL(copy_buffer): LOCAL(copy_buffer):
/* /*
* We need to save %cx and %si because the startup code in * We need to save %cx and %si because the startup code in
@ -451,6 +460,25 @@ LOCAL(copy_buffer):
popw %ds popw %ds
popa 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 */ /* boot kernel */
jmp *(LOCAL(kernel_address)) jmp *(LOCAL(kernel_address))

View file

@ -19,6 +19,8 @@
#include <grub/symbol.h> #include <grub/symbol.h>
#include <grub/machine/boot.h> #include <grub/machine/boot.h>
#define TPM 1
/* /*
* defines for the code go here * defines for the code go here
*/ */
@ -58,6 +60,21 @@ _start:
/* this sets up for the first run through "bootloop" */ /* this sets up for the first run through "bootloop" */
movw $LOCAL(firstlist), %di 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 */ /* save the sector number of the second sector in %ebp */
movl (%di), %ebp movl (%di), %ebp
@ -295,6 +312,29 @@ LOCAL(copy_buffer):
/* END OF MAIN LOOP */ /* END OF MAIN LOOP */
LOCAL(bootit): 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 */ /* print a newline */
MSG(notification_done) MSG(notification_done)
popw %dx /* this makes sure %dl is our "boot" drive */ popw %dx /* this makes sure %dl is our "boot" drive */
@ -329,6 +369,10 @@ geometry_error_string: .asciz "Geom"
read_error_string: .asciz "Read" read_error_string: .asciz "Read"
general_error_string: .asciz " Error" general_error_string: .asciz " Error"
#ifdef TPM
bytes_to_measure: .long 0
#endif
/* /*
* message: write the string pointed to by %si * message: write the string pointed to by %si
* *

View file

@ -32,6 +32,7 @@
#include <grub/env.h> #include <grub/env.h>
#include <grub/cache.h> #include <grub/cache.h>
#include <grub/i18n.h> #include <grub/i18n.h>
#include <grub/tpm.h>
/* Platforms where modules are in a readonly area of memory. */ /* Platforms where modules are in a readonly area of memory. */
#if defined(GRUB_MACHINE_QEMU) #if defined(GRUB_MACHINE_QEMU)
@ -723,6 +724,8 @@ grub_dl_load_file (const char *filename)
opens of the same device. */ opens of the same device. */
grub_file_close (file); grub_file_close (file);
grub_tpm_measure(core, size, GRUB_TPM_PCR, filename);
mod = grub_dl_load_core (core, size); mod = grub_dl_load_core (core, size);
grub_free (core); grub_free (core);
if (! mod) if (! mod)

282
grub-core/kern/efi/tpm.c Normal file
View file

@ -0,0 +1,282 @@
#include <grub/err.h>
#include <grub/i18n.h>
#include <grub/efi/api.h>
#include <grub/efi/efi.h>
#include <grub/efi/tpm.h>
#include <grub/mm.h>
#include <grub/tpm.h>
#include <grub/term.h>
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);
}
}

View file

@ -0,0 +1,132 @@
#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
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, &regs);
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, &regs);
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, &regs);
grub_free(event);
if (regs.eax)
return grub_error (GRUB_ERR_IO, N_("TPM error %x\n"), regs.eax);
return 0;
}

13
grub-core/kern/tpm.c Normal file
View file

@ -0,0 +1,13 @@
#include <grub/err.h>
#include <grub/i18n.h>
#include <grub/misc.h>
#include <grub/mm.h>
#include <grub/tpm.h>
#include <grub/term.h>
grub_err_t
grub_tpm_measure (unsigned char *buf, grub_size_t size, grub_uint8_t pcr,
const char *description)
{
return grub_tpm_log_event(buf, size, pcr, description);
}

View file

@ -19,6 +19,7 @@
#include <grub/lib/cmdline.h> #include <grub/lib/cmdline.h>
#include <grub/misc.h> #include <grub/misc.h>
#include <grub/tpm.h>
static unsigned int check_arg (char *c, int *has_space) 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; int i, space;
unsigned int arg_size; unsigned int arg_size;
char *c; char *c, *orig = buf;
for (i = 0; i < argc; i++) for (i = 0; i < argc; i++)
{ {
@ -104,5 +105,8 @@ int grub_create_loader_cmdline (int argc, char *argv[], char *buf,
*buf = 0; *buf = 0;
grub_tpm_measure ((void *)orig, grub_strlen (orig), GRUB_CMDLINE_PCR,
"Kernel Commandline");
return i; return i;
} }

View file

@ -26,6 +26,7 @@
#include <grub/i18n.h> #include <grub/i18n.h>
#include <grub/lib/cmdline.h> #include <grub/lib/cmdline.h>
#include <grub/efi/efi.h> #include <grub/efi/efi.h>
#include <grub/tpm.h>
#include "../verity-hash.h" #include "../verity-hash.h"
@ -168,6 +169,7 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
argv[i]); argv[i]);
goto fail; goto fail;
} }
grub_tpm_measure (ptr, cursize, GRUB_INITRD_PCR, "UEFI Linux initrd");
ptr += cursize; ptr += cursize;
grub_memset (ptr, 0, ALIGN_UP_OVERHEAD (cursize, 4)); grub_memset (ptr, 0, ALIGN_UP_OVERHEAD (cursize, 4));
ptr += ALIGN_UP_OVERHEAD (cursize, 4); ptr += ALIGN_UP_OVERHEAD (cursize, 4);
@ -193,7 +195,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
grub_file_t file = 0; grub_file_t file = 0;
struct linux_kernel_header lh; struct linux_kernel_header lh;
grub_ssize_t len, start, filelen; grub_ssize_t len, start, filelen;
void *kernel; void *kernel = NULL;
grub_dl_ref (my_mod); grub_dl_ref (my_mod);
@ -223,6 +225,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
goto fail; goto fail;
} }
grub_tpm_measure (kernel, filelen, GRUB_KERNEL_PCR, "UEFI Linux kernel");
if (! grub_linuxefi_secure_validate (kernel, filelen)) if (! grub_linuxefi_secure_validate (kernel, filelen))
{ {
grub_error (GRUB_ERR_INVALID_COMMAND, N_("%s has invalid signature"), argv[0]); grub_error (GRUB_ERR_INVALID_COMMAND, N_("%s has invalid signature"), argv[0]);
@ -230,10 +234,6 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
goto fail; goto fail;
} }
grub_file_seek (file, 0);
grub_free(kernel);
params = grub_efi_allocate_pages_max (0x3fffffff, BYTES_TO_PAGES(16384)); params = grub_efi_allocate_pages_max (0x3fffffff, BYTES_TO_PAGES(16384));
if (! params) if (! params)
@ -242,15 +242,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
goto fail; goto fail;
} }
memset (params, 0, 16384); grub_memset (params, 0, 16384);
if (grub_file_read (file, &lh, sizeof (lh)) != sizeof (lh)) grub_memcpy (&lh, kernel, sizeof (lh));
{
if (!grub_errno)
grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
argv[0]);
goto fail;
}
if (lh.boot_flag != grub_cpu_to_le16 (0xaa55)) if (lh.boot_flag != grub_cpu_to_le16 (0xaa55))
{ {
@ -311,27 +305,12 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
goto fail; goto fail;
} }
if (grub_file_seek (file, start) == (grub_off_t) -1) grub_memcpy (kernel_mem, (char *)kernel + start, len);
{ grub_loader_set (grub_linuxefi_boot, grub_linuxefi_unload, 0);
grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), loaded=1;
argv[0]);
goto fail;
}
if (grub_file_read (file, kernel_mem, len) != len && !grub_errno) lh.code32_start = (grub_uint32_t)(grub_uint64_t) kernel_mem;
{ grub_memcpy (params, &lh, 2 * 512);
grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
argv[0]);
}
if (grub_errno == GRUB_ERR_NONE)
{
grub_loader_set (grub_linuxefi_boot, grub_linuxefi_unload, 0);
loaded = 1;
lh.code32_start = (grub_uint32_t)(grub_uint64_t) kernel_mem;
}
memcpy(params, &lh, 2 * 512);
params->type_of_loader = 0x21; params->type_of_loader = 0x21;
@ -340,6 +319,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
if (file) if (file)
grub_file_close (file); grub_file_close (file);
grub_free (kernel);
if (grub_errno != GRUB_ERR_NONE) if (grub_errno != GRUB_ERR_NONE)
{ {
grub_dl_unref (my_mod); grub_dl_unref (my_mod);

View file

@ -35,6 +35,7 @@
#include <grub/i18n.h> #include <grub/i18n.h>
#include <grub/lib/cmdline.h> #include <grub/lib/cmdline.h>
#include <grub/linux.h> #include <grub/linux.h>
#include <grub/tpm.h>
#include "verity-hash.h" #include "verity-hash.h"
GRUB_MOD_LICENSE ("GPLv3+"); GRUB_MOD_LICENSE ("GPLv3+");
@ -681,12 +682,13 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
grub_file_t file = 0; grub_file_t file = 0;
struct linux_kernel_header lh; struct linux_kernel_header lh;
grub_uint8_t setup_sects; 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; grub_ssize_t len;
int i; int i;
grub_size_t align, min_align; grub_size_t align, min_align;
int relocatable; int relocatable;
grub_uint64_t preferred_address = GRUB_LINUX_BZIMAGE_ADDR; grub_uint64_t preferred_address = GRUB_LINUX_BZIMAGE_ADDR;
grub_uint8_t *kernel = NULL;
grub_dl_ref (my_mod); grub_dl_ref (my_mod);
@ -700,7 +702,15 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
if (! file) if (! file)
goto fail; 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) if (!grub_errno)
grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
@ -708,6 +718,12 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
goto fail; goto fail;
} }
grub_tpm_measure (kernel, len, GRUB_KERNEL_PCR, "Linux Kernel");
grub_memcpy (&lh, kernel, sizeof (lh));
kernel_offset = sizeof (lh);
if (lh.boot_flag != grub_cpu_to_le16_compile_time (0xaa55)) if (lh.boot_flag != grub_cpu_to_le16_compile_time (0xaa55))
{ {
grub_error (GRUB_ERR_BAD_OS, "invalid magic number"); grub_error (GRUB_ERR_BAD_OS, "invalid magic number");
@ -807,13 +823,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
linux_params.ps_mouse = linux_params.padding10 = 0; linux_params.ps_mouse = linux_params.padding10 = 0;
len = sizeof (linux_params) - sizeof (lh); len = sizeof (linux_params) - sizeof (lh);
if (grub_file_read (file, (char *) &linux_params + sizeof (lh), len) != len)
{ grub_memcpy (&linux_params + sizeof (lh), kernel + kernel_offset, len);
if (!grub_errno) kernel_offset += len;
grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
argv[0]);
goto fail;
}
linux_params.type_of_loader = GRUB_LINUX_BOOT_LOADER_TYPE; linux_params.type_of_loader = GRUB_LINUX_BOOT_LOADER_TYPE;
@ -872,7 +884,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
/* The other parameters are filled when booting. */ /* 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", grub_dprintf ("linux", "bzImage, setup=0x%x, size=0x%x\n",
(unsigned) real_size, (unsigned) prot_size); (unsigned) real_size, (unsigned) prot_size);
@ -1018,9 +1030,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
grub_pass_verity_hash(&lh, linux_cmdline); grub_pass_verity_hash(&lh, linux_cmdline);
len = prot_file_size; len = prot_file_size;
if (grub_file_read (file, prot_mode_mem, len) != len && !grub_errno) grub_memcpy (prot_mode_mem, kernel + kernel_offset, len);
grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), kernel_offset += len;
argv[0]);
if (grub_errno == GRUB_ERR_NONE) if (grub_errno == GRUB_ERR_NONE)
{ {
@ -1031,6 +1042,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
fail: fail:
grub_free (kernel);
if (file) if (file)
grub_file_close (file); grub_file_close (file);

View file

@ -36,6 +36,7 @@
#include <grub/net.h> #include <grub/net.h>
#include <grub/i18n.h> #include <grub/i18n.h>
#include <grub/lib/cmdline.h> #include <grub/lib/cmdline.h>
#include <grub/tpm.h>
#ifdef GRUB_MACHINE_EFI #ifdef GRUB_MACHINE_EFI
#include <grub/efi/efi.h> #include <grub/efi/efi.h>
@ -164,6 +165,8 @@ grub_multiboot_load (grub_file_t file, const char *filename)
return grub_errno; return grub_errno;
} }
grub_tpm_measure((unsigned char*)buffer, len, GRUB_KERNEL_PCR, filename);
header = find_header (buffer, len); header = find_header (buffer, len);
if (header == 0) if (header == 0)

View file

@ -35,6 +35,7 @@
#include <grub/i386/floppy.h> #include <grub/i386/floppy.h>
#include <grub/lib/cmdline.h> #include <grub/lib/cmdline.h>
#include <grub/linux.h> #include <grub/linux.h>
#include <grub/tpm.h>
GRUB_MOD_LICENSE ("GPLv3+"); GRUB_MOD_LICENSE ("GPLv3+");
@ -123,13 +124,14 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
grub_file_t file = 0; grub_file_t file = 0;
struct linux_kernel_header lh; struct linux_kernel_header lh;
grub_uint8_t setup_sects; grub_uint8_t setup_sects;
grub_size_t real_size; grub_size_t real_size, kernel_offset = 0;
grub_ssize_t len; grub_ssize_t len;
int i; int i;
char *grub_linux_prot_chunk; char *grub_linux_prot_chunk;
int grub_linux_is_bzimage; int grub_linux_is_bzimage;
grub_addr_t grub_linux_prot_target; grub_addr_t grub_linux_prot_target;
grub_err_t err; grub_err_t err;
grub_uint8_t *kernel = NULL;
grub_dl_ref (my_mod); grub_dl_ref (my_mod);
@ -143,7 +145,15 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
if (! file) if (! file)
goto fail; 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) if (!grub_errno)
grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
@ -151,6 +161,11 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
goto fail; goto fail;
} }
grub_tpm_measure (kernel, len, GRUB_KERNEL_PCR, "BIOS Linux Kernel");
grub_memcpy (&lh, kernel, sizeof (lh));
kernel_offset = sizeof (lh);
if (lh.boot_flag != grub_cpu_to_le16_compile_time (0xaa55)) if (lh.boot_flag != grub_cpu_to_le16_compile_time (0xaa55))
{ {
grub_error (GRUB_ERR_BAD_OS, "invalid magic number"); grub_error (GRUB_ERR_BAD_OS, "invalid magic number");
@ -314,13 +329,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
grub_memmove (grub_linux_real_chunk, &lh, sizeof (lh)); grub_memmove (grub_linux_real_chunk, &lh, sizeof (lh));
len = real_size + GRUB_DISK_SECTOR_SIZE - sizeof (lh); len = real_size + GRUB_DISK_SECTOR_SIZE - sizeof (lh);
if (grub_file_read (file, grub_linux_real_chunk + sizeof (lh), len) != len) grub_memcpy (grub_linux_real_chunk + sizeof (lh), kernel + kernel_offset,
{ len);
if (!grub_errno) kernel_offset += len;
grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
argv[0]);
goto fail;
}
if (lh.header != grub_cpu_to_le32_compile_time (GRUB_LINUX_MAGIC_SIGNATURE) if (lh.header != grub_cpu_to_le32_compile_time (GRUB_LINUX_MAGIC_SIGNATURE)
|| grub_le_to_cpu16 (lh.version) < 0x0200) || grub_le_to_cpu16 (lh.version) < 0x0200)
@ -355,10 +366,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
} }
len = grub_linux16_prot_size; len = grub_linux16_prot_size;
if (grub_file_read (file, grub_linux_prot_chunk, grub_linux16_prot_size) grub_memcpy (grub_linux_prot_chunk, kernel + kernel_offset, len);
!= (grub_ssize_t) grub_linux16_prot_size && !grub_errno) kernel_offset += len;
grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
argv[0]);
if (grub_errno == GRUB_ERR_NONE) if (grub_errno == GRUB_ERR_NONE)
{ {
@ -368,6 +377,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
fail: fail:
grub_free (kernel);
if (file) if (file)
grub_file_close (file); grub_file_close (file);

View file

@ -4,6 +4,7 @@
#include <grub/misc.h> #include <grub/misc.h>
#include <grub/file.h> #include <grub/file.h>
#include <grub/mm.h> #include <grub/mm.h>
#include <grub/tpm.h>
struct newc_head struct newc_head
{ {
@ -288,6 +289,7 @@ grub_initrd_load (struct grub_linux_initrd_context *initrd_ctx,
grub_initrd_close (initrd_ctx); grub_initrd_close (initrd_ctx);
return grub_errno; return grub_errno;
} }
grub_tpm_measure (ptr, cursize, GRUB_INITRD_PCR, "Linux Initrd");
ptr += cursize; ptr += cursize;
} }
if (newc) if (newc)

View file

@ -42,6 +42,7 @@
#include <grub/video.h> #include <grub/video.h>
#include <grub/memory.h> #include <grub/memory.h>
#include <grub/i18n.h> #include <grub/i18n.h>
#include <grub/tpm.h>
GRUB_MOD_LICENSE ("GPLv3+"); GRUB_MOD_LICENSE ("GPLv3+");
@ -384,6 +385,7 @@ grub_cmd_module (grub_command_t cmd __attribute__ ((unused)),
} }
grub_file_close (file); grub_file_close (file);
grub_tpm_measure (module, size, GRUB_KERNEL_PCR, argv[0]);
return GRUB_ERR_NONE; return GRUB_ERR_NONE;
} }

View file

@ -36,6 +36,7 @@
#include <grub/i18n.h> #include <grub/i18n.h>
#include <grub/net.h> #include <grub/net.h>
#include <grub/lib/cmdline.h> #include <grub/lib/cmdline.h>
#include <grub/tpm.h>
#if defined (GRUB_MACHINE_EFI) #if defined (GRUB_MACHINE_EFI)
#include <grub/efi/efi.h> #include <grub/efi/efi.h>
@ -126,6 +127,8 @@ grub_multiboot_load (grub_file_t file, const char *filename)
COMPILE_TIME_ASSERT (MULTIBOOT_HEADER_ALIGN % 4 == 0); COMPILE_TIME_ASSERT (MULTIBOOT_HEADER_ALIGN % 4 == 0);
grub_tpm_measure ((unsigned char *)buffer, len, GRUB_KERNEL_PCR, filename);
header = find_header (buffer, len); header = find_header (buffer, len);
if (header == 0) if (header == 0)

View file

@ -27,6 +27,7 @@
#include <grub/normal.h> #include <grub/normal.h>
#include <grub/extcmd.h> #include <grub/extcmd.h>
#include <grub/i18n.h> #include <grub/i18n.h>
#include <grub/tpm.h>
/* Max digits for a char is 3 (0xFF is 255), similarly for an int it /* 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. */ is sizeof (int) * 3, and one extra for a possible -ve sign. */
@ -933,8 +934,9 @@ grub_script_execute_cmdline (struct grub_script_cmd *cmd)
grub_err_t ret = 0; grub_err_t ret = 0;
grub_script_function_t func = 0; grub_script_function_t func = 0;
char errnobuf[18]; char errnobuf[18];
char *cmdname; char *cmdname, *cmdstring;
int argc; int argc, offset = 0, cmdlen = 0;
unsigned int i;
char **args; char **args;
int invert; int invert;
struct grub_script_argv argv = { 0, 0, 0 }; struct grub_script_argv argv = { 0, 0, 0 };
@ -943,6 +945,25 @@ grub_script_execute_cmdline (struct grub_script_cmd *cmd)
if (grub_script_arglist_to_argv (cmdline->arglist, &argv) || ! argv.args[0]) if (grub_script_arglist_to_argv (cmdline->arglist, &argv) || ! argv.args[0])
return grub_errno; 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_COMMAND_PCR,
cmdstring);
grub_free(cmdstring);
invert = 0; invert = 0;
argc = argv.argc - 1; argc = argv.argc - 1;
args = argv.args + 1; args = argv.args + 1;

153
include/grub/efi/tpm.h Normal file
View file

@ -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 <http://www.gnu.org/licenses/>.
*/
#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

92
include/grub/tpm.h Normal file
View file

@ -0,0 +1,92 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#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_TPM_PCR 9
#define GRUB_KERNEL_PCR 10
#define GRUB_INITRD_PCR 11
#define GRUB_CMDLINE_PCR 12
#define GRUB_COMMAND_PCR 13
#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 *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