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