1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
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:
*/
|