* [PATCH 00/16] Add vTPM support to SLOF
@ 2015-08-08 1:54 Stefan Berger
2015-08-08 1:54 ` [PATCH 01/16] Add a TPM driver implementation Stefan Berger
` (15 more replies)
0 siblings, 16 replies; 17+ messages in thread
From: Stefan Berger @ 2015-08-08 1:54 UTC (permalink / raw)
To: linuxppc-dev, nikunj, aik, pmac
Cc: gcwilson, dimitris, latten, lo1, stefanb, Stefan Berger
The following series of patches adds TPM support to SLOF.
In particular it adds the following:
- TPM drivers for hardware interface and CRQ interface
- TPM initialization
- TPM logging area and firmware API to transfer it to the OS
(measurements are visible in sysfs)
- Some measurement code (Static Core Root Of Trust)
- TPM menu (accessible via 't' key during boot if TPM is available)
- Firmware API extensions following Power Firmware Doc
(to make trusted grub work)
Necessarily, some of its parts are written in Forth, many are written
in 'C'. The extensions are known to work with QEMU for ppc64 running Linux.
Patches 4-6 will eventually need to be merged to avoid compiler warnings
related to unused functions.
Regards,
Stefan
Stefan Berger (16):
Add a TPM driver implementation
Add TPM initialization support
Add sha1 implementation
Add initial support for logging
Extend internal firmware API
Return value of actual log in sml-get-handover-size
Perform some initial measurements
Add support for controlling the states of the TPM
Add support for a TPM menu to control the state of the TPM
Implement measurements of the master boot record
Measure the static core root of trust for measurements
Add TPM firmware API calls hash-all, log-event, hash-log-extend-event
Add TPM firmware API call get-maximum-cmd-size
Add TPM firmware API call pass-through-to-tpm
Add TPM firmware API call get-state
Add TPM firmware API call get-failure-reason
board-js2x/slof/OF.fs | 2 +
board-qemu/Makefile | 2 +-
board-qemu/slof/Makefile | 10 +-
board-qemu/slof/OF.fs | 7 +
board-qemu/slof/tree.fs | 3 +
board-qemu/slof/vio-vtpm-cdriver.fs | 144 ++++
board-qemu/slof/vtpm-sml.fs | 108 +++
include/helpers.h | 1 +
lib/Makefile | 2 +-
lib/libtpm/Makefile | 51 ++
lib/libtpm/sha1.c | 197 +++++
lib/libtpm/sha1.h | 20 +
lib/libtpm/tcgbios.c | 1563 +++++++++++++++++++++++++++++++++++
lib/libtpm/tcgbios.h | 53 ++
lib/libtpm/tcgbios_int.h | 206 +++++
lib/libtpm/tpm.code | 207 +++++
lib/libtpm/tpm.in | 33 +
lib/libtpm/tpm_drivers.c | 456 ++++++++++
lib/libtpm/tpm_drivers.h | 93 +++
slof/fs/packages/disk-label.fs | 6 +-
slof/fs/start-up.fs | 9 +
slof/fs/tpm/tpm-static.fs | 351 ++++++++
slof/helpers.c | 6 +
23 files changed, 3524 insertions(+), 6 deletions(-)
create mode 100644 board-qemu/slof/vio-vtpm-cdriver.fs
create mode 100644 board-qemu/slof/vtpm-sml.fs
create mode 100644 lib/libtpm/Makefile
create mode 100644 lib/libtpm/sha1.c
create mode 100644 lib/libtpm/sha1.h
create mode 100644 lib/libtpm/tcgbios.c
create mode 100644 lib/libtpm/tcgbios.h
create mode 100644 lib/libtpm/tcgbios_int.h
create mode 100644 lib/libtpm/tpm.code
create mode 100644 lib/libtpm/tpm.in
create mode 100644 lib/libtpm/tpm_drivers.c
create mode 100644 lib/libtpm/tpm_drivers.h
create mode 100644 slof/fs/tpm/tpm-static.fs
--
1.9.3
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH 01/16] Add a TPM driver implementation
2015-08-08 1:54 [PATCH 00/16] Add vTPM support to SLOF Stefan Berger
@ 2015-08-08 1:54 ` Stefan Berger
2015-08-08 1:54 ` [PATCH 02/16] Add TPM initialization support Stefan Berger
` (14 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Stefan Berger @ 2015-08-08 1:54 UTC (permalink / raw)
To: linuxppc-dev, nikunj, aik, pmac
Cc: gcwilson, dimitris, latten, lo1, stefanb, Stefan Berger
This patch adds a TPM driver for the CRQ interface as used by
the QEMU PAPR implementation.
Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
---
include/helpers.h | 1 +
lib/libtpm/Makefile | 51 ++++++
lib/libtpm/tpm_drivers.c | 456 +++++++++++++++++++++++++++++++++++++++++++++++
lib/libtpm/tpm_drivers.h | 93 ++++++++++
slof/helpers.c | 6 +
5 files changed, 607 insertions(+)
create mode 100644 lib/libtpm/Makefile
create mode 100644 lib/libtpm/tpm_drivers.c
create mode 100644 lib/libtpm/tpm_drivers.h
diff --git a/include/helpers.h b/include/helpers.h
index fb10534..9e6bdf8 100644
--- a/include/helpers.h
+++ b/include/helpers.h
@@ -33,6 +33,7 @@ extern long SLOF_pci_config_read16(long offset);
extern void SLOF_pci_config_write32(long offset, long value);
extern void SLOF_pci_config_write16(long offset, long value);
extern void *SLOF_translate_my_address(void *addr);
+extern unsigned long SLOF_get_vtpm_unit(void);
#define offset_of(type, member) ((long) &((type *)0)->member)
#define container_of(ptr, type, member) ({ \
diff --git a/lib/libtpm/Makefile b/lib/libtpm/Makefile
new file mode 100644
index 0000000..a174815
--- /dev/null
+++ b/lib/libtpm/Makefile
@@ -0,0 +1,51 @@
+# *****************************************************************************
+# * Copyright (c) 2015 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
+# ****************************************************************************/
+
+TOPCMNDIR ?= ../..
+
+ASFLAGS = $(FLAG) $(RELEASE) $(CPUARCHDEF) -Wa,-mregnames
+CPPFLAGS = -I../libc/include $(CPUARCHDEF) -I$(INCLBRDDIR) \
+ -I$(INCLCMNDIR) -I$(INCLCMNDIR)/$(CPUARCH) -I$(SLOFCMNDIR)
+CPPFLAGS += -I../libhvcall
+
+LDFLAGS = -nostdlib
+
+TARGET = ../libtpm.a
+
+
+all: $(TARGET)
+
+SRCS = tpm_drivers.c
+
+OBJS = $(SRCS:%.c=%.o)
+
+$(TARGET): $(OBJS)
+ $(AR) -rc $@ $(OBJS)
+ $(RANLIB) $@
+
+clean:
+ $(RM) $(TARGET) $(OBJS)
+
+distclean: clean
+ $(RM) Makefile.dep
+
+
+# Rules for creating the dependency file:
+depend:
+ $(RM) Makefile.dep
+ $(MAKE) Makefile.dep
+
+Makefile.dep: Makefile
+ $(CC) -M $(CPPFLAGS) $(CFLAGS) $(SRCS) $(SRCSS) > Makefile.dep
+
+# Include dependency file if available:
+-include Makefile.dep
diff --git a/lib/libtpm/tpm_drivers.c b/lib/libtpm/tpm_drivers.c
new file mode 100644
index 0000000..850da8c
--- /dev/null
+++ b/lib/libtpm/tpm_drivers.c
@@ -0,0 +1,456 @@
+/*****************************************************************************
+ * Copyright (c) 2015 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
+ *****************************************************************************/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdbool.h>
+
+#include "string.h"
+#include "helpers.h"
+#include "byteorder.h"
+#include "tpm_drivers.h"
+#include "tcgbios.h"
+#include "libhvcall.h"
+#include "paflof.h"
+
+#define PAPR_VTPM_DEBUG 0
+
+#define dprintf(_x ...) \
+ if (PAPR_VTPM_DEBUG) { \
+ printf("VTPM CRQ: " _x); \
+ }
+
+#define MIN(a, b) ((a) > (b) ? (b) : (a))
+
+#define TPM_DEFAULT_DURATION_SHORT (2000)
+#define TPM_DEFAULT_DURATION_MEDIUM (20000)
+#define TPM_DEFAULT_DURATION_LONG (60000)
+
+struct crq {
+ uint8_t valid;
+ uint8_t msg;
+ uint16_t len;
+ uint32_t data;
+ uint64_t reserved;
+} __attribute__((packed));
+
+#define PAPR_VTPM_INIT_CRQ_COMMAND 0xC0
+#define PAPR_VTPM_VALID_COMMAND 0x80
+#define PAPR_VTPM_MSG_RESULT 0x80
+
+/* msg types for valid = VALID_INIT_CRQ */
+#define PAPR_VTPM_INIT_CRQ_RESULT 0x1
+
+/* msg types for valid = IBMVTPM_VALID_CMD */
+#define PAPR_VTPM_GET_VERSION 0x1
+#define PAPR_VTPM_TPM_COMMAND 0x2
+#define PAPR_VTPM_GET_RTCE_BUFFER_SIZE 0x3
+
+static const uint32_t tpm_default_durations[TPM_NUM_DURATIONS] = {
+ TPM_DEFAULT_DURATION_SHORT,
+ TPM_DEFAULT_DURATION_MEDIUM,
+ TPM_DEFAULT_DURATION_LONG,
+};
+
+#define PAGE_SIZE 4096
+
+/* state of the PAPR CRQ VTPM driver */
+static struct spapr_vtpm_driver_state {
+ /* durations of short, medium, & long commands */
+ uint32_t durations[TPM_NUM_DURATIONS];
+ unsigned long vtpm_unit;
+ unsigned char *qaddr;
+ unsigned long qsize;
+ /* current q_entry */
+ unsigned int q_entry;
+ /* current response CRQ */
+ struct crq *response;
+ pfw_drv_state driver_state;
+ pfw_drv_error driver_error;
+ /* version of the TPM we talk to -- from CRQ message */
+ uint32_t tpm_version;
+ /* buffer offset in buffer for sending */
+ unsigned int buffer_offset;
+ /* actual size of the buffer being used */
+ unsigned int buffer_size;
+ /* the buffer; may be bigger than buffer_size */
+ unsigned char buffer[PAPR_VTPM_MAX_BUFFER_SIZE];
+} spapr_vtpm = {
+ .qsize = PAGE_SIZE,
+ .driver_state = PFW_DRV_STATE_INVALID,
+ .driver_error = PFW_DRV_ERROR_NO_FAILURE,
+ .buffer_size = sizeof(spapr_vtpm.buffer),
+};
+
+static void pfw_drv_state_set(pfw_drv_state s, pfw_drv_error e)
+{
+ spapr_vtpm.driver_state = s;
+ spapr_vtpm.driver_error = e;
+}
+
+static pfw_drv_state pfw_drv_state_get(void)
+{
+ return spapr_vtpm.driver_state;
+}
+
+static pfw_drv_state pfw_drv_error_get(void)
+{
+ return spapr_vtpm.driver_error;
+}
+
+static void spapr_vtpm_set_durations(
+ const uint32_t durations[TPM_NUM_DURATIONS])
+{
+ memcpy(spapr_vtpm.durations, durations,
+ TPM_NUM_DURATIONS * sizeof(durations[0]));
+}
+
+/*
+ * Get the crq where the response will be found. This
+ * function will clear the CRQ's valid field and advance
+ * the entry counter to the next entry.
+ */
+static struct crq *get_response_crq(void)
+{
+ struct crq *crq;
+
+ dprintf("q_entry = %d\n", spapr_vtpm.q_entry);
+
+ crq = &((struct crq *)spapr_vtpm.qaddr)[spapr_vtpm.q_entry];
+ memset(crq, 0, sizeof(*crq));
+
+ spapr_vtpm.q_entry += 1;
+ if (spapr_vtpm.q_entry == spapr_vtpm.qsize / sizeof(struct crq))
+ spapr_vtpm.q_entry = 0;
+
+ return crq;
+}
+
+/*
+ * Send a message via CRQ and wait for the response
+ */
+static bool spapr_send_crq_and_wait(unsigned long unit,
+ struct crq *crq,
+ struct crq **resp,
+ unsigned timeout,
+ pfw_drv_state state1,
+ pfw_drv_state state2)
+{
+ long rc;
+ unsigned i;
+
+ *resp = get_response_crq();
+
+ pfw_drv_state_set(state1, PFW_DRV_ERROR_NO_FAILURE);
+
+ rc = hv_send_crq(unit, (uint64_t *)crq);
+ if (rc != H_SUCCESS) {
+ pfw_drv_state_set(PFW_DRV_STATE_WAIT_INIT,
+ PFW_DRV_ERROR_TPM_CRQ_ERROR);
+ return false;
+ }
+
+ pfw_drv_state_set(state2,
+ PFW_DRV_ERROR_NO_FAILURE);
+
+ for (i = 0; i < timeout; i++) {
+ if (((*resp)->valid & PAPR_VTPM_MSG_RESULT))
+ return true;
+ SLOF_msleep(1);
+ }
+
+ pfw_drv_state_set(PFW_DRV_STATE_FAILURE,
+ PFW_DRV_ERROR_WAIT_TIMEOUT);
+
+ dprintf("Received no response from CRQ\n");
+ return false;
+}
+
+/*
+ * Get parameters from the CRQ
+ */
+static bool spapr_vtpm_get_params(void)
+{
+ struct crq crq, *response;
+ static bool completed = false; /* only once */
+
+ if (completed)
+ return true;
+
+ /* get the TPM version */
+ crq.valid = PAPR_VTPM_VALID_COMMAND;
+ crq.msg = PAPR_VTPM_GET_VERSION;
+
+ if (!spapr_send_crq_and_wait(spapr_vtpm.vtpm_unit, &crq, &response, 10,
+ PFW_DRV_STATE_SEND_GET_VERSION,
+ PFW_DRV_STATE_WAIT_VERSION)) {
+ dprintf("Failure getting TPM version from CRQ\n");
+ return false;
+ }
+
+ pfw_drv_state_set(PFW_DRV_STATE_CHECK_VERSION,
+ PFW_DRV_ERROR_NO_FAILURE);
+
+ spapr_vtpm.tpm_version = be32_to_cpu(response->data);
+ dprintf("TPM backend version: %d\n", spapr_vtpm.tpm_version);
+
+ /* get the TPM's buffer size */
+ crq.valid = PAPR_VTPM_VALID_COMMAND;
+ crq.msg = PAPR_VTPM_GET_RTCE_BUFFER_SIZE;
+
+ if (!spapr_send_crq_and_wait(spapr_vtpm.vtpm_unit, &crq, &response, 10,
+ PFW_DRV_STATE_SEND_BUFSIZE_REQ,
+ PFW_DRV_STATE_WAIT_BUFSIZE)) {
+ dprintf("Failure getting RTCE buffer size from CRQ\n");
+ return false;
+ }
+
+ pfw_drv_state_set(PFW_DRV_STATE_ALLOC_RTCE_BUF,
+ PFW_DRV_ERROR_NO_FAILURE);
+
+ dprintf("RTCE buffer size: %u\n", be16_to_cpu(response->len));
+ spapr_vtpm.buffer_size = MIN(spapr_vtpm.buffer_size,
+ be16_to_cpu(response->len));
+ if (spapr_vtpm.buffer_size < 1024) {
+ dprintf("RTCE buffer size of %u bytes is too small. "
+ "Minimum is 1024 bytes.\n", spapr_vtpm.buffer_size);
+ pfw_drv_state_set(PFW_DRV_STATE_FAILURE,
+ PFW_DRV_ERROR_BAD_RTCE_SIZE);
+ return false;
+ }
+
+ completed = true;
+
+ return true;
+}
+
+static bool spapr_vtpm_activate(uint8_t locty)
+{
+ long rc;
+ struct crq crq, *resp;
+ static bool initialized = false; /* only one init */
+
+ spapr_vtpm.buffer_offset = 0;
+
+ pfw_drv_state_set(PFW_DRV_STATE_REG_CRQ,
+ PFW_DRV_ERROR_NO_FAILURE);
+
+ rc = hv_reg_crq(spapr_vtpm.vtpm_unit, (unsigned long)spapr_vtpm.qaddr,
+ spapr_vtpm.qsize);
+ if (rc != H_SUCCESS) {
+ pfw_drv_state_set(PFW_DRV_STATE_WAIT_INIT,
+ PFW_DRV_ERROR_UNEXPECTED_REG_ERROR);
+ dprintf("CRQ registration failed\n");
+ return false;
+ }
+
+ /* we always start with q_entry 0 */
+ spapr_vtpm.q_entry = 0;
+
+ if (initialized)
+ goto skip_init;
+
+ crq.valid = PAPR_VTPM_INIT_CRQ_COMMAND;
+ crq.msg = PAPR_VTPM_INIT_CRQ_RESULT;
+
+ if (!spapr_send_crq_and_wait(spapr_vtpm.vtpm_unit,
+ &crq,
+ &resp,
+ 10,
+ PFW_DRV_STATE_SEND_INIT,
+ PFW_DRV_STATE_WAIT_INIT_COMP)) {
+ dprintf("Initializing CRQ failed\n");
+ goto err_exit;
+ }
+ dprintf("Successfully initialized CRQ\n");
+
+ initialized = true;
+
+skip_init:
+ if (!spapr_vtpm_get_params())
+ goto err_exit;
+
+ return true;
+
+err_exit:
+ hv_free_crq(spapr_vtpm.vtpm_unit);
+
+ return false;
+}
+
+static bool spapr_vtpm_init(void)
+{
+ spapr_vtpm_set_durations(tpm_default_durations);
+
+ return true;
+}
+
+/*
+ * Check whether we have a CRQ underneath us
+ */
+static bool spapr_vtpm_probe(void)
+{
+ bool good = true;
+
+ spapr_vtpm_init();
+
+ if (!spapr_vtpm.qaddr) {
+ spapr_vtpm.qaddr = SLOF_alloc_mem(spapr_vtpm.qsize);
+ memset(spapr_vtpm.qaddr, 0, spapr_vtpm.qsize);
+
+ dprintf("getting FORTH vtpm-unit\n");
+ spapr_vtpm.vtpm_unit = SLOF_get_vtpm_unit();
+ }
+
+ dprintf("vtpm_unit = %lx, buffer = %p\n",
+ spapr_vtpm.vtpm_unit, spapr_vtpm.qaddr);
+ if (!spapr_vtpm_activate(0)) {
+ good = false;
+ } else {
+ hv_free_crq(spapr_vtpm.vtpm_unit);
+ }
+
+ return good;
+}
+
+static bool spapr_vtpm_senddata(const uint8_t *const data, uint32_t len)
+{
+ /*
+ * we have to collect all data to be sent in a buffer
+ */
+
+ if (spapr_vtpm.buffer_offset + len > spapr_vtpm.buffer_size) {
+ spapr_vtpm.buffer_offset = 0;
+ return false;
+ }
+
+ memcpy(&spapr_vtpm.buffer[spapr_vtpm.buffer_offset], data, len);
+
+ spapr_vtpm.buffer_offset += len;
+
+ return true;
+}
+
+static bool spapr_vtpm_transfer(void)
+{
+ struct crq crq;
+ long rc;
+
+ spapr_vtpm.response = get_response_crq();
+ /* response CRQ has been set and valid field cleared */
+
+ crq.valid = PAPR_VTPM_VALID_COMMAND;
+ crq.msg = PAPR_VTPM_TPM_COMMAND;
+ crq.len = cpu_to_be16(spapr_vtpm.buffer_offset);
+ crq.data = cpu_to_be32((uint64_t)spapr_vtpm.buffer);
+
+ pfw_drv_state_set(PFW_DRV_STATE_SEND_TPM_CMD,
+ PFW_DRV_ERROR_NO_FAILURE);
+
+ rc = hv_send_crq(spapr_vtpm.vtpm_unit, (uint64_t *)&crq);
+
+ if (rc == H_SUCCESS) {
+ pfw_drv_state_set(PFW_DRV_STATE_WAIT_TPM_RSP,
+ PFW_DRV_ERROR_NO_FAILURE);
+ } else {
+ /* per pfw doc, move to wait_init state */
+ pfw_drv_state_set(PFW_DRV_STATE_WAIT_INIT,
+ PFW_DRV_ERROR_UNEXPECTED_SEND_ERROR);
+ }
+
+ spapr_vtpm.buffer_offset = 0;
+
+ return (rc == H_SUCCESS);
+}
+
+static bool spapr_vtpm_waitrespready(enum tpmDurationType to_t)
+{
+ uint32_t timeout = spapr_vtpm.durations[to_t];
+ int i;
+
+ /* response CRQ has been set */
+
+ for (i = 0; i < timeout; i++) {
+ if (spapr_vtpm.response->valid & PAPR_VTPM_MSG_RESULT) {
+ /* TPM responded: move to Send tpm-cmd state */
+ pfw_drv_state_set(PFW_DRV_STATE_SEND_TPM_CMD,
+ PFW_DRV_ERROR_NO_FAILURE);
+ dprintf("Received response to TPM command\n");
+ return true;
+ }
+ SLOF_msleep(1);
+ }
+
+ pfw_drv_state_set(PFW_DRV_STATE_FAILURE,
+ PFW_DRV_ERROR_WAIT_TIMEOUT);
+
+ dprintf("Received NO response to TPM command");
+
+ return false;
+}
+
+static bool spapr_vtpm_readresp(uint8_t *buffer, uint32_t *len)
+{
+ /* response CRQ has been set */
+
+ memcpy(buffer, (void *)(uint64_t)spapr_vtpm.response->data,
+ MIN(*len, be32_to_cpu(spapr_vtpm.response->len)));
+
+ *len = be32_to_cpu(spapr_vtpm.response->len);
+ dprintf("Length of copied response: %d\n", *len);
+
+ return true;
+}
+
+static bool spapr_vtpm_endcycle(void)
+{
+ hv_free_crq(spapr_vtpm.vtpm_unit);
+
+ spapr_vtpm.response = NULL;
+
+ return true;
+}
+
+static uint32_t spapr_vtpm_get_buffersize(void)
+{
+ return spapr_vtpm.buffer_size;
+}
+
+static pfw_drv_state spapr_vtpm_get_state(void)
+{
+ return pfw_drv_state_get();
+}
+
+static pfw_drv_error spapr_vtpm_get_error(void)
+{
+ return pfw_drv_error_get();
+}
+
+/**** driver structures ****/
+
+struct tpm_driver tpm_drivers[TPM_NUM_DRIVERS] = {
+ [PAPR_DRIVER_IDX] = {
+ .setdurations = spapr_vtpm_set_durations,
+ .probe = spapr_vtpm_probe,
+ .init = spapr_vtpm_init,
+ .activate = spapr_vtpm_activate,
+ .ready = spapr_vtpm_endcycle,
+ .senddata = spapr_vtpm_senddata,
+ .transfer = spapr_vtpm_transfer,
+ .waitrespready = spapr_vtpm_waitrespready,
+ .readresp = spapr_vtpm_readresp,
+ .sha1threshold = 100 * 1024,
+ .getbuffersize = spapr_vtpm_get_buffersize,
+ .getstate = spapr_vtpm_get_state,
+ .geterror = spapr_vtpm_get_error,
+ },
+};
diff --git a/lib/libtpm/tpm_drivers.h b/lib/libtpm/tpm_drivers.h
new file mode 100644
index 0000000..2d74cc0
--- /dev/null
+++ b/lib/libtpm/tpm_drivers.h
@@ -0,0 +1,93 @@
+/*****************************************************************************
+ * Copyright (c) 2015 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
+ *****************************************************************************/
+
+#ifndef TPM_DRIVERS_H
+#define TPM_DRIVERS_H
+
+#include <stdint.h>
+#include <stdbool.h>
+
+enum tpmDurationType {
+ TPM_DURATION_TYPE_SHORT = 0,
+ TPM_DURATION_TYPE_MEDIUM,
+ TPM_DURATION_TYPE_LONG,
+};
+
+#define TPM_NUM_DURATIONS 3
+
+#define PAPR_DRIVER_IDX 0
+#define TPM_NUM_DRIVERS 1
+
+/* firmware driver states */
+typedef enum {
+ PFW_DRV_STATE_INVALID = 0,
+ PFW_DRV_STATE_INIT_CALLED = 1,
+ PFW_DRV_STATE_REG_CRQ = 2,
+ PFW_DRV_STATE_WAIT_INIT = 3,
+ PFW_DRV_STATE_SEND_INIT = 4,
+ PFW_DRV_STATE_FAILURE = 5,
+ PFW_DRV_STATE_WAIT_INIT_COMP = 6,
+ PFW_DRV_STATE_SEND_INIT_COMP = 7,
+ PFW_DRV_STATE_SEND_GET_VERSION = 8,
+ PFW_DRV_STATE_WAIT_VERSION = 9,
+ PFW_DRV_STATE_CHECK_VERSION = 10,
+ PFW_DRV_STATE_SEND_BUFSIZE_REQ = 11,
+ PFW_DRV_STATE_WAIT_BUFSIZE = 12,
+ PFW_DRV_STATE_ALLOC_RTCE_BUF = 13,
+ PFW_DRV_STATE_SEND_TPM_CMD = 14,
+ PFW_DRV_STATE_WAIT_TPM_RSP = 15,
+} pfw_drv_state;
+
+/* firmware driver errors */
+typedef enum {
+ PFW_DRV_ERROR_NO_FAILURE = -1,
+ PFW_DRV_ERROR_NOT_FOUND_TIMEOUT = 0,
+ PFW_DRV_ERROR_UNEXPECTED_REG_ERROR = 1,
+ PFW_DRV_ERROR_PARTNER_FAILED = 2,
+ PFW_DRV_ERROR_UNEXPECTED_TSP_ERROR = 3,
+ PFW_DRV_ERROR_TPM_PROTOCOL_ERROR = 4,
+ PFW_DRV_ERROR_WAIT_TIMEOUT = 5,
+ PFW_DRV_ERROR_UNEXPECTED_SEND_ERROR = 6,
+ PFW_DRV_ERROR_CRQ_OPEN_FAIL = 7,
+ PFW_DRV_ERROR_BAD_STATE = 8,
+ PFW_DRV_ERROR_TPM_FAIL = 9,
+ PFW_DRV_ERROR_TPM_CRQ_ERROR = 10,
+ PFW_DRV_ERROR_BAD_VERSION = 11,
+ PFW_DRV_ERROR_BAD_RTCE_SIZE = 12,
+ PFW_DRV_ERROR_SML_FAILURE = 13,
+ PFW_DRV_ERROR_SML_HANDED_OVER = 14,
+} pfw_drv_error;
+
+/* low level driver implementation */
+struct tpm_driver {
+ void (*setdurations)(const uint32_t durations[TPM_NUM_DURATIONS]);
+ bool (*probe)(void);
+ bool (*init)(void);
+ bool (*activate)(uint8_t locty);
+ bool (*ready)(void);
+ bool (*senddata)(const uint8_t *const data, uint32_t len);
+ bool (*transfer)(void);
+ bool (*waitrespready)(enum tpmDurationType to_t);
+ bool (*readresp)(uint8_t *buffer, uint32_t *len);
+ /* the TPM will be used for buffers of sizes below the sha1threshold
+ for calculating the hash */
+ uint32_t sha1threshold;
+ void (*get_vers_data)(uint16_t *did, uint16_t *vid, uint16_t *rid);
+ uint32_t (*getbuffersize)(void);
+ pfw_drv_state (*getstate)(void);
+ pfw_drv_error (*geterror)(void);
+};
+
+/* the max. buffer size by the external TPM is 4k */
+#define PAPR_VTPM_MAX_BUFFER_SIZE 4096
+
+#endif /* TPM_DRIVERS_H */
diff --git a/slof/helpers.c b/slof/helpers.c
index d7c1888..dc7f08c 100644
--- a/slof/helpers.c
+++ b/slof/helpers.c
@@ -134,3 +134,9 @@ void *SLOF_translate_my_address(void *addr)
forth_eval("translate-my-address");
return (void *)forth_pop();
}
+
+unsigned long SLOF_get_vtpm_unit(void)
+{
+ forth_eval("vtpm-unit");
+ return forth_pop();
+}
--
1.9.3
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 02/16] Add TPM initialization support
2015-08-08 1:54 [PATCH 00/16] Add vTPM support to SLOF Stefan Berger
2015-08-08 1:54 ` [PATCH 01/16] Add a TPM driver implementation Stefan Berger
@ 2015-08-08 1:54 ` Stefan Berger
2015-08-08 1:54 ` [PATCH 03/16] Add sha1 implementation Stefan Berger
` (13 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Stefan Berger @ 2015-08-08 1:54 UTC (permalink / raw)
To: linuxppc-dev, nikunj, aik, pmac
Cc: gcwilson, dimitris, latten, lo1, stefanb, Stefan Berger
This patch implements the main part of the fimrmware extensions. It provides
the following functionality:
- initialization of the TPM by sending a sequence of commands to it
- proper setup of the TPM before the firmware hands over control to the bootloader
Structures that are needed in subsequent patches are also included in the
private header file tcgbios_int.h at this point.
Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
---
board-qemu/Makefile | 2 +-
board-qemu/slof/Makefile | 10 +-
board-qemu/slof/OF.fs | 6 +
board-qemu/slof/tree.fs | 3 +
board-qemu/slof/vio-vtpm-cdriver.fs | 74 +++++++
board-qemu/slof/vtpm-sml.fs | 56 ++++++
lib/Makefile | 2 +-
lib/libtpm/Makefile | 2 +-
lib/libtpm/tcgbios.c | 371 ++++++++++++++++++++++++++++++++++++
lib/libtpm/tcgbios.h | 21 ++
lib/libtpm/tcgbios_int.h | 162 ++++++++++++++++
lib/libtpm/tpm.code | 37 ++++
lib/libtpm/tpm.in | 17 ++
slof/fs/tpm/tpm-static.fs | 34 ++++
14 files changed, 791 insertions(+), 6 deletions(-)
create mode 100644 board-qemu/slof/vio-vtpm-cdriver.fs
create mode 100644 board-qemu/slof/vtpm-sml.fs
create mode 100644 lib/libtpm/tcgbios.c
create mode 100644 lib/libtpm/tcgbios.h
create mode 100644 lib/libtpm/tcgbios_int.h
create mode 100644 lib/libtpm/tpm.code
create mode 100644 lib/libtpm/tpm.in
create mode 100644 slof/fs/tpm/tpm-static.fs
diff --git a/board-qemu/Makefile b/board-qemu/Makefile
index 29ee016..0c03e54 100644
--- a/board-qemu/Makefile
+++ b/board-qemu/Makefile
@@ -15,7 +15,7 @@ BOARD_TARGETS = tools_build romfs_build clients_build stage1 subdirs
SUBDIRS = slof
COMMON_LIBS = libc libbootmsg libbases libnvram libelf libhvcall libvirtio libusb \
- libveth libe1k
+ libveth libe1k libtpm
all: $(BOARD_TARGETS)
$(MAKE) boot_rom.bin
diff --git a/board-qemu/slof/Makefile b/board-qemu/slof/Makefile
index 283f77d..be6eec1 100644
--- a/board-qemu/slof/Makefile
+++ b/board-qemu/slof/Makefile
@@ -21,7 +21,7 @@ all: version.o Makefile.dep OF.ffs paflof $(SLOFCMNDIR)/xvect.bin
CPPFLAGS = -I$(LIBCMNDIR)/libbootmsg -I$(LIBCMNDIR)/libhvcall \
-I$(LIBCMNDIR)/libvirtio -I$(LIBCMNDIR)/libnvram \
-I$(LIBCMNDIR)/libusb -I$(LIBCMNDIR)/libveth \
- -I$(LIBCMNDIR)/libe1k
+ -I$(LIBCMNDIR)/libe1k -I$(LIBCMNDIR)/libtpm
SLOF_LIBS = \
$(LIBCMNDIR)/libbootmsg.a \
$(LIBCMNDIR)/libelf.a \
@@ -30,7 +30,8 @@ SLOF_LIBS = \
$(LIBCMNDIR)/libusb.a \
$(LIBCMNDIR)/libnvram.a \
$(LIBCMNDIR)/libveth.a \
- $(LIBCMNDIR)/libe1k.a
+ $(LIBCMNDIR)/libe1k.a \
+ $(LIBCMNDIR)/libtpm.a
BOARD_SLOF_IN = \
$(LIBCMNDIR)/libhvcall/hvcall.in \
$(LIBCMNDIR)/libvirtio/virtio.in \
@@ -40,7 +41,8 @@ BOARD_SLOF_IN = \
$(LIBCMNDIR)/libnvram/libnvram.in \
$(LIBCMNDIR)/libbases/libbases.in \
$(LIBCMNDIR)/libveth/veth.in \
- $(LIBCMNDIR)/libe1k/e1k.in
+ $(LIBCMNDIR)/libe1k/e1k.in \
+ $(LIBCMNDIR)/libtpm/tpm.in
BOARD_SLOF_CODE = $(BOARD_SLOF_IN:%.in=%.code)
include $(SLOFCMNDIR)/Makefile.inc
@@ -71,6 +73,7 @@ VIO_FFS_FILES = \
$(SLOFBRDDIR)/pci-device_1af4_1009.fs \
$(SLOFBRDDIR)/vio-hvterm.fs \
$(SLOFBRDDIR)/vio-vscsi.fs \
+ $(SLOFBRDDIR)/vio-vtpm-cdriver.fs \
$(SLOFBRDDIR)/vio-veth.fs \
$(SLOFBRDDIR)/rtas-nvram.fs \
$(SLOFBRDDIR)/virtio-net.fs \
@@ -99,6 +102,7 @@ OF_FFS_FILES = \
$(SLOFBRDDIR)/default-font.bin \
$(SLOFBRDDIR)/pci-phb.fs \
$(SLOFBRDDIR)/rtas.fs \
+ $(SLOFBRDDIR)/vtpm-sml.fs \
$(SLOFBRDDIR)/pci-device_1234_1111.fs \
$(SLOFBRDDIR)/pci-device_1013_00b8.fs \
$(SLOFBRDDIR)/pci-device_8086_100e.fs \
diff --git a/board-qemu/slof/OF.fs b/board-qemu/slof/OF.fs
index 561d892..bd9495e 100644
--- a/board-qemu/slof/OF.fs
+++ b/board-qemu/slof/OF.fs
@@ -113,6 +113,10 @@ d# 512000000 VALUE tb-frequency \ default value - needed for "ms" to work
#include "fdt.fs"
+350 cp
+
+#include <tpm/tpm-static.fs>
+
360 cp
#include <root.fs>
@@ -300,6 +304,8 @@ cr
#include "copyright-oss.fs"
cr cr
+vtpm-unassert-pp
+
\ this CATCH is to ensure the code bellow always executes: boot may ABORT!
' start-it CATCH drop
diff --git a/board-qemu/slof/tree.fs b/board-qemu/slof/tree.fs
index 4aba4c5..b71009d 100644
--- a/board-qemu/slof/tree.fs
+++ b/board-qemu/slof/tree.fs
@@ -83,6 +83,9 @@ include fbuffer.fs
2dup " qemu,spapr-nvram" strequal IF
" rtas-nvram.fs" included
THEN
+ 2dup " IBM,vtpm" strequal IF
+ " vio-vtpm-cdriver.fs" included
+ THEN
2drop
THEN
peer
diff --git a/board-qemu/slof/vio-vtpm-cdriver.fs b/board-qemu/slof/vio-vtpm-cdriver.fs
new file mode 100644
index 0000000..2fc1657
--- /dev/null
+++ b/board-qemu/slof/vio-vtpm-cdriver.fs
@@ -0,0 +1,74 @@
+\ *****************************************************************************
+\ * Copyright (c) 2015 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
+\ ****************************************************************************/
+
+." Populating " pwd
+
+false VALUE vtpm-debug?
+0 VALUE vtpm-unit
+
+: setup-alias
+ " ibm,vtpm" find-alias 0= IF
+ " ibm,vtpm" get-node node>path set-alias
+ ELSE
+ drop
+ THEN
+;
+
+: vtpm-cleanup ( )
+ vtpm-debug? IF ." VTPM: Disabling RTAS bypass" cr THEN
+ vtpm-unit 0 rtas-set-tce-bypass
+;
+
+: vtpm-init ( -- true | false )
+ 0 0 get-node open-node ?dup 0= IF EXIT THEN
+ my-self >r
+ dup to my-self
+
+ vtpm-debug? IF ." VTPM: Initializing for c-driver" cr THEN
+
+ my-unit to vtpm-unit
+
+ \ Enable TCE bypass special qemu feature
+ vtpm-unit 1 rtas-set-tce-bypass
+
+ \ Have TCE bypass cleaned up
+ ['] vtpm-cleanup add-quiesce-xt
+
+ tpm-start ( -- errcode )
+ vtpm-debug? IF
+ ." VTPM: Error code from tpm-start: " dup . cr
+ THEN
+
+ \ check errorcode
+ 0= IF
+ \ tpm-start had no error: Setup an alias
+ setup-alias
+ THEN
+
+ close-node
+ r> to my-self
+;
+
+: open ( )
+ vtpm-debug? IF ." VTPM: vTPM open()" cr THEN
+ true
+;
+
+: close ( )
+ vtpm-debug? IF ." VTPM: vTPM close()" cr THEN
+;
+
+\ setup alias and the RTAS bypass
+vtpm-init
+
+\ setup the log
+include vtpm-sml.fs
diff --git a/board-qemu/slof/vtpm-sml.fs b/board-qemu/slof/vtpm-sml.fs
new file mode 100644
index 0000000..72edac0
--- /dev/null
+++ b/board-qemu/slof/vtpm-sml.fs
@@ -0,0 +1,56 @@
+\ *****************************************************************************
+\ * Copyright (c) 2015 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
+\ ****************************************************************************/
+
+\ KVM/qemu TPM SML entries in /ibm,vtpm
+
+" /" find-device
+
+new-device
+
+false VALUE vtpm-debug?
+0 VALUE log-base
+40000 CONSTANT LOG-SIZE \ 256k per VTPM FW spec.
+
+LOG-SIZE alloc-mem to log-base
+
+\ create /ibm,vtpm
+s" ibm,vtpm" 2dup device-name device-type
+
+: sml-get-allocated-size ( -- buffer-size)
+ vtpm-debug? IF
+ ." Call to sml-get-allocated-size; size = " LOG-SIZE . cr
+ THEN
+ LOG-SIZE
+;
+
+: sml-get-handover-size ( -- size )
+ vtpm-debug? IF
+ ." Call to sml-get-handover-size; size = " LOG-SIZE . cr
+ THEN
+ LOG-SIZE
+;
+
+: sml-handover ( dest size -- )
+ vtpm-debug? IF
+ 2dup
+ ." Call to sml-handover; size = " . ." dest = " . cr
+ THEN
+ log-base ( dest size src )
+ -rot ( src dest size )
+ move
+;
+
+: open true ;
+: close ;
+
+finish-device
+device-end
diff --git a/lib/Makefile b/lib/Makefile
index ed8a359..9c802e2 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -11,7 +11,7 @@
# ****************************************************************************/
SUBDIRS = libc libipmi libbootmsg libbases libnvram libelf libhvcall libvirtio \
- libusb libveth libe1k libbcm
+ libusb libveth libe1k libbcm libtpm
all: subdirs
diff --git a/lib/libtpm/Makefile b/lib/libtpm/Makefile
index a174815..53d3abb 100644
--- a/lib/libtpm/Makefile
+++ b/lib/libtpm/Makefile
@@ -24,7 +24,7 @@ TARGET = ../libtpm.a
all: $(TARGET)
-SRCS = tpm_drivers.c
+SRCS = tpm_drivers.c tcgbios.c
OBJS = $(SRCS:%.c=%.o)
diff --git a/lib/libtpm/tcgbios.c b/lib/libtpm/tcgbios.c
new file mode 100644
index 0000000..efa4cdf
--- /dev/null
+++ b/lib/libtpm/tcgbios.c
@@ -0,0 +1,371 @@
+/*****************************************************************************
+ * Copyright (c) 2015 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
+ *****************************************************************************/
+
+/*
+ * Implementation of the TPM BIOS extension according to the specification
+ * described in the IBM VTPM Firmware document and the TCG Specification
+ * that can be found here under the following link:
+ * http://www.trustedcomputinggroup.org/resources/pc_client_work_group_specific_implementation_specification_for_conventional_bios
+ */
+
+#include "types.h"
+#include "byteorder.h"
+#include "tpm_drivers.h"
+#include "string.h"
+#include "tcgbios.h"
+#include "tcgbios_int.h"
+#include "stdio.h"
+
+#define DEBUG 0
+#define dprintf(_x ...) do { \
+ if (DEBUG) { \
+ printf("TCGBIOS: " _x); \
+ } \
+} while (0);
+
+static const uint8_t Startup_ST_CLEAR[] = { 0x00, TPM_ST_CLEAR };
+static const uint8_t Startup_ST_STATE[] = { 0x00, TPM_ST_STATE };
+
+static const uint8_t PhysicalPresence_CMD_ENABLE[] = { 0x00, 0x20 };
+static const uint8_t PhysicalPresence_CMD_DISABLE[] = { 0x01, 0x00 };
+static const uint8_t PhysicalPresence_PRESENT[] = { 0x00, 0x08 };
+static const uint8_t PhysicalPresence_NOT_PRESENT_LOCK[] = { 0x00, 0x14 };
+
+static const uint8_t CommandFlag_FALSE[] = { 0x00 };
+static const uint8_t CommandFlag_TRUE[] = { 0x01 };
+
+static const uint8_t GetCapability_Permanent_Flags[] = {
+ 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04,
+ 0x00, 0x00, 0x01, 0x08
+};
+
+static const uint8_t GetCapability_OwnerAuth[] = {
+ 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04,
+ 0x00, 0x00, 0x01, 0x11
+};
+
+static const uint8_t GetCapability_Timeouts[] = {
+ 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04,
+ 0x00, 0x00, 0x01, 0x15
+};
+
+static const uint8_t GetCapability_Durations[] = {
+ 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04,
+ 0x00, 0x00, 0x01, 0x20
+};
+
+struct tpm_state {
+ uint8_t tpm_probed:1;
+ uint8_t tpm_found:1;
+ uint8_t tpm_working:1;
+ uint8_t if_shutdown:1;
+ struct tpm_driver *tpm_driver_to_use;
+};
+
+static struct tpm_state tpm_state = {
+ .tpm_driver_to_use = NULL,
+};
+
+extern struct tpm_driver tpm_drivers[];
+
+/********************************************************
+ Extensions for TCG-enabled BIOS
+ *******************************************************/
+
+static bool is_tpm_present(void)
+{
+ bool rc = false;
+ unsigned int i;
+
+ for (i = 0; i < TPM_NUM_DRIVERS; i++) {
+ struct tpm_driver *td = &tpm_drivers[i];
+ if (td->probe()) {
+ td->init();
+ tpm_state.tpm_driver_to_use = td;
+ rc = true;
+ break;
+ }
+ }
+
+ return rc;
+}
+
+static void probe_tpm(void)
+{
+ if (!tpm_state.tpm_probed) {
+ tpm_state.tpm_probed = 1;
+ tpm_state.tpm_found = (is_tpm_present() != 0);
+ tpm_state.tpm_working = tpm_state.tpm_found;
+ }
+}
+
+static bool has_working_tpm(void)
+{
+ probe_tpm();
+
+ return tpm_state.tpm_working;
+}
+
+static uint32_t transmit(uint8_t locty, const struct iovec iovec[],
+ uint8_t *respbuffer, uint32_t *respbufferlen,
+ enum tpmDurationType to_t)
+{
+ struct tpm_driver *td;
+ unsigned int i;
+
+ if (tpm_state.tpm_driver_to_use == NULL)
+ return TCGBIOS_FATAL_COM_ERROR;
+
+ td = tpm_state.tpm_driver_to_use;
+
+ if (!td->activate(locty))
+ return TCGBIOS_FATAL_COM_ERROR;
+
+ for (i = 0; iovec[i].length; i++) {
+ if (!td->senddata(iovec[i].data,
+ iovec[i].length))
+ return TCGBIOS_FATAL_COM_ERROR;
+ }
+
+ if (!td->transfer())
+ return TCGBIOS_FATAL_COM_ERROR;
+
+ if (!td->waitrespready(to_t))
+ return TCGBIOS_FATAL_COM_ERROR;
+
+ if (!td->readresp(respbuffer, respbufferlen))
+ return TCGBIOS_FATAL_COM_ERROR;
+
+ td->ready();
+
+ return 0;
+}
+
+/*
+ * Send a TPM command with the given ordinal. Append the given buffer
+ * containing all data in network byte order to the command (this is
+ * the custom part per command) and expect a response of the given size.
+ * If a buffer is provided, the response will be copied into it.
+ */
+static uint32_t build_and_send_cmd_od(uint32_t ordinal,
+ const uint8_t *append,
+ uint32_t append_size,
+ uint8_t *resbuffer,
+ uint32_t return_size,
+ uint32_t *returnCode,
+ const uint8_t *otherdata,
+ uint32_t otherdata_size,
+ enum tpmDurationType to_t)
+{
+#define MAX_APPEND_SIZE sizeof(GetCapability_Timeouts)
+#define MAX_RESPONSE_SIZE sizeof(struct tpm_res_getcap_perm_flags)
+ uint32_t rc;
+ uint8_t ibuffer[TPM_REQ_HEADER_SIZE + MAX_APPEND_SIZE];
+ uint8_t obuffer[MAX_RESPONSE_SIZE];
+ struct tpm_req_header *trqh = (struct tpm_req_header *)ibuffer;
+ struct tpm_rsp_header *trsh = (struct tpm_rsp_header *)obuffer;
+ uint8_t locty = 0;
+ struct iovec iovec[3] = {{ 0 }};
+ uint32_t obuffer_len = sizeof(obuffer);
+
+ if (append_size > MAX_APPEND_SIZE || return_size > MAX_RESPONSE_SIZE) {
+ dprintf("size of requested buffers too big.");
+ return TCGBIOS_FIRMWARE_ERROR;
+ }
+
+ iovec[0].data = trqh;
+ iovec[0].length = TPM_REQ_HEADER_SIZE + append_size;
+
+ if (otherdata) {
+ iovec[1].data = (void *)otherdata;
+ iovec[1].length = otherdata_size;
+ }
+
+ memset(ibuffer, 0, sizeof(ibuffer));
+ memset(obuffer, 0, sizeof(obuffer));
+
+ trqh->tag = cpu_to_be16(TPM_TAG_RQU_CMD);
+ trqh->totlen = cpu_to_be32(TPM_REQ_HEADER_SIZE +
+ append_size + otherdata_size);
+ trqh->ordinal = cpu_to_be32(ordinal);
+
+ if (append_size)
+ memcpy((char *)trqh + sizeof(*trqh),
+ append, append_size);
+
+ rc = transmit(locty, iovec, obuffer, &obuffer_len, to_t);
+ if (rc)
+ return rc;
+
+ *returnCode = be32_to_cpu(trsh->errcode);
+
+ if (resbuffer)
+ memcpy(resbuffer, trsh, return_size);
+
+ return 0;
+}
+
+static uint32_t build_and_send_cmd(uint32_t ordinal, const uint8_t *append,
+ uint32_t append_size, uint8_t *resbuffer,
+ uint32_t return_size, uint32_t *returnCode,
+ enum tpmDurationType to_t)
+{
+ return build_and_send_cmd_od(ordinal, append, append_size,
+ resbuffer, return_size, returnCode,
+ NULL, 0, to_t);
+}
+
+static uint32_t determine_timeouts(void)
+{
+ uint32_t rc;
+ uint32_t returnCode;
+ struct tpm_res_getcap_durations durations;
+ struct tpm_driver *td = tpm_state.tpm_driver_to_use;
+ unsigned int i;
+
+ rc = build_and_send_cmd(TPM_ORD_GetCapability,
+ GetCapability_Durations,
+ sizeof(GetCapability_Durations),
+ (uint8_t *)&durations, sizeof(durations),
+ &returnCode, TPM_DURATION_TYPE_SHORT);
+
+ dprintf("Return code from TPM_GetCapability(Durations) = 0x%08x\n",
+ returnCode);
+
+ if (rc || returnCode)
+ goto err_exit;
+
+ for (i = 0; i < TPM_NUM_DURATIONS; i++)
+ durations.durations[i] = be32_to_cpu(durations.durations[i]);
+
+ dprintf("durations: %u %u %u\n",
+ durations.durations[0],
+ durations.durations[1],
+ durations.durations[2]);
+
+ td->setdurations(durations.durations);
+
+ return 0;
+
+err_exit:
+ dprintf("TPM malfunctioning (line %d).\n", __LINE__);
+
+ tpm_state.tpm_working = 0;
+ if (rc)
+ return rc;
+ return TCGBIOS_COMMAND_ERROR;
+}
+
+static uint32_t tpm_startup(void)
+{
+ uint32_t rc;
+ uint32_t returnCode;
+
+ if (!has_working_tpm())
+ return TCGBIOS_GENERAL_ERROR;
+
+ dprintf("Starting with TPM_Startup(ST_CLEAR)\n");
+ rc = build_and_send_cmd(TPM_ORD_Startup,
+ Startup_ST_CLEAR, sizeof(Startup_ST_CLEAR),
+ NULL, 0, &returnCode,
+ TPM_DURATION_TYPE_SHORT);
+
+ dprintf("Return code from TPM_Startup = 0x%08x\n",
+ returnCode);
+
+ if (rc || returnCode)
+ goto err_exit;
+
+ rc = build_and_send_cmd(TPM_ORD_SelfTestFull, NULL, 0,
+ NULL, 0, &returnCode,
+ TPM_DURATION_TYPE_LONG);
+
+ dprintf("Return code from TPM_SelfTestFull = 0x%08x\n",
+ returnCode);
+
+ if (rc || returnCode)
+ goto err_exit;
+
+ rc = determine_timeouts();
+ if (rc)
+ goto err_exit;
+
+ return 0;
+
+err_exit:
+ dprintf("TPM malfunctioning (line %d).\n", __LINE__);
+
+ tpm_state.tpm_working = 0;
+ if (rc)
+ return rc;
+ return TCGBIOS_COMMAND_ERROR;
+}
+
+uint32_t tpm_start(void)
+{
+ tpm_state.if_shutdown = 0;
+ tpm_state.tpm_probed = 0;
+ tpm_state.tpm_found = 0;
+ tpm_state.tpm_working = 0;
+
+ if (!has_working_tpm()) {
+ dprintf("%s: Machine does not have a working TPM\n",
+ __func__);
+ tpm_state.if_shutdown = 1;
+ return TCGBIOS_FATAL_COM_ERROR;
+ }
+
+ return tpm_startup();
+}
+
+uint32_t tpm_unassert_pp(void)
+{
+ uint32_t rc;
+ uint32_t returnCode;
+
+ if (!has_working_tpm())
+ return TCGBIOS_GENERAL_ERROR;
+
+ rc = build_and_send_cmd(TPM_ORD_PhysicalPresence,
+ PhysicalPresence_CMD_ENABLE,
+ sizeof(PhysicalPresence_CMD_ENABLE),
+ NULL, 0, &returnCode,
+ TPM_DURATION_TYPE_SHORT);
+
+ dprintf("Return code from TPM_PhysicalPresence(CMD_ENABLE) = 0x%08x\n",
+ returnCode);
+
+ if (rc || returnCode)
+ goto err_exit;
+
+ rc = build_and_send_cmd(TPM_ORD_PhysicalPresence,
+ PhysicalPresence_NOT_PRESENT_LOCK,
+ sizeof(PhysicalPresence_NOT_PRESENT_LOCK),
+ NULL, 0, &returnCode,
+ TPM_DURATION_TYPE_SHORT);
+
+ dprintf("Return code from TPM_PhysicalPresence(NOT_PRESENT_LOCK) = 0x%08x\n",
+ returnCode);
+
+ if (rc || returnCode)
+ goto err_exit;
+
+ return 0;
+
+err_exit:
+ dprintf("TPM malfunctioning (line %d).\n", __LINE__);
+
+ tpm_state.tpm_working = 0;
+ if (rc)
+ return rc;
+ return TCGBIOS_COMMAND_ERROR;
+}
diff --git a/lib/libtpm/tcgbios.h b/lib/libtpm/tcgbios.h
new file mode 100644
index 0000000..c4c462e
--- /dev/null
+++ b/lib/libtpm/tcgbios.h
@@ -0,0 +1,21 @@
+/*****************************************************************************
+ * Copyright (c) 2015 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
+ *****************************************************************************/
+
+#ifndef TCGBIOS_H
+#define TCGBIOS_H
+
+#include <stdint.h>
+
+uint32_t tpm_start(void);
+uint32_t tpm_unassert_pp(void);
+
+#endif /* TCGBIOS_H */
diff --git a/lib/libtpm/tcgbios_int.h b/lib/libtpm/tcgbios_int.h
new file mode 100644
index 0000000..c8caf3b
--- /dev/null
+++ b/lib/libtpm/tcgbios_int.h
@@ -0,0 +1,162 @@
+/*****************************************************************************
+ * Copyright (c) 2015 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
+ *****************************************************************************/
+
+#ifndef TCGBIOS_INT_H
+#define TCGBIOS_INT_H
+
+#include <stdint.h>
+
+#include "tpm_drivers.h"
+
+/* internal error codes */
+#define TCGBIOS_OK 0x0
+#define TCGBIOS_LOGOVERFLOW 0x1
+#define TCGBIOS_GENERAL_ERROR 0x2
+#define TCGBIOS_FIRMWARE_ERROR 0x3
+#define TCGBIOS_FATAL_COM_ERROR 0x4
+#define TCGBIOS_INVALID_INPUT_PARA 0x5
+#define TCGBIOS_COMMAND_ERROR 0x6
+#define TCGBIOS_INTERFACE_SHUTDOWN 0x7
+
+#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_Startup 0x00000099
+#define TPM_ORD_PhysicalPresence 0x4000000a
+#define TPM_ORD_Extend 0x00000014
+#define TPM_ORD_SHA1Start 0x000000a0
+#define TPM_ORD_SHA1Update 0x000000a1
+#define TPM_ORD_SHA1Complete 0x000000a2
+
+#define TPM_ST_CLEAR 0x1
+#define TPM_ST_STATE 0x2
+#define TPM_ST_DEACTIVATED 0x3
+
+#define TPM_TAG_RQU_CMD 0x00c1
+
+/* TPM command error codes */
+#define TPM_INVALID_POSTINIT 0x26
+
+/* event types */
+#define EV_POST_CODE 1
+#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
+
+#define STATUS_FLAG_SHUTDOWN (1 << 0)
+
+#define SHA1_BUFSIZE 20
+
+struct iovec {
+ size_t length;
+ void *data;
+};
+
+/* Input and Output blocks for the TCG BIOS commands */
+
+/* PCClient_PCREventStruct -- format of log entries; compatible with x86 */
+struct pcpes {
+ uint32_t pcrindex;
+ uint32_t eventtype;
+ uint8_t digest[SHA1_BUFSIZE];
+ uint32_t eventdatasize;
+ uint32_t event;
+} __attribute__((packed));
+
+#define TPM_REQ_HEADER \
+ uint16_t tag; \
+ uint32_t totlen; \
+ uint32_t ordinal;
+
+#define TPM_REQ_HEADER_SIZE (sizeof(uint16_t) + sizeof(uint32_t) + sizeof(uint32_t))
+
+#define TPM_RSP_HEADER \
+ uint16_t tag; \
+ uint32_t totlen; \
+ uint32_t errcode;
+
+#define TPM_RSP_HEADER_SIZE (sizeof(uint16_t) + sizeof(uint32_t) + sizeof(uint32_t))
+
+struct tpm_req_header {
+ TPM_REQ_HEADER;
+} __attribute__((packed));
+
+struct tpm_rsp_header {
+ TPM_RSP_HEADER;
+} __attribute__((packed));
+
+struct tpm_req_extend {
+ TPM_REQ_HEADER
+ uint32_t pcrindex;
+ uint8_t digest[SHA1_BUFSIZE];
+} __attribute__((packed));
+
+struct tpm_rsp_extend {
+ TPM_RSP_HEADER
+ uint8_t digest[SHA1_BUFSIZE];
+} __attribute__((packed));
+
+struct tpm_req_getcap_perm_flags {
+ TPM_REQ_HEADER
+ uint32_t capArea;
+ uint32_t subCapSize;
+ uint32_t subCap;
+} __attribute__((packed));
+
+struct tpm_permanent_flags {
+ uint16_t tag;
+ uint8_t flags[20];
+} __attribute__((packed));
+
+#define PERM_FLAG_IDX_DISABLE 0
+#define PERM_FLAG_IDX_OWNERSHIP 1
+#define PERM_FLAG_IDX_DEACTIVATED 2
+#define PERM_FLAG_IDX_DISABLEOWNERCLEAR 4
+#define PERM_FLAG_IDX_PHYSICAL_PRESENCE_LIFETIME_LOCK 6
+#define PERM_FLAG_IDX_PHYSICAL_PRESENCE_HW_ENABLE 7
+
+struct tpm_res_getcap_perm_flags {
+ TPM_RSP_HEADER
+ uint32_t size;
+ struct tpm_permanent_flags perm_flags;
+} __attribute__((packed));
+
+struct tpm_res_getcap_ownerauth {
+ TPM_RSP_HEADER
+ uint32_t size;
+ uint8_t flag;
+} __attribute__((packed));
+
+struct tpm_res_getcap_durations {
+ TPM_RSP_HEADER
+ uint32_t size;
+ uint32_t durations[TPM_NUM_DURATIONS];
+} __attribute__((packed));
+
+struct tpm_res_sha1start {
+ TPM_RSP_HEADER
+ uint32_t max_num_bytes;
+} __attribute__((packed));
+
+struct tpm_res_sha1complete {
+ TPM_RSP_HEADER
+ uint8_t hash[SHA1_BUFSIZE];
+} __attribute__((packed));
+
+#endif /* TCGBIOS_INT_H */
diff --git a/lib/libtpm/tpm.code b/lib/libtpm/tpm.code
new file mode 100644
index 0000000..567b384
--- /dev/null
+++ b/lib/libtpm/tpm.code
@@ -0,0 +1,37 @@
+/******************************************************************************
+ * Copyright (c) 2015 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
+ *****************************************************************************/
+/*
+ * libtpm bindings for SLOF - implementation
+ */
+
+#include <tcgbios.h>
+
+
+/************************************************/
+/* Startup TPM code */
+/* SLOF: tpm-start ( -- errcode ) */
+/* LIBNEWUSB: tpm_start(void) */
+/************************************************/
+PRIM(tpm_X2d_start)
+ PUSH;
+ TOS.n = tpm_start();
+MIRP
+
+/************************************************/
+/* Prepare TPM state for bootloader */
+/* SLOF: tpm-unassert-pp ( -- errcode ) */
+/* LIBNEWUSB: tpm_unassert_pp(void) */
+/************************************************/
+PRIM(tpm_X2d_unassert_X2d_pp)
+ PUSH;
+ TOS.n = tpm_unassert_pp();
+MIRP
diff --git a/lib/libtpm/tpm.in b/lib/libtpm/tpm.in
new file mode 100644
index 0000000..266439e
--- /dev/null
+++ b/lib/libtpm/tpm.in
@@ -0,0 +1,17 @@
+/******************************************************************************
+ * Copyright (c) 2015 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
+ *****************************************************************************/
+/*
+ * libtpm bindings for SLOF - definitions
+ */
+
+cod(tpm-start)
+cod(tpm-unassert-pp)
diff --git a/slof/fs/tpm/tpm-static.fs b/slof/fs/tpm/tpm-static.fs
new file mode 100644
index 0000000..11e4ad5
--- /dev/null
+++ b/slof/fs/tpm/tpm-static.fs
@@ -0,0 +1,34 @@
+\ *****************************************************************************
+\ * Copyright (c) 2015 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
+\ ****************************************************************************/
+
+false VALUE vtpm-debug?
+
+\ none of the vTPM functions may be called if the alias is not there
+: vtpm-available?
+ " ibm,vtpm" find-alias 0 <> IF
+ drop
+ true
+ ELSE
+ false
+ THEN
+;
+
+: vtpm-unassert-pp
+ vtpm-available? IF
+ tpm-unassert-pp ( -- errcode )
+ vtpm-debug? IF
+ ." VTPM: Error code from tpm-unassert-pp: " . cr
+ ELSE
+ drop
+ THEN
+ THEN
+;
--
1.9.3
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 03/16] Add sha1 implementation
2015-08-08 1:54 [PATCH 00/16] Add vTPM support to SLOF Stefan Berger
2015-08-08 1:54 ` [PATCH 01/16] Add a TPM driver implementation Stefan Berger
2015-08-08 1:54 ` [PATCH 02/16] Add TPM initialization support Stefan Berger
@ 2015-08-08 1:54 ` Stefan Berger
2015-08-08 1:54 ` [PATCH 04/16] Add initial support for logging Stefan Berger
` (12 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Stefan Berger @ 2015-08-08 1:54 UTC (permalink / raw)
To: linuxppc-dev, nikunj, aik, pmac
Cc: gcwilson, dimitris, latten, lo1, stefanb, Stefan Berger
The following patch adds a SHA1 implementation based on the algorithm
description in NIST FIPS PUB 180-4.
Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
---
lib/libtpm/Makefile | 2 +-
lib/libtpm/sha1.c | 197 ++++++++++++++++++++++++++++++++++++++++++++++++++++
lib/libtpm/sha1.h | 20 ++++++
3 files changed, 218 insertions(+), 1 deletion(-)
create mode 100644 lib/libtpm/sha1.c
create mode 100644 lib/libtpm/sha1.h
diff --git a/lib/libtpm/Makefile b/lib/libtpm/Makefile
index 53d3abb..f8ad468 100644
--- a/lib/libtpm/Makefile
+++ b/lib/libtpm/Makefile
@@ -24,7 +24,7 @@ TARGET = ../libtpm.a
all: $(TARGET)
-SRCS = tpm_drivers.c tcgbios.c
+SRCS = tpm_drivers.c tcgbios.c sha1.c
OBJS = $(SRCS:%.c=%.o)
diff --git a/lib/libtpm/sha1.c b/lib/libtpm/sha1.c
new file mode 100644
index 0000000..2454b8f
--- /dev/null
+++ b/lib/libtpm/sha1.c
@@ -0,0 +1,197 @@
+/*****************************************************************************
+ * Copyright (c) 2015 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-1 in FIPS PUB 180-4
+ */
+
+#include "byteorder.h"
+#include "sha1.h"
+#include "string.h"
+
+typedef struct _sha1_ctx {
+ uint32_t h[5];
+} sha1_ctx;
+
+static uint32_t rol(uint32_t data, uint8_t n)
+{
+ if (!n)
+ return data;
+ return (data << n) | (data >> (32 - n));
+}
+
+static void sha1_block(uint32_t *w, sha1_ctx *ctx)
+{
+ uint32_t i;
+ uint32_t a,b,c,d,e,f;
+ uint32_t tmp;
+ uint32_t idx;
+
+ /*
+ * FIPS 180-4 4.2.1: SHA1 Constants
+ */
+ static const uint32_t sha_ko[4] = {
+ 0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xca62c1d6
+ };
+
+ /*
+ * FIPS 180-4 6.1.2: step 1
+ *
+ * 0 <= i <= 15:
+ * W(t) = M(t)
+ * 16 <= i <= 79:
+ * W(t) = ROTL(W(t-3) XOR W(t-8) XOR W(t-14) XOR W(t-16), 1)
+ */
+
+ /* w(0)..(w15) already in big endian format */
+
+ for (i = 16; i <= 79; i++) {
+ tmp = w[i-3] ^ w[i-8] ^ w[i-14] ^ w[i-16];
+ w[i] = rol(tmp, 1);
+ }
+
+ /*
+ * step 2: a = H0, b = H1, c = H2, d = H3, e = H4.
+ */
+ a = ctx->h[0];
+ b = ctx->h[1];
+ c = ctx->h[2];
+ d = ctx->h[3];
+ e = ctx->h[4];
+
+ /*
+ * step 3: For i = 0 to 79:
+ * T = ROTL(a, 5) + f(i; b,c,d) + e + W(t) + K(t);
+ */
+ for (i = 0; i <= 79; i++) {
+ /*
+ * FIPS 180-4: 4.1.1 : definition of f(i; b,c,d)
+ */
+ if (i <= 19) {
+ /*
+ * 0 <= i <= 19:
+ * f(i; b,c,d) = (b AND c) OR ((NOT b) AND d)
+ */
+ f = (b & c) | ((b ^ 0xffffffff) & d);
+ idx = 0;
+ } else if (i <= 39) {
+ /*
+ * 20 <= i <= 39:
+ * f(i; b,c,d) = b XOR c XOR d
+ */
+ f = b ^ c ^ d;
+ idx = 1;
+ } else if (i <= 59) {
+ /*
+ * 40 <= i <= 59:
+ * f(i; b,c,d) = (b AND c) OR (b AND d) OR (c AND d)
+ */
+ f = (b & c) | (b & d) | (c & d);
+ idx = 2;
+ } else {
+ /*
+ * 60 <= i <= 79:
+ * f(i; b,c,d) = b XOR c XOR d
+ */
+ f = b ^ c ^ d;
+ idx = 3;
+ }
+
+ /*
+ * step 3:
+ * t = ROTL(a, 5) + f(t;b,c,d) + e + K(t) + W(t);
+ * e = d; d = c; c = ROTL(b, 30); b = a; a = t;
+ */
+ tmp = rol(a, 5) +
+ f +
+ e +
+ sha_ko[idx] +
+ w[i];
+ e = d;
+ d = c;
+ c = rol(b, 30);
+ b = a;
+ a = tmp;
+ }
+
+ /*
+ * 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;
+}
+
+static void sha1_do(sha1_ctx *ctx, const uint8_t*data32, uint32_t length)
+{
+ uint32_t offset;
+ uint16_t num;
+ uint32_t bits = 0;
+ uint32_t w[80];
+ uint64_t tmp;
+
+ /* treat data in 64-byte chunks */
+ for (offset = 0; length - offset >= 64; offset += 64) {
+ memcpy(w, data32 + offset, 64);
+ sha1_block((uint32_t *)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
+ */
+ ((uint8_t *)w)[num] = 0x80;
+ if (64 - (num + 1) > 0)
+ memset( &((uint8_t *)w)[num + 1], 0, 64 - (num + 1));
+
+ if (num >= 56) {
+ /* cannot append number of bits here */
+ sha1_block((uint32_t *)w, ctx);
+ memset(w, 0, 60);
+ }
+
+ /* write number of bits to end of block */
+ tmp = bits;
+ memcpy(&w[14], &tmp, 8);
+
+ sha1_block(w, ctx);
+}
+
+uint32_t sha1(const uint8_t *data, uint32_t length, uint8_t *hash)
+{
+ sha1_ctx ctx = {
+ .h = {
+ /*
+ * FIPS 180-4: 6.1.1
+ * -> 5.3.1: initial hash value
+ */
+ 0x67452301,
+ 0xefcdab89,
+ 0x98badcfe,
+ 0x10325476,
+ 0xc3d2e1f0,
+ }
+ };
+
+ sha1_do(&ctx, data, length);
+ memcpy(hash, &ctx.h[0], 20);
+
+ return 0;
+}
diff --git a/lib/libtpm/sha1.h b/lib/libtpm/sha1.h
new file mode 100644
index 0000000..7fa3e03
--- /dev/null
+++ b/lib/libtpm/sha1.h
@@ -0,0 +1,20 @@
+/*****************************************************************************
+ * Copyright (c) 2015 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
+ *****************************************************************************/
+
+#ifndef __SHA1_H
+#define __SHA1_H
+
+#include "types.h"
+
+uint32_t sha1(const uint8_t *data, uint32_t length, uint8_t *hash);
+
+#endif /* __SHA1_H */
--
1.9.3
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 04/16] Add initial support for logging
2015-08-08 1:54 [PATCH 00/16] Add vTPM support to SLOF Stefan Berger
` (2 preceding siblings ...)
2015-08-08 1:54 ` [PATCH 03/16] Add sha1 implementation Stefan Berger
@ 2015-08-08 1:54 ` Stefan Berger
2015-08-08 1:54 ` [PATCH 05/16] Extend internal firmware API Stefan Berger
` (11 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Stefan Berger @ 2015-08-08 1:54 UTC (permalink / raw)
To: linuxppc-dev, nikunj, aik, pmac
Cc: gcwilson, dimitris, latten, lo1, stefanb, Stefan Berger
This patch adds initial support for the logging that will be done
following measurements done by further code added to SLOF.
Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
Reviewed-by: Nikunj A Dadhania <nikunj@linux.vnet.ibm.com>
---
board-qemu/slof/vtpm-sml.fs | 3 +++
lib/libtpm/tcgbios.c | 30 ++++++++++++++++++++++++++++++
lib/libtpm/tcgbios.h | 1 +
lib/libtpm/tpm.code | 11 +++++++++++
lib/libtpm/tpm.in | 1 +
5 files changed, 46 insertions(+)
diff --git a/board-qemu/slof/vtpm-sml.fs b/board-qemu/slof/vtpm-sml.fs
index 72edac0..741a953 100644
--- a/board-qemu/slof/vtpm-sml.fs
+++ b/board-qemu/slof/vtpm-sml.fs
@@ -25,6 +25,9 @@ LOG-SIZE alloc-mem to log-base
\ create /ibm,vtpm
s" ibm,vtpm" 2dup device-name device-type
+\ convey logbase and size to the C driver
+log-base LOG-SIZE tpm-set-log-parameters
+
: sml-get-allocated-size ( -- buffer-size)
vtpm-debug? IF
." Call to sml-get-allocated-size; size = " LOG-SIZE . cr
diff --git a/lib/libtpm/tcgbios.c b/lib/libtpm/tcgbios.c
index efa4cdf..afbaede 100644
--- a/lib/libtpm/tcgbios.c
+++ b/lib/libtpm/tcgbios.c
@@ -77,10 +77,40 @@ static struct tpm_state tpm_state = {
extern struct tpm_driver tpm_drivers[];
+static void *log_base;
+static uint32_t log_area_size;
+
/********************************************************
Extensions for TCG-enabled BIOS
*******************************************************/
+void tpm_set_log_parameters(void *addr, unsigned int size)
+{
+ dprintf("Log is at 0x%llx; size is %u bytes\n",
+ (uint64_t)addr, size);
+ log_base = addr;
+ log_area_size = size;
+}
+
+static uint8_t *get_log_base_ptr(void)
+{
+ return log_base;
+}
+
+static uint32_t get_log_area_size(void)
+{
+ return log_area_size;
+}
+
+/* clear the OpenFirmware device tree log */
+static void reset_ofdt_log(void)
+{
+ uint8_t *log_area_start_address = get_log_base_ptr();
+
+ if (log_area_start_address)
+ memset(log_area_start_address, 0, get_log_area_size());
+}
+
static bool is_tpm_present(void)
{
bool rc = false;
diff --git a/lib/libtpm/tcgbios.h b/lib/libtpm/tcgbios.h
index c4c462e..9b51826 100644
--- a/lib/libtpm/tcgbios.h
+++ b/lib/libtpm/tcgbios.h
@@ -17,5 +17,6 @@
uint32_t tpm_start(void);
uint32_t tpm_unassert_pp(void);
+void tpm_set_log_parameters(void *address, unsigned int size);
#endif /* TCGBIOS_H */
diff --git a/lib/libtpm/tpm.code b/lib/libtpm/tpm.code
index 567b384..a6b66a8 100644
--- a/lib/libtpm/tpm.code
+++ b/lib/libtpm/tpm.code
@@ -35,3 +35,14 @@ PRIM(tpm_X2d_unassert_X2d_pp)
PUSH;
TOS.n = tpm_unassert_pp();
MIRP
+
+/*************************************************************/
+/* Convey log address and size */
+/* SLOF: tpm-set-log-parameters ( addr size -- ) */
+/* LIBTPM: tpm_set_log_parameters(void *addr, uint64_t size) */
+/*************************************************************/
+PRIM(tpm_X2d_set_X2d_log_X2d_parameters)
+ int size = TOS.u; POP;
+ void *addr = TOS.a; POP;
+ tpm_set_log_parameters(addr, size);
+MIRP
diff --git a/lib/libtpm/tpm.in b/lib/libtpm/tpm.in
index 266439e..a2f7cb9 100644
--- a/lib/libtpm/tpm.in
+++ b/lib/libtpm/tpm.in
@@ -15,3 +15,4 @@
cod(tpm-start)
cod(tpm-unassert-pp)
+cod(tpm-set-log-parameters)
--
1.9.3
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 05/16] Extend internal firmware API
2015-08-08 1:54 [PATCH 00/16] Add vTPM support to SLOF Stefan Berger
` (3 preceding siblings ...)
2015-08-08 1:54 ` [PATCH 04/16] Add initial support for logging Stefan Berger
@ 2015-08-08 1:54 ` Stefan Berger
2015-08-08 1:54 ` [PATCH 06/16] Return value of actual log in sml-get-handover-size Stefan Berger
` (10 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Stefan Berger @ 2015-08-08 1:54 UTC (permalink / raw)
To: linuxppc-dev, nikunj, aik, pmac
Cc: gcwilson, dimitris, latten, lo1, stefanb, Stefan Berger
Extend the internal API of the TPM firmware support with additional
functions for hashing data, extending the TPM's platform configuration
registers with a hash, and appending to the log that is recording
what was hashed.
Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
---
lib/libtpm/tcgbios.c | 276 +++++++++++++++++++++++++++++++++++++++++++++++
lib/libtpm/tcgbios_int.h | 1 +
2 files changed, 277 insertions(+)
diff --git a/lib/libtpm/tcgbios.c b/lib/libtpm/tcgbios.c
index afbaede..072ed4d 100644
--- a/lib/libtpm/tcgbios.c
+++ b/lib/libtpm/tcgbios.c
@@ -24,6 +24,9 @@
#include "tcgbios.h"
#include "tcgbios_int.h"
#include "stdio.h"
+#include "sha1.h"
+#include "stddef.h"
+#include "helpers.h"
#define DEBUG 0
#define dprintf(_x ...) do { \
@@ -79,6 +82,8 @@ extern struct tpm_driver tpm_drivers[];
static void *log_base;
static uint32_t log_area_size;
+/* next log entry goes here */
+static void *log_area_address_next;
/********************************************************
Extensions for TCG-enabled BIOS
@@ -89,6 +94,7 @@ void tpm_set_log_parameters(void *addr, unsigned int size)
dprintf("Log is at 0x%llx; size is %u bytes\n",
(uint64_t)addr, size);
log_base = addr;
+ log_area_address_next = addr;
log_area_size = size;
}
@@ -399,3 +405,273 @@ err_exit:
return rc;
return TCGBIOS_COMMAND_ERROR;
}
+
+static void set_log_area_address_next(void *next)
+{
+ log_area_address_next = next;
+}
+
+static void *get_log_area_address_next(void)
+{
+ return log_area_address_next;
+}
+
+static uint32_t tpm_sha1_calc(const uint8_t *data, uint32_t length,
+ uint8_t *hash)
+{
+ uint32_t rc;
+ uint32_t returnCode;
+ struct tpm_res_sha1start start;
+ struct tpm_res_sha1complete complete;
+ uint32_t blocks = length / 64;
+ uint32_t rest = length & 0x3f;
+ uint32_t numbytes, numbytes_no;
+ uint32_t offset = 0;
+
+ rc = build_and_send_cmd(TPM_ORD_SHA1Start,
+ NULL, 0,
+ (uint8_t *)&start, sizeof(start),
+ &returnCode, TPM_DURATION_TYPE_SHORT);
+
+ if (rc || returnCode)
+ goto err_exit;
+
+ while (blocks > 0) {
+
+ numbytes = be32_to_cpu(start.max_num_bytes);
+ if (numbytes > blocks * 64)
+ numbytes = blocks * 64;
+
+ numbytes_no = cpu_to_be32(numbytes);
+
+ rc = build_and_send_cmd_od(TPM_ORD_SHA1Update,
+ (uint8_t *)&numbytes_no,
+ sizeof(numbytes_no),
+ NULL, 0, &returnCode,
+ &data[offset], numbytes,
+ TPM_DURATION_TYPE_SHORT);
+
+ if (rc || returnCode)
+ goto err_exit;
+
+ offset += numbytes;
+ blocks -= (numbytes / 64);
+ }
+
+ numbytes_no = cpu_to_be32(rest);
+
+ rc = build_and_send_cmd_od(TPM_ORD_SHA1Complete,
+ (uint8_t *)&numbytes_no, sizeof(numbytes_no),
+ (uint8_t *)&complete, sizeof(complete),
+ &returnCode,
+ &data[offset], rest,
+ TPM_DURATION_TYPE_SHORT);
+
+ if (rc || returnCode)
+ goto err_exit;
+
+ memcpy(hash, complete.hash, sizeof(complete.hash));
+
+ return 0;
+
+err_exit:
+ dprintf("TPM SHA1 malfunctioning.\n");
+
+ tpm_state.tpm_working = 0;
+ if (rc)
+ return rc;
+ return TCGBIOS_COMMAND_ERROR;
+}
+
+static uint32_t sha1_calc(const uint8_t *data, uint32_t length, uint8_t *hash)
+{
+ if (tpm_state.tpm_driver_to_use &&
+ length < tpm_state.tpm_driver_to_use->sha1threshold)
+ return tpm_sha1_calc(data, length, hash);
+
+ return sha1(data, length, hash);
+}
+
+/*
+ * Extend the ACPI log with the given entry by copying the
+ * entry data into the log.
+ *
+ * @pcpes: Pointer to the structure to be copied into the log
+ * @event: The event to be appended to 'pcpes'
+ * @event_length: The length of the event
+ *
+ * Output:
+ * lower 16 bits of return code contain entry number
+ * if entry number is '0', then upper 16 bits contain error code.
+ */
+static uint32_t tpm_extend_ofdt_log(struct pcpes *pcpes,
+ const char *event, uint32_t event_length)
+{
+ uint32_t size;
+ uint32_t log_area_size = get_log_area_size();
+ uint8_t *log_area_start_address = get_log_base_ptr();
+ uint8_t *log_area_address_next = get_log_area_address_next();
+
+ dprintf("LASA_BASE = %p, LASA_NEXT = %p\n",
+ log_area_start_address, log_area_address_next);
+
+ if (!log_area_address_next || log_area_size == 0)
+ return TCGBIOS_LOGOVERFLOW;
+
+ size = offset_of(struct pcpes, event) + event_length;
+
+ if ((log_area_address_next + size - log_area_start_address) >
+ log_area_size) {
+ dprintf("LOG OVERFLOW: size = %d\n", size);
+ return TCGBIOS_LOGOVERFLOW;
+ }
+
+ pcpes->eventdatasize = event_length;
+
+ memcpy(log_area_address_next, pcpes, offset_of(struct pcpes, event));
+ memcpy(log_area_address_next + offset_of(struct pcpes, event),
+ event, event_length);
+
+ set_log_area_address_next(log_area_address_next + size);
+
+ return 0;
+}
+
+static uint32_t is_preboot_if_shutdown(void)
+{
+ return tpm_state.if_shutdown;
+}
+
+static uint32_t shutdown_preboot_interface(void)
+{
+ uint32_t rc = 0;
+
+ if (!is_preboot_if_shutdown()) {
+ tpm_state.if_shutdown = 1;
+ } else {
+ rc = TCGBIOS_INTERFACE_SHUTDOWN;
+ }
+
+ return rc;
+}
+
+static void tpm_shutdown(void)
+{
+ reset_ofdt_log();
+ shutdown_preboot_interface();
+}
+
+/*
+ * Pass a TPM command through to the TPM
+ *
+ * @req: request buffer to send
+ * @reqlen: request buffer length
+ * @to_t: timeout type
+ * @rsp: response buffer
+ * @rsplen: size of response buffer in input
+ * on output the number of bytes used in the buffer
+ *
+ * Returns an error code or 0 for successful sending of command
+ * and reception of response.
+ */
+static bool pass_through_to_tpm(unsigned char *req,
+ uint32_t reqlen,
+ enum tpmDurationType to_t,
+ unsigned char *rsp,
+ uint32_t *rsplen)
+{
+ uint8_t locty = 0;
+ struct iovec iovec[2] = {{ 0 }};
+
+ if (!has_working_tpm())
+ return TCGBIOS_FATAL_COM_ERROR;
+
+ iovec[0].data = req;
+ iovec[0].length = reqlen;
+
+ return transmit(locty, iovec, rsp, rsplen, to_t);
+}
+
+/*
+ * Extend a PCR of the TPM with the given hash
+ *
+ * @hash: sha1 hash (20 bytes) to extend PCR with
+ * @pcrindex: the PCR to extend [ 0..23 ]
+ */
+static uint32_t tpm_extend(uint8_t *hash, uint32_t pcrindex)
+{
+ struct tpm_req_extend req = {
+ .tag = cpu_to_be16(TPM_TAG_RQU_CMD),
+ .totlen = cpu_to_be32(sizeof(req)),
+ .ordinal = cpu_to_be32(TPM_ORD_Extend),
+ .pcrindex = cpu_to_be32(pcrindex),
+ };
+ struct tpm_rsp_extend rsp;
+ uint32_t rsplen = sizeof(rsp);
+ uint32_t rc;
+
+ memcpy(req.digest, hash, sizeof(req.digest));
+
+ rc = pass_through_to_tpm((unsigned char *)&req, sizeof(req),
+ TPM_DURATION_TYPE_SHORT,
+ (unsigned char *)&rsp, &rsplen);
+ if (!rc) {
+ if (rsplen != sizeof(rsp)) {
+ dprintf("TPM_Extend response has unexpected size: %u\n",
+ rsplen);
+ rc = TCGBIOS_FATAL_COM_ERROR;
+ }
+ }
+
+ if (rc)
+ tpm_shutdown();
+
+ return rc;
+}
+
+/*
+ * Hash then given input data and append the hash to the log
+ *
+ * @hashdata: the data to hash
+ * @hashdatalen: the size of the data to hash
+ * @pcpes: the 'pcpes' to append to the log; the hash will be written into this
+ * structure
+ * @event: the event to append to the pcpes
+ * @event_length: the lenth of the event array
+ */
+static uint32_t hash_log_event(const void *hashdata,
+ uint32_t hashdatalen,
+ struct pcpes *pcpes,
+ const char *event, uint32_t event_length)
+{
+ uint32_t rc;
+
+ if (is_preboot_if_shutdown())
+ return TCGBIOS_INTERFACE_SHUTDOWN;
+
+ if (pcpes->pcrindex >= 24)
+ return TCGBIOS_INVALID_INPUT_PARA;
+
+ if (hashdata) {
+ rc = sha1_calc(hashdata, hashdatalen, pcpes->digest);
+ if (rc)
+ return rc;
+ }
+
+ return tpm_extend_ofdt_log(pcpes, event, event_length);
+}
+
+static uint32_t hash_log_extend_event(const void *hashdata,
+ uint32_t hashdatalen,
+ struct pcpes *pcpes,
+ const char *event, uint32_t event_length,
+ uint32_t pcrindex)
+{
+ uint32_t rc = 0;
+
+ rc = hash_log_event(hashdata, hashdatalen, pcpes, event, event_length);
+ if (rc)
+ return rc;
+
+ return tpm_extend(pcpes->digest, pcrindex);
+}
diff --git a/lib/libtpm/tcgbios_int.h b/lib/libtpm/tcgbios_int.h
index c8caf3b..888186c 100644
--- a/lib/libtpm/tcgbios_int.h
+++ b/lib/libtpm/tcgbios_int.h
@@ -46,6 +46,7 @@
#define TPM_ST_DEACTIVATED 0x3
#define TPM_TAG_RQU_CMD 0x00c1
+#define TPM_TAG_RSP_CMD 0x00c4
/* TPM command error codes */
#define TPM_INVALID_POSTINIT 0x26
--
1.9.3
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 06/16] Return value of actual log in sml-get-handover-size
2015-08-08 1:54 [PATCH 00/16] Add vTPM support to SLOF Stefan Berger
` (4 preceding siblings ...)
2015-08-08 1:54 ` [PATCH 05/16] Extend internal firmware API Stefan Berger
@ 2015-08-08 1:54 ` Stefan Berger
2015-08-08 1:54 ` [PATCH 07/16] Perform some initial measurements Stefan Berger
` (9 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Stefan Berger @ 2015-08-08 1:54 UTC (permalink / raw)
To: linuxppc-dev, nikunj, aik, pmac
Cc: gcwilson, dimitris, latten, lo1, stefanb, Stefan Berger
With the functions for calculating the actual size of the log in place,
use them to determine the exact size of the log that the firmware
API call sml-get-handover-size now returns.
Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
---
board-qemu/slof/vtpm-sml.fs | 4 ++--
lib/libtpm/tcgbios.c | 15 +++++++++++++++
lib/libtpm/tcgbios.h | 1 +
lib/libtpm/tpm.code | 10 ++++++++++
lib/libtpm/tpm.in | 1 +
5 files changed, 29 insertions(+), 2 deletions(-)
diff --git a/board-qemu/slof/vtpm-sml.fs b/board-qemu/slof/vtpm-sml.fs
index 741a953..28c30f1 100644
--- a/board-qemu/slof/vtpm-sml.fs
+++ b/board-qemu/slof/vtpm-sml.fs
@@ -37,9 +37,9 @@ log-base LOG-SIZE tpm-set-log-parameters
: sml-get-handover-size ( -- size )
vtpm-debug? IF
- ." Call to sml-get-handover-size; size = " LOG-SIZE . cr
+ ." Call to sml-get-handover-size; size = " tpm-get-logsize . cr
THEN
- LOG-SIZE
+ tpm-get-logsize
;
: sml-handover ( dest size -- )
diff --git a/lib/libtpm/tcgbios.c b/lib/libtpm/tcgbios.c
index 072ed4d..e86cfc2 100644
--- a/lib/libtpm/tcgbios.c
+++ b/lib/libtpm/tcgbios.c
@@ -416,6 +416,21 @@ static void *get_log_area_address_next(void)
return log_area_address_next;
}
+uint32_t tpm_get_logsize(void)
+{
+ uint8_t *log_area_start_address = get_log_base_ptr();
+ uint8_t *log_area_address_next = get_log_area_address_next();
+ uint32_t logsize;
+
+ if (log_area_address_next) {
+ logsize = log_area_address_next - log_area_start_address;
+ dprintf("log size: %u\n", logsize);
+ return logsize;
+ }
+
+ return 0;
+}
+
static uint32_t tpm_sha1_calc(const uint8_t *data, uint32_t length,
uint8_t *hash)
{
diff --git a/lib/libtpm/tcgbios.h b/lib/libtpm/tcgbios.h
index 9b51826..b217dd1 100644
--- a/lib/libtpm/tcgbios.h
+++ b/lib/libtpm/tcgbios.h
@@ -18,5 +18,6 @@
uint32_t tpm_start(void);
uint32_t tpm_unassert_pp(void);
void tpm_set_log_parameters(void *address, unsigned int size);
+uint32_t tpm_get_logsize(void);
#endif /* TCGBIOS_H */
diff --git a/lib/libtpm/tpm.code b/lib/libtpm/tpm.code
index a6b66a8..b868ca3 100644
--- a/lib/libtpm/tpm.code
+++ b/lib/libtpm/tpm.code
@@ -46,3 +46,13 @@ PRIM(tpm_X2d_set_X2d_log_X2d_parameters)
void *addr = TOS.a; POP;
tpm_set_log_parameters(addr, size);
MIRP
+
+/************************************************/
+/* Get the size of the log */
+/* SLOF: tpm-get-logsize ( -- size ) */
+/* LIBTPM: logsize = tpm_get_logsize(void) */
+/************************************************/
+PRIM(tpm_X2d_get_X2d_logsize)
+ PUSH;
+ TOS.n = tpm_get_logsize();
+MIRP
diff --git a/lib/libtpm/tpm.in b/lib/libtpm/tpm.in
index a2f7cb9..32d675f 100644
--- a/lib/libtpm/tpm.in
+++ b/lib/libtpm/tpm.in
@@ -16,3 +16,4 @@
cod(tpm-start)
cod(tpm-unassert-pp)
cod(tpm-set-log-parameters)
+cod(tpm-get-logsize)
--
1.9.3
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 07/16] Perform some initial measurements
2015-08-08 1:54 [PATCH 00/16] Add vTPM support to SLOF Stefan Berger
` (5 preceding siblings ...)
2015-08-08 1:54 ` [PATCH 06/16] Return value of actual log in sml-get-handover-size Stefan Berger
@ 2015-08-08 1:54 ` Stefan Berger
2015-08-08 1:54 ` [PATCH 08/16] Add support for controlling the states of the TPM Stefan Berger
` (8 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Stefan Berger @ 2015-08-08 1:54 UTC (permalink / raw)
To: linuxppc-dev, nikunj, aik, pmac
Cc: gcwilson, dimitris, latten, lo1, stefanb, Stefan Berger
This patch puts an 'event' separator into the log that can
then be seen in Linux's /sys/kernel/security/tpm0/ascii_bios_measurements.
More low-level C functions are added for measuring and logging of disk
related data, along with their FORTH-level counterparts. These functions
will be called in subsequent patches.
Logging follows the specifications found on the following page:
http://www.trustedcomputinggroup.org/resources/pc_client_work_group_specific_implementation_specification_for_conventional_bios
Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
---
board-qemu/slof/OF.fs | 1 +
lib/libtpm/tcgbios.c | 201 ++++++++++++++++++++++++++++++++++++++++++++++
lib/libtpm/tcgbios.h | 9 +++
lib/libtpm/tpm.code | 34 ++++++++
lib/libtpm/tpm.in | 3 +
slof/fs/tpm/tpm-static.fs | 11 +++
6 files changed, 259 insertions(+)
diff --git a/board-qemu/slof/OF.fs b/board-qemu/slof/OF.fs
index bd9495e..1306371 100644
--- a/board-qemu/slof/OF.fs
+++ b/board-qemu/slof/OF.fs
@@ -304,6 +304,7 @@ cr
#include "copyright-oss.fs"
cr cr
+vtpm-add-event-separators
vtpm-unassert-pp
\ this CATCH is to ensure the code bellow always executes: boot may ABORT!
diff --git a/lib/libtpm/tcgbios.c b/lib/libtpm/tcgbios.c
index e86cfc2..2f5b048 100644
--- a/lib/libtpm/tcgbios.c
+++ b/lib/libtpm/tcgbios.c
@@ -66,6 +66,8 @@ static const uint8_t GetCapability_Durations[] = {
0x00, 0x00, 0x01, 0x20
};
+static uint8_t evt_separator[] = {0xff,0xff,0xff,0xff};
+
struct tpm_state {
uint8_t tpm_probed:1;
uint8_t tpm_found:1;
@@ -690,3 +692,202 @@ static uint32_t hash_log_extend_event(const void *hashdata,
return tpm_extend(pcpes->digest, pcrindex);
}
+
+/*
+ * Add a measurement to the log;
+ *
+ * Input parameters:
+ * @pcrindex : PCR to extend
+ * @event_type : type of event
+ * @info : pointer to info (i.e., string) to be added to the log as-is
+ * @info_length: length of the info
+ * @data : pointer to data to be hashed
+ * @data_length: length of the data
+ *
+ */
+static uint32_t tpm_add_measurement_to_log(uint32_t pcrindex,
+ uint32_t eventtype,
+ const char *info,
+ uint32_t infolen,
+ const uint8_t *data,
+ uint32_t datalen)
+{
+ struct pcpes pcpes;
+
+ pcpes.pcrindex = pcrindex;
+ pcpes.eventtype = eventtype;
+ memset(&pcpes.digest, 0, sizeof(pcpes.digest));
+
+ return hash_log_extend_event(data, datalen, &pcpes,
+ info, infolen, pcrindex);
+}
+
+/*
+ * Add a measurement to the list of measurements
+ * pcrindex : PCR to be extended
+ * event_type : type of event
+ * string : string describing the event; used if event_type is EV_ACTION
+ */
+static uint32_t tpm_add_measurement(uint32_t pcrindex,
+ uint16_t event_type,
+ const char *string)
+{
+ uint32_t rc;
+ uint32_t len;
+
+ switch (event_type) {
+ case EV_SEPARATOR:
+ len = sizeof(evt_separator);
+ rc = tpm_add_measurement_to_log(pcrindex, event_type,
+ NULL, 0,
+ (uint8_t *)evt_separator, len);
+ break;
+
+ case EV_ACTION:
+ rc = tpm_add_measurement_to_log(pcrindex, event_type,
+ string, strlen(string),
+ (uint8_t *)string, strlen(string));
+ break;
+
+ default:
+ rc = TCGBIOS_INVALID_INPUT_PARA;
+ }
+
+ return rc;
+}
+
+/*
+ * Add event separators for PCRs 0 to 7
+ */
+uint32_t tpm_add_event_separators(void)
+{
+ uint32_t rc;
+ uint32_t pcrindex = 0;
+
+ if (!has_working_tpm())
+ return TCGBIOS_GENERAL_ERROR;
+
+ while (pcrindex <= 7) {
+ rc = tpm_add_measurement(pcrindex, EV_SEPARATOR, NULL);
+ if (rc)
+ break;
+ pcrindex ++;
+ }
+
+ return rc;
+}
+
+/*
+ * Add a measurement regarding the boot device (CDRom, Floppy, HDD) to
+ * the list of measurements.
+ */
+static uint32_t tpm_add_bootdevice(uint32_t bootcd, uint32_t bootdrv)
+{
+ const char *string;
+
+ dprintf("add bootdevice: bootcd = %d, bootdrv = 0x%x\n", bootcd, bootdrv);
+
+ if (!has_working_tpm())
+ return TCGBIOS_GENERAL_ERROR;
+
+ switch (bootcd) {
+ case 0:
+ switch (bootdrv) {
+ case 0:
+ string = "Booting BCV device 00h (Floppy)";
+ break;
+
+ case 0x80:
+ string = "Booting BCV device 80h (HDD)";
+ break;
+
+ default:
+ string = "Booting unknown device";
+ break;
+ }
+ break;
+
+ default:
+ string = "Booting from CD ROM device";
+ }
+
+ return tpm_add_measurement_to_log(4, EV_ACTION,
+ string, strlen(string),
+ (uint8_t *)string, strlen(string));
+}
+
+/*
+ * Add a measurement to the log. Creates two log entries
+ *
+ * Input parameter:
+ * bootcd : 0: MBR of hdd, 1: boot image, 2: boot catalog of El Torito
+ * addr : address where the IP data are located
+ * length : IP data length in bytes
+ */
+uint32_t tpm_ipl(enum ipltype bootcd, const uint8_t *addr, uint32_t length)
+{
+ uint32_t rc;
+ const char *string;
+
+ dprintf("tpm_ipl: bootcd = %d, addr = %p, length = 0x%x\n",
+ bootcd, addr, length);
+
+ if (!has_working_tpm())
+ return TCGBIOS_GENERAL_ERROR;
+
+ switch (bootcd) {
+ case IPL_EL_TORITO_1:
+ /* specs: see section 'El Torito' */
+ string = "EL TORITO IPL";
+ rc = tpm_add_measurement_to_log(4, EV_IPL,
+ string, strlen(string),
+ addr, length);
+ break;
+
+ case IPL_EL_TORITO_2:
+ /* specs: see section 'El Torito' */
+ string = "BOOT CATALOG";
+ rc = tpm_add_measurement_to_log(5, EV_IPL_PARTITION_DATA,
+ string, strlen(string),
+ addr, length);
+ break;
+
+ default:
+ /*
+ * equivalent to:
+ * dd if=/dev/hda ibs=1 count=440 | sha1sum
+ */
+ string = "MBR";
+ rc = tpm_add_measurement_to_log(4, EV_IPL,
+ string, strlen(string),
+ addr, 0x1b8);
+
+ if (rc)
+ break;
+
+ /*
+ * equivalent to:
+ * dd if=/dev/hda ibs=1 count=72 skip=440 | sha1sum
+ */
+ string = "MBR PARTITION TABLE";
+ rc = tpm_add_measurement_to_log(5, EV_IPL_PARTITION_DATA,
+ string, strlen(string),
+ addr + 0x1b8, 0x48);
+ }
+
+ return rc;
+}
+
+uint32_t tpm_add_bcv(uint32_t bootdrv, const uint8_t *addr, uint32_t length)
+{
+ uint32_t rc;
+
+ if (!has_working_tpm())
+ return TCGBIOS_GENERAL_ERROR;
+
+ rc = tpm_add_bootdevice(0, bootdrv);
+ if (rc)
+ return rc;
+
+ return tpm_ipl(IPL_BCV, addr, length);
+}
diff --git a/lib/libtpm/tcgbios.h b/lib/libtpm/tcgbios.h
index b217dd1..9b43ce3 100644
--- a/lib/libtpm/tcgbios.h
+++ b/lib/libtpm/tcgbios.h
@@ -15,9 +15,18 @@
#include <stdint.h>
+enum ipltype {
+ IPL_BCV = 0,
+ IPL_EL_TORITO_1,
+ IPL_EL_TORITO_2
+};
+
uint32_t tpm_start(void);
uint32_t tpm_unassert_pp(void);
void tpm_set_log_parameters(void *address, unsigned int size);
uint32_t tpm_get_logsize(void);
+uint32_t tpm_ipl(enum ipltype bootcd, const uint8_t *addr, uint32_t length);
+uint32_t tpm_add_bcv(uint32_t bootdrv, const uint8_t *addr, uint32_t length);
+uint32_t tpm_add_event_separators(void);
#endif /* TCGBIOS_H */
diff --git a/lib/libtpm/tpm.code b/lib/libtpm/tpm.code
index b868ca3..de90717 100644
--- a/lib/libtpm/tpm.code
+++ b/lib/libtpm/tpm.code
@@ -56,3 +56,37 @@ PRIM(tpm_X2d_get_X2d_logsize)
PUSH;
TOS.n = tpm_get_logsize();
MIRP
+
+/************************************************/
+/* Measure and log event separators */
+/* SLOF: tpm-add-event-separators ( -- ) */
+/* LIBTPM: tpm_add_event_separators(void) */
+/************************************************/
+PRIM(tpm_X2d_add_X2d_event_X2d_separators)
+ PUSH;
+ TOS.n = tpm_add_event_separators();
+MIRP
+
+/************************************************/
+/* Measure and log IPL */
+/* SLOF: tpm-ipl ( ipltype addr length -- ) */
+/* LIBTPM: tpm_ipl(void) */
+/************************************************/
+PRIM(tpm_X2d_ipl)
+ int length = TOS.u; POP;
+ void *addr = TOS.a; POP;
+ int bootcd = TOS.u;
+ TOS.n = tpm_ipl(bootcd, addr, length);
+MIRP
+
+/****************************************************/
+/* Measure and log bcv IPL */
+/* SLOF: tpm-add-bcv ( bootdrv addr length -- ) */
+/* LIBTPM: tpm_add_bcv(void) */
+/****************************************************/
+PRIM(tpm_X2d_add_X2d_bcv)
+ int length = TOS.u; POP;
+ void *addr = TOS.a; POP;
+ int bootdrv = TOS.u;
+ TOS.n = tpm_add_bcv(bootdrv, addr, length);
+MIRP
diff --git a/lib/libtpm/tpm.in b/lib/libtpm/tpm.in
index 32d675f..06b0672 100644
--- a/lib/libtpm/tpm.in
+++ b/lib/libtpm/tpm.in
@@ -17,3 +17,6 @@ cod(tpm-start)
cod(tpm-unassert-pp)
cod(tpm-set-log-parameters)
cod(tpm-get-logsize)
+cod(tpm-add-event-separators)
+cod(tpm-ipl)
+cod(tpm-add-bcv)
diff --git a/slof/fs/tpm/tpm-static.fs b/slof/fs/tpm/tpm-static.fs
index 11e4ad5..d425693 100644
--- a/slof/fs/tpm/tpm-static.fs
+++ b/slof/fs/tpm/tpm-static.fs
@@ -22,6 +22,17 @@ false VALUE vtpm-debug?
THEN
;
+: vtpm-add-event-separators
+ vtpm-available? IF
+ tpm-add-event-separators ( -- errcode )
+ vtpm-debug? IF
+ ." VTPM: Error code from tpm-add-event-separators: " . cr
+ ELSE
+ drop
+ THEN
+ THEN
+;
+
: vtpm-unassert-pp
vtpm-available? IF
tpm-unassert-pp ( -- errcode )
--
1.9.3
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 08/16] Add support for controlling the states of the TPM
2015-08-08 1:54 [PATCH 00/16] Add vTPM support to SLOF Stefan Berger
` (6 preceding siblings ...)
2015-08-08 1:54 ` [PATCH 07/16] Perform some initial measurements Stefan Berger
@ 2015-08-08 1:54 ` Stefan Berger
2015-08-08 1:54 ` [PATCH 09/16] Add support for a TPM menu to control the state " Stefan Berger
` (7 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Stefan Berger @ 2015-08-08 1:54 UTC (permalink / raw)
To: linuxppc-dev, nikunj, aik, pmac
Cc: gcwilson, dimitris, latten, lo1, stefanb, Stefan Berger
This patch adds support for controlling the various states of
the TPM, such as enabling and disabling the TPM, deactivating
and activating it, and clearing ownership.
The TPM menu implementation will call these functions by
calling tpm_process_opcode with an opcode indicating as to
how the state of the TPM is to be changed.
Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
---
lib/libtpm/tcgbios.c | 459 +++++++++++++++++++++++++++++++++++++++++++++++
lib/libtpm/tcgbios.h | 2 +
lib/libtpm/tcgbios_int.h | 34 ++++
lib/libtpm/tpm.code | 12 ++
lib/libtpm/tpm.in | 1 +
5 files changed, 508 insertions(+)
diff --git a/lib/libtpm/tcgbios.c b/lib/libtpm/tcgbios.c
index 2f5b048..cabd980 100644
--- a/lib/libtpm/tcgbios.c
+++ b/lib/libtpm/tcgbios.c
@@ -51,6 +51,11 @@ static const uint8_t GetCapability_Permanent_Flags[] = {
0x00, 0x00, 0x01, 0x08
};
+static const uint8_t GetCapability_STClear_Flags[] = {
+ 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04,
+ 0x00, 0x00, 0x01, 0x09
+};
+
static const uint8_t GetCapability_OwnerAuth[] = {
0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04,
0x00, 0x00, 0x01, 0x11
@@ -82,6 +87,10 @@ static struct tpm_state tpm_state = {
extern struct tpm_driver tpm_drivers[];
+typedef struct {
+ uint8_t op;
+} tpm_bios_cfg;
+
static void *log_base;
static uint32_t log_area_size;
/* next log entry goes here */
@@ -891,3 +900,453 @@ uint32_t tpm_add_bcv(uint32_t bootdrv, const uint8_t *addr, uint32_t length)
return tpm_ipl(IPL_BCV, addr, length);
}
+
+static uint32_t read_stclear_flags(char *buf, int buf_len)
+{
+ uint32_t rc;
+ uint32_t returnCode;
+ struct tpm_res_getcap_stclear_flags stcf;
+
+ memset(buf, 0, buf_len);
+
+ rc = build_and_send_cmd(TPM_ORD_GetCapability,
+ GetCapability_STClear_Flags,
+ sizeof(GetCapability_STClear_Flags),
+ (uint8_t *)&stcf, sizeof(stcf),
+ &returnCode, TPM_DURATION_TYPE_SHORT);
+
+ dprintf("Return code from TPM_GetCapability() = 0x%08x\n",
+ returnCode);
+
+ if (rc || returnCode)
+ goto err_exit;
+
+ memcpy(buf, &stcf.stclear_flags, buf_len);
+
+ return 0;
+
+err_exit:
+ dprintf("TPM malfunctioning (line %d).\n", __LINE__);
+
+ tpm_state.tpm_working = 0;
+ if (rc)
+ return rc;
+ return TCGBIOS_COMMAND_ERROR;
+}
+
+static uint32_t assert_physical_presence(bool verbose)
+{
+ uint32_t rc = 0;
+ uint32_t returnCode;
+ struct tpm_stclear_flags stcf;
+
+ rc = read_stclear_flags((char *)&stcf, sizeof(stcf));
+ if (rc) {
+ dprintf("Error reading STClear flags: 0x%08x\n", rc);
+ return rc;
+ }
+
+ if (stcf.flags[STCLEAR_FLAG_IDX_PHYSICAL_PRESENCE])
+ /* physical presence already asserted */
+ return 0;
+
+ rc = build_and_send_cmd(TPM_ORD_PhysicalPresence,
+ PhysicalPresence_CMD_ENABLE,
+ sizeof(PhysicalPresence_CMD_ENABLE),
+ NULL, 0, &returnCode,
+ TPM_DURATION_TYPE_SHORT);
+
+ dprintf("Return code from TSC_PhysicalPresence(CMD_ENABLE) = 0x%08x\n",
+ returnCode);
+
+ if (rc || returnCode) {
+ if (verbose)
+ printf("Error: Could not enable physical presence.\n\n");
+ goto err_exit;
+ }
+
+ rc = build_and_send_cmd(TPM_ORD_PhysicalPresence,
+ PhysicalPresence_PRESENT,
+ sizeof(PhysicalPresence_PRESENT),
+ NULL, 0, &returnCode,
+ TPM_DURATION_TYPE_SHORT);
+
+ dprintf("Return code from TSC_PhysicalPresence(PRESENT) = 0x%08x\n",
+ returnCode);
+
+ if (rc || returnCode) {
+ if (verbose)
+ printf("Error: Could not set presence flag.\n\n");
+ goto err_exit;
+ }
+
+ return 0;
+
+err_exit:
+ dprintf("TPM malfunctioning (line %d).\n", __LINE__);
+
+ tpm_state.tpm_working = 0;
+ if (rc)
+ return rc;
+ return TCGBIOS_COMMAND_ERROR;
+}
+
+static uint32_t read_permanent_flags(char *buf, int buf_len)
+{
+ uint32_t rc;
+ uint32_t returnCode;
+ struct tpm_res_getcap_perm_flags pf;
+
+ memset(buf, 0, buf_len);
+
+ rc = build_and_send_cmd(TPM_ORD_GetCapability,
+ GetCapability_Permanent_Flags,
+ sizeof(GetCapability_Permanent_Flags),
+ (uint8_t *)&pf, sizeof(pf),
+ &returnCode, TPM_DURATION_TYPE_SHORT);
+
+ dprintf("Return code from TPM_GetCapability() = 0x%08x\n",
+ returnCode);
+
+ if (rc || returnCode)
+ goto err_exit;
+
+ memcpy(buf, &pf.perm_flags, buf_len);
+
+ return 0;
+
+err_exit:
+ dprintf("TPM malfunctioning (line %d).\n", __LINE__);
+
+ tpm_state.tpm_working = 0;
+ if (rc)
+ return rc;
+ return TCGBIOS_COMMAND_ERROR;
+}
+
+static uint32_t read_has_owner(bool *has_owner)
+{
+ uint32_t rc;
+ uint32_t returnCode;
+ struct tpm_res_getcap_ownerauth oauth;
+
+ rc = build_and_send_cmd(TPM_ORD_GetCapability,
+ GetCapability_OwnerAuth,
+ sizeof(GetCapability_OwnerAuth),
+ (uint8_t *)&oauth, sizeof(oauth),
+ &returnCode, TPM_DURATION_TYPE_SHORT);
+
+ dprintf("Return code from TPM_GetCapability() = 0x%08x\n",
+ returnCode);
+
+ if (rc || returnCode)
+ goto err_exit;
+
+ *has_owner = oauth.flag;
+
+ return 0;
+
+err_exit:
+ dprintf("TPM malfunctioning (line %d).\n", __LINE__);
+
+ tpm_state.tpm_working = 0;
+ if (rc)
+ return rc;
+ return TCGBIOS_COMMAND_ERROR;
+}
+
+static uint32_t enable_tpm(bool enable, uint32_t *returnCode, bool verbose)
+{
+ uint32_t rc;
+ struct tpm_permanent_flags pf;
+
+ rc = read_permanent_flags((char *)&pf, sizeof(pf));
+ if (rc)
+ return rc;
+
+ if (!!pf.flags[PERM_FLAG_IDX_DISABLE] == !enable)
+ return 0;
+
+ rc = assert_physical_presence(verbose);
+ if (rc) {
+ dprintf("Asserting physical presence failed.\n");
+ return rc;
+ }
+
+ rc = build_and_send_cmd(enable ? TPM_ORD_PhysicalEnable
+ : TPM_ORD_PhysicalDisable,
+ NULL, 0, NULL, 0, returnCode,
+ TPM_DURATION_TYPE_SHORT);
+ if (enable) {
+ dprintf("Return code from TPM_PhysicalEnable = 0x%08x\n",
+ *returnCode);
+ } else {
+ dprintf("Return code from TPM_PhysicalDisable = 0x%08x\n",
+ *returnCode);
+ }
+
+ if (rc || *returnCode)
+ goto err_exit;
+
+ return 0;
+
+err_exit:
+ if (enable) {
+ dprintf("Enabling the TPM failed.\n");
+ } else {
+ dprintf("Disabling the TPM failed.\n");
+ }
+ dprintf("TPM malfunctioning (line %d).\n", __LINE__);
+
+ tpm_state.tpm_working = 0;
+ if (rc)
+ return rc;
+ return TCGBIOS_COMMAND_ERROR;
+}
+
+static uint32_t activate_tpm(bool activate, bool allow_reset,
+ uint32_t *returnCode, bool verbose)
+{
+ uint32_t rc;
+ struct tpm_permanent_flags pf;
+
+ rc = read_permanent_flags((char *)&pf, sizeof(pf));
+ if (rc)
+ return rc;
+
+ if (!!pf.flags[PERM_FLAG_IDX_DEACTIVATED] == !activate)
+ return 0;
+
+ if (pf.flags[PERM_FLAG_IDX_DISABLE])
+ return 0;
+
+ rc = assert_physical_presence(verbose);
+ if (rc) {
+ dprintf("Asserting physical presence failed.\n");
+ return rc;
+ }
+
+ rc = build_and_send_cmd(TPM_ORD_PhysicalSetDeactivated,
+ activate ? CommandFlag_FALSE
+ : CommandFlag_TRUE,
+ activate ? sizeof(CommandFlag_FALSE)
+ : sizeof(CommandFlag_TRUE),
+ NULL, 0, returnCode,
+ TPM_DURATION_TYPE_SHORT);
+
+ dprintf("Return code from PhysicalSetDeactivated(%d) = 0x%08x\n",
+ activate ? 0 : 1, *returnCode);
+
+ if (rc || *returnCode)
+ goto err_exit;
+
+ if (activate && allow_reset) {
+ if (verbose) {
+ printf("Requiring a reboot to activate the TPM.\n");
+ }
+ }
+
+ return 0;
+
+err_exit:
+ dprintf("TPM malfunctioning (line %d).\n", __LINE__);
+
+ tpm_state.tpm_working = 0;
+ if (rc)
+ return rc;
+ return TCGBIOS_COMMAND_ERROR;
+}
+
+static uint32_t enable_activate(int allow_reset, uint32_t *returnCode,
+ bool verbose)
+{
+ uint32_t rc;
+
+ rc = enable_tpm(true, returnCode, verbose);
+ if (rc)
+ return rc;
+
+ rc = activate_tpm(true, allow_reset, returnCode, verbose);
+
+ return rc;
+}
+
+static uint32_t force_clear(bool enable_activate_before,
+ bool enable_activate_after,
+ uint32_t *returnCode, bool verbose)
+{
+ uint32_t rc;
+ bool has_owner;
+
+ rc = read_has_owner(&has_owner);
+ if (rc)
+ return rc;
+ if (!has_owner) {
+ if (verbose)
+ printf("TPM does not have an owner.\n");
+ return 0;
+ }
+
+ if (enable_activate_before) {
+ rc = enable_activate(0, returnCode, verbose);
+ if (rc) {
+ dprintf("Enabling/activating the TPM failed.\n");
+ return rc;
+ }
+ }
+
+ rc = assert_physical_presence(verbose);
+ if (rc) {
+ dprintf("Asserting physical presence failed.\n");
+ return rc;
+ }
+
+ rc = build_and_send_cmd(TPM_ORD_ForceClear,
+ NULL, 0, NULL, 0, returnCode,
+ TPM_DURATION_TYPE_SHORT);
+
+ dprintf("Return code from TPM_ForceClear() = 0x%08x\n",
+ *returnCode);
+
+ if (rc || *returnCode)
+ goto err_exit;
+
+ if (!enable_activate_after) {
+ if (verbose)
+ printf("Owner successfully cleared.\n"
+ "You will need to enable/activate the TPM again.\n\n");
+ return 0;
+ }
+
+ enable_activate(true, returnCode, verbose);
+
+ return 0;
+
+err_exit:
+ dprintf("TPM malfunctioning (line %d).\n", __LINE__);
+
+ tpm_state.tpm_working = 0;
+ if (rc)
+ return rc;
+ return TCGBIOS_COMMAND_ERROR;
+}
+
+static uint32_t set_owner_install(bool allow, uint32_t *returnCode,
+ bool verbose)
+{
+ uint32_t rc;
+ bool has_owner;
+ struct tpm_permanent_flags pf;
+
+ rc = read_has_owner(&has_owner);
+ if (rc)
+ return rc;
+ if (has_owner) {
+ if (verbose)
+ printf("Must first remove owner.\n");
+ return 0;
+ }
+
+ rc = read_permanent_flags((char *)&pf, sizeof(pf));
+ if (rc)
+ return rc;
+
+ if (pf.flags[PERM_FLAG_IDX_DISABLE]) {
+ if (verbose)
+ printf("TPM must first be enable.\n");
+ return 0;
+ }
+
+ rc = assert_physical_presence(verbose);
+ if (rc) {
+ dprintf("Asserting physical presence failed.\n");
+ return rc;
+ }
+
+ rc = build_and_send_cmd(TPM_ORD_SetOwnerInstall,
+ (allow) ? CommandFlag_TRUE :
+ CommandFlag_FALSE,
+ sizeof(CommandFlag_TRUE),
+ NULL, 0, returnCode,
+ TPM_DURATION_TYPE_SHORT);
+
+ dprintf("Return code from TPM_SetOwnerInstall() = 0x%08x\n",
+ *returnCode);
+
+ if (rc || *returnCode)
+ goto err_exit;
+
+ if (verbose) {
+ if (allow)
+ printf("Installation of owner enabled.\n");
+ else
+ printf("Installation of owner disabled.\n");
+ }
+
+ return 0;
+
+err_exit:
+ dprintf("TPM malfunctioning (line %d).\n", __LINE__);
+ tpm_state.tpm_working = 0;
+ if (rc)
+ return rc;
+ return TCGBIOS_COMMAND_ERROR;
+}
+
+static uint32_t tpm_process_cfg(const tpm_bios_cfg *cfg, bool verbose,
+ uint32_t *returnCode)
+{
+ uint32_t rc = 0;
+
+ switch (cfg->op) {
+ case TPM_PPI_OP_NOOP: /* no-op */
+ break;
+
+ case TPM_PPI_OP_ENABLE:
+ rc = enable_tpm(true, returnCode, verbose);
+ break;
+
+ case TPM_PPI_OP_DISABLE:
+ rc = enable_tpm(false, returnCode, verbose);
+ break;
+
+ case TPM_PPI_OP_ACTIVATE:
+ rc = activate_tpm(true, true, returnCode, verbose);
+ break;
+
+ case TPM_PPI_OP_DEACTIVATE:
+ rc = activate_tpm(false, true, returnCode, verbose);
+ break;
+
+ case TPM_PPI_OP_CLEAR:
+ rc = force_clear(true, false, returnCode, verbose);
+ break;
+
+ case TPM_PPI_OP_SET_OWNERINSTALL_TRUE:
+ rc = set_owner_install(true, returnCode, verbose);
+ break;
+
+ case TPM_PPI_OP_SET_OWNERINSTALL_FALSE:
+ rc = set_owner_install(false, returnCode, verbose);
+ break;
+
+ default:
+ break;
+ }
+
+ if (rc)
+ printf("Op %d: An error occurred: 0x%x TPM return code: 0x%x\n",
+ cfg->op, rc, *returnCode);
+
+ return rc;
+}
+
+uint32_t tpm_process_opcode(uint8_t op, bool verbose)
+{
+ uint32_t returnCode;
+ tpm_bios_cfg cfg = {
+ .op = op
+ };
+
+ return tpm_process_cfg(&cfg, verbose, &returnCode);
+}
diff --git a/lib/libtpm/tcgbios.h b/lib/libtpm/tcgbios.h
index 9b43ce3..e0a7045 100644
--- a/lib/libtpm/tcgbios.h
+++ b/lib/libtpm/tcgbios.h
@@ -14,6 +14,7 @@
#define TCGBIOS_H
#include <stdint.h>
+#include <stdbool.h>
enum ipltype {
IPL_BCV = 0,
@@ -28,5 +29,6 @@ uint32_t tpm_get_logsize(void);
uint32_t tpm_ipl(enum ipltype bootcd, const uint8_t *addr, uint32_t length);
uint32_t tpm_add_bcv(uint32_t bootdrv, const uint8_t *addr, uint32_t length);
uint32_t tpm_add_event_separators(void);
+uint32_t tpm_process_opcode(uint8_t op, bool verbose);
#endif /* TCGBIOS_H */
diff --git a/lib/libtpm/tcgbios_int.h b/lib/libtpm/tcgbios_int.h
index 888186c..420049f 100644
--- a/lib/libtpm/tcgbios_int.h
+++ b/lib/libtpm/tcgbios_int.h
@@ -14,6 +14,7 @@
#define TCGBIOS_INT_H
#include <stdint.h>
+#include <stdbool.h>
#include "tpm_drivers.h"
@@ -138,6 +139,30 @@ struct tpm_res_getcap_perm_flags {
struct tpm_permanent_flags perm_flags;
} __attribute__((packed));
+struct tpm_req_getcap_stclear_flags {
+ TPM_REQ_HEADER
+ uint32_t capArea;
+ uint32_t subCapSize;
+ uint32_t subCap;
+} __attribute__((packed));
+
+struct tpm_stclear_flags {
+ uint16_t tag;
+ uint8_t flags[5];
+} __attribute__((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 {
+ TPM_RSP_HEADER
+ uint32_t size;
+ struct tpm_stclear_flags stclear_flags;
+} __attribute__((packed));
+
struct tpm_res_getcap_ownerauth {
TPM_RSP_HEADER
uint32_t size;
@@ -160,4 +185,13 @@ struct tpm_res_sha1complete {
uint8_t hash[SHA1_BUFSIZE];
} __attribute__((packed));
+#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 /* TCGBIOS_INT_H */
diff --git a/lib/libtpm/tpm.code b/lib/libtpm/tpm.code
index de90717..7728317 100644
--- a/lib/libtpm/tpm.code
+++ b/lib/libtpm/tpm.code
@@ -14,6 +14,7 @@
*/
#include <tcgbios.h>
+#include <stdbool.h>
/************************************************/
@@ -90,3 +91,14 @@ PRIM(tpm_X2d_add_X2d_bcv)
int bootdrv = TOS.u;
TOS.n = tpm_add_bcv(bootdrv, addr, length);
MIRP
+
+/******************************************************/
+/* Process an opcode to change state of the TPM */
+/* SLOF: tpm-process-opcode ( opcode verbose -- ) */
+/* LIBTPM: tpm_process_opcode(opcode, verbose) */
+/******************************************************/
+PRIM(tpm_X2d_process_X2d_opcode)
+ int opcode = TOS.u; POP;
+ bool verbose = TOS.u;
+ TOS.n = tpm_process_opcode(opcode, verbose);
+MIRP
diff --git a/lib/libtpm/tpm.in b/lib/libtpm/tpm.in
index 06b0672..e5dbc25 100644
--- a/lib/libtpm/tpm.in
+++ b/lib/libtpm/tpm.in
@@ -20,3 +20,4 @@ cod(tpm-get-logsize)
cod(tpm-add-event-separators)
cod(tpm-ipl)
cod(tpm-add-bcv)
+cod(tpm-process-opcode)
--
1.9.3
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 09/16] Add support for a TPM menu to control the state of the TPM
2015-08-08 1:54 [PATCH 00/16] Add vTPM support to SLOF Stefan Berger
` (7 preceding siblings ...)
2015-08-08 1:54 ` [PATCH 08/16] Add support for controlling the states of the TPM Stefan Berger
@ 2015-08-08 1:54 ` Stefan Berger
2015-08-08 1:54 ` [PATCH 10/16] Implement measurements of the master boot record Stefan Berger
` (6 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Stefan Berger @ 2015-08-08 1:54 UTC (permalink / raw)
To: linuxppc-dev, nikunj, aik, pmac
Cc: gcwilson, dimitris, latten, lo1, stefanb, Stefan Berger
This patch provides an addtional menu that enables the user to control
certain aspects of the TPM's state.
If a working TPM has been detected, the menu will look like this:
The TPM is enabled, active, does not have an owner but one can be installed.
To configure the TPM, choose one of the following actions:
d. Disable the TPM
v. Deactivate the TPM
p. Prevent installation of an owner
Note: To fully use the TPM it must be enabled and activated.
Press escape to continue boot.
This menu can be access by pressing the 't' key during boot. The menu will not
be shown if no TPM is available.
Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
---
board-qemu/slof/OF.fs | 2 +-
lib/libtpm/tcgbios.c | 33 ++++++++
lib/libtpm/tcgbios.h | 9 +++
lib/libtpm/tpm.code | 20 +++++
lib/libtpm/tpm.in | 2 +
slof/fs/start-up.fs | 9 +++
slof/fs/tpm/tpm-static.fs | 193 ++++++++++++++++++++++++++++++++++++++++++++++
7 files changed, 267 insertions(+), 1 deletion(-)
diff --git a/board-qemu/slof/OF.fs b/board-qemu/slof/OF.fs
index 1306371..cb63455 100644
--- a/board-qemu/slof/OF.fs
+++ b/board-qemu/slof/OF.fs
@@ -180,6 +180,7 @@ CREATE version-str 10 ALLOT
version-str 8 + @ \ end
over - terminal-write drop
" Press 's' to enter Open Firmware." terminal-write drop
+ vtpm-available? IF " Press 't' to enter TPM menu." terminal-write drop THEN
cr cr
temp-ptr disp-size > IF
temp-ptr disp-size MOD
@@ -305,7 +306,6 @@ cr
cr cr
vtpm-add-event-separators
-vtpm-unassert-pp
\ this CATCH is to ensure the code bellow always executes: boot may ABORT!
' start-it CATCH drop
diff --git a/lib/libtpm/tcgbios.c b/lib/libtpm/tcgbios.c
index cabd980..40557d6 100644
--- a/lib/libtpm/tcgbios.c
+++ b/lib/libtpm/tcgbios.c
@@ -1350,3 +1350,36 @@ uint32_t tpm_process_opcode(uint8_t op, bool verbose)
return tpm_process_cfg(&cfg, verbose, &returnCode);
}
+
+int tpm_get_state(void)
+{
+ int state = 0;
+ struct tpm_permanent_flags pf;
+ bool has_owner;
+
+ if (read_permanent_flags((char *)&pf, sizeof(pf)) ||
+ read_has_owner(&has_owner))
+ return ~0;
+
+ if (!pf.flags[PERM_FLAG_IDX_DISABLE])
+ state |= TPM_STATE_ENABLED; /* enabled */
+
+ if (!pf.flags[PERM_FLAG_IDX_DEACTIVATED])
+ state |= TPM_STATE_ACTIVE; /* active */
+
+ if (has_owner) {
+ state |= TPM_STATE_OWNED; /* has owner */
+ } else {
+ if (pf.flags[PERM_FLAG_IDX_OWNERSHIP])
+ state |= TPM_STATE_OWNERINSTALL; /* owner can be installed */
+ }
+
+ dprintf("TPM state flags = 0x%x\n", state);
+
+ return state;
+}
+
+bool tpm_is_working(void)
+{
+ return has_working_tpm();
+}
diff --git a/lib/libtpm/tcgbios.h b/lib/libtpm/tcgbios.h
index e0a7045..902ea1f 100644
--- a/lib/libtpm/tcgbios.h
+++ b/lib/libtpm/tcgbios.h
@@ -31,4 +31,13 @@ uint32_t tpm_add_bcv(uint32_t bootdrv, const uint8_t *addr, uint32_t length);
uint32_t tpm_add_event_separators(void);
uint32_t tpm_process_opcode(uint8_t op, bool verbose);
+/* flags returned by tpm_get_state */
+#define TPM_STATE_ENABLED 1
+#define TPM_STATE_ACTIVE 2
+#define TPM_STATE_OWNED 4
+#define TPM_STATE_OWNERINSTALL 8
+
+int tpm_get_state(void);
+bool tpm_is_working(void);
+
#endif /* TCGBIOS_H */
diff --git a/lib/libtpm/tpm.code b/lib/libtpm/tpm.code
index 7728317..66250d5 100644
--- a/lib/libtpm/tpm.code
+++ b/lib/libtpm/tpm.code
@@ -102,3 +102,23 @@ PRIM(tpm_X2d_process_X2d_opcode)
bool verbose = TOS.u;
TOS.n = tpm_process_opcode(opcode, verbose);
MIRP
+
+/************************************************/
+/* Get state of the TPM in form of flags */
+/* SLOF: tpm-get-state ( -- flags ) */
+/* LIBTPM: state = tpm_get_state() */
+/************************************************/
+PRIM(tpm_X2d_get_X2d_state)
+ PUSH;
+ TOS.n = tpm_get_state();
+MIRP
+
+/************************************************/
+/* Check whether the TPM is working */
+/* SLOF: tpm-is-working ( -- true | false ) */
+/* LIBTPM: bool = tpm_is_working() */
+/************************************************/
+PRIM(tpm_X2d_is_X2d_working)
+ PUSH;
+ TOS.n = tpm_is_working();
+MIRP
diff --git a/lib/libtpm/tpm.in b/lib/libtpm/tpm.in
index e5dbc25..f2cc81e 100644
--- a/lib/libtpm/tpm.in
+++ b/lib/libtpm/tpm.in
@@ -21,3 +21,5 @@ cod(tpm-add-event-separators)
cod(tpm-ipl)
cod(tpm-add-bcv)
cod(tpm-process-opcode)
+cod(tpm-get-state)
+cod(tpm-is-working)
diff --git a/slof/fs/start-up.fs b/slof/fs/start-up.fs
index f1488fa..015e6c1 100644
--- a/slof/fs/start-up.fs
+++ b/slof/fs/start-up.fs
@@ -55,7 +55,15 @@
nvramlog-write-string-cr
;
+: (t-pressed) ( -- )
+ vtpm-menu
+;
+
: (boot?) ( -- )
+ \ before we boot (and after the TPM menu) make sure we give up
+ \ physical presence on the TPM and lock it -> call vtpm-unassert-pp
+ vtpm-unassert-pp
+
of-prompt? not auto-boot? and IF
(boot)
THEN
@@ -147,6 +155,7 @@ TRUE VALUE use-load-watchdog?
key? IF
key CASE
[char] s OF (s-pressed) ENDOF
+ [char] t OF (t-pressed) (boot?) ENDOF
1b OF
(esc-sequence) CASE
1 OF
diff --git a/slof/fs/tpm/tpm-static.fs b/slof/fs/tpm/tpm-static.fs
index d425693..7954be2 100644
--- a/slof/fs/tpm/tpm-static.fs
+++ b/slof/fs/tpm/tpm-static.fs
@@ -43,3 +43,196 @@ false VALUE vtpm-debug?
THEN
THEN
;
+
+1 CONSTANT TPM_ST_ENABLED
+2 CONSTANT TPM_ST_ACTIVE
+4 CONSTANT TPM_ST_OWNED
+8 CONSTANT TPM_ST_OWNERINSTALL
+
+\ helper to test whether the TPM is enabled and active
+: vtpm-enabled-active ( state -- ok? )
+ TPM_ST_ENABLED TPM_ST_ACTIVE OR AND TPM_ST_ENABLED TPM_ST_ACTIVE OR =
+;
+
+\ display the menu for manipulating TPM state; we get
+\ the state of the TPM in form of flags from the C-driver
+\
+\ Some info about the TPM's states:
+\ - enabling/disabling can be done at any time
+\ - activating/deactivating the TPM requires an enabled TPM
+\ - clearing ownership can be done even if the TPM is deactivated and disabled
+\ - allowing/preventing owner installation requires an enabled and active TPM
+\
+: vtpm-menu-show ( -- )
+ tpm-is-working IF
+ ." The TPM is "
+
+ tpm-get-state ( -- flags )
+
+ dup TPM_ST_ENABLED AND TPM_ST_ENABLED <> IF
+ ." disabled"
+ ELSE
+ ." enabled"
+ THEN
+
+ dup TPM_ST_ACTIVE AND TPM_ST_ACTIVE <> IF
+ ." , deactivated"
+ ELSE
+ ." , active"
+ THEN
+
+ dup TPM_ST_OWNED AND TPM_ST_OWNED <> IF
+ ." , does not have an owner "
+ dup TPM_ST_OWNERINSTALL AND TPM_ST_OWNERINSTALL <> IF
+ ." and an owner cannot be installed."
+ ELSE
+ ." but one can be installed."
+ THEN
+ ELSE
+ ." , and has an owner."
+ THEN
+
+ cr cr
+ ." To configure the TPM, choose one of the following actions:"
+ cr cr
+
+ dup TPM_ST_ENABLED AND TPM_ST_ENABLED <> IF
+ ." e. Enable the TPM" cr
+ ELSE
+ ." d. Disable the TPM" cr
+
+ dup TPM_ST_ACTIVE AND TPM_ST_ACTIVE <> IF
+ ." a. Activate the TPM" cr
+ ELSE
+ ." v. Deactivate the TPM" cr
+
+ dup TPM_ST_OWNERINSTALL AND TPM_ST_OWNERINSTALL <> IF
+ ." s. Allow installation of an owner" cr
+ ELSE
+ ." p. Prevent installation of an owner" cr
+ THEN
+ THEN
+
+ THEN
+
+ dup TPM_ST_OWNED AND TPM_ST_OWNED = IF
+ ." c. Clear ownership" cr
+ THEN
+
+ cr
+ \ If the TPM is either disabled or deactivated, show message
+ vtpm-enabled-active 0= IF
+ ." Note: To be able to use all features of the TPM, it must be enabled and active."
+ cr cr
+ THEN
+
+ ELSE
+ ." The TPM is not working correctly." cr
+ THEN
+
+ ." Press escape to continue boot." cr cr
+;
+
+\ wait for keyboard input
+: vtpm-menu-key-get
+ 0 0 DO
+ key? IF
+ key
+ UNLOOP EXIT
+ THEN
+ 100 MS
+ LOOP
+ 1b
+;
+
+\ Send a code to the C-driver to change the state of the vTPM
+: vtpm-process-opcode ( verbose? opcode -- )
+ tpm-process-opcode
+ vtpm-debug? IF
+ ." VTPM: Error code from tpm-process-opcode: " . cr
+ ELSE
+ drop
+ THEN
+;
+
+
+1 CONSTANT PPI_OP_ENABLE
+2 CONSTANT PPI_OP_DISABLE
+3 CONSTANT PPI_OP_ACTIVATE
+4 CONSTANT PPI_OP_DEACTIVATE
+5 CONSTANT PPI_OP_CLEAR
+8 CONSTANT PPI_OP_SETOWNERINSTALL_TRUE
+9 CONSTANT PPI_OP_SETOWNERINSTALL_FALSE
+
+\ if there's a vtpm available, display the menu
+\ wait for keyboard input and have the C-driver
+\ process opcodes we derive from the chosen menu
+\ item
+: vtpm-menu
+ vtpm-available? IF
+ tpm-is-working IF
+ \ vtpm-empty-keybuffer
+ vtpm-menu-show
+ 0 0 DO
+ CASE vtpm-menu-key-get
+ [char] e OF tpm-get-state ( -- flags )
+ TPM_ST_ENABLED AND TPM_ST_ENABLED <> IF
+ 0 PPI_OP_ENABLE vtpm-process-opcode
+ vtpm-menu-show
+ THEN
+ ENDOF
+ [char] d OF tpm-get-state ( -- flags )
+ TPM_ST_ENABLED AND TPM_ST_ENABLED = IF
+ 0 PPI_OP_DISABLE vtpm-process-opcode
+ vtpm-menu-show
+ THEN
+ ENDOF
+ [char] a OF tpm-get-state ( -- flags )
+ TPM_ST_ACTIVE AND TPM_ST_ACTIVE <> IF
+ 0 PPI_OP_ACTIVATE vtpm-process-opcode
+ tpm-get-state
+ TPM_ST_ACTIVE AND TPM_ST_ACTIVE = IF
+ ." The system needs to reboot to activate the TPM."
+ 100 MS \ so the message shows
+ reset-all
+ THEN
+ THEN
+ ENDOF
+ [char] v OF tpm-get-state ( -- flags )
+ TPM_ST_ACTIVE AND TPM_ST_ACTIVE = IF
+ 0 PPI_OP_DEACTIVATE vtpm-process-opcode
+ vtpm-menu-show
+ THEN
+ ENDOF
+ [char] c OF tpm-get-state ( -- flags )
+ TPM_ST_OWNED AND TPM_ST_OWNED = IF
+ 0 PPI_OP_CLEAR vtpm-process-opcode
+ vtpm-menu-show
+ THEN
+ ENDOF
+ [char] s OF tpm-get-state
+ \ The TPM must be enabled and active to allow
+ \ owner installation mods
+ dup vtpm-enabled-active IF
+ TPM_ST_OWNERINSTALL AND TPM_ST_OWNERINSTALL <> IF
+ 0 PPI_OP_SETOWNERINSTALL_TRUE vtpm-process-opcode
+ vtpm-menu-show
+ THEN
+ THEN
+ ENDOF
+ [char] p OF tpm-get-state
+ \ The TPM must be enabled and active to allow
+ \ owner installation mods
+ dup vtpm-enabled-active IF
+ TPM_ST_OWNERINSTALL AND TPM_ST_OWNERINSTALL = IF
+ 0 PPI_OP_SETOWNERINSTALL_FALSE vtpm-process-opcode
+ vtpm-menu-show
+ THEN
+ THEN
+ ENDOF
+ 1b OF UNLOOP EXIT ENDOF
+ ENDCASE
+ LOOP
+ THEN
+ THEN
+;
--
1.9.3
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 10/16] Implement measurements of the master boot record
2015-08-08 1:54 [PATCH 00/16] Add vTPM support to SLOF Stefan Berger
` (8 preceding siblings ...)
2015-08-08 1:54 ` [PATCH 09/16] Add support for a TPM menu to control the state " Stefan Berger
@ 2015-08-08 1:54 ` Stefan Berger
2015-08-08 1:55 ` [PATCH 11/16] Measure the static core root of trust for measurements Stefan Berger
` (5 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Stefan Berger @ 2015-08-08 1:54 UTC (permalink / raw)
To: linuxppc-dev, nikunj, aik, pmac
Cc: gcwilson, dimitris, latten, lo1, stefanb, Stefan Berger
This patch adds support for measuring the boot block of the
MBR and logging the measurement.
Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
---
board-js2x/slof/OF.fs | 2 ++
slof/fs/packages/disk-label.fs | 6 +++++-
slof/fs/tpm/tpm-static.fs | 13 +++++++++++++
3 files changed, 20 insertions(+), 1 deletion(-)
diff --git a/board-js2x/slof/OF.fs b/board-js2x/slof/OF.fs
index 3e37735..8e736c7 100644
--- a/board-js2x/slof/OF.fs
+++ b/board-js2x/slof/OF.fs
@@ -255,6 +255,8 @@ create vpd-bootlist 4 allot
#include <usb/usb-static.fs>
320 cp
#include <scsi-loader.fs>
+\\ need tpm-static for verbs in disk-labels.fs
+#include <tpm/tpm-static.fs>
#include <root.fs>
360 cp
#include "tree.fs"
diff --git a/slof/fs/packages/disk-label.fs b/slof/fs/packages/disk-label.fs
index e034d64..f827d72 100644
--- a/slof/fs/packages/disk-label.fs
+++ b/slof/fs/packages/disk-label.fs
@@ -545,7 +545,11 @@ B9E5 CONSTANT GPT-BASIC-DATA-PARTITION-2
\ load from a bootable partition
: load-from-boot-partition ( addr -- size )
debug-disk-label? IF ." Trying DOS boot " .s cr THEN
- dup load-from-dos-boot-partition ?dup 0 <> IF nip EXIT THEN
+ dup load-from-dos-boot-partition ?dup 0 <> IF
+ nip
+ 80 block 200 vtpm-add-bcv
+ EXIT
+ THEN
debug-disk-label? IF ." Trying CHRP boot " .s cr THEN
1 disk-chrp-boot !
diff --git a/slof/fs/tpm/tpm-static.fs b/slof/fs/tpm/tpm-static.fs
index 7954be2..bc5138a 100644
--- a/slof/fs/tpm/tpm-static.fs
+++ b/slof/fs/tpm/tpm-static.fs
@@ -44,6 +44,19 @@ false VALUE vtpm-debug?
THEN
;
+: vtpm-add-bcv ( boodrv addr length -- )
+ vtpm-available? IF
+ tpm-add-bcv ( -- errcode )
+ vtpm-debug? IF
+ ." VTPM: Error code from tpm-add-bootdevice-ipl: " . cr
+ ELSE
+ drop
+ THEN
+ ELSE
+ 3drop
+ THEN
+;
+
1 CONSTANT TPM_ST_ENABLED
2 CONSTANT TPM_ST_ACTIVE
4 CONSTANT TPM_ST_OWNED
--
1.9.3
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 11/16] Measure the static core root of trust for measurements
2015-08-08 1:54 [PATCH 00/16] Add vTPM support to SLOF Stefan Berger
` (9 preceding siblings ...)
2015-08-08 1:54 ` [PATCH 10/16] Implement measurements of the master boot record Stefan Berger
@ 2015-08-08 1:55 ` Stefan Berger
2015-08-08 1:55 ` [PATCH 12/16] Add TPM firmware API calls hash-all, log-event, hash-log-extend-event Stefan Berger
` (4 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Stefan Berger @ 2015-08-08 1:55 UTC (permalink / raw)
To: linuxppc-dev, nikunj, aik, pmac
Cc: gcwilson, dimitris, latten, lo1, stefanb, Stefan Berger
This patch adds support for measuring the static core root of trust
(S-CRTM) and logging the measurements.
Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
---
board-qemu/slof/vio-vtpm-cdriver.fs | 2 ++
lib/libtpm/tcgbios.c | 37 +++++++++++++++++++++++++++++++++++++
lib/libtpm/tcgbios.h | 1 +
lib/libtpm/tcgbios_int.h | 2 ++
lib/libtpm/tpm.code | 10 ++++++++++
lib/libtpm/tpm.in | 1 +
slof/fs/tpm/tpm-static.fs | 11 +++++++++++
7 files changed, 64 insertions(+)
diff --git a/board-qemu/slof/vio-vtpm-cdriver.fs b/board-qemu/slof/vio-vtpm-cdriver.fs
index 2fc1657..0b4ba41 100644
--- a/board-qemu/slof/vio-vtpm-cdriver.fs
+++ b/board-qemu/slof/vio-vtpm-cdriver.fs
@@ -72,3 +72,5 @@ vtpm-init
\ setup the log
include vtpm-sml.fs
+
+vtpm-measure-scrtm
diff --git a/lib/libtpm/tcgbios.c b/lib/libtpm/tcgbios.c
index 40557d6..adec313 100644
--- a/lib/libtpm/tcgbios.c
+++ b/lib/libtpm/tcgbios.c
@@ -1383,3 +1383,40 @@ bool tpm_is_working(void)
{
return has_working_tpm();
}
+
+uint32_t tpm_measure_scrtm(void)
+{
+ uint32_t rc;
+
+ extern long print_version, print_version_end;
+ extern long _slof_data, _slof_data_end;
+
+ char *version_start = (char *)&print_version;
+ uint32_t version_length = (long)&print_version_end - (long)&print_version;
+
+ char *slof_start = (char *)&_slof_data;
+ uint32_t slof_length = (long)&_slof_data_end - (long)&_slof_data;
+
+ const char *scrtm = "S-CRTM Contents";
+
+ dprintf("Measure S-CRTM Version: addr = %p, length = %d\n",
+ version_start, version_length);
+
+ rc = tpm_add_measurement_to_log(
+ 0, EV_S_CRTM_VERSION,
+ version_start, version_length,
+ (uint8_t *)version_start, version_length);
+
+ if (rc)
+ return rc;
+
+ dprintf("Measure S-CRTM Content: start = %p, length = %d\n",
+ &slof_start, slof_length);
+
+ rc = tpm_add_measurement_to_log(
+ 0, EV_S_CRTM_CONTENTS,
+ scrtm, strlen(scrtm),
+ (uint8_t *)slof_start, slof_length);
+
+ return rc;
+}
diff --git a/lib/libtpm/tcgbios.h b/lib/libtpm/tcgbios.h
index 902ea1f..9f07caf 100644
--- a/lib/libtpm/tcgbios.h
+++ b/lib/libtpm/tcgbios.h
@@ -24,6 +24,7 @@ enum ipltype {
uint32_t tpm_start(void);
uint32_t tpm_unassert_pp(void);
+uint32_t tpm_measure_scrtm(void);
void tpm_set_log_parameters(void *address, unsigned int size);
uint32_t tpm_get_logsize(void);
uint32_t tpm_ipl(enum ipltype bootcd, const uint8_t *addr, uint32_t length);
diff --git a/lib/libtpm/tcgbios_int.h b/lib/libtpm/tcgbios_int.h
index 420049f..bedc2f1 100644
--- a/lib/libtpm/tcgbios_int.h
+++ b/lib/libtpm/tcgbios_int.h
@@ -57,6 +57,8 @@
#define EV_SEPARATOR 4
#define EV_ACTION 5
#define EV_EVENT_TAG 6
+#define EV_S_CRTM_CONTENTS 7
+#define EV_S_CRTM_VERSION 8
#define EV_COMPACT_HASH 12
#define EV_IPL 13
#define EV_IPL_PARTITION_DATA 14
diff --git a/lib/libtpm/tpm.code b/lib/libtpm/tpm.code
index 66250d5..34b9cbc 100644
--- a/lib/libtpm/tpm.code
+++ b/lib/libtpm/tpm.code
@@ -122,3 +122,13 @@ PRIM(tpm_X2d_is_X2d_working)
PUSH;
TOS.n = tpm_is_working();
MIRP
+
+/************************************************/
+/* Have the S-CRTM measured */
+/* SLOF: tpm-measure-scrtm ( -- errcode ) */
+/* LIBTPM: errcode = tpm_measure_scrtm */
+/************************************************/
+PRIM(tpm_X2d_measure_X2d_scrtm)
+ PUSH;
+ TOS.n = tpm_measure_scrtm();
+MIRP
diff --git a/lib/libtpm/tpm.in b/lib/libtpm/tpm.in
index f2cc81e..48c0d75 100644
--- a/lib/libtpm/tpm.in
+++ b/lib/libtpm/tpm.in
@@ -23,3 +23,4 @@ cod(tpm-add-bcv)
cod(tpm-process-opcode)
cod(tpm-get-state)
cod(tpm-is-working)
+cod(tpm-measure-scrtm)
diff --git a/slof/fs/tpm/tpm-static.fs b/slof/fs/tpm/tpm-static.fs
index bc5138a..1bc37c9 100644
--- a/slof/fs/tpm/tpm-static.fs
+++ b/slof/fs/tpm/tpm-static.fs
@@ -33,6 +33,17 @@ false VALUE vtpm-debug?
THEN
;
+: vtpm-measure-scrtm
+ vtpm-available? IF
+ tpm-measure-scrtm ( -- errcode )
+ vtpm-debug? IF
+ ." VTPM: Error code from tpm-measure-scrtm: " . cr
+ ELSE
+ drop
+ THEN
+ THEN
+;
+
: vtpm-unassert-pp
vtpm-available? IF
tpm-unassert-pp ( -- errcode )
--
1.9.3
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 12/16] Add TPM firmware API calls hash-all, log-event, hash-log-extend-event
2015-08-08 1:54 [PATCH 00/16] Add vTPM support to SLOF Stefan Berger
` (10 preceding siblings ...)
2015-08-08 1:55 ` [PATCH 11/16] Measure the static core root of trust for measurements Stefan Berger
@ 2015-08-08 1:55 ` Stefan Berger
2015-08-08 1:55 ` [PATCH 13/16] Add TPM firmware API call get-maximum-cmd-size Stefan Berger
` (3 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Stefan Berger @ 2015-08-08 1:55 UTC (permalink / raw)
To: linuxppc-dev, nikunj, aik, pmac
Cc: gcwilson, dimitris, latten, lo1, stefanb, Stefan Berger
Add the TPM firmware API calls hash-all, log-event, and hash-log-extend-event.
These firmware calls are implemented in /vdevice/vtpm and /ibm,vtpm but the
former merely forwards the calls to the latter. The implementation follows
the Virtual TPM firmware documentation.
These particular 3 API calls enable trusted grub extensions.
Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
---
board-qemu/slof/vio-vtpm-cdriver.fs | 37 +++++++++++++++++++++++++++++++++
board-qemu/slof/vtpm-sml.fs | 22 ++++++++++++++++++++
lib/libtpm/tcgbios.c | 41 +++++++++++++++++++++++++++++++++++++
lib/libtpm/tcgbios.h | 5 +++++
lib/libtpm/tpm.code | 32 +++++++++++++++++++++++++++++
lib/libtpm/tpm.in | 3 +++
slof/fs/tpm/tpm-static.fs | 40 ++++++++++++++++++++++++++++++++++++
7 files changed, 180 insertions(+)
diff --git a/board-qemu/slof/vio-vtpm-cdriver.fs b/board-qemu/slof/vio-vtpm-cdriver.fs
index 0b4ba41..44e5aec 100644
--- a/board-qemu/slof/vio-vtpm-cdriver.fs
+++ b/board-qemu/slof/vio-vtpm-cdriver.fs
@@ -58,6 +58,43 @@ false VALUE vtpm-debug?
r> to my-self
;
+\ forward a call to /ibm,vtpm, which implements the function with the
+\ given name
+: call-forward ( arg ... arg name namelen -- failure? ret ... ret )
+ s" /ibm,vtpm" open-dev ?dup IF
+ dup >r ( arg ... arg name namelen ihandle r:ihandle -- )
+ $call-method ( r:ihandle -- ret ... ret )
+ r> close-dev ( -- ret ... ret )
+ false ( -- false ret ... ret )
+ ELSE
+ true ( -- true )
+ THEN
+;
+
+\ firmware API call
+: hash-all ( data-ptr data-len hash-ptr -- )
+ " hash-all" call-forward IF
+ \ call-forward failed; clean up stack
+ 3drop
+ THEN
+;
+
+\ firmware API call
+: log-event ( event-ptr -- success? )
+ " log-event" call-forward IF
+ drop
+ false
+ THEN
+;
+
+\ firmware API call
+: hash-log-extend-event ( event-ptr -- rc )
+ " hash-log-extend-event" call-forward IF
+ drop
+ 9 \ TPM_FAIL
+ THEN
+;
+
: open ( )
vtpm-debug? IF ." VTPM: vTPM open()" cr THEN
true
diff --git a/board-qemu/slof/vtpm-sml.fs b/board-qemu/slof/vtpm-sml.fs
index 28c30f1..8783bf1 100644
--- a/board-qemu/slof/vtpm-sml.fs
+++ b/board-qemu/slof/vtpm-sml.fs
@@ -52,6 +52,28 @@ log-base LOG-SIZE tpm-set-log-parameters
move
;
+: hash-all ( data-ptr data-len hash-ptr -- )
+ vtpm-debug? IF
+ ." Call to hash-all" cr
+ THEN
+ vtpm-hash-all
+;
+
+: log-event ( event-ptr -- ok? )
+ vtpm-debug? IF
+ ." Call to log-event" cr
+ THEN
+ vtpm-log-event
+;
+
+: hash-log-extend-event ( event-ptr -- rc )
+ vtpm-debug? IF
+ ." Call to hash-log-extend-event" cr
+ THEN
+ vtpm-hash-log-extend-event
+;
+
+
: open true ;
: close ;
diff --git a/lib/libtpm/tcgbios.c b/lib/libtpm/tcgbios.c
index adec313..621c3e8 100644
--- a/lib/libtpm/tcgbios.c
+++ b/lib/libtpm/tcgbios.c
@@ -563,6 +563,20 @@ static uint32_t tpm_extend_ofdt_log(struct pcpes *pcpes,
return 0;
}
+/*
+ * tpm_log_event: Function for interfacing with the firmware API
+ */
+bool tpm_log_event(struct pcpes *pcpes)
+{
+ const char *event = NULL;
+ uint32_t event_length = pcpes->eventdatasize;
+
+ if (event_length)
+ event = (void *)pcpes + offset_of(struct pcpes, event);
+
+ return (tpm_extend_ofdt_log(pcpes, event, event_length) == 0);
+}
+
static uint32_t is_preboot_if_shutdown(void)
{
return tpm_state.if_shutdown;
@@ -656,6 +670,14 @@ static uint32_t tpm_extend(uint8_t *hash, uint32_t pcrindex)
}
/*
+ * tpm_hash_all: Function for interfacing with the firmware API
+ */
+uint32_t tpm_hash_all(const void *data, uint32_t datalen, void *hashptr)
+{
+ return sha1(data, datalen, hashptr);
+}
+
+/*
* Hash then given input data and append the hash to the log
*
* @hashdata: the data to hash
@@ -766,6 +788,25 @@ static uint32_t tpm_add_measurement(uint32_t pcrindex,
}
/*
+ * tpm_hash_log_extend_event: Function for interfacing with then firmware API
+ */
+uint32_t tpm_hash_log_extend_event(struct pcpes *pcpes)
+{
+ const char *event = NULL;
+ uint32_t event_length = pcpes->eventdatasize;
+
+ if (!has_working_tpm())
+ return TCGBIOS_GENERAL_ERROR;
+
+ if (event_length)
+ event = (void *)pcpes + offset_of(struct pcpes, event);
+
+ return hash_log_extend_event(&pcpes->event, pcpes->eventdatasize,
+ pcpes, event, event_length,
+ pcpes->pcrindex);
+}
+
+/*
* Add event separators for PCRs 0 to 7
*/
uint32_t tpm_add_event_separators(void)
diff --git a/lib/libtpm/tcgbios.h b/lib/libtpm/tcgbios.h
index 9f07caf..0dacba2 100644
--- a/lib/libtpm/tcgbios.h
+++ b/lib/libtpm/tcgbios.h
@@ -22,6 +22,8 @@ enum ipltype {
IPL_EL_TORITO_2
};
+struct pcpes;
+
uint32_t tpm_start(void);
uint32_t tpm_unassert_pp(void);
uint32_t tpm_measure_scrtm(void);
@@ -31,6 +33,9 @@ uint32_t tpm_ipl(enum ipltype bootcd, const uint8_t *addr, uint32_t length);
uint32_t tpm_add_bcv(uint32_t bootdrv, const uint8_t *addr, uint32_t length);
uint32_t tpm_add_event_separators(void);
uint32_t tpm_process_opcode(uint8_t op, bool verbose);
+uint32_t tpm_hash_log_extend_event(struct pcpes *pcpes);
+bool tpm_log_event(struct pcpes *pcpes);
+uint32_t tpm_hash_all(const void *data, uint32_t datalen, void *hashptr);
/* flags returned by tpm_get_state */
#define TPM_STATE_ENABLED 1
diff --git a/lib/libtpm/tpm.code b/lib/libtpm/tpm.code
index 34b9cbc..acd3a10 100644
--- a/lib/libtpm/tpm.code
+++ b/lib/libtpm/tpm.code
@@ -132,3 +132,35 @@ PRIM(tpm_X2d_measure_X2d_scrtm)
PUSH;
TOS.n = tpm_measure_scrtm();
MIRP
+
+/************************************************/
+/* Firmware API */
+/* SLOF: tpm-log-event ( eventptr -- ok? ) */
+/* LIBTPM: ok = tpm-log-event */
+/************************************************/
+PRIM(tpm_X2d_log_X2d_event)
+ void *eventptr = TOS.a;
+ TOS.n = tpm_log_event(eventptr);
+MIRP
+
+/********************************************************/
+/* Firmware API */
+/* SLOF: tpm-hash-log-extend-event ( eventptr -- rc ) */
+/* LIBTPM: errcode = tpm-hash-log-extend-event */
+/********************************************************/
+PRIM(tpm_X2d_hash_X2d_log_X2d_extend_X2d_event)
+ void *eventptr = TOS.a;
+ TOS.n = tpm_hash_log_extend_event(eventptr);
+MIRP
+
+/*****************************************************************/
+/* Firmware API */
+/* SLOF: tpm-hash-all ( data-ptr data-len hash-ptr -- errcode) */
+/* LIBTPM: errcode = tpm-hash-all */
+/*****************************************************************/
+PRIM(tpm_X2d_hash_X2d_all)
+ void *hashptr = TOS.a; POP;
+ int datalen = TOS.n; POP;
+ void *dataptr = TOS.a;
+ TOS.n = tpm_hash_all(dataptr, datalen, hashptr);
+MIRP
diff --git a/lib/libtpm/tpm.in b/lib/libtpm/tpm.in
index 48c0d75..ad57631 100644
--- a/lib/libtpm/tpm.in
+++ b/lib/libtpm/tpm.in
@@ -24,3 +24,6 @@ cod(tpm-process-opcode)
cod(tpm-get-state)
cod(tpm-is-working)
cod(tpm-measure-scrtm)
+cod(tpm-log-event)
+cod(tpm-hash-log-extend-event)
+cod(tpm-hash-all)
diff --git a/slof/fs/tpm/tpm-static.fs b/slof/fs/tpm/tpm-static.fs
index 1bc37c9..31d3652 100644
--- a/slof/fs/tpm/tpm-static.fs
+++ b/slof/fs/tpm/tpm-static.fs
@@ -68,6 +68,46 @@ false VALUE vtpm-debug?
THEN
;
+\ firmware API function
+: vtpm-log-event ( event-ptr -- ok? )
+ vtpm-available? IF
+ tpm-log-event
+ vtpm-debug? IF
+ ." VTPM: Returned bool from tpm-log-event: " dup . cr
+ THEN
+ ELSE
+ drop
+ false
+ THEN
+;
+
+\ firmware API function
+: vtpm-hash-log-extend-event ( event-ptr -- rc )
+ vtpm-available? IF
+ tpm-hash-log-extend-event
+ vtpm-debug? IF
+ ." VTPM: Error code from tpm-hash-log-extend-event: " dup . cr
+ THEN
+ ELSE
+ drop
+ 9 \ Tpm-fail failure reason
+ THEN
+;
+
+\ firmware API function
+: vtpm-hash-all ( data-ptr data-len hash-ptr -- )
+ vtpm-available? IF
+ tpm-hash-all ( -- errcode )
+ vtpm-debug? IF
+ ." VTPM: Error code from tpm-hash-all: " . cr
+ ELSE
+ drop
+ THEN
+ ELSE
+ 3drop
+ THEN
+;
+
1 CONSTANT TPM_ST_ENABLED
2 CONSTANT TPM_ST_ACTIVE
4 CONSTANT TPM_ST_OWNED
--
1.9.3
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 13/16] Add TPM firmware API call get-maximum-cmd-size
2015-08-08 1:54 [PATCH 00/16] Add vTPM support to SLOF Stefan Berger
` (11 preceding siblings ...)
2015-08-08 1:55 ` [PATCH 12/16] Add TPM firmware API calls hash-all, log-event, hash-log-extend-event Stefan Berger
@ 2015-08-08 1:55 ` Stefan Berger
2015-08-08 1:55 ` [PATCH 14/16] Add TPM firmware API call pass-through-to-tpm Stefan Berger
` (2 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Stefan Berger @ 2015-08-08 1:55 UTC (permalink / raw)
To: linuxppc-dev, nikunj, aik, pmac
Cc: gcwilson, dimitris, latten, lo1, stefanb, Stefan Berger
This patch adds support for the firmware API call get-maximum-cmd-size.
Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
---
board-qemu/slof/vio-vtpm-cdriver.fs | 7 ++++++
board-qemu/slof/vtpm-sml.fs | 6 +++++
lib/libtpm/tcgbios.c | 44 +++++++++++++++++++++++++++++++++++++
lib/libtpm/tcgbios.h | 1 +
lib/libtpm/tcgbios_int.h | 7 ++++++
lib/libtpm/tpm.code | 10 +++++++++
lib/libtpm/tpm.in | 1 +
slof/fs/tpm/tpm-static.fs | 12 ++++++++++
8 files changed, 88 insertions(+)
diff --git a/board-qemu/slof/vio-vtpm-cdriver.fs b/board-qemu/slof/vio-vtpm-cdriver.fs
index 44e5aec..22fef4f 100644
--- a/board-qemu/slof/vio-vtpm-cdriver.fs
+++ b/board-qemu/slof/vio-vtpm-cdriver.fs
@@ -95,6 +95,13 @@ false VALUE vtpm-debug?
THEN
;
+\ firmware API call
+: get-maximum-cmd-size ( -- maximum-size )
+ " get-maximum-cmd-size" call-forward IF
+ 0
+ THEN
+;
+
: open ( )
vtpm-debug? IF ." VTPM: vTPM open()" cr THEN
true
diff --git a/board-qemu/slof/vtpm-sml.fs b/board-qemu/slof/vtpm-sml.fs
index 8783bf1..e62c20c 100644
--- a/board-qemu/slof/vtpm-sml.fs
+++ b/board-qemu/slof/vtpm-sml.fs
@@ -73,6 +73,12 @@ log-base LOG-SIZE tpm-set-log-parameters
vtpm-hash-log-extend-event
;
+: get-maximum-cmd-size ( -- max-size )
+ vtpm-debug? IF
+ ." Call to get-maximum-cmd-size" cr
+ THEN
+ vtpm-get-maximum-cmd-size
+;
: open true ;
: close ;
diff --git a/lib/libtpm/tcgbios.c b/lib/libtpm/tcgbios.c
index 621c3e8..b306edf 100644
--- a/lib/libtpm/tcgbios.c
+++ b/lib/libtpm/tcgbios.c
@@ -35,6 +35,8 @@
} \
} while (0);
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+
static const uint8_t Startup_ST_CLEAR[] = { 0x00, TPM_ST_CLEAR };
static const uint8_t Startup_ST_STATE[] = { 0x00, TPM_ST_STATE };
@@ -71,6 +73,11 @@ static const uint8_t GetCapability_Durations[] = {
0x00, 0x00, 0x01, 0x20
};
+static const uint8_t GetCapability_BufferSize[] = {
+ 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04,
+ 0x00, 0x00, 0x01, 0x24
+};
+
static uint8_t evt_separator[] = {0xff,0xff,0xff,0xff};
struct tpm_state {
@@ -1461,3 +1468,40 @@ uint32_t tpm_measure_scrtm(void)
return rc;
}
+
+/*
+ * tpm_get_maximum_cmd_size: Function for interfacing with the firmware API
+ *
+ * This function returns the maximum size a TPM command (or response) may have.
+ */
+uint32_t tpm_get_maximum_cmd_size(void)
+{
+ uint32_t rc;
+ uint32_t returnCode;
+ struct tpm_res_getcap_buffersize buffersize;
+ uint32_t result;
+ struct tpm_driver *td = tpm_state.tpm_driver_to_use;
+
+ if (!has_working_tpm())
+ return 0;
+
+ rc = build_and_send_cmd(TPM_ORD_GetCapability,
+ GetCapability_BufferSize,
+ sizeof(GetCapability_BufferSize),
+ (uint8_t *)&buffersize, sizeof(buffersize),
+ &returnCode, TPM_DURATION_TYPE_SHORT);
+
+ if (rc || returnCode)
+ goto err_exit;
+
+ result = MIN(cpu_to_be32(buffersize.buffersize), td->getbuffersize());
+
+ return result;
+
+err_exit:
+ dprintf("TPM malfunctioning (line %d).\n", __LINE__);
+
+ tpm_state.tpm_working = 0;
+
+ return 0;
+}
diff --git a/lib/libtpm/tcgbios.h b/lib/libtpm/tcgbios.h
index 0dacba2..2aa7d20 100644
--- a/lib/libtpm/tcgbios.h
+++ b/lib/libtpm/tcgbios.h
@@ -36,6 +36,7 @@ uint32_t tpm_process_opcode(uint8_t op, bool verbose);
uint32_t tpm_hash_log_extend_event(struct pcpes *pcpes);
bool tpm_log_event(struct pcpes *pcpes);
uint32_t tpm_hash_all(const void *data, uint32_t datalen, void *hashptr);
+uint32_t tpm_get_maximum_cmd_size(void);
/* flags returned by tpm_get_state */
#define TPM_STATE_ENABLED 1
diff --git a/lib/libtpm/tcgbios_int.h b/lib/libtpm/tcgbios_int.h
index bedc2f1..249e205 100644
--- a/lib/libtpm/tcgbios_int.h
+++ b/lib/libtpm/tcgbios_int.h
@@ -177,6 +177,13 @@ struct tpm_res_getcap_durations {
uint32_t durations[TPM_NUM_DURATIONS];
} __attribute__((packed));
+struct tpm_res_getcap_buffersize {
+ TPM_RSP_HEADER
+ uint32_t size;
+ uint32_t buffersize;
+} __attribute__((packed));
+
+
struct tpm_res_sha1start {
TPM_RSP_HEADER
uint32_t max_num_bytes;
diff --git a/lib/libtpm/tpm.code b/lib/libtpm/tpm.code
index acd3a10..5c3d4db 100644
--- a/lib/libtpm/tpm.code
+++ b/lib/libtpm/tpm.code
@@ -164,3 +164,13 @@ PRIM(tpm_X2d_hash_X2d_all)
void *dataptr = TOS.a;
TOS.n = tpm_hash_all(dataptr, datalen, hashptr);
MIRP
+
+/****************************************************/
+/* Firmware API */
+/* SLOF: tpm-get-maximum-cmd-size ( -- max-size) */
+/* LIBTPM: maxsize = tpm_get_maximum_cmd_size() */
+/****************************************************/
+PRIM(tpm_X2d_get_X2d_maximum_X2d_cmd_X2d_size)
+ PUSH;
+ TOS.n = tpm_get_maximum_cmd_size();
+MIRP
diff --git a/lib/libtpm/tpm.in b/lib/libtpm/tpm.in
index ad57631..0923fc0 100644
--- a/lib/libtpm/tpm.in
+++ b/lib/libtpm/tpm.in
@@ -27,3 +27,4 @@ cod(tpm-measure-scrtm)
cod(tpm-log-event)
cod(tpm-hash-log-extend-event)
cod(tpm-hash-all)
+cod(tpm-get-maximum-cmd-size)
diff --git a/slof/fs/tpm/tpm-static.fs b/slof/fs/tpm/tpm-static.fs
index 31d3652..fca0058 100644
--- a/slof/fs/tpm/tpm-static.fs
+++ b/slof/fs/tpm/tpm-static.fs
@@ -108,6 +108,18 @@ false VALUE vtpm-debug?
THEN
;
+\ firmware API function
+: vtpm-get-maximum-cmd-size ( -- max-size )
+ vtpm-available? IF
+ tpm-get-maximum-cmd-size ( -- max-size )
+ vtpm-debug? IF
+ ." VTPM: Return value from tpm-get-maximum-cmd-size: " dup . cr
+ THEN
+ ELSE
+ 0
+ THEN
+;
+
1 CONSTANT TPM_ST_ENABLED
2 CONSTANT TPM_ST_ACTIVE
4 CONSTANT TPM_ST_OWNED
--
1.9.3
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 14/16] Add TPM firmware API call pass-through-to-tpm
2015-08-08 1:54 [PATCH 00/16] Add vTPM support to SLOF Stefan Berger
` (12 preceding siblings ...)
2015-08-08 1:55 ` [PATCH 13/16] Add TPM firmware API call get-maximum-cmd-size Stefan Berger
@ 2015-08-08 1:55 ` Stefan Berger
2015-08-08 1:55 ` [PATCH 15/16] Add TPM firmware API call get-state Stefan Berger
2015-08-08 1:55 ` [PATCH 16/16] Add TPM firmware API call get-failure-reason Stefan Berger
15 siblings, 0 replies; 17+ messages in thread
From: Stefan Berger @ 2015-08-08 1:55 UTC (permalink / raw)
To: linuxppc-dev, nikunj, aik, pmac
Cc: gcwilson, dimitris, latten, lo1, stefanb, Stefan Berger
This patch adds support for the firmware API call pass-through-to-tpm.
Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
---
board-qemu/slof/vio-vtpm-cdriver.fs | 8 ++++++++
board-qemu/slof/vtpm-sml.fs | 7 +++++++
lib/libtpm/tcgbios.c | 28 ++++++++++++++++++++++++++++
lib/libtpm/tcgbios.h | 1 +
lib/libtpm/tpm.code | 11 +++++++++++
lib/libtpm/tpm.in | 1 +
slof/fs/tpm/tpm-static.fs | 13 +++++++++++++
7 files changed, 69 insertions(+)
diff --git a/board-qemu/slof/vio-vtpm-cdriver.fs b/board-qemu/slof/vio-vtpm-cdriver.fs
index 22fef4f..5d55148 100644
--- a/board-qemu/slof/vio-vtpm-cdriver.fs
+++ b/board-qemu/slof/vio-vtpm-cdriver.fs
@@ -96,6 +96,14 @@ false VALUE vtpm-debug?
;
\ firmware API call
+: pass-through-to-tpm ( buf-addr buf-size -- response-size )
+ " pass-through-to-tpm" call-forward IF
+ 2drop
+ 0
+ THEN
+;
+
+\ firmware API call
: get-maximum-cmd-size ( -- maximum-size )
" get-maximum-cmd-size" call-forward IF
0
diff --git a/board-qemu/slof/vtpm-sml.fs b/board-qemu/slof/vtpm-sml.fs
index e62c20c..3ce1ace 100644
--- a/board-qemu/slof/vtpm-sml.fs
+++ b/board-qemu/slof/vtpm-sml.fs
@@ -80,6 +80,13 @@ log-base LOG-SIZE tpm-set-log-parameters
vtpm-get-maximum-cmd-size
;
+: pass-through-to-tpm ( buf-addr cmd-size -- rsp-size )
+ vtpm-debug? IF
+ ." Call to pass-through-to-tpm" cr
+ THEN
+ vtpm-pass-through-to-tpm
+;
+
: open true ;
: close ;
diff --git a/lib/libtpm/tcgbios.c b/lib/libtpm/tcgbios.c
index b306edf..6c991b2 100644
--- a/lib/libtpm/tcgbios.c
+++ b/lib/libtpm/tcgbios.c
@@ -640,6 +640,34 @@ static bool pass_through_to_tpm(unsigned char *req,
}
/*
+ * tpm_pass_through_to_tpm: Function for interfacing with the firmware API
+ *
+ * buf: buffer holding the command; also used for holding the entire response
+ * cmdlen: length of the command in the buffer
+ *
+ * Returns 0 in case of failure, the size of the response otherwise.
+ */
+uint32_t tpm_pass_through_to_tpm(unsigned char *buf, uint32_t cmdlen)
+{
+ uint32_t resplen = PAPR_VTPM_MAX_BUFFER_SIZE;
+
+ /*
+ * API spec: caller must ensure that the buffer is large
+ * enough to receive the full response into
+ * the same buffer where the command is in.
+ * We anticipate the largest possible buffer
+ * the driver supports in 'resplen'.
+ * For duration we use the worst-case timeout 'LONG'
+ * so that any command can be sent and will not time out.
+ */
+ if (pass_through_to_tpm(buf, cmdlen,
+ TPM_DURATION_TYPE_LONG,
+ buf, &resplen))
+ return 0;
+ return resplen;
+}
+
+/*
* Extend a PCR of the TPM with the given hash
*
* @hash: sha1 hash (20 bytes) to extend PCR with
diff --git a/lib/libtpm/tcgbios.h b/lib/libtpm/tcgbios.h
index 2aa7d20..6951af3 100644
--- a/lib/libtpm/tcgbios.h
+++ b/lib/libtpm/tcgbios.h
@@ -37,6 +37,7 @@ uint32_t tpm_hash_log_extend_event(struct pcpes *pcpes);
bool tpm_log_event(struct pcpes *pcpes);
uint32_t tpm_hash_all(const void *data, uint32_t datalen, void *hashptr);
uint32_t tpm_get_maximum_cmd_size(void);
+uint32_t tpm_pass_through_to_tpm(unsigned char *buf, uint32_t cmdlen);
/* flags returned by tpm_get_state */
#define TPM_STATE_ENABLED 1
diff --git a/lib/libtpm/tpm.code b/lib/libtpm/tpm.code
index 5c3d4db..e763f45 100644
--- a/lib/libtpm/tpm.code
+++ b/lib/libtpm/tpm.code
@@ -174,3 +174,14 @@ PRIM(tpm_X2d_get_X2d_maximum_X2d_cmd_X2d_size)
PUSH;
TOS.n = tpm_get_maximum_cmd_size();
MIRP
+
+/*******************************************************************/
+/* Firmware API */
+/* SLOF: tpm-pass-through-to-tpm (buf-addr cmd-size -- rsp-size) */
+/* LIBTPM: respsize = tpm_pass_through_to_tpm(buf, cmdsize) */
+/*******************************************************************/
+PRIM(tpm_X2d_pass_X2d_through_X2d_to_X2d_tpm)
+ int cmdsize = TOS.n; POP;
+ void *buf = TOS.a;
+ TOS.n = tpm_pass_through_to_tpm(buf, cmdsize);
+MIRP
diff --git a/lib/libtpm/tpm.in b/lib/libtpm/tpm.in
index 0923fc0..8b7cde8 100644
--- a/lib/libtpm/tpm.in
+++ b/lib/libtpm/tpm.in
@@ -28,3 +28,4 @@ cod(tpm-log-event)
cod(tpm-hash-log-extend-event)
cod(tpm-hash-all)
cod(tpm-get-maximum-cmd-size)
+cod(tpm-pass-through-to-tpm)
diff --git a/slof/fs/tpm/tpm-static.fs b/slof/fs/tpm/tpm-static.fs
index fca0058..f9583b0 100644
--- a/slof/fs/tpm/tpm-static.fs
+++ b/slof/fs/tpm/tpm-static.fs
@@ -120,6 +120,19 @@ false VALUE vtpm-debug?
THEN
;
+\ firmware API function
+: vtpm-pass-through-to-tpm ( buf-addr cmd-size -- rsp-size )
+ vtpm-available? IF
+ tpm-pass-through-to-tpm ( -- rsp-size )
+ vtpm-debug? IF
+ ." VTPM: Return value from tpm-pass-through-to-tpm: " dup . cr
+ THEN
+ ELSE
+ 2drop
+ 0
+ THEN
+;
+
1 CONSTANT TPM_ST_ENABLED
2 CONSTANT TPM_ST_ACTIVE
4 CONSTANT TPM_ST_OWNED
--
1.9.3
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 15/16] Add TPM firmware API call get-state
2015-08-08 1:54 [PATCH 00/16] Add vTPM support to SLOF Stefan Berger
` (13 preceding siblings ...)
2015-08-08 1:55 ` [PATCH 14/16] Add TPM firmware API call pass-through-to-tpm Stefan Berger
@ 2015-08-08 1:55 ` Stefan Berger
2015-08-08 1:55 ` [PATCH 16/16] Add TPM firmware API call get-failure-reason Stefan Berger
15 siblings, 0 replies; 17+ messages in thread
From: Stefan Berger @ 2015-08-08 1:55 UTC (permalink / raw)
To: linuxppc-dev, nikunj, aik, pmac
Cc: gcwilson, dimitris, latten, lo1, stefanb, Stefan Berger
This patch adds support for the TPM firmware API call get-state.
Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
---
board-qemu/slof/vio-vtpm-cdriver.fs | 8 ++++++++
board-qemu/slof/vtpm-sml.fs | 7 +++++++
lib/libtpm/tcgbios.c | 12 ++++++++++++
lib/libtpm/tcgbios.h | 1 +
lib/libtpm/tpm.code | 10 ++++++++++
lib/libtpm/tpm.in | 1 +
slof/fs/tpm/tpm-static.fs | 12 ++++++++++++
7 files changed, 51 insertions(+)
diff --git a/board-qemu/slof/vio-vtpm-cdriver.fs b/board-qemu/slof/vio-vtpm-cdriver.fs
index 5d55148..474c24c 100644
--- a/board-qemu/slof/vio-vtpm-cdriver.fs
+++ b/board-qemu/slof/vio-vtpm-cdriver.fs
@@ -72,6 +72,14 @@ false VALUE vtpm-debug?
;
\ firmware API call
+: get-state ( -- state )
+ " get-state" call-forward IF
+ \ call-forward failed; return a value
+ 0 \ invalid
+ THEN
+;
+
+\ firmware API call
: hash-all ( data-ptr data-len hash-ptr -- )
" hash-all" call-forward IF
\ call-forward failed; clean up stack
diff --git a/board-qemu/slof/vtpm-sml.fs b/board-qemu/slof/vtpm-sml.fs
index 3ce1ace..449f6fc 100644
--- a/board-qemu/slof/vtpm-sml.fs
+++ b/board-qemu/slof/vtpm-sml.fs
@@ -52,6 +52,13 @@ log-base LOG-SIZE tpm-set-log-parameters
move
;
+: get-state ( -- state )
+ vtpm-debug? IF
+ ." Call to get-state" cr
+ THEN
+ vtpm-driver-get-state
+;
+
: hash-all ( data-ptr data-len hash-ptr -- )
vtpm-debug? IF
." Call to hash-all" cr
diff --git a/lib/libtpm/tcgbios.c b/lib/libtpm/tcgbios.c
index 6c991b2..02ad91a 100644
--- a/lib/libtpm/tcgbios.c
+++ b/lib/libtpm/tcgbios.c
@@ -1533,3 +1533,15 @@ err_exit:
return 0;
}
+
+uint32_t tpm_driver_get_state(void)
+{
+ struct tpm_driver *td = tpm_state.tpm_driver_to_use;
+
+ /* do not check for a working TPM here */
+
+ if (!td)
+ return PFW_DRV_STATE_INVALID;
+
+ return td->getstate();
+}
diff --git a/lib/libtpm/tcgbios.h b/lib/libtpm/tcgbios.h
index 6951af3..05cadb0 100644
--- a/lib/libtpm/tcgbios.h
+++ b/lib/libtpm/tcgbios.h
@@ -38,6 +38,7 @@ bool tpm_log_event(struct pcpes *pcpes);
uint32_t tpm_hash_all(const void *data, uint32_t datalen, void *hashptr);
uint32_t tpm_get_maximum_cmd_size(void);
uint32_t tpm_pass_through_to_tpm(unsigned char *buf, uint32_t cmdlen);
+uint32_t tpm_driver_get_state(void);
/* flags returned by tpm_get_state */
#define TPM_STATE_ENABLED 1
diff --git a/lib/libtpm/tpm.code b/lib/libtpm/tpm.code
index e763f45..574c7eb 100644
--- a/lib/libtpm/tpm.code
+++ b/lib/libtpm/tpm.code
@@ -153,6 +153,16 @@ PRIM(tpm_X2d_hash_X2d_log_X2d_extend_X2d_event)
TOS.n = tpm_hash_log_extend_event(eventptr);
MIRP
+/****************************************************/
+/* Firmware API */
+/* SLOF: tpm-driver-get-state ( -- state) */
+/* LIBTPM: state = tpm_driver_get_state(void) */
+/****************************************************/
+PRIM(tpm_X2d_driver_X2d_get_X2d_state)
+ PUSH;
+ TOS.n = tpm_driver_get_state();
+MIRP
+
/*****************************************************************/
/* Firmware API */
/* SLOF: tpm-hash-all ( data-ptr data-len hash-ptr -- errcode) */
diff --git a/lib/libtpm/tpm.in b/lib/libtpm/tpm.in
index 8b7cde8..3dd78f4 100644
--- a/lib/libtpm/tpm.in
+++ b/lib/libtpm/tpm.in
@@ -29,3 +29,4 @@ cod(tpm-hash-log-extend-event)
cod(tpm-hash-all)
cod(tpm-get-maximum-cmd-size)
cod(tpm-pass-through-to-tpm)
+cod(tpm-driver-get-state)
diff --git a/slof/fs/tpm/tpm-static.fs b/slof/fs/tpm/tpm-static.fs
index f9583b0..31ac815 100644
--- a/slof/fs/tpm/tpm-static.fs
+++ b/slof/fs/tpm/tpm-static.fs
@@ -69,6 +69,18 @@ false VALUE vtpm-debug?
;
\ firmware API function
+: vtpm-driver-get-state ( -- state )
+ vtpm-available? IF
+ tpm-driver-get-state
+ vtpm-debug? IF
+ ." VTPM: Return value from tpm-driver-get-state: " dup . cr
+ THEN
+ ELSE
+ 0 \ invalid
+ THEN
+;
+
+\ firmware API function
: vtpm-log-event ( event-ptr -- ok? )
vtpm-available? IF
tpm-log-event
--
1.9.3
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 16/16] Add TPM firmware API call get-failure-reason
2015-08-08 1:54 [PATCH 00/16] Add vTPM support to SLOF Stefan Berger
` (14 preceding siblings ...)
2015-08-08 1:55 ` [PATCH 15/16] Add TPM firmware API call get-state Stefan Berger
@ 2015-08-08 1:55 ` Stefan Berger
15 siblings, 0 replies; 17+ messages in thread
From: Stefan Berger @ 2015-08-08 1:55 UTC (permalink / raw)
To: linuxppc-dev, nikunj, aik, pmac
Cc: gcwilson, dimitris, latten, lo1, stefanb, Stefan Berger
This patch adds support for the TPM firmware API call get-failure-reason.
Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
---
board-qemu/slof/vio-vtpm-cdriver.fs | 8 ++++++++
board-qemu/slof/vtpm-sml.fs | 7 +++++++
lib/libtpm/tcgbios.c | 16 ++++++++++++++++
lib/libtpm/tcgbios.h | 1 +
lib/libtpm/tpm.code | 10 ++++++++++
lib/libtpm/tpm.in | 1 +
slof/fs/tpm/tpm-static.fs | 12 ++++++++++++
7 files changed, 55 insertions(+)
diff --git a/board-qemu/slof/vio-vtpm-cdriver.fs b/board-qemu/slof/vio-vtpm-cdriver.fs
index 474c24c..18ee85a 100644
--- a/board-qemu/slof/vio-vtpm-cdriver.fs
+++ b/board-qemu/slof/vio-vtpm-cdriver.fs
@@ -80,6 +80,14 @@ false VALUE vtpm-debug?
;
\ firmware API call
+: get-failure-reason ( -- reason )
+ " get-failure-reason" call-forward IF
+ \ call-forward failed; return a value
+ 0 \ invalid
+ THEN
+;
+
+\ firmware API call
: hash-all ( data-ptr data-len hash-ptr -- )
" hash-all" call-forward IF
\ call-forward failed; clean up stack
diff --git a/board-qemu/slof/vtpm-sml.fs b/board-qemu/slof/vtpm-sml.fs
index 449f6fc..a37aa80 100644
--- a/board-qemu/slof/vtpm-sml.fs
+++ b/board-qemu/slof/vtpm-sml.fs
@@ -59,6 +59,13 @@ log-base LOG-SIZE tpm-set-log-parameters
vtpm-driver-get-state
;
+: get-failure-reason ( -- reason )
+ vtpm-debug? IF
+ ." Call to get-failure-reason" cr
+ THEN
+ vtpm-driver-get-failure-reason
+;
+
: hash-all ( data-ptr data-len hash-ptr -- )
vtpm-debug? IF
." Call to hash-all" cr
diff --git a/lib/libtpm/tcgbios.c b/lib/libtpm/tcgbios.c
index 02ad91a..7194141 100644
--- a/lib/libtpm/tcgbios.c
+++ b/lib/libtpm/tcgbios.c
@@ -1545,3 +1545,19 @@ uint32_t tpm_driver_get_state(void)
return td->getstate();
}
+
+/*
+ * tpm_driver_get_failure_reason: Function for interfacing with the firmware
+ * API
+ */
+uint32_t tpm_driver_get_failure_reason(void)
+{
+ struct tpm_driver *td = tpm_state.tpm_driver_to_use;
+
+ /* do not check for a working TPM here */
+
+ if (!td)
+ return PFW_DRV_ERROR_NO_FAILURE;
+
+ return td->geterror();
+}
diff --git a/lib/libtpm/tcgbios.h b/lib/libtpm/tcgbios.h
index 05cadb0..c7fbc29 100644
--- a/lib/libtpm/tcgbios.h
+++ b/lib/libtpm/tcgbios.h
@@ -39,6 +39,7 @@ uint32_t tpm_hash_all(const void *data, uint32_t datalen, void *hashptr);
uint32_t tpm_get_maximum_cmd_size(void);
uint32_t tpm_pass_through_to_tpm(unsigned char *buf, uint32_t cmdlen);
uint32_t tpm_driver_get_state(void);
+uint32_t tpm_driver_get_failure_reason(void);
/* flags returned by tpm_get_state */
#define TPM_STATE_ENABLED 1
diff --git a/lib/libtpm/tpm.code b/lib/libtpm/tpm.code
index 574c7eb..29e3b3d 100644
--- a/lib/libtpm/tpm.code
+++ b/lib/libtpm/tpm.code
@@ -163,6 +163,16 @@ PRIM(tpm_X2d_driver_X2d_get_X2d_state)
TOS.n = tpm_driver_get_state();
MIRP
+/****************************************************/
+/* Firmware API */
+/* SLOF: tpm-driver-get-error ( -- errcode) */
+/* LIBTPM: errcode = tpm_driver_get_error(void) */
+/****************************************************/
+PRIM(tpm_X2d_driver_X2d_get_X2d_failure_X2d_reason)
+ PUSH;
+ TOS.n = tpm_driver_get_failure_reason();
+MIRP
+
/*****************************************************************/
/* Firmware API */
/* SLOF: tpm-hash-all ( data-ptr data-len hash-ptr -- errcode) */
diff --git a/lib/libtpm/tpm.in b/lib/libtpm/tpm.in
index 3dd78f4..5f33d05 100644
--- a/lib/libtpm/tpm.in
+++ b/lib/libtpm/tpm.in
@@ -30,3 +30,4 @@ cod(tpm-hash-all)
cod(tpm-get-maximum-cmd-size)
cod(tpm-pass-through-to-tpm)
cod(tpm-driver-get-state)
+cod(tpm-driver-get-failure-reason)
diff --git a/slof/fs/tpm/tpm-static.fs b/slof/fs/tpm/tpm-static.fs
index 31ac815..cbd92cb 100644
--- a/slof/fs/tpm/tpm-static.fs
+++ b/slof/fs/tpm/tpm-static.fs
@@ -81,6 +81,18 @@ false VALUE vtpm-debug?
;
\ firmware API function
+: vtpm-driver-get-failure-reason ( -- reason )
+ vtpm-available? IF
+ tpm-driver-get-failure-reason
+ vtpm-debug? IF
+ ." VTPM: Return value from tpm-driver-get-failure-reason: " dup . cr
+ THEN
+ ELSE
+ -1 \ no failure
+ THEN
+;
+
+\ firmware API function
: vtpm-log-event ( event-ptr -- ok? )
vtpm-available? IF
tpm-log-event
--
1.9.3
^ permalink raw reply related [flat|nested] 17+ messages in thread
end of thread, other threads:[~2015-08-08 1:55 UTC | newest]
Thread overview: 17+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-08-08 1:54 [PATCH 00/16] Add vTPM support to SLOF Stefan Berger
2015-08-08 1:54 ` [PATCH 01/16] Add a TPM driver implementation Stefan Berger
2015-08-08 1:54 ` [PATCH 02/16] Add TPM initialization support Stefan Berger
2015-08-08 1:54 ` [PATCH 03/16] Add sha1 implementation Stefan Berger
2015-08-08 1:54 ` [PATCH 04/16] Add initial support for logging Stefan Berger
2015-08-08 1:54 ` [PATCH 05/16] Extend internal firmware API Stefan Berger
2015-08-08 1:54 ` [PATCH 06/16] Return value of actual log in sml-get-handover-size Stefan Berger
2015-08-08 1:54 ` [PATCH 07/16] Perform some initial measurements Stefan Berger
2015-08-08 1:54 ` [PATCH 08/16] Add support for controlling the states of the TPM Stefan Berger
2015-08-08 1:54 ` [PATCH 09/16] Add support for a TPM menu to control the state " Stefan Berger
2015-08-08 1:54 ` [PATCH 10/16] Implement measurements of the master boot record Stefan Berger
2015-08-08 1:55 ` [PATCH 11/16] Measure the static core root of trust for measurements Stefan Berger
2015-08-08 1:55 ` [PATCH 12/16] Add TPM firmware API calls hash-all, log-event, hash-log-extend-event Stefan Berger
2015-08-08 1:55 ` [PATCH 13/16] Add TPM firmware API call get-maximum-cmd-size Stefan Berger
2015-08-08 1:55 ` [PATCH 14/16] Add TPM firmware API call pass-through-to-tpm Stefan Berger
2015-08-08 1:55 ` [PATCH 15/16] Add TPM firmware API call get-state Stefan Berger
2015-08-08 1:55 ` [PATCH 16/16] Add TPM firmware API call get-failure-reason Stefan Berger
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).