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