tpm2-space.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (C) 2016 Intel Corporation
  4. *
  5. * Authors:
  6. * Jarkko Sakkinen <[email protected]>
  7. *
  8. * Maintained by: <[email protected]>
  9. *
  10. * This file contains TPM2 protocol implementations of the commands
  11. * used by the kernel internally.
  12. */
  13. #include <linux/gfp.h>
  14. #include <asm/unaligned.h>
  15. #include "tpm.h"
  16. enum tpm2_handle_types {
  17. TPM2_HT_HMAC_SESSION = 0x02000000,
  18. TPM2_HT_POLICY_SESSION = 0x03000000,
  19. TPM2_HT_TRANSIENT = 0x80000000,
  20. };
  21. struct tpm2_context {
  22. __be64 sequence;
  23. __be32 saved_handle;
  24. __be32 hierarchy;
  25. __be16 blob_size;
  26. } __packed;
  27. static void tpm2_flush_sessions(struct tpm_chip *chip, struct tpm_space *space)
  28. {
  29. int i;
  30. for (i = 0; i < ARRAY_SIZE(space->session_tbl); i++) {
  31. if (space->session_tbl[i])
  32. tpm2_flush_context(chip, space->session_tbl[i]);
  33. }
  34. }
  35. int tpm2_init_space(struct tpm_space *space, unsigned int buf_size)
  36. {
  37. space->context_buf = kzalloc(buf_size, GFP_KERNEL);
  38. if (!space->context_buf)
  39. return -ENOMEM;
  40. space->session_buf = kzalloc(buf_size, GFP_KERNEL);
  41. if (space->session_buf == NULL) {
  42. kfree(space->context_buf);
  43. /* Prevent caller getting a dangling pointer. */
  44. space->context_buf = NULL;
  45. return -ENOMEM;
  46. }
  47. space->buf_size = buf_size;
  48. return 0;
  49. }
  50. void tpm2_del_space(struct tpm_chip *chip, struct tpm_space *space)
  51. {
  52. if (tpm_try_get_ops(chip) == 0) {
  53. tpm2_flush_sessions(chip, space);
  54. tpm_put_ops(chip);
  55. }
  56. kfree(space->context_buf);
  57. kfree(space->session_buf);
  58. }
  59. static int tpm2_load_context(struct tpm_chip *chip, u8 *buf,
  60. unsigned int *offset, u32 *handle)
  61. {
  62. struct tpm_buf tbuf;
  63. struct tpm2_context *ctx;
  64. unsigned int body_size;
  65. int rc;
  66. rc = tpm_buf_init(&tbuf, TPM2_ST_NO_SESSIONS, TPM2_CC_CONTEXT_LOAD);
  67. if (rc)
  68. return rc;
  69. ctx = (struct tpm2_context *)&buf[*offset];
  70. body_size = sizeof(*ctx) + be16_to_cpu(ctx->blob_size);
  71. tpm_buf_append(&tbuf, &buf[*offset], body_size);
  72. rc = tpm_transmit_cmd(chip, &tbuf, 4, NULL);
  73. if (rc < 0) {
  74. dev_warn(&chip->dev, "%s: failed with a system error %d\n",
  75. __func__, rc);
  76. tpm_buf_destroy(&tbuf);
  77. return -EFAULT;
  78. } else if (tpm2_rc_value(rc) == TPM2_RC_HANDLE ||
  79. rc == TPM2_RC_REFERENCE_H0) {
  80. /*
  81. * TPM_RC_HANDLE means that the session context can't
  82. * be loaded because of an internal counter mismatch
  83. * that makes the TPM think there might have been a
  84. * replay. This might happen if the context was saved
  85. * and loaded outside the space.
  86. *
  87. * TPM_RC_REFERENCE_H0 means the session has been
  88. * flushed outside the space
  89. */
  90. *handle = 0;
  91. tpm_buf_destroy(&tbuf);
  92. return -ENOENT;
  93. } else if (rc > 0) {
  94. dev_warn(&chip->dev, "%s: failed with a TPM error 0x%04X\n",
  95. __func__, rc);
  96. tpm_buf_destroy(&tbuf);
  97. return -EFAULT;
  98. }
  99. *handle = be32_to_cpup((__be32 *)&tbuf.data[TPM_HEADER_SIZE]);
  100. *offset += body_size;
  101. tpm_buf_destroy(&tbuf);
  102. return 0;
  103. }
  104. static int tpm2_save_context(struct tpm_chip *chip, u32 handle, u8 *buf,
  105. unsigned int buf_size, unsigned int *offset)
  106. {
  107. struct tpm_buf tbuf;
  108. unsigned int body_size;
  109. int rc;
  110. rc = tpm_buf_init(&tbuf, TPM2_ST_NO_SESSIONS, TPM2_CC_CONTEXT_SAVE);
  111. if (rc)
  112. return rc;
  113. tpm_buf_append_u32(&tbuf, handle);
  114. rc = tpm_transmit_cmd(chip, &tbuf, 0, NULL);
  115. if (rc < 0) {
  116. dev_warn(&chip->dev, "%s: failed with a system error %d\n",
  117. __func__, rc);
  118. tpm_buf_destroy(&tbuf);
  119. return -EFAULT;
  120. } else if (tpm2_rc_value(rc) == TPM2_RC_REFERENCE_H0) {
  121. tpm_buf_destroy(&tbuf);
  122. return -ENOENT;
  123. } else if (rc) {
  124. dev_warn(&chip->dev, "%s: failed with a TPM error 0x%04X\n",
  125. __func__, rc);
  126. tpm_buf_destroy(&tbuf);
  127. return -EFAULT;
  128. }
  129. body_size = tpm_buf_length(&tbuf) - TPM_HEADER_SIZE;
  130. if ((*offset + body_size) > buf_size) {
  131. dev_warn(&chip->dev, "%s: out of backing storage\n", __func__);
  132. tpm_buf_destroy(&tbuf);
  133. return -ENOMEM;
  134. }
  135. memcpy(&buf[*offset], &tbuf.data[TPM_HEADER_SIZE], body_size);
  136. *offset += body_size;
  137. tpm_buf_destroy(&tbuf);
  138. return 0;
  139. }
  140. void tpm2_flush_space(struct tpm_chip *chip)
  141. {
  142. struct tpm_space *space = &chip->work_space;
  143. int i;
  144. for (i = 0; i < ARRAY_SIZE(space->context_tbl); i++)
  145. if (space->context_tbl[i] && ~space->context_tbl[i])
  146. tpm2_flush_context(chip, space->context_tbl[i]);
  147. tpm2_flush_sessions(chip, space);
  148. }
  149. static int tpm2_load_space(struct tpm_chip *chip)
  150. {
  151. struct tpm_space *space = &chip->work_space;
  152. unsigned int offset;
  153. int i;
  154. int rc;
  155. for (i = 0, offset = 0; i < ARRAY_SIZE(space->context_tbl); i++) {
  156. if (!space->context_tbl[i])
  157. continue;
  158. /* sanity check, should never happen */
  159. if (~space->context_tbl[i]) {
  160. dev_err(&chip->dev, "context table is inconsistent");
  161. return -EFAULT;
  162. }
  163. rc = tpm2_load_context(chip, space->context_buf, &offset,
  164. &space->context_tbl[i]);
  165. if (rc)
  166. return rc;
  167. }
  168. for (i = 0, offset = 0; i < ARRAY_SIZE(space->session_tbl); i++) {
  169. u32 handle;
  170. if (!space->session_tbl[i])
  171. continue;
  172. rc = tpm2_load_context(chip, space->session_buf,
  173. &offset, &handle);
  174. if (rc == -ENOENT) {
  175. /* load failed, just forget session */
  176. space->session_tbl[i] = 0;
  177. } else if (rc) {
  178. tpm2_flush_space(chip);
  179. return rc;
  180. }
  181. if (handle != space->session_tbl[i]) {
  182. dev_warn(&chip->dev, "session restored to wrong handle\n");
  183. tpm2_flush_space(chip);
  184. return -EFAULT;
  185. }
  186. }
  187. return 0;
  188. }
  189. static bool tpm2_map_to_phandle(struct tpm_space *space, void *handle)
  190. {
  191. u32 vhandle = be32_to_cpup((__be32 *)handle);
  192. u32 phandle;
  193. int i;
  194. i = 0xFFFFFF - (vhandle & 0xFFFFFF);
  195. if (i >= ARRAY_SIZE(space->context_tbl) || !space->context_tbl[i])
  196. return false;
  197. phandle = space->context_tbl[i];
  198. *((__be32 *)handle) = cpu_to_be32(phandle);
  199. return true;
  200. }
  201. static int tpm2_map_command(struct tpm_chip *chip, u32 cc, u8 *cmd)
  202. {
  203. struct tpm_space *space = &chip->work_space;
  204. unsigned int nr_handles;
  205. u32 attrs;
  206. __be32 *handle;
  207. int i;
  208. i = tpm2_find_cc(chip, cc);
  209. if (i < 0)
  210. return -EINVAL;
  211. attrs = chip->cc_attrs_tbl[i];
  212. nr_handles = (attrs >> TPM2_CC_ATTR_CHANDLES) & GENMASK(2, 0);
  213. handle = (__be32 *)&cmd[TPM_HEADER_SIZE];
  214. for (i = 0; i < nr_handles; i++, handle++) {
  215. if ((be32_to_cpu(*handle) & 0xFF000000) == TPM2_HT_TRANSIENT) {
  216. if (!tpm2_map_to_phandle(space, handle))
  217. return -EINVAL;
  218. }
  219. }
  220. return 0;
  221. }
  222. static int tpm_find_and_validate_cc(struct tpm_chip *chip,
  223. struct tpm_space *space,
  224. const void *cmd, size_t len)
  225. {
  226. const struct tpm_header *header = (const void *)cmd;
  227. int i;
  228. u32 cc;
  229. u32 attrs;
  230. unsigned int nr_handles;
  231. if (len < TPM_HEADER_SIZE || !chip->nr_commands)
  232. return -EINVAL;
  233. cc = be32_to_cpu(header->ordinal);
  234. i = tpm2_find_cc(chip, cc);
  235. if (i < 0) {
  236. dev_dbg(&chip->dev, "0x%04X is an invalid command\n",
  237. cc);
  238. return -EOPNOTSUPP;
  239. }
  240. attrs = chip->cc_attrs_tbl[i];
  241. nr_handles =
  242. 4 * ((attrs >> TPM2_CC_ATTR_CHANDLES) & GENMASK(2, 0));
  243. if (len < TPM_HEADER_SIZE + 4 * nr_handles)
  244. goto err_len;
  245. return cc;
  246. err_len:
  247. dev_dbg(&chip->dev, "%s: insufficient command length %zu", __func__,
  248. len);
  249. return -EINVAL;
  250. }
  251. int tpm2_prepare_space(struct tpm_chip *chip, struct tpm_space *space, u8 *cmd,
  252. size_t cmdsiz)
  253. {
  254. int rc;
  255. int cc;
  256. if (!space)
  257. return 0;
  258. cc = tpm_find_and_validate_cc(chip, space, cmd, cmdsiz);
  259. if (cc < 0)
  260. return cc;
  261. memcpy(&chip->work_space.context_tbl, &space->context_tbl,
  262. sizeof(space->context_tbl));
  263. memcpy(&chip->work_space.session_tbl, &space->session_tbl,
  264. sizeof(space->session_tbl));
  265. memcpy(chip->work_space.context_buf, space->context_buf,
  266. space->buf_size);
  267. memcpy(chip->work_space.session_buf, space->session_buf,
  268. space->buf_size);
  269. rc = tpm2_load_space(chip);
  270. if (rc) {
  271. tpm2_flush_space(chip);
  272. return rc;
  273. }
  274. rc = tpm2_map_command(chip, cc, cmd);
  275. if (rc) {
  276. tpm2_flush_space(chip);
  277. return rc;
  278. }
  279. chip->last_cc = cc;
  280. return 0;
  281. }
  282. static bool tpm2_add_session(struct tpm_chip *chip, u32 handle)
  283. {
  284. struct tpm_space *space = &chip->work_space;
  285. int i;
  286. for (i = 0; i < ARRAY_SIZE(space->session_tbl); i++)
  287. if (space->session_tbl[i] == 0)
  288. break;
  289. if (i == ARRAY_SIZE(space->session_tbl))
  290. return false;
  291. space->session_tbl[i] = handle;
  292. return true;
  293. }
  294. static u32 tpm2_map_to_vhandle(struct tpm_space *space, u32 phandle, bool alloc)
  295. {
  296. int i;
  297. for (i = 0; i < ARRAY_SIZE(space->context_tbl); i++) {
  298. if (alloc) {
  299. if (!space->context_tbl[i]) {
  300. space->context_tbl[i] = phandle;
  301. break;
  302. }
  303. } else if (space->context_tbl[i] == phandle)
  304. break;
  305. }
  306. if (i == ARRAY_SIZE(space->context_tbl))
  307. return 0;
  308. return TPM2_HT_TRANSIENT | (0xFFFFFF - i);
  309. }
  310. static int tpm2_map_response_header(struct tpm_chip *chip, u32 cc, u8 *rsp,
  311. size_t len)
  312. {
  313. struct tpm_space *space = &chip->work_space;
  314. struct tpm_header *header = (struct tpm_header *)rsp;
  315. u32 phandle;
  316. u32 phandle_type;
  317. u32 vhandle;
  318. u32 attrs;
  319. int i;
  320. if (be32_to_cpu(header->return_code) != TPM2_RC_SUCCESS)
  321. return 0;
  322. i = tpm2_find_cc(chip, cc);
  323. /* sanity check, should never happen */
  324. if (i < 0)
  325. return -EFAULT;
  326. attrs = chip->cc_attrs_tbl[i];
  327. if (!((attrs >> TPM2_CC_ATTR_RHANDLE) & 1))
  328. return 0;
  329. phandle = be32_to_cpup((__be32 *)&rsp[TPM_HEADER_SIZE]);
  330. phandle_type = phandle & 0xFF000000;
  331. switch (phandle_type) {
  332. case TPM2_HT_TRANSIENT:
  333. vhandle = tpm2_map_to_vhandle(space, phandle, true);
  334. if (!vhandle)
  335. goto out_no_slots;
  336. *(__be32 *)&rsp[TPM_HEADER_SIZE] = cpu_to_be32(vhandle);
  337. break;
  338. case TPM2_HT_HMAC_SESSION:
  339. case TPM2_HT_POLICY_SESSION:
  340. if (!tpm2_add_session(chip, phandle))
  341. goto out_no_slots;
  342. break;
  343. default:
  344. dev_err(&chip->dev, "%s: unknown handle 0x%08X\n",
  345. __func__, phandle);
  346. break;
  347. }
  348. return 0;
  349. out_no_slots:
  350. tpm2_flush_context(chip, phandle);
  351. dev_warn(&chip->dev, "%s: out of slots for 0x%08X\n", __func__,
  352. phandle);
  353. return -ENOMEM;
  354. }
  355. struct tpm2_cap_handles {
  356. u8 more_data;
  357. __be32 capability;
  358. __be32 count;
  359. __be32 handles[];
  360. } __packed;
  361. static int tpm2_map_response_body(struct tpm_chip *chip, u32 cc, u8 *rsp,
  362. size_t len)
  363. {
  364. struct tpm_space *space = &chip->work_space;
  365. struct tpm_header *header = (struct tpm_header *)rsp;
  366. struct tpm2_cap_handles *data;
  367. u32 phandle;
  368. u32 phandle_type;
  369. u32 vhandle;
  370. int i;
  371. int j;
  372. if (cc != TPM2_CC_GET_CAPABILITY ||
  373. be32_to_cpu(header->return_code) != TPM2_RC_SUCCESS) {
  374. return 0;
  375. }
  376. if (len < TPM_HEADER_SIZE + 9)
  377. return -EFAULT;
  378. data = (void *)&rsp[TPM_HEADER_SIZE];
  379. if (be32_to_cpu(data->capability) != TPM2_CAP_HANDLES)
  380. return 0;
  381. if (be32_to_cpu(data->count) > (UINT_MAX - TPM_HEADER_SIZE - 9) / 4)
  382. return -EFAULT;
  383. if (len != TPM_HEADER_SIZE + 9 + 4 * be32_to_cpu(data->count))
  384. return -EFAULT;
  385. for (i = 0, j = 0; i < be32_to_cpu(data->count); i++) {
  386. phandle = be32_to_cpup((__be32 *)&data->handles[i]);
  387. phandle_type = phandle & 0xFF000000;
  388. switch (phandle_type) {
  389. case TPM2_HT_TRANSIENT:
  390. vhandle = tpm2_map_to_vhandle(space, phandle, false);
  391. if (!vhandle)
  392. break;
  393. data->handles[j] = cpu_to_be32(vhandle);
  394. j++;
  395. break;
  396. default:
  397. data->handles[j] = cpu_to_be32(phandle);
  398. j++;
  399. break;
  400. }
  401. }
  402. header->length = cpu_to_be32(TPM_HEADER_SIZE + 9 + 4 * j);
  403. data->count = cpu_to_be32(j);
  404. return 0;
  405. }
  406. static int tpm2_save_space(struct tpm_chip *chip)
  407. {
  408. struct tpm_space *space = &chip->work_space;
  409. unsigned int offset;
  410. int i;
  411. int rc;
  412. for (i = 0, offset = 0; i < ARRAY_SIZE(space->context_tbl); i++) {
  413. if (!(space->context_tbl[i] && ~space->context_tbl[i]))
  414. continue;
  415. rc = tpm2_save_context(chip, space->context_tbl[i],
  416. space->context_buf, space->buf_size,
  417. &offset);
  418. if (rc == -ENOENT) {
  419. space->context_tbl[i] = 0;
  420. continue;
  421. } else if (rc)
  422. return rc;
  423. tpm2_flush_context(chip, space->context_tbl[i]);
  424. space->context_tbl[i] = ~0;
  425. }
  426. for (i = 0, offset = 0; i < ARRAY_SIZE(space->session_tbl); i++) {
  427. if (!space->session_tbl[i])
  428. continue;
  429. rc = tpm2_save_context(chip, space->session_tbl[i],
  430. space->session_buf, space->buf_size,
  431. &offset);
  432. if (rc == -ENOENT) {
  433. /* handle error saving session, just forget it */
  434. space->session_tbl[i] = 0;
  435. } else if (rc < 0) {
  436. tpm2_flush_space(chip);
  437. return rc;
  438. }
  439. }
  440. return 0;
  441. }
  442. int tpm2_commit_space(struct tpm_chip *chip, struct tpm_space *space,
  443. void *buf, size_t *bufsiz)
  444. {
  445. struct tpm_header *header = buf;
  446. int rc;
  447. if (!space)
  448. return 0;
  449. rc = tpm2_map_response_header(chip, chip->last_cc, buf, *bufsiz);
  450. if (rc) {
  451. tpm2_flush_space(chip);
  452. goto out;
  453. }
  454. rc = tpm2_map_response_body(chip, chip->last_cc, buf, *bufsiz);
  455. if (rc) {
  456. tpm2_flush_space(chip);
  457. goto out;
  458. }
  459. rc = tpm2_save_space(chip);
  460. if (rc) {
  461. tpm2_flush_space(chip);
  462. goto out;
  463. }
  464. *bufsiz = be32_to_cpu(header->length);
  465. memcpy(&space->context_tbl, &chip->work_space.context_tbl,
  466. sizeof(space->context_tbl));
  467. memcpy(&space->session_tbl, &chip->work_space.session_tbl,
  468. sizeof(space->session_tbl));
  469. memcpy(space->context_buf, chip->work_space.context_buf,
  470. space->buf_size);
  471. memcpy(space->session_buf, chip->work_space.session_buf,
  472. space->buf_size);
  473. return 0;
  474. out:
  475. dev_err(&chip->dev, "%s: error %d\n", __func__, rc);
  476. return rc;
  477. }
  478. /*
  479. * Put the reference to the main device.
  480. */
  481. static void tpm_devs_release(struct device *dev)
  482. {
  483. struct tpm_chip *chip = container_of(dev, struct tpm_chip, devs);
  484. /* release the master device reference */
  485. put_device(&chip->dev);
  486. }
  487. /*
  488. * Remove the device file for exposed TPM spaces and release the device
  489. * reference. This may also release the reference to the master device.
  490. */
  491. void tpm_devs_remove(struct tpm_chip *chip)
  492. {
  493. cdev_device_del(&chip->cdevs, &chip->devs);
  494. put_device(&chip->devs);
  495. }
  496. /*
  497. * Add a device file to expose TPM spaces. Also take a reference to the
  498. * main device.
  499. */
  500. int tpm_devs_add(struct tpm_chip *chip)
  501. {
  502. int rc;
  503. device_initialize(&chip->devs);
  504. chip->devs.parent = chip->dev.parent;
  505. chip->devs.class = tpmrm_class;
  506. /*
  507. * Get extra reference on main device to hold on behalf of devs.
  508. * This holds the chip structure while cdevs is in use. The
  509. * corresponding put is in the tpm_devs_release.
  510. */
  511. get_device(&chip->dev);
  512. chip->devs.release = tpm_devs_release;
  513. chip->devs.devt = MKDEV(MAJOR(tpm_devt), chip->dev_num + TPM_NUM_DEVICES);
  514. cdev_init(&chip->cdevs, &tpmrm_fops);
  515. chip->cdevs.owner = THIS_MODULE;
  516. rc = dev_set_name(&chip->devs, "tpmrm%d", chip->dev_num);
  517. if (rc)
  518. goto err_put_devs;
  519. rc = cdev_device_add(&chip->cdevs, &chip->devs);
  520. if (rc) {
  521. dev_err(&chip->devs,
  522. "unable to cdev_device_add() %s, major %d, minor %d, err=%d\n",
  523. dev_name(&chip->devs), MAJOR(chip->devs.devt),
  524. MINOR(chip->devs.devt), rc);
  525. goto err_put_devs;
  526. }
  527. return 0;
  528. err_put_devs:
  529. put_device(&chip->devs);
  530. return rc;
  531. }