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/mm_private.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/net.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/tpm.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/memory.h
|
||||
|
||||
if COND_i386_pc
|
||||
|
|
|
@ -126,6 +126,7 @@ kernel = {
|
|||
common = kern/rescue_parser.c;
|
||||
common = kern/rescue_reader.c;
|
||||
common = kern/term.c;
|
||||
common = kern/tpm.c;
|
||||
|
||||
noemu = kern/compiler-rt.c;
|
||||
noemu = kern/mm.c;
|
||||
|
@ -173,6 +174,7 @@ kernel = {
|
|||
efi = term/efi/console.c;
|
||||
efi = kern/acpi.c;
|
||||
efi = kern/efi/acpi.c;
|
||||
efi = kern/efi/tpm.c;
|
||||
i386_coreboot = kern/i386/pc/acpi.c;
|
||||
i386_multiboot = kern/i386/pc/acpi.c;
|
||||
i386_coreboot = kern/acpi.c;
|
||||
|
@ -217,6 +219,7 @@ kernel = {
|
|||
|
||||
i386_pc = kern/i386/pc/init.c;
|
||||
i386_pc = kern/i386/pc/mmap.c;
|
||||
i386_pc = kern/i386/pc/tpm.c;
|
||||
i386_pc = term/i386/pc/console.c;
|
||||
|
||||
i386_qemu = bus/pci.c;
|
||||
|
|
|
@ -24,11 +24,14 @@
|
|||
* defines for the code go here
|
||||
*/
|
||||
|
||||
#define TPM 1
|
||||
|
||||
/* Print message string */
|
||||
#define MSG(x) movw $x, %si; call LOCAL(message)
|
||||
#define ERR(x) movw $x, %si; jmp LOCAL(error_message)
|
||||
|
||||
.macro floppy
|
||||
#ifndef TPM
|
||||
part_start:
|
||||
|
||||
LOCAL(probe_values):
|
||||
|
@ -85,6 +88,7 @@ fd_probe_error_string: .asciz "Floppy"
|
|||
movb MACRO_DOLLAR(79), %ch
|
||||
|
||||
jmp LOCAL(final_init)
|
||||
#endif
|
||||
.endm
|
||||
|
||||
.macro scratch
|
||||
|
@ -255,6 +259,7 @@ real_start:
|
|||
/* set %si to the disk address packet */
|
||||
movw $disk_address_packet, %si
|
||||
|
||||
#ifndef TPM
|
||||
/* check if LBA is supported */
|
||||
movb $0x41, %ah
|
||||
movw $0x55aa, %bx
|
||||
|
@ -274,6 +279,7 @@ real_start:
|
|||
|
||||
andw $1, %cx
|
||||
jz LOCAL(chs_mode)
|
||||
#endif
|
||||
|
||||
LOCAL(lba_mode):
|
||||
xorw %ax, %ax
|
||||
|
@ -317,6 +323,9 @@ LOCAL(lba_mode):
|
|||
jmp LOCAL(copy_buffer)
|
||||
|
||||
LOCAL(chs_mode):
|
||||
#ifdef TPM
|
||||
jmp LOCAL(general_error)
|
||||
#else
|
||||
/*
|
||||
* Determine the hard disk geometry from the BIOS!
|
||||
* We do this first, so that LS-120 IDE floppies work correctly.
|
||||
|
@ -428,7 +437,7 @@ setup_sectors:
|
|||
jc LOCAL(read_error)
|
||||
|
||||
movw %es, %bx
|
||||
|
||||
#endif /* TPM */
|
||||
LOCAL(copy_buffer):
|
||||
/*
|
||||
* We need to save %cx and %si because the startup code in
|
||||
|
@ -451,6 +460,25 @@ LOCAL(copy_buffer):
|
|||
popw %ds
|
||||
popa
|
||||
|
||||
#ifdef TPM
|
||||
pusha
|
||||
|
||||
movw $0xBB00, %ax /* TCG_StatusCheck */
|
||||
int $0x1A
|
||||
test %eax, %eax
|
||||
jnz boot /* No TPM or TPM deactivated */
|
||||
|
||||
movw $0xBB07, %ax /* TCG_CompactHashLogExtendEvent */
|
||||
movw $GRUB_BOOT_MACHINE_KERNEL_ADDR, %di
|
||||
xorl %esi, %esi
|
||||
movl $0x41504354, %ebx /* TCPA */
|
||||
movl $0x200, %ecx /* Measure 512 bytes */
|
||||
movl $0x8, %edx /* PCR 8 */
|
||||
int $0x1A
|
||||
|
||||
popa
|
||||
#endif
|
||||
boot:
|
||||
/* boot kernel */
|
||||
jmp *(LOCAL(kernel_address))
|
||||
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
#include <grub/symbol.h>
|
||||
#include <grub/machine/boot.h>
|
||||
|
||||
#define TPM 1
|
||||
|
||||
/*
|
||||
* defines for the code go here
|
||||
*/
|
||||
|
@ -58,6 +60,21 @@ _start:
|
|||
/* this sets up for the first run through "bootloop" */
|
||||
movw $LOCAL(firstlist), %di
|
||||
|
||||
#ifdef TPM
|
||||
/* clear EAX to remove potential garbage */
|
||||
xorl %eax, %eax
|
||||
/* 8(%di) = number of sectors to read */
|
||||
movw 8(%di), %ax
|
||||
|
||||
/* Multiply number of sectors to read with 512 bytes. EAX is 32bit
|
||||
* which is large enough to hold values of up to 4GB. I doubt there
|
||||
* will ever be a core.img larger than that. ;-) */
|
||||
shll $9, %eax
|
||||
|
||||
/* write result to bytes_to_measure var */
|
||||
movl %eax, bytes_to_measure
|
||||
#endif
|
||||
|
||||
/* save the sector number of the second sector in %ebp */
|
||||
movl (%di), %ebp
|
||||
|
||||
|
@ -295,6 +312,29 @@ LOCAL(copy_buffer):
|
|||
/* END OF MAIN LOOP */
|
||||
|
||||
LOCAL(bootit):
|
||||
#ifdef TPM
|
||||
pusha
|
||||
movw $0xBB07, %ax /* TCG_CompactHashLogExtendEvent */
|
||||
|
||||
movw $0x0, %bx
|
||||
movw %bx, %es
|
||||
|
||||
/* We've already measured the first 512 bytes, now measure the rest */
|
||||
xorl %edi, %edi
|
||||
movw $(GRUB_BOOT_MACHINE_KERNEL_ADDR + 0x200), %di
|
||||
|
||||
movl $0x41504354, %ebx /* EBX = "TCPA" */
|
||||
|
||||
/* %ecx = The length, in bytes, of the buffer to measure */
|
||||
movl $bytes_to_measure, %esi
|
||||
movl (%esi), %ecx
|
||||
xorl %esi, %esi
|
||||
movl $0x9, %edx /* PCR 9 */
|
||||
|
||||
int $0x1A
|
||||
|
||||
popa
|
||||
#endif
|
||||
/* print a newline */
|
||||
MSG(notification_done)
|
||||
popw %dx /* this makes sure %dl is our "boot" drive */
|
||||
|
@ -329,6 +369,10 @@ geometry_error_string: .asciz "Geom"
|
|||
read_error_string: .asciz "Read"
|
||||
general_error_string: .asciz " Error"
|
||||
|
||||
#ifdef TPM
|
||||
bytes_to_measure: .long 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
* message: write the string pointed to by %si
|
||||
*
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include <grub/env.h>
|
||||
#include <grub/cache.h>
|
||||
#include <grub/i18n.h>
|
||||
#include <grub/tpm.h>
|
||||
|
||||
/* Platforms where modules are in a readonly area of memory. */
|
||||
#if defined(GRUB_MACHINE_QEMU)
|
||||
|
@ -723,6 +724,8 @@ grub_dl_load_file (const char *filename)
|
|||
opens of the same device. */
|
||||
grub_file_close (file);
|
||||
|
||||
grub_tpm_measure(core, size, GRUB_TPM_PCR, filename);
|
||||
|
||||
mod = grub_dl_load_core (core, size);
|
||||
grub_free (core);
|
||||
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/misc.h>
|
||||
#include <grub/tpm.h>
|
||||
|
||||
static unsigned int check_arg (char *c, int *has_space)
|
||||
{
|
||||
|
@ -67,7 +68,7 @@ int grub_create_loader_cmdline (int argc, char *argv[], char *buf,
|
|||
{
|
||||
int i, space;
|
||||
unsigned int arg_size;
|
||||
char *c;
|
||||
char *c, *orig = buf;
|
||||
|
||||
for (i = 0; i < argc; i++)
|
||||
{
|
||||
|
@ -104,5 +105,8 @@ int grub_create_loader_cmdline (int argc, char *argv[], char *buf,
|
|||
|
||||
*buf = 0;
|
||||
|
||||
grub_tpm_measure ((void *)orig, grub_strlen (orig), GRUB_CMDLINE_PCR,
|
||||
"Kernel Commandline");
|
||||
|
||||
return i;
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include <grub/i18n.h>
|
||||
#include <grub/lib/cmdline.h>
|
||||
#include <grub/efi/efi.h>
|
||||
#include <grub/tpm.h>
|
||||
|
||||
#include "../verity-hash.h"
|
||||
|
||||
|
@ -168,6 +169,7 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
|
|||
argv[i]);
|
||||
goto fail;
|
||||
}
|
||||
grub_tpm_measure (ptr, cursize, GRUB_INITRD_PCR, "UEFI Linux initrd");
|
||||
ptr += cursize;
|
||||
grub_memset (ptr, 0, 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;
|
||||
struct linux_kernel_header lh;
|
||||
grub_ssize_t len, start, filelen;
|
||||
void *kernel;
|
||||
void *kernel = NULL;
|
||||
|
||||
grub_dl_ref (my_mod);
|
||||
|
||||
|
@ -223,6 +225,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
|
|||
goto fail;
|
||||
}
|
||||
|
||||
grub_tpm_measure (kernel, filelen, GRUB_KERNEL_PCR, "UEFI Linux kernel");
|
||||
|
||||
if (! grub_linuxefi_secure_validate (kernel, filelen))
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
grub_file_seek (file, 0);
|
||||
|
||||
grub_free(kernel);
|
||||
|
||||
params = grub_efi_allocate_pages_max (0x3fffffff, BYTES_TO_PAGES(16384));
|
||||
|
||||
if (! params)
|
||||
|
@ -242,15 +242,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
|
|||
goto fail;
|
||||
}
|
||||
|
||||
memset (params, 0, 16384);
|
||||
grub_memset (params, 0, 16384);
|
||||
|
||||
if (grub_file_read (file, &lh, sizeof (lh)) != sizeof (lh))
|
||||
{
|
||||
if (!grub_errno)
|
||||
grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
|
||||
argv[0]);
|
||||
goto fail;
|
||||
}
|
||||
grub_memcpy (&lh, kernel, sizeof (lh));
|
||||
|
||||
if (lh.boot_flag != grub_cpu_to_le16 (0xaa55))
|
||||
{
|
||||
|
@ -311,27 +305,12 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
|
|||
goto fail;
|
||||
}
|
||||
|
||||
if (grub_file_seek (file, start) == (grub_off_t) -1)
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
|
||||
argv[0]);
|
||||
goto fail;
|
||||
}
|
||||
grub_memcpy (kernel_mem, (char *)kernel + start, len);
|
||||
grub_loader_set (grub_linuxefi_boot, grub_linuxefi_unload, 0);
|
||||
loaded=1;
|
||||
|
||||
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);
|
||||
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;
|
||||
|
||||
|
@ -340,6 +319,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
|
|||
if (file)
|
||||
grub_file_close (file);
|
||||
|
||||
grub_free (kernel);
|
||||
|
||||
if (grub_errno != GRUB_ERR_NONE)
|
||||
{
|
||||
grub_dl_unref (my_mod);
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include <grub/i18n.h>
|
||||
#include <grub/lib/cmdline.h>
|
||||
#include <grub/linux.h>
|
||||
#include <grub/tpm.h>
|
||||
|
||||
#include "verity-hash.h"
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
@ -681,12 +682,13 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
|
|||
grub_file_t file = 0;
|
||||
struct linux_kernel_header lh;
|
||||
grub_uint8_t setup_sects;
|
||||
grub_size_t real_size, prot_size, prot_file_size;
|
||||
grub_size_t real_size, prot_size, prot_file_size, kernel_offset;
|
||||
grub_ssize_t len;
|
||||
int i;
|
||||
grub_size_t align, min_align;
|
||||
int relocatable;
|
||||
grub_uint64_t preferred_address = GRUB_LINUX_BZIMAGE_ADDR;
|
||||
grub_uint8_t *kernel = NULL;
|
||||
|
||||
grub_dl_ref (my_mod);
|
||||
|
||||
|
@ -700,7 +702,15 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
|
|||
if (! file)
|
||||
goto fail;
|
||||
|
||||
if (grub_file_read (file, &lh, sizeof (lh)) != sizeof (lh))
|
||||
len = grub_file_size (file);
|
||||
kernel = grub_malloc (len);
|
||||
if (!kernel)
|
||||
{
|
||||
grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("cannot allocate kernel buffer"));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (grub_file_read (file, kernel, len) != len)
|
||||
{
|
||||
if (!grub_errno)
|
||||
grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
|
||||
|
@ -708,6 +718,12 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
|
|||
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))
|
||||
{
|
||||
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;
|
||||
|
||||
len = sizeof (linux_params) - sizeof (lh);
|
||||
if (grub_file_read (file, (char *) &linux_params + sizeof (lh), len) != len)
|
||||
{
|
||||
if (!grub_errno)
|
||||
grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
|
||||
argv[0]);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
grub_memcpy (&linux_params + sizeof (lh), kernel + kernel_offset, len);
|
||||
kernel_offset += len;
|
||||
|
||||
linux_params.type_of_loader = GRUB_LINUX_BOOT_LOADER_TYPE;
|
||||
|
||||
|
@ -872,7 +884,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
|
|||
|
||||
/* The other parameters are filled when booting. */
|
||||
|
||||
grub_file_seek (file, real_size + GRUB_DISK_SECTOR_SIZE);
|
||||
kernel_offset = real_size + GRUB_DISK_SECTOR_SIZE;
|
||||
|
||||
grub_dprintf ("linux", "bzImage, setup=0x%x, size=0x%x\n",
|
||||
(unsigned) real_size, (unsigned) prot_size);
|
||||
|
@ -1018,9 +1030,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
|
|||
|
||||
grub_pass_verity_hash(&lh, linux_cmdline);
|
||||
len = prot_file_size;
|
||||
if (grub_file_read (file, prot_mode_mem, len) != len && !grub_errno)
|
||||
grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
|
||||
argv[0]);
|
||||
grub_memcpy (prot_mode_mem, kernel + kernel_offset, len);
|
||||
kernel_offset += len;
|
||||
|
||||
if (grub_errno == GRUB_ERR_NONE)
|
||||
{
|
||||
|
@ -1031,6 +1042,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
|
|||
|
||||
fail:
|
||||
|
||||
grub_free (kernel);
|
||||
|
||||
if (file)
|
||||
grub_file_close (file);
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
#include <grub/net.h>
|
||||
#include <grub/i18n.h>
|
||||
#include <grub/lib/cmdline.h>
|
||||
#include <grub/tpm.h>
|
||||
|
||||
#ifdef GRUB_MACHINE_EFI
|
||||
#include <grub/efi/efi.h>
|
||||
|
@ -164,6 +165,8 @@ grub_multiboot_load (grub_file_t file, const char *filename)
|
|||
return grub_errno;
|
||||
}
|
||||
|
||||
grub_tpm_measure((unsigned char*)buffer, len, GRUB_KERNEL_PCR, filename);
|
||||
|
||||
header = find_header (buffer, len);
|
||||
|
||||
if (header == 0)
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include <grub/i386/floppy.h>
|
||||
#include <grub/lib/cmdline.h>
|
||||
#include <grub/linux.h>
|
||||
#include <grub/tpm.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
|
@ -123,13 +124,14 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
|
|||
grub_file_t file = 0;
|
||||
struct linux_kernel_header lh;
|
||||
grub_uint8_t setup_sects;
|
||||
grub_size_t real_size;
|
||||
grub_size_t real_size, kernel_offset = 0;
|
||||
grub_ssize_t len;
|
||||
int i;
|
||||
char *grub_linux_prot_chunk;
|
||||
int grub_linux_is_bzimage;
|
||||
grub_addr_t grub_linux_prot_target;
|
||||
grub_err_t err;
|
||||
grub_uint8_t *kernel = NULL;
|
||||
|
||||
grub_dl_ref (my_mod);
|
||||
|
||||
|
@ -143,7 +145,15 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
|
|||
if (! file)
|
||||
goto fail;
|
||||
|
||||
if (grub_file_read (file, &lh, sizeof (lh)) != sizeof (lh))
|
||||
len = grub_file_size (file);
|
||||
kernel = grub_malloc (len);
|
||||
if (!kernel)
|
||||
{
|
||||
grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("cannot allocate kernel buffer"));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (grub_file_read (file, kernel, len) != len)
|
||||
{
|
||||
if (!grub_errno)
|
||||
grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
|
||||
|
@ -151,6 +161,11 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
|
|||
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))
|
||||
{
|
||||
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));
|
||||
|
||||
len = real_size + GRUB_DISK_SECTOR_SIZE - sizeof (lh);
|
||||
if (grub_file_read (file, grub_linux_real_chunk + sizeof (lh), len) != len)
|
||||
{
|
||||
if (!grub_errno)
|
||||
grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
|
||||
argv[0]);
|
||||
goto fail;
|
||||
}
|
||||
grub_memcpy (grub_linux_real_chunk + sizeof (lh), kernel + kernel_offset,
|
||||
len);
|
||||
kernel_offset += len;
|
||||
|
||||
if (lh.header != grub_cpu_to_le32_compile_time (GRUB_LINUX_MAGIC_SIGNATURE)
|
||||
|| grub_le_to_cpu16 (lh.version) < 0x0200)
|
||||
|
@ -355,10 +366,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
|
|||
}
|
||||
|
||||
len = grub_linux16_prot_size;
|
||||
if (grub_file_read (file, grub_linux_prot_chunk, grub_linux16_prot_size)
|
||||
!= (grub_ssize_t) grub_linux16_prot_size && !grub_errno)
|
||||
grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
|
||||
argv[0]);
|
||||
grub_memcpy (grub_linux_prot_chunk, kernel + kernel_offset, len);
|
||||
kernel_offset += len;
|
||||
|
||||
if (grub_errno == GRUB_ERR_NONE)
|
||||
{
|
||||
|
@ -368,6 +377,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
|
|||
|
||||
fail:
|
||||
|
||||
grub_free (kernel);
|
||||
|
||||
if (file)
|
||||
grub_file_close (file);
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include <grub/misc.h>
|
||||
#include <grub/file.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/tpm.h>
|
||||
|
||||
struct newc_head
|
||||
{
|
||||
|
@ -288,6 +289,7 @@ grub_initrd_load (struct grub_linux_initrd_context *initrd_ctx,
|
|||
grub_initrd_close (initrd_ctx);
|
||||
return grub_errno;
|
||||
}
|
||||
grub_tpm_measure (ptr, cursize, GRUB_INITRD_PCR, "Linux Initrd");
|
||||
ptr += cursize;
|
||||
}
|
||||
if (newc)
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
#include <grub/video.h>
|
||||
#include <grub/memory.h>
|
||||
#include <grub/i18n.h>
|
||||
#include <grub/tpm.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
|
@ -384,6 +385,7 @@ grub_cmd_module (grub_command_t cmd __attribute__ ((unused)),
|
|||
}
|
||||
|
||||
grub_file_close (file);
|
||||
grub_tpm_measure (module, size, GRUB_KERNEL_PCR, argv[0]);
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
#include <grub/i18n.h>
|
||||
#include <grub/net.h>
|
||||
#include <grub/lib/cmdline.h>
|
||||
#include <grub/tpm.h>
|
||||
|
||||
#if defined (GRUB_MACHINE_EFI)
|
||||
#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);
|
||||
|
||||
grub_tpm_measure ((unsigned char *)buffer, len, GRUB_KERNEL_PCR, filename);
|
||||
|
||||
header = find_header (buffer, len);
|
||||
|
||||
if (header == 0)
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include <grub/normal.h>
|
||||
#include <grub/extcmd.h>
|
||||
#include <grub/i18n.h>
|
||||
#include <grub/tpm.h>
|
||||
|
||||
/* 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. */
|
||||
|
@ -933,8 +934,9 @@ grub_script_execute_cmdline (struct grub_script_cmd *cmd)
|
|||
grub_err_t ret = 0;
|
||||
grub_script_function_t func = 0;
|
||||
char errnobuf[18];
|
||||
char *cmdname;
|
||||
int argc;
|
||||
char *cmdname, *cmdstring;
|
||||
int argc, offset = 0, cmdlen = 0;
|
||||
unsigned int i;
|
||||
char **args;
|
||||
int invert;
|
||||
struct grub_script_argv argv = { 0, 0, 0 };
|
||||
|
@ -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])
|
||||
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;
|
||||
argc = argv.argc - 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