2 * Copyright (c) 2013 The Chromium OS Authors.
3 * Coypright (c) 2013 Guntermann & Drunck GmbH
5 * SPDX-License-Identifier: GPL-2.0+
12 #include <asm/unaligned.h>
13 #include <u-boot/sha1.h>
15 /* Internal error of TPM command library */
16 #define TPM_LIB_ERROR ((uint32_t)~0u)
18 /* Useful constants */
20 COMMAND_BUFFER_SIZE = 256,
21 TPM_REQUEST_HEADER_LENGTH = 10,
22 TPM_RESPONSE_HEADER_LENGTH = 10,
23 PCR_DIGEST_LENGTH = 20,
25 TPM_REQUEST_AUTH_LENGTH = 45,
26 TPM_RESPONSE_AUTH_LENGTH = 41,
27 /* some max lengths, valid for RSA keys <= 2048 bits */
28 TPM_KEY12_MAX_LENGTH = 618,
29 TPM_PUBKEY_MAX_LENGTH = 288,
32 #ifdef CONFIG_TPM_AUTH_SESSIONS
35 #error "TPM_AUTH_SESSIONS require SHA1 to be configured, too"
36 #endif /* !CONFIG_SHA1 */
41 uint8_t nonce_even[DIGEST_LENGTH];
42 uint8_t nonce_odd[DIGEST_LENGTH];
45 static struct session_data oiap_session = {0, };
47 #endif /* CONFIG_TPM_AUTH_SESSIONS */
50 * Pack data into a byte string. The data types are specified in
51 * the format string: 'b' means unsigned byte, 'w' unsigned word,
52 * 'd' unsigned double word, and 's' byte string. The data are a
53 * series of offsets and values (for type byte string there are also
54 * lengths). The data values are packed into the byte string
55 * sequentially, and so a latter value could over-write a former
58 * @param str output string
59 * @param size size of output string
60 * @param format format string
61 * @param ... data points
62 * @return 0 on success, non-0 on error
64 int pack_byte_string(uint8_t *str, size_t size, const char *format, ...)
67 size_t offset = 0, length = 0;
71 va_start(args, format);
72 for (; *format; format++) {
75 offset = va_arg(args, size_t);
76 value = va_arg(args, int);
80 offset = va_arg(args, size_t);
81 value = va_arg(args, int);
85 offset = va_arg(args, size_t);
86 value = va_arg(args, uint32_t);
90 offset = va_arg(args, size_t);
91 data = va_arg(args, uint8_t *);
92 length = va_arg(args, uint32_t);
95 debug("Couldn't recognize format string\n");
99 if (offset + length > size)
107 put_unaligned_be16(value, str + offset);
110 put_unaligned_be32(value, str + offset);
113 memcpy(str + offset, data, length);
123 * Unpack data from a byte string. The data types are specified in
124 * the format string: 'b' means unsigned byte, 'w' unsigned word,
125 * 'd' unsigned double word, and 's' byte string. The data are a
126 * series of offsets and pointers (for type byte string there are also
129 * @param str output string
130 * @param size size of output string
131 * @param format format string
132 * @param ... data points
133 * @return 0 on success, non-0 on error
135 int unpack_byte_string(const uint8_t *str, size_t size, const char *format, ...)
138 size_t offset = 0, length = 0;
139 uint8_t *ptr8 = NULL;
140 uint16_t *ptr16 = NULL;
141 uint32_t *ptr32 = NULL;
143 va_start(args, format);
144 for (; *format; format++) {
147 offset = va_arg(args, size_t);
148 ptr8 = va_arg(args, uint8_t *);
152 offset = va_arg(args, size_t);
153 ptr16 = va_arg(args, uint16_t *);
157 offset = va_arg(args, size_t);
158 ptr32 = va_arg(args, uint32_t *);
162 offset = va_arg(args, size_t);
163 ptr8 = va_arg(args, uint8_t *);
164 length = va_arg(args, uint32_t);
167 debug("Couldn't recognize format string\n");
171 if (offset + length > size)
179 *ptr16 = get_unaligned_be16(str + offset);
182 *ptr32 = get_unaligned_be32(str + offset);
185 memcpy(ptr8, str + offset, length);
195 * Get TPM command size.
197 * @param command byte string of TPM command
198 * @return command size of the TPM command
200 static uint32_t tpm_command_size(const void *command)
202 const size_t command_size_offset = 2;
203 return get_unaligned_be32(command + command_size_offset);
207 * Get TPM response return code, which is one of TPM_RESULT values.
209 * @param response byte string of TPM response
210 * @return return code of the TPM response
212 static uint32_t tpm_return_code(const void *response)
214 const size_t return_code_offset = 6;
215 return get_unaligned_be32(response + return_code_offset);
219 * Send a TPM command and return response's return code, and optionally
220 * return response to caller.
222 * @param command byte string of TPM command
223 * @param response output buffer for TPM response, or NULL if the
224 * caller does not care about it
225 * @param size_ptr output buffer size (input parameter) and TPM
226 * response length (output parameter); this parameter
228 * @return return code of the TPM response
230 static uint32_t tpm_sendrecv_command(const void *command,
231 void *response, size_t *size_ptr)
233 uint8_t response_buffer[COMMAND_BUFFER_SIZE];
234 size_t response_length;
238 response_length = *size_ptr;
240 response = response_buffer;
241 response_length = sizeof(response_buffer);
247 ret = uclass_first_device(UCLASS_TPM, &dev);
250 err = tpm_xfer(dev, command, tpm_command_size(command),
251 response, &response_length);
253 err = tis_sendrecv(command, tpm_command_size(command),
254 response, &response_length);
257 return TPM_LIB_ERROR;
259 *size_ptr = response_length;
261 return tpm_return_code(response);
271 err = uclass_first_device(UCLASS_TPM, &dev);
274 return tpm_open(dev);
284 uint32_t tpm_startup(enum tpm_startup_type mode)
286 const uint8_t command[12] = {
287 0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0x99, 0x0, 0x0,
289 const size_t mode_offset = 10;
290 uint8_t buf[COMMAND_BUFFER_SIZE];
292 if (pack_byte_string(buf, sizeof(buf), "sw",
293 0, command, sizeof(command),
295 return TPM_LIB_ERROR;
297 return tpm_sendrecv_command(buf, NULL, NULL);
300 uint32_t tpm_self_test_full(void)
302 const uint8_t command[10] = {
303 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x50,
305 return tpm_sendrecv_command(command, NULL, NULL);
308 uint32_t tpm_continue_self_test(void)
310 const uint8_t command[10] = {
311 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x53,
313 return tpm_sendrecv_command(command, NULL, NULL);
316 uint32_t tpm_nv_define_space(uint32_t index, uint32_t perm, uint32_t size)
318 const uint8_t command[101] = {
319 0x0, 0xc1, /* TPM_TAG */
320 0x0, 0x0, 0x0, 0x65, /* parameter size */
321 0x0, 0x0, 0x0, 0xcc, /* TPM_COMMAND_CODE */
322 /* TPM_NV_DATA_PUBLIC->... */
323 0x0, 0x18, /* ...->TPM_STRUCTURE_TAG */
324 0, 0, 0, 0, /* ...->TPM_NV_INDEX */
325 /* TPM_NV_DATA_PUBLIC->TPM_PCR_INFO_SHORT */
329 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
330 /* TPM_NV_DATA_PUBLIC->TPM_PCR_INFO_SHORT */
334 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
335 /* TPM_NV_ATTRIBUTES->... */
336 0x0, 0x17, /* ...->TPM_STRUCTURE_TAG */
337 0, 0, 0, 0, /* ...->attributes */
338 /* End of TPM_NV_ATTRIBUTES */
339 0, /* bReadSTClear */
340 0, /* bWriteSTClear */
341 0, /* bWriteDefine */
342 0, 0, 0, 0, /* size */
344 const size_t index_offset = 12;
345 const size_t perm_offset = 70;
346 const size_t size_offset = 77;
347 uint8_t buf[COMMAND_BUFFER_SIZE];
349 if (pack_byte_string(buf, sizeof(buf), "sddd",
350 0, command, sizeof(command),
354 return TPM_LIB_ERROR;
356 return tpm_sendrecv_command(buf, NULL, NULL);
359 uint32_t tpm_nv_read_value(uint32_t index, void *data, uint32_t count)
361 const uint8_t command[22] = {
362 0x0, 0xc1, 0x0, 0x0, 0x0, 0x16, 0x0, 0x0, 0x0, 0xcf,
364 const size_t index_offset = 10;
365 const size_t length_offset = 18;
366 const size_t data_size_offset = 10;
367 const size_t data_offset = 14;
368 uint8_t buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
369 size_t response_length = sizeof(response);
373 if (pack_byte_string(buf, sizeof(buf), "sdd",
374 0, command, sizeof(command),
376 length_offset, count))
377 return TPM_LIB_ERROR;
378 err = tpm_sendrecv_command(buf, response, &response_length);
381 if (unpack_byte_string(response, response_length, "d",
382 data_size_offset, &data_size))
383 return TPM_LIB_ERROR;
384 if (data_size > count)
385 return TPM_LIB_ERROR;
386 if (unpack_byte_string(response, response_length, "s",
387 data_offset, data, data_size))
388 return TPM_LIB_ERROR;
393 uint32_t tpm_nv_write_value(uint32_t index, const void *data, uint32_t length)
395 const uint8_t command[256] = {
396 0x0, 0xc1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xcd,
398 const size_t command_size_offset = 2;
399 const size_t index_offset = 10;
400 const size_t length_offset = 18;
401 const size_t data_offset = 22;
402 const size_t write_info_size = 12;
403 const uint32_t total_length =
404 TPM_REQUEST_HEADER_LENGTH + write_info_size + length;
405 uint8_t buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
406 size_t response_length = sizeof(response);
409 if (pack_byte_string(buf, sizeof(buf), "sddds",
410 0, command, sizeof(command),
411 command_size_offset, total_length,
413 length_offset, length,
414 data_offset, data, length))
415 return TPM_LIB_ERROR;
416 err = tpm_sendrecv_command(buf, response, &response_length);
423 uint32_t tpm_extend(uint32_t index, const void *in_digest, void *out_digest)
425 const uint8_t command[34] = {
426 0x0, 0xc1, 0x0, 0x0, 0x0, 0x22, 0x0, 0x0, 0x0, 0x14,
428 const size_t index_offset = 10;
429 const size_t in_digest_offset = 14;
430 const size_t out_digest_offset = 10;
431 uint8_t buf[COMMAND_BUFFER_SIZE];
432 uint8_t response[TPM_RESPONSE_HEADER_LENGTH + PCR_DIGEST_LENGTH];
433 size_t response_length = sizeof(response);
436 if (pack_byte_string(buf, sizeof(buf), "sds",
437 0, command, sizeof(command),
439 in_digest_offset, in_digest,
441 return TPM_LIB_ERROR;
442 err = tpm_sendrecv_command(buf, response, &response_length);
446 if (unpack_byte_string(response, response_length, "s",
447 out_digest_offset, out_digest,
449 return TPM_LIB_ERROR;
454 uint32_t tpm_pcr_read(uint32_t index, void *data, size_t count)
456 const uint8_t command[14] = {
457 0x0, 0xc1, 0x0, 0x0, 0x0, 0xe, 0x0, 0x0, 0x0, 0x15,
459 const size_t index_offset = 10;
460 const size_t out_digest_offset = 10;
461 uint8_t buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
462 size_t response_length = sizeof(response);
465 if (count < PCR_DIGEST_LENGTH)
466 return TPM_LIB_ERROR;
468 if (pack_byte_string(buf, sizeof(buf), "sd",
469 0, command, sizeof(command),
470 index_offset, index))
471 return TPM_LIB_ERROR;
472 err = tpm_sendrecv_command(buf, response, &response_length);
475 if (unpack_byte_string(response, response_length, "s",
476 out_digest_offset, data, PCR_DIGEST_LENGTH))
477 return TPM_LIB_ERROR;
482 uint32_t tpm_tsc_physical_presence(uint16_t presence)
484 const uint8_t command[12] = {
485 0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x40, 0x0, 0x0, 0xa, 0x0, 0x0,
487 const size_t presence_offset = 10;
488 uint8_t buf[COMMAND_BUFFER_SIZE];
490 if (pack_byte_string(buf, sizeof(buf), "sw",
491 0, command, sizeof(command),
492 presence_offset, presence))
493 return TPM_LIB_ERROR;
495 return tpm_sendrecv_command(buf, NULL, NULL);
498 uint32_t tpm_read_pubek(void *data, size_t count)
500 const uint8_t command[30] = {
501 0x0, 0xc1, 0x0, 0x0, 0x0, 0x1e, 0x0, 0x0, 0x0, 0x7c,
503 const size_t response_size_offset = 2;
504 const size_t data_offset = 10;
505 const size_t header_and_checksum_size = TPM_RESPONSE_HEADER_LENGTH + 20;
506 uint8_t response[COMMAND_BUFFER_SIZE + TPM_PUBEK_SIZE];
507 size_t response_length = sizeof(response);
511 err = tpm_sendrecv_command(command, response, &response_length);
514 if (unpack_byte_string(response, response_length, "d",
515 response_size_offset, &data_size))
516 return TPM_LIB_ERROR;
517 if (data_size < header_and_checksum_size)
518 return TPM_LIB_ERROR;
519 data_size -= header_and_checksum_size;
520 if (data_size > count)
521 return TPM_LIB_ERROR;
522 if (unpack_byte_string(response, response_length, "s",
523 data_offset, data, data_size))
524 return TPM_LIB_ERROR;
529 uint32_t tpm_force_clear(void)
531 const uint8_t command[10] = {
532 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x5d,
535 return tpm_sendrecv_command(command, NULL, NULL);
538 uint32_t tpm_physical_enable(void)
540 const uint8_t command[10] = {
541 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x6f,
544 return tpm_sendrecv_command(command, NULL, NULL);
547 uint32_t tpm_physical_disable(void)
549 const uint8_t command[10] = {
550 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x70,
553 return tpm_sendrecv_command(command, NULL, NULL);
556 uint32_t tpm_physical_set_deactivated(uint8_t state)
558 const uint8_t command[11] = {
559 0x0, 0xc1, 0x0, 0x0, 0x0, 0xb, 0x0, 0x0, 0x0, 0x72,
561 const size_t state_offset = 10;
562 uint8_t buf[COMMAND_BUFFER_SIZE];
564 if (pack_byte_string(buf, sizeof(buf), "sb",
565 0, command, sizeof(command),
566 state_offset, state))
567 return TPM_LIB_ERROR;
569 return tpm_sendrecv_command(buf, NULL, NULL);
572 uint32_t tpm_get_capability(uint32_t cap_area, uint32_t sub_cap,
573 void *cap, size_t count)
575 const uint8_t command[22] = {
576 0x0, 0xc1, /* TPM_TAG */
577 0x0, 0x0, 0x0, 0x16, /* parameter size */
578 0x0, 0x0, 0x0, 0x65, /* TPM_COMMAND_CODE */
579 0x0, 0x0, 0x0, 0x0, /* TPM_CAPABILITY_AREA */
580 0x0, 0x0, 0x0, 0x4, /* subcap size */
581 0x0, 0x0, 0x0, 0x0, /* subcap value */
583 const size_t cap_area_offset = 10;
584 const size_t sub_cap_offset = 18;
585 const size_t cap_offset = 14;
586 const size_t cap_size_offset = 10;
587 uint8_t buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
588 size_t response_length = sizeof(response);
592 if (pack_byte_string(buf, sizeof(buf), "sdd",
593 0, command, sizeof(command),
594 cap_area_offset, cap_area,
595 sub_cap_offset, sub_cap))
596 return TPM_LIB_ERROR;
597 err = tpm_sendrecv_command(buf, response, &response_length);
600 if (unpack_byte_string(response, response_length, "d",
601 cap_size_offset, &cap_size))
602 return TPM_LIB_ERROR;
603 if (cap_size > response_length || cap_size > count)
604 return TPM_LIB_ERROR;
605 if (unpack_byte_string(response, response_length, "s",
606 cap_offset, cap, cap_size))
607 return TPM_LIB_ERROR;
612 uint32_t tpm_get_permanent_flags(struct tpm_permanent_flags *pflags)
614 const uint8_t command[22] = {
615 0x0, 0xc1, /* TPM_TAG */
616 0x0, 0x0, 0x0, 0x16, /* parameter size */
617 0x0, 0x0, 0x0, 0x65, /* TPM_COMMAND_CODE */
618 0x0, 0x0, 0x0, 0x4, /* TPM_CAP_FLAG_PERM */
619 0x0, 0x0, 0x0, 0x4, /* subcap size */
620 0x0, 0x0, 0x1, 0x8, /* subcap value */
622 uint8_t response[COMMAND_BUFFER_SIZE];
623 size_t response_length = sizeof(response);
626 err = tpm_sendrecv_command(command, response, &response_length);
629 memcpy(pflags, response + TPM_HEADER_SIZE, sizeof(*pflags));
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_AUTH_SESSIONS
665 * Fill an authentication block in a request.
666 * This func can create the first as well as the second auth block (for
667 * double authorized commands).
669 * @param request pointer to the request (w/ uninitialised auth data)
670 * @param request_len0 length of the request without auth data
671 * @param handles_len length of the handles area in request
672 * @param auth_session pointer to the (valid) auth session to be used
673 * @param request_auth pointer to the auth block of the request to be filled
674 * @param auth authentication data (HMAC key)
676 static uint32_t create_request_auth(const void *request, size_t request_len0,
678 struct session_data *auth_session,
679 void *request_auth, const void *auth)
681 uint8_t hmac_data[DIGEST_LENGTH * 3 + 1];
682 sha1_context hash_ctx;
683 const size_t command_code_offset = 6;
684 const size_t auth_nonce_odd_offset = 4;
685 const size_t auth_continue_offset = 24;
686 const size_t auth_auth_offset = 25;
688 if (!auth_session || !auth_session->valid)
689 return TPM_LIB_ERROR;
691 sha1_starts(&hash_ctx);
692 sha1_update(&hash_ctx, request + command_code_offset, 4);
693 if (request_len0 > TPM_REQUEST_HEADER_LENGTH + handles_len)
694 sha1_update(&hash_ctx,
695 request + TPM_REQUEST_HEADER_LENGTH + handles_len,
696 request_len0 - TPM_REQUEST_HEADER_LENGTH
698 sha1_finish(&hash_ctx, hmac_data);
700 sha1_starts(&hash_ctx);
701 sha1_update(&hash_ctx, auth_session->nonce_odd, DIGEST_LENGTH);
702 sha1_update(&hash_ctx, hmac_data, sizeof(hmac_data));
703 sha1_finish(&hash_ctx, auth_session->nonce_odd);
705 if (pack_byte_string(request_auth, TPM_REQUEST_AUTH_LENGTH, "dsb",
706 0, auth_session->handle,
707 auth_nonce_odd_offset, auth_session->nonce_odd,
709 auth_continue_offset, 1))
710 return TPM_LIB_ERROR;
711 if (pack_byte_string(hmac_data, sizeof(hmac_data), "ss",
713 auth_session->nonce_even,
716 request_auth + auth_nonce_odd_offset,
718 return TPM_LIB_ERROR;
719 sha1_hmac(auth, DIGEST_LENGTH, hmac_data, sizeof(hmac_data),
720 request_auth + auth_auth_offset);
726 * Verify an authentication block in a response.
727 * Since this func updates the nonce_even in the session data it has to be
728 * called when receiving a succesfull AUTH response.
729 * This func can verify the first as well as the second auth block (for
730 * double authorized commands).
732 * @param command_code command code of the request
733 * @param response pointer to the request (w/ uninitialised auth data)
734 * @param handles_len length of the handles area in response
735 * @param auth_session pointer to the (valid) auth session to be used
736 * @param response_auth pointer to the auth block of the response to be verified
737 * @param auth authentication data (HMAC key)
739 static uint32_t verify_response_auth(uint32_t command_code,
740 const void *response, size_t response_len0,
742 struct session_data *auth_session,
743 const void *response_auth, const void *auth)
745 uint8_t hmac_data[DIGEST_LENGTH * 3 + 1];
746 uint8_t computed_auth[DIGEST_LENGTH];
747 sha1_context hash_ctx;
748 const size_t return_code_offset = 6;
749 const size_t auth_continue_offset = 20;
750 const size_t auth_auth_offset = 21;
751 uint8_t auth_continue;
753 if (!auth_session || !auth_session->valid)
755 if (pack_byte_string(hmac_data, sizeof(hmac_data), "d",
757 return TPM_LIB_ERROR;
758 if (response_len0 < TPM_RESPONSE_HEADER_LENGTH)
759 return TPM_LIB_ERROR;
761 sha1_starts(&hash_ctx);
762 sha1_update(&hash_ctx, response + return_code_offset, 4);
763 sha1_update(&hash_ctx, hmac_data, 4);
764 if (response_len0 > TPM_RESPONSE_HEADER_LENGTH + handles_len)
765 sha1_update(&hash_ctx,
766 response + TPM_RESPONSE_HEADER_LENGTH + handles_len,
767 response_len0 - TPM_RESPONSE_HEADER_LENGTH
769 sha1_finish(&hash_ctx, hmac_data);
771 memcpy(auth_session->nonce_even, response_auth, DIGEST_LENGTH);
772 auth_continue = ((uint8_t *)response_auth)[auth_continue_offset];
773 if (pack_byte_string(hmac_data, sizeof(hmac_data), "ssb",
778 auth_session->nonce_odd,
782 return TPM_LIB_ERROR;
784 sha1_hmac(auth, DIGEST_LENGTH, hmac_data, sizeof(hmac_data),
787 if (memcmp(computed_auth, response_auth + auth_auth_offset,
795 uint32_t tpm_terminate_auth_session(uint32_t auth_handle)
797 const uint8_t command[18] = {
798 0x00, 0xc1, /* TPM_TAG */
799 0x00, 0x00, 0x00, 0x00, /* parameter size */
800 0x00, 0x00, 0x00, 0xba, /* TPM_COMMAND_CODE */
801 0x00, 0x00, 0x00, 0x00, /* TPM_HANDLE */
802 0x00, 0x00, 0x00, 0x02, /* TPM_RESSOURCE_TYPE */
804 const size_t req_handle_offset = TPM_REQUEST_HEADER_LENGTH;
805 uint8_t request[COMMAND_BUFFER_SIZE];
807 if (pack_byte_string(request, sizeof(request), "sd",
808 0, command, sizeof(command),
809 req_handle_offset, auth_handle))
810 return TPM_LIB_ERROR;
811 if (oiap_session.valid && oiap_session.handle == auth_handle)
812 oiap_session.valid = 0;
814 return tpm_sendrecv_command(request, NULL, NULL);
817 uint32_t tpm_end_oiap(void)
819 uint32_t err = TPM_SUCCESS;
820 if (oiap_session.valid)
821 err = tpm_terminate_auth_session(oiap_session.handle);
825 uint32_t tpm_oiap(uint32_t *auth_handle)
827 const uint8_t command[10] = {
828 0x00, 0xc1, /* TPM_TAG */
829 0x00, 0x00, 0x00, 0x0a, /* parameter size */
830 0x00, 0x00, 0x00, 0x0a, /* TPM_COMMAND_CODE */
832 const size_t res_auth_handle_offset = TPM_RESPONSE_HEADER_LENGTH;
833 const size_t res_nonce_even_offset = TPM_RESPONSE_HEADER_LENGTH + 4;
834 uint8_t response[COMMAND_BUFFER_SIZE];
835 size_t response_length = sizeof(response);
838 if (oiap_session.valid)
839 tpm_terminate_auth_session(oiap_session.handle);
841 err = tpm_sendrecv_command(command, response, &response_length);
844 if (unpack_byte_string(response, response_length, "ds",
845 res_auth_handle_offset, &oiap_session.handle,
846 res_nonce_even_offset, &oiap_session.nonce_even,
847 (uint32_t)DIGEST_LENGTH))
848 return TPM_LIB_ERROR;
849 oiap_session.valid = 1;
851 *auth_handle = oiap_session.handle;
855 uint32_t tpm_load_key2_oiap(uint32_t parent_handle,
856 const void *key, size_t key_length,
857 const void *parent_key_usage_auth,
858 uint32_t *key_handle)
860 const uint8_t command[14] = {
861 0x00, 0xc2, /* TPM_TAG */
862 0x00, 0x00, 0x00, 0x00, /* parameter size */
863 0x00, 0x00, 0x00, 0x41, /* TPM_COMMAND_CODE */
864 0x00, 0x00, 0x00, 0x00, /* parent handle */
866 const size_t req_size_offset = 2;
867 const size_t req_parent_handle_offset = TPM_REQUEST_HEADER_LENGTH;
868 const size_t req_key_offset = TPM_REQUEST_HEADER_LENGTH + 4;
869 const size_t res_handle_offset = TPM_RESPONSE_HEADER_LENGTH;
870 uint8_t request[sizeof(command) + TPM_KEY12_MAX_LENGTH
871 + TPM_REQUEST_AUTH_LENGTH];
872 uint8_t response[COMMAND_BUFFER_SIZE];
873 size_t response_length = sizeof(response);
876 if (!oiap_session.valid) {
877 err = tpm_oiap(NULL);
881 if (pack_byte_string(request, sizeof(request), "sdds",
882 0, command, sizeof(command),
884 sizeof(command) + key_length
885 + TPM_REQUEST_AUTH_LENGTH,
886 req_parent_handle_offset, parent_handle,
887 req_key_offset, key, key_length
889 return TPM_LIB_ERROR;
891 err = create_request_auth(request, sizeof(command) + key_length, 4,
893 request + sizeof(command) + key_length,
894 parent_key_usage_auth);
897 err = tpm_sendrecv_command(request, response, &response_length);
899 if (err == TPM_AUTHFAIL)
900 oiap_session.valid = 0;
904 err = verify_response_auth(0x00000041, response,
905 response_length - TPM_RESPONSE_AUTH_LENGTH,
907 response + response_length - TPM_RESPONSE_AUTH_LENGTH,
908 parent_key_usage_auth);
913 if (unpack_byte_string(response, response_length, "d",
914 res_handle_offset, key_handle))
915 return TPM_LIB_ERROR;
921 uint32_t tpm_get_pub_key_oiap(uint32_t key_handle, const void *usage_auth,
922 void *pubkey, size_t *pubkey_len)
924 const uint8_t command[14] = {
925 0x00, 0xc2, /* TPM_TAG */
926 0x00, 0x00, 0x00, 0x00, /* parameter size */
927 0x00, 0x00, 0x00, 0x21, /* TPM_COMMAND_CODE */
928 0x00, 0x00, 0x00, 0x00, /* key handle */
930 const size_t req_size_offset = 2;
931 const size_t req_key_handle_offset = TPM_REQUEST_HEADER_LENGTH;
932 const size_t res_pubkey_offset = TPM_RESPONSE_HEADER_LENGTH;
933 uint8_t request[sizeof(command) + TPM_REQUEST_AUTH_LENGTH];
934 uint8_t response[TPM_RESPONSE_HEADER_LENGTH + TPM_PUBKEY_MAX_LENGTH
935 + TPM_RESPONSE_AUTH_LENGTH];
936 size_t response_length = sizeof(response);
939 if (!oiap_session.valid) {
940 err = tpm_oiap(NULL);
944 if (pack_byte_string(request, sizeof(request), "sdd",
945 0, command, sizeof(command),
947 (uint32_t)(sizeof(command)
948 + TPM_REQUEST_AUTH_LENGTH),
949 req_key_handle_offset, key_handle
951 return TPM_LIB_ERROR;
952 err = create_request_auth(request, sizeof(command), 4, &oiap_session,
953 request + sizeof(command), usage_auth);
956 err = tpm_sendrecv_command(request, response, &response_length);
958 if (err == TPM_AUTHFAIL)
959 oiap_session.valid = 0;
962 err = verify_response_auth(0x00000021, response,
963 response_length - TPM_RESPONSE_AUTH_LENGTH,
965 response + response_length - TPM_RESPONSE_AUTH_LENGTH,
971 if ((response_length - TPM_RESPONSE_HEADER_LENGTH
972 - TPM_RESPONSE_AUTH_LENGTH) > *pubkey_len)
973 return TPM_LIB_ERROR;
974 *pubkey_len = response_length - TPM_RESPONSE_HEADER_LENGTH
975 - TPM_RESPONSE_AUTH_LENGTH;
976 memcpy(pubkey, response + res_pubkey_offset,
977 response_length - TPM_RESPONSE_HEADER_LENGTH
978 - TPM_RESPONSE_AUTH_LENGTH);
984 #endif /* CONFIG_TPM_AUTH_SESSIONS */