tpm_test.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright (c) 2015 Google, Inc
  4. */
  5. #include <common.h>
  6. #include <command.h>
  7. #include <environment.h>
  8. #include <tpm-v1.h>
  9. /* Prints error and returns on failure */
  10. #define TPM_CHECK(tpm_command) do { \
  11. uint32_t result; \
  12. \
  13. result = (tpm_command); \
  14. if (result != TPM_SUCCESS) { \
  15. printf("TEST FAILED: line %d: " #tpm_command ": 0x%x\n", \
  16. __LINE__, result); \
  17. return result; \
  18. } \
  19. } while (0)
  20. #define INDEX0 0xda70
  21. #define INDEX1 0xda71
  22. #define INDEX2 0xda72
  23. #define INDEX3 0xda73
  24. #define INDEX_INITIALISED 0xda80
  25. #define PHYS_PRESENCE 4
  26. #define PRESENCE 8
  27. static uint32_t TlclStartupIfNeeded(void)
  28. {
  29. uint32_t result = tpm_startup(TPM_ST_CLEAR);
  30. return result == TPM_INVALID_POSTINIT ? TPM_SUCCESS : result;
  31. }
  32. static int test_timer(void)
  33. {
  34. printf("get_timer(0) = %lu\n", get_timer(0));
  35. return 0;
  36. }
  37. static uint32_t tpm_get_flags(uint8_t *disable, uint8_t *deactivated,
  38. uint8_t *nvlocked)
  39. {
  40. struct tpm_permanent_flags pflags;
  41. uint32_t result;
  42. result = tpm_get_permanent_flags(&pflags);
  43. if (result)
  44. return result;
  45. if (disable)
  46. *disable = pflags.disable;
  47. if (deactivated)
  48. *deactivated = pflags.deactivated;
  49. if (nvlocked)
  50. *nvlocked = pflags.nv_locked;
  51. debug("TPM: Got flags disable=%d, deactivated=%d, nvlocked=%d\n",
  52. pflags.disable, pflags.deactivated, pflags.nv_locked);
  53. return 0;
  54. }
  55. static uint32_t tpm_set_global_lock(void)
  56. {
  57. uint32_t x;
  58. debug("TPM: Set global lock\n");
  59. return tpm_nv_write_value(INDEX0, (uint8_t *)&x, 0);
  60. }
  61. static uint32_t tpm_nv_write_value_lock(uint32_t index)
  62. {
  63. debug("TPM: Write lock 0x%x\n", index);
  64. return tpm_nv_write_value(index, NULL, 0);
  65. }
  66. static uint32_t tpm_nv_set_locked(void)
  67. {
  68. debug("TPM: Set NV locked\n");
  69. return tpm_nv_define_space(TPM_NV_INDEX_LOCK, 0, 0);
  70. }
  71. static int tpm_is_owned(void)
  72. {
  73. uint8_t response[TPM_PUBEK_SIZE];
  74. uint32_t result;
  75. result = tpm_read_pubek(response, sizeof(response));
  76. return result != TPM_SUCCESS;
  77. }
  78. static int test_early_extend(void)
  79. {
  80. uint8_t value_in[20];
  81. uint8_t value_out[20];
  82. printf("Testing earlyextend ...");
  83. tpm_init();
  84. TPM_CHECK(tpm_startup(TPM_ST_CLEAR));
  85. TPM_CHECK(tpm_continue_self_test());
  86. TPM_CHECK(tpm_extend(1, value_in, value_out));
  87. printf("done\n");
  88. return 0;
  89. }
  90. static int test_early_nvram(void)
  91. {
  92. uint32_t x;
  93. printf("Testing earlynvram ...");
  94. tpm_init();
  95. TPM_CHECK(tpm_startup(TPM_ST_CLEAR));
  96. TPM_CHECK(tpm_continue_self_test());
  97. TPM_CHECK(tpm_tsc_physical_presence(PRESENCE));
  98. TPM_CHECK(tpm_nv_read_value(INDEX0, (uint8_t *)&x, sizeof(x)));
  99. printf("done\n");
  100. return 0;
  101. }
  102. static int test_early_nvram2(void)
  103. {
  104. uint32_t x;
  105. printf("Testing earlynvram2 ...");
  106. tpm_init();
  107. TPM_CHECK(tpm_startup(TPM_ST_CLEAR));
  108. TPM_CHECK(tpm_continue_self_test());
  109. TPM_CHECK(tpm_tsc_physical_presence(PRESENCE));
  110. TPM_CHECK(tpm_nv_write_value(INDEX0, (uint8_t *)&x, sizeof(x)));
  111. printf("done\n");
  112. return 0;
  113. }
  114. static int test_enable(void)
  115. {
  116. uint8_t disable = 0, deactivated = 0;
  117. printf("Testing enable ...\n");
  118. tpm_init();
  119. TPM_CHECK(TlclStartupIfNeeded());
  120. TPM_CHECK(tpm_self_test_full());
  121. TPM_CHECK(tpm_tsc_physical_presence(PRESENCE));
  122. TPM_CHECK(tpm_get_flags(&disable, &deactivated, NULL));
  123. printf("\tdisable is %d, deactivated is %d\n", disable, deactivated);
  124. TPM_CHECK(tpm_physical_enable());
  125. TPM_CHECK(tpm_physical_set_deactivated(0));
  126. TPM_CHECK(tpm_get_flags(&disable, &deactivated, NULL));
  127. printf("\tdisable is %d, deactivated is %d\n", disable, deactivated);
  128. if (disable == 1 || deactivated == 1)
  129. printf("\tfailed to enable or activate\n");
  130. printf("\tdone\n");
  131. return 0;
  132. }
  133. #define reboot() do { \
  134. printf("\trebooting...\n"); \
  135. reset_cpu(0); \
  136. } while (0)
  137. static int test_fast_enable(void)
  138. {
  139. uint8_t disable = 0, deactivated = 0;
  140. int i;
  141. printf("Testing fastenable ...\n");
  142. tpm_init();
  143. TPM_CHECK(TlclStartupIfNeeded());
  144. TPM_CHECK(tpm_self_test_full());
  145. TPM_CHECK(tpm_tsc_physical_presence(PRESENCE));
  146. TPM_CHECK(tpm_get_flags(&disable, &deactivated, NULL));
  147. printf("\tdisable is %d, deactivated is %d\n", disable, deactivated);
  148. for (i = 0; i < 2; i++) {
  149. TPM_CHECK(tpm_force_clear());
  150. TPM_CHECK(tpm_get_flags(&disable, &deactivated, NULL));
  151. printf("\tdisable is %d, deactivated is %d\n", disable,
  152. deactivated);
  153. assert(disable == 1 && deactivated == 1);
  154. TPM_CHECK(tpm_physical_enable());
  155. TPM_CHECK(tpm_physical_set_deactivated(0));
  156. TPM_CHECK(tpm_get_flags(&disable, &deactivated, NULL));
  157. printf("\tdisable is %d, deactivated is %d\n", disable,
  158. deactivated);
  159. assert(disable == 0 && deactivated == 0);
  160. }
  161. printf("\tdone\n");
  162. return 0;
  163. }
  164. static int test_global_lock(void)
  165. {
  166. uint32_t zero = 0;
  167. uint32_t result;
  168. uint32_t x;
  169. printf("Testing globallock ...\n");
  170. tpm_init();
  171. TPM_CHECK(TlclStartupIfNeeded());
  172. TPM_CHECK(tpm_self_test_full());
  173. TPM_CHECK(tpm_tsc_physical_presence(PRESENCE));
  174. TPM_CHECK(tpm_nv_read_value(INDEX0, (uint8_t *)&x, sizeof(x)));
  175. TPM_CHECK(tpm_nv_write_value(INDEX0, (uint8_t *)&zero,
  176. sizeof(uint32_t)));
  177. TPM_CHECK(tpm_nv_read_value(INDEX1, (uint8_t *)&x, sizeof(x)));
  178. TPM_CHECK(tpm_nv_write_value(INDEX1, (uint8_t *)&zero,
  179. sizeof(uint32_t)));
  180. TPM_CHECK(tpm_set_global_lock());
  181. /* Verifies that write to index0 fails */
  182. x = 1;
  183. result = tpm_nv_write_value(INDEX0, (uint8_t *)&x, sizeof(x));
  184. assert(result == TPM_AREA_LOCKED);
  185. TPM_CHECK(tpm_nv_read_value(INDEX0, (uint8_t *)&x, sizeof(x)));
  186. assert(x == 0);
  187. /* Verifies that write to index1 is still possible */
  188. x = 2;
  189. TPM_CHECK(tpm_nv_write_value(INDEX1, (uint8_t *)&x, sizeof(x)));
  190. TPM_CHECK(tpm_nv_read_value(INDEX1, (uint8_t *)&x, sizeof(x)));
  191. assert(x == 2);
  192. /* Turns off PP */
  193. tpm_tsc_physical_presence(PHYS_PRESENCE);
  194. /* Verifies that write to index1 fails */
  195. x = 3;
  196. result = tpm_nv_write_value(INDEX1, (uint8_t *)&x, sizeof(x));
  197. assert(result == TPM_BAD_PRESENCE);
  198. TPM_CHECK(tpm_nv_read_value(INDEX1, (uint8_t *)&x, sizeof(x)));
  199. assert(x == 2);
  200. printf("\tdone\n");
  201. return 0;
  202. }
  203. static int test_lock(void)
  204. {
  205. printf("Testing lock ...\n");
  206. tpm_init();
  207. tpm_startup(TPM_ST_CLEAR);
  208. tpm_self_test_full();
  209. tpm_tsc_physical_presence(PRESENCE);
  210. tpm_nv_write_value_lock(INDEX0);
  211. printf("\tLocked 0x%x\n", INDEX0);
  212. printf("\tdone\n");
  213. return 0;
  214. }
  215. static void initialise_spaces(void)
  216. {
  217. uint32_t zero = 0;
  218. uint32_t perm = TPM_NV_PER_WRITE_STCLEAR | TPM_NV_PER_PPWRITE;
  219. printf("\tInitialising spaces\n");
  220. tpm_nv_set_locked(); /* useful only the first time */
  221. tpm_nv_define_space(INDEX0, perm, 4);
  222. tpm_nv_write_value(INDEX0, (uint8_t *)&zero, 4);
  223. tpm_nv_define_space(INDEX1, perm, 4);
  224. tpm_nv_write_value(INDEX1, (uint8_t *)&zero, 4);
  225. tpm_nv_define_space(INDEX2, perm, 4);
  226. tpm_nv_write_value(INDEX2, (uint8_t *)&zero, 4);
  227. tpm_nv_define_space(INDEX3, perm, 4);
  228. tpm_nv_write_value(INDEX3, (uint8_t *)&zero, 4);
  229. perm = TPM_NV_PER_READ_STCLEAR | TPM_NV_PER_WRITE_STCLEAR |
  230. TPM_NV_PER_PPWRITE;
  231. tpm_nv_define_space(INDEX_INITIALISED, perm, 1);
  232. }
  233. static int test_readonly(void)
  234. {
  235. uint8_t c;
  236. uint32_t index_0, index_1, index_2, index_3;
  237. int read0, read1, read2, read3;
  238. printf("Testing readonly ...\n");
  239. tpm_init();
  240. tpm_startup(TPM_ST_CLEAR);
  241. tpm_self_test_full();
  242. tpm_tsc_physical_presence(PRESENCE);
  243. /*
  244. * Checks if initialisation has completed by trying to read-lock a
  245. * space that's created at the end of initialisation
  246. */
  247. if (tpm_nv_read_value(INDEX_INITIALISED, &c, 0) == TPM_BADINDEX) {
  248. /* The initialisation did not complete */
  249. initialise_spaces();
  250. }
  251. /* Checks if spaces are OK or messed up */
  252. read0 = tpm_nv_read_value(INDEX0, (uint8_t *)&index_0, sizeof(index_0));
  253. read1 = tpm_nv_read_value(INDEX1, (uint8_t *)&index_1, sizeof(index_1));
  254. read2 = tpm_nv_read_value(INDEX2, (uint8_t *)&index_2, sizeof(index_2));
  255. read3 = tpm_nv_read_value(INDEX3, (uint8_t *)&index_3, sizeof(index_3));
  256. if (read0 || read1 || read2 || read3) {
  257. printf("Invalid contents\n");
  258. return 0;
  259. }
  260. /*
  261. * Writes space, and locks it. Then attempts to write again.
  262. * I really wish I could use the imperative.
  263. */
  264. index_0 += 1;
  265. if (tpm_nv_write_value(INDEX0, (uint8_t *)&index_0, sizeof(index_0) !=
  266. TPM_SUCCESS)) {
  267. pr_err("\tcould not write index 0\n");
  268. }
  269. tpm_nv_write_value_lock(INDEX0);
  270. if (tpm_nv_write_value(INDEX0, (uint8_t *)&index_0, sizeof(index_0)) ==
  271. TPM_SUCCESS)
  272. pr_err("\tindex 0 is not locked\n");
  273. printf("\tdone\n");
  274. return 0;
  275. }
  276. static int test_redefine_unowned(void)
  277. {
  278. uint32_t perm;
  279. uint32_t result;
  280. uint32_t x;
  281. printf("Testing redefine_unowned ...");
  282. tpm_init();
  283. TPM_CHECK(TlclStartupIfNeeded());
  284. TPM_CHECK(tpm_self_test_full());
  285. TPM_CHECK(tpm_tsc_physical_presence(PRESENCE));
  286. assert(!tpm_is_owned());
  287. /* Ensures spaces exist. */
  288. TPM_CHECK(tpm_nv_read_value(INDEX0, (uint8_t *)&x, sizeof(x)));
  289. TPM_CHECK(tpm_nv_read_value(INDEX1, (uint8_t *)&x, sizeof(x)));
  290. /* Redefines spaces a couple of times. */
  291. perm = TPM_NV_PER_PPWRITE | TPM_NV_PER_GLOBALLOCK;
  292. TPM_CHECK(tpm_nv_define_space(INDEX0, perm, 2 * sizeof(uint32_t)));
  293. TPM_CHECK(tpm_nv_define_space(INDEX0, perm, sizeof(uint32_t)));
  294. perm = TPM_NV_PER_PPWRITE;
  295. TPM_CHECK(tpm_nv_define_space(INDEX1, perm, 2 * sizeof(uint32_t)));
  296. TPM_CHECK(tpm_nv_define_space(INDEX1, perm, sizeof(uint32_t)));
  297. /* Sets the global lock */
  298. tpm_set_global_lock();
  299. /* Verifies that index0 cannot be redefined */
  300. result = tpm_nv_define_space(INDEX0, perm, sizeof(uint32_t));
  301. assert(result == TPM_AREA_LOCKED);
  302. /* Checks that index1 can */
  303. TPM_CHECK(tpm_nv_define_space(INDEX1, perm, 2 * sizeof(uint32_t)));
  304. TPM_CHECK(tpm_nv_define_space(INDEX1, perm, sizeof(uint32_t)));
  305. /* Turns off PP */
  306. tpm_tsc_physical_presence(PHYS_PRESENCE);
  307. /* Verifies that neither index0 nor index1 can be redefined */
  308. result = tpm_nv_define_space(INDEX0, perm, sizeof(uint32_t));
  309. assert(result == TPM_BAD_PRESENCE);
  310. result = tpm_nv_define_space(INDEX1, perm, sizeof(uint32_t));
  311. assert(result == TPM_BAD_PRESENCE);
  312. printf("done\n");
  313. return 0;
  314. }
  315. #define PERMPPGL (TPM_NV_PER_PPWRITE | TPM_NV_PER_GLOBALLOCK)
  316. #define PERMPP TPM_NV_PER_PPWRITE
  317. static int test_space_perm(void)
  318. {
  319. uint32_t perm;
  320. printf("Testing spaceperm ...");
  321. tpm_init();
  322. TPM_CHECK(TlclStartupIfNeeded());
  323. TPM_CHECK(tpm_continue_self_test());
  324. TPM_CHECK(tpm_tsc_physical_presence(PRESENCE));
  325. TPM_CHECK(tpm_get_permissions(INDEX0, &perm));
  326. assert((perm & PERMPPGL) == PERMPPGL);
  327. TPM_CHECK(tpm_get_permissions(INDEX1, &perm));
  328. assert((perm & PERMPP) == PERMPP);
  329. printf("done\n");
  330. return 0;
  331. }
  332. static int test_startup(void)
  333. {
  334. uint32_t result;
  335. printf("Testing startup ...\n");
  336. tpm_init();
  337. result = tpm_startup(TPM_ST_CLEAR);
  338. if (result != 0 && result != TPM_INVALID_POSTINIT)
  339. printf("\ttpm startup failed with 0x%x\n", result);
  340. result = tpm_get_flags(NULL, NULL, NULL);
  341. if (result != 0)
  342. printf("\ttpm getflags failed with 0x%x\n", result);
  343. printf("\texecuting SelfTestFull\n");
  344. tpm_self_test_full();
  345. result = tpm_get_flags(NULL, NULL, NULL);
  346. if (result != 0)
  347. printf("\ttpm getflags failed with 0x%x\n", result);
  348. printf("\tdone\n");
  349. return 0;
  350. }
  351. /*
  352. * Runs [op] and ensures it returns success and doesn't run longer than
  353. * [time_limit] in milliseconds.
  354. */
  355. #define TTPM_CHECK(op, time_limit) do { \
  356. ulong start, time; \
  357. uint32_t __result; \
  358. \
  359. start = get_timer(0); \
  360. __result = op; \
  361. if (__result != TPM_SUCCESS) { \
  362. printf("\t" #op ": error 0x%x\n", __result); \
  363. return -1; \
  364. } \
  365. time = get_timer(start); \
  366. printf("\t" #op ": %lu ms\n", time); \
  367. if (time > (ulong)time_limit) { \
  368. printf("\t" #op " exceeded " #time_limit " ms\n"); \
  369. } \
  370. } while (0)
  371. static int test_timing(void)
  372. {
  373. uint32_t x;
  374. uint8_t in[20], out[20];
  375. printf("Testing timing ...");
  376. tpm_init();
  377. TTPM_CHECK(TlclStartupIfNeeded(), 50);
  378. TTPM_CHECK(tpm_continue_self_test(), 100);
  379. TTPM_CHECK(tpm_self_test_full(), 1000);
  380. TTPM_CHECK(tpm_tsc_physical_presence(PRESENCE), 100);
  381. TTPM_CHECK(tpm_nv_write_value(INDEX0, (uint8_t *)&x, sizeof(x)), 100);
  382. TTPM_CHECK(tpm_nv_read_value(INDEX0, (uint8_t *)&x, sizeof(x)), 100);
  383. TTPM_CHECK(tpm_extend(0, in, out), 200);
  384. TTPM_CHECK(tpm_set_global_lock(), 50);
  385. TTPM_CHECK(tpm_tsc_physical_presence(PHYS_PRESENCE), 100);
  386. printf("done\n");
  387. return 0;
  388. }
  389. #define TPM_MAX_NV_WRITES_NOOWNER 64
  390. static int test_write_limit(void)
  391. {
  392. printf("Testing writelimit ...\n");
  393. int i;
  394. uint32_t result;
  395. tpm_init();
  396. TPM_CHECK(TlclStartupIfNeeded());
  397. TPM_CHECK(tpm_self_test_full());
  398. TPM_CHECK(tpm_tsc_physical_presence(PRESENCE));
  399. TPM_CHECK(tpm_force_clear());
  400. TPM_CHECK(tpm_physical_enable());
  401. TPM_CHECK(tpm_physical_set_deactivated(0));
  402. for (i = 0; i < TPM_MAX_NV_WRITES_NOOWNER + 2; i++) {
  403. printf("\twriting %d\n", i);
  404. result = tpm_nv_write_value(INDEX0, (uint8_t *)&i, sizeof(i));
  405. switch (result) {
  406. case TPM_SUCCESS:
  407. break;
  408. case TPM_MAXNVWRITES:
  409. assert(i >= TPM_MAX_NV_WRITES_NOOWNER);
  410. default:
  411. pr_err("\tunexpected error code %d (0x%x)\n",
  412. result, result);
  413. }
  414. }
  415. /* Reset write count */
  416. TPM_CHECK(tpm_force_clear());
  417. TPM_CHECK(tpm_physical_enable());
  418. TPM_CHECK(tpm_physical_set_deactivated(0));
  419. /* Try writing again. */
  420. TPM_CHECK(tpm_nv_write_value(INDEX0, (uint8_t *)&i, sizeof(i)));
  421. printf("\tdone\n");
  422. return 0;
  423. }
  424. #define VOIDTEST(XFUNC) \
  425. int do_test_##XFUNC(cmd_tbl_t *cmd_tbl, int flag, int argc, \
  426. char * const argv[]) \
  427. { \
  428. return test_##XFUNC(); \
  429. }
  430. #define VOIDENT(XNAME) \
  431. U_BOOT_CMD_MKENT(XNAME, 0, 1, do_test_##XNAME, "", ""),
  432. VOIDTEST(early_extend)
  433. VOIDTEST(early_nvram)
  434. VOIDTEST(early_nvram2)
  435. VOIDTEST(enable)
  436. VOIDTEST(fast_enable)
  437. VOIDTEST(global_lock)
  438. VOIDTEST(lock)
  439. VOIDTEST(readonly)
  440. VOIDTEST(redefine_unowned)
  441. VOIDTEST(space_perm)
  442. VOIDTEST(startup)
  443. VOIDTEST(timing)
  444. VOIDTEST(write_limit)
  445. VOIDTEST(timer)
  446. static cmd_tbl_t cmd_cros_tpm_sub[] = {
  447. VOIDENT(early_extend)
  448. VOIDENT(early_nvram)
  449. VOIDENT(early_nvram2)
  450. VOIDENT(enable)
  451. VOIDENT(fast_enable)
  452. VOIDENT(global_lock)
  453. VOIDENT(lock)
  454. VOIDENT(readonly)
  455. VOIDENT(redefine_unowned)
  456. VOIDENT(space_perm)
  457. VOIDENT(startup)
  458. VOIDENT(timing)
  459. VOIDENT(write_limit)
  460. VOIDENT(timer)
  461. };
  462. static int do_tpmtest(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
  463. {
  464. cmd_tbl_t *c;
  465. int i;
  466. printf("argc = %d, argv = ", argc);
  467. for (i = 0; i < argc; i++)
  468. printf(" %s", argv[i]);
  469. printf("\n------\n");
  470. argc--;
  471. argv++;
  472. c = find_cmd_tbl(argv[0], cmd_cros_tpm_sub,
  473. ARRAY_SIZE(cmd_cros_tpm_sub));
  474. return c ? c->cmd(cmdtp, flag, argc, argv) : cmd_usage(cmdtp);
  475. }
  476. U_BOOT_CMD(tpmtest, 2, 1, do_tpmtest, "TPM tests",
  477. "\n\tearly_extend\n"
  478. "\tearly_nvram\n"
  479. "\tearly_nvram2\n"
  480. "\tenable\n"
  481. "\tfast_enable\n"
  482. "\tglobal_lock\n"
  483. "\tlock\n"
  484. "\treadonly\n"
  485. "\tredefine_unowned\n"
  486. "\tspace_perm\n"
  487. "\tstartup\n"
  488. "\ttiming\n"
  489. "\twrite_limit\n");