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