2 * Copyright (c) 2013 The Chromium OS Authors.
3 * Coypright (c) 2013 Guntermann & Drunck GmbH
5 * See file CREDITS for list of people who contributed to this
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of
11 * the License, or (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
28 #include <asm/unaligned.h>
30 /* Internal error of TPM command library */
31 #define TPM_LIB_ERROR ((uint32_t)~0u)
33 /* Useful constants */
35 COMMAND_BUFFER_SIZE = 256,
37 TPM_REQUEST_HEADER_LENGTH = 10,
38 TPM_RESPONSE_HEADER_LENGTH = 10,
39 PCR_DIGEST_LENGTH = 20,
41 TPM_REQUEST_AUTH_LENGTH = 45,
42 TPM_RESPONSE_AUTH_LENGTH = 41,
43 /* some max lengths, valid for RSA keys <= 2048 bits */
44 TPM_KEY12_MAX_LENGTH = 618,
45 TPM_PUBKEY_MAX_LENGTH = 288,
48 #ifdef CONFIG_TPM_AUTH_SESSIONS
51 #error "TPM_AUTH_SESSIONS require SHA1 to be configured, too"
52 #endif /* !CONFIG_SHA1 */
57 uint8_t nonce_even[DIGEST_LENGTH];
58 uint8_t nonce_odd[DIGEST_LENGTH];
61 static struct session_data oiap_session = {0, };
63 #endif /* CONFIG_TPM_AUTH_SESSIONS */
66 * Pack data into a byte string. The data types are specified in
67 * the format string: 'b' means unsigned byte, 'w' unsigned word,
68 * 'd' unsigned double word, and 's' byte string. The data are a
69 * series of offsets and values (for type byte string there are also
70 * lengths). The data values are packed into the byte string
71 * sequentially, and so a latter value could over-write a former
74 * @param str output string
75 * @param size size of output string
76 * @param format format string
77 * @param ... data points
78 * @return 0 on success, non-0 on error
80 int pack_byte_string(uint8_t *str, size_t size, const char *format, ...)
83 size_t offset = 0, length = 0;
87 va_start(args, format);
88 for (; *format; format++) {
91 offset = va_arg(args, size_t);
92 value = va_arg(args, int);
96 offset = va_arg(args, size_t);
97 value = va_arg(args, int);
101 offset = va_arg(args, size_t);
102 value = va_arg(args, uint32_t);
106 offset = va_arg(args, size_t);
107 data = va_arg(args, uint8_t *);
108 length = va_arg(args, uint32_t);
111 debug("Couldn't recognize format string\n");
115 if (offset + length > size)
123 put_unaligned_be16(value, str + offset);
126 put_unaligned_be32(value, str + offset);
129 memcpy(str + offset, data, length);
139 * Unpack data from a byte string. The data types are specified in
140 * the format string: 'b' means unsigned byte, 'w' unsigned word,
141 * 'd' unsigned double word, and 's' byte string. The data are a
142 * series of offsets and pointers (for type byte string there are also
145 * @param str output string
146 * @param size size of output string
147 * @param format format string
148 * @param ... data points
149 * @return 0 on success, non-0 on error
151 int unpack_byte_string(const uint8_t *str, size_t size, const char *format, ...)
154 size_t offset = 0, length = 0;
155 uint8_t *ptr8 = NULL;
156 uint16_t *ptr16 = NULL;
157 uint32_t *ptr32 = NULL;
159 va_start(args, format);
160 for (; *format; format++) {
163 offset = va_arg(args, size_t);
164 ptr8 = va_arg(args, uint8_t *);
168 offset = va_arg(args, size_t);
169 ptr16 = va_arg(args, uint16_t *);
173 offset = va_arg(args, size_t);
174 ptr32 = va_arg(args, uint32_t *);
178 offset = va_arg(args, size_t);
179 ptr8 = va_arg(args, uint8_t *);
180 length = va_arg(args, uint32_t);
183 debug("Couldn't recognize format string\n");
187 if (offset + length > size)
195 *ptr16 = get_unaligned_be16(str + offset);
198 *ptr32 = get_unaligned_be32(str + offset);
201 memcpy(ptr8, str + offset, length);
211 * Get TPM command size.
213 * @param command byte string of TPM command
214 * @return command size of the TPM command
216 static uint32_t tpm_command_size(const void *command)
218 const size_t command_size_offset = 2;
219 return get_unaligned_be32(command + command_size_offset);
223 * Get TPM response return code, which is one of TPM_RESULT values.
225 * @param response byte string of TPM response
226 * @return return code of the TPM response
228 static uint32_t tpm_return_code(const void *response)
230 const size_t return_code_offset = 6;
231 return get_unaligned_be32(response + return_code_offset);
235 * Send a TPM command and return response's return code, and optionally
236 * return response to caller.
238 * @param command byte string of TPM command
239 * @param response output buffer for TPM response, or NULL if the
240 * caller does not care about it
241 * @param size_ptr output buffer size (input parameter) and TPM
242 * response length (output parameter); this parameter
244 * @return return code of the TPM response
246 static uint32_t tpm_sendrecv_command(const void *command,
247 void *response, size_t *size_ptr)
249 uint8_t response_buffer[COMMAND_BUFFER_SIZE];
250 size_t response_length;
254 response_length = *size_ptr;
256 response = response_buffer;
257 response_length = sizeof(response_buffer);
259 err = tis_sendrecv(command, tpm_command_size(command),
260 response, &response_length);
262 return TPM_LIB_ERROR;
264 *size_ptr = response_length;
266 return tpm_return_code(response);
269 uint32_t tpm_init(void)
280 uint32_t tpm_startup(enum tpm_startup_type mode)
282 const uint8_t command[12] = {
283 0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0x99, 0x0, 0x0,
285 const size_t mode_offset = 10;
286 uint8_t buf[COMMAND_BUFFER_SIZE];
288 if (pack_byte_string(buf, sizeof(buf), "sw",
289 0, command, sizeof(command),
291 return TPM_LIB_ERROR;
293 return tpm_sendrecv_command(buf, NULL, NULL);
296 uint32_t tpm_self_test_full(void)
298 const uint8_t command[10] = {
299 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x50,
301 return tpm_sendrecv_command(command, NULL, NULL);
304 uint32_t tpm_continue_self_test(void)
306 const uint8_t command[10] = {
307 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x53,
309 return tpm_sendrecv_command(command, NULL, NULL);
312 uint32_t tpm_nv_define_space(uint32_t index, uint32_t perm, uint32_t size)
314 const uint8_t command[101] = {
315 0x0, 0xc1, /* TPM_TAG */
316 0x0, 0x0, 0x0, 0x65, /* parameter size */
317 0x0, 0x0, 0x0, 0xcc, /* TPM_COMMAND_CODE */
318 /* TPM_NV_DATA_PUBLIC->... */
319 0x0, 0x18, /* ...->TPM_STRUCTURE_TAG */
320 0, 0, 0, 0, /* ...->TPM_NV_INDEX */
321 /* TPM_NV_DATA_PUBLIC->TPM_PCR_INFO_SHORT */
325 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
326 /* TPM_NV_DATA_PUBLIC->TPM_PCR_INFO_SHORT */
330 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
331 /* TPM_NV_ATTRIBUTES->... */
332 0x0, 0x17, /* ...->TPM_STRUCTURE_TAG */
333 0, 0, 0, 0, /* ...->attributes */
334 /* End of TPM_NV_ATTRIBUTES */
335 0, /* bReadSTClear */
336 0, /* bWriteSTClear */
337 0, /* bWriteDefine */
338 0, 0, 0, 0, /* size */
340 const size_t index_offset = 12;
341 const size_t perm_offset = 70;
342 const size_t size_offset = 77;
343 uint8_t buf[COMMAND_BUFFER_SIZE];
345 if (pack_byte_string(buf, sizeof(buf), "sddd",
346 0, command, sizeof(command),
350 return TPM_LIB_ERROR;
352 return tpm_sendrecv_command(buf, NULL, NULL);
355 uint32_t tpm_nv_read_value(uint32_t index, void *data, uint32_t count)
357 const uint8_t command[22] = {
358 0x0, 0xc1, 0x0, 0x0, 0x0, 0x16, 0x0, 0x0, 0x0, 0xcf,
360 const size_t index_offset = 10;
361 const size_t length_offset = 18;
362 const size_t data_size_offset = 10;
363 const size_t data_offset = 14;
364 uint8_t buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
365 size_t response_length = sizeof(response);
369 if (pack_byte_string(buf, sizeof(buf), "sdd",
370 0, command, sizeof(command),
372 length_offset, count))
373 return TPM_LIB_ERROR;
374 err = tpm_sendrecv_command(buf, response, &response_length);
377 if (unpack_byte_string(response, response_length, "d",
378 data_size_offset, &data_size))
379 return TPM_LIB_ERROR;
380 if (data_size > count)
381 return TPM_LIB_ERROR;
382 if (unpack_byte_string(response, response_length, "s",
383 data_offset, data, data_size))
384 return TPM_LIB_ERROR;
389 uint32_t tpm_nv_write_value(uint32_t index, const void *data, uint32_t length)
391 const uint8_t command[256] = {
392 0x0, 0xc1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xcd,
394 const size_t command_size_offset = 2;
395 const size_t index_offset = 10;
396 const size_t length_offset = 18;
397 const size_t data_offset = 22;
398 const size_t write_info_size = 12;
399 const uint32_t total_length =
400 TPM_REQUEST_HEADER_LENGTH + write_info_size + length;
401 uint8_t buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
402 size_t response_length = sizeof(response);
405 if (pack_byte_string(buf, sizeof(buf), "sddds",
406 0, command, sizeof(command),
407 command_size_offset, total_length,
409 length_offset, length,
410 data_offset, data, length))
411 return TPM_LIB_ERROR;
412 err = tpm_sendrecv_command(buf, response, &response_length);
419 uint32_t tpm_extend(uint32_t index, const void *in_digest, void *out_digest)
421 const uint8_t command[34] = {
422 0x0, 0xc1, 0x0, 0x0, 0x0, 0x22, 0x0, 0x0, 0x0, 0x14,
424 const size_t index_offset = 10;
425 const size_t in_digest_offset = 14;
426 const size_t out_digest_offset = 10;
427 uint8_t buf[COMMAND_BUFFER_SIZE];
428 uint8_t response[TPM_RESPONSE_HEADER_LENGTH + PCR_DIGEST_LENGTH];
429 size_t response_length = sizeof(response);
432 if (pack_byte_string(buf, sizeof(buf), "sds",
433 0, command, sizeof(command),
435 in_digest_offset, in_digest,
437 return TPM_LIB_ERROR;
438 err = tpm_sendrecv_command(buf, response, &response_length);
442 if (unpack_byte_string(response, response_length, "s",
443 out_digest_offset, out_digest,
445 return TPM_LIB_ERROR;
450 uint32_t tpm_pcr_read(uint32_t index, void *data, size_t count)
452 const uint8_t command[14] = {
453 0x0, 0xc1, 0x0, 0x0, 0x0, 0xe, 0x0, 0x0, 0x0, 0x15,
455 const size_t index_offset = 10;
456 const size_t out_digest_offset = 10;
457 uint8_t buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
458 size_t response_length = sizeof(response);
461 if (count < PCR_DIGEST_LENGTH)
462 return TPM_LIB_ERROR;
464 if (pack_byte_string(buf, sizeof(buf), "sd",
465 0, command, sizeof(command),
466 index_offset, index))
467 return TPM_LIB_ERROR;
468 err = tpm_sendrecv_command(buf, response, &response_length);
471 if (unpack_byte_string(response, response_length, "s",
472 out_digest_offset, data, PCR_DIGEST_LENGTH))
473 return TPM_LIB_ERROR;
478 uint32_t tpm_tsc_physical_presence(uint16_t presence)
480 const uint8_t command[12] = {
481 0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x40, 0x0, 0x0, 0xa, 0x0, 0x0,
483 const size_t presence_offset = 10;
484 uint8_t buf[COMMAND_BUFFER_SIZE];
486 if (pack_byte_string(buf, sizeof(buf), "sw",
487 0, command, sizeof(command),
488 presence_offset, presence))
489 return TPM_LIB_ERROR;
491 return tpm_sendrecv_command(buf, NULL, NULL);
494 uint32_t tpm_read_pubek(void *data, size_t count)
496 const uint8_t command[30] = {
497 0x0, 0xc1, 0x0, 0x0, 0x0, 0x1e, 0x0, 0x0, 0x0, 0x7c,
499 const size_t response_size_offset = 2;
500 const size_t data_offset = 10;
501 const size_t header_and_checksum_size = TPM_RESPONSE_HEADER_LENGTH + 20;
502 uint8_t response[COMMAND_BUFFER_SIZE + TPM_PUBEK_SIZE];
503 size_t response_length = sizeof(response);
507 err = tpm_sendrecv_command(command, response, &response_length);
510 if (unpack_byte_string(response, response_length, "d",
511 response_size_offset, &data_size))
512 return TPM_LIB_ERROR;
513 if (data_size < header_and_checksum_size)
514 return TPM_LIB_ERROR;
515 data_size -= header_and_checksum_size;
516 if (data_size > count)
517 return TPM_LIB_ERROR;
518 if (unpack_byte_string(response, response_length, "s",
519 data_offset, data, data_size))
520 return TPM_LIB_ERROR;
525 uint32_t tpm_force_clear(void)
527 const uint8_t command[10] = {
528 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x5d,
531 return tpm_sendrecv_command(command, NULL, NULL);
534 uint32_t tpm_physical_enable(void)
536 const uint8_t command[10] = {
537 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x6f,
540 return tpm_sendrecv_command(command, NULL, NULL);
543 uint32_t tpm_physical_disable(void)
545 const uint8_t command[10] = {
546 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x70,
549 return tpm_sendrecv_command(command, NULL, NULL);
552 uint32_t tpm_physical_set_deactivated(uint8_t state)
554 const uint8_t command[11] = {
555 0x0, 0xc1, 0x0, 0x0, 0x0, 0xb, 0x0, 0x0, 0x0, 0x72,
557 const size_t state_offset = 10;
558 uint8_t buf[COMMAND_BUFFER_SIZE];
560 if (pack_byte_string(buf, sizeof(buf), "sb",
561 0, command, sizeof(command),
562 state_offset, state))
563 return TPM_LIB_ERROR;
565 return tpm_sendrecv_command(buf, NULL, NULL);
568 uint32_t tpm_get_capability(uint32_t cap_area, uint32_t sub_cap,
569 void *cap, size_t count)
571 const uint8_t command[22] = {
572 0x0, 0xc1, /* TPM_TAG */
573 0x0, 0x0, 0x0, 0x16, /* parameter size */
574 0x0, 0x0, 0x0, 0x65, /* TPM_COMMAND_CODE */
575 0x0, 0x0, 0x0, 0x0, /* TPM_CAPABILITY_AREA */
576 0x0, 0x0, 0x0, 0x4, /* subcap size */
577 0x0, 0x0, 0x0, 0x0, /* subcap value */
579 const size_t cap_area_offset = 10;
580 const size_t sub_cap_offset = 18;
581 const size_t cap_offset = 14;
582 const size_t cap_size_offset = 10;
583 uint8_t buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
584 size_t response_length = sizeof(response);
588 if (pack_byte_string(buf, sizeof(buf), "sdd",
589 0, command, sizeof(command),
590 cap_area_offset, cap_area,
591 sub_cap_offset, sub_cap))
592 return TPM_LIB_ERROR;
593 err = tpm_sendrecv_command(buf, response, &response_length);
596 if (unpack_byte_string(response, response_length, "d",
597 cap_size_offset, &cap_size))
598 return TPM_LIB_ERROR;
599 if (cap_size > response_length || cap_size > count)
600 return TPM_LIB_ERROR;
601 if (unpack_byte_string(response, response_length, "s",
602 cap_offset, cap, cap_size))
603 return TPM_LIB_ERROR;
608 #ifdef CONFIG_TPM_AUTH_SESSIONS
611 * Fill an authentication block in a request.
612 * This func can create the first as well as the second auth block (for
613 * double authorized commands).
615 * @param request pointer to the request (w/ uninitialised auth data)
616 * @param request_len0 length of the request without auth data
617 * @param handles_len length of the handles area in request
618 * @param auth_session pointer to the (valid) auth session to be used
619 * @param request_auth pointer to the auth block of the request to be filled
620 * @param auth authentication data (HMAC key)
622 static uint32_t create_request_auth(const void *request, size_t request_len0,
624 struct session_data *auth_session,
625 void *request_auth, const void *auth)
627 uint8_t hmac_data[DIGEST_LENGTH * 3 + 1];
628 sha1_context hash_ctx;
629 const size_t command_code_offset = 6;
630 const size_t auth_nonce_odd_offset = 4;
631 const size_t auth_continue_offset = 24;
632 const size_t auth_auth_offset = 25;
634 if (!auth_session || !auth_session->valid)
635 return TPM_LIB_ERROR;
637 sha1_starts(&hash_ctx);
638 sha1_update(&hash_ctx, request + command_code_offset, 4);
639 if (request_len0 > TPM_REQUEST_HEADER_LENGTH + handles_len)
640 sha1_update(&hash_ctx,
641 request + TPM_REQUEST_HEADER_LENGTH + handles_len,
642 request_len0 - TPM_REQUEST_HEADER_LENGTH
644 sha1_finish(&hash_ctx, hmac_data);
646 sha1_starts(&hash_ctx);
647 sha1_update(&hash_ctx, auth_session->nonce_odd, DIGEST_LENGTH);
648 sha1_update(&hash_ctx, hmac_data, sizeof(hmac_data));
649 sha1_finish(&hash_ctx, auth_session->nonce_odd);
651 if (pack_byte_string(request_auth, TPM_REQUEST_AUTH_LENGTH, "dsb",
652 0, auth_session->handle,
653 auth_nonce_odd_offset, auth_session->nonce_odd,
655 auth_continue_offset, 1))
656 return TPM_LIB_ERROR;
657 if (pack_byte_string(hmac_data, sizeof(hmac_data), "ss",
659 auth_session->nonce_even,
662 request_auth + auth_nonce_odd_offset,
664 return TPM_LIB_ERROR;
665 sha1_hmac(auth, DIGEST_LENGTH, hmac_data, sizeof(hmac_data),
666 request_auth + auth_auth_offset);
672 * Verify an authentication block in a response.
673 * Since this func updates the nonce_even in the session data it has to be
674 * called when receiving a succesfull AUTH response.
675 * This func can verify the first as well as the second auth block (for
676 * double authorized commands).
678 * @param command_code command code of the request
679 * @param response pointer to the request (w/ uninitialised auth data)
680 * @param handles_len length of the handles area in response
681 * @param auth_session pointer to the (valid) auth session to be used
682 * @param response_auth pointer to the auth block of the response to be verified
683 * @param auth authentication data (HMAC key)
685 static uint32_t verify_response_auth(uint32_t command_code,
686 const void *response, size_t response_len0,
688 struct session_data *auth_session,
689 const void *response_auth, const void *auth)
691 uint8_t hmac_data[DIGEST_LENGTH * 3 + 1];
692 uint8_t computed_auth[DIGEST_LENGTH];
693 sha1_context hash_ctx;
694 const size_t return_code_offset = 6;
695 const size_t auth_continue_offset = 20;
696 const size_t auth_auth_offset = 21;
697 uint8_t auth_continue;
699 if (!auth_session || !auth_session->valid)
701 if (pack_byte_string(hmac_data, sizeof(hmac_data), "d",
703 return TPM_LIB_ERROR;
704 if (response_len0 < TPM_RESPONSE_HEADER_LENGTH)
705 return TPM_LIB_ERROR;
707 sha1_starts(&hash_ctx);
708 sha1_update(&hash_ctx, response + return_code_offset, 4);
709 sha1_update(&hash_ctx, hmac_data, 4);
710 if (response_len0 > TPM_RESPONSE_HEADER_LENGTH + handles_len)
711 sha1_update(&hash_ctx,
712 response + TPM_RESPONSE_HEADER_LENGTH + handles_len,
713 response_len0 - TPM_RESPONSE_HEADER_LENGTH
715 sha1_finish(&hash_ctx, hmac_data);
717 memcpy(auth_session->nonce_even, response_auth, DIGEST_LENGTH);
718 auth_continue = ((uint8_t *)response_auth)[auth_continue_offset];
719 if (pack_byte_string(hmac_data, sizeof(hmac_data), "ssb",
724 auth_session->nonce_odd,
728 return TPM_LIB_ERROR;
730 sha1_hmac(auth, DIGEST_LENGTH, hmac_data, sizeof(hmac_data),
733 if (memcmp(computed_auth, response_auth + auth_auth_offset,
741 uint32_t tpm_terminate_auth_session(uint32_t auth_handle)
743 const uint8_t command[18] = {
744 0x00, 0xc1, /* TPM_TAG */
745 0x00, 0x00, 0x00, 0x00, /* parameter size */
746 0x00, 0x00, 0x00, 0xba, /* TPM_COMMAND_CODE */
747 0x00, 0x00, 0x00, 0x00, /* TPM_HANDLE */
748 0x00, 0x00, 0x00, 0x02, /* TPM_RESSOURCE_TYPE */
750 const size_t req_handle_offset = TPM_REQUEST_HEADER_LENGTH;
751 uint8_t request[COMMAND_BUFFER_SIZE];
753 if (pack_byte_string(request, sizeof(request), "sd",
754 0, command, sizeof(command),
755 req_handle_offset, auth_handle))
756 return TPM_LIB_ERROR;
757 if (oiap_session.valid && oiap_session.handle == auth_handle)
758 oiap_session.valid = 0;
760 return tpm_sendrecv_command(request, NULL, NULL);
763 uint32_t tpm_end_oiap(void)
765 uint32_t err = TPM_SUCCESS;
766 if (oiap_session.valid)
767 err = tpm_terminate_auth_session(oiap_session.handle);
771 uint32_t tpm_oiap(uint32_t *auth_handle)
773 const uint8_t command[10] = {
774 0x00, 0xc1, /* TPM_TAG */
775 0x00, 0x00, 0x00, 0x0a, /* parameter size */
776 0x00, 0x00, 0x00, 0x0a, /* TPM_COMMAND_CODE */
778 const size_t res_auth_handle_offset = TPM_RESPONSE_HEADER_LENGTH;
779 const size_t res_nonce_even_offset = TPM_RESPONSE_HEADER_LENGTH + 4;
780 uint8_t response[COMMAND_BUFFER_SIZE];
781 size_t response_length = sizeof(response);
784 if (oiap_session.valid)
785 tpm_terminate_auth_session(oiap_session.handle);
787 err = tpm_sendrecv_command(command, response, &response_length);
790 if (unpack_byte_string(response, response_length, "ds",
791 res_auth_handle_offset, &oiap_session.handle,
792 res_nonce_even_offset, &oiap_session.nonce_even,
793 (uint32_t)DIGEST_LENGTH))
794 return TPM_LIB_ERROR;
795 oiap_session.valid = 1;
797 *auth_handle = oiap_session.handle;
801 uint32_t tpm_load_key2_oiap(uint32_t parent_handle,
802 const void *key, size_t key_length,
803 const void *parent_key_usage_auth,
804 uint32_t *key_handle)
806 const uint8_t command[14] = {
807 0x00, 0xc2, /* TPM_TAG */
808 0x00, 0x00, 0x00, 0x00, /* parameter size */
809 0x00, 0x00, 0x00, 0x41, /* TPM_COMMAND_CODE */
810 0x00, 0x00, 0x00, 0x00, /* parent handle */
812 const size_t req_size_offset = 2;
813 const size_t req_parent_handle_offset = TPM_REQUEST_HEADER_LENGTH;
814 const size_t req_key_offset = TPM_REQUEST_HEADER_LENGTH + 4;
815 const size_t res_handle_offset = TPM_RESPONSE_HEADER_LENGTH;
816 uint8_t request[sizeof(command) + TPM_KEY12_MAX_LENGTH
817 + TPM_REQUEST_AUTH_LENGTH];
818 uint8_t response[COMMAND_BUFFER_SIZE];
819 size_t response_length = sizeof(response);
822 if (!oiap_session.valid) {
823 err = tpm_oiap(NULL);
827 if (pack_byte_string(request, sizeof(request), "sdds",
828 0, command, sizeof(command),
830 sizeof(command) + key_length
831 + TPM_REQUEST_AUTH_LENGTH,
832 req_parent_handle_offset, parent_handle,
833 req_key_offset, key, key_length
835 return TPM_LIB_ERROR;
837 err = create_request_auth(request, sizeof(command) + key_length, 4,
839 request + sizeof(command) + key_length,
840 parent_key_usage_auth);
843 err = tpm_sendrecv_command(request, response, &response_length);
845 if (err == TPM_AUTHFAIL)
846 oiap_session.valid = 0;
850 err = verify_response_auth(0x00000041, response,
851 response_length - TPM_RESPONSE_AUTH_LENGTH,
853 response + response_length - TPM_RESPONSE_AUTH_LENGTH,
854 parent_key_usage_auth);
859 if (unpack_byte_string(response, response_length, "d",
860 res_handle_offset, key_handle))
861 return TPM_LIB_ERROR;
867 uint32_t tpm_get_pub_key_oiap(uint32_t key_handle, const void *usage_auth,
868 void *pubkey, size_t *pubkey_len)
870 const uint8_t command[14] = {
871 0x00, 0xc2, /* TPM_TAG */
872 0x00, 0x00, 0x00, 0x00, /* parameter size */
873 0x00, 0x00, 0x00, 0x21, /* TPM_COMMAND_CODE */
874 0x00, 0x00, 0x00, 0x00, /* key handle */
876 const size_t req_size_offset = 2;
877 const size_t req_key_handle_offset = TPM_REQUEST_HEADER_LENGTH;
878 const size_t res_pubkey_offset = TPM_RESPONSE_HEADER_LENGTH;
879 uint8_t request[sizeof(command) + TPM_REQUEST_AUTH_LENGTH];
880 uint8_t response[TPM_RESPONSE_HEADER_LENGTH + TPM_PUBKEY_MAX_LENGTH
881 + TPM_RESPONSE_AUTH_LENGTH];
882 size_t response_length = sizeof(response);
885 if (!oiap_session.valid) {
886 err = tpm_oiap(NULL);
890 if (pack_byte_string(request, sizeof(request), "sdd",
891 0, command, sizeof(command),
893 (uint32_t)(sizeof(command)
894 + TPM_REQUEST_AUTH_LENGTH),
895 req_key_handle_offset, key_handle
897 return TPM_LIB_ERROR;
898 err = create_request_auth(request, sizeof(command), 4, &oiap_session,
899 request + sizeof(command), usage_auth);
902 err = tpm_sendrecv_command(request, response, &response_length);
904 if (err == TPM_AUTHFAIL)
905 oiap_session.valid = 0;
908 err = verify_response_auth(0x00000021, response,
909 response_length - TPM_RESPONSE_AUTH_LENGTH,
911 response + response_length - TPM_RESPONSE_AUTH_LENGTH,
917 if ((response_length - TPM_RESPONSE_HEADER_LENGTH
918 - TPM_RESPONSE_AUTH_LENGTH) > *pubkey_len)
919 return TPM_LIB_ERROR;
920 *pubkey_len = response_length - TPM_RESPONSE_HEADER_LENGTH
921 - TPM_RESPONSE_AUTH_LENGTH;
922 memcpy(pubkey, response + res_pubkey_offset,
923 response_length - TPM_RESPONSE_HEADER_LENGTH
924 - TPM_RESPONSE_AUTH_LENGTH);
930 #endif /* CONFIG_TPM_AUTH_SESSIONS */