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 ((uint32_t)~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 uint8_t nonce_even[DIGEST_LENGTH];
40 uint8_t 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(uint8_t *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, uint32_t);
88 offset = va_arg(args, size_t);
89 data = va_arg(args, uint8_t *);
90 length = va_arg(args, uint32_t);
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 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) {
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 uint32_t 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 uint32_t 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 uint32_t tpm_sendrecv_command(const void *command,
235 void *response, size_t *size_ptr)
239 uint8_t 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 uint32_t tpm_startup(enum tpm_startup_type mode)
276 const uint8_t command[12] = {
277 0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0x99, 0x0, 0x0,
279 const size_t mode_offset = 10;
280 uint8_t 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 uint32_t tpm_self_test_full(void)
292 const uint8_t command[10] = {
293 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x50,
295 return tpm_sendrecv_command(command, NULL, NULL);
298 uint32_t tpm_continue_self_test(void)
300 const uint8_t command[10] = {
301 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x53,
303 return tpm_sendrecv_command(command, NULL, NULL);
306 uint32_t tpm_nv_define_space(uint32_t index, uint32_t perm, uint32_t size)
308 const uint8_t 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 uint8_t 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 uint32_t tpm_nv_read_value(uint32_t index, void *data, uint32_t count)
351 const uint8_t 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 uint8_t 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 uint32_t tpm_nv_write_value(uint32_t index, const void *data, uint32_t length)
385 const uint8_t 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 uint32_t total_length =
394 TPM_REQUEST_HEADER_LENGTH + write_info_size + length;
395 uint8_t 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 uint32_t tpm_extend(uint32_t index, const void *in_digest, void *out_digest)
415 const uint8_t 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 uint8_t buf[COMMAND_BUFFER_SIZE];
422 uint8_t 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 uint32_t tpm_pcr_read(uint32_t index, void *data, size_t count)
446 const uint8_t 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 uint8_t 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 uint32_t tpm_tsc_physical_presence(uint16_t presence)
474 const uint8_t command[12] = {
475 0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x40, 0x0, 0x0, 0xa, 0x0, 0x0,
477 const size_t presence_offset = 10;
478 uint8_t 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 uint32_t tpm_read_pubek(void *data, size_t count)
490 const uint8_t 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 uint8_t 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 uint32_t tpm_force_clear(void)
521 const uint8_t command[10] = {
522 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x5d,
525 return tpm_sendrecv_command(command, NULL, NULL);
528 uint32_t tpm_physical_enable(void)
530 const uint8_t command[10] = {
531 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x6f,
534 return tpm_sendrecv_command(command, NULL, NULL);
537 uint32_t tpm_physical_disable(void)
539 const uint8_t command[10] = {
540 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x70,
543 return tpm_sendrecv_command(command, NULL, NULL);
546 uint32_t tpm_physical_set_deactivated(uint8_t state)
548 const uint8_t command[11] = {
549 0x0, 0xc1, 0x0, 0x0, 0x0, 0xb, 0x0, 0x0, 0x0, 0x72,
551 const size_t state_offset = 10;
552 uint8_t 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 uint32_t tpm_get_capability(uint32_t cap_area, uint32_t sub_cap,
563 void *cap, size_t count)
565 const uint8_t command[22] = {
566 0x0, 0xc1, /* TPM_TAG */
567 0x0, 0x0, 0x0, 0x16, /* parameter size */
568 0x0, 0x0, 0x0, 0x65, /* TPM_COMMAND_CODE */
569 0x0, 0x0, 0x0, 0x0, /* TPM_CAPABILITY_AREA */
570 0x0, 0x0, 0x0, 0x4, /* subcap size */
571 0x0, 0x0, 0x0, 0x0, /* subcap value */
573 const size_t cap_area_offset = 10;
574 const size_t sub_cap_offset = 18;
575 const size_t cap_offset = 14;
576 const size_t cap_size_offset = 10;
577 uint8_t buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
578 size_t response_length = sizeof(response);
582 if (pack_byte_string(buf, sizeof(buf), "sdd",
583 0, command, sizeof(command),
584 cap_area_offset, cap_area,
585 sub_cap_offset, sub_cap))
586 return TPM_LIB_ERROR;
587 err = tpm_sendrecv_command(buf, response, &response_length);
590 if (unpack_byte_string(response, response_length, "d",
591 cap_size_offset, &cap_size))
592 return TPM_LIB_ERROR;
593 if (cap_size > response_length || cap_size > count)
594 return TPM_LIB_ERROR;
595 if (unpack_byte_string(response, response_length, "s",
596 cap_offset, cap, cap_size))
597 return TPM_LIB_ERROR;
602 uint32_t tpm_get_permanent_flags(struct tpm_permanent_flags *pflags)
604 const uint8_t command[22] = {
605 0x0, 0xc1, /* TPM_TAG */
606 0x0, 0x0, 0x0, 0x16, /* parameter size */
607 0x0, 0x0, 0x0, 0x65, /* TPM_COMMAND_CODE */
608 0x0, 0x0, 0x0, 0x4, /* TPM_CAP_FLAG_PERM */
609 0x0, 0x0, 0x0, 0x4, /* subcap size */
610 0x0, 0x0, 0x1, 0x8, /* subcap value */
612 const size_t data_size_offset = TPM_HEADER_SIZE;
613 const size_t data_offset = TPM_HEADER_SIZE + sizeof (uint32_t);
614 uint8_t response[COMMAND_BUFFER_SIZE];
615 size_t response_length = sizeof(response);
619 err = tpm_sendrecv_command(command, response, &response_length);
622 if (unpack_byte_string(response, response_length, "d",
623 data_size_offset, &data_size))
624 return TPM_LIB_ERROR;
625 if (data_size < sizeof(*pflags))
626 return TPM_LIB_ERROR;
627 if (unpack_byte_string(response, response_length, "s",
628 data_offset, pflags, sizeof(*pflags)))
629 return TPM_LIB_ERROR;
634 uint32_t tpm_get_permissions(uint32_t index, uint32_t *perm)
636 const uint8_t command[22] = {
637 0x0, 0xc1, /* TPM_TAG */
638 0x0, 0x0, 0x0, 0x16, /* parameter size */
639 0x0, 0x0, 0x0, 0x65, /* TPM_COMMAND_CODE */
643 const size_t index_offset = 18;
644 const size_t perm_offset = 60;
645 uint8_t buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
646 size_t response_length = sizeof(response);
649 if (pack_byte_string(buf, sizeof(buf), "d", 0, command, sizeof(command),
650 index_offset, index))
651 return TPM_LIB_ERROR;
652 err = tpm_sendrecv_command(buf, response, &response_length);
655 if (unpack_byte_string(response, response_length, "d",
657 return TPM_LIB_ERROR;
662 #ifdef CONFIG_TPM_FLUSH_RESOURCES
663 uint32_t tpm_flush_specific(uint32_t key_handle, uint32_t resource_type)
665 const uint8_t command[18] = {
666 0x00, 0xc1, /* TPM_TAG */
667 0x00, 0x00, 0x00, 0x12, /* parameter size */
668 0x00, 0x00, 0x00, 0xba, /* TPM_COMMAND_CODE */
669 0x00, 0x00, 0x00, 0x00, /* key handle */
670 0x00, 0x00, 0x00, 0x00, /* resource type */
672 const size_t key_handle_offset = 10;
673 const size_t resource_type_offset = 14;
674 uint8_t buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
675 size_t response_length = sizeof(response);
678 if (pack_byte_string(buf, sizeof(buf), "sdd",
679 0, command, sizeof(command),
680 key_handle_offset, key_handle,
681 resource_type_offset, resource_type))
682 return TPM_LIB_ERROR;
684 err = tpm_sendrecv_command(buf, response, &response_length);
689 #endif /* CONFIG_TPM_FLUSH_RESOURCES */
691 #ifdef CONFIG_TPM_AUTH_SESSIONS
694 * Fill an authentication block in a request.
695 * This func can create the first as well as the second auth block (for
696 * double authorized commands).
698 * @param request pointer to the request (w/ uninitialised auth data)
699 * @param request_len0 length of the request without auth data
700 * @param handles_len length of the handles area in request
701 * @param auth_session pointer to the (valid) auth session to be used
702 * @param request_auth pointer to the auth block of the request to be filled
703 * @param auth authentication data (HMAC key)
705 static uint32_t create_request_auth(const void *request, size_t request_len0,
707 struct session_data *auth_session,
708 void *request_auth, const void *auth)
710 uint8_t hmac_data[DIGEST_LENGTH * 3 + 1];
711 sha1_context hash_ctx;
712 const size_t command_code_offset = 6;
713 const size_t auth_nonce_odd_offset = 4;
714 const size_t auth_continue_offset = 24;
715 const size_t auth_auth_offset = 25;
717 if (!auth_session || !auth_session->valid)
718 return TPM_LIB_ERROR;
720 sha1_starts(&hash_ctx);
721 sha1_update(&hash_ctx, request + command_code_offset, 4);
722 if (request_len0 > TPM_REQUEST_HEADER_LENGTH + handles_len)
723 sha1_update(&hash_ctx,
724 request + TPM_REQUEST_HEADER_LENGTH + handles_len,
725 request_len0 - TPM_REQUEST_HEADER_LENGTH
727 sha1_finish(&hash_ctx, hmac_data);
729 sha1_starts(&hash_ctx);
730 sha1_update(&hash_ctx, auth_session->nonce_odd, DIGEST_LENGTH);
731 sha1_update(&hash_ctx, hmac_data, sizeof(hmac_data));
732 sha1_finish(&hash_ctx, auth_session->nonce_odd);
734 if (pack_byte_string(request_auth, TPM_REQUEST_AUTH_LENGTH, "dsb",
735 0, auth_session->handle,
736 auth_nonce_odd_offset, auth_session->nonce_odd,
738 auth_continue_offset, 1))
739 return TPM_LIB_ERROR;
740 if (pack_byte_string(hmac_data, sizeof(hmac_data), "ss",
742 auth_session->nonce_even,
745 request_auth + auth_nonce_odd_offset,
747 return TPM_LIB_ERROR;
748 sha1_hmac(auth, DIGEST_LENGTH, hmac_data, sizeof(hmac_data),
749 request_auth + auth_auth_offset);
755 * Verify an authentication block in a response.
756 * Since this func updates the nonce_even in the session data it has to be
757 * called when receiving a succesfull AUTH response.
758 * This func can verify the first as well as the second auth block (for
759 * double authorized commands).
761 * @param command_code command code of the request
762 * @param response pointer to the request (w/ uninitialised auth data)
763 * @param handles_len length of the handles area in response
764 * @param auth_session pointer to the (valid) auth session to be used
765 * @param response_auth pointer to the auth block of the response to be verified
766 * @param auth authentication data (HMAC key)
768 static uint32_t verify_response_auth(uint32_t command_code,
769 const void *response, size_t response_len0,
771 struct session_data *auth_session,
772 const void *response_auth, const void *auth)
774 uint8_t hmac_data[DIGEST_LENGTH * 3 + 1];
775 uint8_t computed_auth[DIGEST_LENGTH];
776 sha1_context hash_ctx;
777 const size_t return_code_offset = 6;
778 const size_t auth_continue_offset = 20;
779 const size_t auth_auth_offset = 21;
780 uint8_t auth_continue;
782 if (!auth_session || !auth_session->valid)
784 if (pack_byte_string(hmac_data, sizeof(hmac_data), "d",
786 return TPM_LIB_ERROR;
787 if (response_len0 < TPM_RESPONSE_HEADER_LENGTH)
788 return TPM_LIB_ERROR;
790 sha1_starts(&hash_ctx);
791 sha1_update(&hash_ctx, response + return_code_offset, 4);
792 sha1_update(&hash_ctx, hmac_data, 4);
793 if (response_len0 > TPM_RESPONSE_HEADER_LENGTH + handles_len)
794 sha1_update(&hash_ctx,
795 response + TPM_RESPONSE_HEADER_LENGTH + handles_len,
796 response_len0 - TPM_RESPONSE_HEADER_LENGTH
798 sha1_finish(&hash_ctx, hmac_data);
800 memcpy(auth_session->nonce_even, response_auth, DIGEST_LENGTH);
801 auth_continue = ((uint8_t *)response_auth)[auth_continue_offset];
802 if (pack_byte_string(hmac_data, sizeof(hmac_data), "ssb",
807 auth_session->nonce_odd,
811 return TPM_LIB_ERROR;
813 sha1_hmac(auth, DIGEST_LENGTH, hmac_data, sizeof(hmac_data),
816 if (memcmp(computed_auth, response_auth + auth_auth_offset,
824 uint32_t tpm_terminate_auth_session(uint32_t auth_handle)
826 const uint8_t command[18] = {
827 0x00, 0xc1, /* TPM_TAG */
828 0x00, 0x00, 0x00, 0x00, /* parameter size */
829 0x00, 0x00, 0x00, 0xba, /* TPM_COMMAND_CODE */
830 0x00, 0x00, 0x00, 0x00, /* TPM_HANDLE */
831 0x00, 0x00, 0x00, 0x02, /* TPM_RESSOURCE_TYPE */
833 const size_t req_handle_offset = TPM_REQUEST_HEADER_LENGTH;
834 uint8_t request[COMMAND_BUFFER_SIZE];
836 if (pack_byte_string(request, sizeof(request), "sd",
837 0, command, sizeof(command),
838 req_handle_offset, auth_handle))
839 return TPM_LIB_ERROR;
840 if (oiap_session.valid && oiap_session.handle == auth_handle)
841 oiap_session.valid = 0;
843 return tpm_sendrecv_command(request, NULL, NULL);
846 uint32_t tpm_end_oiap(void)
848 uint32_t err = TPM_SUCCESS;
849 if (oiap_session.valid)
850 err = tpm_terminate_auth_session(oiap_session.handle);
854 uint32_t tpm_oiap(uint32_t *auth_handle)
856 const uint8_t command[10] = {
857 0x00, 0xc1, /* TPM_TAG */
858 0x00, 0x00, 0x00, 0x0a, /* parameter size */
859 0x00, 0x00, 0x00, 0x0a, /* TPM_COMMAND_CODE */
861 const size_t res_auth_handle_offset = TPM_RESPONSE_HEADER_LENGTH;
862 const size_t res_nonce_even_offset = TPM_RESPONSE_HEADER_LENGTH + 4;
863 uint8_t response[COMMAND_BUFFER_SIZE];
864 size_t response_length = sizeof(response);
867 if (oiap_session.valid)
868 tpm_terminate_auth_session(oiap_session.handle);
870 err = tpm_sendrecv_command(command, response, &response_length);
873 if (unpack_byte_string(response, response_length, "ds",
874 res_auth_handle_offset, &oiap_session.handle,
875 res_nonce_even_offset, &oiap_session.nonce_even,
876 (uint32_t)DIGEST_LENGTH))
877 return TPM_LIB_ERROR;
878 oiap_session.valid = 1;
880 *auth_handle = oiap_session.handle;
884 uint32_t tpm_load_key2_oiap(uint32_t parent_handle,
885 const void *key, size_t key_length,
886 const void *parent_key_usage_auth,
887 uint32_t *key_handle)
889 const uint8_t command[14] = {
890 0x00, 0xc2, /* TPM_TAG */
891 0x00, 0x00, 0x00, 0x00, /* parameter size */
892 0x00, 0x00, 0x00, 0x41, /* TPM_COMMAND_CODE */
893 0x00, 0x00, 0x00, 0x00, /* parent handle */
895 const size_t req_size_offset = 2;
896 const size_t req_parent_handle_offset = TPM_REQUEST_HEADER_LENGTH;
897 const size_t req_key_offset = TPM_REQUEST_HEADER_LENGTH + 4;
898 const size_t res_handle_offset = TPM_RESPONSE_HEADER_LENGTH;
899 uint8_t request[sizeof(command) + TPM_KEY12_MAX_LENGTH
900 + TPM_REQUEST_AUTH_LENGTH];
901 uint8_t response[COMMAND_BUFFER_SIZE];
902 size_t response_length = sizeof(response);
905 if (!oiap_session.valid) {
906 err = tpm_oiap(NULL);
910 if (pack_byte_string(request, sizeof(request), "sdds",
911 0, command, sizeof(command),
913 sizeof(command) + key_length
914 + TPM_REQUEST_AUTH_LENGTH,
915 req_parent_handle_offset, parent_handle,
916 req_key_offset, key, key_length
918 return TPM_LIB_ERROR;
920 err = create_request_auth(request, sizeof(command) + key_length, 4,
922 request + sizeof(command) + key_length,
923 parent_key_usage_auth);
926 err = tpm_sendrecv_command(request, response, &response_length);
928 if (err == TPM_AUTHFAIL)
929 oiap_session.valid = 0;
933 err = verify_response_auth(0x00000041, response,
934 response_length - TPM_RESPONSE_AUTH_LENGTH,
936 response + response_length - TPM_RESPONSE_AUTH_LENGTH,
937 parent_key_usage_auth);
942 if (unpack_byte_string(response, response_length, "d",
943 res_handle_offset, key_handle))
944 return TPM_LIB_ERROR;
950 uint32_t tpm_get_pub_key_oiap(uint32_t key_handle, const void *usage_auth,
951 void *pubkey, size_t *pubkey_len)
953 const uint8_t command[14] = {
954 0x00, 0xc2, /* TPM_TAG */
955 0x00, 0x00, 0x00, 0x00, /* parameter size */
956 0x00, 0x00, 0x00, 0x21, /* TPM_COMMAND_CODE */
957 0x00, 0x00, 0x00, 0x00, /* key handle */
959 const size_t req_size_offset = 2;
960 const size_t req_key_handle_offset = TPM_REQUEST_HEADER_LENGTH;
961 const size_t res_pubkey_offset = TPM_RESPONSE_HEADER_LENGTH;
962 uint8_t request[sizeof(command) + TPM_REQUEST_AUTH_LENGTH];
963 uint8_t response[TPM_RESPONSE_HEADER_LENGTH + TPM_PUBKEY_MAX_LENGTH
964 + TPM_RESPONSE_AUTH_LENGTH];
965 size_t response_length = sizeof(response);
968 if (!oiap_session.valid) {
969 err = tpm_oiap(NULL);
973 if (pack_byte_string(request, sizeof(request), "sdd",
974 0, command, sizeof(command),
976 (uint32_t)(sizeof(command)
977 + TPM_REQUEST_AUTH_LENGTH),
978 req_key_handle_offset, key_handle
980 return TPM_LIB_ERROR;
981 err = create_request_auth(request, sizeof(command), 4, &oiap_session,
982 request + sizeof(command), usage_auth);
985 err = tpm_sendrecv_command(request, response, &response_length);
987 if (err == TPM_AUTHFAIL)
988 oiap_session.valid = 0;
991 err = verify_response_auth(0x00000021, response,
992 response_length - TPM_RESPONSE_AUTH_LENGTH,
994 response + response_length - TPM_RESPONSE_AUTH_LENGTH,
1000 if ((response_length - TPM_RESPONSE_HEADER_LENGTH
1001 - TPM_RESPONSE_AUTH_LENGTH) > *pubkey_len)
1002 return TPM_LIB_ERROR;
1003 *pubkey_len = response_length - TPM_RESPONSE_HEADER_LENGTH
1004 - TPM_RESPONSE_AUTH_LENGTH;
1005 memcpy(pubkey, response + res_pubkey_offset,
1006 response_length - TPM_RESPONSE_HEADER_LENGTH
1007 - TPM_RESPONSE_AUTH_LENGTH);
1013 #ifdef CONFIG_TPM_LOAD_KEY_BY_SHA1
1014 uint32_t tpm_find_key_sha1(const uint8_t auth[20], const uint8_t
1015 pubkey_digest[20], uint32_t *handle)
1018 uint32_t key_handles[10];
1026 /* fetch list of already loaded keys in the TPM */
1027 err = tpm_get_capability(TPM_CAP_HANDLE, TPM_RT_KEY, buf, sizeof(buf));
1030 key_count = get_unaligned_be16(buf);
1032 for (i = 0; i < key_count; ++i, ptr += 4)
1033 key_handles[i] = get_unaligned_be32(ptr);
1035 /* now search a(/ the) key which we can access with the given auth */
1036 for (i = 0; i < key_count; ++i) {
1037 buf_len = sizeof(buf);
1038 err = tpm_get_pub_key_oiap(key_handles[i], auth, buf, &buf_len);
1039 if (err && err != TPM_AUTHFAIL)
1043 sha1_csum(buf, buf_len, digest);
1044 if (!memcmp(digest, pubkey_digest, 20)) {
1045 *handle = key_handles[i];
1051 #endif /* CONFIG_TPM_LOAD_KEY_BY_SHA1 */
1053 #endif /* CONFIG_TPM_AUTH_SESSIONS */
1055 uint32_t tpm_get_random(void *data, uint32_t count)
1057 const uint8_t command[14] = {
1058 0x0, 0xc1, /* TPM_TAG */
1059 0x0, 0x0, 0x0, 0xe, /* parameter size */
1060 0x0, 0x0, 0x0, 0x46, /* TPM_COMMAND_CODE */
1062 const size_t length_offset = 10;
1063 const size_t data_size_offset = 10;
1064 const size_t data_offset = 14;
1065 uint8_t buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
1066 size_t response_length = sizeof(response);
1068 uint8_t *out = data;
1071 uint32_t this_bytes = min((size_t)count,
1072 sizeof (response) - data_offset);
1075 if (pack_byte_string(buf, sizeof(buf), "sd",
1076 0, command, sizeof(command),
1077 length_offset, this_bytes))
1078 return TPM_LIB_ERROR;
1079 err = tpm_sendrecv_command(buf, response, &response_length);
1082 if (unpack_byte_string(response, response_length, "d",
1083 data_size_offset, &data_size))
1084 return TPM_LIB_ERROR;
1085 if (data_size > count)
1086 return TPM_LIB_ERROR;
1087 if (unpack_byte_string(response, response_length, "s",
1088 data_offset, out, data_size))
1089 return TPM_LIB_ERROR;