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