tpm.c 28 KB

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