1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Copyright (c) 2018, Bootlin 4 * Author: Miquel Raynal <miquel.raynal@bootlin.com> 5 */ 6 7 #include <common.h> 8 #include <dm.h> 9 #include <tpm-v2.h> 10 #include <asm/state.h> 11 #include <asm/unaligned.h> 12 #include <linux/crc8.h> 13 14 /* Hierarchies */ 15 enum tpm2_hierarchy { 16 TPM2_HIERARCHY_LOCKOUT = 0, 17 TPM2_HIERARCHY_ENDORSEMENT, 18 TPM2_HIERARCHY_PLATFORM, 19 TPM2_HIERARCHY_NB, 20 }; 21 22 /* Subset of supported properties */ 23 #define TPM2_PROPERTIES_OFFSET 0x0000020E 24 25 enum tpm2_cap_tpm_property { 26 TPM2_FAIL_COUNTER = 0, 27 TPM2_PROP_MAX_TRIES, 28 TPM2_RECOVERY_TIME, 29 TPM2_LOCKOUT_RECOVERY, 30 TPM2_PROPERTY_NB, 31 }; 32 33 #define SANDBOX_TPM_PCR_NB TPM2_MAX_PCRS 34 #define SANDBOX_TPM_PCR_SELECT_MAX ((SANDBOX_TPM_PCR_NB + 7) / 8) 35 36 static const u8 sandbox_extended_once_pcr[] = { 37 0xf5, 0xa5, 0xfd, 0x42, 0xd1, 0x6a, 0x20, 0x30, 38 0x27, 0x98, 0xef, 0x6e, 0xd3, 0x09, 0x97, 0x9b, 39 0x43, 0x00, 0x3d, 0x23, 0x20, 0xd9, 0xf0, 0xe8, 40 0xea, 0x98, 0x31, 0xa9, 0x27, 0x59, 0xfb, 0x4b, 41 }; 42 43 struct sandbox_tpm2 { 44 /* TPM internal states */ 45 bool init_done; 46 bool startup_done; 47 bool tests_done; 48 /* TPM password per hierarchy */ 49 char pw[TPM2_HIERARCHY_NB][TPM2_DIGEST_LEN + 1]; 50 int pw_sz[TPM2_HIERARCHY_NB]; 51 /* TPM properties */ 52 u32 properties[TPM2_PROPERTY_NB]; 53 /* TPM PCRs */ 54 u8 pcr[SANDBOX_TPM_PCR_NB][TPM2_DIGEST_LEN]; 55 /* TPM PCR extensions */ 56 u32 pcr_extensions[SANDBOX_TPM_PCR_NB]; 57 }; 58 59 /* 60 * Check the tag validity depending on the command (authentication required or 61 * not). If authentication is required, check it is valid. Update the auth 62 * pointer to point to the next chunk of data to process if needed. 63 */ 64 static int sandbox_tpm2_check_session(struct udevice *dev, u32 command, u16 tag, 65 const u8 **auth, 66 enum tpm2_hierarchy *hierarchy) 67 { 68 struct sandbox_tpm2 *tpm = dev_get_priv(dev); 69 u32 handle, auth_sz, session_handle; 70 u16 nonce_sz, pw_sz; 71 const char *pw; 72 73 switch (command) { 74 case TPM2_CC_STARTUP: 75 case TPM2_CC_SELF_TEST: 76 case TPM2_CC_GET_CAPABILITY: 77 case TPM2_CC_PCR_READ: 78 if (tag != TPM2_ST_NO_SESSIONS) { 79 printf("No session required for command 0x%x\n", 80 command); 81 return TPM2_RC_BAD_TAG; 82 } 83 84 return 0; 85 86 case TPM2_CC_CLEAR: 87 case TPM2_CC_HIERCHANGEAUTH: 88 case TPM2_CC_DAM_RESET: 89 case TPM2_CC_DAM_PARAMETERS: 90 case TPM2_CC_PCR_EXTEND: 91 if (tag != TPM2_ST_SESSIONS) { 92 printf("Session required for command 0x%x\n", command); 93 return TPM2_RC_AUTH_CONTEXT; 94 } 95 96 handle = get_unaligned_be32(*auth); 97 *auth += sizeof(handle); 98 99 /* 100 * PCR_Extend had a different protection mechanism and does not 101 * use the same standards as other commands. 102 */ 103 if (command == TPM2_CC_PCR_EXTEND) 104 break; 105 106 switch (handle) { 107 case TPM2_RH_LOCKOUT: 108 *hierarchy = TPM2_HIERARCHY_LOCKOUT; 109 break; 110 case TPM2_RH_ENDORSEMENT: 111 if (command == TPM2_CC_CLEAR) { 112 printf("Endorsement hierarchy unsupported\n"); 113 return TPM2_RC_AUTH_MISSING; 114 } 115 *hierarchy = TPM2_HIERARCHY_ENDORSEMENT; 116 break; 117 case TPM2_RH_PLATFORM: 118 *hierarchy = TPM2_HIERARCHY_PLATFORM; 119 break; 120 default: 121 printf("Wrong handle 0x%x\n", handle); 122 return TPM2_RC_VALUE; 123 } 124 125 break; 126 127 default: 128 printf("Command code not recognized: 0x%x\n", command); 129 return TPM2_RC_COMMAND_CODE; 130 } 131 132 auth_sz = get_unaligned_be32(*auth); 133 *auth += sizeof(auth_sz); 134 135 session_handle = get_unaligned_be32(*auth); 136 *auth += sizeof(session_handle); 137 if (session_handle != TPM2_RS_PW) { 138 printf("Wrong session handle 0x%x\n", session_handle); 139 return TPM2_RC_VALUE; 140 } 141 142 nonce_sz = get_unaligned_be16(*auth); 143 *auth += sizeof(nonce_sz); 144 if (nonce_sz) { 145 printf("Nonces not supported in Sandbox, aborting\n"); 146 return TPM2_RC_HANDLE; 147 } 148 149 /* Ignore attributes */ 150 *auth += sizeof(u8); 151 152 pw_sz = get_unaligned_be16(*auth); 153 *auth += sizeof(pw_sz); 154 if (auth_sz != (9 + nonce_sz + pw_sz)) { 155 printf("Authentication size (%d) do not match %d\n", 156 auth_sz, 9 + nonce_sz + pw_sz); 157 return TPM2_RC_SIZE; 158 } 159 160 /* No passwork is acceptable */ 161 if (!pw_sz && !tpm->pw_sz[*hierarchy]) 162 return TPM2_RC_SUCCESS; 163 164 /* Password is too long */ 165 if (pw_sz > TPM2_DIGEST_LEN) { 166 printf("Password should not be more than %dB\n", 167 TPM2_DIGEST_LEN); 168 return TPM2_RC_AUTHSIZE; 169 } 170 171 pw = (const char *)*auth; 172 *auth += pw_sz; 173 174 /* Password is wrong */ 175 if (pw_sz != tpm->pw_sz[*hierarchy] || 176 strncmp(pw, tpm->pw[*hierarchy], tpm->pw_sz[*hierarchy])) { 177 printf("Authentication failed: wrong password.\n"); 178 return TPM2_RC_BAD_AUTH; 179 } 180 181 return TPM2_RC_SUCCESS; 182 } 183 184 static int sandbox_tpm2_check_readyness(struct udevice *dev, int command) 185 { 186 struct sandbox_tpm2 *tpm = dev_get_priv(dev); 187 188 switch (command) { 189 case TPM2_CC_STARTUP: 190 if (!tpm->init_done || tpm->startup_done) 191 return TPM2_RC_INITIALIZE; 192 193 break; 194 case TPM2_CC_GET_CAPABILITY: 195 if (!tpm->init_done || !tpm->startup_done) 196 return TPM2_RC_INITIALIZE; 197 198 break; 199 case TPM2_CC_SELF_TEST: 200 if (!tpm->startup_done) 201 return TPM2_RC_INITIALIZE; 202 203 break; 204 default: 205 if (!tpm->tests_done) 206 return TPM2_RC_NEEDS_TEST; 207 208 break; 209 } 210 211 return 0; 212 } 213 214 static int sandbox_tpm2_fill_buf(u8 *recv, size_t *recv_len, u16 tag, u32 rc) 215 { 216 *recv_len = sizeof(tag) + sizeof(u32) + sizeof(rc); 217 218 /* Write tag */ 219 put_unaligned_be16(tag, recv); 220 recv += sizeof(tag); 221 222 /* Write length */ 223 put_unaligned_be32(*recv_len, recv); 224 recv += sizeof(u32); 225 226 /* Write return code */ 227 put_unaligned_be32(rc, recv); 228 recv += sizeof(rc); 229 230 /* Add trailing \0 */ 231 *recv = '\0'; 232 233 return 0; 234 } 235 236 static int sandbox_tpm2_extend(struct udevice *dev, int pcr_index, 237 const u8 *extension) 238 { 239 struct sandbox_tpm2 *tpm = dev_get_priv(dev); 240 int i; 241 242 /* Only simulate the first extensions from all '0' with only '0' */ 243 for (i = 0; i < TPM2_DIGEST_LEN; i++) 244 if (tpm->pcr[pcr_index][i] || extension[i]) 245 return TPM2_RC_FAILURE; 246 247 memcpy(tpm->pcr[pcr_index], sandbox_extended_once_pcr, 248 TPM2_DIGEST_LEN); 249 tpm->pcr_extensions[pcr_index]++; 250 251 return 0; 252 }; 253 254 static int sandbox_tpm2_xfer(struct udevice *dev, const u8 *sendbuf, 255 size_t send_size, u8 *recvbuf, 256 size_t *recv_len) 257 { 258 struct sandbox_tpm2 *tpm = dev_get_priv(dev); 259 enum tpm2_hierarchy hierarchy = 0; 260 const u8 *sent = sendbuf; 261 u8 *recv = recvbuf; 262 u32 length, command, rc = 0; 263 u16 tag, mode, new_pw_sz; 264 u8 yes_no; 265 int i, j; 266 267 /* TPM2_GetProperty */ 268 u32 capability, property, property_count, val; 269 270 /* TPM2_PCR_Read/Extend variables */ 271 int pcr_index = 0; 272 u64 pcr_map = 0; 273 u32 selections, pcr_nb; 274 u16 alg; 275 u8 pcr_array_sz; 276 277 tag = get_unaligned_be16(sent); 278 sent += sizeof(tag); 279 280 length = get_unaligned_be32(sent); 281 sent += sizeof(length); 282 if (length != send_size) { 283 printf("TPM2: Unmatching length, received: %ld, expected: %d\n", 284 send_size, length); 285 rc = TPM2_RC_SIZE; 286 sandbox_tpm2_fill_buf(recv, recv_len, tag, rc); 287 return 0; 288 } 289 290 command = get_unaligned_be32(sent); 291 sent += sizeof(command); 292 rc = sandbox_tpm2_check_readyness(dev, command); 293 if (rc) { 294 sandbox_tpm2_fill_buf(recv, recv_len, tag, rc); 295 return 0; 296 } 297 298 rc = sandbox_tpm2_check_session(dev, command, tag, &sent, &hierarchy); 299 if (rc) { 300 sandbox_tpm2_fill_buf(recv, recv_len, tag, rc); 301 return 0; 302 } 303 304 switch (command) { 305 case TPM2_CC_STARTUP: 306 mode = get_unaligned_be16(sent); 307 sent += sizeof(mode); 308 switch (mode) { 309 case TPM2_SU_CLEAR: 310 case TPM2_SU_STATE: 311 break; 312 default: 313 rc = TPM2_RC_VALUE; 314 } 315 316 tpm->startup_done = true; 317 318 sandbox_tpm2_fill_buf(recv, recv_len, tag, rc); 319 break; 320 321 case TPM2_CC_SELF_TEST: 322 yes_no = *sent; 323 sent += sizeof(yes_no); 324 switch (yes_no) { 325 case TPMI_YES: 326 case TPMI_NO: 327 break; 328 default: 329 rc = TPM2_RC_VALUE; 330 } 331 332 tpm->tests_done = true; 333 334 sandbox_tpm2_fill_buf(recv, recv_len, tag, rc); 335 break; 336 337 case TPM2_CC_CLEAR: 338 /* Reset this hierarchy password */ 339 tpm->pw_sz[hierarchy] = 0; 340 341 /* Reset all password if thisis the PLATFORM hierarchy */ 342 if (hierarchy == TPM2_HIERARCHY_PLATFORM) 343 for (i = 0; i < TPM2_HIERARCHY_NB; i++) 344 tpm->pw_sz[i] = 0; 345 346 /* Reset the properties */ 347 for (i = 0; i < TPM2_PROPERTY_NB; i++) 348 tpm->properties[i] = 0; 349 350 /* Reset the PCRs and their number of extensions */ 351 for (i = 0; i < SANDBOX_TPM_PCR_NB; i++) { 352 tpm->pcr_extensions[i] = 0; 353 for (j = 0; j < TPM2_DIGEST_LEN; j++) 354 tpm->pcr[i][j] = 0; 355 } 356 357 sandbox_tpm2_fill_buf(recv, recv_len, tag, rc); 358 break; 359 360 case TPM2_CC_HIERCHANGEAUTH: 361 new_pw_sz = get_unaligned_be16(sent); 362 sent += sizeof(new_pw_sz); 363 if (new_pw_sz > TPM2_DIGEST_LEN) { 364 rc = TPM2_RC_SIZE; 365 } else if (new_pw_sz) { 366 tpm->pw_sz[hierarchy] = new_pw_sz; 367 memcpy(tpm->pw[hierarchy], sent, new_pw_sz); 368 sent += new_pw_sz; 369 } 370 371 sandbox_tpm2_fill_buf(recv, recv_len, tag, rc); 372 break; 373 374 case TPM2_CC_GET_CAPABILITY: 375 capability = get_unaligned_be32(sent); 376 sent += sizeof(capability); 377 property = get_unaligned_be32(sent); 378 sent += sizeof(property); 379 property_count = get_unaligned_be32(sent); 380 sent += sizeof(property_count); 381 382 switch (capability) { 383 case TPM2_CAP_PCRS: 384 break; 385 case TPM2_CAP_TPM_PROPERTIES: 386 if (!property_count) { 387 rc = TPM2_RC_HANDLE; 388 return sandbox_tpm2_fill_buf(recv, recv_len, 389 tag, rc); 390 } 391 392 if (property >= TPM2_PROPERTIES_OFFSET && 393 ((property - TPM2_PROPERTIES_OFFSET) + 394 property_count > TPM2_PROPERTY_NB)) { 395 rc = TPM2_RC_HANDLE; 396 return sandbox_tpm2_fill_buf(recv, recv_len, 397 tag, rc); 398 } 399 break; 400 default: 401 printf("Sandbox TPM2 only supports TPM2_CAP_PCRS or " 402 "TPM2_CAP_TPM_PROPERTIES\n"); 403 rc = TPM2_RC_HANDLE; 404 return sandbox_tpm2_fill_buf(recv, recv_len, tag, rc); 405 } 406 407 /* Write tag */ 408 put_unaligned_be16(tag, recv); 409 recv += sizeof(tag); 410 411 /* Ignore length for now */ 412 recv += sizeof(u32); 413 414 /* Write return code */ 415 put_unaligned_be32(rc, recv); 416 recv += sizeof(rc); 417 418 /* Tell there is more data to read */ 419 *recv = TPMI_YES; 420 recv += sizeof(yes_no); 421 422 /* Repeat the capability */ 423 put_unaligned_be32(capability, recv); 424 recv += sizeof(capability); 425 426 switch (capability) { 427 case TPM2_CAP_PCRS: 428 /* Give the number of algorithms supported - just SHA256 */ 429 put_unaligned_be32(1, recv); 430 recv += sizeof(u32); 431 432 /* Give SHA256 algorithm */ 433 put_unaligned_be16(TPM2_ALG_SHA256, recv); 434 recv += sizeof(u16); 435 436 /* Select the PCRs supported */ 437 *recv = SANDBOX_TPM_PCR_SELECT_MAX; 438 recv++; 439 440 /* Activate all the PCR bits */ 441 for (i = 0; i < SANDBOX_TPM_PCR_SELECT_MAX; ++i) { 442 *recv = 0xff; 443 recv++; 444 } 445 break; 446 case TPM2_CAP_TPM_PROPERTIES: 447 /* Give the number of properties that follow */ 448 put_unaligned_be32(property_count, recv); 449 recv += sizeof(property_count); 450 451 /* Fill with the properties */ 452 for (i = 0; i < property_count; i++) { 453 put_unaligned_be32(property + i, recv); 454 recv += sizeof(property); 455 if (property >= TPM2_PROPERTIES_OFFSET) { 456 val = tpm->properties[(property - 457 TPM2_PROPERTIES_OFFSET) + i]; 458 } else { 459 switch (property) { 460 case TPM2_PT_PCR_COUNT: 461 val = SANDBOX_TPM_PCR_NB; 462 break; 463 default: 464 val = 0xffffffff; 465 break; 466 } 467 } 468 469 put_unaligned_be32(val, recv); 470 recv += sizeof(property); 471 } 472 break; 473 } 474 475 /* Add trailing \0 */ 476 *recv = '\0'; 477 478 /* Write response length */ 479 *recv_len = recv - recvbuf; 480 put_unaligned_be32(*recv_len, recvbuf + sizeof(tag)); 481 482 break; 483 484 case TPM2_CC_DAM_PARAMETERS: 485 tpm->properties[TPM2_PROP_MAX_TRIES] = get_unaligned_be32(sent); 486 sent += sizeof(*tpm->properties); 487 tpm->properties[TPM2_RECOVERY_TIME] = get_unaligned_be32(sent); 488 sent += sizeof(*tpm->properties); 489 tpm->properties[TPM2_LOCKOUT_RECOVERY] = get_unaligned_be32(sent); 490 sent += sizeof(*tpm->properties); 491 492 sandbox_tpm2_fill_buf(recv, recv_len, tag, rc); 493 break; 494 495 case TPM2_CC_PCR_READ: 496 selections = get_unaligned_be32(sent); 497 sent += sizeof(selections); 498 if (selections != 1) { 499 printf("Sandbox cannot handle more than one PCR\n"); 500 rc = TPM2_RC_VALUE; 501 return sandbox_tpm2_fill_buf(recv, recv_len, tag, rc); 502 } 503 504 alg = get_unaligned_be16(sent); 505 sent += sizeof(alg); 506 if (alg != TPM2_ALG_SHA256) { 507 printf("Sandbox TPM only handle SHA256 algorithm\n"); 508 rc = TPM2_RC_VALUE; 509 return sandbox_tpm2_fill_buf(recv, recv_len, tag, rc); 510 } 511 512 pcr_array_sz = *sent; 513 sent += sizeof(pcr_array_sz); 514 if (!pcr_array_sz || pcr_array_sz > 8) { 515 printf("Sandbox TPM cannot handle so much PCRs\n"); 516 rc = TPM2_RC_VALUE; 517 return sandbox_tpm2_fill_buf(recv, recv_len, tag, rc); 518 } 519 520 for (i = 0; i < pcr_array_sz; i++) 521 pcr_map += (u64)sent[i] << (i * 8); 522 523 if (pcr_map >> SANDBOX_TPM_PCR_NB) { 524 printf("Sandbox TPM handles up to %d PCR(s)\n", 525 SANDBOX_TPM_PCR_NB); 526 rc = TPM2_RC_VALUE; 527 return sandbox_tpm2_fill_buf(recv, recv_len, tag, rc); 528 } 529 530 if (!pcr_map) { 531 printf("Empty PCR map.\n"); 532 rc = TPM2_RC_VALUE; 533 return sandbox_tpm2_fill_buf(recv, recv_len, tag, rc); 534 } 535 536 for (i = 0; i < SANDBOX_TPM_PCR_NB; i++) 537 if (pcr_map & BIT(i)) 538 pcr_index = i; 539 540 /* Write tag */ 541 put_unaligned_be16(tag, recv); 542 recv += sizeof(tag); 543 544 /* Ignore length for now */ 545 recv += sizeof(u32); 546 547 /* Write return code */ 548 put_unaligned_be32(rc, recv); 549 recv += sizeof(rc); 550 551 /* Number of extensions */ 552 put_unaligned_be32(tpm->pcr_extensions[pcr_index], recv); 553 recv += sizeof(u32); 554 555 /* Copy the PCR */ 556 memcpy(recv, tpm->pcr[pcr_index], TPM2_DIGEST_LEN); 557 recv += TPM2_DIGEST_LEN; 558 559 /* Add trailing \0 */ 560 *recv = '\0'; 561 562 /* Write response length */ 563 *recv_len = recv - recvbuf; 564 put_unaligned_be32(*recv_len, recvbuf + sizeof(tag)); 565 566 break; 567 568 case TPM2_CC_PCR_EXTEND: 569 /* Get the PCR index */ 570 pcr_index = get_unaligned_be32(sendbuf + sizeof(tag) + 571 sizeof(length) + 572 sizeof(command)); 573 if (pcr_index > SANDBOX_TPM_PCR_NB) { 574 printf("Sandbox TPM handles up to %d PCR(s)\n", 575 SANDBOX_TPM_PCR_NB); 576 rc = TPM2_RC_VALUE; 577 } 578 579 /* Check the number of hashes */ 580 pcr_nb = get_unaligned_be32(sent); 581 sent += sizeof(pcr_nb); 582 if (pcr_nb != 1) { 583 printf("Sandbox cannot handle more than one PCR\n"); 584 rc = TPM2_RC_VALUE; 585 return sandbox_tpm2_fill_buf(recv, recv_len, tag, rc); 586 } 587 588 /* Check the hash algorithm */ 589 alg = get_unaligned_be16(sent); 590 sent += sizeof(alg); 591 if (alg != TPM2_ALG_SHA256) { 592 printf("Sandbox TPM only handle SHA256 algorithm\n"); 593 rc = TPM2_RC_VALUE; 594 return sandbox_tpm2_fill_buf(recv, recv_len, tag, rc); 595 } 596 597 /* Extend the PCR */ 598 rc = sandbox_tpm2_extend(dev, pcr_index, sent); 599 600 sandbox_tpm2_fill_buf(recv, recv_len, tag, rc); 601 break; 602 603 default: 604 printf("TPM2 command %02x unknown in Sandbox\n", command); 605 rc = TPM2_RC_COMMAND_CODE; 606 sandbox_tpm2_fill_buf(recv, recv_len, tag, rc); 607 } 608 609 return 0; 610 } 611 612 static int sandbox_tpm2_get_desc(struct udevice *dev, char *buf, int size) 613 { 614 if (size < 15) 615 return -ENOSPC; 616 617 return snprintf(buf, size, "Sandbox TPM2.x"); 618 } 619 620 static int sandbox_tpm2_open(struct udevice *dev) 621 { 622 struct sandbox_tpm2 *tpm = dev_get_priv(dev); 623 624 if (tpm->init_done) 625 return -EIO; 626 627 tpm->init_done = true; 628 629 return 0; 630 } 631 632 static int sandbox_tpm2_probe(struct udevice *dev) 633 { 634 struct sandbox_tpm2 *tpm = dev_get_priv(dev); 635 struct tpm_chip_priv *priv = dev_get_uclass_priv(dev); 636 637 /* Use the TPM v2 stack */ 638 priv->version = TPM_V2; 639 640 memset(tpm, 0, sizeof(*tpm)); 641 642 priv->pcr_count = 32; 643 priv->pcr_select_min = 2; 644 645 return 0; 646 } 647 648 static int sandbox_tpm2_close(struct udevice *dev) 649 { 650 return 0; 651 } 652 653 static const struct tpm_ops sandbox_tpm2_ops = { 654 .open = sandbox_tpm2_open, 655 .close = sandbox_tpm2_close, 656 .get_desc = sandbox_tpm2_get_desc, 657 .xfer = sandbox_tpm2_xfer, 658 }; 659 660 static const struct udevice_id sandbox_tpm2_ids[] = { 661 { .compatible = "sandbox,tpm2" }, 662 { } 663 }; 664 665 U_BOOT_DRIVER(sandbox_tpm2) = { 666 .name = "sandbox_tpm2", 667 .id = UCLASS_TPM, 668 .of_match = sandbox_tpm2_ids, 669 .ops = &sandbox_tpm2_ops, 670 .probe = sandbox_tpm2_probe, 671 .priv_auto_alloc_size = sizeof(struct sandbox_tpm2), 672 }; 673