2 * Copyright (c) 2013 The Chromium OS Authors.
3 * Coypright (c) 2013 Guntermann & Drunck GmbH
5 * SPDX-License-Identifier: GPL-2.0+
11 #include <asm/unaligned.h>
12 #include <u-boot/sha1.h>
14 /* Internal error of TPM command library */
15 #define TPM_LIB_ERROR ((uint32_t)~0u)
17 /* Useful constants */
19 COMMAND_BUFFER_SIZE = 256,
20 TPM_REQUEST_HEADER_LENGTH = 10,
21 TPM_RESPONSE_HEADER_LENGTH = 10,
22 PCR_DIGEST_LENGTH = 20,
24 TPM_REQUEST_AUTH_LENGTH = 45,
25 TPM_RESPONSE_AUTH_LENGTH = 41,
26 /* some max lengths, valid for RSA keys <= 2048 bits */
27 TPM_KEY12_MAX_LENGTH = 618,
28 TPM_PUBKEY_MAX_LENGTH = 288,
31 #ifdef CONFIG_TPM_AUTH_SESSIONS
34 #error "TPM_AUTH_SESSIONS require SHA1 to be configured, too"
35 #endif /* !CONFIG_SHA1 */
40 uint8_t nonce_even[DIGEST_LENGTH];
41 uint8_t nonce_odd[DIGEST_LENGTH];
44 static struct session_data oiap_session = {0, };
46 #endif /* CONFIG_TPM_AUTH_SESSIONS */
49 * Pack data into a byte string. The data types are specified in
50 * the format string: 'b' means unsigned byte, 'w' unsigned word,
51 * 'd' unsigned double word, and 's' byte string. The data are a
52 * series of offsets and values (for type byte string there are also
53 * lengths). The data values are packed into the byte string
54 * sequentially, and so a latter value could over-write a former
57 * @param str output string
58 * @param size size of output string
59 * @param format format string
60 * @param ... data points
61 * @return 0 on success, non-0 on error
63 int pack_byte_string(uint8_t *str, size_t size, const char *format, ...)
66 size_t offset = 0, length = 0;
70 va_start(args, format);
71 for (; *format; format++) {
74 offset = va_arg(args, size_t);
75 value = va_arg(args, int);
79 offset = va_arg(args, size_t);
80 value = va_arg(args, int);
84 offset = va_arg(args, size_t);
85 value = va_arg(args, uint32_t);
89 offset = va_arg(args, size_t);
90 data = va_arg(args, uint8_t *);
91 length = va_arg(args, uint32_t);
94 debug("Couldn't recognize format string\n");
98 if (offset + length > size)
106 put_unaligned_be16(value, str + offset);
109 put_unaligned_be32(value, str + offset);
112 memcpy(str + offset, data, length);
122 * Unpack data from a byte string. The data types are specified in
123 * the format string: 'b' means unsigned byte, 'w' unsigned word,
124 * 'd' unsigned double word, and 's' byte string. The data are a
125 * series of offsets and pointers (for type byte string there are also
128 * @param str output string
129 * @param size size of output string
130 * @param format format string
131 * @param ... data points
132 * @return 0 on success, non-0 on error
134 int unpack_byte_string(const uint8_t *str, size_t size, const char *format, ...)
137 size_t offset = 0, length = 0;
138 uint8_t *ptr8 = NULL;
139 uint16_t *ptr16 = NULL;
140 uint32_t *ptr32 = NULL;
142 va_start(args, format);
143 for (; *format; format++) {
146 offset = va_arg(args, size_t);
147 ptr8 = va_arg(args, uint8_t *);
151 offset = va_arg(args, size_t);
152 ptr16 = va_arg(args, uint16_t *);
156 offset = va_arg(args, size_t);
157 ptr32 = va_arg(args, uint32_t *);
161 offset = va_arg(args, size_t);
162 ptr8 = va_arg(args, uint8_t *);
163 length = va_arg(args, uint32_t);
166 debug("Couldn't recognize format string\n");
170 if (offset + length > size)
178 *ptr16 = get_unaligned_be16(str + offset);
181 *ptr32 = get_unaligned_be32(str + offset);
184 memcpy(ptr8, str + offset, length);
194 * Get TPM command size.
196 * @param command byte string of TPM command
197 * @return command size of the TPM command
199 static uint32_t tpm_command_size(const void *command)
201 const size_t command_size_offset = 2;
202 return get_unaligned_be32(command + command_size_offset);
206 * Get TPM response return code, which is one of TPM_RESULT values.
208 * @param response byte string of TPM response
209 * @return return code of the TPM response
211 static uint32_t tpm_return_code(const void *response)
213 const size_t return_code_offset = 6;
214 return get_unaligned_be32(response + return_code_offset);
218 * Send a TPM command and return response's return code, and optionally
219 * return response to caller.
221 * @param command byte string of TPM command
222 * @param response output buffer for TPM response, or NULL if the
223 * caller does not care about it
224 * @param size_ptr output buffer size (input parameter) and TPM
225 * response length (output parameter); this parameter
227 * @return return code of the TPM response
229 static uint32_t tpm_sendrecv_command(const void *command,
230 void *response, size_t *size_ptr)
234 uint8_t response_buffer[COMMAND_BUFFER_SIZE];
235 size_t response_length;
238 response_length = *size_ptr;
240 response = response_buffer;
241 response_length = sizeof(response_buffer);
244 ret = uclass_first_device_err(UCLASS_TPM, &dev);
247 err = tpm_xfer(dev, command, tpm_command_size(command),
248 response, &response_length);
251 return TPM_LIB_ERROR;
253 *size_ptr = response_length;
255 return tpm_return_code(response);
263 err = uclass_first_device_err(UCLASS_TPM, &dev);
266 return tpm_open(dev);
269 uint32_t tpm_startup(enum tpm_startup_type mode)
271 const uint8_t command[12] = {
272 0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0x99, 0x0, 0x0,
274 const size_t mode_offset = 10;
275 uint8_t buf[COMMAND_BUFFER_SIZE];
277 if (pack_byte_string(buf, sizeof(buf), "sw",
278 0, command, sizeof(command),
280 return TPM_LIB_ERROR;
282 return tpm_sendrecv_command(buf, NULL, NULL);
285 uint32_t tpm_self_test_full(void)
287 const uint8_t command[10] = {
288 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x50,
290 return tpm_sendrecv_command(command, NULL, NULL);
293 uint32_t tpm_continue_self_test(void)
295 const uint8_t command[10] = {
296 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x53,
298 return tpm_sendrecv_command(command, NULL, NULL);
301 uint32_t tpm_nv_define_space(uint32_t index, uint32_t perm, uint32_t size)
303 const uint8_t command[101] = {
304 0x0, 0xc1, /* TPM_TAG */
305 0x0, 0x0, 0x0, 0x65, /* parameter size */
306 0x0, 0x0, 0x0, 0xcc, /* TPM_COMMAND_CODE */
307 /* TPM_NV_DATA_PUBLIC->... */
308 0x0, 0x18, /* ...->TPM_STRUCTURE_TAG */
309 0, 0, 0, 0, /* ...->TPM_NV_INDEX */
310 /* TPM_NV_DATA_PUBLIC->TPM_PCR_INFO_SHORT */
314 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
315 /* TPM_NV_DATA_PUBLIC->TPM_PCR_INFO_SHORT */
319 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
320 /* TPM_NV_ATTRIBUTES->... */
321 0x0, 0x17, /* ...->TPM_STRUCTURE_TAG */
322 0, 0, 0, 0, /* ...->attributes */
323 /* End of TPM_NV_ATTRIBUTES */
324 0, /* bReadSTClear */
325 0, /* bWriteSTClear */
326 0, /* bWriteDefine */
327 0, 0, 0, 0, /* size */
329 const size_t index_offset = 12;
330 const size_t perm_offset = 70;
331 const size_t size_offset = 77;
332 uint8_t buf[COMMAND_BUFFER_SIZE];
334 if (pack_byte_string(buf, sizeof(buf), "sddd",
335 0, command, sizeof(command),
339 return TPM_LIB_ERROR;
341 return tpm_sendrecv_command(buf, NULL, NULL);
344 uint32_t tpm_nv_read_value(uint32_t index, void *data, uint32_t count)
346 const uint8_t command[22] = {
347 0x0, 0xc1, 0x0, 0x0, 0x0, 0x16, 0x0, 0x0, 0x0, 0xcf,
349 const size_t index_offset = 10;
350 const size_t length_offset = 18;
351 const size_t data_size_offset = 10;
352 const size_t data_offset = 14;
353 uint8_t buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
354 size_t response_length = sizeof(response);
358 if (pack_byte_string(buf, sizeof(buf), "sdd",
359 0, command, sizeof(command),
361 length_offset, count))
362 return TPM_LIB_ERROR;
363 err = tpm_sendrecv_command(buf, response, &response_length);
366 if (unpack_byte_string(response, response_length, "d",
367 data_size_offset, &data_size))
368 return TPM_LIB_ERROR;
369 if (data_size > count)
370 return TPM_LIB_ERROR;
371 if (unpack_byte_string(response, response_length, "s",
372 data_offset, data, data_size))
373 return TPM_LIB_ERROR;
378 uint32_t tpm_nv_write_value(uint32_t index, const void *data, uint32_t length)
380 const uint8_t command[256] = {
381 0x0, 0xc1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xcd,
383 const size_t command_size_offset = 2;
384 const size_t index_offset = 10;
385 const size_t length_offset = 18;
386 const size_t data_offset = 22;
387 const size_t write_info_size = 12;
388 const uint32_t total_length =
389 TPM_REQUEST_HEADER_LENGTH + write_info_size + length;
390 uint8_t buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
391 size_t response_length = sizeof(response);
394 if (pack_byte_string(buf, sizeof(buf), "sddds",
395 0, command, sizeof(command),
396 command_size_offset, total_length,
398 length_offset, length,
399 data_offset, data, length))
400 return TPM_LIB_ERROR;
401 err = tpm_sendrecv_command(buf, response, &response_length);
408 uint32_t tpm_extend(uint32_t index, const void *in_digest, void *out_digest)
410 const uint8_t command[34] = {
411 0x0, 0xc1, 0x0, 0x0, 0x0, 0x22, 0x0, 0x0, 0x0, 0x14,
413 const size_t index_offset = 10;
414 const size_t in_digest_offset = 14;
415 const size_t out_digest_offset = 10;
416 uint8_t buf[COMMAND_BUFFER_SIZE];
417 uint8_t response[TPM_RESPONSE_HEADER_LENGTH + PCR_DIGEST_LENGTH];
418 size_t response_length = sizeof(response);
421 if (pack_byte_string(buf, sizeof(buf), "sds",
422 0, command, sizeof(command),
424 in_digest_offset, in_digest,
426 return TPM_LIB_ERROR;
427 err = tpm_sendrecv_command(buf, response, &response_length);
431 if (unpack_byte_string(response, response_length, "s",
432 out_digest_offset, out_digest,
434 return TPM_LIB_ERROR;
439 uint32_t tpm_pcr_read(uint32_t index, void *data, size_t count)
441 const uint8_t command[14] = {
442 0x0, 0xc1, 0x0, 0x0, 0x0, 0xe, 0x0, 0x0, 0x0, 0x15,
444 const size_t index_offset = 10;
445 const size_t out_digest_offset = 10;
446 uint8_t buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
447 size_t response_length = sizeof(response);
450 if (count < PCR_DIGEST_LENGTH)
451 return TPM_LIB_ERROR;
453 if (pack_byte_string(buf, sizeof(buf), "sd",
454 0, command, sizeof(command),
455 index_offset, index))
456 return TPM_LIB_ERROR;
457 err = tpm_sendrecv_command(buf, response, &response_length);
460 if (unpack_byte_string(response, response_length, "s",
461 out_digest_offset, data, PCR_DIGEST_LENGTH))
462 return TPM_LIB_ERROR;
467 uint32_t tpm_tsc_physical_presence(uint16_t presence)
469 const uint8_t command[12] = {
470 0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x40, 0x0, 0x0, 0xa, 0x0, 0x0,
472 const size_t presence_offset = 10;
473 uint8_t buf[COMMAND_BUFFER_SIZE];
475 if (pack_byte_string(buf, sizeof(buf), "sw",
476 0, command, sizeof(command),
477 presence_offset, presence))
478 return TPM_LIB_ERROR;
480 return tpm_sendrecv_command(buf, NULL, NULL);
483 uint32_t tpm_read_pubek(void *data, size_t count)
485 const uint8_t command[30] = {
486 0x0, 0xc1, 0x0, 0x0, 0x0, 0x1e, 0x0, 0x0, 0x0, 0x7c,
488 const size_t response_size_offset = 2;
489 const size_t data_offset = 10;
490 const size_t header_and_checksum_size = TPM_RESPONSE_HEADER_LENGTH + 20;
491 uint8_t response[COMMAND_BUFFER_SIZE + TPM_PUBEK_SIZE];
492 size_t response_length = sizeof(response);
496 err = tpm_sendrecv_command(command, response, &response_length);
499 if (unpack_byte_string(response, response_length, "d",
500 response_size_offset, &data_size))
501 return TPM_LIB_ERROR;
502 if (data_size < header_and_checksum_size)
503 return TPM_LIB_ERROR;
504 data_size -= header_and_checksum_size;
505 if (data_size > count)
506 return TPM_LIB_ERROR;
507 if (unpack_byte_string(response, response_length, "s",
508 data_offset, data, data_size))
509 return TPM_LIB_ERROR;
514 uint32_t tpm_force_clear(void)
516 const uint8_t command[10] = {
517 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x5d,
520 return tpm_sendrecv_command(command, NULL, NULL);
523 uint32_t tpm_physical_enable(void)
525 const uint8_t command[10] = {
526 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x6f,
529 return tpm_sendrecv_command(command, NULL, NULL);
532 uint32_t tpm_physical_disable(void)
534 const uint8_t command[10] = {
535 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x70,
538 return tpm_sendrecv_command(command, NULL, NULL);
541 uint32_t tpm_physical_set_deactivated(uint8_t state)
543 const uint8_t command[11] = {
544 0x0, 0xc1, 0x0, 0x0, 0x0, 0xb, 0x0, 0x0, 0x0, 0x72,
546 const size_t state_offset = 10;
547 uint8_t buf[COMMAND_BUFFER_SIZE];
549 if (pack_byte_string(buf, sizeof(buf), "sb",
550 0, command, sizeof(command),
551 state_offset, state))
552 return TPM_LIB_ERROR;
554 return tpm_sendrecv_command(buf, NULL, NULL);
557 uint32_t tpm_get_capability(uint32_t cap_area, uint32_t sub_cap,
558 void *cap, size_t count)
560 const uint8_t command[22] = {
561 0x0, 0xc1, /* TPM_TAG */
562 0x0, 0x0, 0x0, 0x16, /* parameter size */
563 0x0, 0x0, 0x0, 0x65, /* TPM_COMMAND_CODE */
564 0x0, 0x0, 0x0, 0x0, /* TPM_CAPABILITY_AREA */
565 0x0, 0x0, 0x0, 0x4, /* subcap size */
566 0x0, 0x0, 0x0, 0x0, /* subcap value */
568 const size_t cap_area_offset = 10;
569 const size_t sub_cap_offset = 18;
570 const size_t cap_offset = 14;
571 const size_t cap_size_offset = 10;
572 uint8_t buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
573 size_t response_length = sizeof(response);
577 if (pack_byte_string(buf, sizeof(buf), "sdd",
578 0, command, sizeof(command),
579 cap_area_offset, cap_area,
580 sub_cap_offset, sub_cap))
581 return TPM_LIB_ERROR;
582 err = tpm_sendrecv_command(buf, response, &response_length);
585 if (unpack_byte_string(response, response_length, "d",
586 cap_size_offset, &cap_size))
587 return TPM_LIB_ERROR;
588 if (cap_size > response_length || cap_size > count)
589 return TPM_LIB_ERROR;
590 if (unpack_byte_string(response, response_length, "s",
591 cap_offset, cap, cap_size))
592 return TPM_LIB_ERROR;
597 uint32_t tpm_get_permanent_flags(struct tpm_permanent_flags *pflags)
599 const uint8_t command[22] = {
600 0x0, 0xc1, /* TPM_TAG */
601 0x0, 0x0, 0x0, 0x16, /* parameter size */
602 0x0, 0x0, 0x0, 0x65, /* TPM_COMMAND_CODE */
603 0x0, 0x0, 0x0, 0x4, /* TPM_CAP_FLAG_PERM */
604 0x0, 0x0, 0x0, 0x4, /* subcap size */
605 0x0, 0x0, 0x1, 0x8, /* subcap value */
607 uint8_t response[COMMAND_BUFFER_SIZE];
608 size_t response_length = sizeof(response);
611 err = tpm_sendrecv_command(command, response, &response_length);
614 memcpy(pflags, response + TPM_HEADER_SIZE, sizeof(*pflags));
619 uint32_t tpm_get_permissions(uint32_t index, uint32_t *perm)
621 const uint8_t command[22] = {
622 0x0, 0xc1, /* TPM_TAG */
623 0x0, 0x0, 0x0, 0x16, /* parameter size */
624 0x0, 0x0, 0x0, 0x65, /* TPM_COMMAND_CODE */
628 const size_t index_offset = 18;
629 const size_t perm_offset = 60;
630 uint8_t buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
631 size_t response_length = sizeof(response);
634 if (pack_byte_string(buf, sizeof(buf), "d", 0, command, sizeof(command),
635 index_offset, index))
636 return TPM_LIB_ERROR;
637 err = tpm_sendrecv_command(buf, response, &response_length);
640 if (unpack_byte_string(response, response_length, "d",
642 return TPM_LIB_ERROR;
647 #ifdef CONFIG_TPM_FLUSH_RESOURCES
648 uint32_t tpm_flush_specific(uint32_t key_handle, uint32_t resource_type)
650 const uint8_t command[18] = {
651 0x00, 0xc1, /* TPM_TAG */
652 0x00, 0x00, 0x00, 0x12, /* parameter size */
653 0x00, 0x00, 0x00, 0xba, /* TPM_COMMAND_CODE */
654 0x00, 0x00, 0x00, 0x00, /* key handle */
655 0x00, 0x00, 0x00, 0x00, /* resource type */
657 const size_t key_handle_offset = 10;
658 const size_t resource_type_offset = 14;
659 uint8_t buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
660 size_t response_length = sizeof(response);
663 if (pack_byte_string(buf, sizeof(buf), "sdd",
664 0, command, sizeof(command),
665 key_handle_offset, key_handle,
666 resource_type_offset, resource_type))
667 return TPM_LIB_ERROR;
669 err = tpm_sendrecv_command(buf, response, &response_length);
674 #endif /* CONFIG_TPM_FLUSH_RESOURCES */
676 #ifdef CONFIG_TPM_AUTH_SESSIONS
679 * Fill an authentication block in a request.
680 * This func can create the first as well as the second auth block (for
681 * double authorized commands).
683 * @param request pointer to the request (w/ uninitialised auth data)
684 * @param request_len0 length of the request without auth data
685 * @param handles_len length of the handles area in request
686 * @param auth_session pointer to the (valid) auth session to be used
687 * @param request_auth pointer to the auth block of the request to be filled
688 * @param auth authentication data (HMAC key)
690 static uint32_t create_request_auth(const void *request, size_t request_len0,
692 struct session_data *auth_session,
693 void *request_auth, const void *auth)
695 uint8_t hmac_data[DIGEST_LENGTH * 3 + 1];
696 sha1_context hash_ctx;
697 const size_t command_code_offset = 6;
698 const size_t auth_nonce_odd_offset = 4;
699 const size_t auth_continue_offset = 24;
700 const size_t auth_auth_offset = 25;
702 if (!auth_session || !auth_session->valid)
703 return TPM_LIB_ERROR;
705 sha1_starts(&hash_ctx);
706 sha1_update(&hash_ctx, request + command_code_offset, 4);
707 if (request_len0 > TPM_REQUEST_HEADER_LENGTH + handles_len)
708 sha1_update(&hash_ctx,
709 request + TPM_REQUEST_HEADER_LENGTH + handles_len,
710 request_len0 - TPM_REQUEST_HEADER_LENGTH
712 sha1_finish(&hash_ctx, hmac_data);
714 sha1_starts(&hash_ctx);
715 sha1_update(&hash_ctx, auth_session->nonce_odd, DIGEST_LENGTH);
716 sha1_update(&hash_ctx, hmac_data, sizeof(hmac_data));
717 sha1_finish(&hash_ctx, auth_session->nonce_odd);
719 if (pack_byte_string(request_auth, TPM_REQUEST_AUTH_LENGTH, "dsb",
720 0, auth_session->handle,
721 auth_nonce_odd_offset, auth_session->nonce_odd,
723 auth_continue_offset, 1))
724 return TPM_LIB_ERROR;
725 if (pack_byte_string(hmac_data, sizeof(hmac_data), "ss",
727 auth_session->nonce_even,
730 request_auth + auth_nonce_odd_offset,
732 return TPM_LIB_ERROR;
733 sha1_hmac(auth, DIGEST_LENGTH, hmac_data, sizeof(hmac_data),
734 request_auth + auth_auth_offset);
740 * Verify an authentication block in a response.
741 * Since this func updates the nonce_even in the session data it has to be
742 * called when receiving a succesfull AUTH response.
743 * This func can verify the first as well as the second auth block (for
744 * double authorized commands).
746 * @param command_code command code of the request
747 * @param response pointer to the request (w/ uninitialised auth data)
748 * @param handles_len length of the handles area in response
749 * @param auth_session pointer to the (valid) auth session to be used
750 * @param response_auth pointer to the auth block of the response to be verified
751 * @param auth authentication data (HMAC key)
753 static uint32_t verify_response_auth(uint32_t command_code,
754 const void *response, size_t response_len0,
756 struct session_data *auth_session,
757 const void *response_auth, const void *auth)
759 uint8_t hmac_data[DIGEST_LENGTH * 3 + 1];
760 uint8_t computed_auth[DIGEST_LENGTH];
761 sha1_context hash_ctx;
762 const size_t return_code_offset = 6;
763 const size_t auth_continue_offset = 20;
764 const size_t auth_auth_offset = 21;
765 uint8_t auth_continue;
767 if (!auth_session || !auth_session->valid)
769 if (pack_byte_string(hmac_data, sizeof(hmac_data), "d",
771 return TPM_LIB_ERROR;
772 if (response_len0 < TPM_RESPONSE_HEADER_LENGTH)
773 return TPM_LIB_ERROR;
775 sha1_starts(&hash_ctx);
776 sha1_update(&hash_ctx, response + return_code_offset, 4);
777 sha1_update(&hash_ctx, hmac_data, 4);
778 if (response_len0 > TPM_RESPONSE_HEADER_LENGTH + handles_len)
779 sha1_update(&hash_ctx,
780 response + TPM_RESPONSE_HEADER_LENGTH + handles_len,
781 response_len0 - TPM_RESPONSE_HEADER_LENGTH
783 sha1_finish(&hash_ctx, hmac_data);
785 memcpy(auth_session->nonce_even, response_auth, DIGEST_LENGTH);
786 auth_continue = ((uint8_t *)response_auth)[auth_continue_offset];
787 if (pack_byte_string(hmac_data, sizeof(hmac_data), "ssb",
792 auth_session->nonce_odd,
796 return TPM_LIB_ERROR;
798 sha1_hmac(auth, DIGEST_LENGTH, hmac_data, sizeof(hmac_data),
801 if (memcmp(computed_auth, response_auth + auth_auth_offset,
809 uint32_t tpm_terminate_auth_session(uint32_t auth_handle)
811 const uint8_t command[18] = {
812 0x00, 0xc1, /* TPM_TAG */
813 0x00, 0x00, 0x00, 0x00, /* parameter size */
814 0x00, 0x00, 0x00, 0xba, /* TPM_COMMAND_CODE */
815 0x00, 0x00, 0x00, 0x00, /* TPM_HANDLE */
816 0x00, 0x00, 0x00, 0x02, /* TPM_RESSOURCE_TYPE */
818 const size_t req_handle_offset = TPM_REQUEST_HEADER_LENGTH;
819 uint8_t request[COMMAND_BUFFER_SIZE];
821 if (pack_byte_string(request, sizeof(request), "sd",
822 0, command, sizeof(command),
823 req_handle_offset, auth_handle))
824 return TPM_LIB_ERROR;
825 if (oiap_session.valid && oiap_session.handle == auth_handle)
826 oiap_session.valid = 0;
828 return tpm_sendrecv_command(request, NULL, NULL);
831 uint32_t tpm_end_oiap(void)
833 uint32_t err = TPM_SUCCESS;
834 if (oiap_session.valid)
835 err = tpm_terminate_auth_session(oiap_session.handle);
839 uint32_t tpm_oiap(uint32_t *auth_handle)
841 const uint8_t command[10] = {
842 0x00, 0xc1, /* TPM_TAG */
843 0x00, 0x00, 0x00, 0x0a, /* parameter size */
844 0x00, 0x00, 0x00, 0x0a, /* TPM_COMMAND_CODE */
846 const size_t res_auth_handle_offset = TPM_RESPONSE_HEADER_LENGTH;
847 const size_t res_nonce_even_offset = TPM_RESPONSE_HEADER_LENGTH + 4;
848 uint8_t response[COMMAND_BUFFER_SIZE];
849 size_t response_length = sizeof(response);
852 if (oiap_session.valid)
853 tpm_terminate_auth_session(oiap_session.handle);
855 err = tpm_sendrecv_command(command, response, &response_length);
858 if (unpack_byte_string(response, response_length, "ds",
859 res_auth_handle_offset, &oiap_session.handle,
860 res_nonce_even_offset, &oiap_session.nonce_even,
861 (uint32_t)DIGEST_LENGTH))
862 return TPM_LIB_ERROR;
863 oiap_session.valid = 1;
865 *auth_handle = oiap_session.handle;
869 uint32_t tpm_load_key2_oiap(uint32_t parent_handle,
870 const void *key, size_t key_length,
871 const void *parent_key_usage_auth,
872 uint32_t *key_handle)
874 const uint8_t command[14] = {
875 0x00, 0xc2, /* TPM_TAG */
876 0x00, 0x00, 0x00, 0x00, /* parameter size */
877 0x00, 0x00, 0x00, 0x41, /* TPM_COMMAND_CODE */
878 0x00, 0x00, 0x00, 0x00, /* parent handle */
880 const size_t req_size_offset = 2;
881 const size_t req_parent_handle_offset = TPM_REQUEST_HEADER_LENGTH;
882 const size_t req_key_offset = TPM_REQUEST_HEADER_LENGTH + 4;
883 const size_t res_handle_offset = TPM_RESPONSE_HEADER_LENGTH;
884 uint8_t request[sizeof(command) + TPM_KEY12_MAX_LENGTH
885 + TPM_REQUEST_AUTH_LENGTH];
886 uint8_t response[COMMAND_BUFFER_SIZE];
887 size_t response_length = sizeof(response);
890 if (!oiap_session.valid) {
891 err = tpm_oiap(NULL);
895 if (pack_byte_string(request, sizeof(request), "sdds",
896 0, command, sizeof(command),
898 sizeof(command) + key_length
899 + TPM_REQUEST_AUTH_LENGTH,
900 req_parent_handle_offset, parent_handle,
901 req_key_offset, key, key_length
903 return TPM_LIB_ERROR;
905 err = create_request_auth(request, sizeof(command) + key_length, 4,
907 request + sizeof(command) + key_length,
908 parent_key_usage_auth);
911 err = tpm_sendrecv_command(request, response, &response_length);
913 if (err == TPM_AUTHFAIL)
914 oiap_session.valid = 0;
918 err = verify_response_auth(0x00000041, response,
919 response_length - TPM_RESPONSE_AUTH_LENGTH,
921 response + response_length - TPM_RESPONSE_AUTH_LENGTH,
922 parent_key_usage_auth);
927 if (unpack_byte_string(response, response_length, "d",
928 res_handle_offset, key_handle))
929 return TPM_LIB_ERROR;
935 uint32_t tpm_get_pub_key_oiap(uint32_t key_handle, const void *usage_auth,
936 void *pubkey, size_t *pubkey_len)
938 const uint8_t command[14] = {
939 0x00, 0xc2, /* TPM_TAG */
940 0x00, 0x00, 0x00, 0x00, /* parameter size */
941 0x00, 0x00, 0x00, 0x21, /* TPM_COMMAND_CODE */
942 0x00, 0x00, 0x00, 0x00, /* key handle */
944 const size_t req_size_offset = 2;
945 const size_t req_key_handle_offset = TPM_REQUEST_HEADER_LENGTH;
946 const size_t res_pubkey_offset = TPM_RESPONSE_HEADER_LENGTH;
947 uint8_t request[sizeof(command) + TPM_REQUEST_AUTH_LENGTH];
948 uint8_t response[TPM_RESPONSE_HEADER_LENGTH + TPM_PUBKEY_MAX_LENGTH
949 + TPM_RESPONSE_AUTH_LENGTH];
950 size_t response_length = sizeof(response);
953 if (!oiap_session.valid) {
954 err = tpm_oiap(NULL);
958 if (pack_byte_string(request, sizeof(request), "sdd",
959 0, command, sizeof(command),
961 (uint32_t)(sizeof(command)
962 + TPM_REQUEST_AUTH_LENGTH),
963 req_key_handle_offset, key_handle
965 return TPM_LIB_ERROR;
966 err = create_request_auth(request, sizeof(command), 4, &oiap_session,
967 request + sizeof(command), usage_auth);
970 err = tpm_sendrecv_command(request, response, &response_length);
972 if (err == TPM_AUTHFAIL)
973 oiap_session.valid = 0;
976 err = verify_response_auth(0x00000021, response,
977 response_length - TPM_RESPONSE_AUTH_LENGTH,
979 response + response_length - TPM_RESPONSE_AUTH_LENGTH,
985 if ((response_length - TPM_RESPONSE_HEADER_LENGTH
986 - TPM_RESPONSE_AUTH_LENGTH) > *pubkey_len)
987 return TPM_LIB_ERROR;
988 *pubkey_len = response_length - TPM_RESPONSE_HEADER_LENGTH
989 - TPM_RESPONSE_AUTH_LENGTH;
990 memcpy(pubkey, response + res_pubkey_offset,
991 response_length - TPM_RESPONSE_HEADER_LENGTH
992 - TPM_RESPONSE_AUTH_LENGTH);
998 #ifdef CONFIG_TPM_LOAD_KEY_BY_SHA1
999 uint32_t tpm_find_key_sha1(const uint8_t auth[20], const uint8_t
1000 pubkey_digest[20], uint32_t *handle)
1003 uint32_t key_handles[10];
1011 /* fetch list of already loaded keys in the TPM */
1012 err = tpm_get_capability(TPM_CAP_HANDLE, TPM_RT_KEY, buf, sizeof(buf));
1015 key_count = get_unaligned_be16(buf);
1017 for (i = 0; i < key_count; ++i, ptr += 4)
1018 key_handles[i] = get_unaligned_be32(ptr);
1020 /* now search a(/ the) key which we can access with the given auth */
1021 for (i = 0; i < key_count; ++i) {
1022 buf_len = sizeof(buf);
1023 err = tpm_get_pub_key_oiap(key_handles[i], auth, buf, &buf_len);
1024 if (err && err != TPM_AUTHFAIL)
1028 sha1_csum(buf, buf_len, digest);
1029 if (!memcmp(digest, pubkey_digest, 20)) {
1030 *handle = key_handles[i];
1036 #endif /* CONFIG_TPM_LOAD_KEY_BY_SHA1 */
1038 #endif /* CONFIG_TPM_AUTH_SESSIONS */