[coreboot-gerrit] New patch to review for coreboot: tpm2: implement tlcl layer

Martin Roth (martinroth@google.com) gerrit at coreboot.org
Thu Jul 7 18:28:31 CEST 2016


Martin Roth (martinroth at google.com) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/15569

-gerrit

commit 1f0a9855149cb8dcca1c02c4df4b58ee20c2aac3
Author: Vadim Bendebury <vbendeb at chromium.org>
Date:   Tue Apr 5 16:01:57 2016 -0700

    tpm2: implement tlcl layer
    
    This is the first approximation of implementing TPM2 support in
    coreboot. It is very clearly incomplete, some of the larger missing
    pieces being:
    
     - PCR(s) modification
     - protection NVRAM spaces from unauthorized deletion/modification.
     - resume handling
     - cr50 specific factory initialization
    
    The existing TPM1.2 firmware API is being implemented for TPM2. Some
    functions are not required at all, some do not map fully, but the API
    is not yet being changed, many functions are just stubs.
    
    An addition to the API is the new tlcl_define_space() function. It
    abstracts TMP internals allowing the caller to specify the privilege
    level of the space to be defined. Two privilege levels are defined,
    higher for the RO firmware and lower for RW firmware, they determine
    who can write into the spaces.
    
    BRANCH=none
    BUG=chrome-os-partner:50645
    TEST=with the rest of the patches applied Kevin/Gru devices can
         initialize and use firmware and kernel spaces
    
    Change-Id: Ife3301cf161ce38d61f11e4b60f1b43cab9a4eba
    Signed-off-by: Martin Roth <martinroth at chromium.org>
    Original-Commit-Id: bcc8e62604c705798ca106e7995a0960b92b3f35
    Original-Change-Id: Ib340fa8e7db51c10e5080973c16a19b0ebbb61e6
    Original-Signed-off-by: Vadim Bendebury <vbendeb at chromium.org>
    Original-Reviewed-on: https://chromium-review.googlesource.com/353914
    Original-Commit-Ready: Martin Roth <martinroth at chromium.org>
    Original-Reviewed-by: Duncan Laurie <dlaurie at chromium.org>
---
 src/include/tpm_lite/tlcl.h    |  23 +++
 src/lib/Makefile.inc           |   3 +-
 src/lib/tpm2_tlcl.c            | 284 +++++++++++++++++++++++++++++++++++
 src/lib/tpm2_tlcl_structures.h | 325 +++++++++++++++++++++++++++++++++++++++++
 4 files changed, 634 insertions(+), 1 deletion(-)

diff --git a/src/include/tpm_lite/tlcl.h b/src/include/tpm_lite/tlcl.h
index 7724592..c777ff9 100644
--- a/src/include/tpm_lite/tlcl.h
+++ b/src/include/tpm_lite/tlcl.h
@@ -12,6 +12,7 @@
 #ifndef TPM_LITE_TLCL_H_
 #define TPM_LITE_TLCL_H_
 #include <stdint.h>
+#include <types.h>
 
 #include "tss_constants.h"
 
@@ -56,12 +57,34 @@ uint32_t tlcl_self_test_full(void);
  */
 uint32_t tlcl_continue_self_test(void);
 
+#if IS_ENABLED(CONFIG_TPM)
 /**
  * Define a space with permission [perm].  [index] is the index for the space,
  * [size] the usable data size.  The TPM error code is returned.
  */
 uint32_t tlcl_define_space(uint32_t index, uint32_t perm, uint32_t size);
 
