1 /* 2 * Copyright (c) 2013 The Chromium OS Authors. 3 * Coypright (c) 2013 Guntermann & Drunck GmbH 4 * 5 * SPDX-License-Identifier: GPL-2.0+ 6 */ 7 8 #include <common.h> 9 #include <dm.h> 10 #include <tis.h> 11 #include <tpm.h> 12 #include <asm/unaligned.h> 13 #include <u-boot/sha1.h> 14 15 /* Internal error of TPM command library */ 16 #define TPM_LIB_ERROR ((uint32_t)~0u) 17 18 /* Useful constants */ 19 enum { 20 COMMAND_BUFFER_SIZE = 256, 21 TPM_REQUEST_HEADER_LENGTH = 10, 22 TPM_RESPONSE_HEADER_LENGTH = 10, 23 PCR_DIGEST_LENGTH = 20, 24 DIGEST_LENGTH = 20, 25 TPM_REQUEST_AUTH_LENGTH = 45, 26 TPM_RESPONSE_AUTH_LENGTH = 41, 27 /* some max lengths, valid for RSA keys <= 2048 bits */ 28 TPM_KEY12_MAX_LENGTH = 618, 29 TPM_PUBKEY_MAX_LENGTH = 288, 30 }; 31 32 #ifdef CONFIG_TPM_AUTH_SESSIONS 33 34 #ifndef CONFIG_SHA1 35 #error "TPM_AUTH_SESSIONS require SHA1 to be configured, too" 36 #endif /* !CONFIG_SHA1 */ 37 38 struct session_data { 39 int valid; 40 uint32_t handle; 41 uint8_t nonce_even[DIGEST_LENGTH]; 42 uint8_t nonce_odd[DIGEST_LENGTH]; 43 }; 44 45 static struct session_data oiap_session = {0, }; 46 47 #endif /* CONFIG_TPM_AUTH_SESSIONS */ 48 49 /** 50 * Pack data into a byte string. The data types are specified in 51 * the format string: 'b' means unsigned byte, 'w' unsigned word, 52 * 'd' unsigned double word, and 's' byte string. The data are a 53 * series of offsets and values (for type byte string there are also 54 * lengths). The data values are packed into the byte string 55 * sequentially, and so a latter value could over-write a former 56 * value. 57 * 58 * @param str output string 59 * @param size size of output string 60 * @param format format string 61 * @param ... data points 62 * @return 0 on success, non-0 on error 63 */ 64 int pack_byte_string(uint8_t *str, size_t size, const char *format, ...) 65 { 66 va_list args; 67 size_t offset = 0, length = 0; 68 uint8_t *data = NULL; 69 uint32_t value = 0; 70 71 va_start(args, format); 72 for (; *format; format++) { 73 switch (*format) { 74 case 'b': 75 offset = va_arg(args, size_t); 76 value = va_arg(args, int); 77 length = 1; 78 break; 79 case 'w': 80 offset = va_arg(args, size_t); 81 value = va_arg(args, int); 82 length = 2; 83 break; 84 case 'd': 85 offset = va_arg(args, size_t); 86 value = va_arg(args, uint32_t); 87 length = 4; 88 break; 89 case 's': 90 offset = va_arg(args, size_t); 91 data = va_arg(args, uint8_t *); 92 length = va_arg(args, uint32_t); 93 break; 94 default: 95 debug("Couldn't recognize format string\n"); 96 return -1; 97 } 98 99 if (offset + length > size) 100 return -1; 101 102 switch (*format) { 103 case 'b': 104 str[offset] = value; 105 break; 106 case 'w': 107 put_unaligned_be16(value, str + offset); 108 break; 109 case 'd': 110 put_unaligned_be32(value, str + offset); 111 break; 112 case 's': 113 memcpy(str + offset, data, length); 114 break; 115 } 116 } 117 va_end(args); 118 119 return 0; 120 } 121 122 /** 123 * Unpack data from a byte string. The data types are specified in 124 * the format string: 'b' means unsigned byte, 'w' unsigned word, 125 * 'd' unsigned double word, and 's' byte string. The data are a 126 * series of offsets and pointers (for type byte string there are also 127 * lengths). 128 * 129 * @param str output string 130 * @param size size of output string 131 * @param format format string 132 * @param ... data points 133 * @return 0 on success, non-0 on error 134 */ 135 int unpack_byte_string(const uint8_t *str, size_t size, const char *format, ...) 136 { 137 va_list args; 138 size_t offset = 0, length = 0; 139 uint8_t *ptr8 = NULL; 140 uint16_t *ptr16 = NULL; 141 uint32_t *ptr32 = NULL; 142 143 va_start(args, format); 144 for (; *format; format++) { 145 switch (*format) { 146 case 'b': 147 offset = va_arg(args, size_t); 148 ptr8 = va_arg(args, uint8_t *); 149 length = 1; 150 break; 151 case 'w': 152 offset = va_arg(args, size_t); 153 ptr16 = va_arg(args, uint16_t *); 154 length = 2; 155 break; 156 case 'd': 157 offset = va_arg(args, size_t); 158 ptr32 = va_arg(args, uint32_t *); 159 length = 4; 160 break; 161 case 's': 162 offset = va_arg(args, size_t); 163 ptr8 = va_arg(args, uint8_t *); 164 length = va_arg(args, uint32_t); 165 break; 166 default: 167 debug("Couldn't recognize format string\n"); 168 return -1; 169 } 170 171 if (offset + length > size) 172 return -1; 173 174 switch (*format) { 175 case 'b': 176 *ptr8 = str[offset]; 177 break; 178 case 'w': 179 *ptr16 = get_unaligned_be16(str + offset); 180 break; 181 case 'd': 182 *ptr32 = get_unaligned_be32(str + offset); 183 break; 184 case 's': 185 memcpy(ptr8, str + offset, length); 186 break; 187 } 188 } 189 va_end(args); 190 191 return 0; 192 } 193 194 /** 195 * Get TPM command size. 196 * 197 * @param command byte string of TPM command 198 * @return command size of the TPM command 199 */ 200 static uint32_t tpm_command_size(const void *command) 201 { 202 const size_t command_size_offset = 2; 203 return get_unaligned_be32(command + command_size_offset); 204 } 205 206 /** 207 * Get TPM response return code, which is one of TPM_RESULT values. 208 * 209 * @param response byte string of TPM response 210 * @return return code of the TPM response 211 */ 212 static uint32_t tpm_return_code(const void *response) 213 { 214 const size_t return_code_offset = 6; 215 return get_unaligned_be32(response + return_code_offset); 216 } 217 218 /** 219 * Send a TPM command and return response's return code, and optionally 220 * return response to caller. 221 * 222 * @param command byte string of TPM command 223 * @param response output buffer for TPM response, or NULL if the 224 * caller does not care about it 225 * @param size_ptr output buffer size (input parameter) and TPM 226 * response length (output parameter); this parameter 227 * is a bidirectional 228 * @return return code of the TPM response 229 */ 230 static uint32_t tpm_sendrecv_command(const void *command, 231 void *response, size_t *size_ptr) 232 { 233 uint8_t response_buffer[COMMAND_BUFFER_SIZE]; 234 size_t response_length; 235 uint32_t err; 236 237 if (response) { 238 response_length = *size_ptr; 239 } else { 240 response = response_buffer; 241 response_length = sizeof(response_buffer); 242 } 243 #ifdef CONFIG_DM_TPM 244 struct udevice *dev; 245 int ret; 246 247 ret = uclass_first_device(UCLASS_TPM, &dev); 248 if (ret) 249 return ret; 250 err = tpm_xfer(dev, command, tpm_command_size(command), 251 response, &response_length); 252 #else 253 err = tis_sendrecv(command, tpm_command_size(command), 254 response, &response_length); 255 #endif 256 if (err < 0) 257 return TPM_LIB_ERROR; 258 if (size_ptr) 259 *size_ptr = response_length; 260 261 return tpm_return_code(response); 262 } 263 264 int tpm_init(void) 265 { 266 int err; 267 268 #ifdef CONFIG_DM_TPM 269 struct udevice *dev; 270 271 err = uclass_first_device(UCLASS_TPM, &dev); 272 if (err) 273 return err; 274 return tpm_open(dev); 275 #else 276 err = tis_init(); 277 if (err) 278 return err; 279 280 return tis_open(); 281 #endif 282 } 283 284 uint32_t tpm_startup(enum tpm_startup_type mode) 285 { 286 const uint8_t command[12] = { 287 0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0x99, 0x0, 0x0, 288 }; 289 const size_t mode_offset = 10; 290 uint8_t buf[COMMAND_BUFFER_SIZE]; 291 292 if (pack_byte_string(buf, sizeof(buf), "sw", 293 0, command, sizeof(command), 294 mode_offset, mode)) 295 return TPM_LIB_ERROR; 296 297 return tpm_sendrecv_command(buf, NULL, NULL); 298 } 299 300 uint32_t tpm_self_test_full(void) 301 { 302 const uint8_t command[10] = { 303 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x50, 304 }; 305 return tpm_sendrecv_command(command, NULL, NULL); 306 } 307 308 uint32_t tpm_continue_self_test(void) 309 { 310 const uint8_t command[10] = { 311 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x53, 312 }; 313 return tpm_sendrecv_command(command, NULL, NULL); 314 } 315 316 uint32_t tpm_nv_define_space(uint32_t index, uint32_t perm, uint32_t size) 317 { 318 const uint8_t command[101] = { 319 0x0, 0xc1, /* TPM_TAG */ 320 0x0, 0x0, 0x0, 0x65, /* parameter size */ 321 0x0, 0x0, 0x0, 0xcc, /* TPM_COMMAND_CODE */ 322 /* TPM_NV_DATA_PUBLIC->... */ 323 0x0, 0x18, /* ...->TPM_STRUCTURE_TAG */ 324 0, 0, 0, 0, /* ...->TPM_NV_INDEX */ 325 /* TPM_NV_DATA_PUBLIC->TPM_PCR_INFO_SHORT */ 326 0x0, 0x3, 327 0, 0, 0, 328 0x1f, 329 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 330 /* TPM_NV_DATA_PUBLIC->TPM_PCR_INFO_SHORT */ 331 0x0, 0x3, 332 0, 0, 0, 333 0x1f, 334 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 335 /* TPM_NV_ATTRIBUTES->... */ 336 0x0, 0x17, /* ...->TPM_STRUCTURE_TAG */ 337 0, 0, 0, 0, /* ...->attributes */ 338 /* End of TPM_NV_ATTRIBUTES */ 339 0, /* bReadSTClear */ 340 0, /* bWriteSTClear */ 341 0, /* bWriteDefine */ 342 0, 0, 0, 0, /* size */ 343 }; 344 const size_t index_offset = 12; 345 const size_t perm_offset = 70; 346 const size_t size_offset = 77; 347 uint8_t buf[COMMAND_BUFFER_SIZE]; 348 349 if (pack_byte_string(buf, sizeof(buf), "sddd", 350 0, command, sizeof(command), 351 index_offset, index, 352 perm_offset, perm, 353 size_offset, size)) 354 return TPM_LIB_ERROR; 355 356 return tpm_sendrecv_command(buf, NULL, NULL); 357 } 358 359 uint32_t tpm_nv_read_value(uint32_t index, void *data, uint32_t count) 360 { 361 const uint8_t command[22] = { 362 0x0, 0xc1, 0x0, 0x0, 0x0, 0x16, 0x0, 0x0, 0x0, 0xcf, 363 }; 364 const size_t index_offset = 10; 365 const size_t length_offset = 18; 366 const size_t data_size_offset = 10; 367 const size_t data_offset = 14; 368 uint8_t buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE]; 369 size_t response_length = sizeof(response); 370 uint32_t data_size; 371 uint32_t err; 372 373 if (pack_byte_string(buf, sizeof(buf), "sdd", 374 0, command, sizeof(command), 375 index_offset, index, 376 length_offset, count)) 377 return TPM_LIB_ERROR; 378 err = tpm_sendrecv_command(buf, response, &response_length); 379 if (err) 380 return err; 381 if (unpack_byte_string(response, response_length, "d", 382 data_size_offset, &data_size)) 383 return TPM_LIB_ERROR; 384 if (data_size > count) 385 return TPM_LIB_ERROR; 386 if (unpack_byte_string(response, response_length, "s", 387 data_offset, data, data_size)) 388 return TPM_LIB_ERROR; 389 390 return 0; 391 } 392 393 uint32_t tpm_nv_write_value(uint32_t index, const void *data, uint32_t length) 394 { 395 const uint8_t command[256] = { 396 0x0, 0xc1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xcd, 397 }; 398 const size_t command_size_offset = 2; 399 const size_t index_offset = 10; 400 const size_t length_offset = 18; 401 const size_t data_offset = 22; 402 const size_t write_info_size = 12; 403 const uint32_t total_length = 404 TPM_REQUEST_HEADER_LENGTH + write_info_size + length; 405 uint8_t buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE]; 406 size_t response_length = sizeof(response); 407 uint32_t err; 408 409 if (pack_byte_string(buf, sizeof(buf), "sddds", 410 0, command, sizeof(command), 411 command_size_offset, total_length, 412 index_offset, index, 413 length_offset, length, 414 data_offset, data, length)) 415 return TPM_LIB_ERROR; 416 err = tpm_sendrecv_command(buf, response, &response_length); 417 if (err) 418 return err; 419 420 return 0; 421 } 422 423 uint32_t tpm_extend(uint32_t index, const void *in_digest, void *out_digest) 424 { 425 const uint8_t command[34] = { 426 0x0, 0xc1, 0x0, 0x0, 0x0, 0x22, 0x0, 0x0, 0x0, 0x14, 427 }; 428 const size_t index_offset = 10; 429 const size_t in_digest_offset = 14; 430 const size_t out_digest_offset = 10; 431 uint8_t buf[COMMAND_BUFFER_SIZE]; 432 uint8_t response[TPM_RESPONSE_HEADER_LENGTH + PCR_DIGEST_LENGTH]; 433 size_t response_length = sizeof(response); 434 uint32_t err; 435 436 if (pack_byte_string(buf, sizeof(buf), "sds", 437 0, command, sizeof(command), 438 index_offset, index, 439 in_digest_offset, in_digest, 440 PCR_DIGEST_LENGTH)) 441 return TPM_LIB_ERROR; 442 err = tpm_sendrecv_command(buf, response, &response_length); 443 if (err) 444 return err; 445 446 if (unpack_byte_string(response, response_length, "s", 447 out_digest_offset, out_digest, 448 PCR_DIGEST_LENGTH)) 449 return TPM_LIB_ERROR; 450 451 return 0; 452 } 453 454 uint32_t tpm_pcr_read(uint32_t index, void *data, size_t count) 455 { 456 const uint8_t command[14] = { 457 0x0, 0xc1, 0x0, 0x0, 0x0, 0xe, 0x0, 0x0, 0x0, 0x15, 458 }; 459 const size_t index_offset = 10; 460 const size_t out_digest_offset = 10; 461 uint8_t buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE]; 462 size_t response_length = sizeof(response); 463 uint32_t err; 464 465 if (count < PCR_DIGEST_LENGTH) 466 return TPM_LIB_ERROR; 467 468 if (pack_byte_string(buf, sizeof(buf), "sd", 469 0, command, sizeof(command), 470 index_offset, index)) 471 return TPM_LIB_ERROR; 472 err = tpm_sendrecv_command(buf, response, &response_length); 473 if (err) 474 return err; 475 if (unpack_byte_string(response, response_length, "s", 476 out_digest_offset, data, PCR_DIGEST_LENGTH)) 477 return TPM_LIB_ERROR; 478 479 return 0; 480 } 481 482 uint32_t tpm_tsc_physical_presence(uint16_t presence) 483 { 484 const uint8_t command[12] = { 485 0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x40, 0x0, 0x0, 0xa, 0x0, 0x0, 486 }; 487 const size_t presence_offset = 10; 488 uint8_t buf[COMMAND_BUFFER_SIZE]; 489 490 if (pack_byte_string(buf, sizeof(buf), "sw", 491 0, command, sizeof(command), 492 presence_offset, presence)) 493 return TPM_LIB_ERROR; 494 495 return tpm_sendrecv_command(buf, NULL, NULL); 496 } 497 498 uint32_t tpm_read_pubek(void *data, size_t count) 499 { 500 const uint8_t command[30] = { 501 0x0, 0xc1, 0x0, 0x0, 0x0, 0x1e, 0x0, 0x0, 0x0, 0x7c, 502 }; 503 const size_t response_size_offset = 2; 504 const size_t data_offset = 10; 505 const size_t header_and_checksum_size = TPM_RESPONSE_HEADER_LENGTH + 20; 506 uint8_t response[COMMAND_BUFFER_SIZE + TPM_PUBEK_SIZE]; 507 size_t response_length = sizeof(response); 508 uint32_t data_size; 509 uint32_t err; 510 511 err = tpm_sendrecv_command(command, response, &response_length); 512 if (err) 513 return err; 514 if (unpack_byte_string(response, response_length, "d", 515 response_size_offset, &data_size)) 516 return TPM_LIB_ERROR; 517 if (data_size < header_and_checksum_size) 518 return TPM_LIB_ERROR; 519 data_size -= header_and_checksum_size; 520 if (data_size > count) 521 return TPM_LIB_ERROR; 522 if (unpack_byte_string(response, response_length, "s", 523 data_offset, data, data_size)) 524 return TPM_LIB_ERROR; 525 526 return 0; 527 } 528 529 uint32_t tpm_force_clear(void) 530 { 531 const uint8_t command[10] = { 532 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x5d, 533 }; 534 535 return tpm_sendrecv_command(command, NULL, NULL); 536 } 537 538 uint32_t tpm_physical_enable(void) 539 { 540 const uint8_t command[10] = { 541 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x6f, 542 }; 543 544 return tpm_sendrecv_command(command, NULL, NULL); 545 } 546 547 uint32_t tpm_physical_disable(void) 548 { 549 const uint8_t command[10] = { 550 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x70, 551 }; 552 553 return tpm_sendrecv_command(command, NULL, NULL); 554 } 555 556 uint32_t tpm_physical_set_deactivated(uint8_t state) 557 { 558 const uint8_t command[11] = { 559 0x0, 0xc1, 0x0, 0x0, 0x0, 0xb, 0x0, 0x0, 0x0, 0x72, 560 }; 561 const size_t state_offset = 10; 562 uint8_t buf[COMMAND_BUFFER_SIZE]; 563 564 if (pack_byte_string(buf, sizeof(buf), "sb", 565 0, command, sizeof(command), 566 state_offset, state)) 567 return TPM_LIB_ERROR; 568 569 return tpm_sendrecv_command(buf, NULL, NULL); 570 } 571 572 uint32_t tpm_get_capability(uint32_t cap_area, uint32_t sub_cap, 573 void *cap, size_t count) 574 { 575 const uint8_t command[22] = { 576 0x0, 0xc1, /* TPM_TAG */ 577 0x0, 0x0, 0x0, 0x16, /* parameter size */ 578 0x0, 0x0, 0x0, 0x65, /* TPM_COMMAND_CODE */ 579 0x0, 0x0, 0x0, 0x0, /* TPM_CAPABILITY_AREA */ 580 0x0, 0x0, 0x0, 0x4, /* subcap size */ 581 0x0, 0x0, 0x0, 0x0, /* subcap value */ 582 }; 583 const size_t cap_area_offset = 10; 584 const size_t sub_cap_offset = 18; 585 const size_t cap_offset = 14; 586 const size_t cap_size_offset = 10; 587 uint8_t buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE]; 588 size_t response_length = sizeof(response); 589 uint32_t cap_size; 590 uint32_t err; 591 592 if (pack_byte_string(buf, sizeof(buf), "sdd", 593 0, command, sizeof(command), 594 cap_area_offset, cap_area, 595 sub_cap_offset, sub_cap)) 596 return TPM_LIB_ERROR; 597 err = tpm_sendrecv_command(buf, response, &response_length); 598 if (err) 599 return err; 600 if (unpack_byte_string(response, response_length, "d", 601 cap_size_offset, &cap_size)) 602 return TPM_LIB_ERROR; 603 if (cap_size > response_length || cap_size > count) 604 return TPM_LIB_ERROR; 605 if (unpack_byte_string(response, response_length, "s", 606 cap_offset, cap, cap_size)) 607 return TPM_LIB_ERROR; 608 609 return 0; 610 } 611 612 uint32_t tpm_get_permanent_flags(struct tpm_permanent_flags *pflags) 613 { 614 const uint8_t command[22] = { 615 0x0, 0xc1, /* TPM_TAG */ 616 0x0, 0x0, 0x0, 0x16, /* parameter size */ 617 0x0, 0x0, 0x0, 0x65, /* TPM_COMMAND_CODE */ 618 0x0, 0x0, 0x0, 0x4, /* TPM_CAP_FLAG_PERM */ 619 0x0, 0x0, 0x0, 0x4, /* subcap size */ 620 0x0, 0x0, 0x1, 0x8, /* subcap value */ 621 }; 622 uint8_t response[COMMAND_BUFFER_SIZE]; 623 size_t response_length = sizeof(response); 624 uint32_t err; 625 626 err = tpm_sendrecv_command(command, response, &response_length); 627 if (err) 628 return err; 629 memcpy(pflags, response + TPM_HEADER_SIZE, sizeof(*pflags)); 630 631 return 0; 632 } 633 634 uint32_t tpm_get_permissions(uint32_t index, uint32_t *perm) 635 { 636 const uint8_t command[22] = { 637 0x0, 0xc1, /* TPM_TAG */ 638 0x0, 0x0, 0x0, 0x16, /* parameter size */ 639 0x0, 0x0, 0x0, 0x65, /* TPM_COMMAND_CODE */ 640 0x0, 0x0, 0x0, 0x11, 641 0x0, 0x0, 0x0, 0x4, 642 }; 643 const size_t index_offset = 18; 644 const size_t perm_offset = 60; 645 uint8_t buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE]; 646 size_t response_length = sizeof(response); 647 uint32_t err; 648 649 if (pack_byte_string(buf, sizeof(buf), "d", 0, command, sizeof(command), 650 index_offset, index)) 651 return TPM_LIB_ERROR; 652 err = tpm_sendrecv_command(buf, response, &response_length); 653 if (err) 654 return err; 655 if (unpack_byte_string(response, response_length, "d", 656 perm_offset, perm)) 657 return TPM_LIB_ERROR; 658 659 return 0; 660 } 661 662 #ifdef CONFIG_TPM_AUTH_SESSIONS 663 664 /** 665 * Fill an authentication block in a request. 666 * This func can create the first as well as the second auth block (for 667 * double authorized commands). 668 * 669 * @param request pointer to the request (w/ uninitialised auth data) 670 * @param request_len0 length of the request without auth data 671 * @param handles_len length of the handles area in request 672 * @param auth_session pointer to the (valid) auth session to be used 673 * @param request_auth pointer to the auth block of the request to be filled 674 * @param auth authentication data (HMAC key) 675 */ 676 static uint32_t create_request_auth(const void *request, size_t request_len0, 677 size_t handles_len, 678 struct session_data *auth_session, 679 void *request_auth, const void *auth) 680 { 681 uint8_t hmac_data[DIGEST_LENGTH * 3 + 1]; 682 sha1_context hash_ctx; 683 const size_t command_code_offset = 6; 684 const size_t auth_nonce_odd_offset = 4; 685 const size_t auth_continue_offset = 24; 686 const size_t auth_auth_offset = 25; 687 688 if (!auth_session || !auth_session->valid) 689 return TPM_LIB_ERROR; 690 691 sha1_starts(&hash_ctx); 692 sha1_update(&hash_ctx, request + command_code_offset, 4); 693 if (request_len0 > TPM_REQUEST_HEADER_LENGTH + handles_len) 694 sha1_update(&hash_ctx, 695 request + TPM_REQUEST_HEADER_LENGTH + handles_len, 696 request_len0 - TPM_REQUEST_HEADER_LENGTH 697 - handles_len); 698 sha1_finish(&hash_ctx, hmac_data); 699 700 sha1_starts(&hash_ctx); 701 sha1_update(&hash_ctx, auth_session->nonce_odd, DIGEST_LENGTH); 702 sha1_update(&hash_ctx, hmac_data, sizeof(hmac_data)); 703 sha1_finish(&hash_ctx, auth_session->nonce_odd); 704 705 if (pack_byte_string(request_auth, TPM_REQUEST_AUTH_LENGTH, "dsb", 706 0, auth_session->handle, 707 auth_nonce_odd_offset, auth_session->nonce_odd, 708 DIGEST_LENGTH, 709 auth_continue_offset, 1)) 710 return TPM_LIB_ERROR; 711 if (pack_byte_string(hmac_data, sizeof(hmac_data), "ss", 712 DIGEST_LENGTH, 713 auth_session->nonce_even, 714 DIGEST_LENGTH, 715 2 * DIGEST_LENGTH, 716 request_auth + auth_nonce_odd_offset, 717 DIGEST_LENGTH + 1)) 718 return TPM_LIB_ERROR; 719 sha1_hmac(auth, DIGEST_LENGTH, hmac_data, sizeof(hmac_data), 720 request_auth + auth_auth_offset); 721 722 return TPM_SUCCESS; 723 } 724 725 /** 726 * Verify an authentication block in a response. 727 * Since this func updates the nonce_even in the session data it has to be 728 * called when receiving a succesfull AUTH response. 729 * This func can verify the first as well as the second auth block (for 730 * double authorized commands). 731 * 732 * @param command_code command code of the request 733 * @param response pointer to the request (w/ uninitialised auth data) 734 * @param handles_len length of the handles area in response 735 * @param auth_session pointer to the (valid) auth session to be used 736 * @param response_auth pointer to the auth block of the response to be verified 737 * @param auth authentication data (HMAC key) 738 */ 739 static uint32_t verify_response_auth(uint32_t command_code, 740 const void *response, size_t response_len0, 741 size_t handles_len, 742 struct session_data *auth_session, 743 const void *response_auth, const void *auth) 744 { 745 uint8_t hmac_data[DIGEST_LENGTH * 3 + 1]; 746 uint8_t computed_auth[DIGEST_LENGTH]; 747 sha1_context hash_ctx; 748 const size_t return_code_offset = 6; 749 const size_t auth_continue_offset = 20; 750 const size_t auth_auth_offset = 21; 751 uint8_t auth_continue; 752 753 if (!auth_session || !auth_session->valid) 754 return TPM_AUTHFAIL; 755 if (pack_byte_string(hmac_data, sizeof(hmac_data), "d", 756 0, command_code)) 757 return TPM_LIB_ERROR; 758 if (response_len0 < TPM_RESPONSE_HEADER_LENGTH) 759 return TPM_LIB_ERROR; 760 761 sha1_starts(&hash_ctx); 762 sha1_update(&hash_ctx, response + return_code_offset, 4); 763 sha1_update(&hash_ctx, hmac_data, 4); 764 if (response_len0 > TPM_RESPONSE_HEADER_LENGTH + handles_len) 765 sha1_update(&hash_ctx, 766 response + TPM_RESPONSE_HEADER_LENGTH + handles_len, 767 response_len0 - TPM_RESPONSE_HEADER_LENGTH 768 - handles_len); 769 sha1_finish(&hash_ctx, hmac_data); 770 771 memcpy(auth_session->nonce_even, response_auth, DIGEST_LENGTH); 772 auth_continue = ((uint8_t *)response_auth)[auth_continue_offset]; 773 if (pack_byte_string(hmac_data, sizeof(hmac_data), "ssb", 774 DIGEST_LENGTH, 775 response_auth, 776 DIGEST_LENGTH, 777 2 * DIGEST_LENGTH, 778 auth_session->nonce_odd, 779 DIGEST_LENGTH, 780 3 * DIGEST_LENGTH, 781 auth_continue)) 782 return TPM_LIB_ERROR; 783 784 sha1_hmac(auth, DIGEST_LENGTH, hmac_data, sizeof(hmac_data), 785 computed_auth); 786 787 if (memcmp(computed_auth, response_auth + auth_auth_offset, 788 DIGEST_LENGTH)) 789 return TPM_AUTHFAIL; 790 791 return TPM_SUCCESS; 792 } 793 794 795 uint32_t tpm_terminate_auth_session(uint32_t auth_handle) 796 { 797 const uint8_t command[18] = { 798 0x00, 0xc1, /* TPM_TAG */ 799 0x00, 0x00, 0x00, 0x00, /* parameter size */ 800 0x00, 0x00, 0x00, 0xba, /* TPM_COMMAND_CODE */ 801 0x00, 0x00, 0x00, 0x00, /* TPM_HANDLE */ 802 0x00, 0x00, 0x00, 0x02, /* TPM_RESSOURCE_TYPE */ 803 }; 804 const size_t req_handle_offset = TPM_REQUEST_HEADER_LENGTH; 805 uint8_t request[COMMAND_BUFFER_SIZE]; 806 807 if (pack_byte_string(request, sizeof(request), "sd", 808 0, command, sizeof(command), 809 req_handle_offset, auth_handle)) 810 return TPM_LIB_ERROR; 811 if (oiap_session.valid && oiap_session.handle == auth_handle) 812 oiap_session.valid = 0; 813 814 return tpm_sendrecv_command(request, NULL, NULL); 815 } 816 817 uint32_t tpm_end_oiap(void) 818 { 819 uint32_t err = TPM_SUCCESS; 820 if (oiap_session.valid) 821 err = tpm_terminate_auth_session(oiap_session.handle); 822 return err; 823 } 824 825 uint32_t tpm_oiap(uint32_t *auth_handle) 826 { 827 const uint8_t command[10] = { 828 0x00, 0xc1, /* TPM_TAG */ 829 0x00, 0x00, 0x00, 0x0a, /* parameter size */ 830 0x00, 0x00, 0x00, 0x0a, /* TPM_COMMAND_CODE */ 831 }; 832 const size_t res_auth_handle_offset = TPM_RESPONSE_HEADER_LENGTH; 833 const size_t res_nonce_even_offset = TPM_RESPONSE_HEADER_LENGTH + 4; 834 uint8_t response[COMMAND_BUFFER_SIZE]; 835 size_t response_length = sizeof(response); 836 uint32_t err; 837 838 if (oiap_session.valid) 839 tpm_terminate_auth_session(oiap_session.handle); 840 841 err = tpm_sendrecv_command(command, response, &response_length); 842 if (err) 843 return err; 844 if (unpack_byte_string(response, response_length, "ds", 845 res_auth_handle_offset, &oiap_session.handle, 846 res_nonce_even_offset, &oiap_session.nonce_even, 847 (uint32_t)DIGEST_LENGTH)) 848 return TPM_LIB_ERROR; 849 oiap_session.valid = 1; 850 if (auth_handle) 851 *auth_handle = oiap_session.handle; 852 return 0; 853 } 854 855 uint32_t tpm_load_key2_oiap(uint32_t parent_handle, 856 const void *key, size_t key_length, 857 const void *parent_key_usage_auth, 858 uint32_t *key_handle) 859 { 860 const uint8_t command[14] = { 861 0x00, 0xc2, /* TPM_TAG */ 862 0x00, 0x00, 0x00, 0x00, /* parameter size */ 863 0x00, 0x00, 0x00, 0x41, /* TPM_COMMAND_CODE */ 864 0x00, 0x00, 0x00, 0x00, /* parent handle */ 865 }; 866 const size_t req_size_offset = 2; 867 const size_t req_parent_handle_offset = TPM_REQUEST_HEADER_LENGTH; 868 const size_t req_key_offset = TPM_REQUEST_HEADER_LENGTH + 4; 869 const size_t res_handle_offset = TPM_RESPONSE_HEADER_LENGTH; 870 uint8_t request[sizeof(command) + TPM_KEY12_MAX_LENGTH 871 + TPM_REQUEST_AUTH_LENGTH]; 872 uint8_t response[COMMAND_BUFFER_SIZE]; 873 size_t response_length = sizeof(response); 874 uint32_t err; 875 876 if (!oiap_session.valid) { 877 err = tpm_oiap(NULL); 878 if (err) 879 return err; 880 } 881 if (pack_byte_string(request, sizeof(request), "sdds", 882 0, command, sizeof(command), 883 req_size_offset, 884 sizeof(command) + key_length 885 + TPM_REQUEST_AUTH_LENGTH, 886 req_parent_handle_offset, parent_handle, 887 req_key_offset, key, key_length 888 )) 889 return TPM_LIB_ERROR; 890 891 err = create_request_auth(request, sizeof(command) + key_length, 4, 892 &oiap_session, 893 request + sizeof(command) + key_length, 894 parent_key_usage_auth); 895 if (err) 896 return err; 897 err = tpm_sendrecv_command(request, response, &response_length); 898 if (err) { 899 if (err == TPM_AUTHFAIL) 900 oiap_session.valid = 0; 901 return err; 902 } 903 904 err = verify_response_auth(0x00000041, response, 905 response_length - TPM_RESPONSE_AUTH_LENGTH, 906 4, &oiap_session, 907 response + response_length - TPM_RESPONSE_AUTH_LENGTH, 908 parent_key_usage_auth); 909 if (err) 910 return err; 911 912 if (key_handle) { 913 if (unpack_byte_string(response, response_length, "d", 914 res_handle_offset, key_handle)) 915 return TPM_LIB_ERROR; 916 } 917 918 return 0; 919 } 920 921 uint32_t tpm_get_pub_key_oiap(uint32_t key_handle, const void *usage_auth, 922 void *pubkey, size_t *pubkey_len) 923 { 924 const uint8_t command[14] = { 925 0x00, 0xc2, /* TPM_TAG */ 926 0x00, 0x00, 0x00, 0x00, /* parameter size */ 927 0x00, 0x00, 0x00, 0x21, /* TPM_COMMAND_CODE */ 928 0x00, 0x00, 0x00, 0x00, /* key handle */ 929 }; 930 const size_t req_size_offset = 2; 931 const size_t req_key_handle_offset = TPM_REQUEST_HEADER_LENGTH; 932 const size_t res_pubkey_offset = TPM_RESPONSE_HEADER_LENGTH; 933 uint8_t request[sizeof(command) + TPM_REQUEST_AUTH_LENGTH]; 934 uint8_t response[TPM_RESPONSE_HEADER_LENGTH + TPM_PUBKEY_MAX_LENGTH 935 + TPM_RESPONSE_AUTH_LENGTH]; 936 size_t response_length = sizeof(response); 937 uint32_t err; 938 939 if (!oiap_session.valid) { 940 err = tpm_oiap(NULL); 941 if (err) 942 return err; 943 } 944 if (pack_byte_string(request, sizeof(request), "sdd", 945 0, command, sizeof(command), 946 req_size_offset, 947 (uint32_t)(sizeof(command) 948 + TPM_REQUEST_AUTH_LENGTH), 949 req_key_handle_offset, key_handle 950 )) 951 return TPM_LIB_ERROR; 952 err = create_request_auth(request, sizeof(command), 4, &oiap_session, 953 request + sizeof(command), usage_auth); 954 if (err) 955 return err; 956 err = tpm_sendrecv_command(request, response, &response_length); 957 if (err) { 958 if (err == TPM_AUTHFAIL) 959 oiap_session.valid = 0; 960 return err; 961 } 962 err = verify_response_auth(0x00000021, response, 963 response_length - TPM_RESPONSE_AUTH_LENGTH, 964 0, &oiap_session, 965 response + response_length - TPM_RESPONSE_AUTH_LENGTH, 966 usage_auth); 967 if (err) 968 return err; 969 970 if (pubkey) { 971 if ((response_length - TPM_RESPONSE_HEADER_LENGTH 972 - TPM_RESPONSE_AUTH_LENGTH) > *pubkey_len) 973 return TPM_LIB_ERROR; 974 *pubkey_len = response_length - TPM_RESPONSE_HEADER_LENGTH 975 - TPM_RESPONSE_AUTH_LENGTH; 976 memcpy(pubkey, response + res_pubkey_offset, 977 response_length - TPM_RESPONSE_HEADER_LENGTH 978 - TPM_RESPONSE_AUTH_LENGTH); 979 } 980 981 return 0; 982 } 983 984 #endif /* CONFIG_TPM_AUTH_SESSIONS */ 985