tpm-v2.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright (c) 2018 Bootlin
  4. * Author: Miquel Raynal <miquel.raynal@bootlin.com>
  5. */
  6. #include <common.h>
  7. #include <dm.h>
  8. #include <tpm-common.h>
  9. #include <tpm-v2.h>
  10. #include <linux/bitops.h>
  11. #include "tpm-utils.h"
  12. u32 tpm2_startup(struct udevice *dev, enum tpm2_startup_types mode)
  13. {
  14. const u8 command_v2[12] = {
  15. tpm_u16(TPM2_ST_NO_SESSIONS),
  16. tpm_u32(12),
  17. tpm_u32(TPM2_CC_STARTUP),
  18. tpm_u16(mode),
  19. };
  20. int ret;
  21. /*
  22. * Note TPM2_Startup command will return RC_SUCCESS the first time,
  23. * but will return RC_INITIALIZE otherwise.
  24. */
  25. ret = tpm_sendrecv_command(dev, command_v2, NULL, NULL);
  26. if (ret && ret != TPM2_RC_INITIALIZE)
  27. return ret;
  28. return 0;
  29. }
  30. u32 tpm2_self_test(struct udevice *dev, enum tpm2_yes_no full_test)
  31. {
  32. const u8 command_v2[12] = {
  33. tpm_u16(TPM2_ST_NO_SESSIONS),
  34. tpm_u32(11),
  35. tpm_u32(TPM2_CC_SELF_TEST),
  36. full_test,
  37. };
  38. return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
  39. }
  40. u32 tpm2_auto_start(struct udevice *dev)
  41. {
  42. u32 rc;
  43. rc = tpm2_self_test(dev, TPMI_YES);
  44. if (rc == TPM2_RC_INITIALIZE) {
  45. rc = tpm2_startup(dev, TPM2_SU_CLEAR);
  46. if (rc)
  47. return rc;
  48. rc = tpm2_self_test(dev, TPMI_YES);
  49. }
  50. return rc;
  51. }
  52. u32 tpm2_clear(struct udevice *dev, u32 handle, const char *pw,
  53. const ssize_t pw_sz)
  54. {
  55. /* Length of the message header, up to start of password */
  56. uint offset = 27;
  57. u8 command_v2[COMMAND_BUFFER_SIZE] = {
  58. tpm_u16(TPM2_ST_SESSIONS), /* TAG */
  59. tpm_u32(offset + pw_sz), /* Length */
  60. tpm_u32(TPM2_CC_CLEAR), /* Command code */
  61. /* HANDLE */
  62. tpm_u32(handle), /* TPM resource handle */
  63. /* AUTH_SESSION */
  64. tpm_u32(9 + pw_sz), /* Authorization size */
  65. tpm_u32(TPM2_RS_PW), /* Session handle */
  66. tpm_u16(0), /* Size of <nonce> */
  67. /* <nonce> (if any) */
  68. 0, /* Attributes: Cont/Excl/Rst */
  69. tpm_u16(pw_sz), /* Size of <hmac/password> */
  70. /* STRING(pw) <hmac/password> (if any) */
  71. };
  72. int ret;
  73. /*
  74. * Fill the command structure starting from the first buffer:
  75. * - the password (if any)
  76. */
  77. ret = pack_byte_string(command_v2, sizeof(command_v2), "s",
  78. offset, pw, pw_sz);
  79. offset += pw_sz;
  80. if (ret)
  81. return TPM_LIB_ERROR;
  82. return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
  83. }
  84. u32 tpm2_nv_define_space(struct udevice *dev, u32 space_index,
  85. size_t space_size, u32 nv_attributes,
  86. const u8 *nv_policy, size_t nv_policy_size)
  87. {
  88. /*
  89. * Calculate the offset of the nv_policy piece by adding each of the
  90. * chunks below.
  91. */
  92. const int platform_len = sizeof(u32);
  93. const int session_hdr_len = 13;
  94. const int message_len = 14;
  95. uint offset = TPM2_HDR_LEN + platform_len + session_hdr_len +
  96. message_len;
  97. u8 command_v2[COMMAND_BUFFER_SIZE] = {
  98. /* header 10 bytes */
  99. tpm_u16(TPM2_ST_SESSIONS), /* TAG */
  100. tpm_u32(offset + nv_policy_size + 2),/* Length */
  101. tpm_u32(TPM2_CC_NV_DEFINE_SPACE),/* Command code */
  102. /* handles 4 bytes */
  103. tpm_u32(TPM2_RH_PLATFORM), /* Primary platform seed */
  104. /* session header 13 bytes */
  105. tpm_u32(9), /* Header size */
  106. tpm_u32(TPM2_RS_PW), /* Password authorisation */
  107. tpm_u16(0), /* nonce_size */
  108. 0, /* session_attrs */
  109. tpm_u16(0), /* auth_size */
  110. /* message 14 bytes + policy */
  111. tpm_u16(message_len + nv_policy_size), /* size */
  112. tpm_u32(space_index),
  113. tpm_u16(TPM2_ALG_SHA256),
  114. tpm_u32(nv_attributes),
  115. tpm_u16(nv_policy_size),
  116. /*
  117. * nv_policy
  118. * space_size
  119. */
  120. };
  121. int ret;
  122. /*
  123. * Fill the command structure starting from the first buffer:
  124. * - the password (if any)
  125. */
  126. ret = pack_byte_string(command_v2, sizeof(command_v2), "sw",
  127. offset, nv_policy, nv_policy_size,
  128. offset + nv_policy_size, space_size);
  129. if (ret)
  130. return TPM_LIB_ERROR;
  131. return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
  132. }
  133. u32 tpm2_pcr_extend(struct udevice *dev, u32 index, u32 algorithm,
  134. const u8 *digest, u32 digest_len)
  135. {
  136. /* Length of the message header, up to start of digest */
  137. uint offset = 33;
  138. u8 command_v2[COMMAND_BUFFER_SIZE] = {
  139. tpm_u16(TPM2_ST_SESSIONS), /* TAG */
  140. tpm_u32(offset + digest_len), /* Length */
  141. tpm_u32(TPM2_CC_PCR_EXTEND), /* Command code */
  142. /* HANDLE */
  143. tpm_u32(index), /* Handle (PCR Index) */
  144. /* AUTH_SESSION */
  145. tpm_u32(9), /* Authorization size */
  146. tpm_u32(TPM2_RS_PW), /* Session handle */
  147. tpm_u16(0), /* Size of <nonce> */
  148. /* <nonce> (if any) */
  149. 0, /* Attributes: Cont/Excl/Rst */
  150. tpm_u16(0), /* Size of <hmac/password> */
  151. /* <hmac/password> (if any) */
  152. /* hashes */
  153. tpm_u32(1), /* Count (number of hashes) */
  154. tpm_u16(algorithm), /* Algorithm of the hash */
  155. /* STRING(digest) Digest */
  156. };
  157. int ret;
  158. if (!digest)
  159. return -EINVAL;
  160. /*
  161. * Fill the command structure starting from the first buffer:
  162. * - the digest
  163. */
  164. ret = pack_byte_string(command_v2, sizeof(command_v2), "s",
  165. offset, digest, digest_len);
  166. if (ret)
  167. return TPM_LIB_ERROR;
  168. return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
  169. }
  170. u32 tpm2_nv_read_value(struct udevice *dev, u32 index, void *data, u32 count)
  171. {
  172. u8 command_v2[COMMAND_BUFFER_SIZE] = {
  173. /* header 10 bytes */
  174. tpm_u16(TPM2_ST_SESSIONS), /* TAG */
  175. tpm_u32(10 + 8 + 4 + 9 + 4), /* Length */
  176. tpm_u32(TPM2_CC_NV_READ), /* Command code */
  177. /* handles 8 bytes */
  178. tpm_u32(TPM2_RH_PLATFORM), /* Primary platform seed */
  179. tpm_u32(HR_NV_INDEX + index), /* Password authorisation */
  180. /* AUTH_SESSION */
  181. tpm_u32(9), /* Authorization size */
  182. tpm_u32(TPM2_RS_PW), /* Session handle */
  183. tpm_u16(0), /* Size of <nonce> */
  184. /* <nonce> (if any) */
  185. 0, /* Attributes: Cont/Excl/Rst */
  186. tpm_u16(0), /* Size of <hmac/password> */
  187. /* <hmac/password> (if any) */
  188. tpm_u16(count), /* Number of bytes */
  189. tpm_u16(0), /* Offset */
  190. };
  191. size_t response_len = COMMAND_BUFFER_SIZE;
  192. u8 response[COMMAND_BUFFER_SIZE];
  193. int ret;
  194. u16 tag;
  195. u32 size, code;
  196. ret = tpm_sendrecv_command(dev, command_v2, response, &response_len);
  197. if (ret)
  198. return log_msg_ret("read", ret);
  199. if (unpack_byte_string(response, response_len, "wdds",
  200. 0, &tag, 2, &size, 6, &code,
  201. 16, data, count))
  202. return TPM_LIB_ERROR;
  203. return 0;
  204. }
  205. u32 tpm2_nv_write_value(struct udevice *dev, u32 index, const void *data,
  206. u32 count)
  207. {
  208. struct tpm_chip_priv *priv = dev_get_uclass_priv(dev);
  209. uint offset = 10 + 8 + 4 + 9 + 2;
  210. uint len = offset + count + 2;
  211. /* Use empty password auth if platform hierarchy is disabled */
  212. u32 auth = priv->plat_hier_disabled ? HR_NV_INDEX + index :
  213. TPM2_RH_PLATFORM;
  214. u8 command_v2[COMMAND_BUFFER_SIZE] = {
  215. /* header 10 bytes */
  216. tpm_u16(TPM2_ST_SESSIONS), /* TAG */
  217. tpm_u32(len), /* Length */
  218. tpm_u32(TPM2_CC_NV_WRITE), /* Command code */
  219. /* handles 8 bytes */
  220. tpm_u32(auth), /* Primary platform seed */
  221. tpm_u32(HR_NV_INDEX + index), /* Password authorisation */
  222. /* AUTH_SESSION */
  223. tpm_u32(9), /* Authorization size */
  224. tpm_u32(TPM2_RS_PW), /* Session handle */
  225. tpm_u16(0), /* Size of <nonce> */
  226. /* <nonce> (if any) */
  227. 0, /* Attributes: Cont/Excl/Rst */
  228. tpm_u16(0), /* Size of <hmac/password> */
  229. /* <hmac/password> (if any) */
  230. tpm_u16(count),
  231. };
  232. size_t response_len = COMMAND_BUFFER_SIZE;
  233. u8 response[COMMAND_BUFFER_SIZE];
  234. int ret;
  235. ret = pack_byte_string(command_v2, sizeof(command_v2), "sw",
  236. offset, data, count,
  237. offset + count, 0);
  238. if (ret)
  239. return TPM_LIB_ERROR;
  240. return tpm_sendrecv_command(dev, command_v2, response, &response_len);
  241. }
  242. u32 tpm2_pcr_read(struct udevice *dev, u32 idx, unsigned int idx_min_sz,
  243. u16 algorithm, void *data, u32 digest_len,
  244. unsigned int *updates)
  245. {
  246. u8 idx_array_sz = max(idx_min_sz, DIV_ROUND_UP(idx, 8));
  247. u8 command_v2[COMMAND_BUFFER_SIZE] = {
  248. tpm_u16(TPM2_ST_NO_SESSIONS), /* TAG */
  249. tpm_u32(17 + idx_array_sz), /* Length */
  250. tpm_u32(TPM2_CC_PCR_READ), /* Command code */
  251. /* TPML_PCR_SELECTION */
  252. tpm_u32(1), /* Number of selections */
  253. tpm_u16(algorithm), /* Algorithm of the hash */
  254. idx_array_sz, /* Array size for selection */
  255. /* bitmap(idx) Selected PCR bitmap */
  256. };
  257. size_t response_len = COMMAND_BUFFER_SIZE;
  258. u8 response[COMMAND_BUFFER_SIZE];
  259. unsigned int pcr_sel_idx = idx / 8;
  260. u8 pcr_sel_bit = BIT(idx % 8);
  261. unsigned int counter = 0;
  262. int ret;
  263. if (pack_byte_string(command_v2, COMMAND_BUFFER_SIZE, "b",
  264. 17 + pcr_sel_idx, pcr_sel_bit))
  265. return TPM_LIB_ERROR;
  266. ret = tpm_sendrecv_command(dev, command_v2, response, &response_len);
  267. if (ret)
  268. return ret;
  269. if (digest_len > response_len)
  270. return TPM_LIB_ERROR;
  271. if (unpack_byte_string(response, response_len, "ds",
  272. 10, &counter,
  273. response_len - digest_len, data,
  274. digest_len))
  275. return TPM_LIB_ERROR;
  276. if (updates)
  277. *updates = counter;
  278. return 0;
  279. }
  280. u32 tpm2_get_capability(struct udevice *dev, u32 capability, u32 property,
  281. void *buf, size_t prop_count)
  282. {
  283. u8 command_v2[COMMAND_BUFFER_SIZE] = {
  284. tpm_u16(TPM2_ST_NO_SESSIONS), /* TAG */
  285. tpm_u32(22), /* Length */
  286. tpm_u32(TPM2_CC_GET_CAPABILITY), /* Command code */
  287. tpm_u32(capability), /* Capability */
  288. tpm_u32(property), /* Property */
  289. tpm_u32(prop_count), /* Property count */
  290. };
  291. u8 response[COMMAND_BUFFER_SIZE];
  292. size_t response_len = COMMAND_BUFFER_SIZE;
  293. unsigned int properties_off;
  294. int ret;
  295. ret = tpm_sendrecv_command(dev, command_v2, response, &response_len);
  296. if (ret)
  297. return ret;
  298. /*
  299. * In the response buffer, the properties are located after the:
  300. * tag (u16), response size (u32), response code (u32),
  301. * YES/NO flag (u8), TPM_CAP (u32).
  302. */
  303. properties_off = sizeof(u16) + sizeof(u32) + sizeof(u32) +
  304. sizeof(u8) + sizeof(u32);
  305. memcpy(buf, &response[properties_off], response_len - properties_off);
  306. return 0;
  307. }
  308. u32 tpm2_dam_reset(struct udevice *dev, const char *pw, const ssize_t pw_sz)
  309. {
  310. u8 command_v2[COMMAND_BUFFER_SIZE] = {
  311. tpm_u16(TPM2_ST_SESSIONS), /* TAG */
  312. tpm_u32(27 + pw_sz), /* Length */
  313. tpm_u32(TPM2_CC_DAM_RESET), /* Command code */
  314. /* HANDLE */
  315. tpm_u32(TPM2_RH_LOCKOUT), /* TPM resource handle */
  316. /* AUTH_SESSION */
  317. tpm_u32(9 + pw_sz), /* Authorization size */
  318. tpm_u32(TPM2_RS_PW), /* Session handle */
  319. tpm_u16(0), /* Size of <nonce> */
  320. /* <nonce> (if any) */
  321. 0, /* Attributes: Cont/Excl/Rst */
  322. tpm_u16(pw_sz), /* Size of <hmac/password> */
  323. /* STRING(pw) <hmac/password> (if any) */
  324. };
  325. unsigned int offset = 27;
  326. int ret;
  327. /*
  328. * Fill the command structure starting from the first buffer:
  329. * - the password (if any)
  330. */
  331. ret = pack_byte_string(command_v2, sizeof(command_v2), "s",
  332. offset, pw, pw_sz);
  333. offset += pw_sz;
  334. if (ret)
  335. return TPM_LIB_ERROR;
  336. return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
  337. }
  338. u32 tpm2_dam_parameters(struct udevice *dev, const char *pw,
  339. const ssize_t pw_sz, unsigned int max_tries,
  340. unsigned int recovery_time,
  341. unsigned int lockout_recovery)
  342. {
  343. u8 command_v2[COMMAND_BUFFER_SIZE] = {
  344. tpm_u16(TPM2_ST_SESSIONS), /* TAG */
  345. tpm_u32(27 + pw_sz + 12), /* Length */
  346. tpm_u32(TPM2_CC_DAM_PARAMETERS), /* Command code */
  347. /* HANDLE */
  348. tpm_u32(TPM2_RH_LOCKOUT), /* TPM resource handle */
  349. /* AUTH_SESSION */
  350. tpm_u32(9 + pw_sz), /* Authorization size */
  351. tpm_u32(TPM2_RS_PW), /* Session handle */
  352. tpm_u16(0), /* Size of <nonce> */
  353. /* <nonce> (if any) */
  354. 0, /* Attributes: Cont/Excl/Rst */
  355. tpm_u16(pw_sz), /* Size of <hmac/password> */
  356. /* STRING(pw) <hmac/password> (if any) */
  357. /* LOCKOUT PARAMETERS */
  358. /* tpm_u32(max_tries) Max tries (0, always lock) */
  359. /* tpm_u32(recovery_time) Recovery time (0, no lock) */
  360. /* tpm_u32(lockout_recovery) Lockout recovery */
  361. };
  362. unsigned int offset = 27;
  363. int ret;
  364. /*
  365. * Fill the command structure starting from the first buffer:
  366. * - the password (if any)
  367. * - max tries
  368. * - recovery time
  369. * - lockout recovery
  370. */
  371. ret = pack_byte_string(command_v2, sizeof(command_v2), "sddd",
  372. offset, pw, pw_sz,
  373. offset + pw_sz, max_tries,
  374. offset + pw_sz + 4, recovery_time,
  375. offset + pw_sz + 8, lockout_recovery);
  376. offset += pw_sz + 12;
  377. if (ret)
  378. return TPM_LIB_ERROR;
  379. return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
  380. }
  381. int tpm2_change_auth(struct udevice *dev, u32 handle, const char *newpw,
  382. const ssize_t newpw_sz, const char *oldpw,
  383. const ssize_t oldpw_sz)
  384. {
  385. unsigned int offset = 27;
  386. u8 command_v2[COMMAND_BUFFER_SIZE] = {
  387. tpm_u16(TPM2_ST_SESSIONS), /* TAG */
  388. tpm_u32(offset + oldpw_sz + 2 + newpw_sz), /* Length */
  389. tpm_u32(TPM2_CC_HIERCHANGEAUTH), /* Command code */
  390. /* HANDLE */
  391. tpm_u32(handle), /* TPM resource handle */
  392. /* AUTH_SESSION */
  393. tpm_u32(9 + oldpw_sz), /* Authorization size */
  394. tpm_u32(TPM2_RS_PW), /* Session handle */
  395. tpm_u16(0), /* Size of <nonce> */
  396. /* <nonce> (if any) */
  397. 0, /* Attributes: Cont/Excl/Rst */
  398. tpm_u16(oldpw_sz) /* Size of <hmac/password> */
  399. /* STRING(oldpw) <hmac/password> (if any) */
  400. /* TPM2B_AUTH (TPM2B_DIGEST) */
  401. /* tpm_u16(newpw_sz) Digest size, new pw length */
  402. /* STRING(newpw) Digest buffer, new pw */
  403. };
  404. int ret;
  405. /*
  406. * Fill the command structure starting from the first buffer:
  407. * - the old password (if any)
  408. * - size of the new password
  409. * - new password
  410. */
  411. ret = pack_byte_string(command_v2, sizeof(command_v2), "sws",
  412. offset, oldpw, oldpw_sz,
  413. offset + oldpw_sz, newpw_sz,
  414. offset + oldpw_sz + 2, newpw, newpw_sz);
  415. offset += oldpw_sz + 2 + newpw_sz;
  416. if (ret)
  417. return TPM_LIB_ERROR;
  418. return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
  419. }
  420. u32 tpm2_pcr_setauthpolicy(struct udevice *dev, const char *pw,
  421. const ssize_t pw_sz, u32 index, const char *key)
  422. {
  423. u8 command_v2[COMMAND_BUFFER_SIZE] = {
  424. tpm_u16(TPM2_ST_SESSIONS), /* TAG */
  425. tpm_u32(35 + pw_sz + TPM2_DIGEST_LEN), /* Length */
  426. tpm_u32(TPM2_CC_PCR_SETAUTHPOL), /* Command code */
  427. /* HANDLE */
  428. tpm_u32(TPM2_RH_PLATFORM), /* TPM resource handle */
  429. /* AUTH_SESSION */
  430. tpm_u32(9 + pw_sz), /* Authorization size */
  431. tpm_u32(TPM2_RS_PW), /* session handle */
  432. tpm_u16(0), /* Size of <nonce> */
  433. /* <nonce> (if any) */
  434. 0, /* Attributes: Cont/Excl/Rst */
  435. tpm_u16(pw_sz) /* Size of <hmac/password> */
  436. /* STRING(pw) <hmac/password> (if any) */
  437. /* TPM2B_AUTH (TPM2B_DIGEST) */
  438. /* tpm_u16(TPM2_DIGEST_LEN) Digest size length */
  439. /* STRING(key) Digest buffer (PCR key) */
  440. /* TPMI_ALG_HASH */
  441. /* tpm_u16(TPM2_ALG_SHA256) Algorithm of the hash */
  442. /* TPMI_DH_PCR */
  443. /* tpm_u32(index), PCR Index */
  444. };
  445. unsigned int offset = 27;
  446. int ret;
  447. /*
  448. * Fill the command structure starting from the first buffer:
  449. * - the password (if any)
  450. * - the PCR key length
  451. * - the PCR key
  452. * - the hash algorithm
  453. * - the PCR index
  454. */
  455. ret = pack_byte_string(command_v2, sizeof(command_v2), "swswd",
  456. offset, pw, pw_sz,
  457. offset + pw_sz, TPM2_DIGEST_LEN,
  458. offset + pw_sz + 2, key, TPM2_DIGEST_LEN,
  459. offset + pw_sz + 2 + TPM2_DIGEST_LEN,
  460. TPM2_ALG_SHA256,
  461. offset + pw_sz + 4 + TPM2_DIGEST_LEN, index);
  462. offset += pw_sz + 2 + TPM2_DIGEST_LEN + 2 + 4;
  463. if (ret)
  464. return TPM_LIB_ERROR;
  465. return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
  466. }
  467. u32 tpm2_pcr_setauthvalue(struct udevice *dev, const char *pw,
  468. const ssize_t pw_sz, u32 index, const char *key,
  469. const ssize_t key_sz)
  470. {
  471. u8 command_v2[COMMAND_BUFFER_SIZE] = {
  472. tpm_u16(TPM2_ST_SESSIONS), /* TAG */
  473. tpm_u32(33 + pw_sz + TPM2_DIGEST_LEN), /* Length */
  474. tpm_u32(TPM2_CC_PCR_SETAUTHVAL), /* Command code */
  475. /* HANDLE */
  476. tpm_u32(index), /* Handle (PCR Index) */
  477. /* AUTH_SESSION */
  478. tpm_u32(9 + pw_sz), /* Authorization size */
  479. tpm_u32(TPM2_RS_PW), /* session handle */
  480. tpm_u16(0), /* Size of <nonce> */
  481. /* <nonce> (if any) */
  482. 0, /* Attributes: Cont/Excl/Rst */
  483. tpm_u16(pw_sz), /* Size of <hmac/password> */
  484. /* STRING(pw) <hmac/password> (if any) */
  485. /* TPM2B_DIGEST */
  486. /* tpm_u16(key_sz) Key length */
  487. /* STRING(key) Key */
  488. };
  489. unsigned int offset = 27;
  490. int ret;
  491. /*
  492. * Fill the command structure starting from the first buffer:
  493. * - the password (if any)
  494. * - the number of digests, 1 in our case
  495. * - the algorithm, sha256 in our case
  496. * - the digest (64 bytes)
  497. */
  498. ret = pack_byte_string(command_v2, sizeof(command_v2), "sws",
  499. offset, pw, pw_sz,
  500. offset + pw_sz, key_sz,
  501. offset + pw_sz + 2, key, key_sz);
  502. offset += pw_sz + 2 + key_sz;
  503. if (ret)
  504. return TPM_LIB_ERROR;
  505. return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
  506. }
  507. u32 tpm2_get_random(struct udevice *dev, void *data, u32 count)
  508. {
  509. const u8 command_v2[10] = {
  510. tpm_u16(TPM2_ST_NO_SESSIONS),
  511. tpm_u32(12),
  512. tpm_u32(TPM2_CC_GET_RANDOM),
  513. };
  514. u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
  515. const size_t data_size_offset = 10;
  516. const size_t data_offset = 12;
  517. size_t response_length = sizeof(response);
  518. u32 data_size;
  519. u8 *out = data;
  520. while (count > 0) {
  521. u32 this_bytes = min((size_t)count,
  522. sizeof(response) - data_offset);
  523. u32 err;
  524. if (pack_byte_string(buf, sizeof(buf), "sw",
  525. 0, command_v2, sizeof(command_v2),
  526. sizeof(command_v2), this_bytes))
  527. return TPM_LIB_ERROR;
  528. err = tpm_sendrecv_command(dev, buf, response,
  529. &response_length);
  530. if (err)
  531. return err;
  532. if (unpack_byte_string(response, response_length, "w",
  533. data_size_offset, &data_size))
  534. return TPM_LIB_ERROR;
  535. if (data_size > this_bytes)
  536. return TPM_LIB_ERROR;
  537. if (unpack_byte_string(response, response_length, "s",
  538. data_offset, out, data_size))
  539. return TPM_LIB_ERROR;
  540. count -= data_size;
  541. out += data_size;
  542. }
  543. return 0;
  544. }
  545. u32 tpm2_write_lock(struct udevice *dev, u32 index)
  546. {
  547. u8 command_v2[COMMAND_BUFFER_SIZE] = {
  548. /* header 10 bytes */
  549. tpm_u16(TPM2_ST_SESSIONS), /* TAG */
  550. tpm_u32(10 + 8 + 13), /* Length */
  551. tpm_u32(TPM2_CC_NV_WRITELOCK), /* Command code */
  552. /* handles 8 bytes */
  553. tpm_u32(TPM2_RH_PLATFORM), /* Primary platform seed */
  554. tpm_u32(HR_NV_INDEX + index), /* Password authorisation */
  555. /* session header 9 bytes */
  556. tpm_u32(9), /* Header size */
  557. tpm_u32(TPM2_RS_PW), /* Password authorisation */
  558. tpm_u16(0), /* nonce_size */
  559. 0, /* session_attrs */
  560. tpm_u16(0), /* auth_size */
  561. };
  562. return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
  563. }
  564. u32 tpm2_disable_platform_hierarchy(struct udevice *dev)
  565. {
  566. struct tpm_chip_priv *priv = dev_get_uclass_priv(dev);
  567. u8 command_v2[COMMAND_BUFFER_SIZE] = {
  568. /* header 10 bytes */
  569. tpm_u16(TPM2_ST_SESSIONS), /* TAG */
  570. tpm_u32(10 + 4 + 13 + 5), /* Length */
  571. tpm_u32(TPM2_CC_HIER_CONTROL), /* Command code */
  572. /* 4 bytes */
  573. tpm_u32(TPM2_RH_PLATFORM), /* Primary platform seed */
  574. /* session header 9 bytes */
  575. tpm_u32(9), /* Header size */
  576. tpm_u32(TPM2_RS_PW), /* Password authorisation */
  577. tpm_u16(0), /* nonce_size */
  578. 0, /* session_attrs */
  579. tpm_u16(0), /* auth_size */
  580. /* payload 5 bytes */
  581. tpm_u32(TPM2_RH_PLATFORM), /* Hierarchy to disable */
  582. 0, /* 0=disable */
  583. };
  584. int ret;
  585. ret = tpm_sendrecv_command(dev, command_v2, NULL, NULL);
  586. log_info("ret=%s, %x\n", dev->name, ret);
  587. if (ret)
  588. return ret;
  589. priv->plat_hier_disabled = true;
  590. return 0;
  591. }
  592. u32 tpm2_submit_command(struct udevice *dev, const u8 *sendbuf,
  593. u8 *recvbuf, size_t *recv_size)
  594. {
  595. return tpm_sendrecv_command(dev, sendbuf, recvbuf, recv_size);
  596. }
  597. u32 tpm2_report_state(struct udevice *dev, uint vendor_cmd, uint vendor_subcmd,
  598. u8 *recvbuf, size_t *recv_size)
  599. {
  600. u8 command_v2[COMMAND_BUFFER_SIZE] = {
  601. /* header 10 bytes */
  602. tpm_u16(TPM2_ST_NO_SESSIONS), /* TAG */
  603. tpm_u32(10 + 2), /* Length */
  604. tpm_u32(vendor_cmd), /* Command code */
  605. tpm_u16(vendor_subcmd),
  606. };
  607. int ret;
  608. ret = tpm_sendrecv_command(dev, command_v2, recvbuf, recv_size);
  609. log_debug("ret=%s, %x\n", dev->name, ret);
  610. if (ret)
  611. return ret;
  612. if (*recv_size < 12)
  613. return -ENODATA;
  614. *recv_size -= 12;
  615. memcpy(recvbuf, recvbuf + 12, *recv_size);
  616. return 0;
  617. }
  618. u32 tpm2_enable_nvcommits(struct udevice *dev, uint vendor_cmd,
  619. uint vendor_subcmd)
  620. {
  621. u8 command_v2[COMMAND_BUFFER_SIZE] = {
  622. /* header 10 bytes */
  623. tpm_u16(TPM2_ST_NO_SESSIONS), /* TAG */
  624. tpm_u32(10 + 2), /* Length */
  625. tpm_u32(vendor_cmd), /* Command code */
  626. tpm_u16(vendor_subcmd),
  627. };
  628. int ret;
  629. ret = tpm_sendrecv_command(dev, command_v2, NULL, NULL);
  630. log_debug("ret=%s, %x\n", dev->name, ret);
  631. if (ret)
  632. return ret;
  633. return 0;
  634. }