commit
d4bc2bf02f
19 changed files with 854 additions and 63 deletions
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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))
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
*
|
*
|
||||||
|
|
|
@ -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
282
grub-core/kern/efi/tpm.c
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
132
grub-core/kern/i386/pc/tpm.c
Normal file
132
grub-core/kern/i386/pc/tpm.c
Normal 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, ®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;
|
||||||
|
}
|
13
grub-core/kern/tpm.c
Normal file
13
grub-core/kern/tpm.c
Normal 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);
|
||||||
|
}
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
|
|
||||||
argv[0]);
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (grub_file_read (file, kernel_mem, len) != len && !grub_errno)
|
|
||||||
{
|
|
||||||
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);
|
grub_loader_set (grub_linuxefi_boot, grub_linuxefi_unload, 0);
|
||||||
loaded = 1;
|
loaded=1;
|
||||||
lh.code32_start = (grub_uint32_t)(grub_uint64_t) kernel_mem;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(params, &lh, 2 * 512);
|
lh.code32_start = (grub_uint32_t)(grub_uint64_t) kernel_mem;
|
||||||
|
grub_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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
153
include/grub/efi/tpm.h
Normal 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
92
include/grub/tpm.h
Normal 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
|
Loading…
Reference in a new issue