summaryrefslogtreecommitdiffstats
path: root/tboot/include/tpm.h
diff options
context:
space:
mode:
Diffstat (limited to 'tboot/include/tpm.h')
-rw-r--r--tboot/include/tpm.h521
1 files changed, 521 insertions, 0 deletions
diff --git a/tboot/include/tpm.h b/tboot/include/tpm.h
new file mode 100644
index 0000000..59ebde1
--- /dev/null
+++ b/tboot/include/tpm.h
@@ -0,0 +1,521 @@
+/*
+ * tpm.h: TPM-related support functions
+ *
+ * Copyright (c) 2006-2009, Intel Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of the Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __TPM_H__
+#define __TPM_H__
+
+#include <types.h>
+#include <io.h>
+#include <hash.h>
+#include <integrity.h>
+
+/* un-comment to enable detailed command tracing */
+//#define TPM_TRACE
+
+#define TPM_IF_12 0
+#define TPM_IF_20_FIFO 1
+#define TPM_IF_20_CRB 2
+
+#define TPM_INTERFACE_ID_FIFO_20 0x0
+#define TPM_INTERFACE_ID_CRB 0x1
+#define TPM_INTERFACE_ID_FIFO_13 0xF
+
+#define TPM_LOCALITY_BASE 0xfed40000
+#define TPM_LOCALITY_0 TPM_LOCALITY_BASE
+#define TPM_LOCALITY_1 (TPM_LOCALITY_BASE | 0x1000)
+#define TPM_LOCALITY_2 (TPM_LOCALITY_BASE | 0x2000)
+#define TPM_LOCALITY_3 (TPM_LOCALITY_BASE | 0x3000)
+#define TPM_LOCALITY_4 (TPM_LOCALITY_BASE | 0x4000)
+#define TPM_LOCALITY_BASE_N(n) (TPM_LOCALITY_BASE | ((n) << 12))
+#define TPM_NR_LOCALITIES 5
+#define NR_TPM_LOCALITY_PAGES ((TPM_LOCALITY_1 - TPM_LOCALITY_0) >> PAGE_SHIFT)
+
+#define TPM_LOCALITY_CRB_BASE 0xfed40000
+#define TPM_LOCALITY_CRB_0 TPM_LOCALITY_CRB_BASE
+#define TPM_LOCALITY_CRB_1 (TPM_LOCALITY_CRB_BASE | 0x1000)
+#define TPM_LOCALITY_CRB_2 (TPM_LOCALITY_CRB_BASE | 0x2000)
+#define TPM_LOCALITY_CRB_3 (TPM_LOCALITY_CRB_BASE | 0x3000)
+#define TPM_LOCALITY_CRB_4 (TPM_LOCALITY_CRB_BASE | 0x4000)
+#define TPM_LOCALITY_CRB_BASE_N(n) (TPM_LOCALITY_CRB_BASE | ((n) << 12))
+#define TPM_NR_CRB_LOCALITIES 5
+#define NR_TPM_LOCALITY_CRB_PAGES ((TPM_LOCALITY_CRB_1 - TPM_LOCALITY_CRB_0) >> PAGE_SHIFT)
+/*
+ * Command Header Fields:
+ * 0 1 2 3 4 5 6 7 8 9 10 ...
+ * -------------------------------------------------------------
+ * | TAG | SIZE | COMMAND CODE | other ...
+ * -------------------------------------------------------------
+ *
+ * Response Header Fields:
+ * 0 1 2 3 4 5 6 7 8 9 10 ...
+ * -------------------------------------------------------------
+ * | TAG | SIZE | RETURN CODE | other ...
+ * -------------------------------------------------------------
+ */
+#define CMD_HEAD_SIZE 10
+#define RSP_HEAD_SIZE 10
+#define CMD_SIZE_OFFSET 2
+#define CMD_CC_OFFSET 6
+#define RSP_SIZE_OFFSET 2
+#define RSP_RST_OFFSET 6
+
+/*
+ * The term timeout applies to timings between various states
+ * or transitions within the interface protocol.
+ */
+#define TIMEOUT_UNIT (0x100000 / 330) /* ~1ms, 1 tpm r/w need > 330ns */
+#define TIMEOUT_A 750 /* 750ms */
+#define TIMEOUT_B 2000 /* 2s */
+#define TIMEOUT_C 75000 /* 750ms */
+#define TIMEOUT_D 750 /* 750ms */
+
+typedef struct __packed {
+ uint32_t timeout_a;
+ uint32_t timeout_b;
+ uint32_t timeout_c;
+ uint32_t timeout_d;
+} tpm_timeout_t;
+
+/*
+ * The TCG maintains a registry of all algorithms that have an
+ * assigned algorithm ID. That registry is the definitive list
+ * of algorithms that may be supported by a TPM.
+ */
+#define TPM_ALG_ERROR 0x0000
+#define TPM_ALG_FIRST 0x0001
+#define TPM_ALG_RSA 0x0001
+#define TPM_ALG_DES 0x0002
+#define TPM_ALG__3DES 0x0003
+#define TPM_ALG_SHA 0x0004
+#define TPM_ALG_SHA1 0x0004
+#define TPM_ALG_HMAC 0x0005
+#define TPM_ALG_AES 0x0006
+#define TPM_ALG_MGF1 0x0007
+#define TPM_ALG_KEYEDHASH 0x0008
+#define TPM_ALG_XOR 0x000A
+#define TPM_ALG_SHA256 0x000B
+#define TPM_ALG_SHA384 0x000C
+#define TPM_ALG_SHA512 0x000D
+#define TPM_ALG_WHIRLPOOL512 0x000E
+#define TPM_ALG_NULL 0x0010
+#define TPM_ALG_SM3_256 0x0012
+#define TPM_ALG_SM4 0x0013
+#define TPM_ALG_RSASSA 0x0014
+#define TPM_ALG_RSAES 0x0015
+#define TPM_ALG_RSAPSS 0x0016
+#define TPM_ALG_OAEP 0x0017
+#define TPM_ALG_ECDSA 0x0018
+#define TPM_ALG_ECDH 0x0019
+#define TPM_ALG_ECDAA 0x001A
+#define TPM_ALG_SM2 0x001B
+#define TPM_ALG_ECSCHNORR 0x001C
+#define TPM_ALG_KDF1_SP800_56a 0x0020
+#define TPM_ALG_KDF2 0x0021
+#define TPM_ALG_KDF1_SP800_108 0x0022
+#define TPM_ALG_ECC 0x0023
+#define TPM_ALG_SYMCIPHER 0x0025
+#define TPM_ALG_CTR 0x0040
+#define TPM_ALG_OFB 0x0041
+#define TPM_ALG_CBC 0x0042
+#define TPM_ALG_CFB 0x0043
+#define TPM_ALG_ECB 0x0044
+#define TPM_ALG_LAST 0x0044
+#define TPM_ALG_MAX_NUM (TPM_ALG_LAST - TPM_ALG_ERROR)
+
+
+// move from tpm.c
+
+/*
+ * TPM registers and data structures
+ *
+ * register values are offsets from each locality base
+ * see {read,write}_tpm_reg() for data struct format
+ */
+
+/* TPM_ACCESS_x */
+#define TPM_REG_ACCESS 0x00
+#define TPM_REG_STS 0x18
+
+typedef union {
+ u8 _raw[1]; /* 1-byte reg */
+ struct __packed {
+ u8 tpm_establishment : 1; /* RO, 0=T/OS has been established
+ before */
+ u8 request_use : 1; /* RW, 1=locality is requesting TPM use */
+ u8 pending_request : 1; /* RO, 1=other locality is requesting
+ TPM usage */
+ u8 seize : 1; /* WO, 1=seize locality */
+ u8 been_seized : 1; /* RW, 1=locality seized while active */
+ u8 active_locality : 1; /* RW, 1=locality is active */
+ u8 reserved : 1;
+ u8 tpm_reg_valid_sts : 1; /* RO, 1=other bits are valid */
+ };
+} tpm_reg_access_t;
+
+/* TPM_STS_x */
+
+typedef union {
+ u8 _raw[3]; /* 3-byte reg */
+ struct __packed {
+ u8 reserved1 : 1;
+ u8 response_retry : 1; /* WO, 1=re-send response */
+ u8 self_test_done : 1; /* RO, only for version 2 */
+ u8 expect : 1; /* RO, 1=more data for command expected */
+ u8 data_avail : 1; /* RO, 0=no more data for response */
+ u8 tpm_go : 1; /* WO, 1=execute sent command */
+ u8 command_ready : 1; /* RW, 1=TPM ready to receive new cmd */
+ u8 sts_valid : 1; /* RO, 1=data_avail and expect bits are valid */
+ u16 burst_count : 16; /* RO, # read/writes bytes before wait */
+ };
+} tpm12_reg_sts_t;
+
+typedef union {
+ u8 _raw[4]; /* 4-byte reg */
+ struct __packed {
+ u8 reserved1 : 1;
+ u8 response_retry : 1; /* WO, 1=re-send response */
+ u8 self_test_done : 1; /* RO, only for version 2 */
+ u8 expect : 1; /* RO, 1=more data for command expected */
+ u8 data_avail : 1; /* RO, 0=no more data for response */
+ u8 tpm_go : 1; /* WO, 1=execute sent command */
+ u8 command_ready : 1; /* RW, 1=TPM ready to receive new cmd */
+ u8 sts_valid : 1; /* RO, 1=data_avail and expect bits are
+ valid */
+ u16 burst_count : 16; /* RO, # read/writes bytes before wait */
+ /* version >= 2 */
+ u8 command_cancel : 1;
+ u8 reset_establishment : 1;
+ u8 tpm_family : 2;
+ u8 reserved2 : 4;
+ };
+} tpm20_reg_sts_t;
+
+//-----------------------------------------------------------------------------
+// CRB I/F related definitions, see TCG PC Client Platform TPM Profile (PTP) Specification, Level 00 Revision 00.43
+//-----------------------------------------------------------------------------
+#define TPM_REG_LOC_STATE 0x00
+#define TPM_REG_LOC_CTRL 0x8
+#define TPM_LOCALITY_STS 0x0C
+#define TPM_INTERFACE_ID 0x30
+#define TPM_CONTROL_AREA 0x40
+#define TPM_CRB_CTRL_REQ 0x40
+#define TPM_CRB_CTRL_STS 0x44
+#define TPM_CRB_CTRL_CANCEL 0x48
+#define TPM_CRB_CTRL_START 0x4C
+#define TPM_CRB_CTRL_CMD_SIZE 0x58
+#define TPM_CRB_CTRL_CMD_ADDR 0x5C
+#define TPM_CRB_CTRL_CMD_HADDR 0x60
+#define TPM_CRB_CTRL_RSP_SIZE 0x64
+#define TPM_CRB_CTRL_RSP_ADDR 0x68
+#define TPM_CRB_DATA_BUFFER 0x80
+#define TPMCRBBUF_LEN 0xF80 //3968 Bytes
+
+//#define CTRL_AREA_ADDR (uint32_t) (TPM_CRB_BASE + 0x40)
+//#define DATA_BUF_ADDR (uint32_t) (TPM_CRB_BASE + 0x80)
+
+typedef union {
+ u8 _raw[4]; /* 4-byte reg */
+ struct __packed {
+ u8 tpm_establishment : 1;
+ u8 loc_assigned : 1;
+ u8 active_locality : 3;
+ u8 reserved : 2;
+ u8 tpm_reg_valid_sts : 1; /* RO, 1=other bits are valid */
+ u8 reserved1 :8;
+ u16 reserved2 :16;
+ };
+} tpm_reg_loc_state_t;
+
+typedef union {
+ uint8_t _raw[4];
+ struct __packed {
+ uint32_t requestAccess:1;
+ uint32_t relinquish:1;
+ uint32_t seize:1;
+ uint32_t resetEstablishment:1;
+ uint32_t reserved1:28;
+ };
+} tpm_reg_loc_ctrl_t;
+
+typedef union {
+ uint8_t _raw[4];
+ struct __packed{
+ uint32_t Granted:1;
+ uint32_t BeenSeized:1;
+ uint32_t R:30;
+ };
+} tpm_reg_loc_sts_t;
+
+typedef union {
+ uint8_t _raw[8]; // 8-byte reg
+ struct __packed {
+ uint64_t interface_type:4;
+ uint64_t interface_version:4;
+ uint64_t interface_capability:4;
+ uint64_t interface_selector:4;
+ uint64_t rid:8;
+ uint64_t res:8;
+ uint64_t vid:16;
+ uint64_t did:16;
+ };
+} tpm_crb_interface_id_t;
+
+typedef union {
+ uint8_t _raw[4];
+ struct __packed{
+ uint32_t cmdReady:1;
+ uint32_t goIdle:1;
+ uint32_t Reserved:30;
+ };
+ } tpm_reg_ctrl_request_t;
+
+typedef union {
+ uint8_t _raw[4];
+ struct __packed{
+ uint32_t tpmsts:1;
+ uint32_t tpmidle:1;
+ uint32_t reserved:30;
+ };
+} tpm_reg_ctrl_sts_t;
+
+typedef union {
+ uint8_t _raw[4];
+ struct __packed{
+ uint32_t start;
+ };
+} tpm_reg_ctrl_start_t;
+
+typedef union {
+ uint8_t _raw[4];
+ struct __packed{
+ uint32_t cancel;
+ };
+} tpm_reg_ctrl_cancel_t;
+
+typedef union {
+ uint8_t _raw[8];
+ struct __packed{
+ uint32_t cmdladdr;
+ uint32_t cmdhaddr;
+ };
+} tpm_reg_ctrl_cmdaddr_t;
+
+typedef union {
+ uint8_t _raw[4];
+ struct __packed{
+ uint32_t cmdsize;
+ };
+} tpm_reg_ctrl_cmdsize_t;
+
+typedef union {
+ uint8_t _raw[8];
+ struct __packed{
+ uint64_t rspaddr;
+ };
+} tpm_reg_ctrl_rspaddr_t;
+
+typedef union {
+ uint8_t _raw[4];
+ struct __packed{
+ uint32_t rspsize;
+ };
+} tpm_reg_ctrl_rspsize_t;
+
+typedef union {
+ uint8_t _raw[48];
+ struct __packed {
+ tpm_reg_ctrl_request_t Request;
+ tpm_reg_ctrl_sts_t Status;
+ tpm_reg_ctrl_cancel_t Cancel;
+ tpm_reg_ctrl_start_t Start;
+ uint64_t R;
+ tpm_reg_ctrl_cmdsize_t CmdSize;
+ tpm_reg_ctrl_cmdaddr_t CmdAddr;
+ tpm_reg_ctrl_rspsize_t RspSize;
+ tpm_reg_ctrl_rspaddr_t RspAddr;
+ };
+} tpm_ctrl_area_t;
+
+// END OF CRB I/F
+
+/*
+ * assumes that all reg types follow above format:
+ * - packed
+ * - member named '_raw' which is array whose size is that of data to read
+ */
+#define read_tpm_reg(locality, reg, pdata) _read_tpm_reg(locality, reg, (pdata)->_raw, sizeof(*(pdata)))
+
+#define write_tpm_reg(locality, reg, pdata) _write_tpm_reg(locality, reg, (pdata)->_raw, sizeof(*(pdata)))
+
+static inline void _read_tpm_reg(int locality, u32 reg, u8 *_raw, size_t size)
+{
+ for ( size_t i = 0; i < size; i++ ) _raw[i] = readb((TPM_LOCALITY_BASE_N(locality) | reg) + i);
+}
+
+static inline void _write_tpm_reg(int locality, u32 reg, u8 *_raw, size_t size)
+{
+ for ( size_t i = 0; i < size; i++ ) writeb((TPM_LOCALITY_BASE_N(locality) | reg) + i, _raw[i]);
+}
+
+
+/*
+ * the following inline function reversely copy the bytes from 'in' to
+ * 'out', the byte number to copy is given in count.
+ */
+#define reverse_copy(out, in, count) _reverse_copy((uint8_t *)(out), (uint8_t *)(in), count)
+
+static inline void _reverse_copy(uint8_t *out, uint8_t *in, uint32_t count)
+{
+ for ( uint32_t i = 0; i < count; i++ )
+ out[i] = in[count - i - 1];
+}
+
+/* alg id list supported by Tboot */
+u16 tboot_alg_list[2];
+
+typedef tb_hash_t tpm_digest_t;
+typedef tpm_digest_t tpm_pcr_value_t;
+
+/* only for tpm1.2 to (un)seal */
+tpm_pcr_value_t post_launch_pcr17;
+tpm_pcr_value_t post_launch_pcr18;
+
+struct tpm_if;
+
+struct tpm_if {
+#define TPM12_VER_MAJOR 1
+#define TPM12_VER_MINOR 2
+#define TPM20_VER_MAJOR 2
+#define TPM20_VER_MINOR 0
+ u8 major;
+ u8 minor;
+ u16 family;
+
+ tpm_timeout_t timeout;
+
+ u32 error; /* last reported error */
+ u32 cur_loc;
+
+ u16 banks;
+ u16 algs_banks[TPM_ALG_MAX_NUM];
+ u16 alg_count;
+ u16 algs[TPM_ALG_MAX_NUM];
+
+ /*
+ * Only for version>=2. PCR extend policy.
+ */
+#define TB_EXTPOL_AGILE 0
+#define TB_EXTPOL_EMBEDDED 1
+#define TB_EXTPOL_FIXED 2
+ u8 extpol;
+ u16 cur_alg;
+
+ /* NV index to be used */
+ u32 lcp_own_index;
+ u32 tb_policy_index;
+ u32 tb_err_index;
+ u32 sgx_svn_index;
+
+ bool (*init)(struct tpm_if *ti);
+
+ bool (*pcr_read)(struct tpm_if *ti, u32 locality, u32 pcr, tpm_pcr_value_t *out);
+ bool (*pcr_extend)(struct tpm_if *ti, u32 locality, u32 pcr, const hash_list_t *in);
+ bool (*pcr_reset)(struct tpm_if *ti, u32 locality, u32 pcr);
+ bool (*hash)(struct tpm_if *ti, u32 locality, const u8 *data, u32 data_size, hash_list_t *hl);
+
+ bool (*nv_read)(struct tpm_if *ti, u32 locality, u32 index, u32 offset, u8 *data, u32 *data_size);
+ bool (*nv_write)(struct tpm_if *ti, u32 locality, u32 index, u32 offset, const u8 *data, u32 data_size);
+ bool (*get_nvindex_size)(struct tpm_if *ti, u32 locality, u32 index, u32 *size);
+
+#define TPM_NV_PER_WRITE_STCLEAR (1<<14)
+#define TPM_NV_PER_WRITEDEFINE (1<<13)
+#define TPM_NV_PER_WRITEALL (1<<12)
+#define TPM_NV_PER_AUTHWRITE (1<<2)
+#define TPM_NV_PER_OWNERWRITE (1<<1)
+#define TPM_NV_PER_PPWRITE (1<<0)
+ bool (*get_nvindex_permission)(struct tpm_if *ti, u32 locality, u32 index, u32 *attribute);
+
+ bool (*seal)(struct tpm_if *ti, u32 locality, u32 in_data_size, const u8 *in_data, u32 *sealed_data_size, u8 *sealed_data);
+ bool (*unseal)(struct tpm_if *ti, u32 locality, u32 sealed_data_size, const u8 *sealed_data, u32 *secret_size, u8 *secret);
+ bool (*verify_creation)(struct tpm_if *ti, u32 sealed_data_size, u8 *sealed_data);
+
+ bool (*get_random)(struct tpm_if *ti, u32 locality, u8 *random_data, u32 *data_size);
+
+ uint32_t (*save_state)(struct tpm_if *ti, u32 locality);
+
+ bool (*cap_pcrs)(struct tpm_if *ti, u32 locality, int pcr);
+ bool (*check)(void);
+};
+
+struct tpm_if tpm_12_if;
+struct tpm_if tpm_20_if;
+struct tpm_if *g_tpm;
+uint8_t g_tpm_family;
+
+bool tpm_validate_locality(uint32_t locality);
+bool tpm_validate_locality_crb(uint32_t locality);
+bool release_locality(uint32_t locality);
+bool prepare_tpm(void);
+bool tpm_detect(void);
+void tpm_print(struct tpm_if *ti);
+bool tpm_submit_cmd(u32 locality, u8 *in, u32 in_size, u8 *out, u32 *out_size);
+bool tpm_submit_cmd_crb(u32 locality, u8 *in, u32 in_size, u8 *out, u32 *out_size);
+bool tpm_wait_cmd_ready(uint32_t locality);
+bool tpm_request_locality_crb(uint32_t locality);
+bool tpm_relinquish_locality_crb(uint32_t locality);
+bool txt_is_launched(void);
+bool tpm_workaround_crb(void);
+
+
+//#define TPM_UNIT_TEST 1
+
+#ifdef TPM_UNIT_TEST
+void tpm_unit_test(void);
+#else
+#define tpm_unit_test()
+#endif /* TPM_UNIT_TEST */
+
+
+#endif /* __TPM_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */