diff --git a/Makefile b/Makefile index 01f42ec..2546c15 100644 --- a/Makefile +++ b/Makefile @@ -38,14 +38,14 @@ SRCBOTH=misc.c stacks.c output.c string.c block.c cdrom.c disk.c \ SRC16=$(SRCBOTH) SRC32FLAT=$(SRCBOTH) post.c e820map.c malloc.c romfile.c x86.c \ optionroms.c pmm.c font.c boot.c bootsplash.c jpeg.c bmp.c \ - tcgbios.c sha1.c hw/pcidevice.c hw/ahci.c hw/pvscsi.c \ + hw/pcidevice.c hw/ahci.c hw/pvscsi.c \ hw/usb-xhci.c hw/usb-hub.c hw/sdcard.c fw/coreboot.c \ fw/lzmadecode.c fw/multiboot.c fw/csm.c fw/biostables.c \ fw/paravirt.c fw/shadow.c fw/pciinit.c fw/smm.c fw/smp.c \ fw/mtrr.c fw/xen.c fw/acpi.c fw/mptable.c fw/pirtable.c \ fw/smbios.c fw/romfile_loader.c fw/dsdt_parser.c hw/virtio-ring.c \ hw/virtio-pci.c hw/virtio-mmio.c hw/virtio-blk.c hw/virtio-scsi.c \ - hw/tpm_drivers.c hw/nvme.c sha256.c sha512.c + hw/nvme.c SRC32SEG=string.c output.c pcibios.c apm.c stacks.c hw/pci.c hw/serialio.c DIRS=src src/hw src/fw vgasrc diff --git a/src/Kconfig b/src/Kconfig index 332b52d..163ac4a 100644 --- a/src/Kconfig +++ b/src/Kconfig @@ -471,13 +471,6 @@ menu "BIOS interfaces" modified by programs. However, some old DOS high memory managers may require the UMB region to be read-only. - config TCGBIOS - depends on S3_RESUME - bool "TPM support and TCG BIOS extensions" - default y - help - Provide TPM support along with TCG BIOS extensions - endmenu menu "BIOS Tables" diff --git a/src/boot.c b/src/boot.c index 608d346..9959a5a 100644 --- a/src/boot.c +++ b/src/boot.c @@ -20,7 +20,6 @@ #include "std/disk.h" // struct mbr_s #include "string.h" // memset #include "util.h" // irqtimer_calc -#include "tcgbios.h" // tpm_* #include "rf_config.h" /**************************************************************** @@ -699,12 +698,14 @@ interactive_bootmenu(void) return; // skip menu if only one boot device and no TPM - if (RF_CONF_SHOW_BOOT_MENU == 2 && !tpm_can_show_menu() + /* + if (RF_CONF_SHOW_BOOT_MENU == 2 && !hlist_empty(&BootList) && !BootList.first->next) { dprintf(1, "Only one boot device present. Skip boot menu.\n"); printf("\n"); return; } + */ int menukey; if (RF_CONF_OBSCURE_MODE) { @@ -747,9 +748,6 @@ interactive_bootmenu(void) , strtcpy(desc, pos->description, ARRAY_SIZE(desc))); maxmenu++; } - if (tpm_can_show_menu()) { - printf("\nt. TPM Configuration\n"); - } // Get key press. If the menu key is ESC, do not restart boot unless // 1.5 seconds have passed. Otherwise users (trained by years of @@ -765,10 +763,6 @@ interactive_bootmenu(void) scan_code = keystroke >> 8; int key_ascii = keystroke & 0xff; - if (tpm_can_show_menu() && key_ascii == 't') { - printf("\n"); - tpm_menu(); - } if (scan_code == 1) { // ESC printf("\n"); @@ -910,8 +904,6 @@ boot_disk(u8 bootdrv, int checksig) } } - tpm_add_bcv(bootdrv, MAKE_FLATPTR(bootseg, 0), 512); - /* Canonicalize bootseg:bootip */ u16 bootip = (bootseg & 0x0fff) << 4; bootseg &= 0xf000; @@ -936,8 +928,6 @@ boot_cdrom(struct drive_s *drive) u8 bootdrv = CDEmu.emulated_drive; u16 bootseg = CDEmu.load_segment; - tpm_add_cdrom(bootdrv, MAKE_FLATPTR(bootseg, 0), 512); - /* Canonicalize bootseg:bootip */ u16 bootip = (bootseg & 0x0fff) << 4; bootseg &= 0xf000; diff --git a/src/cdrom.c b/src/cdrom.c index a77671a..7ad9de0 100644 --- a/src/cdrom.c +++ b/src/cdrom.c @@ -15,7 +15,6 @@ #include "std/disk.h" // DISK_RET_SUCCESS #include "string.h" // memset #include "util.h" // cdrom_prepboot -#include "tcgbios.h" // tpm_* /**************************************************************** @@ -184,9 +183,6 @@ cdrom_boot(struct drive_s *drive) if (buffer[0x20] != 0x88) return 11; // Bootable - /* measure 2048 bytes (one sector) */ - tpm_add_cdrom_catalog(MAKE_FLATPTR(GET_SEG(SS), buffer), sizeof(buffer)); - // Fill in el-torito cdrom emulation fields. emulated_drive_gf = drive; u8 media = buffer[0x21]; diff --git a/src/clock.c b/src/clock.c index e44e112..6b4cf15 100644 --- a/src/clock.c +++ b/src/clock.c @@ -244,11 +244,7 @@ handle_1a07(struct bregs *regs) static void handle_1abb(struct bregs *regs) { - if (!CONFIG_TCGBIOS) - return; - - dprintf(DEBUG_tcg, "16: Calling tpm_interrupt_handler\n"); - call32(tpm_interrupt_handler32, MAKE_FLATPTR(GET_SEG(SS), regs), 0); + return; } // Unsupported diff --git a/src/hw/tpm_drivers.c b/src/hw/tpm_drivers.c deleted file mode 100644 index 2b5753c..0000000 --- a/src/hw/tpm_drivers.c +++ /dev/null @@ -1,637 +0,0 @@ -// Implementation of a TPM driver for the TPM TIS interface -// -// Copyright (C) 2006-2011 IBM Corporation -// -// Authors: -// Stefan Berger -// -// This file may be distributed under the terms of the GNU LGPLv3 license. - -#include "byteorder.h" // be32_to_cpu -#include "config.h" // CONFIG_TPM_TIS_SHA1THRESHOLD -#include "hw/tpm_drivers.h" // struct tpm_driver -#include "std/tcg.h" // TCG_RESPONSE_TIMEOUT -#include "output.h" // warn_timeout -#include "stacks.h" // yield -#include "string.h" // memcpy -#include "util.h" // timer_calc_usec -#include "x86.h" // readl - -/* low level driver implementation */ -struct tpm_driver { - u32 *timeouts; - u32 *durations; - void (*set_timeouts)(u32 timeouts[4], u32 durations[3]); - u32 (*probe)(void); - TPMVersion (*get_tpm_version)(void); - u32 (*init)(void); - u32 (*activate)(u8 locty); - u32 (*ready)(void); - u32 (*senddata)(const u8 *const data, u32 len); - u32 (*readresp)(u8 *buffer, u32 *len); - u32 (*waitdatavalid)(void); - u32 (*waitrespready)(enum tpmDurationType to_t); -}; - -extern struct tpm_driver tpm_drivers[]; - -#define TIS_DRIVER_IDX 0 -#define CRB_DRIVER_IDX 1 -#define TPM_NUM_DRIVERS 2 - -#define TPM_INVALID_DRIVER 0xf - -static const u32 tis_default_timeouts[4] = { - TIS_DEFAULT_TIMEOUT_A, - TIS_DEFAULT_TIMEOUT_B, - TIS_DEFAULT_TIMEOUT_C, - TIS_DEFAULT_TIMEOUT_D, -}; - -static const u32 tpm_default_durations[3] = { - TPM_DEFAULT_DURATION_SHORT, - TPM_DEFAULT_DURATION_MEDIUM, - TPM_DEFAULT_DURATION_LONG, -}; - -/* determined values */ -static u32 tpm_default_dur[3]; -static u32 tpm_default_to[4]; - -static u32 crb_cmd_size; -static void *crb_cmd; -static u32 crb_resp_size; -static void *crb_resp; - -static u32 wait_reg8(u8* reg, u32 time, u8 mask, u8 expect) -{ - if (!CONFIG_TCGBIOS) - return 0; - - u32 rc = 1; - u32 end = timer_calc_usec(time); - - for (;;) { - u8 value = readl(reg); - if ((value & mask) == expect) { - rc = 0; - break; - } - if (timer_check(end)) { - warn_timeout(); - break; - } - yield(); - } - return rc; -} - -static u32 tis_wait_access(u8 locty, u32 time, u8 mask, u8 expect) -{ - return wait_reg8(TIS_REG(locty, TIS_REG_ACCESS), time, mask, expect); -} - -static u32 tis_wait_sts(u8 locty, u32 time, u8 mask, u8 expect) -{ - return wait_reg8(TIS_REG(locty, TIS_REG_STS), time, mask, expect); -} - -static u32 crb_wait_reg(u8 locty, u16 reg, u32 time, u8 mask, u8 expect) -{ - return wait_reg8(CRB_REG(locty, reg), time, mask, expect); -} - -/* if device is not there, return '0', '1' otherwise */ -static u32 tis_probe(void) -{ - if (!CONFIG_TCGBIOS) - return 0; - - /* Wait for the interface to report it's ready */ - u32 rc = tis_wait_access(0, TIS_DEFAULT_TIMEOUT_A, - TIS_ACCESS_TPM_REG_VALID_STS, - TIS_ACCESS_TPM_REG_VALID_STS); - if (rc) - return 0; - - u32 didvid = readl(TIS_REG(0, TIS_REG_DID_VID)); - - if ((didvid != 0) && (didvid != 0xffffffff)) - rc = 1; - - /* TPM 2 has an interface register */ - u32 ifaceid = readl(TIS_REG(0, TIS_REG_IFACE_ID)); - - if ((ifaceid & 0xf) != 0xf) { - if ((ifaceid & 0xf) == 1) { - /* CRB is active; no TIS */ - return 0; - } - if ((ifaceid & (1 << 13)) == 0) { - /* TIS cannot be selected */ - return 0; - } - /* write of 0 to bits 17-18 selects TIS */ - writel(TIS_REG(0, TIS_REG_IFACE_ID), 0); - /* since we only support TIS, we lock it */ - writel(TIS_REG(0, TIS_REG_IFACE_ID), (1 << 19)); - } - - return rc; -} - -static TPMVersion tis_get_tpm_version(void) -{ - u32 reg = readl(TIS_REG(0, TIS_REG_IFACE_ID)); - - /* - * FIFO interface as defined in TIS1.3 is active - * Interface capabilities are defined in TIS_REG_INTF_CAPABILITY - */ - if ((reg & 0xf) == 0xf) { - reg = readl(TIS_REG(0, TIS_REG_INTF_CAPABILITY)); - /* Interface 1.3 for TPM 2.0 */ - if (((reg >> 28) & 0x7) == 3) - return TPM_VERSION_2; - } - /* FIFO interface as defined in PTP for TPM 2.0 is active */ - else if ((reg & 0xf) == 0) { - return TPM_VERSION_2; - } - - return TPM_VERSION_1_2; -} - -static void init_timeout(int driver) -{ - if (tpm_drivers[driver].durations == NULL) { - u32 *durations = tpm_default_dur; - memcpy(durations, tpm_default_durations, - sizeof(tpm_default_durations)); - tpm_drivers[driver].durations = durations; - } - - if (tpm_drivers[driver].timeouts == NULL) { - u32 *timeouts = tpm_default_to; - memcpy(timeouts, tis_default_timeouts, - sizeof(tis_default_timeouts)); - tpm_drivers[driver].timeouts = timeouts; - } -} - -static u32 tis_init(void) -{ - if (!CONFIG_TCGBIOS) - return 1; - - writeb(TIS_REG(0, TIS_REG_INT_ENABLE), 0); - - init_timeout(TIS_DRIVER_IDX); - - return 1; -} - - -static void set_timeouts(u32 timeouts[4], u32 durations[3]) -{ - if (!CONFIG_TCGBIOS) - return; - - u32 *tos = tpm_drivers[TIS_DRIVER_IDX].timeouts; - u32 *dus = tpm_drivers[TIS_DRIVER_IDX].durations; - - if (tos && tos != tis_default_timeouts && timeouts) - memcpy(tos, timeouts, 4 * sizeof(u32)); - if (dus && dus != tpm_default_durations && durations) - memcpy(dus, durations, 3 * sizeof(u32)); -} - -static u32 tis_activate(u8 locty) -{ - if (!CONFIG_TCGBIOS) - return 0; - - u32 rc = 0; - u8 acc; - int l; - u32 timeout_a = tpm_drivers[TIS_DRIVER_IDX].timeouts[TIS_TIMEOUT_TYPE_A]; - - if (!(readb(TIS_REG(locty, TIS_REG_ACCESS)) & - TIS_ACCESS_ACTIVE_LOCALITY)) { - /* release locality in use top-downwards */ - for (l = 4; l >= 0; l--) - writeb(TIS_REG(l, TIS_REG_ACCESS), - TIS_ACCESS_ACTIVE_LOCALITY); - } - - /* request access to locality */ - writeb(TIS_REG(locty, TIS_REG_ACCESS), TIS_ACCESS_REQUEST_USE); - - acc = readb(TIS_REG(locty, TIS_REG_ACCESS)); - if ((acc & TIS_ACCESS_ACTIVE_LOCALITY)) { - writeb(TIS_REG(locty, TIS_REG_STS), TIS_STS_COMMAND_READY); - rc = tis_wait_sts(locty, timeout_a, - TIS_STS_COMMAND_READY, TIS_STS_COMMAND_READY); - } - - return rc; -} - -static u32 tis_find_active_locality(void) -{ - if (!CONFIG_TCGBIOS) - return 0; - - u8 locty; - - for (locty = 0; locty <= 4; locty++) { - if ((readb(TIS_REG(locty, TIS_REG_ACCESS)) & - TIS_ACCESS_ACTIVE_LOCALITY)) - return locty; - } - - tis_activate(0); - - return 0; -} - -static u32 tis_ready(void) -{ - if (!CONFIG_TCGBIOS) - return 0; - - u32 rc = 0; - u8 locty = tis_find_active_locality(); - u32 timeout_b = tpm_drivers[TIS_DRIVER_IDX].timeouts[TIS_TIMEOUT_TYPE_B]; - - writeb(TIS_REG(locty, TIS_REG_STS), TIS_STS_COMMAND_READY); - rc = tis_wait_sts(locty, timeout_b, - TIS_STS_COMMAND_READY, TIS_STS_COMMAND_READY); - - return rc; -} - -static u32 tis_senddata(const u8 *const data, u32 len) -{ - if (!CONFIG_TCGBIOS) - return 0; - - u32 rc = 0; - u32 offset = 0; - u32 end_loop = 0; - u16 burst = 0; - u8 locty = tis_find_active_locality(); - u32 timeout_d = tpm_drivers[TIS_DRIVER_IDX].timeouts[TIS_TIMEOUT_TYPE_D]; - u32 end = timer_calc_usec(timeout_d); - - do { - while (burst == 0) { - burst = readl(TIS_REG(locty, TIS_REG_STS)) >> 8; - if (burst == 0) { - if (timer_check(end)) { - warn_timeout(); - break; - } - yield(); - } - } - - if (burst == 0) { - rc = TCG_RESPONSE_TIMEOUT; - break; - } - - while (1) { - writeb(TIS_REG(locty, TIS_REG_DATA_FIFO), data[offset++]); - burst--; - - if (burst == 0 || offset == len) - break; - } - - if (offset == len) - end_loop = 1; - } while (end_loop == 0); - - return rc; -} - -static u32 tis_readresp(u8 *buffer, u32 *len) -{ - if (!CONFIG_TCGBIOS) - return 0; - - u32 rc = 0; - u32 offset = 0; - u32 sts; - u8 locty = tis_find_active_locality(); - - while (offset < *len) { - buffer[offset] = readb(TIS_REG(locty, TIS_REG_DATA_FIFO)); - offset++; - sts = readb(TIS_REG(locty, TIS_REG_STS)); - /* data left ? */ - if ((sts & TIS_STS_DATA_AVAILABLE) == 0) - break; - } - - *len = offset; - - return rc; -} - - -static u32 tis_waitdatavalid(void) -{ - if (!CONFIG_TCGBIOS) - return 0; - - u32 rc = 0; - u8 locty = tis_find_active_locality(); - u32 timeout_c = tpm_drivers[TIS_DRIVER_IDX].timeouts[TIS_TIMEOUT_TYPE_C]; - - if (tis_wait_sts(locty, timeout_c, TIS_STS_VALID, TIS_STS_VALID) != 0) - rc = 1; - - return rc; -} - -static u32 tis_waitrespready(enum tpmDurationType to_t) -{ - if (!CONFIG_TCGBIOS) - return 0; - - u32 rc = 0; - u8 locty = tis_find_active_locality(); - u32 timeout = tpm_drivers[TIS_DRIVER_IDX].durations[to_t]; - - writeb(TIS_REG(locty ,TIS_REG_STS), TIS_STS_TPM_GO); - - if (tis_wait_sts(locty, timeout, - TIS_STS_DATA_AVAILABLE, TIS_STS_DATA_AVAILABLE) != 0) - rc = 1; - - return rc; -} - -#define CRB_STATE_VALID_STS 0b10000000 -#define CRB_STATE_LOC_ASSIGNED 0x00000010 -#define CRB_STATE_READY_MASK (CRB_STATE_VALID_STS | CRB_STATE_LOC_ASSIGNED) - -/* if device is not there, return '0', '1' otherwise */ -static u32 crb_probe(void) -{ - if (!CONFIG_TCGBIOS) - return 0; - - /* Wait for the interface to report it's ready */ - u32 rc = crb_wait_reg(0, CRB_REG_LOC_STATE, TIS2_DEFAULT_TIMEOUT_D, - CRB_STATE_READY_MASK, CRB_STATE_VALID_STS); - if (rc) - return 0; - - u32 ifaceid = readl(CRB_REG(0, CRB_REG_INTF_ID)); - - if ((ifaceid & 0xf) != 0xf) { - if ((ifaceid & 0xf) == 1) { - /* CRB is active */ - } else if ((ifaceid & (1 << 14)) == 0) { - /* CRB cannot be selected */ - return 0; - } - /* write of 1 to bits 17-18 selects CRB */ - writel(CRB_REG(0, CRB_REG_INTF_ID), (1 << 17)); - /* lock it */ - writel(CRB_REG(0, CRB_REG_INTF_ID), (1 << 19)); - } - - /* no support for 64 bit addressing yet */ - if (readl(CRB_REG(0, CRB_REG_CTRL_CMD_HADDR))) - return 0; - - u64 addr = readq(CRB_REG(0, CRB_REG_CTRL_RSP_ADDR)); - if (addr > 0xffffffff) - return 0; - - return 1; -} - -static TPMVersion crb_get_tpm_version(void) -{ - /* CRB is supposed to be TPM 2.0 only */ - return TPM_VERSION_2; -} - -static u32 crb_init(void) -{ - if (!CONFIG_TCGBIOS) - return 1; - - crb_cmd = (void*)readl(CRB_REG(0, CRB_REG_CTRL_CMD_LADDR)); - crb_cmd_size = readl(CRB_REG(0, CRB_REG_CTRL_CMD_SIZE)); - crb_resp = (void*)readl(CRB_REG(0, CRB_REG_CTRL_RSP_ADDR)); - crb_resp_size = readl(CRB_REG(0, CRB_REG_CTRL_RSP_SIZE)); - - init_timeout(CRB_DRIVER_IDX); - - return 0; -} - -static u32 crb_activate(u8 locty) -{ - if (!CONFIG_TCGBIOS) - return 0; - - writeb(CRB_REG(locty, CRB_REG_LOC_CTRL), 1); - - return 0; -} - -static u32 crb_find_active_locality(void) -{ - if (!CONFIG_TCGBIOS) - return 0; - - return 0; -} - -#define CRB_CTRL_REQ_CMD_READY 0b1 -#define CRB_START_INVOKE 0b1 -#define CRB_CTRL_STS_ERROR 0b1 - -static u32 crb_ready(void) -{ - if (!CONFIG_TCGBIOS) - return 0; - - u32 rc = 0; - u8 locty = crb_find_active_locality(); - u32 timeout_c = tpm_drivers[CRB_DRIVER_IDX].timeouts[TIS_TIMEOUT_TYPE_C]; - - writel(CRB_REG(locty, CRB_REG_CTRL_REQ), CRB_CTRL_REQ_CMD_READY); - rc = crb_wait_reg(locty, CRB_REG_CTRL_REQ, timeout_c, - CRB_CTRL_REQ_CMD_READY, 0); - - return rc; -} - -static u32 crb_senddata(const u8 *const data, u32 len) -{ - if (!CONFIG_TCGBIOS) - return 0; - - if (len > crb_cmd_size) - return 1; - - u8 locty = crb_find_active_locality(); - memcpy(crb_cmd, data, len); - writel(CRB_REG(locty, CRB_REG_CTRL_START), CRB_START_INVOKE); - - return 0; -} - -static u32 crb_readresp(u8 *buffer, u32 *len) -{ - if (!CONFIG_TCGBIOS) - return 0; - - u8 locty = crb_find_active_locality(); - if (readl(CRB_REG(locty, CRB_REG_CTRL_STS)) & CRB_CTRL_STS_ERROR) - return 1; - - if (*len < 6) - return 1; - - memcpy(buffer, crb_resp, 6); - u32 expected = be32_to_cpu(*(u32 *) &buffer[2]); - if (expected < 6) - return 1; - - *len = (*len < expected) ? *len : expected; - - memcpy(buffer + 6, crb_resp + 6, *len - 6); - - return 0; -} - - -static u32 crb_waitdatavalid(void) -{ - return 0; -} - -static u32 crb_waitrespready(enum tpmDurationType to_t) -{ - if (!CONFIG_TCGBIOS) - return 0; - - u32 rc = 0; - u8 locty = crb_find_active_locality(); - u32 timeout = tpm_drivers[CRB_DRIVER_IDX].durations[to_t]; - - rc = crb_wait_reg(locty, CRB_REG_CTRL_START, timeout, - CRB_START_INVOKE, 0); - - return rc; -} - -struct tpm_driver tpm_drivers[TPM_NUM_DRIVERS] = { - [TIS_DRIVER_IDX] = - { - .timeouts = NULL, - .durations = NULL, - .set_timeouts = set_timeouts, - .probe = tis_probe, - .get_tpm_version = tis_get_tpm_version, - .init = tis_init, - .activate = tis_activate, - .ready = tis_ready, - .senddata = tis_senddata, - .readresp = tis_readresp, - .waitdatavalid = tis_waitdatavalid, - .waitrespready = tis_waitrespready, - }, - [CRB_DRIVER_IDX] = - { - .timeouts = NULL, - .durations = NULL, - .set_timeouts = set_timeouts, - .probe = crb_probe, - .get_tpm_version = crb_get_tpm_version, - .init = crb_init, - .activate = crb_activate, - .ready = crb_ready, - .senddata = crb_senddata, - .readresp = crb_readresp, - .waitdatavalid = crb_waitdatavalid, - .waitrespready = crb_waitrespready, - }, -}; - -static u8 TPMHW_driver_to_use = TPM_INVALID_DRIVER; - -TPMVersion -tpmhw_probe(void) -{ - unsigned int i; - for (i = 0; i < TPM_NUM_DRIVERS; i++) { - struct tpm_driver *td = &tpm_drivers[i]; - if (td->probe() != 0) { - td->init(); - TPMHW_driver_to_use = i; - return td->get_tpm_version(); - } - } - return TPM_VERSION_NONE; -} - -int -tpmhw_is_present(void) -{ - return TPMHW_driver_to_use != TPM_INVALID_DRIVER; -} - -int -tpmhw_transmit(u8 locty, struct tpm_req_header *req, - void *respbuffer, u32 *respbufferlen, - enum tpmDurationType to_t) -{ - if (TPMHW_driver_to_use == TPM_INVALID_DRIVER) - return -1; - - struct tpm_driver *td = &tpm_drivers[TPMHW_driver_to_use]; - - u32 irc = td->activate(locty); - if (irc != 0) { - /* tpm could not be activated */ - return -1; - } - - irc = td->senddata((void*)req, be32_to_cpu(req->totlen)); - if (irc != 0) - return -1; - - irc = td->waitdatavalid(); - if (irc != 0) - return -1; - - irc = td->waitrespready(to_t); - if (irc != 0) - return -1; - - irc = td->readresp(respbuffer, respbufferlen); - if (irc != 0 || - *respbufferlen < sizeof(struct tpm_rsp_header)) - return -1; - - td->ready(); - - return 0; -} - -void -tpmhw_set_timeouts(u32 timeouts[4], u32 durations[3]) -{ - struct tpm_driver *td = &tpm_drivers[TPMHW_driver_to_use]; - td->set_timeouts(timeouts, durations); -} diff --git a/src/hw/tpm_drivers.h b/src/hw/tpm_drivers.h deleted file mode 100644 index adf1839..0000000 --- a/src/hw/tpm_drivers.h +++ /dev/null @@ -1,127 +0,0 @@ -#ifndef TPM_DRIVERS_H -#define TPM_DRIVERS_H - -#include "types.h" // u32 - - -enum tpmDurationType { - TPM_DURATION_TYPE_SHORT = 0, - TPM_DURATION_TYPE_MEDIUM, - TPM_DURATION_TYPE_LONG, -}; - -typedef u8 TPMVersion; - -#define TPM_VERSION_NONE 0 -#define TPM_VERSION_1_2 1 -#define TPM_VERSION_2 2 - -TPMVersion tpmhw_probe(void); -int tpmhw_is_present(void); -struct tpm_req_header; -int tpmhw_transmit(u8 locty, struct tpm_req_header *req, - void *respbuffer, u32 *respbufferlen, - enum tpmDurationType to_t); -void tpmhw_set_timeouts(u32 timeouts[4], u32 durations[3]); - -/* CRB driver */ -/* address of locality 0 (CRB) */ -#define TPM_CRB_BASE_ADDRESS 0xfed40000 - -#define CRB_REG(LOCTY, REG) \ - (void *)(TPM_CRB_BASE_ADDRESS + (LOCTY << 12) + REG) - -/* hardware registers */ -#define CRB_REG_LOC_STATE 0x0 -#define CRB_REG_LOC_CTRL 0x8 -#define CRB_REG_LOC_STS 0xC -#define CRB_REG_INTF_ID 0x30 -#define CRB_REG_CTRL_EXT 0x38 -#define CRB_REG_CTRL_REQ 0x40 -#define CRB_REG_CTRL_STS 0x44 -#define CRB_REG_CTRL_CANCEL 0x48 -#define CRB_REG_CTRL_START 0x4C -#define CRB_REG_INT_ENABLE 0x50 -#define CRB_REG_INT_STS 0x54 -#define CRB_REG_CTRL_CMD_SIZE 0x58 -#define CRB_REG_CTRL_CMD_LADDR 0x5C -#define CRB_REG_CTRL_CMD_HADDR 0x60 -#define CRB_REG_CTRL_RSP_SIZE 0x64 -#define CRB_REG_CTRL_RSP_ADDR 0x68 -#define CRB_REG_DATA_BUFFER 0x80 - -/* TIS driver */ -/* address of locality 0 (TIS) */ -#define TPM_TIS_BASE_ADDRESS 0xfed40000 - -#define TIS_REG(LOCTY, REG) \ - (void *)(TPM_TIS_BASE_ADDRESS + (LOCTY << 12) + REG) - -/* hardware registers */ -#define TIS_REG_ACCESS 0x0 -#define TIS_REG_INT_ENABLE 0x8 -#define TIS_REG_INT_VECTOR 0xc -#define TIS_REG_INT_STATUS 0x10 -#define TIS_REG_INTF_CAPABILITY 0x14 -#define TIS_REG_STS 0x18 -#define TIS_REG_DATA_FIFO 0x24 -#define TIS_REG_IFACE_ID 0x30 -#define TIS_REG_DID_VID 0xf00 -#define TIS_REG_RID 0xf04 - -#define TIS_STS_VALID (1 << 7) /* 0x80 */ -#define TIS_STS_COMMAND_READY (1 << 6) /* 0x40 */ -#define TIS_STS_TPM_GO (1 << 5) /* 0x20 */ -#define TIS_STS_DATA_AVAILABLE (1 << 4) /* 0x10 */ -#define TIS_STS_EXPECT (1 << 3) /* 0x08 */ -#define TIS_STS_RESPONSE_RETRY (1 << 1) /* 0x02 */ - -#define TIS_ACCESS_TPM_REG_VALID_STS (1 << 7) /* 0x80 */ -#define TIS_ACCESS_ACTIVE_LOCALITY (1 << 5) /* 0x20 */ -#define TIS_ACCESS_BEEN_SEIZED (1 << 4) /* 0x10 */ -#define TIS_ACCESS_SEIZE (1 << 3) /* 0x08 */ -#define TIS_ACCESS_PENDING_REQUEST (1 << 2) /* 0x04 */ -#define TIS_ACCESS_REQUEST_USE (1 << 1) /* 0x02 */ -#define TIS_ACCESS_TPM_ESTABLISHMENT (1 << 0) /* 0x01 */ - -/* - * Default TIS timeouts used before getting them from the TPM itself - */ -#define TIS_DEFAULT_TIMEOUT_A 750000 /* us */ -#define TIS_DEFAULT_TIMEOUT_B 2000000 /* us */ -#define TIS_DEFAULT_TIMEOUT_C 750000 /* us */ -#define TIS_DEFAULT_TIMEOUT_D 750000 /* us */ - -/* - * Default TIS 2 timeouts given in TPM Profile (TPT) Spec - */ -#define TIS2_DEFAULT_TIMEOUT_A 750000 /* us */ -#define TIS2_DEFAULT_TIMEOUT_B 2000000 /* us */ -#define TIS2_DEFAULT_TIMEOUT_C 200000 /* us */ -#define TIS2_DEFAULT_TIMEOUT_D 30000 /* us */ - -enum tisTimeoutType { - TIS_TIMEOUT_TYPE_A = 0, - TIS_TIMEOUT_TYPE_B, - TIS_TIMEOUT_TYPE_C, - TIS_TIMEOUT_TYPE_D, -}; - -/* - * Default command durations used before getting them from the - * TPM itself - */ -#define TPM_DEFAULT_DURATION_SHORT 2000000 /* us */ -#define TPM_DEFAULT_DURATION_MEDIUM 20000000 /* us */ -#define TPM_DEFAULT_DURATION_LONG 60000000 /* us */ - -/* - * TPM 2 command durations; we set them to the timeout values - * given in TPM Profile (PTP) Specification; exceeding those - * timeout values indicates a faulty TPM. - */ -#define TPM2_DEFAULT_DURATION_SHORT 750000 /* us */ -#define TPM2_DEFAULT_DURATION_MEDIUM 2000000 /* us */ -#define TPM2_DEFAULT_DURATION_LONG 2000000 /* us */ - -#endif /* TPM_DRIVERS_H */ diff --git a/src/optionroms.c b/src/optionroms.c index e906ab9..a5b83a9 100644 --- a/src/optionroms.c +++ b/src/optionroms.c @@ -21,7 +21,6 @@ #include "std/pnpbios.h" // PNP_SIGNATURE #include "string.h" // memset #include "util.h" // get_pnp_offset -#include "tcgbios.h" // tpm_* static int EnforceChecksum, S3ResumeVga, RunPCIroms; @@ -135,8 +134,6 @@ init_optionrom(struct rom_header *rom, u16 bdf, int isvga) if (newrom != rom) memmove(newrom, rom, rom->size * 512); - tpm_option_rom(newrom, rom->size * 512); - if (isvga || get_pnp_rom(newrom)) // Only init vga and PnP roms here. callrom(newrom, bdf); diff --git a/src/post.c b/src/post.c index f93106a..2c861d9 100644 --- a/src/post.c +++ b/src/post.c @@ -22,7 +22,6 @@ #include "output.h" // dprintf #include "string.h" // memset #include "util.h" // kbd_init -#include "tcgbios.h" // tpm_* /**************************************************************** @@ -152,17 +151,11 @@ platform_hardware_setup(void) // Setup timers and periodic clock interrupt timer_setup(); clock_setup(); - - // Initialize TPM - tpm_setup(); } void prepareboot(void) { - // Change TPM phys. presence state befor leaving BIOS - tpm_prepboot(); - // Run BCVs bcv_prepboot(); diff --git a/src/resume.c b/src/resume.c index fb0b8a8..424fd91 100644 --- a/src/resume.c +++ b/src/resume.c @@ -16,7 +16,6 @@ #include "std/bda.h" // struct bios_data_area_s #include "string.h" // memset #include "util.h" // dma_setup -#include "tcgbios.h" // tpm_s3_resume #include "fw/romfile_loader.h" // romfile_fw_cfg_resume // Handler for post calls that look like a resume. @@ -103,7 +102,6 @@ s3_resume(void) pci_resume(); /* resume TPM before we may measure option roms */ - tpm_s3_resume(); s3_resume_vga(); /* Replay any fw_cfg entries that go back to the host */ diff --git a/src/sha.h b/src/sha.h deleted file mode 100644 index edc9437..0000000 --- a/src/sha.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef __SHA_H -#define __SHA_H - -#include "types.h" // u32 - -void sha1(const u8 *data, u32 length, u8 *hash); -void sha256(const u8 *data, u32 length, u8 *hash); -void sha384(const u8 *data, u32 length, u8 *hash); -void sha512(const u8 *data, u32 length, u8 *hash); - -#endif // sha.h diff --git a/src/sha1.c b/src/sha1.c deleted file mode 100644 index e6d80c8..0000000 --- a/src/sha1.c +++ /dev/null @@ -1,147 +0,0 @@ -// Support for Calculation of SHA1 in SW -// -// Copyright (C) 2006-2011 IBM Corporation -// -// Authors: -// Stefan Berger -// -// This file may be distributed under the terms of the GNU LGPLv3 license. -// -// See: http://www.itl.nist.gov/fipspubs/fip180-1.htm -// RFC3174, Wikipedia's SHA1 alogrithm description -// - -#include "config.h" -#include "byteorder.h" // cpu_to_*, __swab64 -#include "sha.h" // sha1 -#include "string.h" // memcpy -#include "x86.h" // rol - -typedef struct _sha1_ctx { - u32 h[5]; -} sha1_ctx; - - -static void -sha1_block(u32 *w, sha1_ctx *ctx) -{ - u32 i; - u32 a,b,c,d,e,f; - u32 tmp; - u32 idx; - - static const u32 sha_ko[4] = { - 0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xca62c1d6 }; - - /* change endianness of given data */ - for (i = 0; i < 16; i++) - w[i] = be32_to_cpu(w[i]); - - for (i = 16; i <= 79; i++) { - tmp = w[i-3] ^ w[i-8] ^ w[i-14] ^ w[i-16]; - w[i] = rol(tmp,1); - } - - a = ctx->h[0]; - b = ctx->h[1]; - c = ctx->h[2]; - d = ctx->h[3]; - e = ctx->h[4]; - - for (i = 0; i <= 79; i++) { - if (i <= 19) { - f = (b & c) | ((b ^ 0xffffffff) & d); - idx = 0; - } else if (i <= 39) { - f = b ^ c ^ d; - idx = 1; - } else if (i <= 59) { - f = (b & c) | (b & d) | (c & d); - idx = 2; - } else { - f = b ^ c ^ d; - idx = 3; - } - - tmp = rol(a, 5) + - f + - e + - sha_ko[idx] + - w[i]; - e = d; - d = c; - c = rol(b, 30); - b = a; - a = tmp; - } - - ctx->h[0] += a; - ctx->h[1] += b; - ctx->h[2] += c; - ctx->h[3] += d; - ctx->h[4] += e; -} - - -static void -sha1_do(sha1_ctx *ctx, const u8 *data32, u32 length) -{ - u32 offset; - u16 num; - u32 bits = 0; - u32 w[80]; - u64 tmp; - - /* treat data in 64-byte chunks */ - for (offset = 0; length - offset >= 64; offset += 64) { - memcpy(w, data32 + offset, 64); - sha1_block((u32 *)w, ctx); - bits += (64 * 8); - } - - /* last block with less than 64 bytes */ - num = length - offset; - bits += (num << 3); - - memcpy(w, data32 + offset, num); - ((u8 *)w)[num] = 0x80; - if (64 - (num + 1) > 0) - memset( &((u8 *)w)[num + 1], 0x0, 64 - (num + 1)); - - if (num >= 56) { - /* cannot append number of bits here */ - sha1_block((u32 *)w, ctx); - memset(w, 0x0, 60); - } - - /* write number of bits to end of block */ - tmp = __swab64(bits); - memcpy(&w[14], &tmp, 8); - - sha1_block(w, ctx); - - /* need to switch result's endianness */ - for (num = 0; num < 5; num++) - ctx->h[num] = cpu_to_be32(ctx->h[num]); -} - - -void -sha1(const u8 *data, u32 length, u8 *hash) -{ - if (!CONFIG_TCGBIOS) - return; - - sha1_ctx ctx = { - .h[0] = 0x67452301, - .h[1] = 0xefcdab89, - .h[2] = 0x98badcfe, - .h[3] = 0x10325476, - .h[4] = 0xc3d2e1f0, - }; - - sha1_do(&ctx, data, length); - memcpy(hash, &ctx.h[0], 20); - - return; -} diff --git a/src/sha256.c b/src/sha256.c deleted file mode 100644 index 72c3df8..0000000 --- a/src/sha256.c +++ /dev/null @@ -1,211 +0,0 @@ -/***************************************************************************** - * Copyright (c) 2015-2020 IBM Corporation - * All rights reserved. - * This program and the accompanying materials - * are made available under the terms of the BSD License - * which accompanies this distribution, and is available at - * http://www.opensource.org/licenses/bsd-license.php - * - * Contributors: - * IBM Corporation - initial implementation - *****************************************************************************/ - -/* - * See: NIST standard for SHA-256 in FIPS PUB 180-4 - */ - -#include "config.h" -#include "byteorder.h" -#include "sha.h" -#include "string.h" -#include "x86.h" - -typedef struct _sha256_ctx { - u32 h[8]; -} sha256_ctx; - -static inline u32 Ch(u32 x, u32 y, u32 z) -{ - return (x & y) | ((x ^ 0xffffffff) & z); -} - -static inline u32 Maj(u32 x, u32 y, u32 z) -{ - return (x & y) | (x & z) | (y & z); -} - -static inline u32 sum0(u32 x) -{ - return ror(x, 2) ^ ror(x, 13) ^ ror(x, 22); -} - -static inline u32 sum1(u32 x) -{ - return ror(x, 6) ^ ror(x, 11) ^ ror(x, 25); -} - -static inline u32 sigma0(u32 x) -{ - return ror(x, 7) ^ ror(x, 18) ^ (x >> 3); -} - -static inline u32 sigma1(u32 x) -{ - return ror(x, 17) ^ ror(x, 19) ^ (x >> 10); -} - -static void sha256_block(u32 *w, sha256_ctx *ctx) -{ - u32 t; - u32 a, b, c, d, e, f, g, h; - u32 T1, T2; - - /* - * FIPS 180-4 4.2.2: SHA256 Constants - */ - static const u32 sha_ko[64] = { - 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, - 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, - 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, - 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, - 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, - 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, - 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, - 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, - 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, - 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, - 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, - 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, - 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, - 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, - 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, - 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 - }; - - /* - * FIPS 180-4 6.2.2: step 1 - * - * 0 <= i <= 15: - * W(t) = M(t) - * 16 <= i <= 63: - * W(t) = sigma1(W(t-2)) + W(t-7) + sigma0(W(t-15)) + W(t-16) - */ - - /* w(0)..w(15) are in big endian format */ - for (t = 0; t <= 15; t++) - w[t] = be32_to_cpu(w[t]); - - for (t = 16; t <= 63; t++) - w[t] = sigma1(w[t-2]) + w[t-7] + sigma0(w[t-15]) + w[t-16]; - - /* - * step 2: a = H0, b = H1, c = H2, d = H3, e = H4, f = H5, g = H6, h = H7 - */ - a = ctx->h[0]; - b = ctx->h[1]; - c = ctx->h[2]; - d = ctx->h[3]; - e = ctx->h[4]; - f = ctx->h[5]; - g = ctx->h[6]; - h = ctx->h[7]; - - /* - * step 3: For i = 0 to 63: - * T1 = h + sum1(e) + Ch(e,f,g) + K(t) + W(t); - * T2 = sum0(a) + Maj(a,b,c) - * h = g; g = f; f = e; e = d + T1; d = c; c = b; b = a; a + T1 + T2 - */ - for (t = 0; t <= 63; t++) { - T1 = h + sum1(e) + Ch(e, f, g) + sha_ko[t] + w[t]; - T2 = sum0(a) + Maj(a, b, c); - h = g; - g = f; - f = e; - e = d + T1; - d = c; - c = b; - b = a; - a = T1 + T2; - } - - /* - * step 4: - * H0 = a + H0, H1 = b + H1, H2 = c + H2, H3 = d + H3, H4 = e + H4 - */ - ctx->h[0] += a; - ctx->h[1] += b; - ctx->h[2] += c; - ctx->h[3] += d; - ctx->h[4] += e; - ctx->h[5] += f; - ctx->h[6] += g; - ctx->h[7] += h; -} - -static void sha256_do(sha256_ctx *ctx, const u8 *data32, u32 length) -{ - u32 offset; - u16 num; - u32 bits = 0; - u32 w[64]; - u64 tmp; - - /* treat data in 64-byte chunks */ - for (offset = 0; length - offset >= 64; offset += 64) { - memcpy(w, data32 + offset, 64); - sha256_block((u32 *)w, ctx); - bits += (64 * 8); - } - - /* last block with less than 64 bytes */ - num = length - offset; - bits += (num << 3); - - memcpy(w, data32 + offset, num); - /* - * FIPS 180-4 5.1: Padding the Message - */ - ((u8 *)w)[num] = 0x80; - if (64 - (num + 1) > 0) - memset( &((u8 *)w)[num + 1], 0, 64 - (num + 1)); - - if (num >= 56) { - /* cannot append number of bits here */ - sha256_block((u32 *)w, ctx); - memset(w, 0, 60); - } - - /* write number of bits to end of block */ - tmp = cpu_to_be64(bits); - memcpy(&w[14], &tmp, 8); - - sha256_block(w, ctx); - - /* need to switch result's endianness */ - for (num = 0; num < 8; num++) - ctx->h[num] = cpu_to_be32(ctx->h[num]); -} - -void sha256(const u8 *data, u32 length, u8 *hash) -{ - sha256_ctx ctx = { - .h = { - /* - * FIPS 180-4: 6.2.1 - * -> 5.3.3: initial hash value - */ - 0x6a09e667, - 0xbb67ae85, - 0x3c6ef372, - 0xa54ff53a, - 0x510e527f, - 0x9b05688c, - 0x1f83d9ab, - 0x5be0cd19 - } - }; - - sha256_do(&ctx, data, length); - memcpy(hash, ctx.h, sizeof(ctx.h)); -} diff --git a/src/sha512.c b/src/sha512.c deleted file mode 100644 index fddd9fa..0000000 --- a/src/sha512.c +++ /dev/null @@ -1,244 +0,0 @@ -/***************************************************************************** - * Copyright (c) 2021 IBM Corporation - * All rights reserved. - * This program and the accompanying materials - * are made available under the terms of the BSD License - * which accompanies this distribution, and is available at - * http://www.opensource.org/licenses/bsd-license.php - * - * Contributors: - * IBM Corporation - initial implementation - *****************************************************************************/ - -/* - * See: NIST standard for SHA-512 and SHA-384 in FIPS PUB 180-4 & RFC 6234 - */ - -#include "config.h" -#include "byteorder.h" -#include "sha.h" -#include "string.h" - -typedef struct _sha512_ctx { - u64 h[8]; -} sha512_ctx; - -static inline u64 ror64(u64 x, u8 n) -{ - return (x >> n) | (x << (64 - n)); -} - -static inline u64 Ch64(u64 x, u64 y, u64 z) -{ - return (x & y) ^ ((x ^ 0xffffffffffffffffULL) & z); -} - -static inline u64 Maj64(u64 x, u64 y, u64 z) -{ - return (x & y) ^ (x & z) ^ (y & z); -} - -static inline u64 sum0_64(u64 x) -{ - return ror64(x, 28) ^ ror64(x, 34) ^ ror64(x, 39); -} - -static inline u64 sum1_64(u64 x) -{ - return ror64(x, 14) ^ ror64(x, 18) ^ ror64(x, 41); -} - -static inline u64 sigma0_64(u64 x) -{ - return ror64(x, 1) ^ ror64(x, 8) ^ (x >> 7); -} - -static inline u64 sigma1_64(u64 x) -{ - return ror64(x, 19) ^ ror64(x, 61) ^ (x >> 6); -} - -static void sha512_block(u64 *w, sha512_ctx *ctx) -{ - u32 t; - u64 a, b, c, d, e, f, g, h; - u64 T1, T2; - - /* - * FIPS 180-4 4.2.2: SHA512 Constants - */ - static const u64 sha_ko[80] = { - 0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f, 0xe9b5dba58189dbbc, - 0x3956c25bf348b538, 0x59f111f1b605d019, 0x923f82a4af194f9b, 0xab1c5ed5da6d8118, - 0xd807aa98a3030242, 0x12835b0145706fbe, 0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2, - 0x72be5d74f27b896f, 0x80deb1fe3b1696b1, 0x9bdc06a725c71235, 0xc19bf174cf692694, - 0xe49b69c19ef14ad2, 0xefbe4786384f25e3, 0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65, - 0x2de92c6f592b0275, 0x4a7484aa6ea6e483, 0x5cb0a9dcbd41fbd4, 0x76f988da831153b5, - 0x983e5152ee66dfab, 0xa831c66d2db43210, 0xb00327c898fb213f, 0xbf597fc7beef0ee4, - 0xc6e00bf33da88fc2, 0xd5a79147930aa725, 0x06ca6351e003826f, 0x142929670a0e6e70, - 0x27b70a8546d22ffc, 0x2e1b21385c26c926, 0x4d2c6dfc5ac42aed, 0x53380d139d95b3df, - 0x650a73548baf63de, 0x766a0abb3c77b2a8, 0x81c2c92e47edaee6, 0x92722c851482353b, - 0xa2bfe8a14cf10364, 0xa81a664bbc423001, 0xc24b8b70d0f89791, 0xc76c51a30654be30, - 0xd192e819d6ef5218, 0xd69906245565a910, 0xf40e35855771202a, 0x106aa07032bbd1b8, - 0x19a4c116b8d2d0c8, 0x1e376c085141ab53, 0x2748774cdf8eeb99, 0x34b0bcb5e19b48a8, - 0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb, 0x5b9cca4f7763e373, 0x682e6ff3d6b2b8a3, - 0x748f82ee5defb2fc, 0x78a5636f43172f60, 0x84c87814a1f0ab72, 0x8cc702081a6439ec, - 0x90befffa23631e28, 0xa4506cebde82bde9, 0xbef9a3f7b2c67915, 0xc67178f2e372532b, - 0xca273eceea26619c, 0xd186b8c721c0c207, 0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178, - 0x06f067aa72176fba, 0x0a637dc5a2c898a6, 0x113f9804bef90dae, 0x1b710b35131c471b, - 0x28db77f523047d84, 0x32caab7b40c72493, 0x3c9ebe0a15c9bebc, 0x431d67c49c100d4c, - 0x4cc5d4becb3e42b6, 0x597f299cfc657e2a, 0x5fcb6fab3ad6faec, 0x6c44198c4a475817 - }; - - /* - * FIPS 180-4 6.4.2: step 1 - * - * 0 <= i <= 15: - * W(t) = M(t) - * 16 <= i <= 79: - * W(t) = sigma1(W(t-2)) + W(t-7) + sigma0(W(t-15)) + W(t-16) - */ - - /* w(0)..w(15) are in big endian format */ - for (t = 0; t <= 15; t++) - w[t] = be64_to_cpu(w[t]); - - for (t = 16; t <= 79; t++) - w[t] = sigma1_64(w[t-2]) + w[t-7] + sigma0_64(w[t-15]) + w[t-16]; - - /* - * step 2: a = H0, b = H1, c = H2, d = H3, e = H4, f = H5, g = H6, h = H7 - */ - a = ctx->h[0]; - b = ctx->h[1]; - c = ctx->h[2]; - d = ctx->h[3]; - e = ctx->h[4]; - f = ctx->h[5]; - g = ctx->h[6]; - h = ctx->h[7]; - - /* - * step 3: For i = 0 to 79: - * T1 = h + sum1(e) + Ch(e,f,g) + K(t) + W(t); - * T2 = sum0(a) + Maj(a,b,c) - * h = g; g = f; f = e; e = d + T1; d = c; c = b; b = a; a + T1 + T2 - */ - for (t = 0; t <= 79; t++) { - T1 = h + sum1_64(e) + Ch64(e, f, g) + sha_ko[t] + w[t]; - T2 = sum0_64(a) + Maj64(a, b, c); - h = g; - g = f; - f = e; - e = d + T1; - d = c; - c = b; - b = a; - a = T1 + T2; - } - - /* - * step 4: - * H0 = a + H0, H1 = b + H1, H2 = c + H2, H3 = d + H3, H4 = e + H4 - */ - ctx->h[0] += a; - ctx->h[1] += b; - ctx->h[2] += c; - ctx->h[3] += d; - ctx->h[4] += e; - ctx->h[5] += f; - ctx->h[6] += g; - ctx->h[7] += h; -} - -static void sha512_do(sha512_ctx *ctx, const u8 *data32, u32 length) -{ - u32 offset; - u16 num; - u64 bits = 0; - u64 w[80]; - u64 tmp; - - /* treat data in 128-byte/1024 bit chunks */ - for (offset = 0; length - offset >= 128; offset += 128) { - memcpy(w, data32 + offset, 128); - sha512_block(w, ctx); - bits += (128 * 8); - } - - /* last block with less than 128 bytes */ - num = length - offset; - bits += (num << 3); - - memcpy(w, data32 + offset, num); - /* - * FIPS 180-4 5.1: Padding the Message - */ - ((u8 *)w)[num] = 0x80; - if (128 - (num + 1) > 0) - memset( &((u8 *)w)[num + 1], 0, 128 - (num + 1)); - - if (num >= 112) { - /* cannot append number of bits here; - * need space for 128 bits (16 bytes) - */ - sha512_block((u64 *)w, ctx); - memset(w, 0, 128); - } - - /* write number of bits to end of the block; we write 64 bits */ - tmp = cpu_to_be64(bits); - memcpy(&w[15], &tmp, 8); - - sha512_block(w, ctx); - - /* need to switch result's endianness */ - for (num = 0; num < 8; num++) - ctx->h[num] = cpu_to_be64(ctx->h[num]); -} - -void sha384(const u8 *data, u32 length, u8 *hash) -{ - sha512_ctx ctx = { - .h = { - /* - * FIPS 180-4: 6.2.1 - * -> 5.3.4: initial hash value - */ - 0xcbbb9d5dc1059ed8, - 0x629a292a367cd507, - 0x9159015a3070dd17, - 0x152fecd8f70e5939, - 0x67332667ffc00b31, - 0x8eb44a8768581511, - 0xdb0c2e0d64f98fa7, - 0x47b5481dbefa4fa4 - } - }; - - sha512_do(&ctx, data, length); - memcpy(hash, ctx.h, 384/8); -} - -void sha512(const u8 *data, u32 length, u8 *hash) -{ - sha512_ctx ctx = { - .h = { - /* - * FIPS 180-4: 6.2.1 - * -> 5.3.5: initial hash value - */ - 0x6a09e667f3bcc908, - 0xbb67ae8584caa73b, - 0x3c6ef372fe94f82b, - 0xa54ff53a5f1d36f1, - 0x510e527fade682d1, - 0x9b05688c2b3e6c1f, - 0x1f83d9abfb41bd6b, - 0x5be0cd19137e2179 - } - }; - - sha512_do(&ctx, data, length); - memcpy(hash, ctx.h, sizeof(ctx.h)); -} diff --git a/src/std/tcg.h b/src/std/tcg.h deleted file mode 100644 index 98cca49..0000000 --- a/src/std/tcg.h +++ /dev/null @@ -1,580 +0,0 @@ -#ifndef STD_TCG_H -#define STD_TCG_H - -#include "types.h" - -#define SHA1_BUFSIZE 20 -#define SHA256_BUFSIZE 32 -#define SHA384_BUFSIZE 48 -#define SHA512_BUFSIZE 64 -#define SM3_256_BUFSIZE 32 -#define SHA3_256_BUFSIZE 32 -#define SHA3_384_BUFSIZE 48 -#define SHA3_512_BUFSIZE 64 - - -/**************************************************************** - * 16bit BIOS interface - ****************************************************************/ - -/* Define for section 12.3 */ -#define TCG_PC_OK 0x0 -#define TCG_PC_TPMERROR 0x1 -#define TCG_PC_LOGOVERFLOW 0x2 -#define TCG_PC_UNSUPPORTED 0x3 - -#define TPM_ALG_SHA 0x4 - -#define TCG_MAGIC 0x41504354L -#define TCG_VERSION_MAJOR 1 -#define TCG_VERSION_MINOR 2 - -#define TPM_OK 0x0 -#define TPM_RET_BASE 0x1 -#define TCG_GENERAL_ERROR (TPM_RET_BASE + 0x0) -#define TCG_TPM_IS_LOCKED (TPM_RET_BASE + 0x1) -#define TCG_NO_RESPONSE (TPM_RET_BASE + 0x2) -#define TCG_INVALID_RESPONSE (TPM_RET_BASE + 0x3) -#define TCG_INVALID_ACCESS_REQUEST (TPM_RET_BASE + 0x4) -#define TCG_FIRMWARE_ERROR (TPM_RET_BASE + 0x5) -#define TCG_INTEGRITY_CHECK_FAILED (TPM_RET_BASE + 0x6) -#define TCG_INVALID_DEVICE_ID (TPM_RET_BASE + 0x7) -#define TCG_INVALID_VENDOR_ID (TPM_RET_BASE + 0x8) -#define TCG_UNABLE_TO_OPEN (TPM_RET_BASE + 0x9) -#define TCG_UNABLE_TO_CLOSE (TPM_RET_BASE + 0xa) -#define TCG_RESPONSE_TIMEOUT (TPM_RET_BASE + 0xb) -#define TCG_INVALID_COM_REQUEST (TPM_RET_BASE + 0xc) -#define TCG_INVALID_ADR_REQUEST (TPM_RET_BASE + 0xd) -#define TCG_WRITE_BYTE_ERROR (TPM_RET_BASE + 0xe) -#define TCG_READ_BYTE_ERROR (TPM_RET_BASE + 0xf) -#define TCG_BLOCK_WRITE_TIMEOUT (TPM_RET_BASE + 0x10) -#define TCG_CHAR_WRITE_TIMEOUT (TPM_RET_BASE + 0x11) -#define TCG_CHAR_READ_TIMEOUT (TPM_RET_BASE + 0x12) -#define TCG_BLOCK_READ_TIMEOUT (TPM_RET_BASE + 0x13) -#define TCG_TRANSFER_ABORT (TPM_RET_BASE + 0x14) -#define TCG_INVALID_DRV_FUNCTION (TPM_RET_BASE + 0x15) -#define TCG_OUTPUT_BUFFER_TOO_SHORT (TPM_RET_BASE + 0x16) -#define TCG_FATAL_COM_ERROR (TPM_RET_BASE + 0x17) -#define TCG_INVALID_INPUT_PARA (TPM_RET_BASE + 0x18) -#define TCG_TCG_COMMAND_ERROR (TPM_RET_BASE + 0x19) -#define TCG_INTERFACE_SHUTDOWN (TPM_RET_BASE + 0x20) -//define TCG_PC_UNSUPPORTED (TPM_RET_BASE + 0x21) -#define TCG_PC_TPM_NOT_PRESENT (TPM_RET_BASE + 0x22) -#define TCG_PC_TPM_DEACTIVATED (TPM_RET_BASE + 0x23) - -/* interrupt identifiers (al register) */ -enum irq_ids { - TCG_StatusCheck = 0, - TCG_HashLogExtendEvent = 1, - TCG_PassThroughToTPM = 2, - TCG_ShutdownPreBootInterface = 3, - TCG_HashLogEvent = 4, - TCG_HashAll = 5, - TCG_TSS = 6, - TCG_CompactHashLogExtendEvent = 7, -}; - -/* Input and Output blocks for the TCG BIOS commands */ - -struct hleei_short -{ - u16 ipblength; - u16 reserved; - const void *hashdataptr; - u32 hashdatalen; - u32 pcrindex; - const void *logdataptr; - u32 logdatalen; -} PACKED; - -struct hleei_long -{ - u16 ipblength; - u16 reserved; - void *hashdataptr; - u32 hashdatalen; - u32 pcrindex; - u32 reserved2; - void *logdataptr; - u32 logdatalen; -} PACKED; - -struct hleeo -{ - u16 opblength; - u16 reserved; - u32 eventnumber; - u8 digest[SHA1_BUFSIZE]; -} PACKED; - -struct pttti -{ - u16 ipblength; - u16 reserved; - u16 opblength; - u16 reserved2; - u8 tpmopin[0]; -} PACKED; - -struct pttto -{ - u16 opblength; - u16 reserved; - u8 tpmopout[0]; -}; - -struct hlei -{ - u16 ipblength; - u16 reserved; - const void *hashdataptr; - u32 hashdatalen; - u32 pcrindex; - u32 logeventtype; - const void *logdataptr; - u32 logdatalen; -} PACKED; - -struct hleo -{ - u16 opblength; - u16 reserved; - u32 eventnumber; -} PACKED; - -struct hai -{ - u16 ipblength; - u16 reserved; - const void *hashdataptr; - u32 hashdatalen; - u32 algorithmid; -} PACKED; - -struct ti -{ - u16 ipblength; - u16 reserved; - u16 opblength; - u16 reserved2; - u8 tssoperandin[0]; -} PACKED; - -struct to -{ - u16 opblength; - u16 reserved; - u8 tssoperandout[0]; -} PACKED; - -struct pcpes -{ - u32 pcrindex; - u32 eventtype; - u8 digest[SHA1_BUFSIZE]; - u32 eventdatasize; - u8 event[0]; -} PACKED; - - -/**************************************************************** - * TPM v1.2 hardware commands - ****************************************************************/ - -#define TPM_ORD_SelfTestFull 0x00000050 -#define TPM_ORD_ForceClear 0x0000005d -#define TPM_ORD_GetCapability 0x00000065 -#define TPM_ORD_PhysicalEnable 0x0000006f -#define TPM_ORD_PhysicalDisable 0x00000070 -#define TPM_ORD_SetOwnerInstall 0x00000071 -#define TPM_ORD_PhysicalSetDeactivated 0x00000072 -#define TPM_ORD_SetTempDeactivated 0x00000073 -#define TPM_ORD_Startup 0x00000099 -#define TPM_ORD_PhysicalPresence 0x4000000a -#define TPM_ORD_Extend 0x00000014 -#define TSC_ORD_ResetEstablishmentBit 0x4000000b - -#define TPM_ST_CLEAR 0x0001 -#define TPM_ST_STATE 0x0002 -#define TPM_ST_DEACTIVATED 0x0003 - -#define TPM_PP_CMD_ENABLE 0x0020 -#define TPM_PP_PRESENT 0x0008 -#define TPM_PP_NOT_PRESENT_LOCK 0x0014 - -/* TPM command error codes */ -#define TPM_INVALID_POSTINIT 0x26 -#define TPM_BAD_LOCALITY 0x3d - -/* TPM command tags */ -#define TPM_TAG_RQU_CMD 0x00c1 -#define TPM_TAG_RQU_AUTH1_CMD 0x00c2 -#define TPM_TAG_RQU_AUTH2_CMD 0x00c3 - -struct tpm_req_header { - u16 tag; - u32 totlen; - u32 ordinal; -} PACKED; - -struct tpm_rsp_header { - u16 tag; - u32 totlen; - u32 errcode; -} PACKED; - -struct tpm_req_extend { - struct tpm_req_header hdr; - u32 pcrindex; - u8 digest[SHA1_BUFSIZE]; -} PACKED; - -struct tpm_rsp_extend { - struct tpm_rsp_header hdr; - u8 digest[SHA1_BUFSIZE]; -} PACKED; - -struct tpm_req_getcap { - struct tpm_req_header hdr; - u32 capArea; - u32 subCapSize; - u32 subCap; -} PACKED; - -#define TPM_CAP_FLAG 0x04 -#define TPM_CAP_PROPERTY 0x05 -#define TPM_CAP_FLAG_PERMANENT 0x108 -#define TPM_CAP_FLAG_VOLATILE 0x109 -#define TPM_CAP_PROP_OWNER 0x111 -#define TPM_CAP_PROP_TIS_TIMEOUT 0x115 -#define TPM_CAP_PROP_DURATION 0x120 - -struct tpm_permanent_flags { - u16 tag; - u8 flags[20]; -} PACKED; - -enum permFlagsIndex { - PERM_FLAG_IDX_DISABLE = 0, - PERM_FLAG_IDX_OWNERSHIP, - PERM_FLAG_IDX_DEACTIVATED, - PERM_FLAG_IDX_READPUBEK, - PERM_FLAG_IDX_DISABLEOWNERCLEAR, - PERM_FLAG_IDX_ALLOW_MAINTENANCE, - PERM_FLAG_IDX_PHYSICAL_PRESENCE_LIFETIME_LOCK, - PERM_FLAG_IDX_PHYSICAL_PRESENCE_HW_ENABLE, - PERM_FLAG_IDX_PHYSICAL_PRESENCE_CMD_ENABLE, -}; - -struct tpm_res_getcap_perm_flags { - struct tpm_rsp_header hdr; - u32 size; - struct tpm_permanent_flags perm_flags; -} PACKED; - -struct tpm_stclear_flags { - u16 tag; - u8 flags[5]; -} PACKED; - -#define STCLEAR_FLAG_IDX_DEACTIVATED 0 -#define STCLEAR_FLAG_IDX_DISABLE_FORCE_CLEAR 1 -#define STCLEAR_FLAG_IDX_PHYSICAL_PRESENCE 2 -#define STCLEAR_FLAG_IDX_PHYSICAL_PRESENCE_LOCK 3 -#define STCLEAR_FLAG_IDX_GLOBAL_LOCK 4 - -struct tpm_res_getcap_stclear_flags { - struct tpm_rsp_header hdr; - u32 size; - struct tpm_stclear_flags stclear_flags; -} PACKED; - -struct tpm_res_getcap_ownerauth { - struct tpm_rsp_header hdr; - u32 size; - u8 flag; -} PACKED; - -struct tpm_res_getcap_timeouts { - struct tpm_rsp_header hdr; - u32 size; - u32 timeouts[4]; -} PACKED; - -struct tpm_res_getcap_durations { - struct tpm_rsp_header hdr; - u32 size; - u32 durations[3]; -} PACKED; - -struct tpm_res_sha1start { - struct tpm_rsp_header hdr; - u32 max_num_bytes; -} PACKED; - -struct tpm_res_sha1complete { - struct tpm_rsp_header hdr; - u8 hash[20]; -} PACKED; - - -/**************************************************************** - * TPM v2.0 hardware commands - ****************************************************************/ - -#define TPM2_NO 0 -#define TPM2_YES 1 - -#define TPM2_SU_CLEAR 0x0000 -#define TPM2_SU_STATE 0x0001 - -#define TPM2_RH_OWNER 0x40000001 -#define TPM2_RS_PW 0x40000009 -#define TPM2_RH_ENDORSEMENT 0x4000000b -#define TPM2_RH_PLATFORM 0x4000000c - -#define TPM2_ALG_SHA1 0x0004 -#define TPM2_ALG_SHA256 0x000b -#define TPM2_ALG_SHA384 0x000c -#define TPM2_ALG_SHA512 0x000d -#define TPM2_ALG_SM3_256 0x0012 -#define TPM2_ALG_SHA3_256 0x0027 -#define TPM2_ALG_SHA3_384 0x0028 -#define TPM2_ALG_SHA3_512 0x0029 - -#define TPM2_ALG_SHA1_FLAG (1 << 0) -#define TPM2_ALG_SHA256_FLAG (1 << 1) -#define TPM2_ALG_SHA384_FLAG (1 << 2) -#define TPM2_ALG_SHA512_FLAG (1 << 3) -#define TPM2_ALG_SM3_256_FLAG (1 << 4) -#define TPM2_ALG_SHA3_256_FLAG (1 << 5) -#define TPM2_ALG_SHA3_384_FLAG (1 << 6) -#define TPM2_ALG_SHA3_512_FLAG (1 << 7) - -/* TPM 2 command tags */ -#define TPM2_ST_NO_SESSIONS 0x8001 -#define TPM2_ST_SESSIONS 0x8002 - -/* TPM 2 commands */ -#define TPM2_CC_HierarchyControl 0x121 -#define TPM2_CC_Clear 0x126 -#define TPM2_CC_ClearControl 0x127 -#define TPM2_CC_HierarchyChangeAuth 0x129 -#define TPM2_CC_PCR_Allocate 0x12b -#define TPM2_CC_SelfTest 0x143 -#define TPM2_CC_Startup 0x144 -#define TPM2_CC_Shutdown 0x145 -#define TPM2_CC_StirRandom 0x146 -#define TPM2_CC_GetCapability 0x17a -#define TPM2_CC_GetRandom 0x17b -#define TPM2_CC_PCR_Extend 0x182 - -/* TPM 2 error codes */ -#define TPM2_RC_INITIALIZE 0x100 - -/* TPM 2 Capabilities */ -#define TPM2_CAP_PCRS 0x00000005 - -/* TPM 2 data structures */ - -struct tpm2_req_stirrandom { - struct tpm_req_header hdr; - u16 size; - u64 stir; -} PACKED; - -struct tpm2_req_getrandom { - struct tpm_req_header hdr; - u16 bytesRequested; -} PACKED; - -struct tpm2b_20 { - u16 size; - u8 buffer[20]; -} PACKED; - -struct tpm2_res_getrandom { - struct tpm_rsp_header hdr; - struct tpm2b_20 rnd; -} PACKED; - -struct tpm2_authblock { - u32 handle; - u16 noncesize; /* always 0 */ - u8 contsession; /* always TPM2_YES */ - u16 pwdsize; /* always 0 */ -} PACKED; - -struct tpm2_req_hierarchychangeauth { - struct tpm_req_header hdr; - u32 authhandle; - u32 authblocksize; - struct tpm2_authblock authblock; - struct tpm2b_20 newAuth; -} PACKED; - -struct tpm2_req_extend { - struct tpm_req_header hdr; - u32 pcrindex; - u32 authblocksize; - struct tpm2_authblock authblock; - u8 digest[0]; -} PACKED; - -struct tpm2_req_clearcontrol { - struct tpm_req_header hdr; - u32 authhandle; - u32 authblocksize; - struct tpm2_authblock authblock; - u8 disable; -} PACKED; - -struct tpm2_req_clear { - struct tpm_req_header hdr; - u32 authhandle; - u32 authblocksize; - struct tpm2_authblock authblock; -} PACKED; - -struct tpm2_req_hierarchycontrol { - struct tpm_req_header hdr; - u32 authhandle; - u32 authblocksize; - struct tpm2_authblock authblock; - u32 enable; - u8 state; -} PACKED; - -struct tpm2_req_getcapability { - struct tpm_req_header hdr; - u32 capability; - u32 property; - u32 propertycount; -} PACKED; - -struct tpm2_res_getcapability { - struct tpm_rsp_header hdr; - u8 moreData; - u32 capability; - u8 data[0]; /* capability dependent data */ -} PACKED; - -struct tpm2_req_pcr_allocate { - struct tpm_req_header hdr; - u32 authhandle; - u32 authblocksize; - struct tpm2_authblock authblock; - u32 count; - u8 tpms_pcr_selections[4]; -} PACKED; - -struct tpms_pcr_selection { - u16 hashAlg; - u8 sizeOfSelect; - u8 pcrSelect[0]; -} PACKED; - -struct tpml_pcr_selection { - u32 count; - struct tpms_pcr_selection selections[0]; -} PACKED; - - -/**************************************************************** - * ACPI TCPA table interface - ****************************************************************/ - -/* event types: 10.4.1 / table 11 */ -#define EV_POST_CODE 1 -#define EV_NO_ACTION 3 -#define EV_SEPARATOR 4 -#define EV_ACTION 5 -#define EV_EVENT_TAG 6 -#define EV_COMPACT_HASH 12 -#define EV_IPL 13 -#define EV_IPL_PARTITION_DATA 14 - -struct tpm2_digest_value { - u16 hashAlg; - u8 hash[0]; /* size depends on hashAlg */ -} PACKED; - -struct tpm2_digest_values { - u32 count; - struct tpm2_digest_value digest[0]; -} PACKED; - -// Each entry in the TPM log contains: a tpm_log_header, a variable -// length digest, a tpm_log_trailer, and a variable length event. The -// 'digest' matches what is sent to the TPM hardware via the Extend -// command. On TPM1.2 the digest is a SHA1 hash; on TPM2.0 the digest -// contains a tpm2_digest_values struct followed by a variable number -// of tpm2_digest_value structs (as specified by the hardware via the -// TPM2_CAP_PCRS request). -struct tpm_log_header { - u32 pcrindex; - u32 eventtype; - u8 digest[0]; -} PACKED; - -struct tpm_log_trailer { - u32 eventdatasize; - u8 event[0]; -} PACKED; - -struct TCG_EfiSpecIdEventStruct { - u8 signature[16]; - u32 platformClass; - u8 specVersionMinor; - u8 specVersionMajor; - u8 specErrata; - u8 uintnSize; - u32 numberOfAlgorithms; - struct TCG_EfiSpecIdEventAlgorithmSize { - u16 algorithmId; - u16 digestSize; - } digestSizes[]; - /* - u8 vendorInfoSize; - u8 vendorInfo[0]; - */ -} PACKED; - -#define TPM_TCPA_ACPI_CLASS_CLIENT 0 - -struct pcctes -{ - u32 eventid; - u32 eventdatasize; - u8 digest[SHA1_BUFSIZE]; -} PACKED; - -struct pcctes_romex -{ - u32 eventid; - u32 eventdatasize; - u16 reserved; - u16 pfa; - u8 digest[SHA1_BUFSIZE]; -} PACKED; - - -/**************************************************************** - * Physical presence interface - ****************************************************************/ - -#define TPM_STATE_ENABLED 1 -#define TPM_STATE_ACTIVE 2 -#define TPM_STATE_OWNED 4 -#define TPM_STATE_OWNERINSTALL 8 - -#define TPM_PPI_OP_NOOP 0 -#define TPM_PPI_OP_ENABLE 1 -#define TPM_PPI_OP_DISABLE 2 -#define TPM_PPI_OP_ACTIVATE 3 -#define TPM_PPI_OP_DEACTIVATE 4 -#define TPM_PPI_OP_CLEAR 5 -#define TPM_PPI_OP_SET_OWNERINSTALL_TRUE 8 -#define TPM_PPI_OP_SET_OWNERINSTALL_FALSE 9 - -#endif // tcg.h diff --git a/src/tcgbios.c b/src/tcgbios.c deleted file mode 100644 index fe844b2..0000000 --- a/src/tcgbios.c +++ /dev/null @@ -1,2321 +0,0 @@ -// Implementation of the TCG BIOS extension according to the specification -// described in specs found at -// http://www.trustedcomputinggroup.org/resources/pc_client_work_group_specific_implementation_specification_for_conventional_bios -// -// Copyright (C) 2006-2011, 2014, 2015 IBM Corporation -// -// Authors: -// Stefan Berger -// -// This file may be distributed under the terms of the GNU LGPLv3 license. - -#include "bregs.h" // struct bregs -#include "byteorder.h" // cpu_to_* -#include "config.h" // CONFIG_TCGBIOS -#include "farptr.h" // MAKE_FLATPTR -#include "fw/paravirt.h" // runningOnXen -#include "hw/tpm_drivers.h" // tpm_drivers[] -#include "output.h" // dprintf -#include "sha.h" // sha1, sha256, ... -#include "std/acpi.h" // RSDP_SIGNATURE, rsdt_descriptor -#include "std/smbios.h" // struct smbios_21_entry_point -#include "std/tcg.h" // TCG_PC_LOGOVERFLOW -#include "string.h" // checksum -#include "tcgbios.h"// tpm_*, prototypes -#include "util.h" // printf, get_keystroke -#include "stacks.h" // wait_threads, reset -#include "malloc.h" // malloc_high - - -/**************************************************************** - * ACPI TCPA table interface - ****************************************************************/ - -struct { - /* length of the TCPA log buffer */ - u32 log_area_minimum_length; - - /* start address of TCPA log buffer */ - u8 * log_area_start_address; - - /* number of log entries written */ - u32 entry_count; - - /* address to write next log entry to */ - u8 * log_area_next_entry; - - /* address of last entry written (need for TCG_StatusCheck) */ - u8 * log_area_last_entry; -} tpm_state VARLOW; - -static int tpm_set_log_area(u8 *log_area_start_address, - u32 log_area_minimum_length) -{ - if (!log_area_start_address || !log_area_minimum_length) - return -1; - - memset(log_area_start_address, 0, log_area_minimum_length); - tpm_state.log_area_start_address = log_area_start_address; - tpm_state.log_area_minimum_length = log_area_minimum_length; - tpm_state.log_area_next_entry = log_area_start_address; - tpm_state.log_area_last_entry = NULL; - tpm_state.entry_count = 0; - return 0; -} - -static int -tpm_tcpa_probe(void) -{ - struct tcpa_descriptor_rev2 *tcpa = find_acpi_table(TCPA_SIGNATURE); - if (!tcpa) - return -1; - - dprintf(DEBUG_tcg, "TCGBIOS: TCPA: LASA = %p, LAML = %u\n", - (u8 *)(long)tcpa->log_area_start_address, - tcpa->log_area_minimum_length); - - return tpm_set_log_area((u8*)(long)tcpa->log_area_start_address, - tcpa->log_area_minimum_length); -} - -static int -tpm_tpm2_probe(void) -{ - struct tpm2_descriptor_rev2 *tpm2 = find_acpi_table(TPM2_SIGNATURE); - if (!tpm2) - return -1; - - if (tpm2->length < 76) - return -1; - - dprintf(DEBUG_tcg, "TCGBIOS: TPM2: LASA = %p, LAML = %u\n", - (u8 *)(long)tpm2->log_area_start_address, - tpm2->log_area_minimum_length); - - return tpm_set_log_area((u8*)(long)tpm2->log_area_start_address, - tpm2->log_area_minimum_length); -} - -/* - * Extend the ACPI log with the given entry by copying the - * entry data into the log. - * Input - * entry : The header data to use (including the variable length digest) - * digest_len : Length of the digest in 'entry' - * event : Pointer to the event body to be copied into the log - * event_len : Length of 'event' - * - * Output: - * Returns an error code in case of faiure, 0 in case of success - */ -static int -tpm_log_event(struct tpm_log_header *entry, int digest_len - , const void *event, int event_len) -{ - dprintf(DEBUG_tcg, "TCGBIOS: LASA = %p, next entry = %p\n", - tpm_state.log_area_start_address, tpm_state.log_area_next_entry); - - if (tpm_state.log_area_next_entry == NULL) - return -1; - - u32 size = (sizeof(*entry) + digest_len - + sizeof(struct tpm_log_trailer) + event_len); - u32 logsize = (tpm_state.log_area_next_entry + size - - tpm_state.log_area_start_address); - if (logsize > tpm_state.log_area_minimum_length) { - dprintf(DEBUG_tcg, "TCGBIOS: LOG OVERFLOW: size = %d\n", size); - return -1; - } - - void *dest = tpm_state.log_area_next_entry; - memcpy(dest, entry, sizeof(*entry) + digest_len); - struct tpm_log_trailer *t = dest + sizeof(*entry) + digest_len; - t->eventdatasize = event_len; - memcpy(t->event, event, event_len); - - tpm_state.log_area_last_entry = tpm_state.log_area_next_entry; - tpm_state.log_area_next_entry += size; - tpm_state.entry_count++; - - return 0; -} - - -/**************************************************************** - * Digest formatting - ****************************************************************/ - -static TPMVersion TPM_version; -static u32 tpm20_pcr_selection_size; -static struct tpml_pcr_selection *tpm20_pcr_selection; - -// A 'struct tpm_log_entry' is a local data structure containing a -// 'tpm_log_header' followed by space for the maximum supported -// digest. (The digest is a sha1 hash on tpm1.2 or a series of -// tpm2_digest_value structs on tpm2.0) -struct tpm_log_entry { - struct tpm_log_header hdr; - u8 pad[sizeof(struct tpm2_digest_values) - + 8 * sizeof(struct tpm2_digest_value) - + SHA1_BUFSIZE + SHA256_BUFSIZE + SHA384_BUFSIZE - + SHA512_BUFSIZE + SM3_256_BUFSIZE + SHA3_256_BUFSIZE - + SHA3_384_BUFSIZE + SHA3_512_BUFSIZE]; -} PACKED; - -static const struct hash_parameters { - u16 hashalg; - u8 hashalg_flag; - u8 hash_buffersize; - const char *name; - void (*hashfunc)(const u8 *data, u32 length, u8 *hash); -} hash_parameters[] = { - { - .hashalg = TPM2_ALG_SHA1, - .hashalg_flag = TPM2_ALG_SHA1_FLAG, - .hash_buffersize = SHA1_BUFSIZE, - .name = "SHA1", - .hashfunc = sha1, - }, { - .hashalg = TPM2_ALG_SHA256, - .hashalg_flag = TPM2_ALG_SHA256_FLAG, - .hash_buffersize = SHA256_BUFSIZE, - .name = "SHA256", - .hashfunc = sha256, - }, { - .hashalg = TPM2_ALG_SHA384, - .hashalg_flag = TPM2_ALG_SHA384_FLAG, - .hash_buffersize = SHA384_BUFSIZE, - .name = "SHA384", - .hashfunc = sha384, - }, { - .hashalg = TPM2_ALG_SHA512, - .hashalg_flag = TPM2_ALG_SHA512_FLAG, - .hash_buffersize = SHA512_BUFSIZE, - .name = "SHA512", - .hashfunc = sha512, - }, { - .hashalg = TPM2_ALG_SM3_256, - .hashalg_flag = TPM2_ALG_SM3_256_FLAG, - .hash_buffersize = SM3_256_BUFSIZE, - .name = "SM3-256", - }, { - .hashalg = TPM2_ALG_SHA3_256, - .hashalg_flag = TPM2_ALG_SHA3_256_FLAG, - .hash_buffersize = SHA3_256_BUFSIZE, - .name = "SHA3-256", - }, { - .hashalg = TPM2_ALG_SHA3_384, - .hashalg_flag = TPM2_ALG_SHA3_384_FLAG, - .hash_buffersize = SHA3_384_BUFSIZE, - .name = "SHA3-384", - }, { - .hashalg = TPM2_ALG_SHA3_512, - .hashalg_flag = TPM2_ALG_SHA3_512_FLAG, - .hash_buffersize = SHA3_512_BUFSIZE, - .name = "SHA3-512", - } -}; - -static int -tpm20_get_hash_buffersize(u16 hashAlg) -{ - unsigned i; - - for (i = 0; i < ARRAY_SIZE(hash_parameters); i++) { - if (hash_parameters[i].hashalg == hashAlg) - return hash_parameters[i].hash_buffersize; - } - return -1; -} - -static u8 -tpm20_hashalg_to_flag(u16 hashAlg) -{ - unsigned i; - - for (i = 0; i < ARRAY_SIZE(hash_parameters); i++) { - if (hash_parameters[i].hashalg == hashAlg) - return hash_parameters[i].hashalg_flag; - } - return 0; -} - -static u16 -tpm20_hashalg_flag_to_hashalg(u8 hashalg_flag) -{ - unsigned i; - - for (i = 0; i < ARRAY_SIZE(hash_parameters); i++) { - if (hash_parameters[i].hashalg_flag == hashalg_flag) - return hash_parameters[i].hashalg; - } - return 0; -} - -static const char * -tpm20_hashalg_flag_to_name(u8 hashalg_flag) -{ - unsigned i; - - for (i = 0; i < ARRAY_SIZE(hash_parameters); i++) { - if (hash_parameters[i].hashalg_flag == hashalg_flag) - return hash_parameters[i].name; - } - return NULL; -} - -static void tpm2_hash_data(u16 hashAlg, const u8 *data, u32 data_len, u8 *hash) -{ - unsigned i; - - for (i = 0; i < ARRAY_SIZE(hash_parameters); i++) { - if (hash_parameters[i].hashalg == hashAlg) { - if (hash_parameters[i].hashfunc) { - hash_parameters[i].hashfunc(data, data_len, hash); - } else { - memset(hash, 0xff, hash_parameters[i].hash_buffersize); - } - } - } -} - -// Add an entry at the start of the log describing digest formats -static int -tpm20_write_EfiSpecIdEventStruct(void) -{ - if (!tpm20_pcr_selection) - return -1; - - struct { - struct TCG_EfiSpecIdEventStruct hdr; - u8 pad[sizeof(struct tpm_log_entry) + sizeof(u8)]; - } event = { - .hdr.signature = "Spec ID Event03", - .hdr.platformClass = TPM_TCPA_ACPI_CLASS_CLIENT, - .hdr.specVersionMinor = 0, - .hdr.specVersionMajor = 2, - .hdr.specErrata = 2, - .hdr.uintnSize = 2, - }; - - struct tpms_pcr_selection *sel = tpm20_pcr_selection->selections; - void *nsel, *end = (void*)tpm20_pcr_selection + tpm20_pcr_selection_size; - - u32 count, numAlgs = 0; - for (count = 0; count < be32_to_cpu(tpm20_pcr_selection->count); count++) { - u8 sizeOfSelect = sel->sizeOfSelect; - - nsel = (void*)sel + sizeof(*sel) + sizeOfSelect; - if (nsel > end) - break; - - if (!sizeOfSelect || sel->pcrSelect[0] == 0) { - sel = nsel; - continue; - } - - int hsize = tpm20_get_hash_buffersize(be16_to_cpu(sel->hashAlg)); - if (hsize < 0) { - dprintf(DEBUG_tcg, "TPM is using an unsupported hash: %d\n", - be16_to_cpu(sel->hashAlg)); - return -1; - } - - int event_size = offsetof(struct TCG_EfiSpecIdEventStruct - , digestSizes[count+1]); - if (event_size > sizeof(event) - sizeof(u8)) { - dprintf(DEBUG_tcg, "EfiSpecIdEventStruct pad too small\n"); - return -1; - } - - event.hdr.digestSizes[numAlgs].algorithmId = be16_to_cpu(sel->hashAlg); - event.hdr.digestSizes[numAlgs].digestSize = hsize; - numAlgs++; - - sel = nsel; - } - - if (sel != end) { - dprintf(DEBUG_tcg, "Malformed pcr selection structure fron TPM\n"); - return -1; - } - - event.hdr.numberOfAlgorithms = numAlgs; - int event_size = offsetof(struct TCG_EfiSpecIdEventStruct - , digestSizes[numAlgs]); - u8 *vendorInfoSize = (void*)&event + event_size; - *vendorInfoSize = 0; - event_size += sizeof(*vendorInfoSize); - - struct tpm_log_entry le = { - .hdr.eventtype = EV_NO_ACTION, - }; - return tpm_log_event(&le.hdr, SHA1_BUFSIZE, &event, event_size); -} - -/* - * Build the TPM2 tpm2_digest_values data structure from the given hash. - * Follow the PCR bank configuration of the TPM and write the same hash - * in either truncated or zero-padded form in the areas of all the other - * hashes. For example, write the sha1 hash in the area of the sha256 - * hash and fill the remaining bytes with zeros. Or truncate the sha256 - * hash when writing it in the area of the sha1 hash. - * - * le: the log entry to build the digest in - * hashdata: the data to hash - * hashdata_len: the length of the hashdata - * bigEndian: whether to build in big endian format for the TPM or - * little endian for the log - * - * Returns the digest size; -1 on fatal error - */ -static int -tpm20_build_digest(struct tpm_log_entry *le, - const u8 *hashdata, u32 hashdata_len, int bigEndian) -{ - if (!tpm20_pcr_selection) - return -1; - - struct tpms_pcr_selection *sel = tpm20_pcr_selection->selections; - void *nsel, *end = (void*)tpm20_pcr_selection + tpm20_pcr_selection_size; - void *dest = le->hdr.digest + sizeof(struct tpm2_digest_values); - - u32 count, numAlgs = 0; - for (count = 0; count < be32_to_cpu(tpm20_pcr_selection->count); count++) { - u8 sizeOfSelect = sel->sizeOfSelect; - - nsel = (void*)sel + sizeof(*sel) + sizeOfSelect; - if (nsel > end) - break; - - /* PCR 0-7 unused? -- skip */ - if (!sizeOfSelect || sel->pcrSelect[0] == 0) { - sel = nsel; - continue; - } - - int hsize = tpm20_get_hash_buffersize(be16_to_cpu(sel->hashAlg)); - if (hsize < 0) { - dprintf(DEBUG_tcg, "TPM is using an unsupported hash: %d\n", - be16_to_cpu(sel->hashAlg)); - return -1; - } - - /* buffer size sanity check before writing */ - struct tpm2_digest_value *v = dest; - if (dest + sizeof(*v) + hsize > (void*)le + sizeof(*le)) { - dprintf(DEBUG_tcg, "tpm_log_entry is too small\n"); - return -1; - } - - if (bigEndian) - v->hashAlg = sel->hashAlg; - else - v->hashAlg = be16_to_cpu(sel->hashAlg); - - tpm2_hash_data(be16_to_cpu(sel->hashAlg), hashdata, hashdata_len, - v->hash); - - dest += sizeof(*v) + hsize; - sel = nsel; - - numAlgs++; - } - - if (sel != end) { - dprintf(DEBUG_tcg, "Malformed pcr selection structure fron TPM\n"); - return -1; - } - - struct tpm2_digest_values *v = (void*)le->hdr.digest; - if (bigEndian) - v->count = cpu_to_be32(numAlgs); - else - v->count = numAlgs; - - return dest - (void*)le->hdr.digest; -} - -static int -tpm12_build_digest(struct tpm_log_entry *le, - const u8 *hashdata, u32 hashdata_len) -{ - sha1(hashdata, hashdata_len, le->hdr.digest); - return SHA1_BUFSIZE; -} - -static int -tpm12_build_digest_direct(struct tpm_log_entry *le, const u8 *sha1) -{ - // On TPM 1.2 the digest contains just the SHA1 hash - memcpy(le->hdr.digest, sha1, SHA1_BUFSIZE); - return SHA1_BUFSIZE; -} - -static int -tpm_build_digest(struct tpm_log_entry *le, const u8 *hashdata, u32 hashdata_len - , int bigEndian) -{ - switch (TPM_version) { - case TPM_VERSION_1_2: - return tpm12_build_digest(le, hashdata, hashdata_len); - case TPM_VERSION_2: - return tpm20_build_digest(le, hashdata, hashdata_len, bigEndian); - } - return -1; -} - - -/**************************************************************** - * TPM hardware command wrappers - ****************************************************************/ - -// Helper function for sending tpm commands that take a single -// optional parameter (0, 1, or 2 bytes) and have no special response. -static int -tpm_simple_cmd(u8 locty, u32 ordinal - , int param_size, u16 param, enum tpmDurationType to_t) -{ - struct { - struct tpm_req_header trqh; - u16 param; - } PACKED req = { - .trqh.totlen = cpu_to_be32(sizeof(req.trqh) + param_size), - .trqh.ordinal = cpu_to_be32(ordinal), - .param = param_size == 2 ? cpu_to_be16(param) : param, - }; - switch (TPM_version) { - case TPM_VERSION_1_2: - req.trqh.tag = cpu_to_be16(TPM_TAG_RQU_CMD); - break; - case TPM_VERSION_2: - req.trqh.tag = cpu_to_be16(TPM2_ST_NO_SESSIONS); - break; - } - - u8 obuffer[64]; - struct tpm_rsp_header *trsh = (void*)obuffer; - u32 obuffer_len = sizeof(obuffer); - memset(obuffer, 0x0, sizeof(obuffer)); - - int ret = tpmhw_transmit(locty, &req.trqh, obuffer, &obuffer_len, to_t); - ret = ret ? -1 : be32_to_cpu(trsh->errcode); - dprintf(DEBUG_tcg, "Return from tpm_simple_cmd(%x, %x) = %x\n", - ordinal, param, ret); - return ret; -} - -static int -tpm20_getcapability(u32 capability, u32 property, u32 count, - struct tpm_rsp_header *rsp, u32 rsize) -{ - struct tpm2_req_getcapability trg = { - .hdr.tag = cpu_to_be16(TPM2_ST_NO_SESSIONS), - .hdr.totlen = cpu_to_be32(sizeof(trg)), - .hdr.ordinal = cpu_to_be32(TPM2_CC_GetCapability), - .capability = cpu_to_be32(capability), - .property = cpu_to_be32(property), - .propertycount = cpu_to_be32(count), - }; - - u32 resp_size = rsize; - int ret = tpmhw_transmit(0, &trg.hdr, rsp, &resp_size, - TPM_DURATION_TYPE_SHORT); - ret = (ret || - rsize < be32_to_cpu(rsp->totlen)) ? -1 : be32_to_cpu(rsp->errcode); - - dprintf(DEBUG_tcg, "TCGBIOS: Return value from sending TPM2_CC_GetCapability = 0x%08x\n", - ret); - - return ret; -} - -static int -tpm20_get_pcrbanks(void) -{ - u8 buffer[128]; - struct tpm2_res_getcapability *trg = - (struct tpm2_res_getcapability *)&buffer; - - int ret = tpm20_getcapability(TPM2_CAP_PCRS, 0, 8, &trg->hdr, - sizeof(buffer)); - if (ret) - return ret; - - /* defend against (broken) TPM sending packets that are too short */ - u32 resplen = be32_to_cpu(trg->hdr.totlen); - if (resplen <= offsetof(struct tpm2_res_getcapability, data)) - return -1; - - u32 size = resplen - offsetof(struct tpm2_res_getcapability, data); - /* we need a valid tpml_pcr_selection up to and including sizeOfSelect */ - if (size < offsetof(struct tpml_pcr_selection, selections) + - offsetof(struct tpms_pcr_selection, pcrSelect)) - return -1; - - tpm20_pcr_selection = malloc_high(size); - if (tpm20_pcr_selection) { - memcpy(tpm20_pcr_selection, &trg->data, size); - tpm20_pcr_selection_size = size; - } else { - warn_noalloc(); - ret = -1; - } - - return ret; -} - -static int -tpm20_get_suppt_pcrbanks(u8 *suppt_pcrbanks, u8 *active_pcrbanks) -{ - *suppt_pcrbanks = 0; - *active_pcrbanks = 0; - - if (!tpm20_pcr_selection) - return -1; - - struct tpms_pcr_selection *sel = tpm20_pcr_selection->selections; - void *end = (void*)tpm20_pcr_selection + tpm20_pcr_selection_size; - - while (1) { - u8 sizeOfSelect = sel->sizeOfSelect; - void *nsel = (void*)sel + sizeof(*sel) + sizeOfSelect; - if (nsel > end) - return 0; - - u16 hashalg = be16_to_cpu(sel->hashAlg); - u8 hashalg_flag = tpm20_hashalg_to_flag(hashalg); - - *suppt_pcrbanks |= hashalg_flag; - - unsigned i; - for (i = 0; i < sizeOfSelect; i++) { - if (sel->pcrSelect[i]) { - *active_pcrbanks |= hashalg_flag; - break; - } - } - - sel = nsel; - } -} - -static int -tpm20_set_pcrbanks(u32 active_banks) -{ - struct tpm2_req_pcr_allocate trpa = { - .hdr.tag = cpu_to_be16(TPM2_ST_SESSIONS), - .hdr.ordinal = cpu_to_be32(TPM2_CC_PCR_Allocate), - .authhandle = cpu_to_be32(TPM2_RH_PLATFORM), - .authblocksize = cpu_to_be32(sizeof(trpa.authblock)), - .authblock = { - .handle = cpu_to_be32(TPM2_RS_PW), - .noncesize = cpu_to_be16(0), - .contsession = TPM2_YES, - .pwdsize = cpu_to_be16(0), - }, - }; - struct tpms_pcr_selection3 { - u16 hashAlg; - u8 sizeOfSelect; - u8 pcrSelect[3]; - } tps[ARRAY_SIZE(trpa.tpms_pcr_selections)]; - int i = 0; - u8 hashalg_flag = TPM2_ALG_SHA1_FLAG; - u8 dontcare, suppt_banks; - - tpm20_get_suppt_pcrbanks(&suppt_banks, &dontcare); - - while (hashalg_flag) { - if ((hashalg_flag & suppt_banks)) { - u16 hashalg = tpm20_hashalg_flag_to_hashalg(hashalg_flag); - - if (hashalg) { - u8 mask = 0; - tps[i].hashAlg = cpu_to_be16(hashalg); - tps[i].sizeOfSelect = 3; - - if (active_banks & hashalg_flag) - mask = 0xff; - - tps[i].pcrSelect[0] = mask; - tps[i].pcrSelect[1] = mask; - tps[i].pcrSelect[2] = mask; - i++; - } - } - hashalg_flag <<= 1; - } - - trpa.count = cpu_to_be32(i); - memcpy(trpa.tpms_pcr_selections, tps, i * sizeof(tps[0])); - trpa.hdr.totlen = cpu_to_be32(offsetof(struct tpm2_req_pcr_allocate, - tpms_pcr_selections) + - i * sizeof(tps[0])); - - struct tpm_rsp_header rsp; - u32 resp_length = sizeof(rsp); - - int ret = tpmhw_transmit(0, &trpa.hdr, &rsp, &resp_length, - TPM_DURATION_TYPE_SHORT); - ret = ret ? -1 : be32_to_cpu(rsp.errcode); - - return ret; -} - -static int tpm20_activate_pcrbanks(u32 active_banks) -{ - int ret = tpm20_set_pcrbanks(active_banks); - if (!ret) - ret = tpm_simple_cmd(0, TPM2_CC_Shutdown, - 2, TPM2_SU_CLEAR, TPM_DURATION_TYPE_SHORT); - if (!ret) - reset(); - return ret; -} - -static int -tpm12_get_capability(u32 cap, u32 subcap, struct tpm_rsp_header *rsp, u32 rsize) -{ - struct tpm_req_getcap trgc = { - .hdr.tag = cpu_to_be16(TPM_TAG_RQU_CMD), - .hdr.totlen = cpu_to_be32(sizeof(trgc)), - .hdr.ordinal = cpu_to_be32(TPM_ORD_GetCapability), - .capArea = cpu_to_be32(cap), - .subCapSize = cpu_to_be32(sizeof(trgc.subCap)), - .subCap = cpu_to_be32(subcap) - }; - u32 resp_size = rsize; - int ret = tpmhw_transmit(0, &trgc.hdr, rsp, &resp_size, - TPM_DURATION_TYPE_SHORT); - ret = (ret || resp_size != rsize) ? -1 : be32_to_cpu(rsp->errcode); - dprintf(DEBUG_tcg, "TCGBIOS: Return code from TPM_GetCapability(%d, %d)" - " = %x\n", cap, subcap, ret); - return ret; -} - -static int -tpm12_read_permanent_flags(char *buf, int buf_len) -{ - memset(buf, 0, buf_len); - - struct tpm_res_getcap_perm_flags pf; - int ret = tpm12_get_capability(TPM_CAP_FLAG, TPM_CAP_FLAG_PERMANENT - , &pf.hdr, sizeof(pf)); - if (ret) - return -1; - - memcpy(buf, &pf.perm_flags, buf_len); - - return 0; -} - -static int -tpm12_determine_timeouts(void) -{ - struct tpm_res_getcap_timeouts timeouts; - int ret = tpm12_get_capability(TPM_CAP_PROPERTY, TPM_CAP_PROP_TIS_TIMEOUT - , &timeouts.hdr, sizeof(timeouts)); - if (ret) - return ret; - - struct tpm_res_getcap_durations durations; - ret = tpm12_get_capability(TPM_CAP_PROPERTY, TPM_CAP_PROP_DURATION - , &durations.hdr, sizeof(durations)); - if (ret) - return ret; - - int i; - for (i = 0; i < 3; i++) - durations.durations[i] = be32_to_cpu(durations.durations[i]); - - for (i = 0; i < 4; i++) - timeouts.timeouts[i] = be32_to_cpu(timeouts.timeouts[i]); - - dprintf(DEBUG_tcg, "TCGBIOS: timeouts: %u %u %u %u\n", - timeouts.timeouts[0], - timeouts.timeouts[1], - timeouts.timeouts[2], - timeouts.timeouts[3]); - - dprintf(DEBUG_tcg, "TCGBIOS: durations: %u %u %u\n", - durations.durations[0], - durations.durations[1], - durations.durations[2]); - - tpmhw_set_timeouts(timeouts.timeouts, durations.durations); - - return 0; -} - -static void -tpm20_set_timeouts(void) -{ - u32 durations[3] = { - TPM2_DEFAULT_DURATION_SHORT, - TPM2_DEFAULT_DURATION_MEDIUM, - TPM2_DEFAULT_DURATION_LONG, - }; - u32 timeouts[4] = { - TIS2_DEFAULT_TIMEOUT_A, - TIS2_DEFAULT_TIMEOUT_B, - TIS2_DEFAULT_TIMEOUT_C, - TIS2_DEFAULT_TIMEOUT_D, - }; - - tpmhw_set_timeouts(timeouts, durations); -} - -static int -tpm12_extend(struct tpm_log_entry *le, int digest_len) -{ - struct tpm_req_extend tre = { - .hdr.tag = cpu_to_be16(TPM_TAG_RQU_CMD), - .hdr.totlen = cpu_to_be32(sizeof(tre)), - .hdr.ordinal = cpu_to_be32(TPM_ORD_Extend), - .pcrindex = cpu_to_be32(le->hdr.pcrindex), - }; - memcpy(tre.digest, le->hdr.digest, sizeof(tre.digest)); - - struct tpm_rsp_extend rsp; - u32 resp_length = sizeof(rsp); - int ret = tpmhw_transmit(0, &tre.hdr, &rsp, &resp_length, - TPM_DURATION_TYPE_SHORT); - if (ret || resp_length != sizeof(rsp) || rsp.hdr.errcode) - return -1; - - return 0; -} - -static int tpm20_extend(struct tpm_log_entry *le, int digest_len) -{ - struct tpm2_req_extend tmp_tre = { - .hdr.tag = cpu_to_be16(TPM2_ST_SESSIONS), - .hdr.totlen = cpu_to_be32(0), - .hdr.ordinal = cpu_to_be32(TPM2_CC_PCR_Extend), - .pcrindex = cpu_to_be32(le->hdr.pcrindex), - .authblocksize = cpu_to_be32(sizeof(tmp_tre.authblock)), - .authblock = { - .handle = cpu_to_be32(TPM2_RS_PW), - .noncesize = cpu_to_be16(0), - .contsession = TPM2_YES, - .pwdsize = cpu_to_be16(0), - }, - }; - u8 buffer[sizeof(tmp_tre) + sizeof(le->pad)]; - struct tpm2_req_extend *tre = (struct tpm2_req_extend *)buffer; - - memcpy(tre, &tmp_tre, sizeof(tmp_tre)); - memcpy(&tre->digest[0], le->hdr.digest, digest_len); - - tre->hdr.totlen = cpu_to_be32(sizeof(tmp_tre) + digest_len); - - struct tpm_rsp_header rsp; - u32 resp_length = sizeof(rsp); - int ret = tpmhw_transmit(0, &tre->hdr, &rsp, &resp_length, - TPM_DURATION_TYPE_SHORT); - if (ret || resp_length != sizeof(rsp) || rsp.errcode) - return -1; - - return 0; -} - -static int -tpm_extend(struct tpm_log_entry *le, int digest_len) -{ - switch (TPM_version) { - case TPM_VERSION_1_2: - return tpm12_extend(le, digest_len); - case TPM_VERSION_2: - return tpm20_extend(le, digest_len); - } - return -1; -} - -static int -tpm20_stirrandom(void) -{ - struct tpm2_req_stirrandom stir = { - .hdr.tag = cpu_to_be16(TPM2_ST_NO_SESSIONS), - .hdr.totlen = cpu_to_be32(sizeof(stir)), - .hdr.ordinal = cpu_to_be32(TPM2_CC_StirRandom), - .size = cpu_to_be16(sizeof(stir.stir)), - .stir = rdtscll(), - }; - /* set more bits to stir with */ - stir.stir += swab64(rdtscll()); - - struct tpm_rsp_header rsp; - u32 resp_length = sizeof(rsp); - int ret = tpmhw_transmit(0, &stir.hdr, &rsp, &resp_length, - TPM_DURATION_TYPE_SHORT); - if (ret || resp_length != sizeof(rsp) || rsp.errcode) - ret = -1; - - dprintf(DEBUG_tcg, "TCGBIOS: Return value from sending TPM2_CC_StirRandom = 0x%08x\n", - ret); - - return ret; -} - -static int -tpm20_getrandom(u8 *buf, u16 buf_len) -{ - struct tpm2_res_getrandom rsp; - - if (buf_len > sizeof(rsp.rnd.buffer)) - return -1; - - struct tpm2_req_getrandom trgr = { - .hdr.tag = cpu_to_be16(TPM2_ST_NO_SESSIONS), - .hdr.totlen = cpu_to_be32(sizeof(trgr)), - .hdr.ordinal = cpu_to_be32(TPM2_CC_GetRandom), - .bytesRequested = cpu_to_be16(buf_len), - }; - u32 resp_length = sizeof(rsp); - - int ret = tpmhw_transmit(0, &trgr.hdr, &rsp, &resp_length, - TPM_DURATION_TYPE_MEDIUM); - if (ret || resp_length != sizeof(rsp) || rsp.hdr.errcode) - ret = -1; - else - memcpy(buf, rsp.rnd.buffer, buf_len); - - dprintf(DEBUG_tcg, "TCGBIOS: Return value from sending TPM2_CC_GetRandom = 0x%08x\n", - ret); - - return ret; -} - -static int -tpm20_hierarchycontrol(u32 hierarchy, u8 state) -{ - /* we will try to deactivate the TPM now - ignoring all errors */ - struct tpm2_req_hierarchycontrol trh = { - .hdr.tag = cpu_to_be16(TPM2_ST_SESSIONS), - .hdr.totlen = cpu_to_be32(sizeof(trh)), - .hdr.ordinal = cpu_to_be32(TPM2_CC_HierarchyControl), - .authhandle = cpu_to_be32(TPM2_RH_PLATFORM), - .authblocksize = cpu_to_be32(sizeof(trh.authblock)), - .authblock = { - .handle = cpu_to_be32(TPM2_RS_PW), - .noncesize = cpu_to_be16(0), - .contsession = TPM2_YES, - .pwdsize = cpu_to_be16(0), - }, - .enable = cpu_to_be32(hierarchy), - .state = state, - }; - struct tpm_rsp_header rsp; - u32 resp_length = sizeof(rsp); - int ret = tpmhw_transmit(0, &trh.hdr, &rsp, &resp_length, - TPM_DURATION_TYPE_MEDIUM); - if (ret || resp_length != sizeof(rsp) || rsp.errcode) - ret = -1; - - dprintf(DEBUG_tcg, "TCGBIOS: Return value from sending TPM2_CC_HierarchyControl = 0x%08x\n", - ret); - - return ret; -} - -static int -tpm20_hierarchychangeauth(u8 auth[20]) -{ - struct tpm2_req_hierarchychangeauth trhca = { - .hdr.tag = cpu_to_be16(TPM2_ST_SESSIONS), - .hdr.totlen = cpu_to_be32(sizeof(trhca)), - .hdr.ordinal = cpu_to_be32(TPM2_CC_HierarchyChangeAuth), - .authhandle = cpu_to_be32(TPM2_RH_PLATFORM), - .authblocksize = cpu_to_be32(sizeof(trhca.authblock)), - .authblock = { - .handle = cpu_to_be32(TPM2_RS_PW), - .noncesize = cpu_to_be16(0), - .contsession = TPM2_YES, - .pwdsize = cpu_to_be16(0), - }, - .newAuth = { - .size = cpu_to_be16(sizeof(trhca.newAuth.buffer)), - }, - }; - memcpy(trhca.newAuth.buffer, auth, sizeof(trhca.newAuth.buffer)); - - struct tpm_rsp_header rsp; - u32 resp_length = sizeof(rsp); - int ret = tpmhw_transmit(0, &trhca.hdr, &rsp, &resp_length, - TPM_DURATION_TYPE_MEDIUM); - if (ret || resp_length != sizeof(rsp) || rsp.errcode) - ret = -1; - - dprintf(DEBUG_tcg, "TCGBIOS: Return value from sending TPM2_CC_HierarchyChangeAuth = 0x%08x\n", - ret); - - return ret; -} - - -/**************************************************************** - * Setup and Measurements - ****************************************************************/ - -static int TPM_has_physical_presence; -u8 TPM_working VARLOW; - -static int -tpm_is_working(void) -{ - return CONFIG_TCGBIOS && TPM_working; -} - -static void -tpm_set_failure(void) -{ - switch (TPM_version) { - case TPM_VERSION_1_2: - /* - * We will try to deactivate the TPM now - ignoring all errors - * Physical presence is asserted. - */ - - tpm_simple_cmd(0, TPM_ORD_SetTempDeactivated, - 0, 0, TPM_DURATION_TYPE_SHORT); - break; - case TPM_VERSION_2: - tpm20_hierarchycontrol(TPM2_RH_ENDORSEMENT, TPM2_NO); - tpm20_hierarchycontrol(TPM2_RH_OWNER, TPM2_NO); - tpm20_hierarchycontrol(TPM2_RH_PLATFORM, TPM2_NO); - break; - } - - TPM_working = 0; -} - -/* - * Add a measurement to the log; the data at data_seg:data/length are - * appended to the TCG_PCClientPCREventStruct - * - * Input parameters: - * pcrindex : which PCR to extend - * event_type : type of event; specs section on 'Event Types' - * event : pointer to info (e.g., string) to be added to log as-is - * event_length: length of the event - * hashdata : pointer to the data to be hashed - * hashdata_length: length of the data to be hashed - */ -static void -tpm_add_measurement_to_log(u32 pcrindex, u32 event_type, - const char *event, u32 event_length, - const u8 *hashdata, u32 hashdata_length) -{ - if (!tpm_is_working()) - return; - - struct tpm_log_entry le = { - .hdr.pcrindex = pcrindex, - .hdr.eventtype = event_type, - }; - int digest_len = tpm_build_digest(&le, hashdata, hashdata_length, 1); - if (digest_len < 0) - return; - int ret = tpm_extend(&le, digest_len); - if (ret) { - tpm_set_failure(); - return; - } - tpm_build_digest(&le, hashdata, hashdata_length, 0); - tpm_log_event(&le.hdr, digest_len, event, event_length); -} - -// Add an EV_ACTION measurement to the list of measurements -static void -tpm_add_action(u32 pcrIndex, const char *string) -{ - u32 len = strlen(string); - tpm_add_measurement_to_log(pcrIndex, EV_ACTION, - string, len, (u8 *)string, len); -} - -/* - * Add event separators for PCRs 0 to 7; specs on 'Measuring Boot Events' - */ -static void -tpm_add_event_separators(void) -{ - static const u8 evt_separator[] = {0xff,0xff,0xff,0xff}; - u32 pcrIndex; - for (pcrIndex = 0; pcrIndex <= 7; pcrIndex++) - tpm_add_measurement_to_log(pcrIndex, EV_SEPARATOR, - (const char *)evt_separator, - sizeof(evt_separator), - evt_separator, - sizeof(evt_separator)); -} - -static void -tpm_smbios_measure(void) -{ - struct pcctes pcctes = { - .eventid = 1, - .eventdatasize = SHA1_BUFSIZE, - }; - u32 smbios_len; - void *smbios_tables = smbios_get_tables(&smbios_len); - - dprintf(DEBUG_tcg, "TCGBIOS: SMBIOS tables at %p\n", smbios_tables); - - if (!smbios_tables) - return; - - sha1((const u8 *)smbios_tables, smbios_len, pcctes.digest); - tpm_add_measurement_to_log(1, - EV_EVENT_TAG, - (const char *)&pcctes, sizeof(pcctes), - (u8 *)&pcctes, sizeof(pcctes)); -} - -static int -tpm12_assert_physical_presence(void) -{ - int ret = tpm_simple_cmd(0, TPM_ORD_PhysicalPresence, - 2, TPM_PP_PRESENT, TPM_DURATION_TYPE_SHORT); - if (!ret) - return 0; - - struct tpm_permanent_flags pf; - ret = tpm12_read_permanent_flags((char *)&pf, sizeof(pf)); - if (ret) - return -1; - - /* check if hardware physical presence is supported */ - if (pf.flags[PERM_FLAG_IDX_PHYSICAL_PRESENCE_HW_ENABLE]) { - /* HW phys. presence may not be asserted... */ - return 0; - } - - if (!pf.flags[PERM_FLAG_IDX_PHYSICAL_PRESENCE_LIFETIME_LOCK] - && !pf.flags[PERM_FLAG_IDX_PHYSICAL_PRESENCE_CMD_ENABLE]) { - tpm_simple_cmd(0, TPM_ORD_PhysicalPresence, - 2, TPM_PP_CMD_ENABLE, TPM_DURATION_TYPE_SHORT); - - return tpm_simple_cmd(0, TPM_ORD_PhysicalPresence, - 2, TPM_PP_PRESENT, TPM_DURATION_TYPE_SHORT); - } - return -1; -} - -static int -tpm12_startup(void) -{ - dprintf(DEBUG_tcg, "TCGBIOS: Starting with TPM_Startup(ST_CLEAR)\n"); - int ret = tpm_simple_cmd(0, TPM_ORD_Startup, - 2, TPM_ST_CLEAR, TPM_DURATION_TYPE_SHORT); - if (CONFIG_COREBOOT && ret == TPM_INVALID_POSTINIT) - /* with other firmware on the system the TPM may already have been - * initialized - */ - ret = 0; - if (ret) - goto err_exit; - - /* assertion of physical presence is only possible after startup */ - ret = tpm12_assert_physical_presence(); - if (!ret) - TPM_has_physical_presence = 1; - - ret = tpm12_determine_timeouts(); - if (ret) - goto err_exit; - - ret = tpm_simple_cmd(0, TPM_ORD_SelfTestFull, - 0, 0, TPM_DURATION_TYPE_LONG); - if (ret) - goto err_exit; - - ret = tpm_simple_cmd(3, TSC_ORD_ResetEstablishmentBit, - 0, 0, TPM_DURATION_TYPE_SHORT); - if (ret && ret != TPM_BAD_LOCALITY) - goto err_exit; - - return 0; - -err_exit: - dprintf(DEBUG_tcg, "TCGBIOS: TPM malfunctioning (line %d).\n", __LINE__); - - tpm_set_failure(); - return -1; -} - -static int -tpm20_startup(void) -{ - tpm20_set_timeouts(); - - int ret = tpm_simple_cmd(0, TPM2_CC_Startup, - 2, TPM2_SU_CLEAR, TPM_DURATION_TYPE_SHORT); - - dprintf(DEBUG_tcg, "TCGBIOS: Return value from sending TPM2_CC_Startup(SU_CLEAR) = 0x%08x\n", - ret); - - if (CONFIG_COREBOOT && ret == TPM2_RC_INITIALIZE) - /* with other firmware on the system the TPM may already have been - * initialized - */ - ret = 0; - - if (ret) - goto err_exit; - - ret = tpm_simple_cmd(0, TPM2_CC_SelfTest, - 1, TPM2_YES, TPM_DURATION_TYPE_LONG); - - dprintf(DEBUG_tcg, "TCGBIOS: Return value from sending TPM2_CC_SelfTest = 0x%08x\n", - ret); - - if (ret) - goto err_exit; - - ret = tpm20_get_pcrbanks(); - if (ret) - goto err_exit; - - ret = tpm20_write_EfiSpecIdEventStruct(); - if (ret) - goto err_exit; - - return 0; - -err_exit: - dprintf(DEBUG_tcg, "TCGBIOS: TPM malfunctioning (line %d).\n", __LINE__); - - tpm_set_failure(); - return -1; -} - -static int -tpm_startup(void) -{ - switch (TPM_version) { - case TPM_VERSION_1_2: - return tpm12_startup(); - case TPM_VERSION_2: - return tpm20_startup(); - } - return -1; -} - -void -tpm_setup(void) -{ - if (!CONFIG_TCGBIOS) - return; - - int ret = tpm_tpm2_probe(); - if (ret) { - ret = tpm_tcpa_probe(); - if (ret) - return; - } - - TPM_version = tpmhw_probe(); - if (TPM_version == TPM_VERSION_NONE) - return; - - dprintf(DEBUG_tcg, - "TCGBIOS: Detected a TPM %s.\n", - (TPM_version == TPM_VERSION_1_2) ? "1.2" : "2"); - - TPM_working = 1; - - if (runningOnXen()) - return; - - ret = tpm_startup(); - if (ret) - return; - - tpm_smbios_measure(); - tpm_add_action(2, "Start Option ROM Scan"); -} - -static void -tpm20_prepboot(void) -{ - int ret = tpm20_stirrandom(); - if (ret) - goto err_exit; - - u8 auth[20]; - ret = tpm20_getrandom(&auth[0], sizeof(auth)); - if (ret) - goto err_exit; - - ret = tpm20_hierarchychangeauth(auth); - if (ret) - goto err_exit; - - return; - -err_exit: - dprintf(DEBUG_tcg, "TCGBIOS: TPM malfunctioning (line %d).\n", __LINE__); - - tpm_set_failure(); -} - -void -tpm_prepboot(void) -{ - if (!CONFIG_TCGBIOS) - return; - - switch (TPM_version) { - case TPM_VERSION_1_2: - if (TPM_has_physical_presence) - tpm_simple_cmd(0, TPM_ORD_PhysicalPresence, - 2, TPM_PP_NOT_PRESENT_LOCK, TPM_DURATION_TYPE_SHORT); - break; - case TPM_VERSION_2: - tpm20_prepboot(); - break; - } - - tpm_add_action(4, "Calling INT 19h"); - tpm_add_event_separators(); -} - -/* - * Add measurement to the log about an option rom - */ -void -tpm_option_rom(const void *addr, u32 len) -{ - if (!tpm_is_working()) - return; - - struct pcctes_romex pcctes = { - .eventid = 7, - .eventdatasize = sizeof(u16) + sizeof(u16) + SHA1_BUFSIZE, - }; - sha1((const u8 *)addr, len, pcctes.digest); - tpm_add_measurement_to_log(2, - EV_EVENT_TAG, - (const char *)&pcctes, sizeof(pcctes), - (u8 *)&pcctes, sizeof(pcctes)); -} - -void -tpm_add_bcv(u32 bootdrv, const u8 *addr, u32 length) -{ - if (!tpm_is_working()) - return; - - if (length < 0x200) - return; - - const char *string = "Booting BCV device 00h (Floppy)"; - if (bootdrv == 0x80) - string = "Booting BCV device 80h (HDD)"; - tpm_add_action(4, string); - - /* specs: see section 'Hard Disk Device or Hard Disk-Like Devices' */ - /* equivalent to: dd if=/dev/hda ibs=1 count=440 | sha1sum */ - string = "MBR"; - tpm_add_measurement_to_log(4, EV_IPL, - string, strlen(string), - addr, 0x1b8); - - /* equivalent to: dd if=/dev/hda ibs=1 count=72 skip=440 | sha1sum */ - string = "MBR PARTITION_TABLE"; - tpm_add_measurement_to_log(5, EV_IPL_PARTITION_DATA, - string, strlen(string), - addr + 0x1b8, 0x48); -} - -void -tpm_add_cdrom(u32 bootdrv, const u8 *addr, u32 length) -{ - if (!tpm_is_working()) - return; - - tpm_add_action(4, "Booting from CD ROM device"); - - /* specs: see section 'El Torito' */ - const char *string = "EL TORITO IPL"; - tpm_add_measurement_to_log(4, EV_IPL, - string, strlen(string), - addr, length); -} - -void -tpm_add_cdrom_catalog(const u8 *addr, u32 length) -{ - if (!tpm_is_working()) - return; - - tpm_add_action(4, "Booting from CD ROM device"); - - /* specs: see section 'El Torito' */ - const char *string = "BOOT CATALOG"; - tpm_add_measurement_to_log(5, EV_IPL_PARTITION_DATA, - string, strlen(string), - addr, length); -} - -void -tpm_s3_resume(void) -{ - if (!tpm_is_working()) - return; - - dprintf(DEBUG_tcg, "TCGBIOS: Resuming with TPM_Startup(ST_STATE)\n"); - - int ret = -1; - - switch (TPM_version) { - case TPM_VERSION_1_2: - ret = tpm_simple_cmd(0, TPM_ORD_Startup, - 2, TPM_ST_STATE, TPM_DURATION_TYPE_SHORT); - break; - case TPM_VERSION_2: - ret = tpm_simple_cmd(0, TPM2_CC_Startup, - 2, TPM2_SU_STATE, TPM_DURATION_TYPE_SHORT); - - dprintf(DEBUG_tcg, "TCGBIOS: Return value from sending TPM2_CC_Startup(SU_STATE) = 0x%08x\n", - ret); - - if (ret) - goto err_exit; - - - ret = tpm_simple_cmd(0, TPM2_CC_SelfTest, - 1, TPM2_YES, TPM_DURATION_TYPE_LONG); - - dprintf(DEBUG_tcg, "TCGBIOS: Return value from sending TPM2_CC_SelfTest() = 0x%08x\n", - ret); - - break; - } - - if (ret) - goto err_exit; - - return; - -err_exit: - dprintf(DEBUG_tcg, "TCGBIOS: TPM malfunctioning (line %d).\n", __LINE__); - - tpm_set_failure(); -} - - -/**************************************************************** - * BIOS interface - ****************************************************************/ - -u8 TPM_interface_shutdown VARLOW; - -static inline void *input_buf32(struct bregs *regs) -{ - return MAKE_FLATPTR(regs->es, regs->di); -} - -static inline void *output_buf32(struct bregs *regs) -{ - return MAKE_FLATPTR(regs->ds, regs->si); -} - -static u32 -hash_log_extend(struct pcpes *pcpes, const void *hashdata, u32 hashdata_length - , void *event, int extend) -{ - if (pcpes->pcrindex >= 24) - return TCG_INVALID_INPUT_PARA; - if (hashdata) - sha1(hashdata, hashdata_length, pcpes->digest); - - struct tpm_log_entry le = { - .hdr.pcrindex = pcpes->pcrindex, - .hdr.eventtype = pcpes->eventtype, - }; - int digest_len = tpm12_build_digest_direct(&le, pcpes->digest); - if (digest_len < 0) - return TCG_GENERAL_ERROR; - if (extend) { - int ret = tpm_extend(&le, digest_len); - if (ret) - return TCG_TCG_COMMAND_ERROR; - } - tpm12_build_digest_direct(&le, pcpes->digest); - int ret = tpm_log_event(&le.hdr, digest_len - , pcpes->event, pcpes->eventdatasize); - if (ret) - return TCG_PC_LOGOVERFLOW; - return 0; -} - -static u32 -hash_log_extend_event_int(const struct hleei_short *hleei_s, - struct hleeo *hleeo) -{ - u32 rc = 0; - struct hleei_long *hleei_l = (struct hleei_long *)hleei_s; - const void *logdataptr; - u32 logdatalen; - struct pcpes *pcpes; - u32 pcrindex; - - /* short or long version? */ - switch (hleei_s->ipblength) { - case sizeof(struct hleei_short): - /* short */ - logdataptr = hleei_s->logdataptr; - logdatalen = hleei_s->logdatalen; - pcrindex = hleei_s->pcrindex; - break; - - case sizeof(struct hleei_long): - /* long */ - logdataptr = hleei_l->logdataptr; - logdatalen = hleei_l->logdatalen; - pcrindex = hleei_l->pcrindex; - break; - - default: - /* bad input block */ - rc = TCG_INVALID_INPUT_PARA; - goto err_exit; - } - - pcpes = (struct pcpes *)logdataptr; - - if (pcpes->pcrindex != pcrindex - || logdatalen != sizeof(*pcpes) + pcpes->eventdatasize) { - rc = TCG_INVALID_INPUT_PARA; - goto err_exit; - } - rc = hash_log_extend(pcpes, hleei_s->hashdataptr, hleei_s->hashdatalen - , pcpes->event, 1); - if (rc) - goto err_exit; - - hleeo->opblength = sizeof(struct hleeo); - hleeo->reserved = 0; - hleeo->eventnumber = tpm_state.entry_count; - memcpy(hleeo->digest, pcpes->digest, sizeof(hleeo->digest)); - -err_exit: - if (rc != 0) { - hleeo->opblength = 4; - hleeo->reserved = 0; - } - - return rc; -} - -static u32 -pass_through_to_tpm_int(struct pttti *pttti, struct pttto *pttto) -{ - u32 rc = 0; - struct tpm_req_header *trh = (void*)pttti->tpmopin; - - if (pttti->ipblength < sizeof(struct pttti) + sizeof(*trh) - || pttti->ipblength != sizeof(struct pttti) + be32_to_cpu(trh->totlen) - || pttti->opblength < sizeof(struct pttto)) { - rc = TCG_INVALID_INPUT_PARA; - goto err_exit; - } - - u16 tag = be16_to_cpu(trh->tag); - - switch (TPM_version) { - case TPM_VERSION_1_2: - if (tag != TPM_TAG_RQU_CMD && tag != TPM_TAG_RQU_AUTH1_CMD - && tag != TPM_TAG_RQU_AUTH2_CMD) { - rc = TCG_INVALID_INPUT_PARA; - goto err_exit; - } - break; - case TPM_VERSION_2: - if (tag != TPM2_ST_NO_SESSIONS && tag != TPM2_ST_SESSIONS) { - rc = TCG_INVALID_INPUT_PARA; - goto err_exit; - } - } - - u32 resbuflen = pttti->opblength - offsetof(struct pttto, tpmopout); - int ret = tpmhw_transmit(0, trh, pttto->tpmopout, &resbuflen, - TPM_DURATION_TYPE_LONG /* worst case */); - if (ret) { - rc = TCG_FATAL_COM_ERROR; - goto err_exit; - } - - pttto->opblength = offsetof(struct pttto, tpmopout) + resbuflen; - pttto->reserved = 0; - -err_exit: - if (rc != 0) { - pttto->opblength = 4; - pttto->reserved = 0; - } - - return rc; -} - -static u32 -shutdown_preboot_interface(void) -{ - TPM_interface_shutdown = 1; - return 0; -} - -static u32 -hash_log_event_int(const struct hlei *hlei, struct hleo *hleo) -{ - u32 rc = 0; - u16 size; - struct pcpes *pcpes; - - size = hlei->ipblength; - if (size != sizeof(*hlei)) { - rc = TCG_INVALID_INPUT_PARA; - goto err_exit; - } - - pcpes = (struct pcpes *)hlei->logdataptr; - - if (pcpes->pcrindex != hlei->pcrindex - || pcpes->eventtype != hlei->logeventtype - || hlei->logdatalen != sizeof(*pcpes) + pcpes->eventdatasize) { - rc = TCG_INVALID_INPUT_PARA; - goto err_exit; - } - rc = hash_log_extend(pcpes, hlei->hashdataptr, hlei->hashdatalen - , pcpes->event, 0); - if (rc) - goto err_exit; - - /* updating the log was fine */ - hleo->opblength = sizeof(struct hleo); - hleo->reserved = 0; - hleo->eventnumber = tpm_state.entry_count; - -err_exit: - if (rc != 0) { - hleo->opblength = 2; - hleo->reserved = 0; - } - - return rc; -} - -static u32 -hash_all_int(const struct hai *hai, u8 *hash) -{ - if (hai->ipblength != sizeof(struct hai) || - hai->hashdataptr == 0 || - hai->hashdatalen == 0 || - hai->algorithmid != TPM_ALG_SHA) - return TCG_INVALID_INPUT_PARA; - - sha1((const u8 *)hai->hashdataptr, hai->hashdatalen, hash); - return 0; -} - -static u32 -tss_int(struct ti *ti, struct to *to) -{ - to->opblength = sizeof(struct to); - to->reserved = 0; - - return TCG_PC_UNSUPPORTED; -} - -static u32 -compact_hash_log_extend_event_int(u8 *buffer, - u32 info, - u32 length, - u32 pcrindex, - u32 *edx_ptr) -{ - struct pcpes pcpes = { - .pcrindex = pcrindex, - .eventtype = EV_COMPACT_HASH, - .eventdatasize = sizeof(info), - }; - u32 rc = hash_log_extend(&pcpes, buffer, length, &info, 1); - if (rc) - return rc; - - *edx_ptr = tpm_state.entry_count; - return 0; -} - -void VISIBLE32FLAT -tpm_interrupt_handler32(struct bregs *regs) -{ - if (!CONFIG_TCGBIOS) - return; - - set_cf(regs, 0); - - if (TPM_interface_shutdown && regs->al) { - regs->eax = TCG_INTERFACE_SHUTDOWN; - return; - } - - switch ((enum irq_ids)regs->al) { - case TCG_StatusCheck: - if (!tpmhw_is_present()) { - /* no TPM available */ - regs->eax = TCG_PC_TPM_NOT_PRESENT; - } else { - regs->eax = 0; - regs->ebx = TCG_MAGIC; - regs->ch = TCG_VERSION_MAJOR; - regs->cl = TCG_VERSION_MINOR; - regs->edx = 0x0; - regs->esi = (u32)tpm_state.log_area_start_address; - regs->edi = (u32)tpm_state.log_area_last_entry; - } - break; - - case TCG_HashLogExtendEvent: - regs->eax = - hash_log_extend_event_int( - (struct hleei_short *)input_buf32(regs), - (struct hleeo *)output_buf32(regs)); - break; - - case TCG_PassThroughToTPM: - regs->eax = - pass_through_to_tpm_int((struct pttti *)input_buf32(regs), - (struct pttto *)output_buf32(regs)); - break; - - case TCG_ShutdownPreBootInterface: - regs->eax = shutdown_preboot_interface(); - break; - - case TCG_HashLogEvent: - regs->eax = hash_log_event_int((struct hlei*)input_buf32(regs), - (struct hleo*)output_buf32(regs)); - break; - - case TCG_HashAll: - regs->eax = - hash_all_int((struct hai*)input_buf32(regs), - (u8 *)output_buf32(regs)); - break; - - case TCG_TSS: - regs->eax = tss_int((struct ti*)input_buf32(regs), - (struct to*)output_buf32(regs)); - break; - - case TCG_CompactHashLogExtendEvent: - regs->eax = - compact_hash_log_extend_event_int((u8 *)input_buf32(regs), - regs->esi, - regs->ecx, - regs->edx, - ®s->edx); - break; - - default: - set_cf(regs, 1); - } - - return; -} - - -/**************************************************************** - * TPM Configuration Menu - ****************************************************************/ - -typedef u8 tpm_ppi_code; - -static int -tpm12_read_has_owner(int *has_owner) -{ - struct tpm_res_getcap_ownerauth oauth; - int ret = tpm12_get_capability(TPM_CAP_PROPERTY, TPM_CAP_PROP_OWNER - , &oauth.hdr, sizeof(oauth)); - if (ret) - return -1; - - *has_owner = oauth.flag; - - return 0; -} - -static int -tpm12_enable_tpm(int enable, int verbose) -{ - struct tpm_permanent_flags pf; - int ret = tpm12_read_permanent_flags((char *)&pf, sizeof(pf)); - if (ret) - return -1; - - if (pf.flags[PERM_FLAG_IDX_DISABLE] && !enable) - return 0; - - ret = tpm_simple_cmd(0, enable ? TPM_ORD_PhysicalEnable - : TPM_ORD_PhysicalDisable, - 0, 0, TPM_DURATION_TYPE_SHORT); - if (ret) { - if (enable) - dprintf(DEBUG_tcg, "TCGBIOS: Enabling the TPM failed.\n"); - else - dprintf(DEBUG_tcg, "TCGBIOS: Disabling the TPM failed.\n"); - } - return ret; -} - -static int -tpm12_activate_tpm(int activate, int allow_reset, int verbose) -{ - struct tpm_permanent_flags pf; - int ret = tpm12_read_permanent_flags((char *)&pf, sizeof(pf)); - if (ret) - return -1; - - if (pf.flags[PERM_FLAG_IDX_DEACTIVATED] && !activate) - return 0; - - if (pf.flags[PERM_FLAG_IDX_DISABLE]) - return 0; - - ret = tpm_simple_cmd(0, TPM_ORD_PhysicalSetDeactivated, - 1, activate ? 0x00 : 0x01, TPM_DURATION_TYPE_SHORT); - if (ret) - return ret; - - if (activate && allow_reset) { - if (verbose) { - printf("Requiring a reboot to activate the TPM.\n"); - - msleep(2000); - } - reset(); - } - - return 0; -} - -static int -tpm12_enable_activate(int allow_reset, int verbose) -{ - int ret = tpm12_enable_tpm(1, verbose); - if (ret) - return ret; - - return tpm12_activate_tpm(1, allow_reset, verbose); -} - -static int -tpm12_force_clear(int enable_activate_before, int enable_activate_after, - int verbose) -{ - int has_owner; - int ret = tpm12_read_has_owner(&has_owner); - if (ret) - return -1; - if (!has_owner) { - if (verbose) - printf("TPM does not have an owner.\n"); - return 0; - } - - if (enable_activate_before) { - ret = tpm12_enable_activate(0, verbose); - if (ret) { - dprintf(DEBUG_tcg, - "TCGBIOS: Enabling/activating the TPM failed.\n"); - return ret; - } - } - - ret = tpm_simple_cmd(0, TPM_ORD_ForceClear, - 0, 0, TPM_DURATION_TYPE_SHORT); - if (ret) - return ret; - - if (!enable_activate_after) { - if (verbose) - printf("Owner successfully cleared.\n" - "You will need to enable/activate the TPM again.\n\n"); - return 0; - } - - return tpm12_enable_activate(1, verbose); -} - -static int -tpm12_set_owner_install(int allow, int verbose) -{ - int has_owner; - int ret = tpm12_read_has_owner(&has_owner); - if (ret) - return -1; - if (has_owner) { - if (verbose) - printf("Must first remove owner.\n"); - return 0; - } - - struct tpm_permanent_flags pf; - ret = tpm12_read_permanent_flags((char *)&pf, sizeof(pf)); - if (ret) - return -1; - - if (pf.flags[PERM_FLAG_IDX_DISABLE]) { - if (verbose) - printf("TPM must first be enable.\n"); - return 0; - } - - ret = tpm_simple_cmd(0, TPM_ORD_SetOwnerInstall, - 1, allow ? 0x01 : 0x00, TPM_DURATION_TYPE_SHORT); - if (ret) - return ret; - - if (verbose) - printf("Installation of owner %s.\n", allow ? "enabled" : "disabled"); - - return 0; -} - -static int -tpm12_process_cfg(tpm_ppi_code msgCode, int verbose) -{ - int ret = 0; - - switch (msgCode) { - case TPM_PPI_OP_NOOP: /* no-op */ - break; - - case TPM_PPI_OP_ENABLE: - ret = tpm12_enable_tpm(1, verbose); - break; - - case TPM_PPI_OP_DISABLE: - ret = tpm12_enable_tpm(0, verbose); - break; - - case TPM_PPI_OP_ACTIVATE: - ret = tpm12_activate_tpm(1, 1, verbose); - break; - - case TPM_PPI_OP_DEACTIVATE: - ret = tpm12_activate_tpm(0, 1, verbose); - break; - - case TPM_PPI_OP_CLEAR: - ret = tpm12_force_clear(1, 0, verbose); - break; - - case TPM_PPI_OP_SET_OWNERINSTALL_TRUE: - ret = tpm12_set_owner_install(1, verbose); - break; - - case TPM_PPI_OP_SET_OWNERINSTALL_FALSE: - ret = tpm12_set_owner_install(0, verbose); - break; - - default: - break; - } - - if (ret) - printf("Op %d: An error occurred: 0x%x\n", msgCode, ret); - - return ret; -} - -static int -tpm20_clearcontrol(u8 disable, int verbose) -{ - struct tpm2_req_clearcontrol trc = { - .hdr.tag = cpu_to_be16(TPM2_ST_SESSIONS), - .hdr.totlen = cpu_to_be32(sizeof(trc)), - .hdr.ordinal = cpu_to_be32(TPM2_CC_ClearControl), - .authhandle = cpu_to_be32(TPM2_RH_PLATFORM), - .authblocksize = cpu_to_be32(sizeof(trc.authblock)), - .authblock = { - .handle = cpu_to_be32(TPM2_RS_PW), - .noncesize = cpu_to_be16(0), - .contsession = TPM2_YES, - .pwdsize = cpu_to_be16(0), - }, - .disable = disable, - }; - struct tpm_rsp_header rsp; - u32 resp_length = sizeof(rsp); - int ret = tpmhw_transmit(0, &trc.hdr, &rsp, &resp_length, - TPM_DURATION_TYPE_SHORT); - if (ret || resp_length != sizeof(rsp) || rsp.errcode) - ret = -1; - - dprintf(DEBUG_tcg, "TCGBIOS: Return value from sending TPM2_CC_ClearControl = 0x%08x\n", - ret); - - return ret; -} - -static int -tpm20_clear(void) -{ - struct tpm2_req_clear trq = { - .hdr.tag = cpu_to_be16(TPM2_ST_SESSIONS), - .hdr.totlen = cpu_to_be32(sizeof(trq)), - .hdr.ordinal = cpu_to_be32(TPM2_CC_Clear), - .authhandle = cpu_to_be32(TPM2_RH_PLATFORM), - .authblocksize = cpu_to_be32(sizeof(trq.authblock)), - .authblock = { - .handle = cpu_to_be32(TPM2_RS_PW), - .noncesize = cpu_to_be16(0), - .contsession = TPM2_YES, - .pwdsize = cpu_to_be16(0), - }, - }; - struct tpm_rsp_header rsp; - u32 resp_length = sizeof(rsp); - int ret = tpmhw_transmit(0, &trq.hdr, &rsp, &resp_length, - TPM_DURATION_TYPE_MEDIUM); - if (ret || resp_length != sizeof(rsp) || rsp.errcode) - ret = -1; - - dprintf(DEBUG_tcg, "TCGBIOS: Return value from sending TPM2_CC_Clear = 0x%08x\n", - ret); - - return ret; -} - -static int -tpm20_process_cfg(tpm_ppi_code msgCode, int verbose) -{ - int ret = 0; - - switch (msgCode) { - case TPM_PPI_OP_NOOP: /* no-op */ - break; - - case TPM_PPI_OP_CLEAR: - ret = tpm20_clearcontrol(0, verbose); - if (!ret) - ret = tpm20_clear(); - break; - } - - if (ret) - printf("Op %d: An error occurred: 0x%x\n", msgCode, ret); - - return ret; -} - -static int -tpm12_get_tpm_state(void) -{ - int state = 0; - struct tpm_permanent_flags pf; - int has_owner; - - if (tpm12_read_permanent_flags((char *)&pf, sizeof(pf)) || - tpm12_read_has_owner(&has_owner)) - return ~0; - - if (!pf.flags[PERM_FLAG_IDX_DISABLE]) - state |= TPM_STATE_ENABLED; - - if (!pf.flags[PERM_FLAG_IDX_DEACTIVATED]) - state |= TPM_STATE_ACTIVE; - - if (has_owner) { - state |= TPM_STATE_OWNED; - } else { - if (pf.flags[PERM_FLAG_IDX_OWNERSHIP]) - state |= TPM_STATE_OWNERINSTALL; - } - - return state; -} - -static void -tpm12_show_tpm_menu(int state, int next_scancodes[7]) -{ - int i = 0; - - printf("\nThe current state of the TPM is:\n"); - - if (state & TPM_STATE_ENABLED) - printf(" Enabled"); - else - printf(" Disabled"); - - if (state & TPM_STATE_ACTIVE) - printf(" and active\n"); - else - printf(" and deactivated\n"); - - if (state & TPM_STATE_OWNED) - printf(" Ownership has been taken\n"); - else { - printf(" Ownership has not been taken\n"); - if (state & TPM_STATE_OWNERINSTALL) - printf(" A user can take ownership of the TPM\n"); - else - printf(" Taking ownership of the TPM has been disabled\n"); - } - - if ((state & (TPM_STATE_ENABLED | TPM_STATE_ACTIVE)) != - (TPM_STATE_ENABLED | TPM_STATE_ACTIVE)) { - printf("\nNote: To make use of all functionality, the TPM must be " - "enabled and active.\n"); - } - - printf("\nAvailable options are:\n"); - if (state & TPM_STATE_ENABLED) { - printf(" d. Disable the TPM\n"); - next_scancodes[i++] = 32; - - if (state & TPM_STATE_ACTIVE) { - printf(" v. Deactivate the TPM\n"); - next_scancodes[i++] = 47; - - if (state & TPM_STATE_OWNERINSTALL) { - printf(" p. Prevent installation of an owner\n"); - next_scancodes[i++] = 25; - } else { - printf(" s. Allow installation of an owner\n"); - next_scancodes[i++] = 31; - } - } else { - printf(" a. Activate the TPM\n"); - next_scancodes[i++] = 30; - } - - } else { - printf(" e. Enable the TPM\n"); - next_scancodes[i++] = 18; - } - - if (state & TPM_STATE_OWNED) { - printf(" c. Clear ownership\n"); - next_scancodes[i++] = 46; - } - - next_scancodes[i++] = 0; -} - -static void -tpm12_menu(void) -{ - int scancode, next_scancodes[7]; - tpm_ppi_code msgCode; - int state = 0, i; - int waitkey; - - printf("The Trusted Platform Module (TPM) is a hardware device in " - "this machine.\n" - "It can help verify the integrity of system software.\n\n"); - - for (;;) { - if ((state = tpm12_get_tpm_state()) != ~0) { - tpm12_show_tpm_menu(state, next_scancodes); - } else { - printf("TPM is not working correctly.\n"); - return; - } - - printf("\nIf no change is desired or if this menu was reached by " - "mistake, press ESC to\n" - "reboot the machine.\n"); - - msgCode = TPM_PPI_OP_NOOP; - - waitkey = 1; - - while (waitkey) { - while ((scancode = get_keystroke(1000)) == ~0) - ; - - switch (scancode) { - case 1: - // ESC - reset(); - break; - case 18: /* e. enable */ - msgCode = TPM_PPI_OP_ENABLE; - break; - case 32: /* d. disable */ - msgCode = TPM_PPI_OP_DISABLE; - break; - case 30: /* a. activate */ - msgCode = TPM_PPI_OP_ACTIVATE; - break; - case 47: /* v. deactivate */ - msgCode = TPM_PPI_OP_DEACTIVATE; - break; - case 46: /* c. clear owner */ - msgCode = TPM_PPI_OP_CLEAR; - break; - case 25: /* p. prevent ownerinstall */ - msgCode = TPM_PPI_OP_SET_OWNERINSTALL_FALSE; - break; - case 31: /* s. allow ownerinstall */ - msgCode = TPM_PPI_OP_SET_OWNERINSTALL_TRUE; - break; - default: - continue; - } - - /* - * Using the next_scancodes array, check whether the - * pressed key is currently a valid option. - */ - for (i = 0; i < sizeof(next_scancodes); i++) { - if (next_scancodes[i] == 0) - break; - - if (next_scancodes[i] == scancode) { - tpm12_process_cfg(msgCode, 1); - waitkey = 0; - break; - } - } - } - } -} - -static int -tpm20_menu_change_active_pcrbanks(void) -{ - u8 active_banks, suppt_banks; - - tpm20_get_suppt_pcrbanks(&suppt_banks, &active_banks); - - u8 activate_banks = active_banks; - - while (1) { - u8 hashalg_flag = TPM2_ALG_SHA1_FLAG; - u8 i = 0; - - printf("\nToggle active PCR banks by pressing number key\n\n"); - - while (hashalg_flag) { - u8 flag = hashalg_flag & suppt_banks; - const char *hashname = tpm20_hashalg_flag_to_name(flag); - - i++; - if (hashname) { - printf(" %d: %s", i, hashname); - if (activate_banks & hashalg_flag) - printf(" (enabled)"); - printf("\n"); - } - - hashalg_flag <<= 1; - } - printf("\n" - "ESC: return to previous menu without changes\n"); - if (activate_banks) - printf("A : activate selection\n"); - - u8 flagnum; - int show = 0; - while (!show) { - int scancode = get_keystroke(1000); - - switch (scancode) { - case ~0: - continue; - case 1: /* ESC */ - printf("\n"); - return -1; - case 2 ... 6: /* keys 1 .. 5 */ - flagnum = scancode - 1; - if (flagnum > i) - continue; - if (suppt_banks & (1 << (flagnum - 1))) { - activate_banks ^= 1 << (flagnum - 1); - show = 1; - } - break; - case 30: /* a */ - if (activate_banks) - tpm20_activate_pcrbanks(activate_banks); - } - } - } -} - -static void -tpm20_menu(void) -{ - int scan_code; - tpm_ppi_code msgCode; - - for (;;) { - printf("1. Clear TPM\n"); - printf("2. Change active PCR banks\n"); - - printf("\nIf no change is desired or if this menu was reached by " - "mistake, press ESC to\n" - "reboot the machine.\n"); - - msgCode = TPM_PPI_OP_NOOP; - - while ((scan_code = get_keystroke(1000)) == ~0) - ; - - switch (scan_code) { - case 1: - // ESC - reset(); - break; - case 2: - msgCode = TPM_PPI_OP_CLEAR; - break; - case 3: - tpm20_menu_change_active_pcrbanks(); - continue; - default: - continue; - } - - tpm20_process_cfg(msgCode, 0); - } -} - -void -tpm_menu(void) -{ - if (!CONFIG_TCGBIOS) - return; - - while (get_keystroke(0) >= 0) - ; - wait_threads(); - - switch (TPM_version) { - case TPM_VERSION_1_2: - tpm12_menu(); - break; - case TPM_VERSION_2: - tpm20_menu(); - break; - } -} - -int -tpm_can_show_menu(void) -{ - switch (TPM_version) { - case TPM_VERSION_1_2: - return tpm_is_working() && TPM_has_physical_presence; - case TPM_VERSION_2: - return tpm_is_working(); - } - return 0; -} diff --git a/src/tcgbios.h b/src/tcgbios.h deleted file mode 100644 index 32fb941..0000000 --- a/src/tcgbios.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef TCGBIOS_H -#define TCGBIOS_H - -#include "types.h" - -struct bregs; -void tpm_interrupt_handler32(struct bregs *regs); - -void tpm_setup(void); -void tpm_prepboot(void); -void tpm_s3_resume(void); -void tpm_add_bcv(u32 bootdrv, const u8 *addr, u32 length); -void tpm_add_cdrom(u32 bootdrv, const u8 *addr, u32 length); -void tpm_add_cdrom_catalog(const u8 *addr, u32 length); -void tpm_option_rom(const void *addr, u32 len); -int tpm_can_show_menu(void); -void tpm_menu(void); - -#endif /* TCGBIOS_H */