summaryrefslogtreecommitdiffstats
path: root/tboot/include/tpm.h
blob: 59ebde101dc1ab5daf2c9f2a2c508036f6d8d1d4 (plain)
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:
 */