1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright (c) 2013 The Chromium OS Authors.
4 * Coypright (c) 2013 Guntermann & Drunck GmbH
10 #include <asm/unaligned.h>
11 #include <u-boot/sha1.h>
13 /* Internal error of TPM command library */
14 #define TPM_LIB_ERROR ((u32)~0u)
16 /* Useful constants */
18 COMMAND_BUFFER_SIZE = 256,
19 TPM_REQUEST_HEADER_LENGTH = 10,
20 TPM_RESPONSE_HEADER_LENGTH = 10,
21 PCR_DIGEST_LENGTH = 20,
23 TPM_REQUEST_AUTH_LENGTH = 45,
24 TPM_RESPONSE_AUTH_LENGTH = 41,
25 /* some max lengths, valid for RSA keys <= 2048 bits */
26 TPM_KEY12_MAX_LENGTH = 618,
27 TPM_PUBKEY_MAX_LENGTH = 288,
30 #ifdef CONFIG_TPM_AUTH_SESSIONS
33 #error "TPM_AUTH_SESSIONS require SHA1 to be configured, too"
34 #endif /* !CONFIG_SHA1 */
39 u8 nonce_even[DIGEST_LENGTH];
40 u8 nonce_odd[DIGEST_LENGTH];
43 static struct session_data oiap_session = {0, };
45 #endif /* CONFIG_TPM_AUTH_SESSIONS */
48 * Pack data into a byte string. The data types are specified in
49 * the format string: 'b' means unsigned byte, 'w' unsigned word,
50 * 'd' unsigned double word, and 's' byte string. The data are a
51 * series of offsets and values (for type byte string there are also
52 * lengths). The data values are packed into the byte string
53 * sequentially, and so a latter value could over-write a former
56 * @param str output string
57 * @param size size of output string
58 * @param format format string
59 * @param ... data points
60 * @return 0 on success, non-0 on error
62 int pack_byte_string(u8 *str, size_t size, const char *format, ...)
65 size_t offset = 0, length = 0;
69 va_start(args, format);
70 for (; *format; format++) {
73 offset = va_arg(args, size_t);
74 value = va_arg(args, int);
78 offset = va_arg(args, size_t);
79 value = va_arg(args, int);
83 offset = va_arg(args, size_t);
84 value = va_arg(args, u32);
88 offset = va_arg(args, size_t);
89 data = va_arg(args, u8 *);
90 length = va_arg(args, u32);
93 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 u8 *str, size_t size, const char *format, ...)
139 size_t offset = 0, length = 0;
144 va_start(args, format);
145 for (; *format; format++) {
148 offset = va_arg(args, size_t);
149 ptr8 = va_arg(args, u8 *);
153 offset = va_arg(args, size_t);
154 ptr16 = va_arg(args, u16 *);
158 offset = va_arg(args, size_t);
159 ptr32 = va_arg(args, u32 *);
163 offset = va_arg(args, size_t);
164 ptr8 = va_arg(args, u8 *);
165 length = va_arg(args, u32);
169 debug("Couldn't recognize format string\n");
173 if (offset + length > size) {
183 *ptr16 = get_unaligned_be16(str + offset);
186 *ptr32 = get_unaligned_be32(str + offset);
189 memcpy(ptr8, str + offset, length);
199 * Get TPM command size.
201 * @param command byte string of TPM command
202 * @return command size of the TPM command
204 static u32 tpm_command_size(const void *command)
206 const size_t command_size_offset = 2;
207 return get_unaligned_be32(command + command_size_offset);
211 * Get TPM response return code, which is one of TPM_RESULT values.
213 * @param response byte string of TPM response
214 * @return return code of the TPM response
216 static u32 tpm_return_code(const void *response)
218 const size_t return_code_offset = 6;
219 return get_unaligned_be32(response + return_code_offset);
223 * Send a TPM command and return response's return code, and optionally
224 * return response to caller.
226 * @param command byte string of TPM command
227 * @param response output buffer for TPM response, or NULL if the
228 * caller does not care about it
229 * @param size_ptr output buffer size (input parameter) and TPM
230 * response length (output parameter); this parameter
232 * @return return code of the TPM response
234 static u32 tpm_sendrecv_command(const void *command, void *response,
239 u8 response_buffer[COMMAND_BUFFER_SIZE];
240 size_t response_length;
243 response_length = *size_ptr;
245 response = response_buffer;
246 response_length = sizeof(response_buffer);
249 ret = uclass_first_device_err(UCLASS_TPM, &dev);
252 err = tpm_xfer(dev, command, tpm_command_size(command),
253 response, &response_length);
256 return TPM_LIB_ERROR;
258 *size_ptr = response_length;
260 return tpm_return_code(response);
268 err = uclass_first_device_err(UCLASS_TPM, &dev);
271 return tpm_open(dev);
274 u32 tpm_startup(enum tpm_startup_type mode)
276 const u8 command[12] = {
277 0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0x99, 0x0, 0x0,
279 const size_t mode_offset = 10;
280 u8 buf[COMMAND_BUFFER_SIZE];
282 if (pack_byte_string(buf, sizeof(buf), "sw",
283 0, command, sizeof(command),
285 return TPM_LIB_ERROR;
287 return tpm_sendrecv_command(buf, NULL, NULL);
290 u32 tpm_self_test_full(void)
292 const u8 command[10] = {
293 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x50,
295 return tpm_sendrecv_command(command, NULL, NULL);
298 u32 tpm_continue_self_test(void)
300 const u8 command[10] = {
301 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x53,
303 return tpm_sendrecv_command(command, NULL, NULL);
306 u32 tpm_nv_define_space(u32 index, u32 perm, u32 size)
308 const u8 command[101] = {
309 0x0, 0xc1, /* TPM_TAG */
310 0x0, 0x0, 0x0, 0x65, /* parameter size */
311 0x0, 0x0, 0x0, 0xcc, /* TPM_COMMAND_CODE */
312 /* TPM_NV_DATA_PUBLIC->... */
313 0x0, 0x18, /* ...->TPM_STRUCTURE_TAG */
314 0, 0, 0, 0, /* ...->TPM_NV_INDEX */
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_DATA_PUBLIC->TPM_PCR_INFO_SHORT */
324 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
325 /* TPM_NV_ATTRIBUTES->... */
326 0x0, 0x17, /* ...->TPM_STRUCTURE_TAG */
327 0, 0, 0, 0, /* ...->attributes */
328 /* End of TPM_NV_ATTRIBUTES */
329 0, /* bReadSTClear */
330 0, /* bWriteSTClear */
331 0, /* bWriteDefine */
332 0, 0, 0, 0, /* size */
334 const size_t index_offset = 12;
335 const size_t perm_offset = 70;
336 const size_t size_offset = 77;
337 u8 buf[COMMAND_BUFFER_SIZE];
339 if (pack_byte_string(buf, sizeof(buf), "sddd",
340 0, command, sizeof(command),
344 return TPM_LIB_ERROR;
346 return tpm_sendrecv_command(buf, NULL, NULL);
349 u32 tpm_nv_read_value(u32 index, void *data, u32 count)
351 const u8 command[22] = {
352 0x0, 0xc1, 0x0, 0x0, 0x0, 0x16, 0x0, 0x0, 0x0, 0xcf,
354 const size_t index_offset = 10;
355 const size_t length_offset = 18;
356 const size_t data_size_offset = 10;
357 const size_t data_offset = 14;
358 u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
359 size_t response_length = sizeof(response);
363 if (pack_byte_string(buf, sizeof(buf), "sdd",
364 0, command, sizeof(command),
366 length_offset, count))
367 return TPM_LIB_ERROR;
368 err = tpm_sendrecv_command(buf, response, &response_length);
371 if (unpack_byte_string(response, response_length, "d",
372 data_size_offset, &data_size))
373 return TPM_LIB_ERROR;
374 if (data_size > count)
375 return TPM_LIB_ERROR;
376 if (unpack_byte_string(response, response_length, "s",
377 data_offset, data, data_size))
378 return TPM_LIB_ERROR;
383 u32 tpm_nv_write_value(u32 index, const void *data, u32 length)
385 const u8 command[256] = {
386 0x0, 0xc1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xcd,
388 const size_t command_size_offset = 2;
389 const size_t index_offset = 10;
390 const size_t length_offset = 18;
391 const size_t data_offset = 22;
392 const size_t write_info_size = 12;
393 const u32 total_length =
394 TPM_REQUEST_HEADER_LENGTH + write_info_size + length;
395 u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
396 size_t response_length = sizeof(response);
399 if (pack_byte_string(buf, sizeof(buf), "sddds",
400 0, command, sizeof(command),
401 command_size_offset, total_length,
403 length_offset, length,
404 data_offset, data, length))
405 return TPM_LIB_ERROR;
406 err = tpm_sendrecv_command(buf, response, &response_length);
413 u32 tpm_extend(u32 index, const void *in_digest, void *out_digest)
415 const u8 command[34] = {
416 0x0, 0xc1, 0x0, 0x0, 0x0, 0x22, 0x0, 0x0, 0x0, 0x14,
418 const size_t index_offset = 10;
419 const size_t in_digest_offset = 14;
420 const size_t out_digest_offset = 10;
421 u8 buf[COMMAND_BUFFER_SIZE];
422 u8 response[TPM_RESPONSE_HEADER_LENGTH + PCR_DIGEST_LENGTH];
423 size_t response_length = sizeof(response);
426 if (pack_byte_string(buf, sizeof(buf), "sds",
427 0, command, sizeof(command),
429 in_digest_offset, in_digest,
431 return TPM_LIB_ERROR;
432 err = tpm_sendrecv_command(buf, response, &response_length);
436 if (unpack_byte_string(response, response_length, "s",
437 out_digest_offset, out_digest,
439 return TPM_LIB_ERROR;
444 u32 tpm_pcr_read(u32 index, void *data, size_t count)
446 const u8 command[14] = {
447 0x0, 0xc1, 0x0, 0x0, 0x0, 0xe, 0x0, 0x0, 0x0, 0x15,
449 const size_t index_offset = 10;
450 const size_t out_digest_offset = 10;
451 u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
452 size_t response_length = sizeof(response);
455 if (count < PCR_DIGEST_LENGTH)
456 return TPM_LIB_ERROR;
458 if (pack_byte_string(buf, sizeof(buf), "sd",
459 0, command, sizeof(command),
460 index_offset, index))
461 return TPM_LIB_ERROR;
462 err = tpm_sendrecv_command(buf, response, &response_length);
465 if (unpack_byte_string(response, response_length, "s",
466 out_digest_offset, data, PCR_DIGEST_LENGTH))
467 return TPM_LIB_ERROR;
472 u32 tpm_tsc_physical_presence(u16 presence)
474 const u8 command[12] = {
475 0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x40, 0x0, 0x0, 0xa, 0x0, 0x0,
477 const size_t presence_offset = 10;
478 u8 buf[COMMAND_BUFFER_SIZE];
480 if (pack_byte_string(buf, sizeof(buf), "sw",
481 0, command, sizeof(command),
482 presence_offset, presence))
483 return TPM_LIB_ERROR;
485 return tpm_sendrecv_command(buf, NULL, NULL);
488 u32 tpm_read_pubek(void *data, size_t count)
490 const u8 command[30] = {
491 0x0, 0xc1, 0x0, 0x0, 0x0, 0x1e, 0x0, 0x0, 0x0, 0x7c,
493 const size_t response_size_offset = 2;
494 const size_t data_offset = 10;
495 const size_t header_and_checksum_size = TPM_RESPONSE_HEADER_LENGTH + 20;
496 u8 response[COMMAND_BUFFER_SIZE + TPM_PUBEK_SIZE];
497 size_t response_length = sizeof(response);
501 err = tpm_sendrecv_command(command, response, &response_length);
504 if (unpack_byte_string(response, response_length, "d",
505 response_size_offset, &data_size))
506 return TPM_LIB_ERROR;
507 if (data_size < header_and_checksum_size)
508 return TPM_LIB_ERROR;
509 data_size -= header_and_checksum_size;
510 if (data_size > count)
511 return TPM_LIB_ERROR;
512 if (unpack_byte_string(response, response_length, "s",
513 data_offset, data, data_size))
514 return TPM_LIB_ERROR;
519 u32 tpm_force_clear(void)
521 const u8 command[10] = {
522 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x5d,
525 return tpm_sendrecv_command(command, NULL, NULL);
528 u32 tpm_physical_enable(void)
530 const u8 command[10] = {
531 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x6f,
534 return tpm_sendrecv_command(command, NULL, NULL);
537 u32 tpm_physical_disable(void)
539 const u8 command[10] = {
540 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x70,
543 return tpm_sendrecv_command(command, NULL, NULL);
546 u32 tpm_physical_set_deactivated(u8 state)
548 const u8 command[11] = {
549 0x0, 0xc1, 0x0, 0x0, 0x0, 0xb, 0x0, 0x0, 0x0, 0x72,
551 const size_t state_offset = 10;
552 u8 buf[COMMAND_BUFFER_SIZE];
554 if (pack_byte_string(buf, sizeof(buf), "sb",
555 0, command, sizeof(command),
556 state_offset, state))
557 return TPM_LIB_ERROR;
559 return tpm_sendrecv_command(buf, NULL, NULL);
562 u32 tpm_get_capability(u32 cap_area, u32 sub_cap, void *cap, size_t count)
564 const u8 command[22] = {
565 0x0, 0xc1, /* TPM_TAG */
566 0x0, 0x0, 0x0, 0x16, /* parameter size */
567 0x0, 0x0, 0x0, 0x65, /* TPM_COMMAND_CODE */
568 0x0, 0x0, 0x0, 0x0, /* TPM_CAPABILITY_AREA */
569 0x0, 0x0, 0x0, 0x4, /* subcap size */
570 0x0, 0x0, 0x0, 0x0, /* subcap value */
572 const size_t cap_area_offset = 10;
573 const size_t sub_cap_offset = 18;
574 const size_t cap_offset = 14;
575 const size_t cap_size_offset = 10;
576 u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
577 size_t response_length = sizeof(response);
581 if (pack_byte_string(buf, sizeof(buf), "sdd",
582 0, command, sizeof(command),
583 cap_area_offset, cap_area,
584 sub_cap_offset, sub_cap))
585 return TPM_LIB_ERROR;
586 err = tpm_sendrecv_command(buf, response, &response_length);
589 if (unpack_byte_string(response, response_length, "d",
590 cap_size_offset, &cap_size))
591 return TPM_LIB_ERROR;
592 if (cap_size > response_length || cap_size > count)
593 return TPM_LIB_ERROR;
594 if (unpack_byte_string(response, response_length, "s",
595 cap_offset, cap, cap_size))
596 return TPM_LIB_ERROR;
601 u32 tpm_get_permanent_flags(struct tpm_permanent_flags *pflags)
603 const u8 command[22] = {
604 0x0, 0xc1, /* TPM_TAG */
605 0x0, 0x0, 0x0, 0x16, /* parameter size */
606 0x0, 0x0, 0x0, 0x65, /* TPM_COMMAND_CODE */
607 0x0, 0x0, 0x0, 0x4, /* TPM_CAP_FLAG_PERM */
608 0x0, 0x0, 0x0, 0x4, /* subcap size */
609 0x0, 0x0, 0x1, 0x8, /* subcap value */
611 const size_t data_size_offset = TPM_HEADER_SIZE;
612 const size_t data_offset = TPM_HEADER_SIZE + sizeof(u32);
613 u8 response[COMMAND_BUFFER_SIZE];
614 size_t response_length = sizeof(response);
618 err = tpm_sendrecv_command(command, response, &response_length);
621 if (unpack_byte_string(response, response_length, "d",
622 data_size_offset, &data_size))
623 return TPM_LIB_ERROR;
624 if (data_size < sizeof(*pflags))
625 return TPM_LIB_ERROR;
626 if (unpack_byte_string(response, response_length, "s",
627 data_offset, pflags, sizeof(*pflags)))
628 return TPM_LIB_ERROR;
633 u32 tpm_get_permissions(u32 index, u32 *perm)
635 const u8 command[22] = {
636 0x0, 0xc1, /* TPM_TAG */
637 0x0, 0x0, 0x0, 0x16, /* parameter size */
638 0x0, 0x0, 0x0, 0x65, /* TPM_COMMAND_CODE */
642 const size_t index_offset = 18;
643 const size_t perm_offset = 60;
644 u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
645 size_t response_length = sizeof(response);
648 if (pack_byte_string(buf, sizeof(buf), "d", 0, command, sizeof(command),
649 index_offset, index))
650 return TPM_LIB_ERROR;
651 err = tpm_sendrecv_command(buf, response, &response_length);
654 if (unpack_byte_string(response, response_length, "d",
656 return TPM_LIB_ERROR;
661 #ifdef CONFIG_TPM_FLUSH_RESOURCES
662 u32 tpm_flush_specific(u32 key_handle, u32 resource_type)
664 const u8 command[18] = {
665 0x00, 0xc1, /* TPM_TAG */
666 0x00, 0x00, 0x00, 0x12, /* parameter size */
667 0x00, 0x00, 0x00, 0xba, /* TPM_COMMAND_CODE */
668 0x00, 0x00, 0x00, 0x00, /* key handle */
669 0x00, 0x00, 0x00, 0x00, /* resource type */
671 const size_t key_handle_offset = 10;
672 const size_t resource_type_offset = 14;
673 u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
674 size_t response_length = sizeof(response);
677 if (pack_byte_string(buf, sizeof(buf), "sdd",
678 0, command, sizeof(command),
679 key_handle_offset, key_handle,
680 resource_type_offset, resource_type))
681 return TPM_LIB_ERROR;
683 err = tpm_sendrecv_command(buf, response, &response_length);
688 #endif /* CONFIG_TPM_FLUSH_RESOURCES */
690 #ifdef CONFIG_TPM_AUTH_SESSIONS
693 * Fill an authentication block in a request.
694 * This func can create the first as well as the second auth block (for
695 * double authorized commands).
697 * @param request pointer to the request (w/ uninitialised auth data)
698 * @param request_len0 length of the request without auth data
699 * @param handles_len length of the handles area in request
700 * @param auth_session pointer to the (valid) auth session to be used
701 * @param request_auth pointer to the auth block of the request to be filled
702 * @param auth authentication data (HMAC key)
704 static u32 create_request_auth(const void *request, size_t request_len0,
706 struct session_data *auth_session,
707 void *request_auth, const void *auth)
709 u8 hmac_data[DIGEST_LENGTH * 3 + 1];
710 sha1_context hash_ctx;
711 const size_t command_code_offset = 6;
712 const size_t auth_nonce_odd_offset = 4;
713 const size_t auth_continue_offset = 24;
714 const size_t auth_auth_offset = 25;
716 if (!auth_session || !auth_session->valid)
717 return TPM_LIB_ERROR;
719 sha1_starts(&hash_ctx);
720 sha1_update(&hash_ctx, request + command_code_offset, 4);
721 if (request_len0 > TPM_REQUEST_HEADER_LENGTH + handles_len)
722 sha1_update(&hash_ctx,
723 request + TPM_REQUEST_HEADER_LENGTH + handles_len,
724 request_len0 - TPM_REQUEST_HEADER_LENGTH
726 sha1_finish(&hash_ctx, hmac_data);
728 sha1_starts(&hash_ctx);
729 sha1_update(&hash_ctx, auth_session->nonce_odd, DIGEST_LENGTH);
730 sha1_update(&hash_ctx, hmac_data, sizeof(hmac_data));
731 sha1_finish(&hash_ctx, auth_session->nonce_odd);
733 if (pack_byte_string(request_auth, TPM_REQUEST_AUTH_LENGTH, "dsb",
734 0, auth_session->handle,
735 auth_nonce_odd_offset, auth_session->nonce_odd,
737 auth_continue_offset, 1))
738 return TPM_LIB_ERROR;
739 if (pack_byte_string(hmac_data, sizeof(hmac_data), "ss",
741 auth_session->nonce_even,
744 request_auth + auth_nonce_odd_offset,
746 return TPM_LIB_ERROR;
747 sha1_hmac(auth, DIGEST_LENGTH, hmac_data, sizeof(hmac_data),
748 request_auth + auth_auth_offset);
754 * Verify an authentication block in a response.
755 * Since this func updates the nonce_even in the session data it has to be
756 * called when receiving a succesfull AUTH response.
757 * This func can verify the first as well as the second auth block (for
758 * double authorized commands).
760 * @param command_code command code of the request
761 * @param response pointer to the request (w/ uninitialised auth data)
762 * @param handles_len length of the handles area in response
763 * @param auth_session pointer to the (valid) auth session to be used
764 * @param response_auth pointer to the auth block of the response to be verified
765 * @param auth authentication data (HMAC key)
767 static u32 verify_response_auth(u32 command_code, const void *response,
768 size_t response_len0, size_t handles_len,
769 struct session_data *auth_session,
770 const void *response_auth, const void *auth)
772 u8 hmac_data[DIGEST_LENGTH * 3 + 1];
773 u8 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;
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 = ((u8 *)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,
821 u32 tpm_terminate_auth_session(u32 auth_handle)
823 const u8 command[18] = {
824 0x00, 0xc1, /* TPM_TAG */
825 0x00, 0x00, 0x00, 0x00, /* parameter size */
826 0x00, 0x00, 0x00, 0xba, /* TPM_COMMAND_CODE */
827 0x00, 0x00, 0x00, 0x00, /* TPM_HANDLE */
828 0x00, 0x00, 0x00, 0x02, /* TPM_RESOURCE_TYPE */
830 const size_t req_handle_offset = TPM_REQUEST_HEADER_LENGTH;
831 u8 request[COMMAND_BUFFER_SIZE];
833 if (pack_byte_string(request, sizeof(request), "sd",
834 0, command, sizeof(command),
835 req_handle_offset, auth_handle))
836 return TPM_LIB_ERROR;
837 if (oiap_session.valid && oiap_session.handle == auth_handle)
838 oiap_session.valid = 0;
840 return tpm_sendrecv_command(request, NULL, NULL);
843 u32 tpm_end_oiap(void)
845 u32 err = TPM_SUCCESS;
846 if (oiap_session.valid)
847 err = tpm_terminate_auth_session(oiap_session.handle);
851 u32 tpm_oiap(u32 *auth_handle)
853 const u8 command[10] = {
854 0x00, 0xc1, /* TPM_TAG */
855 0x00, 0x00, 0x00, 0x0a, /* parameter size */
856 0x00, 0x00, 0x00, 0x0a, /* TPM_COMMAND_CODE */
858 const size_t res_auth_handle_offset = TPM_RESPONSE_HEADER_LENGTH;
859 const size_t res_nonce_even_offset = TPM_RESPONSE_HEADER_LENGTH + 4;
860 u8 response[COMMAND_BUFFER_SIZE];
861 size_t response_length = sizeof(response);
864 if (oiap_session.valid)
865 tpm_terminate_auth_session(oiap_session.handle);
867 err = tpm_sendrecv_command(command, response, &response_length);
870 if (unpack_byte_string(response, response_length, "ds",
871 res_auth_handle_offset, &oiap_session.handle,
872 res_nonce_even_offset, &oiap_session.nonce_even,
874 return TPM_LIB_ERROR;
875 oiap_session.valid = 1;
877 *auth_handle = oiap_session.handle;
881 u32 tpm_load_key2_oiap(u32 parent_handle, const void *key, size_t key_length,
882 const void *parent_key_usage_auth, u32 *key_handle)
884 const u8 command[14] = {
885 0x00, 0xc2, /* TPM_TAG */
886 0x00, 0x00, 0x00, 0x00, /* parameter size */
887 0x00, 0x00, 0x00, 0x41, /* TPM_COMMAND_CODE */
888 0x00, 0x00, 0x00, 0x00, /* parent handle */
890 const size_t req_size_offset = 2;
891 const size_t req_parent_handle_offset = TPM_REQUEST_HEADER_LENGTH;
892 const size_t req_key_offset = TPM_REQUEST_HEADER_LENGTH + 4;
893 const size_t res_handle_offset = TPM_RESPONSE_HEADER_LENGTH;
894 u8 request[sizeof(command) + TPM_KEY12_MAX_LENGTH +
895 TPM_REQUEST_AUTH_LENGTH];
896 u8 response[COMMAND_BUFFER_SIZE];
897 size_t response_length = sizeof(response);
900 if (!oiap_session.valid) {
901 err = tpm_oiap(NULL);
905 if (pack_byte_string(request, sizeof(request), "sdds",
906 0, command, sizeof(command),
908 sizeof(command) + key_length
909 + TPM_REQUEST_AUTH_LENGTH,
910 req_parent_handle_offset, parent_handle,
911 req_key_offset, key, key_length
913 return TPM_LIB_ERROR;
915 err = create_request_auth(request, sizeof(command) + key_length, 4,
917 request + sizeof(command) + key_length,
918 parent_key_usage_auth);
921 err = tpm_sendrecv_command(request, response, &response_length);
923 if (err == TPM_AUTHFAIL)
924 oiap_session.valid = 0;
928 err = verify_response_auth(0x00000041, response,
929 response_length - TPM_RESPONSE_AUTH_LENGTH,
931 response + response_length -
932 TPM_RESPONSE_AUTH_LENGTH,
933 parent_key_usage_auth);
938 if (unpack_byte_string(response, response_length, "d",
939 res_handle_offset, key_handle))
940 return TPM_LIB_ERROR;
946 u32 tpm_get_pub_key_oiap(u32 key_handle, const void *usage_auth, void *pubkey,
949 const u8 command[14] = {
950 0x00, 0xc2, /* TPM_TAG */
951 0x00, 0x00, 0x00, 0x00, /* parameter size */
952 0x00, 0x00, 0x00, 0x21, /* TPM_COMMAND_CODE */
953 0x00, 0x00, 0x00, 0x00, /* key handle */
955 const size_t req_size_offset = 2;
956 const size_t req_key_handle_offset = TPM_REQUEST_HEADER_LENGTH;
957 const size_t res_pubkey_offset = TPM_RESPONSE_HEADER_LENGTH;
958 u8 request[sizeof(command) + TPM_REQUEST_AUTH_LENGTH];
959 u8 response[TPM_RESPONSE_HEADER_LENGTH + TPM_PUBKEY_MAX_LENGTH +
960 TPM_RESPONSE_AUTH_LENGTH];
961 size_t response_length = sizeof(response);
964 if (!oiap_session.valid) {
965 err = tpm_oiap(NULL);
969 if (pack_byte_string(request, sizeof(request), "sdd",
970 0, command, sizeof(command),
972 (u32)(sizeof(command)
973 + TPM_REQUEST_AUTH_LENGTH),
974 req_key_handle_offset, key_handle
976 return TPM_LIB_ERROR;
977 err = create_request_auth(request, sizeof(command), 4, &oiap_session,
978 request + sizeof(command), usage_auth);
981 err = tpm_sendrecv_command(request, response, &response_length);
983 if (err == TPM_AUTHFAIL)
984 oiap_session.valid = 0;
987 err = verify_response_auth(0x00000021, response,
988 response_length - TPM_RESPONSE_AUTH_LENGTH,
990 response + response_length -
991 TPM_RESPONSE_AUTH_LENGTH,
997 if ((response_length - TPM_RESPONSE_HEADER_LENGTH
998 - TPM_RESPONSE_AUTH_LENGTH) > *pubkey_len)
999 return TPM_LIB_ERROR;
1000 *pubkey_len = response_length - TPM_RESPONSE_HEADER_LENGTH
1001 - TPM_RESPONSE_AUTH_LENGTH;
1002 memcpy(pubkey, response + res_pubkey_offset,
1003 response_length - TPM_RESPONSE_HEADER_LENGTH
1004 - TPM_RESPONSE_AUTH_LENGTH);
1010 #ifdef CONFIG_TPM_LOAD_KEY_BY_SHA1
1011 u32 tpm_find_key_sha1(const u8 auth[20], const u8 pubkey_digest[20],
1015 u32 key_handles[10];
1023 /* fetch list of already loaded keys in the TPM */
1024 err = tpm_get_capability(TPM_CAP_HANDLE, TPM_RT_KEY, buf, sizeof(buf));
1027 key_count = get_unaligned_be16(buf);
1029 for (i = 0; i < key_count; ++i, ptr += 4)
1030 key_handles[i] = get_unaligned_be32(ptr);
1032 /* now search a(/ the) key which we can access with the given auth */
1033 for (i = 0; i < key_count; ++i) {
1034 buf_len = sizeof(buf);
1035 err = tpm_get_pub_key_oiap(key_handles[i], auth, buf, &buf_len);
1036 if (err && err != TPM_AUTHFAIL)
1040 sha1_csum(buf, buf_len, digest);
1041 if (!memcmp(digest, pubkey_digest, 20)) {
1042 *handle = key_handles[i];
1048 #endif /* CONFIG_TPM_LOAD_KEY_BY_SHA1 */
1050 #endif /* CONFIG_TPM_AUTH_SESSIONS */
1052 u32 tpm_get_random(void *data, u32 count)
1054 const u8 command[14] = {
1055 0x0, 0xc1, /* TPM_TAG */
1056 0x0, 0x0, 0x0, 0xe, /* parameter size */
1057 0x0, 0x0, 0x0, 0x46, /* TPM_COMMAND_CODE */
1059 const size_t length_offset = 10;
1060 const size_t data_size_offset = 10;
1061 const size_t data_offset = 14;
1062 u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
1063 size_t response_length = sizeof(response);
1068 u32 this_bytes = min((size_t)count,
1069 sizeof(response) - data_offset);
1072 if (pack_byte_string(buf, sizeof(buf), "sd",
1073 0, command, sizeof(command),
1074 length_offset, this_bytes))
1075 return TPM_LIB_ERROR;
1076 err = tpm_sendrecv_command(buf, response, &response_length);
1079 if (unpack_byte_string(response, response_length, "d",
1080 data_size_offset, &data_size))
1081 return TPM_LIB_ERROR;
1082 if (data_size > count)
1083 return TPM_LIB_ERROR;
1084 if (unpack_byte_string(response, response_length, "s",
1085 data_offset, out, data_size))
1086 return TPM_LIB_ERROR;