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