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) {
108 put_unaligned_be16(value, str + offset);
111 put_unaligned_be32(value, str + offset);
114 memcpy(str + offset, data, length);
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
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
136 int unpack_byte_string(const uint8_t *str, size_t size, const char *format, ...)
139 size_t offset = 0, length = 0;
140 uint8_t *ptr8 = NULL;
141 uint16_t *ptr16 = NULL;
142 uint32_t *ptr32 = NULL;
144 va_start(args, format);
145 for (; *format; format++) {
148 offset = va_arg(args, size_t);
149 ptr8 = va_arg(args, uint8_t *);
153 offset = va_arg(args, size_t);
154 ptr16 = va_arg(args, uint16_t *);
158 offset = va_arg(args, size_t);
159 ptr32 = va_arg(args, uint32_t *);
163 offset = va_arg(args, size_t);
164 ptr8 = va_arg(args, uint8_t *);
165 length = va_arg(args, uint32_t);
169 debug("Couldn't recognize format string\n");
173 if (offset + length > size)
181 *ptr16 = get_unaligned_be16(str + offset);
184 *ptr32 = get_unaligned_be32(str + offset);
187 memcpy(ptr8, str + offset, length);
197 * Get TPM command size.
199 * @param command byte string of TPM command
200 * @return command size of the TPM command
202 static uint32_t tpm_command_size(const void *command)
204 const size_t command_size_offset = 2;
205 return get_unaligned_be32(command + command_size_offset);
209 * Get TPM response return code, which is one of TPM_RESULT values.
211 * @param response byte string of TPM response
212 * @return return code of the TPM response
214 static uint32_t tpm_return_code(const void *response)
216 const size_t return_code_offset = 6;
217 return get_unaligned_be32(response + return_code_offset);
221 * Send a TPM command and return response's return code, and optionally
222 * return response to caller.
224 * @param command byte string of TPM command
225 * @param response output buffer for TPM response, or NULL if the
226 * caller does not care about it
227 * @param size_ptr output buffer size (input parameter) and TPM
228 * response length (output parameter); this parameter
230 * @return return code of the TPM response
232 static uint32_t tpm_sendrecv_command(const void *command,
233 void *response, size_t *size_ptr)
237 uint8_t response_buffer[COMMAND_BUFFER_SIZE];
238 size_t response_length;
241 response_length = *size_ptr;
243 response = response_buffer;
244 response_length = sizeof(response_buffer);
247 ret = uclass_first_device_err(UCLASS_TPM, &dev);
250 err = tpm_xfer(dev, command, tpm_command_size(command),
251 response, &response_length);
254 return TPM_LIB_ERROR;
256 *size_ptr = response_length;
258 return tpm_return_code(response);
266 err = uclass_first_device_err(UCLASS_TPM, &dev);
269 return tpm_open(dev);
272 uint32_t tpm_startup(enum tpm_startup_type mode)
274 const uint8_t command[12] = {
275 0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0x99, 0x0, 0x0,
277 const size_t mode_offset = 10;
278 uint8_t buf[COMMAND_BUFFER_SIZE];
280 if (pack_byte_string(buf, sizeof(buf), "sw",
281 0, command, sizeof(command),
283 return TPM_LIB_ERROR;
285 return tpm_sendrecv_command(buf, NULL, NULL);
288 uint32_t tpm_self_test_full(void)
290 const uint8_t command[10] = {
291 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x50,
293 return tpm_sendrecv_command(command, NULL, NULL);
296 uint32_t tpm_continue_self_test(void)
298 const uint8_t command[10] = {
299 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x53,
301 return tpm_sendrecv_command(command, NULL, NULL);
304 uint32_t tpm_nv_define_space(uint32_t index, uint32_t perm, uint32_t size)
306 const uint8_t command[101] = {
307 0x0, 0xc1, /* TPM_TAG */
308 0x0, 0x0, 0x0, 0x65, /* parameter size */
309 0x0, 0x0, 0x0, 0xcc, /* TPM_COMMAND_CODE */
310 /* TPM_NV_DATA_PUBLIC->... */
311 0x0, 0x18, /* ...->TPM_STRUCTURE_TAG */
312 0, 0, 0, 0, /* ...->TPM_NV_INDEX */
313 /* TPM_NV_DATA_PUBLIC->TPM_PCR_INFO_SHORT */
317 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
318 /* TPM_NV_DATA_PUBLIC->TPM_PCR_INFO_SHORT */
322 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
323 /* TPM_NV_ATTRIBUTES->... */
324 0x0, 0x17, /* ...->TPM_STRUCTURE_TAG */
325 0, 0, 0, 0, /* ...->attributes */
326 /* End of TPM_NV_ATTRIBUTES */
327 0, /* bReadSTClear */
328 0, /* bWriteSTClear */
329 0, /* bWriteDefine */
330 0, 0, 0, 0, /* size */
332 const size_t index_offset = 12;
333 const size_t perm_offset = 70;
334 const size_t size_offset = 77;
335 uint8_t buf[COMMAND_BUFFER_SIZE];
337 if (pack_byte_string(buf, sizeof(buf), "sddd",
338 0, command, sizeof(command),
342 return TPM_LIB_ERROR;
344 return tpm_sendrecv_command(buf, NULL, NULL);
347 uint32_t tpm_nv_read_value(uint32_t index, void *data, uint32_t count)
349 const uint8_t command[22] = {
350 0x0, 0xc1, 0x0, 0x0, 0x0, 0x16, 0x0, 0x0, 0x0, 0xcf,
352 const size_t index_offset = 10;
353 const size_t length_offset = 18;
354 const size_t data_size_offset = 10;
355 const size_t data_offset = 14;
356 uint8_t buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
357 size_t response_length = sizeof(response);
361 if (pack_byte_string(buf, sizeof(buf), "sdd",
362 0, command, sizeof(command),
364 length_offset, count))
365 return TPM_LIB_ERROR;
366 err = tpm_sendrecv_command(buf, response, &response_length);
369 if (unpack_byte_string(response, response_length, "d",
370 data_size_offset, &data_size))
371 return TPM_LIB_ERROR;
372 if (data_size > count)
373 return TPM_LIB_ERROR;
374 if (unpack_byte_string(response, response_length, "s",
375 data_offset, data, data_size))
376 return TPM_LIB_ERROR;
381 uint32_t tpm_nv_write_value(uint32_t index, const void *data, uint32_t length)
383 const uint8_t command[256] = {
384 0x0, 0xc1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xcd,
386 const size_t command_size_offset = 2;
387 const size_t index_offset = 10;
388 const size_t length_offset = 18;
389 const size_t data_offset = 22;
390 const size_t write_info_size = 12;
391 const uint32_t total_length =
392 TPM_REQUEST_HEADER_LENGTH + write_info_size + length;
393 uint8_t buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
394 size_t response_length = sizeof(response);
397 if (pack_byte_string(buf, sizeof(buf), "sddds",
398 0, command, sizeof(command),
399 command_size_offset, total_length,
401 length_offset, length,
402 data_offset, data, length))
403 return TPM_LIB_ERROR;
404 err = tpm_sendrecv_command(buf, response, &response_length);
411 uint32_t tpm_extend(uint32_t index, const void *in_digest, void *out_digest)
413 const uint8_t command[34] = {
414 0x0, 0xc1, 0x0, 0x0, 0x0, 0x22, 0x0, 0x0, 0x0, 0x14,
416 const size_t index_offset = 10;
417 const size_t in_digest_offset = 14;
418 const size_t out_digest_offset = 10;
419 uint8_t buf[COMMAND_BUFFER_SIZE];
420 uint8_t response[TPM_RESPONSE_HEADER_LENGTH + PCR_DIGEST_LENGTH];
421 size_t response_length = sizeof(response);
424 if (pack_byte_string(buf, sizeof(buf), "sds",
425 0, command, sizeof(command),
427 in_digest_offset, in_digest,
429 return TPM_LIB_ERROR;
430 err = tpm_sendrecv_command(buf, response, &response_length);
434 if (unpack_byte_string(response, response_length, "s",
435 out_digest_offset, out_digest,
437 return TPM_LIB_ERROR;
442 uint32_t tpm_pcr_read(uint32_t index, void *data, size_t count)
444 const uint8_t command[14] = {
445 0x0, 0xc1, 0x0, 0x0, 0x0, 0xe, 0x0, 0x0, 0x0, 0x15,
447 const size_t index_offset = 10;
448 const size_t out_digest_offset = 10;
449 uint8_t buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
450 size_t response_length = sizeof(response);
453 if (count < PCR_DIGEST_LENGTH)
454 return TPM_LIB_ERROR;
456 if (pack_byte_string(buf, sizeof(buf), "sd",
457 0, command, sizeof(command),
458 index_offset, index))
459 return TPM_LIB_ERROR;
460 err = tpm_sendrecv_command(buf, response, &response_length);
463 if (unpack_byte_string(response, response_length, "s",
464 out_digest_offset, data, PCR_DIGEST_LENGTH))
465 return TPM_LIB_ERROR;
470 uint32_t tpm_tsc_physical_presence(uint16_t presence)
472 const uint8_t command[12] = {
473 0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x40, 0x0, 0x0, 0xa, 0x0, 0x0,
475 const size_t presence_offset = 10;
476 uint8_t buf[COMMAND_BUFFER_SIZE];
478 if (pack_byte_string(buf, sizeof(buf), "sw",
479 0, command, sizeof(command),
480 presence_offset, presence))
481 return TPM_LIB_ERROR;
483 return tpm_sendrecv_command(buf, NULL, NULL);
486 uint32_t tpm_read_pubek(void *data, size_t count)
488 const uint8_t command[30] = {
489 0x0, 0xc1, 0x0, 0x0, 0x0, 0x1e, 0x0, 0x0, 0x0, 0x7c,
491 const size_t response_size_offset = 2;
492 const size_t data_offset = 10;
493 const size_t header_and_checksum_size = TPM_RESPONSE_HEADER_LENGTH + 20;
494 uint8_t response[COMMAND_BUFFER_SIZE + TPM_PUBEK_SIZE];
495 size_t response_length = sizeof(response);
499 err = tpm_sendrecv_command(command, response, &response_length);
502 if (unpack_byte_string(response, response_length, "d",
503 response_size_offset, &data_size))
504 return TPM_LIB_ERROR;
505 if (data_size < header_and_checksum_size)
506 return TPM_LIB_ERROR;
507 data_size -= header_and_checksum_size;
508 if (data_size > count)
509 return TPM_LIB_ERROR;
510 if (unpack_byte_string(response, response_length, "s",
511 data_offset, data, data_size))
512 return TPM_LIB_ERROR;
517 uint32_t tpm_force_clear(void)
519 const uint8_t command[10] = {
520 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x5d,
523 return tpm_sendrecv_command(command, NULL, NULL);
526 uint32_t tpm_physical_enable(void)
528 const uint8_t command[10] = {
529 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x6f,
532 return tpm_sendrecv_command(command, NULL, NULL);
535 uint32_t tpm_physical_disable(void)
537 const uint8_t command[10] = {
538 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x70,
541 return tpm_sendrecv_command(command, NULL, NULL);
544 uint32_t tpm_physical_set_deactivated(uint8_t state)
546 const uint8_t command[11] = {
547 0x0, 0xc1, 0x0, 0x0, 0x0, 0xb, 0x0, 0x0, 0x0, 0x72,
549 const size_t state_offset = 10;
550 uint8_t buf[COMMAND_BUFFER_SIZE];
552 if (pack_byte_string(buf, sizeof(buf), "sb",
553 0, command, sizeof(command),
554 state_offset, state))
555 return TPM_LIB_ERROR;
557 return tpm_sendrecv_command(buf, NULL, NULL);
560 uint32_t tpm_get_capability(uint32_t cap_area, uint32_t sub_cap,
561 void *cap, size_t count)
563 const uint8_t command[22] = {
564 0x0, 0xc1, /* TPM_TAG */
565 0x0, 0x0, 0x0, 0x16, /* parameter size */
566 0x0, 0x0, 0x0, 0x65, /* TPM_COMMAND_CODE */
567 0x0, 0x0, 0x0, 0x0, /* TPM_CAPABILITY_AREA */
568 0x0, 0x0, 0x0, 0x4, /* subcap size */
569 0x0, 0x0, 0x0, 0x0, /* subcap value */
571 const size_t cap_area_offset = 10;
572 const size_t sub_cap_offset = 18;
573 const size_t cap_offset = 14;
574 const size_t cap_size_offset = 10;
575 uint8_t buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
576 size_t response_length = sizeof(response);
580 if (pack_byte_string(buf, sizeof(buf), "sdd",
581 0, command, sizeof(command),
582 cap_area_offset, cap_area,
583 sub_cap_offset, sub_cap))
584 return TPM_LIB_ERROR;
585 err = tpm_sendrecv_command(buf, response, &response_length);
588 if (unpack_byte_string(response, response_length, "d",
589 cap_size_offset, &cap_size))
590 return TPM_LIB_ERROR;
591 if (cap_size > response_length || cap_size > count)
592 return TPM_LIB_ERROR;
593 if (unpack_byte_string(response, response_length, "s",
594 cap_offset, cap, cap_size))
595 return TPM_LIB_ERROR;
600 uint32_t tpm_get_permanent_flags(struct tpm_permanent_flags *pflags)
602 const uint8_t command[22] = {
603 0x0, 0xc1, /* TPM_TAG */
604 0x0, 0x0, 0x0, 0x16, /* parameter size */
605 0x0, 0x0, 0x0, 0x65, /* TPM_COMMAND_CODE */
606 0x0, 0x0, 0x0, 0x4, /* TPM_CAP_FLAG_PERM */
607 0x0, 0x0, 0x0, 0x4, /* subcap size */
608 0x0, 0x0, 0x1, 0x8, /* subcap value */
610 const size_t data_size_offset = TPM_HEADER_SIZE;
611 const size_t data_offset = TPM_HEADER_SIZE + sizeof (uint32_t);
612 uint8_t response[COMMAND_BUFFER_SIZE];
613 size_t response_length = sizeof(response);
617 err = tpm_sendrecv_command(command, response, &response_length);
620 if (unpack_byte_string(response, response_length, "d",
621 data_size_offset, &data_size))
622 return TPM_LIB_ERROR;
623 if (data_size < sizeof(*pflags))
624 return TPM_LIB_ERROR;
625 if (unpack_byte_string(response, response_length, "s",
626 data_offset, pflags, sizeof(*pflags)))
627 return TPM_LIB_ERROR;
632 uint32_t tpm_get_permissions(uint32_t index, uint32_t *perm)
634 const uint8_t command[22] = {
635 0x0, 0xc1, /* TPM_TAG */
636 0x0, 0x0, 0x0, 0x16, /* parameter size */
637 0x0, 0x0, 0x0, 0x65, /* TPM_COMMAND_CODE */
641 const size_t index_offset = 18;
642 const size_t perm_offset = 60;
643 uint8_t buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
644 size_t response_length = sizeof(response);
647 if (pack_byte_string(buf, sizeof(buf), "d", 0, command, sizeof(command),
648 index_offset, index))
649 return TPM_LIB_ERROR;
650 err = tpm_sendrecv_command(buf, response, &response_length);
653 if (unpack_byte_string(response, response_length, "d",
655 return TPM_LIB_ERROR;
660 #ifdef CONFIG_TPM_FLUSH_RESOURCES
661 uint32_t tpm_flush_specific(uint32_t key_handle, uint32_t resource_type)
663 const uint8_t command[18] = {
664 0x00, 0xc1, /* TPM_TAG */
665 0x00, 0x00, 0x00, 0x12, /* parameter size */
666 0x00, 0x00, 0x00, 0xba, /* TPM_COMMAND_CODE */
667 0x00, 0x00, 0x00, 0x00, /* key handle */
668 0x00, 0x00, 0x00, 0x00, /* resource type */
670 const size_t key_handle_offset = 10;
671 const size_t resource_type_offset = 14;
672 uint8_t buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
673 size_t response_length = sizeof(response);
676 if (pack_byte_string(buf, sizeof(buf), "sdd",
677 0, command, sizeof(command),
678 key_handle_offset, key_handle,
679 resource_type_offset, resource_type))
680 return TPM_LIB_ERROR;
682 err = tpm_sendrecv_command(buf, response, &response_length);
687 #endif /* CONFIG_TPM_FLUSH_RESOURCES */
689 #ifdef CONFIG_TPM_AUTH_SESSIONS
692 * Fill an authentication block in a request.
693 * This func can create the first as well as the second auth block (for
694 * double authorized commands).
696 * @param request pointer to the request (w/ uninitialised auth data)
697 * @param request_len0 length of the request without auth data
698 * @param handles_len length of the handles area in request
699 * @param auth_session pointer to the (valid) auth session to be used
700 * @param request_auth pointer to the auth block of the request to be filled
701 * @param auth authentication data (HMAC key)
703 static uint32_t create_request_auth(const void *request, size_t request_len0,
705 struct session_data *auth_session,
706 void *request_auth, const void *auth)
708 uint8_t hmac_data[DIGEST_LENGTH * 3 + 1];
709 sha1_context hash_ctx;
710 const size_t command_code_offset = 6;
711 const size_t auth_nonce_odd_offset = 4;
712 const size_t auth_continue_offset = 24;
713 const size_t auth_auth_offset = 25;
715 if (!auth_session || !auth_session->valid)
716 return TPM_LIB_ERROR;
718 sha1_starts(&hash_ctx);
719 sha1_update(&hash_ctx, request + command_code_offset, 4);
720 if (request_len0 > TPM_REQUEST_HEADER_LENGTH + handles_len)
721 sha1_update(&hash_ctx,
722 request + TPM_REQUEST_HEADER_LENGTH + handles_len,
723 request_len0 - TPM_REQUEST_HEADER_LENGTH
725 sha1_finish(&hash_ctx, hmac_data);
727 sha1_starts(&hash_ctx);
728 sha1_update(&hash_ctx, auth_session->nonce_odd, DIGEST_LENGTH);
729 sha1_update(&hash_ctx, hmac_data, sizeof(hmac_data));
730 sha1_finish(&hash_ctx, auth_session->nonce_odd);
732 if (pack_byte_string(request_auth, TPM_REQUEST_AUTH_LENGTH, "dsb",
733 0, auth_session->handle,
734 auth_nonce_odd_offset, auth_session->nonce_odd,
736 auth_continue_offset, 1))
737 return TPM_LIB_ERROR;
738 if (pack_byte_string(hmac_data, sizeof(hmac_data), "ss",
740 auth_session->nonce_even,
743 request_auth + auth_nonce_odd_offset,
745 return TPM_LIB_ERROR;
746 sha1_hmac(auth, DIGEST_LENGTH, hmac_data, sizeof(hmac_data),
747 request_auth + auth_auth_offset);
753 * Verify an authentication block in a response.
754 * Since this func updates the nonce_even in the session data it has to be
755 * called when receiving a succesfull AUTH response.
756 * This func can verify the first as well as the second auth block (for
757 * double authorized commands).
759 * @param command_code command code of the request
760 * @param response pointer to the request (w/ uninitialised auth data)
761 * @param handles_len length of the handles area in response
762 * @param auth_session pointer to the (valid) auth session to be used
763 * @param response_auth pointer to the auth block of the response to be verified
764 * @param auth authentication data (HMAC key)
766 static uint32_t verify_response_auth(uint32_t command_code,
767 const void *response, size_t response_len0,
769 struct session_data *auth_session,
770 const void *response_auth, const void *auth)
772 uint8_t hmac_data[DIGEST_LENGTH * 3 + 1];
773 uint8_t computed_auth[DIGEST_LENGTH];
774 sha1_context hash_ctx;
775 const size_t return_code_offset = 6;
776 const size_t auth_continue_offset = 20;
777 const size_t auth_auth_offset = 21;
778 uint8_t auth_continue;
780 if (!auth_session || !auth_session->valid)
782 if (pack_byte_string(hmac_data, sizeof(hmac_data), "d",
784 return TPM_LIB_ERROR;
785 if (response_len0 < TPM_RESPONSE_HEADER_LENGTH)
786 return TPM_LIB_ERROR;
788 sha1_starts(&hash_ctx);
789 sha1_update(&hash_ctx, response + return_code_offset, 4);
790 sha1_update(&hash_ctx, hmac_data, 4);
791 if (response_len0 > TPM_RESPONSE_HEADER_LENGTH + handles_len)
792 sha1_update(&hash_ctx,
793 response + TPM_RESPONSE_HEADER_LENGTH + handles_len,
794 response_len0 - TPM_RESPONSE_HEADER_LENGTH
796 sha1_finish(&hash_ctx, hmac_data);
798 memcpy(auth_session->nonce_even, response_auth, DIGEST_LENGTH);
799 auth_continue = ((uint8_t *)response_auth)[auth_continue_offset];
800 if (pack_byte_string(hmac_data, sizeof(hmac_data), "ssb",
805 auth_session->nonce_odd,
809 return TPM_LIB_ERROR;
811 sha1_hmac(auth, DIGEST_LENGTH, hmac_data, sizeof(hmac_data),
814 if (memcmp(computed_auth, response_auth + auth_auth_offset,
822 uint32_t tpm_terminate_auth_session(uint32_t auth_handle)
824 const uint8_t command[18] = {
825 0x00, 0xc1, /* TPM_TAG */
826 0x00, 0x00, 0x00, 0x00, /* parameter size */
827 0x00, 0x00, 0x00, 0xba, /* TPM_COMMAND_CODE */
828 0x00, 0x00, 0x00, 0x00, /* TPM_HANDLE */
829 0x00, 0x00, 0x00, 0x02, /* TPM_RESSOURCE_TYPE */
831 const size_t req_handle_offset = TPM_REQUEST_HEADER_LENGTH;
832 uint8_t request[COMMAND_BUFFER_SIZE];
834 if (pack_byte_string(request, sizeof(request), "sd",
835 0, command, sizeof(command),
836 req_handle_offset, auth_handle))
837 return TPM_LIB_ERROR;
838 if (oiap_session.valid && oiap_session.handle == auth_handle)
839 oiap_session.valid = 0;
841 return tpm_sendrecv_command(request, NULL, NULL);
844 uint32_t tpm_end_oiap(void)
846 uint32_t err = TPM_SUCCESS;
847 if (oiap_session.valid)
848 err = tpm_terminate_auth_session(oiap_session.handle);
852 uint32_t tpm_oiap(uint32_t *auth_handle)
854 const uint8_t command[10] = {
855 0x00, 0xc1, /* TPM_TAG */
856 0x00, 0x00, 0x00, 0x0a, /* parameter size */
857 0x00, 0x00, 0x00, 0x0a, /* TPM_COMMAND_CODE */
859 const size_t res_auth_handle_offset = TPM_RESPONSE_HEADER_LENGTH;
860 const size_t res_nonce_even_offset = TPM_RESPONSE_HEADER_LENGTH + 4;
861 uint8_t response[COMMAND_BUFFER_SIZE];
862 size_t response_length = sizeof(response);
865 if (oiap_session.valid)
866 tpm_terminate_auth_session(oiap_session.handle);
868 err = tpm_sendrecv_command(command, response, &response_length);
871 if (unpack_byte_string(response, response_length, "ds",
872 res_auth_handle_offset, &oiap_session.handle,
873 res_nonce_even_offset, &oiap_session.nonce_even,
874 (uint32_t)DIGEST_LENGTH))
875 return TPM_LIB_ERROR;
876 oiap_session.valid = 1;
878 *auth_handle = oiap_session.handle;
882 uint32_t tpm_load_key2_oiap(uint32_t parent_handle,
883 const void *key, size_t key_length,
884 const void *parent_key_usage_auth,
885 uint32_t *key_handle)
887 const uint8_t command[14] = {
888 0x00, 0xc2, /* TPM_TAG */
889 0x00, 0x00, 0x00, 0x00, /* parameter size */
890 0x00, 0x00, 0x00, 0x41, /* TPM_COMMAND_CODE */
891 0x00, 0x00, 0x00, 0x00, /* parent handle */
893 const size_t req_size_offset = 2;
894 const size_t req_parent_handle_offset = TPM_REQUEST_HEADER_LENGTH;
895 const size_t req_key_offset = TPM_REQUEST_HEADER_LENGTH + 4;
896 const size_t res_handle_offset = TPM_RESPONSE_HEADER_LENGTH;
897 uint8_t request[sizeof(command) + TPM_KEY12_MAX_LENGTH
898 + TPM_REQUEST_AUTH_LENGTH];
899 uint8_t response[COMMAND_BUFFER_SIZE];
900 size_t response_length = sizeof(response);
903 if (!oiap_session.valid) {
904 err = tpm_oiap(NULL);
908 if (pack_byte_string(request, sizeof(request), "sdds",
909 0, command, sizeof(command),
911 sizeof(command) + key_length
912 + TPM_REQUEST_AUTH_LENGTH,
913 req_parent_handle_offset, parent_handle,
914 req_key_offset, key, key_length
916 return TPM_LIB_ERROR;
918 err = create_request_auth(request, sizeof(command) + key_length, 4,
920 request + sizeof(command) + key_length,
921 parent_key_usage_auth);
924 err = tpm_sendrecv_command(request, response, &response_length);
926 if (err == TPM_AUTHFAIL)
927 oiap_session.valid = 0;
931 err = verify_response_auth(0x00000041, response,
932 response_length - TPM_RESPONSE_AUTH_LENGTH,
934 response + response_length - TPM_RESPONSE_AUTH_LENGTH,
935 parent_key_usage_auth);
940 if (unpack_byte_string(response, response_length, "d",
941 res_handle_offset, key_handle))
942 return TPM_LIB_ERROR;
948 uint32_t tpm_get_pub_key_oiap(uint32_t key_handle, const void *usage_auth,
949 void *pubkey, size_t *pubkey_len)
951 const uint8_t command[14] = {
952 0x00, 0xc2, /* TPM_TAG */
953 0x00, 0x00, 0x00, 0x00, /* parameter size */
954 0x00, 0x00, 0x00, 0x21, /* TPM_COMMAND_CODE */
955 0x00, 0x00, 0x00, 0x00, /* key handle */
957 const size_t req_size_offset = 2;
958 const size_t req_key_handle_offset = TPM_REQUEST_HEADER_LENGTH;
959 const size_t res_pubkey_offset = TPM_RESPONSE_HEADER_LENGTH;
960 uint8_t request[sizeof(command) + TPM_REQUEST_AUTH_LENGTH];
961 uint8_t response[TPM_RESPONSE_HEADER_LENGTH + TPM_PUBKEY_MAX_LENGTH
962 + TPM_RESPONSE_AUTH_LENGTH];
963 size_t response_length = sizeof(response);
966 if (!oiap_session.valid) {
967 err = tpm_oiap(NULL);
971 if (pack_byte_string(request, sizeof(request), "sdd",
972 0, command, sizeof(command),
974 (uint32_t)(sizeof(command)
975 + TPM_REQUEST_AUTH_LENGTH),
976 req_key_handle_offset, key_handle
978 return TPM_LIB_ERROR;
979 err = create_request_auth(request, sizeof(command), 4, &oiap_session,
980 request + sizeof(command), usage_auth);
983 err = tpm_sendrecv_command(request, response, &response_length);
985 if (err == TPM_AUTHFAIL)
986 oiap_session.valid = 0;
989 err = verify_response_auth(0x00000021, response,
990 response_length - TPM_RESPONSE_AUTH_LENGTH,
992 response + response_length - TPM_RESPONSE_AUTH_LENGTH,
998 if ((response_length - TPM_RESPONSE_HEADER_LENGTH
999 - TPM_RESPONSE_AUTH_LENGTH) > *pubkey_len)
1000 return TPM_LIB_ERROR;
1001 *pubkey_len = response_length - TPM_RESPONSE_HEADER_LENGTH
1002 - TPM_RESPONSE_AUTH_LENGTH;
1003 memcpy(pubkey, response + res_pubkey_offset,
1004 response_length - TPM_RESPONSE_HEADER_LENGTH
1005 - TPM_RESPONSE_AUTH_LENGTH);
1011 #ifdef CONFIG_TPM_LOAD_KEY_BY_SHA1
1012 uint32_t tpm_find_key_sha1(const uint8_t auth[20], const uint8_t
1013 pubkey_digest[20], uint32_t *handle)
1016 uint32_t key_handles[10];
1024 /* fetch list of already loaded keys in the TPM */
1025 err = tpm_get_capability(TPM_CAP_HANDLE, TPM_RT_KEY, buf, sizeof(buf));
1028 key_count = get_unaligned_be16(buf);
1030 for (i = 0; i < key_count; ++i, ptr += 4)
1031 key_handles[i] = get_unaligned_be32(ptr);
1033 /* now search a(/ the) key which we can access with the given auth */
1034 for (i = 0; i < key_count; ++i) {
1035 buf_len = sizeof(buf);
1036 err = tpm_get_pub_key_oiap(key_handles[i], auth, buf, &buf_len);
1037 if (err && err != TPM_AUTHFAIL)
1041 sha1_csum(buf, buf_len, digest);
1042 if (!memcmp(digest, pubkey_digest, 20)) {
1043 *handle = key_handles[i];
1049 #endif /* CONFIG_TPM_LOAD_KEY_BY_SHA1 */
1051 #endif /* CONFIG_TPM_AUTH_SESSIONS */
1053 uint32_t tpm_get_random(void *data, uint32_t count)
1055 const uint8_t command[14] = {
1056 0x0, 0xc1, /* TPM_TAG */
1057 0x0, 0x0, 0x0, 0xe, /* parameter size */
1058 0x0, 0x0, 0x0, 0x46, /* TPM_COMMAND_CODE */
1060 const size_t length_offset = 10;
1061 const size_t data_size_offset = 10;
1062 const size_t data_offset = 14;
1063 uint8_t buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
1064 size_t response_length = sizeof(response);
1066 uint8_t *out = data;
1069 uint32_t this_bytes = min((size_t)count,
1070 sizeof (response) - data_offset);
1073 if (pack_byte_string(buf, sizeof(buf), "sd",
1074 0, command, sizeof(command),
1075 length_offset, this_bytes))
1076 return TPM_LIB_ERROR;
1077 err = tpm_sendrecv_command(buf, response, &response_length);
1080 if (unpack_byte_string(response, response_length, "d",
1081 data_size_offset, &data_size))
1082 return TPM_LIB_ERROR;
1083 if (data_size > count)
1084 return TPM_LIB_ERROR;
1085 if (unpack_byte_string(response, response_length, "s",
1086 data_offset, out, data_size))
1087 return TPM_LIB_ERROR;