+#elif IS_ENABLED(CONFIG_TPM2)
+
+/*
+ * This enum allows to communicate firmware privilege levels to the TPM layer,
+ * which can map them into its own attributes.
+ */
+enum privilege_level {
+	high_privilege = 1,
+	low_privilege
+};
+
+/*
+ * Define a TPM space. Privilege level describes who can modify the space
+ * (high_privilege - the RO code only, low_privilege - ether RO or RW. The
+ * privilege level needs to be dropped below low_privilege before starting the
+ * kernel.
+ */
+uint32_t tlcl_define_space(uint32_t space_index,
+			   enum privilege_level priv_level, size_t space_size);
+#endif
+
 /**
  * Write [length] bytes of [data] to space at [index].  The TPM error code is
  * returned.
diff --git a/src/lib/Makefile.inc b/src/lib/Makefile.inc
index 1028917..bc38f67 100644
--- a/src/lib/Makefile.inc
+++ b/src/lib/Makefile.inc
@@ -54,7 +54,8 @@ verstage-$(CONFIG_COMMON_CBFS_SPI_WRAPPER) += cbfs_spi.c
 ifeq ($(MOCK_TPM),1)
 libverstage-y += mocked_tlcl.c
 else
-libverstage-y += tlcl.c
+libverstage-$(CONFIG_TPM) += tlcl.c
+libverstage-$(CONFIG_TPM2) += tpm2_tlcl.c
 endif
 
 verstage-$(CONFIG_GENERIC_UDELAY) += timer.c
diff --git a/src/lib/tpm2_tlcl.c b/src/lib/tpm2_tlcl.c
new file mode 100644
index 0000000..c352a2c
--- /dev/null
+++ b/src/lib/tpm2_tlcl.c
@@ -0,0 +1,284 @@
+/*
+ * Copyright 2016 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include <console/console.h>
+#include <endian.h>
+#include <lib/tpm2_tlcl_structures.h>
+#include <string.h>
+#include <tpm.h>
+#include <vb2_api.h>
+
+#include "tpm2_marshaling.h"
+
+/*
+ * This file provides interface between firmware and TPM2 device. The TPM1.2
+ * API was copied as is and relevant functions modified to comply with the
+ * TPM2 specification.
+ */
+
+static void *tpm_process_command(TPM_CC command, void *command_body)
+{
+	size_t out_size, in_size;
+	/* Command/response buffer. */
+	static uint8_t cr_buffer[TPM_BUFFER_SIZE];
+
+	out_size = tpm_marshal_command(command, command_body,
+				       cr_buffer, sizeof(cr_buffer));
+	if (out_size < 0) {
+		printk(BIOS_ERR, "command %#x, cr size %zd\n",
+		       command, out_size);
+		return NULL;
+	}
+
+	in_size = sizeof(cr_buffer);
+	if (tis_sendrecv(cr_buffer, out_size,
+			 cr_buffer, &in_size)) {
+		printk(BIOS_ERR, "tpm transaction failed\n");
+		return NULL;
+	}
+
+	return tpm_unmarshal_response(command, cr_buffer, in_size);
+}
+
+
+uint32_t tlcl_get_permanent_flags(TPM_PERMANENT_FLAGS *pflags)
+{
+	printk(BIOS_INFO, "%s:%s:%d\n", __FILE__, __func__, __LINE__);
+	return TPM_SUCCESS;
+}
+
+uint32_t tlcl_resume(void)
+{
+	printk(BIOS_INFO, "%s:%s:%d\n", __FILE__, __func__, __LINE__);
+	return TPM_SUCCESS;
+}
+
+uint32_t tlcl_assert_physical_presence(void)
+{
+	/*
+	 * Nothing to do on TPM2 for this, use platform hierarchy availability
+	 * instead.
+	 */
+	return TPM_SUCCESS;
+}
+
+uint32_t tlcl_extend(int pcr_num, const uint8_t *in_digest,
+		     uint8_t *out_digest)
+{
+	printk(BIOS_INFO, "%s:%s:%d\n", __FILE__, __func__, __LINE__);
+	return TPM_SUCCESS;
+}
+
+uint32_t tlcl_finalize_physical_presence(void)
+{
+	/* Nothing needs to be done with tpm2. */
+	printk(BIOS_INFO, "%s:%s:%d\n", __FILE__, __func__, __LINE__);
+	return TPM_SUCCESS;
+}
+
+uint32_t tlcl_force_clear(void)
+{
+	printk(BIOS_INFO, "%s:%s:%d\n", __FILE__, __func__, __LINE__);
+	return TPM_SUCCESS;
+}
+
+uint32_t tlcl_get_flags(uint8_t *disable, uint8_t *deactivated,
+			uint8_t *nvlocked)
+{
+	/*
+	 * TPM2 does not map directly into these flags TPM1.2 based firmware
+	 * expects to be able to retrieve.
+	 *
+	 * In any case, if any of these conditions are present, the following
+	 * firmware flow would be interrupted and will have a chance to report
+	 * an error. Let's just hardcode an "All OK" response for now.
+	 */
+
+	if (disable)
+		*disable = 0;
+
+	if (nvlocked)
+		*nvlocked = 1;
+
+	if (deactivated)
+		*deactivated = 0;
+
+	return TPM_SUCCESS;
+}
+
+uint32_t tlcl_lib_init(void)
+{
+	/*
+	 * This function is called directly by vboot, uses vboot return
+	 * types.
+	 */
+	if (tis_init())
+		return VB2_ERROR_UNKNOWN;
+	if (tis_open())
+		return VB2_ERROR_UNKNOWN;
+	return VB2_SUCCESS;
+}
+
+uint32_t tlcl_physical_presence_cmd_enable(void)
+{
+	printk(BIOS_INFO, "%s:%s:%d\n", __FILE__, __func__, __LINE__);
+	return TPM_SUCCESS;
+}
+
+uint32_t tlcl_read(uint32_t index, void *data, uint32_t length)
+{
+	struct tpm2_nv_read_cmd nv_readc;
+	struct tpm2_response *response;
+
+	memset(&nv_readc, 0, sizeof(nv_readc));
+
+	nv_readc.nvIndex = HR_NV_INDEX + index;
+	nv_readc.size = length;
+
+	response = tpm_process_command(TPM2_NV_Read, &nv_readc);
+
+	/* Need to map tpm error codes into internal values. */
+	if (!response)
+		return TPM_E_READ_FAILURE;
+
+	printk(BIOS_INFO, "%s:%d index %#x return code %x\n",
+	       __FILE__, __LINE__, index, response->hdr.tpm_code);
+	switch (response->hdr.tpm_code) {
+	case 0:
+		break;
+
+	case 0x28b:
+		return TPM_E_BADINDEX;
+
+	default:
+		return TPM_E_READ_FAILURE;
+	}
+
+	if (length > response->nvr.buffer.t.size)
+		return TPM_E_RESPONSE_TOO_LARGE;
+
+	if (length < response->nvr.buffer.t.size)
+		return TPM_E_READ_EMPTY;
+
+	memcpy(data, response->nvr.buffer.t.buffer, length);
+
+	return TPM_SUCCESS;
+}
+
+uint32_t tlcl_self_test_full(void)
+{
+	struct tpm2_self_test st;
+	struct tpm2_response *response;
+
+	st.yes_no = 1;
+
+	response = tpm_process_command(TPM2_SelfTest, &st);
+	printk(BIOS_INFO, "%s: response is %x\n",
+	       __func__, response ? response->hdr.tpm_code : -1);
+	return TPM_SUCCESS;
+}
+
+uint32_t tlcl_set_deactivated(uint8_t flag)
+{
+	printk(BIOS_INFO, "%s:%s:%d\n", __FILE__, __func__, __LINE__);
+	return TPM_SUCCESS;
+}
+
+uint32_t tlcl_set_enable(void)
+{
+	printk(BIOS_INFO, "%s:%s:%d\n", __FILE__, __func__, __LINE__);
+	return TPM_SUCCESS;
+}
+
+uint32_t tlcl_set_global_lock(void)
+{
+	/*
+	 * This is where the locking of the RO NVram index is supposed to
+	 * happen. The most likely way to achieve it is to extend PCR used for
+	 * policy when defining this space.
+	 */
+	printk(BIOS_INFO, "%s:%s:%d\n", __FILE__, __func__, __LINE__);
+	return TPM_SUCCESS;
+}
+uint32_t tlcl_set_nv_locked(void)
+{
+	printk(BIOS_INFO, "%s:%s:%d\n", __FILE__, __func__, __LINE__);
+	return TPM_SUCCESS;
+}
+
+uint32_t tlcl_startup(void)
+{
+	struct tpm2_startup startup;
+	struct tpm2_response *response;
+
+	startup.startup_type = TPM_SU_CLEAR;
+	response = tpm_process_command(TPM2_Startup, &startup);
+	if (response && response->hdr.tpm_code &&
+	    (response->hdr.tpm_code != TPM_RC_INITIALIZE)) {
+		printk(BIOS_INFO, "startup return code is %x\n",
+		       response->hdr.tpm_code);
+		return TPM_E_IOERROR;
+	}
+	return TPM_SUCCESS;
+}
+
+uint32_t tlcl_write(uint32_t index, const void *data, uint32_t length)
+{
+	struct tpm2_nv_write_cmd nv_writec;
+	struct tpm2_response *response;
+
+	memset(&nv_writec, 0, sizeof(nv_writec));
+
+	nv_writec.nvIndex = HR_NV_INDEX + index;
+	nv_writec.data.t.size = length;
+	nv_writec.data.t.buffer = data;
+
+	response = tpm_process_command(TPM2_NV_Write, &nv_writec);
+
+	/* Need to map tpm error codes into internal values. */
+	if (!response)
+		return TPM_E_WRITE_FAILURE;
+
+	printk(BIOS_INFO, "%s:%d return code %x\n", __func__, __LINE__,
+	       response->hdr.tpm_code);
+
+	return TPM_SUCCESS;
+}
+
+uint32_t tlcl_define_space(uint32_t space_index,
+			   enum privilege_level priv_level, size_t space_size)
+{
+	struct tpm2_nv_define_space_cmd nvds_cmd;
+	struct tpm2_response *response;
+
+	/* Prepare the define space command structure. */
+	memset(&nvds_cmd, 0, sizeof(nvds_cmd));
+
+	nvds_cmd.publicInfo.dataSize = space_size;
+	nvds_cmd.publicInfo.nvIndex = HR_NV_INDEX + space_index;
+	nvds_cmd.publicInfo.nameAlg = TPM_ALG_SHA256;
+
+	/* Attributes common for all privilege levels. */
+	nvds_cmd.publicInfo.attributes.TPMA_NV_PPWRITE = 1;
+	nvds_cmd.publicInfo.attributes.TPMA_NV_AUTHREAD = 1;
+	nvds_cmd.publicInfo.attributes.TPMA_NV_PPREAD = 1;
+	nvds_cmd.publicInfo.attributes.TPMA_NV_PLATFORMCREATE = 1;
+
+	if (priv_level == high_privilege) {
+		nvds_cmd.publicInfo.attributes.TPMA_NV_WRITE_STCLEAR = 1;
+		nvds_cmd.publicInfo.attributes.TPMA_NV_POLICY_DELETE = 1;
+	}
+
+	response = tpm_process_command(TPM2_NV_DefineSpace, &nvds_cmd);
+	printk(BIOS_INFO, "%s: response is %x\n",
+	       __func__, response ? response->hdr.tpm_code : -1);
+
+	if (!response)
+		return TPM_E_NO_DEVICE;
+
+	return response->hdr.tpm_code ? TPM_E_INTERNAL_INCONSISTENCY :
+		TPM_SUCCESS;
+}
diff --git a/src/lib/tpm2_tlcl_structures.h b/src/lib/tpm2_tlcl_structures.h
new file mode 100644
index 0000000..fad9c0d
--- /dev/null
+++ b/src/lib/tpm2_tlcl_structures.h
@@ -0,0 +1,325 @@
+/*
+ * Copyright 2016 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef __SRC_LIB_TPM2_TLCL_STRUCTURES_H
+#define __SRC_LIB_TPM2_TLCL_STRUCTURES_H
+
+/*
+ * This file includes a subset of definitions of TPM protocol version 2.x
+ * constants and structures needed for functions used in coreboot.
+ */
+#include <stdint.h>
+#include <tpm_lite/tlcl.h>
+#include <types.h>
+
+/* This should be plenty for what firmware needs. */
+#define TPM_BUFFER_SIZE 256
+
+/* Basic TPM2 types. */
+typedef uint16_t TPM_SU;
+typedef uint16_t TPM_ALG_ID;
+typedef uint32_t TPM_CC;
+typedef uint32_t TPM_HANDLE;
+typedef uint32_t TPM_RC;
+typedef uint8_t TPMI_YES_NO;
+typedef TPM_HANDLE TPMI_RH_NV_INDEX;
+typedef TPM_HANDLE TPMI_RH_PROVISION;
+typedef TPM_HANDLE TPMI_SH_AUTH_SESSION;
+typedef TPM_HANDLE TPM_RH;
+typedef TPM_ALG_ID TPMI_ALG_HASH;
+
+/* Some hardcoded algorithm values. */
+#define TPM_ALG_HMAC   ((TPM_ALG_ID)0x0005)
+#define TPM_ALG_NULL   ((TPM_ALG_ID)0x0010)
+#define TPM_ALG_SHA1   ((TPM_ALG_ID)0x0004)
+#define TPM_ALG_SHA256 ((TPM_ALG_ID)0x000b)
+
+/* Some hardcoded hierarchies. */
+#define TPM_RH_NULL         0x40000007
+#define TPM_RS_PW           0x40000009
+#define TPM_RH_PLATFORM     0x4000000C
+
+typedef struct {
+	uint16_t      size;
+	uint8_t       *buffer;
+} TPM2B;
+
+typedef union {
+	uint8_t  body[512];
+} TPMU_HA;
+
+typedef struct {
+	TPMI_ALG_HASH  hashAlg;
+	TPMU_HA        digest;
+} TPMT_HA;
+
+typedef union {
+	TPMT_HA     digest;
+	TPM_HANDLE  handle;
+} TPMU_NAME;
+
+typedef union {
+	struct {
+		uint16_t  size;
+		uint8_t   name[sizeof(TPMU_NAME)];
+	} t;
+	TPM2B b;
+} TPM2B_NAME;
+
+/* Relevant TPM Command's structures. */
+/* Common command/response header. */
+struct tpm_header {
+	uint16_t tpm_tag;
+	uint32_t tpm_size;
+	TPM_CC tpm_code;
+} __attribute__((packed));
+
+/* TPM command codes. */
+#define TPM2_NV_DefineSpace ((TPM_CC)0x0000012A)
+#define TPM2_NV_Write       ((TPM_CC)0x00000137)
+#define TPM2_SelfTest       ((TPM_CC)0x00000143)
+#define TPM2_Startup        ((TPM_CC)0x00000144)
+#define TPM2_NV_Read        ((TPM_CC)0x0000014E)
+#define TPM2_GetCapability  ((TPM_CC)0x0000017A)
+
+/* Startup values. */
+#define TPM_SU_CLEAR 0
+#define TPM_SU_STATE 1
+
+#define TPM_HT_NV_INDEX        0x01
+#define TPM_HT_HMAC_SESSION    0x02
+#define TPM_HT_POLICY_SESSION  0x03
+
+#define HR_SHIFT               24
+#define HR_PCR                (TPM_HT_PCR <<  HR_SHIFT)
+#define HR_HMAC_SESSION       (TPM_HT_HMAC_SESSION <<  HR_SHIFT)
+#define HR_POLICY_SESSION     (TPM_HT_POLICY_SESSION <<  HR_SHIFT)
+#define HR_TRANSIENT          (TPM_HT_TRANSIENT <<  HR_SHIFT)
+#define HR_PERSISTENT         (TPM_HT_PERSISTENT <<  HR_SHIFT)
+#define HR_NV_INDEX           (TPM_HT_NV_INDEX <<  HR_SHIFT)
+#define HR_PERMANENT          (TPM_HT_PERMANENT <<  HR_SHIFT)
+#define PCR_FIRST             (HR_PCR + 0)
+#define PCR_LAST              (PCR_FIRST + IMPLEMENTATION_PCR-1)
+#define HMAC_SESSION_FIRST    (HR_HMAC_SESSION + 0)
+#define HMAC_SESSION_LAST     (HMAC_SESSION_FIRST+MAX_ACTIVE_SESSIONS-1)
+#define LOADED_SESSION_FIRST  HMAC_SESSION_FIRST
+#define LOADED_SESSION_LAST   HMAC_SESSION_LAST
+#define POLICY_SESSION_FIRST  (HR_POLICY_SESSION + 0)
+#define POLICY_SESSION_LAST   (POLICY_SESSION_FIRST + MAX_ACTIVE_SESSIONS-1)
+#define TRANSIENT_FIRST       (HR_TRANSIENT + 0)
+#define ACTIVE_SESSION_FIRST  POLICY_SESSION_FIRST
+#define ACTIVE_SESSION_LAST   POLICY_SESSION_LAST
+#define TRANSIENT_LAST        (TRANSIENT_FIRST+MAX_LOADED_OBJECTS-1)
+#define PERSISTENT_FIRST      (HR_PERSISTENT + 0)
+#define PERSISTENT_LAST       (PERSISTENT_FIRST + 0x00FFFFFF)
+#define PLATFORM_PERSISTENT   (PERSISTENT_FIRST + 0x00800000)
+#define NV_INDEX_FIRST        (HR_NV_INDEX + 0)
+#define NV_INDEX_LAST         (NV_INDEX_FIRST + 0x00FFFFFF)
+#define PERMANENT_FIRST       TPM_RH_FIRST
+#define PERMANENT_LAST        TPM_RH_LAST
+
+/* Tpm2 command tags. */
+#define TPM_ST_NO_SESSIONS 0x8001
+#define TPM_ST_SESSIONS    0x8002
+
+#define RC_VER1                                         0x100
+#define TPM_RC_INITIALIZE         ((TPM_RC)(RC_VER1 + 0x000))
+
+/* TPM command structures. */
+
+struct tpm2_startup {
+	TPM_SU  startup_type;
+};
+
+/* Various TPM capability types to use when querying the device. */
+typedef uint32_t TPM_CAP;
+#define TPM_CAP_TPM_PROPERTIES   ((TPM_CAP)0x00000006)
+
+typedef TPM_HANDLE TPMI_RH_NV_AUTH;
+typedef TPM_HANDLE TPMI_RH_NV_INDEX;
+
+/* TPM Property capability constants. */
+typedef uint32_t TPM_PT;
+#define PT_GROUP                                   0x00000100
+#define PT_VAR                                 (PT_GROUP * 2)
+#define TPM_PT_PERMANENT               ((TPM_PT)(PT_VAR + 0))
+
+/* Structures of payloads of various TPM2 commands. */
+struct tpm2_get_capability {
+	TPM_CAP capability;
+	uint32_t property;
+	uint32_t propertyCount;
+};
+
+/* get_capability response when PT_PERMANENT is requested. */
+typedef struct {
+	uint32_t ownerAuthSet       : 1;
+	uint32_t endorsementAuthSet : 1;
+	uint32_t lockoutAuthSet     : 1;
+	uint32_t reserved3_7        : 5;
+	uint32_t disableClear       : 1;
+	uint32_t inLockout          : 1;
+	uint32_t tpmGeneratedEPS    : 1;
+	uint32_t reserved11_31      : 21;
+} TPMA_PERMANENT;
+
+typedef struct {
+	uint32_t TPMA_NV_PPWRITE        : 1;
+	uint32_t TPMA_NV_OWNERWRITE     : 1;
+	uint32_t TPMA_NV_AUTHWRITE      : 1;
+	uint32_t TPMA_NV_POLICYWRITE    : 1;
+	uint32_t TPMA_NV_COUNTER        : 1;
+	uint32_t TPMA_NV_BITS           : 1;
+	uint32_t TPMA_NV_EXTEND         : 1;
+	uint32_t reserved7_9            : 3;
+	uint32_t TPMA_NV_POLICY_DELETE  : 1;
+	uint32_t TPMA_NV_WRITELOCKED    : 1;
+	uint32_t TPMA_NV_WRITEALL       : 1;
+	uint32_t TPMA_NV_WRITEDEFINE    : 1;
+	uint32_t TPMA_NV_WRITE_STCLEAR  : 1;
+	uint32_t TPMA_NV_GLOBALLOCK     : 1;
+	uint32_t TPMA_NV_PPREAD         : 1;
+	uint32_t TPMA_NV_OWNERREAD      : 1;
+	uint32_t TPMA_NV_AUTHREAD       : 1;
+	uint32_t TPMA_NV_POLICYREAD     : 1;
+	uint32_t reserved20_24          : 5;
+	uint32_t TPMA_NV_NO_DA          : 1;
+	uint32_t TPMA_NV_ORDERLY        : 1;
+	uint32_t TPMA_NV_CLEAR_STCLEAR  : 1;
+	uint32_t TPMA_NV_READLOCKED     : 1;
+	uint32_t TPMA_NV_WRITTEN        : 1;
+	uint32_t TPMA_NV_PLATFORMCREATE : 1;
+	uint32_t TPMA_NV_READ_STCLEAR   : 1;
+} TPMA_NV;
+
+typedef union {
+	struct {
+		uint16_t  size;
+		uint8_t   buffer[sizeof(TPMU_HA)];
+	} t;
+	TPM2B b;
+} TPM2B_DIGEST;
+
+typedef TPM2B_DIGEST TPM2B_AUTH;
+typedef TPM2B_DIGEST TPM2B_NONCE;
+
+typedef struct {
+	TPM_PT  property;
+	uint32_t  value;
+} TPMS_TAGGED_PROPERTY;
+
+#define MAX_CAP_DATA (TPM_BUFFER_SIZE - sizeof(struct tpm_header) - \
+		      sizeof(TPMI_YES_NO) - sizeof(TPM_CAP) - sizeof(uint32_t))
+#define MAX_TPM_PROPERTIES  (MAX_CAP_DATA/sizeof(TPMS_TAGGED_PROPERTY))
+
+/* Somewhat arbitrary, leave enough room for command wrappers. */
+#define MAX_NV_BUFFER_SIZE (TPM_BUFFER_SIZE - sizeof(struct tpm_header) - 50)
+
+typedef struct {
+	uint32_t              count;
+	TPMS_TAGGED_PROPERTY  tpmProperty[MAX_TPM_PROPERTIES];
+} TPML_TAGGED_TPM_PROPERTY;
+
+typedef union {
+	TPML_TAGGED_TPM_PROPERTY  tpmProperties;
+} TPMU_CAPABILITIES;
+
+typedef struct {
+	TPM_CAP            capability;
+	TPMU_CAPABILITIES  data;
+} TPMS_CAPABILITY_DATA;
+
+struct get_cap_response {
+	TPMI_YES_NO more_data;
+	TPMS_CAPABILITY_DATA cd;
+};
+
+typedef struct {
+	TPMI_RH_NV_INDEX  nvIndex;
+	TPMI_ALG_HASH     nameAlg;
+	TPMA_NV           attributes;
+	TPM2B_DIGEST      authPolicy;
+	uint16_t          dataSize;
+} TPMS_NV_PUBLIC;
+
+typedef union {
+	struct {
+		uint16_t        size;
+		TPMS_NV_PUBLIC  nvPublic;
+	} t;
+	TPM2B b;
+} TPM2B_NV_PUBLIC;
+
+typedef union {
+	struct {
+		uint16_t  size;
+		const uint8_t   *buffer;
+	} t;
+	TPM2B b;
+} TPM2B_MAX_NV_BUFFER;
+
+struct nv_read_response {
+	uint32_t params_size;
+	TPM2B_MAX_NV_BUFFER buffer;
+};
+
+struct tpm2_session_attrs {
+	uint8_t continueSession : 1;
+	uint8_t auditExclusive  : 1;
+	uint8_t auditReset      : 1;
+	uint8_t reserved3_4     : 2;
+	uint8_t decrypt         : 1;
+	uint8_t encrypt         : 1;
+	uint8_t audit           : 1;
+};
+
+/*
+ * TPM session header for commands requiring session information. Also
+ * included in the responses to those commands.
+ */
+struct tpm2_session_header {
+	uint32_t session_handle;
+	uint16_t nonce_size;
+	uint8_t *nonce;
+	union {
+		struct tpm2_session_attrs session_attr_bits;
+		uint8_t session_attrs;
+	}  __attribute__((packed));
+	uint16_t auth_size;
+	uint8_t *auth;
+};
+
+struct tpm2_response {
+	struct tpm_header hdr;
+	union {
+		struct get_cap_response gc;
+		struct nv_read_response nvr;
+		struct tpm2_session_header def_space;
+	};
+};
+
+struct tpm2_nv_define_space_cmd {
+	TPM2B_AUTH auth;
+	TPMS_NV_PUBLIC publicInfo;
+};
+
+struct tpm2_nv_write_cmd {
+	TPMI_RH_NV_INDEX nvIndex;
+	TPM2B_MAX_NV_BUFFER data;
+	uint16_t offset;
+};
+
+struct tpm2_self_test {
+	TPMI_YES_NO yes_no;
+};
+
+struct tpm2_nv_read_cmd {
+	TPMI_RH_NV_INDEX nvIndex;
+	uint16_t size;
+	uint16_t offset;
+};
+
+#endif // __SRC_LIB_TPM2_TLCL_STRUCTURES_H



More information about the coreboot-gerrit mailing list