tpm.c 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453
  1. /*
  2. * Copyright (C) 2011 Infineon Technologies
  3. *
  4. * Authors:
  5. * Peter Huewe <huewe.external@infineon.com>
  6. *
  7. * Description:
  8. * Device driver for TCG/TCPA TPM (trusted platform module).
  9. * Specifications at www.trustedcomputinggroup.org
  10. *
  11. * It is based on the Linux kernel driver tpm.c from Leendert van
  12. * Dorn, Dave Safford, Reiner Sailer, and Kyleen Hall.
  13. *
  14. * Version: 2.1.1
  15. *
  16. * See file CREDITS for list of people who contributed to this
  17. * project.
  18. *
  19. * This program is free software; you can redistribute it and/or
  20. * modify it under the terms of the GNU General Public License as
  21. * published by the Free Software Foundation, version 2 of the
  22. * License.
  23. *
  24. * This program is distributed in the hope that it will be useful,
  25. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  26. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  27. * GNU General Public License for more details.
  28. *
  29. * You should have received a copy of the GNU General Public License
  30. * along with this program; if not, write to the Free Software
  31. * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  32. * MA 02111-1307 USA
  33. */
  34. #include <malloc.h>
  35. #include "tpm.h"
  36. /* global structure for tpm chip data */
  37. struct tpm_chip g_chip;
  38. enum tpm_duration {
  39. TPM_SHORT = 0,
  40. TPM_MEDIUM = 1,
  41. TPM_LONG = 2,
  42. TPM_UNDEFINED,
  43. };
  44. #define TPM_MAX_ORDINAL 243
  45. #define TPM_MAX_PROTECTED_ORDINAL 12
  46. #define TPM_PROTECTED_ORDINAL_MASK 0xFF
  47. /*
  48. * Array with one entry per ordinal defining the maximum amount
  49. * of time the chip could take to return the result. The ordinal
  50. * designation of short, medium or long is defined in a table in
  51. * TCG Specification TPM Main Part 2 TPM Structures Section 17. The
  52. * values of the SHORT, MEDIUM, and LONG durations are retrieved
  53. * from the chip during initialization with a call to tpm_get_timeouts.
  54. */
  55. static const u8 tpm_protected_ordinal_duration[TPM_MAX_PROTECTED_ORDINAL] = {
  56. TPM_UNDEFINED, /* 0 */
  57. TPM_UNDEFINED,
  58. TPM_UNDEFINED,
  59. TPM_UNDEFINED,
  60. TPM_UNDEFINED,
  61. TPM_UNDEFINED, /* 5 */
  62. TPM_UNDEFINED,
  63. TPM_UNDEFINED,
  64. TPM_UNDEFINED,
  65. TPM_UNDEFINED,
  66. TPM_SHORT, /* 10 */
  67. TPM_SHORT,
  68. };
  69. static const u8 tpm_ordinal_duration[TPM_MAX_ORDINAL] = {
  70. TPM_UNDEFINED, /* 0 */
  71. TPM_UNDEFINED,
  72. TPM_UNDEFINED,
  73. TPM_UNDEFINED,
  74. TPM_UNDEFINED,
  75. TPM_UNDEFINED, /* 5 */
  76. TPM_UNDEFINED,
  77. TPM_UNDEFINED,
  78. TPM_UNDEFINED,
  79. TPM_UNDEFINED,
  80. TPM_SHORT, /* 10 */
  81. TPM_SHORT,
  82. TPM_MEDIUM,
  83. TPM_LONG,
  84. TPM_LONG,
  85. TPM_MEDIUM, /* 15 */
  86. TPM_SHORT,
  87. TPM_SHORT,
  88. TPM_MEDIUM,
  89. TPM_LONG,
  90. TPM_SHORT, /* 20 */
  91. TPM_SHORT,
  92. TPM_MEDIUM,
  93. TPM_MEDIUM,
  94. TPM_MEDIUM,
  95. TPM_SHORT, /* 25 */
  96. TPM_SHORT,
  97. TPM_MEDIUM,
  98. TPM_SHORT,
  99. TPM_SHORT,
  100. TPM_MEDIUM, /* 30 */
  101. TPM_LONG,
  102. TPM_MEDIUM,
  103. TPM_SHORT,
  104. TPM_SHORT,
  105. TPM_SHORT, /* 35 */
  106. TPM_MEDIUM,
  107. TPM_MEDIUM,
  108. TPM_UNDEFINED,
  109. TPM_UNDEFINED,
  110. TPM_MEDIUM, /* 40 */
  111. TPM_LONG,
  112. TPM_MEDIUM,
  113. TPM_SHORT,
  114. TPM_SHORT,
  115. TPM_SHORT, /* 45 */
  116. TPM_SHORT,
  117. TPM_SHORT,
  118. TPM_SHORT,
  119. TPM_LONG,
  120. TPM_MEDIUM, /* 50 */
  121. TPM_MEDIUM,
  122. TPM_UNDEFINED,
  123. TPM_UNDEFINED,
  124. TPM_UNDEFINED,
  125. TPM_UNDEFINED, /* 55 */
  126. TPM_UNDEFINED,
  127. TPM_UNDEFINED,
  128. TPM_UNDEFINED,
  129. TPM_UNDEFINED,
  130. TPM_MEDIUM, /* 60 */
  131. TPM_MEDIUM,
  132. TPM_MEDIUM,
  133. TPM_SHORT,
  134. TPM_SHORT,
  135. TPM_MEDIUM, /* 65 */
  136. TPM_UNDEFINED,
  137. TPM_UNDEFINED,
  138. TPM_UNDEFINED,
  139. TPM_UNDEFINED,
  140. TPM_SHORT, /* 70 */
  141. TPM_SHORT,
  142. TPM_UNDEFINED,
  143. TPM_UNDEFINED,
  144. TPM_UNDEFINED,
  145. TPM_UNDEFINED, /* 75 */
  146. TPM_UNDEFINED,
  147. TPM_UNDEFINED,
  148. TPM_UNDEFINED,
  149. TPM_UNDEFINED,
  150. TPM_LONG, /* 80 */
  151. TPM_UNDEFINED,
  152. TPM_MEDIUM,
  153. TPM_LONG,
  154. TPM_SHORT,
  155. TPM_UNDEFINED, /* 85 */
  156. TPM_UNDEFINED,
  157. TPM_UNDEFINED,
  158. TPM_UNDEFINED,
  159. TPM_UNDEFINED,
  160. TPM_SHORT, /* 90 */
  161. TPM_SHORT,
  162. TPM_SHORT,
  163. TPM_SHORT,
  164. TPM_SHORT,
  165. TPM_UNDEFINED, /* 95 */
  166. TPM_UNDEFINED,
  167. TPM_UNDEFINED,
  168. TPM_UNDEFINED,
  169. TPM_UNDEFINED,
  170. TPM_MEDIUM, /* 100 */
  171. TPM_SHORT,
  172. TPM_SHORT,
  173. TPM_UNDEFINED,
  174. TPM_UNDEFINED,
  175. TPM_UNDEFINED, /* 105 */
  176. TPM_UNDEFINED,
  177. TPM_UNDEFINED,
  178. TPM_UNDEFINED,
  179. TPM_UNDEFINED,
  180. TPM_SHORT, /* 110 */
  181. TPM_SHORT,
  182. TPM_SHORT,
  183. TPM_SHORT,
  184. TPM_SHORT,
  185. TPM_SHORT, /* 115 */
  186. TPM_SHORT,
  187. TPM_SHORT,
  188. TPM_UNDEFINED,
  189. TPM_UNDEFINED,
  190. TPM_LONG, /* 120 */
  191. TPM_LONG,
  192. TPM_MEDIUM,
  193. TPM_UNDEFINED,
  194. TPM_SHORT,
  195. TPM_SHORT, /* 125 */
  196. TPM_SHORT,
  197. TPM_LONG,
  198. TPM_SHORT,
  199. TPM_SHORT,
  200. TPM_SHORT, /* 130 */
  201. TPM_MEDIUM,
  202. TPM_UNDEFINED,
  203. TPM_SHORT,
  204. TPM_MEDIUM,
  205. TPM_UNDEFINED, /* 135 */
  206. TPM_UNDEFINED,
  207. TPM_UNDEFINED,
  208. TPM_UNDEFINED,
  209. TPM_UNDEFINED,
  210. TPM_SHORT, /* 140 */
  211. TPM_SHORT,
  212. TPM_UNDEFINED,
  213. TPM_UNDEFINED,
  214. TPM_UNDEFINED,
  215. TPM_UNDEFINED, /* 145 */
  216. TPM_UNDEFINED,
  217. TPM_UNDEFINED,
  218. TPM_UNDEFINED,
  219. TPM_UNDEFINED,
  220. TPM_SHORT, /* 150 */
  221. TPM_MEDIUM,
  222. TPM_MEDIUM,
  223. TPM_SHORT,
  224. TPM_SHORT,
  225. TPM_UNDEFINED, /* 155 */
  226. TPM_UNDEFINED,
  227. TPM_UNDEFINED,
  228. TPM_UNDEFINED,
  229. TPM_UNDEFINED,
  230. TPM_SHORT, /* 160 */
  231. TPM_SHORT,
  232. TPM_SHORT,
  233. TPM_SHORT,
  234. TPM_UNDEFINED,
  235. TPM_UNDEFINED, /* 165 */
  236. TPM_UNDEFINED,
  237. TPM_UNDEFINED,
  238. TPM_UNDEFINED,
  239. TPM_UNDEFINED,
  240. TPM_LONG, /* 170 */
  241. TPM_UNDEFINED,
  242. TPM_UNDEFINED,
  243. TPM_UNDEFINED,
  244. TPM_UNDEFINED,
  245. TPM_UNDEFINED, /* 175 */
  246. TPM_UNDEFINED,
  247. TPM_UNDEFINED,
  248. TPM_UNDEFINED,
  249. TPM_UNDEFINED,
  250. TPM_MEDIUM, /* 180 */
  251. TPM_SHORT,
  252. TPM_MEDIUM,
  253. TPM_MEDIUM,
  254. TPM_MEDIUM,
  255. TPM_MEDIUM, /* 185 */
  256. TPM_SHORT,
  257. TPM_UNDEFINED,
  258. TPM_UNDEFINED,
  259. TPM_UNDEFINED,
  260. TPM_UNDEFINED, /* 190 */
  261. TPM_UNDEFINED,
  262. TPM_UNDEFINED,
  263. TPM_UNDEFINED,
  264. TPM_UNDEFINED,
  265. TPM_UNDEFINED, /* 195 */
  266. TPM_UNDEFINED,
  267. TPM_UNDEFINED,
  268. TPM_UNDEFINED,
  269. TPM_UNDEFINED,
  270. TPM_SHORT, /* 200 */
  271. TPM_UNDEFINED,
  272. TPM_UNDEFINED,
  273. TPM_UNDEFINED,
  274. TPM_SHORT,
  275. TPM_SHORT, /* 205 */
  276. TPM_SHORT,
  277. TPM_SHORT,
  278. TPM_SHORT,
  279. TPM_SHORT,
  280. TPM_MEDIUM, /* 210 */
  281. TPM_UNDEFINED,
  282. TPM_MEDIUM,
  283. TPM_MEDIUM,
  284. TPM_MEDIUM,
  285. TPM_UNDEFINED, /* 215 */
  286. TPM_MEDIUM,
  287. TPM_UNDEFINED,
  288. TPM_UNDEFINED,
  289. TPM_SHORT,
  290. TPM_SHORT, /* 220 */
  291. TPM_SHORT,
  292. TPM_SHORT,
  293. TPM_SHORT,
  294. TPM_SHORT,
  295. TPM_UNDEFINED, /* 225 */
  296. TPM_UNDEFINED,
  297. TPM_UNDEFINED,
  298. TPM_UNDEFINED,
  299. TPM_UNDEFINED,
  300. TPM_SHORT, /* 230 */
  301. TPM_LONG,
  302. TPM_MEDIUM,
  303. TPM_UNDEFINED,
  304. TPM_UNDEFINED,
  305. TPM_UNDEFINED, /* 235 */
  306. TPM_UNDEFINED,
  307. TPM_UNDEFINED,
  308. TPM_UNDEFINED,
  309. TPM_UNDEFINED,
  310. TPM_SHORT, /* 240 */
  311. TPM_UNDEFINED,
  312. TPM_MEDIUM,
  313. };
  314. /*
  315. * Returns max number of milliseconds to wait
  316. */
  317. unsigned long tpm_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal)
  318. {
  319. int duration_idx = TPM_UNDEFINED;
  320. int duration = 0;
  321. if (ordinal < TPM_MAX_ORDINAL)
  322. duration_idx = tpm_ordinal_duration[ordinal];
  323. else if ((ordinal & TPM_PROTECTED_ORDINAL_MASK) <
  324. TPM_MAX_PROTECTED_ORDINAL)
  325. duration_idx =
  326. tpm_protected_ordinal_duration[ordinal &
  327. TPM_PROTECTED_ORDINAL_MASK];
  328. if (duration_idx != TPM_UNDEFINED)
  329. duration = chip->vendor.duration[duration_idx];
  330. if (duration <= 0)
  331. return 2 * 60 * HZ; /*two minutes timeout*/
  332. else
  333. return duration;
  334. }
  335. #define TPM_CMD_COUNT_BYTE 2
  336. #define TPM_CMD_ORDINAL_BYTE 6
  337. ssize_t tpm_transmit(const unsigned char *buf, size_t bufsiz)
  338. {
  339. ssize_t rc;
  340. u32 count, ordinal;
  341. unsigned long start, stop;
  342. struct tpm_chip *chip = &g_chip;
  343. /* switch endianess: big->little */
  344. count = get_unaligned_be32(buf + TPM_CMD_COUNT_BYTE);
  345. ordinal = get_unaligned_be32(buf + TPM_CMD_ORDINAL_BYTE);
  346. if (count == 0) {
  347. dev_err(chip->dev, "no data\n");
  348. return -ENODATA;
  349. }
  350. if (count > bufsiz) {
  351. dev_err(chip->dev,
  352. "invalid count value %x %zx\n", count, bufsiz);
  353. return -E2BIG;
  354. }
  355. rc = chip->vendor.send(chip, (u8 *)buf, count);
  356. if (rc < 0) {
  357. dev_err(chip->dev, "tpm_transmit: tpm_send: error %zd\n", rc);
  358. goto out;
  359. }
  360. if (chip->vendor.irq)
  361. goto out_recv;
  362. start = get_timer(0);
  363. stop = tpm_calc_ordinal_duration(chip, ordinal);
  364. do {
  365. dbg_printf("waiting for status...\n");
  366. u8 status = chip->vendor.status(chip);
  367. if ((status & chip->vendor.req_complete_mask) ==
  368. chip->vendor.req_complete_val) {
  369. dbg_printf("...got it;\n");
  370. goto out_recv;
  371. }
  372. if ((status == chip->vendor.req_canceled)) {
  373. dev_err(chip->dev, "Operation Canceled\n");
  374. rc = -ECANCELED;
  375. goto out;
  376. }
  377. msleep(TPM_TIMEOUT);
  378. } while (get_timer(start) < stop);
  379. chip->vendor.cancel(chip);
  380. dev_err(chip->dev, "Operation Timed out\n");
  381. rc = -ETIME;
  382. goto out;
  383. out_recv:
  384. dbg_printf("out_recv: reading response...\n");
  385. rc = chip->vendor.recv(chip, (u8 *)buf, TPM_BUFSIZE);
  386. if (rc < 0)
  387. dev_err(chip->dev, "tpm_transmit: tpm_recv: error %zd\n", rc);
  388. out:
  389. return rc;
  390. }
  391. #define TPM_ERROR_SIZE 10
  392. enum tpm_capabilities {
  393. TPM_CAP_PROP = cpu_to_be32(5),
  394. };
  395. enum tpm_sub_capabilities {
  396. TPM_CAP_PROP_TIS_TIMEOUT = cpu_to_be32(0x115),
  397. TPM_CAP_PROP_TIS_DURATION = cpu_to_be32(0x120),
  398. };
  399. struct tpm_chip *tpm_register_hardware(const struct tpm_vendor_specific *entry)
  400. {
  401. struct tpm_chip *chip;
  402. /* Driver specific per-device data */
  403. chip = &g_chip;
  404. memcpy(&chip->vendor, entry, sizeof(struct tpm_vendor_specific));
  405. chip->is_open = 1;
  406. return chip;
  407. }
  408. int tpm_open(uint32_t dev_addr)
  409. {
  410. int rc;
  411. if (g_chip.is_open)
  412. return -EBUSY;
  413. rc = tpm_vendor_init(dev_addr);
  414. if (rc < 0)
  415. g_chip.is_open = 0;
  416. return rc;
  417. }
  418. void tpm_close(void)
  419. {
  420. if (g_chip.is_open) {
  421. tpm_vendor_cleanup(&g_chip);
  422. g_chip.is_open = 0;
  423. }
  424. }