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