PageRenderTime 68ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 0ms

/tboot-1.7.0/tboot/common/tpm.c

#
C | 2132 lines | 1604 code | 325 blank | 203 comment | 329 complexity | 71ffc436c183b2797fc2729663aebc4c MD5 | raw file

Large files files are truncated, but you can click here to view the full file

  1. /*
  2. * tpm.c: TPM-related support functions
  3. *
  4. * Copyright (c) 2006-2010, Intel Corporation
  5. * All rights reserved.
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions
  9. * are met:
  10. *
  11. * * Redistributions of source code must retain the above copyright
  12. * notice, this list of conditions and the following disclaimer.
  13. * * Redistributions in binary form must reproduce the above
  14. * copyright notice, this list of conditions and the following
  15. * disclaimer in the documentation and/or other materials provided
  16. * with the distribution.
  17. * * Neither the name of the Intel Corporation nor the names of its
  18. * contributors may be used to endorse or promote products derived
  19. * from this software without specific prior written permission.
  20. *
  21. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  22. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  23. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  24. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  25. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  26. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  27. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  28. * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  29. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  30. * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  31. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  32. * OF THE POSSIBILITY OF SUCH DAMAGE.
  33. *
  34. */
  35. #include <config.h>
  36. #include <types.h>
  37. #include <stdbool.h>
  38. #include <printk.h>
  39. #include <misc.h>
  40. #include <compiler.h>
  41. #include <processor.h>
  42. #include <io.h>
  43. #include <string.h>
  44. #include <tpm.h>
  45. #include <sha1.h>
  46. /* un-comment to enable detailed command tracing */
  47. //#define TPM_TRACE
  48. /* ~5 secs are required for Infineon that requires this, so leave some extra */
  49. #define MAX_SAVESTATE_RETRIES 60
  50. #define TPM_TAG_RQU_COMMAND 0x00C1
  51. #define TPM_TAG_RQU_AUTH1_COMMAND 0x00C2
  52. #define TPM_TAG_RQU_AUTH2_COMMAND 0x00C3
  53. #define TPM_ORD_PCR_EXTEND 0x00000014
  54. #define TPM_ORD_PCR_READ 0x00000015
  55. #define TPM_ORD_PCR_RESET 0x000000C8
  56. #define TPM_ORD_NV_READ_VALUE 0x000000CF
  57. #define TPM_ORD_NV_WRITE_VALUE 0x000000CD
  58. #define TPM_ORD_GET_CAPABILITY 0x00000065
  59. #define TPM_ORD_SEAL 0x00000017
  60. #define TPM_ORD_UNSEAL 0x00000018
  61. #define TPM_ORD_OSAP 0x0000000B
  62. #define TPM_ORD_OIAP 0x0000000A
  63. #define TPM_ORD_SAVE_STATE 0x00000098
  64. #define TPM_ORD_GET_RANDOM 0x00000046
  65. #define TPM_TAG_PCR_INFO_LONG 0x0006
  66. #define TPM_TAG_STORED_DATA12 0x0016
  67. /*
  68. * TPM registers and data structures
  69. *
  70. * register values are offsets from each locality base
  71. * see {read,write}_tpm_reg() for data struct format
  72. */
  73. /* TPM_ACCESS_x */
  74. #define TPM_REG_ACCESS 0x00
  75. typedef union {
  76. u8 _raw[1]; /* 1-byte reg */
  77. struct __packed {
  78. u8 tpm_establishment : 1; /* RO, 0=T/OS has been established
  79. before */
  80. u8 request_use : 1; /* RW, 1=locality is requesting TPM use */
  81. u8 pending_request : 1; /* RO, 1=other locality is requesting
  82. TPM usage */
  83. u8 seize : 1; /* WO, 1=seize locality */
  84. u8 been_seized : 1; /* RW, 1=locality seized while active */
  85. u8 active_locality : 1; /* RW, 1=locality is active */
  86. u8 reserved : 1;
  87. u8 tpm_reg_valid_sts : 1; /* RO, 1=other bits are valid */
  88. };
  89. } tpm_reg_access_t;
  90. /* TPM_STS_x */
  91. #define TPM_REG_STS 0x18
  92. typedef union {
  93. u8 _raw[3]; /* 3-byte reg */
  94. struct __packed {
  95. u8 reserved1 : 1;
  96. u8 response_retry : 1; /* WO, 1=re-send response */
  97. u8 reserved2 : 1;
  98. u8 expect : 1; /* RO, 1=more data for command expected */
  99. u8 data_avail : 1; /* RO, 0=no more data for response */
  100. u8 tpm_go : 1; /* WO, 1=execute sent command */
  101. u8 command_ready : 1; /* RW, 1=TPM ready to receive new cmd */
  102. u8 sts_valid : 1; /* RO, 1=data_avail and expect bits are
  103. valid */
  104. u16 burst_count : 16; /* RO, # read/writes bytes before wait */
  105. };
  106. } tpm_reg_sts_t;
  107. /* TPM_DATA_FIFO_x */
  108. #define TPM_REG_DATA_FIFO 0x24
  109. typedef union {
  110. uint8_t _raw[1]; /* 1-byte reg */
  111. } tpm_reg_data_fifo_t;
  112. /*
  113. * assumes that all reg types follow above format:
  114. * - packed
  115. * - member named '_raw' which is array whose size is that of data to read
  116. */
  117. #define read_tpm_reg(locality, reg, pdata) \
  118. _read_tpm_reg(locality, reg, (pdata)->_raw, sizeof(*(pdata)))
  119. #define write_tpm_reg(locality, reg, pdata) \
  120. _write_tpm_reg(locality, reg, (pdata)->_raw, sizeof(*(pdata)))
  121. static void _read_tpm_reg(int locality, u32 reg, u8 *_raw, size_t size)
  122. {
  123. for ( size_t i = 0; i < size; i++ )
  124. _raw[i] = readb((TPM_LOCALITY_BASE_N(locality) | reg) + i);
  125. }
  126. static void _write_tpm_reg(int locality, u32 reg, u8 *_raw, size_t size)
  127. {
  128. for ( size_t i = 0; i < size; i++ )
  129. writeb((TPM_LOCALITY_BASE_N(locality) | reg) + i, _raw[i]);
  130. }
  131. /*
  132. * the following inline function reversely copy the bytes from 'in' to
  133. * 'out', the byte number to copy is given in count.
  134. */
  135. #define reverse_copy(out, in, count) \
  136. _reverse_copy((uint8_t *)(out), (uint8_t *)(in), count)
  137. static inline void _reverse_copy(uint8_t *out, uint8_t *in, uint32_t count)
  138. {
  139. for ( uint32_t i = 0; i < count; i++ )
  140. out[i] = in[count - i - 1];
  141. }
  142. #define TPM_VALIDATE_LOCALITY_TIME_OUT 0x100
  143. static bool tpm_validate_locality(uint32_t locality)
  144. {
  145. uint32_t i;
  146. tpm_reg_access_t reg_acc;
  147. for ( i = TPM_VALIDATE_LOCALITY_TIME_OUT; i > 0; i-- ) {
  148. /*
  149. * TCG spec defines reg_acc.tpm_reg_valid_sts bit to indicate whether
  150. * other bits of access reg are valid.( but this bit will also be 1
  151. * while this locality is not available, so check seize bit too)
  152. * It also defines that reading reg_acc.seize should always return 0
  153. */
  154. read_tpm_reg(locality, TPM_REG_ACCESS, &reg_acc);
  155. if ( reg_acc.tpm_reg_valid_sts == 1 && reg_acc.seize == 0)
  156. return true;
  157. cpu_relax();
  158. }
  159. if ( i <= 0 )
  160. printk("TPM: tpm_validate_locality timeout\n");
  161. return false;
  162. }
  163. #define TIMEOUT_UNIT (0x100000 / 330) /* ~1ms, 1 tpm r/w need > 330ns */
  164. #define TIMEOUT_A 750 /* 750ms */
  165. #define TIMEOUT_B 2000 /* 2s */
  166. #define TIMEOUT_C 750 /* 750ms */
  167. #define TIMEOUT_D 750 /* 750ms */
  168. typedef struct __packed {
  169. uint32_t timeout_a;
  170. uint32_t timeout_b;
  171. uint32_t timeout_c;
  172. uint32_t timeout_d;
  173. } tpm_timeout_t;
  174. static tpm_timeout_t g_timeout = {TIMEOUT_A,
  175. TIMEOUT_B,
  176. TIMEOUT_C,
  177. TIMEOUT_D};
  178. #define TPM_ACTIVE_LOCALITY_TIME_OUT \
  179. (TIMEOUT_UNIT * g_timeout.timeout_a) /* according to spec */
  180. #define TPM_CMD_READY_TIME_OUT \
  181. (TIMEOUT_UNIT * g_timeout.timeout_b) /* according to spec */
  182. #define TPM_CMD_WRITE_TIME_OUT \
  183. (TIMEOUT_UNIT * g_timeout.timeout_d) /* let it long enough */
  184. #define TPM_DATA_AVAIL_TIME_OUT \
  185. (TIMEOUT_UNIT * g_timeout.timeout_c) /* let it long enough */
  186. #define TPM_RSP_READ_TIME_OUT \
  187. (TIMEOUT_UNIT * g_timeout.timeout_d) /* let it long enough */
  188. static uint32_t tpm_wait_cmd_ready(uint32_t locality)
  189. {
  190. uint32_t i;
  191. tpm_reg_access_t reg_acc;
  192. tpm_reg_sts_t reg_sts;
  193. /* ensure the contents of the ACCESS register are valid */
  194. read_tpm_reg(locality, TPM_REG_ACCESS, &reg_acc);
  195. #ifdef TPM_TRACE
  196. printk("TPM: Access reg content: 0x%02x\n", (uint32_t)reg_acc._raw[0]);
  197. #endif
  198. if ( reg_acc.tpm_reg_valid_sts == 0 ) {
  199. printk("TPM: Access reg not valid\n");
  200. return TPM_FAIL;
  201. }
  202. /* request access to the TPM from locality N */
  203. reg_acc._raw[0] = 0;
  204. reg_acc.request_use = 1;
  205. write_tpm_reg(locality, TPM_REG_ACCESS, &reg_acc);
  206. i = 0;
  207. do {
  208. read_tpm_reg(locality, TPM_REG_ACCESS, &reg_acc);
  209. if ( reg_acc.active_locality == 1 )
  210. break;
  211. else
  212. cpu_relax();
  213. i++;
  214. } while ( i <= TPM_ACTIVE_LOCALITY_TIME_OUT);
  215. if ( i > TPM_ACTIVE_LOCALITY_TIME_OUT ) {
  216. printk("TPM: access reg request use timeout\n");
  217. return TPM_FAIL;
  218. }
  219. /* ensure the TPM is ready to accept a command */
  220. #ifdef TPM_TRACE
  221. printk("TPM: wait for cmd ready ");
  222. #endif
  223. i = 0;
  224. do {
  225. /* write 1 to TPM_STS_x.commandReady to let TPM enter ready state */
  226. memset((void *)&reg_sts, 0, sizeof(reg_sts));
  227. reg_sts.command_ready = 1;
  228. write_tpm_reg(locality, TPM_REG_STS, &reg_sts);
  229. cpu_relax();
  230. /* then see if it has */
  231. read_tpm_reg(locality, TPM_REG_STS, &reg_sts);
  232. #ifdef TPM_TRACE
  233. printk(".");
  234. #endif
  235. if ( reg_sts.command_ready == 1 )
  236. break;
  237. else
  238. cpu_relax();
  239. i++;
  240. } while ( i <= TPM_CMD_READY_TIME_OUT );
  241. #ifdef TPM_TRACE
  242. printk("\n");
  243. #endif
  244. if ( i > TPM_CMD_READY_TIME_OUT ) {
  245. printk("TPM: status reg content: %02x %02x %02x\n",
  246. (uint32_t)reg_sts._raw[0],
  247. (uint32_t)reg_sts._raw[1],
  248. (uint32_t)reg_sts._raw[2]);
  249. printk("TPM: tpm timeout for command_ready\n");
  250. goto RelinquishControl;
  251. }
  252. return TPM_SUCCESS;
  253. RelinquishControl:
  254. /* deactivate current locality */
  255. reg_acc._raw[0] = 0;
  256. reg_acc.active_locality = 1;
  257. write_tpm_reg(locality, TPM_REG_ACCESS, &reg_acc);
  258. return TPM_FAIL;
  259. }
  260. /*
  261. * locality : TPM locality (0 - 3)
  262. * in : All bytes for a single TPM command, including TAG, SIZE,
  263. * ORDINAL, and other arguments. All data should be in big-endian
  264. * style. The in MUST NOT be NULL, containing at least 10 bytes.
  265. * 0 1 2 3 4 5 6 7 8 9 10 ...
  266. * -------------------------------------------------------------
  267. * | TAG | SIZE | ORDINAL | arguments ...
  268. * -------------------------------------------------------------
  269. * in_size : The size of the whole command contained within the in buffer.
  270. * It should equal to the SIZE contained in the in buffer.
  271. * out : All bytes of the TPM response to a single command. All data
  272. * within it will be in big-endian style. The out MUST not be
  273. * NULL, and will return at least 10 bytes.
  274. * 0 1 2 3 4 5 6 7 8 9 10 ...
  275. * -------------------------------------------------------------
  276. * | TAG | SIZE | RETURN CODE | other data ...
  277. * -------------------------------------------------------------
  278. * out_size : In/out paramter. As in, it is the size of the out buffer;
  279. * as out, it is the size of the response within the out buffer.
  280. * The out_size MUST NOT be NULL.
  281. * return : 0 = success; if not 0, it equal to the RETURN CODE in out buf.
  282. */
  283. #define CMD_HEAD_SIZE 10
  284. #define RSP_HEAD_SIZE 10
  285. #define CMD_SIZE_OFFSET 2
  286. #define CMD_ORD_OFFSET 6
  287. #define RSP_SIZE_OFFSET 2
  288. #define RSP_RST_OFFSET 6
  289. static uint32_t tpm_write_cmd_fifo(uint32_t locality, uint8_t *in,
  290. uint32_t in_size, uint8_t *out,
  291. uint32_t *out_size)
  292. {
  293. uint32_t i, rsp_size, offset, ret;
  294. uint16_t row_size;
  295. tpm_reg_access_t reg_acc;
  296. tpm_reg_sts_t reg_sts;
  297. if ( locality >= TPM_NR_LOCALITIES ) {
  298. printk("TPM: Invalid locality for tpm_write_cmd_fifo()\n");
  299. return TPM_BAD_PARAMETER;
  300. }
  301. if ( in == NULL || out == NULL || out_size == NULL ) {
  302. printk("TPM: Invalid parameter for tpm_write_cmd_fifo()\n");
  303. return TPM_BAD_PARAMETER;
  304. }
  305. if ( in_size < CMD_HEAD_SIZE || *out_size < RSP_HEAD_SIZE ) {
  306. printk("TPM: in/out buf size must be larger than 10 bytes\n");
  307. return TPM_BAD_PARAMETER;
  308. }
  309. if ( !tpm_validate_locality(locality) ) {
  310. printk("TPM: Locality %d is not open\n", locality);
  311. return TPM_FAIL;
  312. }
  313. ret = tpm_wait_cmd_ready(locality);
  314. if ( ret != TPM_SUCCESS )
  315. return ret;
  316. #ifdef TPM_TRACE
  317. {
  318. printk("TPM: cmd size = %d\nTPM: cmd content: ", in_size);
  319. print_hex("TPM: \t", in, in_size);
  320. }
  321. #endif
  322. /* write the command to the TPM FIFO */
  323. offset = 0;
  324. do {
  325. i = 0;
  326. do {
  327. read_tpm_reg(locality, TPM_REG_STS, &reg_sts);
  328. /* find out how many bytes the TPM can accept in a row */
  329. row_size = reg_sts.burst_count;
  330. if ( row_size > 0 )
  331. break;
  332. else
  333. cpu_relax();
  334. i++;
  335. } while ( i <= TPM_CMD_WRITE_TIME_OUT );
  336. if ( i > TPM_CMD_WRITE_TIME_OUT ) {
  337. printk("TPM: write cmd timeout\n");
  338. ret = TPM_FAIL;
  339. goto RelinquishControl;
  340. }
  341. for ( ; row_size > 0 && offset < in_size; row_size--, offset++ )
  342. write_tpm_reg(locality, TPM_REG_DATA_FIFO,
  343. (tpm_reg_data_fifo_t *)&in[offset]);
  344. } while ( offset < in_size );
  345. i = 0;
  346. do {
  347. read_tpm_reg(locality,TPM_REG_STS, &reg_sts);
  348. #ifdef TPM_TRACE
  349. printk("Wait on Expect = 0, Status register %02x\n", reg_sts._raw[0]);
  350. #endif
  351. if ( reg_sts.sts_valid == 1 && reg_sts.expect == 0 )
  352. break;
  353. else
  354. cpu_relax();
  355. i++;
  356. } while ( i <= TPM_DATA_AVAIL_TIME_OUT );
  357. if ( i > TPM_DATA_AVAIL_TIME_OUT ) {
  358. printk("TPM: wait for expect becoming 0 timeout\n");
  359. ret = TPM_FAIL;
  360. goto RelinquishControl;
  361. }
  362. /* command has been written to the TPM, it is time to execute it. */
  363. memset(&reg_sts, 0, sizeof(reg_sts));
  364. reg_sts.tpm_go = 1;
  365. write_tpm_reg(locality, TPM_REG_STS, &reg_sts);
  366. /* check for data available */
  367. i = 0;
  368. do {
  369. read_tpm_reg(locality,TPM_REG_STS, &reg_sts);
  370. #ifdef TPM_TRACE
  371. printk("Waiting for DA Flag, Status register %02x\n", reg_sts._raw[0]);
  372. #endif
  373. if ( reg_sts.sts_valid == 1 && reg_sts.data_avail == 1 )
  374. break;
  375. else
  376. cpu_relax();
  377. i++;
  378. } while ( i <= TPM_DATA_AVAIL_TIME_OUT );
  379. if ( i > TPM_DATA_AVAIL_TIME_OUT ) {
  380. printk("TPM: wait for data available timeout\n");
  381. ret = TPM_FAIL;
  382. goto RelinquishControl;
  383. }
  384. rsp_size = 0;
  385. offset = 0;
  386. do {
  387. /* find out how many bytes the TPM returned in a row */
  388. i = 0;
  389. do {
  390. read_tpm_reg(locality, TPM_REG_STS, &reg_sts);
  391. row_size = reg_sts.burst_count;
  392. if ( row_size > 0 )
  393. break;
  394. else
  395. cpu_relax();
  396. i++;
  397. } while ( i <= TPM_RSP_READ_TIME_OUT );
  398. if ( i > TPM_RSP_READ_TIME_OUT ) {
  399. printk("TPM: read rsp timeout\n");
  400. ret = TPM_FAIL;
  401. goto RelinquishControl;
  402. }
  403. for ( ; row_size > 0 && offset < *out_size; row_size--, offset++ ) {
  404. if ( offset < *out_size )
  405. read_tpm_reg(locality, TPM_REG_DATA_FIFO,
  406. (tpm_reg_data_fifo_t *)&out[offset]);
  407. else {
  408. /* discard the responded bytes exceeding out buf size */
  409. tpm_reg_data_fifo_t discard;
  410. read_tpm_reg(locality, TPM_REG_DATA_FIFO,
  411. (tpm_reg_data_fifo_t *)&discard);
  412. }
  413. /* get outgoing data size */
  414. if ( offset == RSP_RST_OFFSET - 1 ) {
  415. reverse_copy(&rsp_size, &out[RSP_SIZE_OFFSET],
  416. sizeof(rsp_size));
  417. }
  418. }
  419. } while ( offset < RSP_RST_OFFSET ||
  420. (offset < rsp_size && offset < *out_size) );
  421. *out_size = (*out_size > rsp_size) ? rsp_size : *out_size;
  422. /* out buffer contains the complete outgoing data, get return code */
  423. reverse_copy(&ret, &out[RSP_RST_OFFSET], sizeof(ret));
  424. #ifdef TPM_TRACE
  425. {
  426. printk("TPM: response size = %d\n", *out_size);
  427. printk("TPM: response content: ");
  428. print_hex("TPM: \t", out, *out_size);
  429. }
  430. #endif
  431. memset(&reg_sts, 0, sizeof(reg_sts));
  432. reg_sts.command_ready = 1;
  433. write_tpm_reg(locality, TPM_REG_STS, &reg_sts);
  434. RelinquishControl:
  435. /* deactivate current locality */
  436. reg_acc._raw[0] = 0;
  437. reg_acc.active_locality = 1;
  438. write_tpm_reg(locality, TPM_REG_ACCESS, &reg_acc);
  439. return ret;
  440. }
  441. /*
  442. * The _tpm_submit_cmd function comes with 2 global buffers: cmd_buf & rsp_buf.
  443. * Before calling, caller should fill cmd arguements into cmd_buf via
  444. * WRAPPER_IN_BUF macro. After calling, caller should fetch result from
  445. * rsp_buffer via WRAPPER_OUT_BUF macro.
  446. * cmd_buf content:
  447. * 0 1 2 3 4 5 6 7 8 9 10 ...
  448. * -------------------------------------------------------------
  449. * | TAG | SIZE | ORDINAL | arguments ...
  450. * -------------------------------------------------------------
  451. * rsp_buf content:
  452. * 0 1 2 3 4 5 6 7 8 9 10 ...
  453. * -------------------------------------------------------------
  454. * | TAG | SIZE | RETURN CODE | other data ...
  455. * -------------------------------------------------------------
  456. *
  457. * locality : TPM locality (0 - 4)
  458. * tag : The TPM command tag
  459. * cmd : The TPM command ordinal
  460. * arg_size : Size of argument data.
  461. * out_size : IN/OUT paramter. The IN is the expected size of out data;
  462. * the OUT is the size of output data within out buffer.
  463. * The out_size MUST NOT be NULL.
  464. * return : TPM_SUCCESS for success, for other error code, refer to the .h
  465. */
  466. static uint8_t cmd_buf[TPM_CMD_SIZE_MAX];
  467. static uint8_t rsp_buf[TPM_RSP_SIZE_MAX];
  468. #define WRAPPER_IN_BUF (cmd_buf + CMD_HEAD_SIZE)
  469. #define WRAPPER_OUT_BUF (rsp_buf + RSP_HEAD_SIZE)
  470. #define WRAPPER_IN_MAX_SIZE (TPM_CMD_SIZE_MAX - CMD_HEAD_SIZE)
  471. #define WRAPPER_OUT_MAX_SIZE (TPM_RSP_SIZE_MAX - RSP_HEAD_SIZE)
  472. static uint32_t _tpm_submit_cmd(uint32_t locality, uint16_t tag, uint32_t cmd,
  473. uint32_t arg_size, uint32_t *out_size)
  474. {
  475. uint32_t ret;
  476. uint32_t cmd_size, rsp_size = 0;
  477. if ( out_size == NULL ) {
  478. printk("TPM: invalid param for _tpm_submit_cmd()\n");
  479. return TPM_BAD_PARAMETER;
  480. }
  481. /*
  482. * real cmd size should add 10 more bytes:
  483. * 2 bytes for tag
  484. * 4 bytes for size
  485. * 4 bytes for ordinal
  486. */
  487. cmd_size = CMD_HEAD_SIZE + arg_size;
  488. if ( cmd_size > TPM_CMD_SIZE_MAX ) {
  489. printk("TPM: cmd exceeds the max supported size.\n");
  490. return TPM_BAD_PARAMETER;
  491. }
  492. /* copy tag, size & ordinal into buf in a reversed byte order */
  493. reverse_copy(cmd_buf, &tag, sizeof(tag));
  494. reverse_copy(cmd_buf + CMD_SIZE_OFFSET, &cmd_size, sizeof(cmd_size));
  495. reverse_copy(cmd_buf + CMD_ORD_OFFSET, &cmd, sizeof(cmd));
  496. rsp_size = RSP_HEAD_SIZE + *out_size;
  497. rsp_size = (rsp_size > TPM_RSP_SIZE_MAX) ? TPM_RSP_SIZE_MAX: rsp_size;
  498. ret = tpm_write_cmd_fifo(locality, cmd_buf, cmd_size, rsp_buf, &rsp_size);
  499. /*
  500. * should subtract 10 bytes from real response size:
  501. * 2 bytes for tag
  502. * 4 bytes for size
  503. * 4 bytes for return code
  504. */
  505. rsp_size -= (rsp_size > RSP_HEAD_SIZE) ? RSP_HEAD_SIZE : rsp_size;
  506. if ( ret != TPM_SUCCESS )
  507. return ret;
  508. if ( *out_size == 0 || rsp_size == 0 )
  509. *out_size = 0;
  510. else
  511. *out_size = (rsp_size < *out_size) ? rsp_size : *out_size;
  512. return ret;
  513. }
  514. static inline uint32_t tpm_submit_cmd(uint32_t locality, uint32_t cmd,
  515. uint32_t arg_size, uint32_t *out_size)
  516. {
  517. return _tpm_submit_cmd(locality, TPM_TAG_RQU_COMMAND, cmd,
  518. arg_size, out_size);
  519. }
  520. static inline uint32_t tpm_submit_cmd_auth1(uint32_t locality, uint32_t cmd,
  521. uint32_t arg_size, uint32_t *out_size)
  522. {
  523. return _tpm_submit_cmd(locality, TPM_TAG_RQU_AUTH1_COMMAND, cmd,
  524. arg_size, out_size);
  525. }
  526. static inline uint32_t tpm_submit_cmd_auth2(uint32_t locality, uint32_t cmd,
  527. uint32_t arg_size, uint32_t *out_size)
  528. {
  529. return _tpm_submit_cmd(locality, TPM_TAG_RQU_AUTH2_COMMAND, cmd,
  530. arg_size, out_size);
  531. }
  532. uint32_t tpm_pcr_read(uint32_t locality, uint32_t pcr, tpm_pcr_value_t *out)
  533. {
  534. uint32_t ret, out_size = sizeof(*out);
  535. if ( out == NULL )
  536. return TPM_BAD_PARAMETER;
  537. if ( pcr >= TPM_NR_PCRS )
  538. return TPM_BAD_PARAMETER;
  539. /* copy pcr into buf in reversed byte order */
  540. reverse_copy(WRAPPER_IN_BUF, &pcr, sizeof(pcr));
  541. ret = tpm_submit_cmd(locality, TPM_ORD_PCR_READ, sizeof(pcr), &out_size);
  542. #ifdef TPM_TRACE
  543. printk("TPM: Pcr %d Read return value = %08X\n", pcr, ret);
  544. #endif
  545. if ( ret != TPM_SUCCESS ) {
  546. printk("TPM: Pcr %d Read return value = %08X\n", pcr, ret);
  547. return ret;
  548. }
  549. if ( out_size > sizeof(*out) )
  550. out_size = sizeof(*out);
  551. memcpy((void *)out, WRAPPER_OUT_BUF, out_size);
  552. #ifdef TPM_TRACE
  553. {
  554. printk("TPM: ");
  555. print_hex(NULL, out->digest, out_size);
  556. }
  557. #endif
  558. return ret;
  559. }
  560. uint32_t tpm_pcr_extend(uint32_t locality, uint32_t pcr,
  561. const tpm_digest_t* in, tpm_pcr_value_t* out)
  562. {
  563. uint32_t ret, in_size = 0, out_size;
  564. if ( in == NULL )
  565. return TPM_BAD_PARAMETER;
  566. if ( pcr >= TPM_NR_PCRS )
  567. return TPM_BAD_PARAMETER;
  568. if ( out == NULL )
  569. out_size = 0;
  570. else
  571. out_size = sizeof(*out);
  572. /* copy pcr into buf in reversed byte order, then copy in data */
  573. reverse_copy(WRAPPER_IN_BUF, &pcr, sizeof(pcr));
  574. in_size += sizeof(pcr);
  575. memcpy(WRAPPER_IN_BUF + in_size, (void *)in, sizeof(*in));
  576. in_size += sizeof(*in);
  577. ret = tpm_submit_cmd(locality, TPM_ORD_PCR_EXTEND, in_size, &out_size);
  578. #ifdef TPM_TRACE
  579. printk("TPM: Pcr %d extend, return value = %08X\n", pcr, ret);
  580. #endif
  581. if ( ret != TPM_SUCCESS ) {
  582. printk("TPM: Pcr %d extend, return value = %08X\n", pcr, ret);
  583. return ret;
  584. }
  585. if ( out != NULL && out_size > 0 ) {
  586. out_size = (out_size > sizeof(*out)) ? sizeof(*out) : out_size;
  587. memcpy((void *)out, WRAPPER_OUT_BUF, out_size);
  588. }
  589. #ifdef TPM_TRACE
  590. {
  591. printk("TPM: ");
  592. print_hex(NULL, out->digest, out_size);
  593. }
  594. #endif
  595. return ret;
  596. }
  597. typedef struct __packed {
  598. uint16_t size_of_select;
  599. uint8_t pcr_select[3];
  600. } tpm_pcr_selection_t;
  601. uint32_t tpm_pcr_reset(uint32_t locality, uint32_t pcr)
  602. {
  603. uint32_t ret, in_size, out_size = 0;
  604. uint16_t size_of_select;
  605. tpm_pcr_selection_t pcr_sel = {0,{0,}};
  606. if ( pcr >= TPM_NR_PCRS || pcr < TPM_PCR_RESETABLE_MIN )
  607. return TPM_BAD_PARAMETER;
  608. /* the pcr_sel.pcr_select[size_of_select - 1] should not be 0 */
  609. size_of_select = pcr / 8 + 1;
  610. reverse_copy(&pcr_sel.size_of_select, &size_of_select,
  611. sizeof(size_of_select));
  612. pcr_sel.pcr_select[pcr / 8] = 1 << (pcr % 8);
  613. in_size = sizeof(pcr_sel);
  614. memcpy(WRAPPER_IN_BUF, (void *)&pcr_sel, in_size);
  615. ret = tpm_submit_cmd(locality, TPM_ORD_PCR_RESET, in_size, &out_size);
  616. printk("TPM: Pcr %d reset, return value = %08X\n", pcr, ret);
  617. return ret;
  618. }
  619. uint32_t tpm_nv_read_value(uint32_t locality, tpm_nv_index_t index,
  620. uint32_t offset, uint8_t *data,
  621. uint32_t *data_size)
  622. {
  623. uint32_t ret, in_size = 0, out_size;
  624. if ( data == NULL || data_size == NULL )
  625. return TPM_BAD_PARAMETER;
  626. if ( *data_size == 0 )
  627. return TPM_BAD_PARAMETER;
  628. if ( *data_size > TPM_NV_READ_VALUE_DATA_SIZE_MAX )
  629. *data_size = TPM_NV_READ_VALUE_DATA_SIZE_MAX;
  630. /* copy the index, offset and *data_size into buf in reversed byte order */
  631. reverse_copy(WRAPPER_IN_BUF, &index, sizeof(index));
  632. in_size += sizeof(index);
  633. reverse_copy(WRAPPER_IN_BUF + in_size, &offset, sizeof(offset));
  634. in_size += sizeof(offset);
  635. reverse_copy(WRAPPER_IN_BUF + in_size, data_size, sizeof(*data_size));
  636. in_size += sizeof(*data_size);
  637. out_size = *data_size + sizeof(*data_size);
  638. ret = tpm_submit_cmd(locality, TPM_ORD_NV_READ_VALUE, in_size, &out_size);
  639. #ifdef TPM_TRACE
  640. printk("TPM: read nv index %08x from offset %08x, return value = %08X\n",
  641. index, offset, ret);
  642. #endif
  643. if ( ret != TPM_SUCCESS ) {
  644. printk("TPM: read nv index %08x offset %08x, return value = %08X\n",
  645. index, offset, ret);
  646. return ret;
  647. }
  648. #ifdef TPM_TRACE
  649. {
  650. printk("TPM: ");
  651. print_hex(NULL, WRAPPER_OUT_BUF, out_size);
  652. }
  653. #endif
  654. if ( out_size <= sizeof(*data_size) ) {
  655. *data_size = 0;
  656. return ret;
  657. }
  658. out_size -= sizeof(*data_size);
  659. reverse_copy(data_size, WRAPPER_OUT_BUF, sizeof(*data_size));
  660. *data_size = (*data_size > out_size) ? out_size : *data_size;
  661. if( *data_size > 0 )
  662. memcpy(data, WRAPPER_OUT_BUF + sizeof(*data_size), *data_size);
  663. return ret;
  664. }
  665. uint32_t tpm_nv_write_value(uint32_t locality, tpm_nv_index_t index,
  666. uint32_t offset, const uint8_t *data,
  667. uint32_t data_size)
  668. {
  669. uint32_t ret, in_size = 0, out_size = 0;
  670. if ( data == NULL )
  671. return TPM_BAD_PARAMETER;
  672. if ( data_size == 0 || data_size > TPM_NV_WRITE_VALUE_DATA_SIZE_MAX )
  673. return TPM_BAD_PARAMETER;
  674. /* copy index, offset and *data_size into buf in reversed byte order */
  675. reverse_copy(WRAPPER_IN_BUF, &index, sizeof(index));
  676. in_size += sizeof(index);
  677. reverse_copy(WRAPPER_IN_BUF + in_size, &offset, sizeof(offset));
  678. in_size += sizeof(offset);
  679. reverse_copy(WRAPPER_IN_BUF + in_size, &data_size, sizeof(data_size));
  680. in_size += sizeof(data_size);
  681. memcpy(WRAPPER_IN_BUF + in_size, data, data_size);
  682. in_size += data_size;
  683. ret = tpm_submit_cmd(locality, TPM_ORD_NV_WRITE_VALUE,
  684. in_size, &out_size);
  685. #ifdef TPM_TRACE
  686. printk("TPM: write nv %08x, offset %08x, %08x bytes, return = %08X\n",
  687. index, offset, data_size, ret);
  688. #endif
  689. if ( ret != TPM_SUCCESS )
  690. printk("TPM: write nv %08x, offset %08x, %08x bytes, return = %08X\n",
  691. index, offset, data_size, ret);
  692. return ret;
  693. }
  694. #define TPM_CAP_VERSION_VAL 0x1A
  695. typedef uint16_t tpm_structure_tag_t;
  696. typedef struct __packed {
  697. uint8_t major;
  698. uint8_t minor;
  699. uint8_t rev_major;
  700. uint8_t rev_minor;
  701. } tpm_version_t;
  702. typedef struct __packed {
  703. tpm_structure_tag_t tag;
  704. tpm_version_t version;
  705. uint16_t specLevel;
  706. uint8_t errataRev;
  707. uint8_t tpmVendorID[4];
  708. uint16_t vendorSpecificSize;
  709. uint8_t vendorSpecific[];
  710. } tpm_cap_version_info_t;
  711. /* get tpm module version */
  712. uint32_t tpm_get_version(uint8_t *major, uint8_t *minor)
  713. {
  714. uint32_t ret, in_size = 0, out_size;
  715. uint32_t cap_area = TPM_CAP_VERSION_VAL;
  716. uint32_t sub_cap_size = 0;
  717. uint32_t resp_size = 0;
  718. tpm_cap_version_info_t *cap_version;
  719. if ( major == NULL || minor == NULL )
  720. return TPM_BAD_PARAMETER;
  721. reverse_copy(WRAPPER_IN_BUF, &cap_area, sizeof(cap_area));
  722. in_size += sizeof(cap_area);
  723. reverse_copy(WRAPPER_IN_BUF+in_size, &sub_cap_size, sizeof(sub_cap_size));
  724. in_size += sizeof(sub_cap_size);
  725. out_size = sizeof(resp_size) + sizeof(tpm_cap_version_info_t);
  726. ret = tpm_submit_cmd(0, TPM_ORD_GET_CAPABILITY, in_size, &out_size);
  727. #ifdef TPM_TRACE
  728. printk("TPM: get version, return value = %08X\n", ret);
  729. #endif
  730. if ( ret != TPM_SUCCESS ) {
  731. printk("TPM: get version, return value = %08X\n", ret);
  732. return ret;
  733. }
  734. #ifdef TPM_TRACE
  735. {
  736. printk("TPM: ");
  737. print_hex(NULL, WRAPPER_OUT_BUF, out_size);
  738. }
  739. #endif
  740. reverse_copy(&resp_size, WRAPPER_OUT_BUF, sizeof(resp_size));
  741. cap_version = (tpm_cap_version_info_t *)
  742. (WRAPPER_OUT_BUF + sizeof(resp_size));
  743. *major = cap_version->version.major;
  744. *minor = cap_version->version.minor;
  745. return ret;
  746. }
  747. #define HMAC_BLOCK_SIZE 64
  748. #define HMAC_OUTPUT_SIZE 20
  749. static bool hmac(const uint8_t key[HMAC_OUTPUT_SIZE], const uint8_t *msg,
  750. uint32_t len, uint8_t md[HMAC_OUTPUT_SIZE])
  751. {
  752. uint8_t ipad[HMAC_BLOCK_SIZE], opad[HMAC_BLOCK_SIZE];
  753. uint32_t i;
  754. SHA_CTX ctx;
  755. COMPILE_TIME_ASSERT(HMAC_OUTPUT_SIZE <= HMAC_BLOCK_SIZE);
  756. for ( i = 0; i < HMAC_BLOCK_SIZE; i++ ) {
  757. ipad[i] = 0x36;
  758. opad[i] = 0x5C;
  759. }
  760. for ( i = 0; i < HMAC_OUTPUT_SIZE; i++ ) {
  761. ipad[i] ^= key[i];
  762. opad[i] ^= key[i];
  763. }
  764. SHA1_Init(&ctx);
  765. SHA1_Update(&ctx, ipad, HMAC_BLOCK_SIZE);
  766. SHA1_Update(&ctx, msg, len);
  767. SHA1_Final(md, &ctx);
  768. SHA1_Init(&ctx);
  769. SHA1_Update(&ctx, opad, HMAC_BLOCK_SIZE);
  770. SHA1_Update(&ctx, md, HMAC_OUTPUT_SIZE);
  771. SHA1_Final(md, &ctx);
  772. return true;
  773. }
  774. typedef uint16_t tpm_entity_type_t;
  775. typedef uint32_t tpm_authhandle_t;
  776. typedef struct __packed {
  777. uint8_t nonce[20];
  778. } tpm_nonce_t;
  779. #define TPM_ET_SRK 0x0004
  780. #define TPM_KH_SRK 0x40000000
  781. typedef uint32_t tpm_key_handle_t;
  782. typedef tpm_digest_t tpm_composite_hash_t;
  783. typedef struct __packed {
  784. tpm_structure_tag_t tag;
  785. tpm_locality_selection_t locality_at_creation;
  786. tpm_locality_selection_t locality_at_release;
  787. tpm_pcr_selection_t creation_pcr_selection;
  788. tpm_pcr_selection_t release_pcr_selection;
  789. tpm_composite_hash_t digest_at_creation;
  790. tpm_composite_hash_t digest_at_release;
  791. } tpm_pcr_info_long_t;
  792. typedef uint8_t tpm_authdata_t[20];
  793. typedef tpm_authdata_t tpm_encauth_t;
  794. typedef struct __packed {
  795. tpm_structure_tag_t tag;
  796. tpm_entity_type_t et;
  797. uint32_t seal_info_size;
  798. } tpm_stored_data12_header_t;
  799. typedef struct __packed {
  800. tpm_stored_data12_header_t header;
  801. uint32_t enc_data_size;
  802. uint8_t enc_data[];
  803. } tpm_stored_data12_short_t;
  804. typedef struct __packed {
  805. tpm_stored_data12_header_t header;
  806. tpm_pcr_info_long_t seal_info;
  807. uint32_t enc_data_size;
  808. uint8_t enc_data[];
  809. } tpm_stored_data12_t;
  810. #define UNLOAD_INTEGER(buf, offset, var) {\
  811. reverse_copy(buf + offset, &(var), sizeof(var));\
  812. offset += sizeof(var);\
  813. }
  814. #define UNLOAD_BLOB(buf, offset, blob, size) {\
  815. memcpy(buf + offset, blob, size);\
  816. offset += size;\
  817. }
  818. #define UNLOAD_BLOB_TYPE(buf, offset, blob) \
  819. UNLOAD_BLOB(buf, offset, blob, sizeof(*(blob)))
  820. #define UNLOAD_PCR_SELECTION(buf, offset, sel) {\
  821. UNLOAD_INTEGER(buf, offset, (sel)->size_of_select);\
  822. UNLOAD_BLOB(buf, offset, (sel)->pcr_select, (sel)->size_of_select);\
  823. }
  824. #define UNLOAD_PCR_INFO_LONG(buf, offset, info) {\
  825. UNLOAD_INTEGER(buf, offset, (info)->tag);\
  826. UNLOAD_BLOB_TYPE(buf, offset, &(info)->locality_at_creation);\
  827. UNLOAD_BLOB_TYPE(buf, offset, &(info)->locality_at_release);\
  828. UNLOAD_PCR_SELECTION(buf, offset, &(info)->creation_pcr_selection);\
  829. UNLOAD_PCR_SELECTION(buf, offset, &(info)->release_pcr_selection);\
  830. UNLOAD_BLOB_TYPE(buf, offset, &(info)->digest_at_creation);\
  831. UNLOAD_BLOB_TYPE(buf, offset, &(info)->digest_at_release);\
  832. }
  833. #define UNLOAD_STORED_DATA12(buf, offset, hdr) {\
  834. UNLOAD_INTEGER(buf, offset, ((tpm_stored_data12_header_t *)(hdr))->tag);\
  835. UNLOAD_INTEGER(buf, offset, ((tpm_stored_data12_header_t *)(hdr))->et);\
  836. UNLOAD_INTEGER(buf, offset,\
  837. ((tpm_stored_data12_header_t *)(hdr))->seal_info_size);\
  838. if ( ((tpm_stored_data12_header_t *)(hdr))->seal_info_size == 0 ) {\
  839. UNLOAD_INTEGER(buf, offset,\
  840. ((tpm_stored_data12_short_t *)hdr)->enc_data_size);\
  841. UNLOAD_BLOB(buf, offset,\
  842. ((tpm_stored_data12_short_t *)hdr)->enc_data,\
  843. ((tpm_stored_data12_short_t *)hdr)->enc_data_size);\
  844. }\
  845. else {\
  846. UNLOAD_PCR_INFO_LONG(buf, offset,\
  847. &((tpm_stored_data12_t *)hdr)->seal_info);\
  848. UNLOAD_INTEGER(buf, offset,\
  849. ((tpm_stored_data12_t *)hdr)->enc_data_size);\
  850. UNLOAD_BLOB(buf, offset,\
  851. ((tpm_stored_data12_t *)hdr)->enc_data,\
  852. ((tpm_stored_data12_t *)hdr)->enc_data_size);\
  853. }\
  854. }
  855. #define LOAD_INTEGER(buf, offset, var) {\
  856. reverse_copy(&(var), buf + offset, sizeof(var));\
  857. offset += sizeof(var);\
  858. }
  859. #define LOAD_BLOB(buf, offset, blob, size) {\
  860. memcpy(blob, buf + offset, size);\
  861. offset += size;\
  862. }
  863. #define LOAD_BLOB_TYPE(buf, offset, blob) \
  864. LOAD_BLOB(buf, offset, blob, sizeof(*(blob)))
  865. #define LOAD_PCR_SELECTION(buf, offset, sel) {\
  866. LOAD_INTEGER(buf, offset, (sel)->size_of_select);\
  867. LOAD_BLOB(buf, offset, (sel)->pcr_select, (sel)->size_of_select);\
  868. }
  869. #define LOAD_PCR_INFO_LONG(buf, offset, info) {\
  870. LOAD_INTEGER(buf, offset, (info)->tag);\
  871. LOAD_BLOB_TYPE(buf, offset, &(info)->locality_at_creation);\
  872. LOAD_BLOB_TYPE(buf, offset, &(info)->locality_at_release);\
  873. LOAD_PCR_SELECTION(buf, offset, &(info)->creation_pcr_selection);\
  874. LOAD_PCR_SELECTION(buf, offset, &(info)->release_pcr_selection);\
  875. LOAD_BLOB_TYPE(buf, offset, &(info)->digest_at_creation);\
  876. LOAD_BLOB_TYPE(buf, offset, &(info)->digest_at_release);\
  877. }
  878. #define LOAD_STORED_DATA12(buf, offset, hdr) {\
  879. LOAD_INTEGER(buf, offset, ((tpm_stored_data12_header_t *)(hdr))->tag);\
  880. LOAD_INTEGER(buf, offset, ((tpm_stored_data12_header_t *)(hdr))->et);\
  881. LOAD_INTEGER(buf, offset, \
  882. ((tpm_stored_data12_header_t *)(hdr))->seal_info_size);\
  883. if ( ((tpm_stored_data12_header_t *)(hdr))->seal_info_size == 0 ) {\
  884. LOAD_INTEGER(buf, offset,\
  885. ((tpm_stored_data12_short_t *)hdr)->enc_data_size);\
  886. LOAD_BLOB(buf, offset,\
  887. ((tpm_stored_data12_short_t *)hdr)->enc_data,\
  888. ((tpm_stored_data12_short_t *)hdr)->enc_data_size);\
  889. }\
  890. else {\
  891. LOAD_PCR_INFO_LONG(buf, offset,\
  892. &((tpm_stored_data12_t *)hdr)->seal_info);\
  893. LOAD_INTEGER(buf, offset,\
  894. ((tpm_stored_data12_t *)hdr)->enc_data_size);\
  895. LOAD_BLOB(buf, offset,\
  896. ((tpm_stored_data12_t *)hdr)->enc_data,\
  897. ((tpm_stored_data12_t *)hdr)->enc_data_size);\
  898. }\
  899. }
  900. static uint32_t tpm_oiap(uint32_t locality, tpm_authhandle_t *hauth,
  901. tpm_nonce_t *nonce_even)
  902. {
  903. uint32_t ret, offset, out_size;
  904. if ( hauth == NULL || nonce_even == NULL )
  905. return TPM_BAD_PARAMETER;
  906. offset = 0;
  907. out_size = sizeof(*hauth) + sizeof(*nonce_even);
  908. ret = tpm_submit_cmd(locality, TPM_ORD_OIAP, offset, &out_size);
  909. #ifdef TPM_TRACE
  910. printk("TPM: start OIAP, return value = %08X\n", ret);
  911. #endif
  912. if ( ret != TPM_SUCCESS ) {
  913. printk("TPM: start OIAP, return value = %08X\n", ret);
  914. return ret;
  915. }
  916. #ifdef TPM_TRACE
  917. {
  918. printk("TPM: ");
  919. print_hex(NULL, WRAPPER_OUT_BUF, out_size);
  920. }
  921. #endif
  922. offset = 0;
  923. LOAD_INTEGER(WRAPPER_OUT_BUF, offset, *hauth);
  924. LOAD_BLOB_TYPE(WRAPPER_OUT_BUF, offset, nonce_even);
  925. return ret;
  926. }
  927. static uint32_t tpm_osap(uint32_t locality, tpm_entity_type_t ent_type,
  928. uint32_t ent_value, const tpm_nonce_t *odd_osap,
  929. tpm_authhandle_t *hauth, tpm_nonce_t *nonce_even,
  930. tpm_nonce_t *even_osap)
  931. {
  932. uint32_t ret, offset, out_size;
  933. if ( odd_osap == NULL || hauth == NULL ||
  934. nonce_even == NULL || even_osap == NULL )
  935. return TPM_BAD_PARAMETER;
  936. offset = 0;
  937. UNLOAD_INTEGER(WRAPPER_IN_BUF, offset, ent_type);
  938. UNLOAD_INTEGER(WRAPPER_IN_BUF, offset, ent_value);
  939. UNLOAD_BLOB_TYPE(WRAPPER_IN_BUF, offset, odd_osap);
  940. out_size = sizeof(*hauth) + sizeof(*nonce_even) + sizeof(*even_osap);
  941. ret = tpm_submit_cmd(locality, TPM_ORD_OSAP, offset, &out_size);
  942. #ifdef TPM_TRACE
  943. printk("TPM: start OSAP, return value = %08X\n", ret);
  944. #endif
  945. if ( ret != TPM_SUCCESS ) {
  946. printk("TPM: start OSAP, return value = %08X\n", ret);
  947. return ret;
  948. }
  949. #ifdef TPM_TRACE
  950. {
  951. printk("TPM: ");
  952. print_hex(NULL, WRAPPER_OUT_BUF, out_size);
  953. }
  954. #endif
  955. offset = 0;
  956. LOAD_INTEGER(WRAPPER_OUT_BUF, offset, *hauth);
  957. LOAD_BLOB_TYPE(WRAPPER_OUT_BUF, offset, nonce_even);
  958. LOAD_BLOB_TYPE(WRAPPER_OUT_BUF, offset, even_osap);
  959. return ret;
  960. }
  961. static uint32_t _tpm_seal(uint32_t locality, tpm_key_handle_t hkey,
  962. const tpm_encauth_t *enc_auth, uint32_t pcr_info_size,
  963. const tpm_pcr_info_long_t *pcr_info, uint32_t in_data_size,
  964. const uint8_t *in_data,
  965. tpm_authhandle_t hauth, const tpm_nonce_t *nonce_odd,
  966. uint8_t *cont_session, const tpm_authdata_t *pub_auth,
  967. uint32_t *sealed_data_size, uint8_t *sealed_data,
  968. tpm_nonce_t *nonce_even, tpm_authdata_t *res_auth)
  969. {
  970. uint32_t ret, offset, out_size;
  971. if ( enc_auth == NULL || pcr_info == NULL || in_data == NULL ||
  972. nonce_odd == NULL || cont_session == NULL || pub_auth == NULL ||
  973. sealed_data_size == NULL || sealed_data == NULL ||
  974. nonce_even == NULL || res_auth == NULL ) {
  975. printk("TPM: _tpm_seal() bad parameter\n");
  976. return TPM_BAD_PARAMETER;
  977. }
  978. offset = 0;
  979. UNLOAD_INTEGER(WRAPPER_IN_BUF, offset, hkey);
  980. UNLOAD_BLOB_TYPE(WRAPPER_IN_BUF, offset, enc_auth);
  981. UNLOAD_INTEGER(WRAPPER_IN_BUF, offset, pcr_info_size);
  982. UNLOAD_PCR_INFO_LONG(WRAPPER_IN_BUF, offset, pcr_info);
  983. UNLOAD_INTEGER(WRAPPER_IN_BUF, offset, in_data_size);
  984. UNLOAD_BLOB(WRAPPER_IN_BUF, offset, in_data, in_data_size);
  985. UNLOAD_INTEGER(WRAPPER_IN_BUF, offset, hauth);
  986. UNLOAD_BLOB_TYPE(WRAPPER_IN_BUF, offset, nonce_odd);
  987. UNLOAD_INTEGER(WRAPPER_IN_BUF, offset, *cont_session);
  988. UNLOAD_BLOB_TYPE(WRAPPER_IN_BUF, offset, pub_auth);
  989. out_size = WRAPPER_OUT_MAX_SIZE;
  990. ret = tpm_submit_cmd_auth1(locality, TPM_ORD_SEAL, offset, &out_size);
  991. #ifdef TPM_TRACE
  992. printk("TPM: seal data, return value = %08X\n", ret);
  993. #endif
  994. if ( ret != TPM_SUCCESS ) {
  995. printk("TPM: seal data, return value = %08X\n", ret);
  996. return ret;
  997. }
  998. #ifdef TPM_TRACE
  999. {
  1000. printk("TPM: ");
  1001. print_hex(NULL, WRAPPER_OUT_BUF, out_size);
  1002. }
  1003. #endif
  1004. if ( *sealed_data_size <
  1005. ( out_size - sizeof(*nonce_even) - sizeof(*cont_session)
  1006. - sizeof(*res_auth) ) ) {
  1007. printk("TPM: sealed blob is too small\n");
  1008. return TPM_NOSPACE;
  1009. }
  1010. offset = 0;
  1011. LOAD_STORED_DATA12(WRAPPER_OUT_BUF, offset, sealed_data);
  1012. *sealed_data_size = offset;
  1013. LOAD_BLOB_TYPE(WRAPPER_OUT_BUF, offset, nonce_even);
  1014. LOAD_INTEGER(WRAPPER_OUT_BUF, offset, *cont_session);
  1015. LOAD_BLOB_TYPE(WRAPPER_OUT_BUF, offset, res_auth);
  1016. return ret;
  1017. }
  1018. static uint32_t _tpm_unseal(uint32_t locality, tpm_key_handle_t hkey,
  1019. const uint8_t *in_data,
  1020. tpm_authhandle_t hauth, const tpm_nonce_t *nonce_odd,
  1021. uint8_t *cont_session, const tpm_authdata_t *auth,
  1022. tpm_authhandle_t hauth_d, const tpm_nonce_t *nonce_odd_d,
  1023. uint8_t *cont_session_d, const tpm_authdata_t *auth_d,
  1024. uint32_t *secret_size, uint8_t *secret,
  1025. tpm_nonce_t *nonce_even, tpm_authdata_t *res_auth,
  1026. tpm_nonce_t *nonce_even_d, tpm_authdata_t *res_auth_d)
  1027. {
  1028. uint32_t ret, offset, out_size;
  1029. if ( in_data == NULL || nonce_odd == NULL || cont_session == NULL ||
  1030. auth == NULL || nonce_odd_d == NULL || cont_session_d == NULL ||
  1031. auth_d == NULL || secret_size == NULL || secret == NULL ||
  1032. nonce_even == NULL || res_auth == NULL || nonce_even_d == NULL ||
  1033. res_auth_d == NULL ) {
  1034. printk("TPM: _tpm_unseal() bad parameter\n");
  1035. return TPM_BAD_PARAMETER;
  1036. }
  1037. offset = 0;
  1038. UNLOAD_INTEGER(WRAPPER_IN_BUF, offset, hkey);
  1039. UNLOAD_STORED_DATA12(WRAPPER_IN_BUF, offset, in_data);
  1040. UNLOAD_INTEGER(WRAPPER_IN_BUF, offset, hauth);
  1041. UNLOAD_BLOB_TYPE(WRAPPER_IN_BUF, offset, nonce_odd);
  1042. UNLOAD_INTEGER(WRAPPER_IN_BUF, offset, *cont_session);
  1043. UNLOAD_BLOB_TYPE(WRAPPER_IN_BUF, offset, auth);
  1044. UNLOAD_INTEGER(WRAPPER_IN_BUF, offset, hauth_d);
  1045. UNLOAD_BLOB_TYPE(WRAPPER_IN_BUF, offset, nonce_odd_d);
  1046. UNLOAD_INTEGER(WRAPPER_IN_BUF, offset, *cont_session_d);
  1047. UNLOAD_BLOB_TYPE(WRAPPER_IN_BUF, offset, auth_d);
  1048. out_size = WRAPPER_OUT_MAX_SIZE;
  1049. ret = tpm_submit_cmd_auth2(locality, TPM_ORD_UNSEAL, offset, &out_size);
  1050. #ifdef TPM_TRACE
  1051. printk("TPM: unseal data, return value = %08X\n", ret);
  1052. #endif
  1053. if ( ret != TPM_SUCCESS ) {
  1054. printk("TPM: unseal data, return value = %08X\n", ret);
  1055. return ret;
  1056. }
  1057. #ifdef TPM_TRACE
  1058. {
  1059. printk("TPM: ");
  1060. print_hex(NULL, WRAPPER_OUT_BUF, out_size);
  1061. }
  1062. #endif
  1063. if ( *secret_size <
  1064. ( out_size - sizeof(*secret_size) - sizeof(*nonce_even)
  1065. - sizeof(*cont_session) - sizeof(*res_auth) - sizeof(*nonce_even_d)
  1066. - sizeof(*cont_session_d) - sizeof(*res_auth_d) ) ) {
  1067. printk("TPM: unsealed data too small\n");
  1068. return TPM_NOSPACE;
  1069. }
  1070. offset = 0;
  1071. LOAD_INTEGER(WRAPPER_OUT_BUF, offset, *secret_size);
  1072. LOAD_BLOB(WRAPPER_OUT_BUF, offset, secret, *secret_size);
  1073. LOAD_BLOB_TYPE(WRAPPER_OUT_BUF, offset, nonce_even);
  1074. LOAD_INTEGER(WRAPPER_OUT_BUF, offset, *cont_session);
  1075. LOAD_BLOB_TYPE(WRAPPER_OUT_BUF, offset, res_auth);
  1076. LOAD_BLOB_TYPE(WRAPPER_OUT_BUF, offset, nonce_even_d);
  1077. LOAD_INTEGER(WRAPPER_OUT_BUF, offset, *cont_session_d);
  1078. LOAD_BLOB_TYPE(WRAPPER_OUT_BUF, offset, res_auth_d);
  1079. return ret;
  1080. }
  1081. #define XOR_BLOB_TYPE(data, pad) {\
  1082. for ( uint32_t i = 0; i < sizeof(*(data)); i++ ) \
  1083. ((uint8_t *)data)[i] ^= ((uint8_t *)pad)[i % sizeof(*(pad))];\
  1084. }
  1085. static const tpm_authdata_t srk_authdata =
  1086. {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
  1087. static const tpm_authdata_t blob_authdata =
  1088. {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
  1089. static uint32_t _tpm_wrap_seal(uint32_t locality,
  1090. const tpm_pcr_info_long_t *pcr_info,
  1091. uint32_t in_data_size, const uint8_t *in_data,
  1092. uint32_t *sealed_data_size, uint8_t *sealed_data)
  1093. {
  1094. uint32_t ret;
  1095. tpm_nonce_t odd_osap, even_osap, nonce_even, nonce_odd;
  1096. tpm_authhandle_t hauth;
  1097. tpm_authdata_t shared_secret, pub_auth, res_auth;
  1098. tpm_encauth_t enc_auth;
  1099. uint8_t cont_session = false;
  1100. tpm_key_handle_t hkey = TPM_KH_SRK;
  1101. uint32_t pcr_info_size = sizeof(*pcr_info);
  1102. uint32_t offset;
  1103. uint32_t ordinal = TPM_ORD_SEAL;
  1104. tpm_digest_t digest;
  1105. /* skip generate nonce for odd_osap, just use the random value in stack */
  1106. /* establish a osap session */
  1107. ret = tpm_osap(locality, TPM_ET_SRK, TPM_KH_SRK, &odd_osap, &hauth,
  1108. &nonce_even, &even_osap);
  1109. if ( ret != TPM_SUCCESS )
  1110. return ret;
  1111. /* calculate the shared secret
  1112. shared-secret = HMAC(srk_auth, even_osap || odd_osap) */
  1113. offset = 0;
  1114. UNLOAD_BLOB_TYPE(WRAPPER_IN_BUF, offset, &even_osap);
  1115. UNLOAD_BLOB_TYPE(WRAPPER_IN_BUF, offset, &odd_osap);
  1116. hmac((uint8_t *)&srk_authdata, WRAPPER_IN_BUF, offset,
  1117. (uint8_t *)&shared_secret);
  1118. /* generate ecrypted authdata for data
  1119. enc_auth = XOR(authdata, sha1(shared_secret || last_even_nonce)) */
  1120. offset = 0;
  1121. UNLOAD_BLOB_TYPE(WRAPPER_IN_BUF, offset, &shared_secret);
  1122. UNLOAD_BLOB_TYPE(WRAPPER_IN_BUF, offset, &nonce_even);
  1123. sha1_buffer(WRAPPER_IN_BUF, offset, (uint8_t *)&digest);
  1124. memcpy(&enc_auth, &blob_authdata, sizeof(blob_authdata));
  1125. XOR_BLOB_TYPE(&enc_auth, &digest);
  1126. /* skip generate nonce for nonce_odd, just use the random value in stack */
  1127. /* calculate authdata */
  1128. /* in_param_digest = sha1(1S ~ 6S) */
  1129. offset = 0;
  1130. UNLOAD_INTEGER(WRAPPER_IN_BUF, offset, ordinal);
  1131. UNLOAD_BLOB_TYPE(WRAPPER_IN_BUF, offset, &enc_auth);
  1132. UNLOAD_INTEGER(WRAPPER_IN_BUF, offset, pcr_info_size);
  1133. UNLOAD_PCR_INFO_LONG(WRAPPER_IN_BUF, offset, pcr_info);
  1134. UNLOAD_INTEGER(WRAPPER_IN_BUF, offset, in_data_size);
  1135. UNLOAD_BLOB(WRAPPER_IN_BUF, offset, in_data, in_data_size);
  1136. sha1_buffer(WRAPPER_IN_BUF, offset, (uint8_t *)&digest);
  1137. /* authdata = hmac(key, in_param_digest || auth_params) */
  1138. offset = 0;
  1139. UNLOAD_BLOB_TYPE(WRAPPER_IN_BUF, offset, &digest);
  1140. UNLOAD_BLOB_TYPE(WRAPPER_IN_BUF, offset, &nonce_even);
  1141. UNLOAD_BLOB_TYPE(WRAPPER_IN_BUF, offset, &nonce_odd);
  1142. UNLOAD_INTEGER(WRAPPER_IN_BUF, offset, cont_session);
  1143. hmac((uint8_t *)&shared_secret, WRAPPER_IN_BUF, offset,
  1144. (uint8_t *)&pub_auth);
  1145. /* call the simple seal function */
  1146. ret = _tpm_seal(locality, hkey, (const tpm_encauth_t *)&enc_auth,
  1147. pcr_info_size, pcr_info, in_data_size, in_data,
  1148. hauth, &nonce_odd, &cont_session,
  1149. (const tpm_authdata_t *)&pub_auth,
  1150. sealed_data_size, sealed_data,
  1151. &nonce_even, &res_auth);
  1152. /* skip check for res_auth */
  1153. return ret;
  1154. }
  1155. static uint32_t _tpm_wrap_unseal(uint32_t locality, const uint8_t *in_data,
  1156. uint32_t *secret_size, uint8_t *secret)
  1157. {
  1158. uint32_t ret;
  1159. tpm_nonce_t odd_osap, even_osap;
  1160. tpm_nonce_t nonce_even, nonce_odd, nonce_even_d, nonce_odd_d;
  1161. tpm_authhandle_t hauth, hauth_d;
  1162. tpm_authdata_t shared_secret;
  1163. tpm_authdata_t pub_auth, res_auth, pub_auth_d, res_auth_d;
  1164. uint8_t cont_session = false, cont_session_d = false;
  1165. tpm_key_handle_t hkey = TPM_KH_SRK;
  1166. uint32_t offset;
  1167. uint32_t ordinal = TPM_ORD_UNSEAL;
  1168. tpm_digest_t digest;
  1169. /* skip generate nonce for odd_osap, just use the random value in stack */
  1170. /* establish a osap session */
  1171. ret = tpm_osap(locality, TPM_ET_SRK, TPM_KH_SRK, &odd_osap, &hauth,
  1172. &nonce_even, &even_osap);
  1173. if ( ret != TPM_SUCCESS )
  1174. return ret;
  1175. /* calculate the shared secret
  1176. shared-secret = HMAC(auth, even_osap || odd_osap) */
  1177. offset = 0;
  1178. UNLOAD_BLOB_TYPE(WRAPPER_IN_BUF, offset, &even_osap);
  1179. UNLOAD_BLOB_TYPE(WRAPPER_IN_BUF, offset, &odd_osap);
  1180. hmac((uint8_t *)&srk_authdata, WRAPPER_IN_BUF, offset,
  1181. (uint8_t *)&shared_secret);
  1182. /* establish a oiap session */
  1183. ret = tpm_oiap(locality, &hauth_d, &nonce_even_d);
  1184. if ( ret != TPM_SUCCESS )
  1185. return ret;
  1186. /* skip generate nonce_odd & nonce_odd_d, just use the random values */
  1187. /* calculate authdata */
  1188. /* in_param_digest = sha1(1S ~ 6S) */
  1189. offset = 0;
  1190. UNLOAD_INTEGER(WRAPPER_IN_BUF, offset, ordinal);
  1191. UNLOAD_STORED_DATA12(WRAPPER_IN_BUF, offset, in_data);
  1192. sha1_buffer(WRAPPER_IN_BUF, offset, (uint8_t *)&digest);
  1193. /* authdata1 = hmac(key, in_param_digest || auth_params1) */
  1194. offset = 0;
  1195. UNLOAD_BLOB_TYPE(WRAPPER_IN_BUF, offset, &digest);
  1196. UNLOAD_BLOB_TYPE(WRAPPER_IN_BUF, offset, &nonce_even);
  1197. UNLOAD_BLOB_TYPE(WRAPPER_IN_BUF, offset, &nonce_odd);
  1198. UNLOAD_INTEGER(WRAPPER_IN_BUF, offset, cont_session);
  1199. hmac((uint8_t *)&shared_secret, WRAPPER_IN_BUF, offset,
  1200. (uint8_t *)&pub_auth);
  1201. /* authdata2 = hmac(key, in_param_digest || auth_params2) */
  1202. offset = 0;
  1203. UNLOAD_BLOB_TYPE(WRAPPER_IN_BUF, offset, &digest);
  1204. UNLOAD_BLOB_TYPE(WRAPPER_IN_BUF, offset, &nonce_even_d);
  1205. UNLOAD_BLOB_TYPE(WRAPPER_IN_BUF, offset, &nonce_odd_d);
  1206. UNLOAD_INTEGER(WRAPPER_IN_BUF, offset, cont_session_d);
  1207. hmac((uint8_t *)&blob_authdata, WRAPPER_IN_BUF, offset,
  1208. (uint8_t *)&pub_auth_d);
  1209. /* call the simple seal function */
  1210. ret = _tpm_unseal(locality, hkey, in_data,
  1211. hauth, &nonce_odd, &cont_session,
  1212. (const tpm_authdata_t *)&pub_auth,
  1213. hauth_d, &nonce_odd_d, &cont_session_d,
  1214. (const tpm_authdata_t *)&pub_auth_d,
  1215. secret_size, secret,
  1216. &nonce_even, &res_auth, &nonce_even_d, &res_auth_d);
  1217. /* skip check for res_auth */
  1218. return ret;
  1219. }
  1220. static bool init_pcr_info(uint32_t locality,
  1221. tpm_locality_selection_t release_locs,
  1222. uint32_t nr_create, const uint8_t indcs_create[],
  1223. uint32_t nr_release, const uint8_t indcs_release[],
  1224. const tpm_pcr_value_t *values_release[],
  1225. tpm_pcr_info_long_t *pcr_info)
  1226. {
  1227. uint32_t offset;
  1228. uint32_t i, blob_size;
  1229. static tpm_locality_selection_t localities[TPM_NR_LOCALITIES] = {
  1230. TPM_LOC_ZERO, TPM_LOC_

Large files files are truncated, but you can click here to view the full file