tpm.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970
  1. /*
  2. * Copyright (c) 2013 The Chromium OS Authors.
  3. * Coypright (c) 2013 Guntermann & Drunck GmbH
  4. *
  5. * SPDX-License-Identifier: GPL-2.0+
  6. */
  7. #include <common.h>
  8. #include <dm.h>
  9. #include <tpm.h>
  10. #include <asm/unaligned.h>
  11. #include <u-boot/sha1.h>
  12. /* Internal error of TPM command library */
  13. #define TPM_LIB_ERROR ((uint32_t)~0u)
  14. /* Useful constants */
  15. enum {
  16. COMMAND_BUFFER_SIZE = 256,
  17. TPM_REQUEST_HEADER_LENGTH = 10,
  18. TPM_RESPONSE_HEADER_LENGTH = 10,
  19. PCR_DIGEST_LENGTH = 20,
  20. DIGEST_LENGTH = 20,
  21. TPM_REQUEST_AUTH_LENGTH = 45,
  22. TPM_RESPONSE_AUTH_LENGTH = 41,
  23. /* some max lengths, valid for RSA keys <= 2048 bits */
  24. TPM_KEY12_MAX_LENGTH = 618,
  25. TPM_PUBKEY_MAX_LENGTH = 288,
  26. };
  27. #ifdef CONFIG_TPM_AUTH_SESSIONS
  28. #ifndef CONFIG_SHA1
  29. #error "TPM_AUTH_SESSIONS require SHA1 to be configured, too"
  30. #endif /* !CONFIG_SHA1 */
  31. struct session_data {
  32. int valid;
  33. uint32_t handle;
  34. uint8_t nonce_even[DIGEST_LENGTH];
  35. uint8_t nonce_odd[DIGEST_LENGTH];
  36. };
  37. static struct session_data oiap_session = {0, };
  38. #endif /* CONFIG_TPM_AUTH_SESSIONS */
  39. /**
  40. * Pack data into a byte string. The data types are specified in
  41. * the format string: 'b' means unsigned byte, 'w' unsigned word,
  42. * 'd' unsigned double word, and 's' byte string. The data are a
  43. * series of offsets and values (for type byte string there are also
  44. * lengths). The data values are packed into the byte string
  45. * sequentially, and so a latter value could over-write a former
  46. * value.
  47. *
  48. * @param str output string
  49. * @param size size of output string
  50. * @param format format string
  51. * @param ... data points
  52. * @return 0 on success, non-0 on error
  53. */
  54. int pack_byte_string(uint8_t *str, size_t size, const char *format, ...)
  55. {
  56. va_list args;
  57. size_t offset = 0, length = 0;
  58. uint8_t *data = NULL;
  59. uint32_t value = 0;
  60. va_start(args, format);
  61. for (; *format; format++) {
  62. switch (*format) {
  63. case 'b':
  64. offset = va_arg(args, size_t);
  65. value = va_arg(args, int);
  66. length = 1;
  67. break;
  68. case 'w':
  69. offset = va_arg(args, size_t);
  70. value = va_arg(args, int);
  71. length = 2;
  72. break;
  73. case 'd':
  74. offset = va_arg(args, size_t);
  75. value = va_arg(args, uint32_t);
  76. length = 4;
  77. break;
  78. case 's':
  79. offset = va_arg(args, size_t);
  80. data = va_arg(args, uint8_t *);
  81. length = va_arg(args, uint32_t);
  82. break;
  83. default:
  84. debug("Couldn't recognize format string\n");
  85. return -1;
  86. }
  87. if (offset + length > size)
  88. return -1;
  89. switch (*format) {
  90. case 'b':
  91. str[offset] = value;
  92. break;
  93. case 'w':
  94. put_unaligned_be16(value, str + offset);
  95. break;
  96. case 'd':
  97. put_unaligned_be32(value, str + offset);
  98. break;
  99. case 's':
  100. memcpy(str + offset, data, length);
  101. break;
  102. }
  103. }
  104. va_end(args);
  105. return 0;
  106. }
  107. /**
  108. * Unpack data from a byte string. The data types are specified in
  109. * the format string: 'b' means unsigned byte, 'w' unsigned word,
  110. * 'd' unsigned double word, and 's' byte string. The data are a
  111. * series of offsets and pointers (for type byte string there are also
  112. * lengths).
  113. *
  114. * @param str output string
  115. * @param size size of output string
  116. * @param format format string
  117. * @param ... data points
  118. * @return 0 on success, non-0 on error
  119. */
  120. int unpack_byte_string(const uint8_t *str, size_t size, const char *format, ...)
  121. {
  122. va_list args;
  123. size_t offset = 0, length = 0;
  124. uint8_t *ptr8 = NULL;
  125. uint16_t *ptr16 = NULL;
  126. uint32_t *ptr32 = NULL;
  127. va_start(args, format);
  128. for (; *format; format++) {
  129. switch (*format) {
  130. case 'b':
  131. offset = va_arg(args, size_t);
  132. ptr8 = va_arg(args, uint8_t *);
  133. length = 1;
  134. break;
  135. case 'w':
  136. offset = va_arg(args, size_t);
  137. ptr16 = va_arg(args, uint16_t *);
  138. length = 2;
  139. break;
  140. case 'd':
  141. offset = va_arg(args, size_t);
  142. ptr32 = va_arg(args, uint32_t *);
  143. length = 4;
  144. break;
  145. case 's':
  146. offset = va_arg(args, size_t);
  147. ptr8 = va_arg(args, uint8_t *);
  148. length = va_arg(args, uint32_t);
  149. break;
  150. default:
  151. debug("Couldn't recognize format string\n");
  152. return -1;
  153. }
  154. if (offset + length > size)
  155. return -1;
  156. switch (*format) {
  157. case 'b':
  158. *ptr8 = str[offset];
  159. break;
  160. case 'w':
  161. *ptr16 = get_unaligned_be16(str + offset);
  162. break;
  163. case 'd':
  164. *ptr32 = get_unaligned_be32(str + offset);
  165. break;
  166. case 's':
  167. memcpy(ptr8, str + offset, length);
  168. break;
  169. }
  170. }
  171. va_end(args);
  172. return 0;
  173. }
  174. /**
  175. * Get TPM command size.
  176. *
  177. * @param command byte string of TPM command
  178. * @return command size of the TPM command
  179. */
  180. static uint32_t tpm_command_size(const void *command)
  181. {
  182. const size_t command_size_offset = 2;
  183. return get_unaligned_be32(command + command_size_offset);
  184. }
  185. /**
  186. * Get TPM response return code, which is one of TPM_RESULT values.
  187. *
  188. * @param response byte string of TPM response
  189. * @return return code of the TPM response
  190. */
  191. static uint32_t tpm_return_code(const void *response)
  192. {
  193. const size_t return_code_offset = 6;
  194. return get_unaligned_be32(response + return_code_offset);
  195. }
  196. /**
  197. * Send a TPM command and return response's return code, and optionally
  198. * return response to caller.
  199. *
  200. * @param command byte string of TPM command
  201. * @param response output buffer for TPM response, or NULL if the
  202. * caller does not care about it
  203. * @param size_ptr output buffer size (input parameter) and TPM
  204. * response length (output parameter); this parameter
  205. * is a bidirectional
  206. * @return return code of the TPM response
  207. */
  208. static uint32_t tpm_sendrecv_command(const void *command,
  209. void *response, size_t *size_ptr)
  210. {
  211. struct udevice *dev;
  212. int ret;
  213. uint8_t response_buffer[COMMAND_BUFFER_SIZE];
  214. size_t response_length;
  215. uint32_t err;
  216. if (response) {
  217. response_length = *size_ptr;
  218. } else {
  219. response = response_buffer;
  220. response_length = sizeof(response_buffer);
  221. }
  222. ret = uclass_first_device_err(UCLASS_TPM, &dev);
  223. if (ret)
  224. return ret;
  225. err = tpm_xfer(dev, command, tpm_command_size(command),
  226. response, &response_length);
  227. if (err < 0)
  228. return TPM_LIB_ERROR;
  229. if (size_ptr)
  230. *size_ptr = response_length;
  231. return tpm_return_code(response);
  232. }
  233. int tpm_init(void)
  234. {
  235. int err;
  236. struct udevice *dev;
  237. err = uclass_first_device_err(UCLASS_TPM, &dev);
  238. if (err)
  239. return err;
  240. return tpm_open(dev);
  241. }
  242. uint32_t tpm_startup(enum tpm_startup_type mode)
  243. {
  244. const uint8_t command[12] = {
  245. 0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0x99, 0x0, 0x0,
  246. };
  247. const size_t mode_offset = 10;
  248. uint8_t buf[COMMAND_BUFFER_SIZE];
  249. if (pack_byte_string(buf, sizeof(buf), "sw",
  250. 0, command, sizeof(command),
  251. mode_offset, mode))
  252. return TPM_LIB_ERROR;
  253. return tpm_sendrecv_command(buf, NULL, NULL);
  254. }
  255. uint32_t tpm_self_test_full(void)
  256. {
  257. const uint8_t command[10] = {
  258. 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x50,
  259. };
  260. return tpm_sendrecv_command(command, NULL, NULL);
  261. }
  262. uint32_t tpm_continue_self_test(void)
  263. {
  264. const uint8_t command[10] = {
  265. 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x53,
  266. };
  267. return tpm_sendrecv_command(command, NULL, NULL);
  268. }
  269. uint32_t tpm_nv_define_space(uint32_t index, uint32_t perm, uint32_t size)
  270. {
  271. const uint8_t command[101] = {
  272. 0x0, 0xc1, /* TPM_TAG */
  273. 0x0, 0x0, 0x0, 0x65, /* parameter size */
  274. 0x0, 0x0, 0x0, 0xcc, /* TPM_COMMAND_CODE */
  275. /* TPM_NV_DATA_PUBLIC->... */
  276. 0x0, 0x18, /* ...->TPM_STRUCTURE_TAG */
  277. 0, 0, 0, 0, /* ...->TPM_NV_INDEX */
  278. /* TPM_NV_DATA_PUBLIC->TPM_PCR_INFO_SHORT */
  279. 0x0, 0x3,
  280. 0, 0, 0,
  281. 0x1f,
  282. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  283. /* TPM_NV_DATA_PUBLIC->TPM_PCR_INFO_SHORT */
  284. 0x0, 0x3,
  285. 0, 0, 0,
  286. 0x1f,
  287. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  288. /* TPM_NV_ATTRIBUTES->... */
  289. 0x0, 0x17, /* ...->TPM_STRUCTURE_TAG */
  290. 0, 0, 0, 0, /* ...->attributes */
  291. /* End of TPM_NV_ATTRIBUTES */
  292. 0, /* bReadSTClear */
  293. 0, /* bWriteSTClear */
  294. 0, /* bWriteDefine */
  295. 0, 0, 0, 0, /* size */
  296. };
  297. const size_t index_offset = 12;
  298. const size_t perm_offset = 70;
  299. const size_t size_offset = 77;
  300. uint8_t buf[COMMAND_BUFFER_SIZE];
  301. if (pack_byte_string(buf, sizeof(buf), "sddd",
  302. 0, command, sizeof(command),
  303. index_offset, index,
  304. perm_offset, perm,
  305. size_offset, size))
  306. return TPM_LIB_ERROR;
  307. return tpm_sendrecv_command(buf, NULL, NULL);
  308. }
  309. uint32_t tpm_nv_read_value(uint32_t index, void *data, uint32_t count)
  310. {
  311. const uint8_t command[22] = {
  312. 0x0, 0xc1, 0x0, 0x0, 0x0, 0x16, 0x0, 0x0, 0x0, 0xcf,
  313. };
  314. const size_t index_offset = 10;
  315. const size_t length_offset = 18;
  316. const size_t data_size_offset = 10;
  317. const size_t data_offset = 14;
  318. uint8_t buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
  319. size_t response_length = sizeof(response);
  320. uint32_t data_size;
  321. uint32_t err;
  322. if (pack_byte_string(buf, sizeof(buf), "sdd",
  323. 0, command, sizeof(command),
  324. index_offset, index,
  325. length_offset, count))
  326. return TPM_LIB_ERROR;
  327. err = tpm_sendrecv_command(buf, response, &response_length);
  328. if (err)
  329. return err;
  330. if (unpack_byte_string(response, response_length, "d",
  331. data_size_offset, &data_size))
  332. return TPM_LIB_ERROR;
  333. if (data_size > count)
  334. return TPM_LIB_ERROR;
  335. if (unpack_byte_string(response, response_length, "s",
  336. data_offset, data, data_size))
  337. return TPM_LIB_ERROR;
  338. return 0;
  339. }
  340. uint32_t tpm_nv_write_value(uint32_t index, const void *data, uint32_t length)
  341. {
  342. const uint8_t command[256] = {
  343. 0x0, 0xc1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xcd,
  344. };
  345. const size_t command_size_offset = 2;
  346. const size_t index_offset = 10;
  347. const size_t length_offset = 18;
  348. const size_t data_offset = 22;
  349. const size_t write_info_size = 12;
  350. const uint32_t total_length =
  351. TPM_REQUEST_HEADER_LENGTH + write_info_size + length;
  352. uint8_t buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
  353. size_t response_length = sizeof(response);
  354. uint32_t err;
  355. if (pack_byte_string(buf, sizeof(buf), "sddds",
  356. 0, command, sizeof(command),
  357. command_size_offset, total_length,
  358. index_offset, index,
  359. length_offset, length,
  360. data_offset, data, length))
  361. return TPM_LIB_ERROR;
  362. err = tpm_sendrecv_command(buf, response, &response_length);
  363. if (err)
  364. return err;
  365. return 0;
  366. }
  367. uint32_t tpm_extend(uint32_t index, const void *in_digest, void *out_digest)
  368. {
  369. const uint8_t command[34] = {
  370. 0x0, 0xc1, 0x0, 0x0, 0x0, 0x22, 0x0, 0x0, 0x0, 0x14,
  371. };
  372. const size_t index_offset = 10;
  373. const size_t in_digest_offset = 14;
  374. const size_t out_digest_offset = 10;
  375. uint8_t buf[COMMAND_BUFFER_SIZE];
  376. uint8_t response[TPM_RESPONSE_HEADER_LENGTH + PCR_DIGEST_LENGTH];
  377. size_t response_length = sizeof(response);
  378. uint32_t err;
  379. if (pack_byte_string(buf, sizeof(buf), "sds",
  380. 0, command, sizeof(command),
  381. index_offset, index,
  382. in_digest_offset, in_digest,
  383. PCR_DIGEST_LENGTH))
  384. return TPM_LIB_ERROR;
  385. err = tpm_sendrecv_command(buf, response, &response_length);
  386. if (err)
  387. return err;
  388. if (unpack_byte_string(response, response_length, "s",
  389. out_digest_offset, out_digest,
  390. PCR_DIGEST_LENGTH))
  391. return TPM_LIB_ERROR;
  392. return 0;
  393. }
  394. uint32_t tpm_pcr_read(uint32_t index, void *data, size_t count)
  395. {
  396. const uint8_t command[14] = {
  397. 0x0, 0xc1, 0x0, 0x0, 0x0, 0xe, 0x0, 0x0, 0x0, 0x15,
  398. };
  399. const size_t index_offset = 10;
  400. const size_t out_digest_offset = 10;
  401. uint8_t buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
  402. size_t response_length = sizeof(response);
  403. uint32_t err;
  404. if (count < PCR_DIGEST_LENGTH)
  405. return TPM_LIB_ERROR;
  406. if (pack_byte_string(buf, sizeof(buf), "sd",
  407. 0, command, sizeof(command),
  408. index_offset, index))
  409. return TPM_LIB_ERROR;
  410. err = tpm_sendrecv_command(buf, response, &response_length);
  411. if (err)
  412. return err;
  413. if (unpack_byte_string(response, response_length, "s",
  414. out_digest_offset, data, PCR_DIGEST_LENGTH))
  415. return TPM_LIB_ERROR;
  416. return 0;
  417. }
  418. uint32_t tpm_tsc_physical_presence(uint16_t presence)
  419. {
  420. const uint8_t command[12] = {
  421. 0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x40, 0x0, 0x0, 0xa, 0x0, 0x0,
  422. };
  423. const size_t presence_offset = 10;
  424. uint8_t buf[COMMAND_BUFFER_SIZE];
  425. if (pack_byte_string(buf, sizeof(buf), "sw",
  426. 0, command, sizeof(command),
  427. presence_offset, presence))
  428. return TPM_LIB_ERROR;
  429. return tpm_sendrecv_command(buf, NULL, NULL);
  430. }
  431. uint32_t tpm_read_pubek(void *data, size_t count)
  432. {
  433. const uint8_t command[30] = {
  434. 0x0, 0xc1, 0x0, 0x0, 0x0, 0x1e, 0x0, 0x0, 0x0, 0x7c,
  435. };
  436. const size_t response_size_offset = 2;
  437. const size_t data_offset = 10;
  438. const size_t header_and_checksum_size = TPM_RESPONSE_HEADER_LENGTH + 20;
  439. uint8_t response[COMMAND_BUFFER_SIZE + TPM_PUBEK_SIZE];
  440. size_t response_length = sizeof(response);
  441. uint32_t data_size;
  442. uint32_t err;
  443. err = tpm_sendrecv_command(command, response, &response_length);
  444. if (err)
  445. return err;
  446. if (unpack_byte_string(response, response_length, "d",
  447. response_size_offset, &data_size))
  448. return TPM_LIB_ERROR;
  449. if (data_size < header_and_checksum_size)
  450. return TPM_LIB_ERROR;
  451. data_size -= header_and_checksum_size;
  452. if (data_size > count)
  453. return TPM_LIB_ERROR;
  454. if (unpack_byte_string(response, response_length, "s",
  455. data_offset, data, data_size))
  456. return TPM_LIB_ERROR;
  457. return 0;
  458. }
  459. uint32_t tpm_force_clear(void)
  460. {
  461. const uint8_t command[10] = {
  462. 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x5d,
  463. };
  464. return tpm_sendrecv_command(command, NULL, NULL);
  465. }
  466. uint32_t tpm_physical_enable(void)
  467. {
  468. const uint8_t command[10] = {
  469. 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x6f,
  470. };
  471. return tpm_sendrecv_command(command, NULL, NULL);
  472. }
  473. uint32_t tpm_physical_disable(void)
  474. {
  475. const uint8_t command[10] = {
  476. 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x70,
  477. };
  478. return tpm_sendrecv_command(command, NULL, NULL);
  479. }
  480. uint32_t tpm_physical_set_deactivated(uint8_t state)
  481. {
  482. const uint8_t command[11] = {
  483. 0x0, 0xc1, 0x0, 0x0, 0x0, 0xb, 0x0, 0x0, 0x0, 0x72,
  484. };
  485. const size_t state_offset = 10;
  486. uint8_t buf[COMMAND_BUFFER_SIZE];
  487. if (pack_byte_string(buf, sizeof(buf), "sb",
  488. 0, command, sizeof(command),
  489. state_offset, state))
  490. return TPM_LIB_ERROR;
  491. return tpm_sendrecv_command(buf, NULL, NULL);
  492. }
  493. uint32_t tpm_get_capability(uint32_t cap_area, uint32_t sub_cap,
  494. void *cap, size_t count)
  495. {
  496. const uint8_t command[22] = {
  497. 0x0, 0xc1, /* TPM_TAG */
  498. 0x0, 0x0, 0x0, 0x16, /* parameter size */
  499. 0x0, 0x0, 0x0, 0x65, /* TPM_COMMAND_CODE */
  500. 0x0, 0x0, 0x0, 0x0, /* TPM_CAPABILITY_AREA */
  501. 0x0, 0x0, 0x0, 0x4, /* subcap size */
  502. 0x0, 0x0, 0x0, 0x0, /* subcap value */
  503. };
  504. const size_t cap_area_offset = 10;
  505. const size_t sub_cap_offset = 18;
  506. const size_t cap_offset = 14;
  507. const size_t cap_size_offset = 10;
  508. uint8_t buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
  509. size_t response_length = sizeof(response);
  510. uint32_t cap_size;
  511. uint32_t err;
  512. if (pack_byte_string(buf, sizeof(buf), "sdd",
  513. 0, command, sizeof(command),
  514. cap_area_offset, cap_area,
  515. sub_cap_offset, sub_cap))
  516. return TPM_LIB_ERROR;
  517. err = tpm_sendrecv_command(buf, response, &response_length);
  518. if (err)
  519. return err;
  520. if (unpack_byte_string(response, response_length, "d",
  521. cap_size_offset, &cap_size))
  522. return TPM_LIB_ERROR;
  523. if (cap_size > response_length || cap_size > count)
  524. return TPM_LIB_ERROR;
  525. if (unpack_byte_string(response, response_length, "s",
  526. cap_offset, cap, cap_size))
  527. return TPM_LIB_ERROR;
  528. return 0;
  529. }
  530. uint32_t tpm_get_permanent_flags(struct tpm_permanent_flags *pflags)
  531. {
  532. const uint8_t command[22] = {
  533. 0x0, 0xc1, /* TPM_TAG */
  534. 0x0, 0x0, 0x0, 0x16, /* parameter size */
  535. 0x0, 0x0, 0x0, 0x65, /* TPM_COMMAND_CODE */
  536. 0x0, 0x0, 0x0, 0x4, /* TPM_CAP_FLAG_PERM */
  537. 0x0, 0x0, 0x0, 0x4, /* subcap size */
  538. 0x0, 0x0, 0x1, 0x8, /* subcap value */
  539. };
  540. uint8_t response[COMMAND_BUFFER_SIZE];
  541. size_t response_length = sizeof(response);
  542. uint32_t err;
  543. err = tpm_sendrecv_command(command, response, &response_length);
  544. if (err)
  545. return err;
  546. memcpy(pflags, response + TPM_HEADER_SIZE, sizeof(*pflags));
  547. return 0;
  548. }
  549. uint32_t tpm_get_permissions(uint32_t index, uint32_t *perm)
  550. {
  551. const uint8_t command[22] = {
  552. 0x0, 0xc1, /* TPM_TAG */
  553. 0x0, 0x0, 0x0, 0x16, /* parameter size */
  554. 0x0, 0x0, 0x0, 0x65, /* TPM_COMMAND_CODE */
  555. 0x0, 0x0, 0x0, 0x11,
  556. 0x0, 0x0, 0x0, 0x4,
  557. };
  558. const size_t index_offset = 18;
  559. const size_t perm_offset = 60;
  560. uint8_t buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
  561. size_t response_length = sizeof(response);
  562. uint32_t err;
  563. if (pack_byte_string(buf, sizeof(buf), "d", 0, command, sizeof(command),
  564. index_offset, index))
  565. return TPM_LIB_ERROR;
  566. err = tpm_sendrecv_command(buf, response, &response_length);
  567. if (err)
  568. return err;
  569. if (unpack_byte_string(response, response_length, "d",
  570. perm_offset, perm))
  571. return TPM_LIB_ERROR;
  572. return 0;
  573. }
  574. #ifdef CONFIG_TPM_AUTH_SESSIONS
  575. /**
  576. * Fill an authentication block in a request.
  577. * This func can create the first as well as the second auth block (for
  578. * double authorized commands).
  579. *
  580. * @param request pointer to the request (w/ uninitialised auth data)
  581. * @param request_len0 length of the request without auth data
  582. * @param handles_len length of the handles area in request
  583. * @param auth_session pointer to the (valid) auth session to be used
  584. * @param request_auth pointer to the auth block of the request to be filled
  585. * @param auth authentication data (HMAC key)
  586. */
  587. static uint32_t create_request_auth(const void *request, size_t request_len0,
  588. size_t handles_len,
  589. struct session_data *auth_session,
  590. void *request_auth, const void *auth)
  591. {
  592. uint8_t hmac_data[DIGEST_LENGTH * 3 + 1];
  593. sha1_context hash_ctx;
  594. const size_t command_code_offset = 6;
  595. const size_t auth_nonce_odd_offset = 4;
  596. const size_t auth_continue_offset = 24;
  597. const size_t auth_auth_offset = 25;
  598. if (!auth_session || !auth_session->valid)
  599. return TPM_LIB_ERROR;
  600. sha1_starts(&hash_ctx);
  601. sha1_update(&hash_ctx, request + command_code_offset, 4);
  602. if (request_len0 > TPM_REQUEST_HEADER_LENGTH + handles_len)
  603. sha1_update(&hash_ctx,
  604. request + TPM_REQUEST_HEADER_LENGTH + handles_len,
  605. request_len0 - TPM_REQUEST_HEADER_LENGTH
  606. - handles_len);
  607. sha1_finish(&hash_ctx, hmac_data);
  608. sha1_starts(&hash_ctx);
  609. sha1_update(&hash_ctx, auth_session->nonce_odd, DIGEST_LENGTH);
  610. sha1_update(&hash_ctx, hmac_data, sizeof(hmac_data));
  611. sha1_finish(&hash_ctx, auth_session->nonce_odd);
  612. if (pack_byte_string(request_auth, TPM_REQUEST_AUTH_LENGTH, "dsb",
  613. 0, auth_session->handle,
  614. auth_nonce_odd_offset, auth_session->nonce_odd,
  615. DIGEST_LENGTH,
  616. auth_continue_offset, 1))
  617. return TPM_LIB_ERROR;
  618. if (pack_byte_string(hmac_data, sizeof(hmac_data), "ss",
  619. DIGEST_LENGTH,
  620. auth_session->nonce_even,
  621. DIGEST_LENGTH,
  622. 2 * DIGEST_LENGTH,
  623. request_auth + auth_nonce_odd_offset,
  624. DIGEST_LENGTH + 1))
  625. return TPM_LIB_ERROR;
  626. sha1_hmac(auth, DIGEST_LENGTH, hmac_data, sizeof(hmac_data),
  627. request_auth + auth_auth_offset);
  628. return TPM_SUCCESS;
  629. }
  630. /**
  631. * Verify an authentication block in a response.
  632. * Since this func updates the nonce_even in the session data it has to be
  633. * called when receiving a succesfull AUTH response.
  634. * This func can verify the first as well as the second auth block (for
  635. * double authorized commands).
  636. *
  637. * @param command_code command code of the request
  638. * @param response pointer to the request (w/ uninitialised auth data)
  639. * @param handles_len length of the handles area in response
  640. * @param auth_session pointer to the (valid) auth session to be used
  641. * @param response_auth pointer to the auth block of the response to be verified
  642. * @param auth authentication data (HMAC key)
  643. */
  644. static uint32_t verify_response_auth(uint32_t command_code,
  645. const void *response, size_t response_len0,
  646. size_t handles_len,
  647. struct session_data *auth_session,
  648. const void *response_auth, const void *auth)
  649. {
  650. uint8_t hmac_data[DIGEST_LENGTH * 3 + 1];
  651. uint8_t computed_auth[DIGEST_LENGTH];
  652. sha1_context hash_ctx;
  653. const size_t return_code_offset = 6;
  654. const size_t auth_continue_offset = 20;
  655. const size_t auth_auth_offset = 21;
  656. uint8_t auth_continue;
  657. if (!auth_session || !auth_session->valid)
  658. return TPM_AUTHFAIL;
  659. if (pack_byte_string(hmac_data, sizeof(hmac_data), "d",
  660. 0, command_code))
  661. return TPM_LIB_ERROR;
  662. if (response_len0 < TPM_RESPONSE_HEADER_LENGTH)
  663. return TPM_LIB_ERROR;
  664. sha1_starts(&hash_ctx);
  665. sha1_update(&hash_ctx, response + return_code_offset, 4);
  666. sha1_update(&hash_ctx, hmac_data, 4);
  667. if (response_len0 > TPM_RESPONSE_HEADER_LENGTH + handles_len)
  668. sha1_update(&hash_ctx,
  669. response + TPM_RESPONSE_HEADER_LENGTH + handles_len,
  670. response_len0 - TPM_RESPONSE_HEADER_LENGTH
  671. - handles_len);
  672. sha1_finish(&hash_ctx, hmac_data);
  673. memcpy(auth_session->nonce_even, response_auth, DIGEST_LENGTH);
  674. auth_continue = ((uint8_t *)response_auth)[auth_continue_offset];
  675. if (pack_byte_string(hmac_data, sizeof(hmac_data), "ssb",
  676. DIGEST_LENGTH,
  677. response_auth,
  678. DIGEST_LENGTH,
  679. 2 * DIGEST_LENGTH,
  680. auth_session->nonce_odd,
  681. DIGEST_LENGTH,
  682. 3 * DIGEST_LENGTH,
  683. auth_continue))
  684. return TPM_LIB_ERROR;
  685. sha1_hmac(auth, DIGEST_LENGTH, hmac_data, sizeof(hmac_data),
  686. computed_auth);
  687. if (memcmp(computed_auth, response_auth + auth_auth_offset,
  688. DIGEST_LENGTH))
  689. return TPM_AUTHFAIL;
  690. return TPM_SUCCESS;
  691. }
  692. uint32_t tpm_terminate_auth_session(uint32_t auth_handle)
  693. {
  694. const uint8_t command[18] = {
  695. 0x00, 0xc1, /* TPM_TAG */
  696. 0x00, 0x00, 0x00, 0x00, /* parameter size */
  697. 0x00, 0x00, 0x00, 0xba, /* TPM_COMMAND_CODE */
  698. 0x00, 0x00, 0x00, 0x00, /* TPM_HANDLE */
  699. 0x00, 0x00, 0x00, 0x02, /* TPM_RESSOURCE_TYPE */
  700. };
  701. const size_t req_handle_offset = TPM_REQUEST_HEADER_LENGTH;
  702. uint8_t request[COMMAND_BUFFER_SIZE];
  703. if (pack_byte_string(request, sizeof(request), "sd",
  704. 0, command, sizeof(command),
  705. req_handle_offset, auth_handle))
  706. return TPM_LIB_ERROR;
  707. if (oiap_session.valid && oiap_session.handle == auth_handle)
  708. oiap_session.valid = 0;
  709. return tpm_sendrecv_command(request, NULL, NULL);
  710. }
  711. uint32_t tpm_end_oiap(void)
  712. {
  713. uint32_t err = TPM_SUCCESS;
  714. if (oiap_session.valid)
  715. err = tpm_terminate_auth_session(oiap_session.handle);
  716. return err;
  717. }
  718. uint32_t tpm_oiap(uint32_t *auth_handle)
  719. {
  720. const uint8_t command[10] = {
  721. 0x00, 0xc1, /* TPM_TAG */
  722. 0x00, 0x00, 0x00, 0x0a, /* parameter size */
  723. 0x00, 0x00, 0x00, 0x0a, /* TPM_COMMAND_CODE */
  724. };
  725. const size_t res_auth_handle_offset = TPM_RESPONSE_HEADER_LENGTH;
  726. const size_t res_nonce_even_offset = TPM_RESPONSE_HEADER_LENGTH + 4;
  727. uint8_t response[COMMAND_BUFFER_SIZE];
  728. size_t response_length = sizeof(response);
  729. uint32_t err;
  730. if (oiap_session.valid)
  731. tpm_terminate_auth_session(oiap_session.handle);
  732. err = tpm_sendrecv_command(command, response, &response_length);
  733. if (err)
  734. return err;
  735. if (unpack_byte_string(response, response_length, "ds",
  736. res_auth_handle_offset, &oiap_session.handle,
  737. res_nonce_even_offset, &oiap_session.nonce_even,
  738. (uint32_t)DIGEST_LENGTH))
  739. return TPM_LIB_ERROR;
  740. oiap_session.valid = 1;
  741. if (auth_handle)
  742. *auth_handle = oiap_session.handle;
  743. return 0;
  744. }
  745. uint32_t tpm_load_key2_oiap(uint32_t parent_handle,
  746. const void *key, size_t key_length,
  747. const void *parent_key_usage_auth,
  748. uint32_t *key_handle)
  749. {
  750. const uint8_t command[14] = {
  751. 0x00, 0xc2, /* TPM_TAG */
  752. 0x00, 0x00, 0x00, 0x00, /* parameter size */
  753. 0x00, 0x00, 0x00, 0x41, /* TPM_COMMAND_CODE */
  754. 0x00, 0x00, 0x00, 0x00, /* parent handle */
  755. };
  756. const size_t req_size_offset = 2;
  757. const size_t req_parent_handle_offset = TPM_REQUEST_HEADER_LENGTH;
  758. const size_t req_key_offset = TPM_REQUEST_HEADER_LENGTH + 4;
  759. const size_t res_handle_offset = TPM_RESPONSE_HEADER_LENGTH;
  760. uint8_t request[sizeof(command) + TPM_KEY12_MAX_LENGTH
  761. + TPM_REQUEST_AUTH_LENGTH];
  762. uint8_t response[COMMAND_BUFFER_SIZE];
  763. size_t response_length = sizeof(response);
  764. uint32_t err;
  765. if (!oiap_session.valid) {
  766. err = tpm_oiap(NULL);
  767. if (err)
  768. return err;
  769. }
  770. if (pack_byte_string(request, sizeof(request), "sdds",
  771. 0, command, sizeof(command),
  772. req_size_offset,
  773. sizeof(command) + key_length
  774. + TPM_REQUEST_AUTH_LENGTH,
  775. req_parent_handle_offset, parent_handle,
  776. req_key_offset, key, key_length
  777. ))
  778. return TPM_LIB_ERROR;
  779. err = create_request_auth(request, sizeof(command) + key_length, 4,
  780. &oiap_session,
  781. request + sizeof(command) + key_length,
  782. parent_key_usage_auth);
  783. if (err)
  784. return err;
  785. err = tpm_sendrecv_command(request, response, &response_length);
  786. if (err) {
  787. if (err == TPM_AUTHFAIL)
  788. oiap_session.valid = 0;
  789. return err;
  790. }
  791. err = verify_response_auth(0x00000041, response,
  792. response_length - TPM_RESPONSE_AUTH_LENGTH,
  793. 4, &oiap_session,
  794. response + response_length - TPM_RESPONSE_AUTH_LENGTH,
  795. parent_key_usage_auth);
  796. if (err)
  797. return err;
  798. if (key_handle) {
  799. if (unpack_byte_string(response, response_length, "d",
  800. res_handle_offset, key_handle))
  801. return TPM_LIB_ERROR;
  802. }
  803. return 0;
  804. }
  805. uint32_t tpm_get_pub_key_oiap(uint32_t key_handle, const void *usage_auth,
  806. void *pubkey, size_t *pubkey_len)
  807. {
  808. const uint8_t command[14] = {
  809. 0x00, 0xc2, /* TPM_TAG */
  810. 0x00, 0x00, 0x00, 0x00, /* parameter size */
  811. 0x00, 0x00, 0x00, 0x21, /* TPM_COMMAND_CODE */
  812. 0x00, 0x00, 0x00, 0x00, /* key handle */
  813. };
  814. const size_t req_size_offset = 2;
  815. const size_t req_key_handle_offset = TPM_REQUEST_HEADER_LENGTH;
  816. const size_t res_pubkey_offset = TPM_RESPONSE_HEADER_LENGTH;
  817. uint8_t request[sizeof(command) + TPM_REQUEST_AUTH_LENGTH];
  818. uint8_t response[TPM_RESPONSE_HEADER_LENGTH + TPM_PUBKEY_MAX_LENGTH
  819. + TPM_RESPONSE_AUTH_LENGTH];
  820. size_t response_length = sizeof(response);
  821. uint32_t err;
  822. if (!oiap_session.valid) {
  823. err = tpm_oiap(NULL);
  824. if (err)
  825. return err;
  826. }
  827. if (pack_byte_string(request, sizeof(request), "sdd",
  828. 0, command, sizeof(command),
  829. req_size_offset,
  830. (uint32_t)(sizeof(command)
  831. + TPM_REQUEST_AUTH_LENGTH),
  832. req_key_handle_offset, key_handle
  833. ))
  834. return TPM_LIB_ERROR;
  835. err = create_request_auth(request, sizeof(command), 4, &oiap_session,
  836. request + sizeof(command), usage_auth);
  837. if (err)
  838. return err;
  839. err = tpm_sendrecv_command(request, response, &response_length);
  840. if (err) {
  841. if (err == TPM_AUTHFAIL)
  842. oiap_session.valid = 0;
  843. return err;
  844. }
  845. err = verify_response_auth(0x00000021, response,
  846. response_length - TPM_RESPONSE_AUTH_LENGTH,
  847. 0, &oiap_session,
  848. response + response_length - TPM_RESPONSE_AUTH_LENGTH,
  849. usage_auth);
  850. if (err)
  851. return err;
  852. if (pubkey) {
  853. if ((response_length - TPM_RESPONSE_HEADER_LENGTH
  854. - TPM_RESPONSE_AUTH_LENGTH) > *pubkey_len)
  855. return TPM_LIB_ERROR;
  856. *pubkey_len = response_length - TPM_RESPONSE_HEADER_LENGTH
  857. - TPM_RESPONSE_AUTH_LENGTH;
  858. memcpy(pubkey, response + res_pubkey_offset,
  859. response_length - TPM_RESPONSE_HEADER_LENGTH
  860. - TPM_RESPONSE_AUTH_LENGTH);
  861. }
  862. return 0;
  863. }
  864. #endif /* CONFIG_TPM_AUTH_SESSIONS */