2 * Copyright (c) 2013 The Chromium OS Authors.
3 * Coypright (c) 2013 Guntermann & Drunck GmbH
5 * SPDX-License-Identifier: GPL-2.0+
10 #include <u-boot/sha1.h>
12 #include <asm/unaligned.h>
14 /* Internal error of TPM command library */
15 #define TPM_LIB_ERROR ((uint32_t)~0u)
17 /* Useful constants */
19 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
);
243 err
= tis_sendrecv(command
, tpm_command_size(command
),
244 response
, &response_length
);
246 return TPM_LIB_ERROR
;
248 *size_ptr
= response_length
;
250 return tpm_return_code(response
);
253 uint32_t tpm_init(void)
264 uint32_t tpm_startup(enum tpm_startup_type mode
)
266 const uint8_t command
[12] = {
267 0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0x99, 0x0, 0x0,
269 const size_t mode_offset
= 10;
270 uint8_t buf
[COMMAND_BUFFER_SIZE
];
272 if (pack_byte_string(buf
, sizeof(buf
), "sw",
273 0, command
, sizeof(command
),
275 return TPM_LIB_ERROR
;
277 return tpm_sendrecv_command(buf
, NULL
, NULL
);
280 uint32_t tpm_self_test_full(void)
282 const uint8_t command
[10] = {
283 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x50,
285 return tpm_sendrecv_command(command
, NULL
, NULL
);
288 uint32_t tpm_continue_self_test(void)
290 const uint8_t command
[10] = {
291 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x53,
293 return tpm_sendrecv_command(command
, NULL
, NULL
);
296 uint32_t tpm_nv_define_space(uint32_t index
, uint32_t perm
, uint32_t size
)
298 const uint8_t command
[101] = {
299 0x0, 0xc1, /* TPM_TAG */
300 0x0, 0x0, 0x0, 0x65, /* parameter size */
301 0x0, 0x0, 0x0, 0xcc, /* TPM_COMMAND_CODE */
302 /* TPM_NV_DATA_PUBLIC->... */
303 0x0, 0x18, /* ...->TPM_STRUCTURE_TAG */
304 0, 0, 0, 0, /* ...->TPM_NV_INDEX */
305 /* TPM_NV_DATA_PUBLIC->TPM_PCR_INFO_SHORT */
309 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
310 /* TPM_NV_DATA_PUBLIC->TPM_PCR_INFO_SHORT */
314 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
315 /* TPM_NV_ATTRIBUTES->... */
316 0x0, 0x17, /* ...->TPM_STRUCTURE_TAG */
317 0, 0, 0, 0, /* ...->attributes */
318 /* End of TPM_NV_ATTRIBUTES */
319 0, /* bReadSTClear */
320 0, /* bWriteSTClear */
321 0, /* bWriteDefine */
322 0, 0, 0, 0, /* size */
324 const size_t index_offset
= 12;
325 const size_t perm_offset
= 70;
326 const size_t size_offset
= 77;
327 uint8_t buf
[COMMAND_BUFFER_SIZE
];
329 if (pack_byte_string(buf
, sizeof(buf
), "sddd",
330 0, command
, sizeof(command
),
334 return TPM_LIB_ERROR
;
336 return tpm_sendrecv_command(buf
, NULL
, NULL
);
339 uint32_t tpm_nv_read_value(uint32_t index
, void *data
, uint32_t count
)
341 const uint8_t command
[22] = {
342 0x0, 0xc1, 0x0, 0x0, 0x0, 0x16, 0x0, 0x0, 0x0, 0xcf,
344 const size_t index_offset
= 10;
345 const size_t length_offset
= 18;
346 const size_t data_size_offset
= 10;
347 const size_t data_offset
= 14;
348 uint8_t buf
[COMMAND_BUFFER_SIZE
], response
[COMMAND_BUFFER_SIZE
];
349 size_t response_length
= sizeof(response
);
353 if (pack_byte_string(buf
, sizeof(buf
), "sdd",
354 0, command
, sizeof(command
),
356 length_offset
, count
))
357 return TPM_LIB_ERROR
;
358 err
= tpm_sendrecv_command(buf
, response
, &response_length
);
361 if (unpack_byte_string(response
, response_length
, "d",
362 data_size_offset
, &data_size
))
363 return TPM_LIB_ERROR
;
364 if (data_size
> count
)
365 return TPM_LIB_ERROR
;
366 if (unpack_byte_string(response
, response_length
, "s",
367 data_offset
, data
, data_size
))
368 return TPM_LIB_ERROR
;
373 uint32_t tpm_nv_write_value(uint32_t index
, const void *data
, uint32_t length
)
375 const uint8_t command
[256] = {
376 0x0, 0xc1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xcd,
378 const size_t command_size_offset
= 2;
379 const size_t index_offset
= 10;
380 const size_t length_offset
= 18;
381 const size_t data_offset
= 22;
382 const size_t write_info_size
= 12;
383 const uint32_t total_length
=
384 TPM_REQUEST_HEADER_LENGTH
+ write_info_size
+ length
;
385 uint8_t buf
[COMMAND_BUFFER_SIZE
], response
[COMMAND_BUFFER_SIZE
];
386 size_t response_length
= sizeof(response
);
389 if (pack_byte_string(buf
, sizeof(buf
), "sddds",
390 0, command
, sizeof(command
),
391 command_size_offset
, total_length
,
393 length_offset
, length
,
394 data_offset
, data
, length
))
395 return TPM_LIB_ERROR
;
396 err
= tpm_sendrecv_command(buf
, response
, &response_length
);
403 uint32_t tpm_extend(uint32_t index
, const void *in_digest
, void *out_digest
)
405 const uint8_t command
[34] = {
406 0x0, 0xc1, 0x0, 0x0, 0x0, 0x22, 0x0, 0x0, 0x0, 0x14,
408 const size_t index_offset
= 10;
409 const size_t in_digest_offset
= 14;
410 const size_t out_digest_offset
= 10;
411 uint8_t buf
[COMMAND_BUFFER_SIZE
];
412 uint8_t response
[TPM_RESPONSE_HEADER_LENGTH
+ PCR_DIGEST_LENGTH
];
413 size_t response_length
= sizeof(response
);
416 if (pack_byte_string(buf
, sizeof(buf
), "sds",
417 0, command
, sizeof(command
),
419 in_digest_offset
, in_digest
,
421 return TPM_LIB_ERROR
;
422 err
= tpm_sendrecv_command(buf
, response
, &response_length
);
426 if (unpack_byte_string(response
, response_length
, "s",
427 out_digest_offset
, out_digest
,
429 return TPM_LIB_ERROR
;
434 uint32_t tpm_pcr_read(uint32_t index
, void *data
, size_t count
)
436 const uint8_t command
[14] = {
437 0x0, 0xc1, 0x0, 0x0, 0x0, 0xe, 0x0, 0x0, 0x0, 0x15,
439 const size_t index_offset
= 10;
440 const size_t out_digest_offset
= 10;
441 uint8_t buf
[COMMAND_BUFFER_SIZE
], response
[COMMAND_BUFFER_SIZE
];
442 size_t response_length
= sizeof(response
);
445 if (count
< PCR_DIGEST_LENGTH
)
446 return TPM_LIB_ERROR
;
448 if (pack_byte_string(buf
, sizeof(buf
), "sd",
449 0, command
, sizeof(command
),
450 index_offset
, index
))
451 return TPM_LIB_ERROR
;
452 err
= tpm_sendrecv_command(buf
, response
, &response_length
);
455 if (unpack_byte_string(response
, response_length
, "s",
456 out_digest_offset
, data
, PCR_DIGEST_LENGTH
))
457 return TPM_LIB_ERROR
;
462 uint32_t tpm_tsc_physical_presence(uint16_t presence
)
464 const uint8_t command
[12] = {
465 0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x40, 0x0, 0x0, 0xa, 0x0, 0x0,
467 const size_t presence_offset
= 10;
468 uint8_t buf
[COMMAND_BUFFER_SIZE
];
470 if (pack_byte_string(buf
, sizeof(buf
), "sw",
471 0, command
, sizeof(command
),
472 presence_offset
, presence
))
473 return TPM_LIB_ERROR
;
475 return tpm_sendrecv_command(buf
, NULL
, NULL
);
478 uint32_t tpm_read_pubek(void *data
, size_t count
)
480 const uint8_t command
[30] = {
481 0x0, 0xc1, 0x0, 0x0, 0x0, 0x1e, 0x0, 0x0, 0x0, 0x7c,
483 const size_t response_size_offset
= 2;
484 const size_t data_offset
= 10;
485 const size_t header_and_checksum_size
= TPM_RESPONSE_HEADER_LENGTH
+ 20;
486 uint8_t response
[COMMAND_BUFFER_SIZE
+ TPM_PUBEK_SIZE
];
487 size_t response_length
= sizeof(response
);
491 err
= tpm_sendrecv_command(command
, response
, &response_length
);
494 if (unpack_byte_string(response
, response_length
, "d",
495 response_size_offset
, &data_size
))
496 return TPM_LIB_ERROR
;
497 if (data_size
< header_and_checksum_size
)
498 return TPM_LIB_ERROR
;
499 data_size
-= header_and_checksum_size
;
500 if (data_size
> count
)
501 return TPM_LIB_ERROR
;
502 if (unpack_byte_string(response
, response_length
, "s",
503 data_offset
, data
, data_size
))
504 return TPM_LIB_ERROR
;
509 uint32_t tpm_force_clear(void)
511 const uint8_t command
[10] = {
512 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x5d,
515 return tpm_sendrecv_command(command
, NULL
, NULL
);
518 uint32_t tpm_physical_enable(void)
520 const uint8_t command
[10] = {
521 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x6f,
524 return tpm_sendrecv_command(command
, NULL
, NULL
);
527 uint32_t tpm_physical_disable(void)
529 const uint8_t command
[10] = {
530 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x70,
533 return tpm_sendrecv_command(command
, NULL
, NULL
);
536 uint32_t tpm_physical_set_deactivated(uint8_t state
)
538 const uint8_t command
[11] = {
539 0x0, 0xc1, 0x0, 0x0, 0x0, 0xb, 0x0, 0x0, 0x0, 0x72,
541 const size_t state_offset
= 10;
542 uint8_t buf
[COMMAND_BUFFER_SIZE
];
544 if (pack_byte_string(buf
, sizeof(buf
), "sb",
545 0, command
, sizeof(command
),
546 state_offset
, state
))
547 return TPM_LIB_ERROR
;
549 return tpm_sendrecv_command(buf
, NULL
, NULL
);
552 uint32_t tpm_get_capability(uint32_t cap_area
, uint32_t sub_cap
,
553 void *cap
, size_t count
)
555 const uint8_t command
[22] = {
556 0x0, 0xc1, /* TPM_TAG */
557 0x0, 0x0, 0x0, 0x16, /* parameter size */
558 0x0, 0x0, 0x0, 0x65, /* TPM_COMMAND_CODE */
559 0x0, 0x0, 0x0, 0x0, /* TPM_CAPABILITY_AREA */
560 0x0, 0x0, 0x0, 0x4, /* subcap size */
561 0x0, 0x0, 0x0, 0x0, /* subcap value */
563 const size_t cap_area_offset
= 10;
564 const size_t sub_cap_offset
= 18;
565 const size_t cap_offset
= 14;
566 const size_t cap_size_offset
= 10;
567 uint8_t buf
[COMMAND_BUFFER_SIZE
], response
[COMMAND_BUFFER_SIZE
];
568 size_t response_length
= sizeof(response
);
572 if (pack_byte_string(buf
, sizeof(buf
), "sdd",
573 0, command
, sizeof(command
),
574 cap_area_offset
, cap_area
,
575 sub_cap_offset
, sub_cap
))
576 return TPM_LIB_ERROR
;
577 err
= tpm_sendrecv_command(buf
, response
, &response_length
);
580 if (unpack_byte_string(response
, response_length
, "d",
581 cap_size_offset
, &cap_size
))
582 return TPM_LIB_ERROR
;
583 if (cap_size
> response_length
|| cap_size
> count
)
584 return TPM_LIB_ERROR
;
585 if (unpack_byte_string(response
, response_length
, "s",
586 cap_offset
, cap
, cap_size
))
587 return TPM_LIB_ERROR
;
592 #ifdef CONFIG_TPM_AUTH_SESSIONS
595 * Fill an authentication block in a request.
596 * This func can create the first as well as the second auth block (for
597 * double authorized commands).
599 * @param request pointer to the request (w/ uninitialised auth data)
600 * @param request_len0 length of the request without auth data
601 * @param handles_len length of the handles area in request
602 * @param auth_session pointer to the (valid) auth session to be used
603 * @param request_auth pointer to the auth block of the request to be filled
604 * @param auth authentication data (HMAC key)
606 static uint32_t create_request_auth(const void *request
, size_t request_len0
,
608 struct session_data
*auth_session
,
609 void *request_auth
, const void *auth
)
611 uint8_t hmac_data
[DIGEST_LENGTH
* 3 + 1];
612 sha1_context hash_ctx
;
613 const size_t command_code_offset
= 6;
614 const size_t auth_nonce_odd_offset
= 4;
615 const size_t auth_continue_offset
= 24;
616 const size_t auth_auth_offset
= 25;
618 if (!auth_session
|| !auth_session
->valid
)
619 return TPM_LIB_ERROR
;
621 sha1_starts(&hash_ctx
);
622 sha1_update(&hash_ctx
, request
+ command_code_offset
, 4);
623 if (request_len0
> TPM_REQUEST_HEADER_LENGTH
+ handles_len
)
624 sha1_update(&hash_ctx
,
625 request
+ TPM_REQUEST_HEADER_LENGTH
+ handles_len
,
626 request_len0
- TPM_REQUEST_HEADER_LENGTH
628 sha1_finish(&hash_ctx
, hmac_data
);
630 sha1_starts(&hash_ctx
);
631 sha1_update(&hash_ctx
, auth_session
->nonce_odd
, DIGEST_LENGTH
);
632 sha1_update(&hash_ctx
, hmac_data
, sizeof(hmac_data
));
633 sha1_finish(&hash_ctx
, auth_session
->nonce_odd
);
635 if (pack_byte_string(request_auth
, TPM_REQUEST_AUTH_LENGTH
, "dsb",
636 0, auth_session
->handle
,
637 auth_nonce_odd_offset
, auth_session
->nonce_odd
,
639 auth_continue_offset
, 1))
640 return TPM_LIB_ERROR
;
641 if (pack_byte_string(hmac_data
, sizeof(hmac_data
), "ss",
643 auth_session
->nonce_even
,
646 request_auth
+ auth_nonce_odd_offset
,
648 return TPM_LIB_ERROR
;
649 sha1_hmac(auth
, DIGEST_LENGTH
, hmac_data
, sizeof(hmac_data
),
650 request_auth
+ auth_auth_offset
);
656 * Verify an authentication block in a response.
657 * Since this func updates the nonce_even in the session data it has to be
658 * called when receiving a succesfull AUTH response.
659 * This func can verify the first as well as the second auth block (for
660 * double authorized commands).
662 * @param command_code command code of the request
663 * @param response pointer to the request (w/ uninitialised auth data)
664 * @param handles_len length of the handles area in response
665 * @param auth_session pointer to the (valid) auth session to be used
666 * @param response_auth pointer to the auth block of the response to be verified
667 * @param auth authentication data (HMAC key)
669 static uint32_t verify_response_auth(uint32_t command_code
,
670 const void *response
, size_t response_len0
,
672 struct session_data
*auth_session
,
673 const void *response_auth
, const void *auth
)
675 uint8_t hmac_data
[DIGEST_LENGTH
* 3 + 1];
676 uint8_t computed_auth
[DIGEST_LENGTH
];
677 sha1_context hash_ctx
;
678 const size_t return_code_offset
= 6;
679 const size_t auth_continue_offset
= 20;
680 const size_t auth_auth_offset
= 21;
681 uint8_t auth_continue
;
683 if (!auth_session
|| !auth_session
->valid
)
685 if (pack_byte_string(hmac_data
, sizeof(hmac_data
), "d",
687 return TPM_LIB_ERROR
;
688 if (response_len0
< TPM_RESPONSE_HEADER_LENGTH
)
689 return TPM_LIB_ERROR
;
691 sha1_starts(&hash_ctx
);
692 sha1_update(&hash_ctx
, response
+ return_code_offset
, 4);
693 sha1_update(&hash_ctx
, hmac_data
, 4);
694 if (response_len0
> TPM_RESPONSE_HEADER_LENGTH
+ handles_len
)
695 sha1_update(&hash_ctx
,
696 response
+ TPM_RESPONSE_HEADER_LENGTH
+ handles_len
,
697 response_len0
- TPM_RESPONSE_HEADER_LENGTH
699 sha1_finish(&hash_ctx
, hmac_data
);
701 memcpy(auth_session
->nonce_even
, response_auth
, DIGEST_LENGTH
);
702 auth_continue
= ((uint8_t *)response_auth
)[auth_continue_offset
];
703 if (pack_byte_string(hmac_data
, sizeof(hmac_data
), "ssb",
708 auth_session
->nonce_odd
,
712 return TPM_LIB_ERROR
;
714 sha1_hmac(auth
, DIGEST_LENGTH
, hmac_data
, sizeof(hmac_data
),
717 if (memcmp(computed_auth
, response_auth
+ auth_auth_offset
,
725 uint32_t tpm_terminate_auth_session(uint32_t auth_handle
)
727 const uint8_t command
[18] = {
728 0x00, 0xc1, /* TPM_TAG */
729 0x00, 0x00, 0x00, 0x00, /* parameter size */
730 0x00, 0x00, 0x00, 0xba, /* TPM_COMMAND_CODE */
731 0x00, 0x00, 0x00, 0x00, /* TPM_HANDLE */
732 0x00, 0x00, 0x00, 0x02, /* TPM_RESSOURCE_TYPE */
734 const size_t req_handle_offset
= TPM_REQUEST_HEADER_LENGTH
;
735 uint8_t request
[COMMAND_BUFFER_SIZE
];
737 if (pack_byte_string(request
, sizeof(request
), "sd",
738 0, command
, sizeof(command
),
739 req_handle_offset
, auth_handle
))
740 return TPM_LIB_ERROR
;
741 if (oiap_session
.valid
&& oiap_session
.handle
== auth_handle
)
742 oiap_session
.valid
= 0;
744 return tpm_sendrecv_command(request
, NULL
, NULL
);
747 uint32_t tpm_end_oiap(void)
749 uint32_t err
= TPM_SUCCESS
;
750 if (oiap_session
.valid
)
751 err
= tpm_terminate_auth_session(oiap_session
.handle
);
755 uint32_t tpm_oiap(uint32_t *auth_handle
)
757 const uint8_t command
[10] = {
758 0x00, 0xc1, /* TPM_TAG */
759 0x00, 0x00, 0x00, 0x0a, /* parameter size */
760 0x00, 0x00, 0x00, 0x0a, /* TPM_COMMAND_CODE */
762 const size_t res_auth_handle_offset
= TPM_RESPONSE_HEADER_LENGTH
;
763 const size_t res_nonce_even_offset
= TPM_RESPONSE_HEADER_LENGTH
+ 4;
764 uint8_t response
[COMMAND_BUFFER_SIZE
];
765 size_t response_length
= sizeof(response
);
768 if (oiap_session
.valid
)
769 tpm_terminate_auth_session(oiap_session
.handle
);
771 err
= tpm_sendrecv_command(command
, response
, &response_length
);
774 if (unpack_byte_string(response
, response_length
, "ds",
775 res_auth_handle_offset
, &oiap_session
.handle
,
776 res_nonce_even_offset
, &oiap_session
.nonce_even
,
777 (uint32_t)DIGEST_LENGTH
))
778 return TPM_LIB_ERROR
;
779 oiap_session
.valid
= 1;
781 *auth_handle
= oiap_session
.handle
;
785 uint32_t tpm_load_key2_oiap(uint32_t parent_handle
,
786 const void *key
, size_t key_length
,
787 const void *parent_key_usage_auth
,
788 uint32_t *key_handle
)
790 const uint8_t command
[14] = {
791 0x00, 0xc2, /* TPM_TAG */
792 0x00, 0x00, 0x00, 0x00, /* parameter size */
793 0x00, 0x00, 0x00, 0x41, /* TPM_COMMAND_CODE */
794 0x00, 0x00, 0x00, 0x00, /* parent handle */
796 const size_t req_size_offset
= 2;
797 const size_t req_parent_handle_offset
= TPM_REQUEST_HEADER_LENGTH
;
798 const size_t req_key_offset
= TPM_REQUEST_HEADER_LENGTH
+ 4;
799 const size_t res_handle_offset
= TPM_RESPONSE_HEADER_LENGTH
;
800 uint8_t request
[sizeof(command
) + TPM_KEY12_MAX_LENGTH
801 + TPM_REQUEST_AUTH_LENGTH
];
802 uint8_t response
[COMMAND_BUFFER_SIZE
];
803 size_t response_length
= sizeof(response
);
806 if (!oiap_session
.valid
) {
807 err
= tpm_oiap(NULL
);
811 if (pack_byte_string(request
, sizeof(request
), "sdds",
812 0, command
, sizeof(command
),
814 sizeof(command
) + key_length
815 + TPM_REQUEST_AUTH_LENGTH
,
816 req_parent_handle_offset
, parent_handle
,
817 req_key_offset
, key
, key_length
819 return TPM_LIB_ERROR
;
821 err
= create_request_auth(request
, sizeof(command
) + key_length
, 4,
823 request
+ sizeof(command
) + key_length
,
824 parent_key_usage_auth
);
827 err
= tpm_sendrecv_command(request
, response
, &response_length
);
829 if (err
== TPM_AUTHFAIL
)
830 oiap_session
.valid
= 0;
834 err
= verify_response_auth(0x00000041, response
,
835 response_length
- TPM_RESPONSE_AUTH_LENGTH
,
837 response
+ response_length
- TPM_RESPONSE_AUTH_LENGTH
,
838 parent_key_usage_auth
);
843 if (unpack_byte_string(response
, response_length
, "d",
844 res_handle_offset
, key_handle
))
845 return TPM_LIB_ERROR
;
851 uint32_t tpm_get_pub_key_oiap(uint32_t key_handle
, const void *usage_auth
,
852 void *pubkey
, size_t *pubkey_len
)
854 const uint8_t command
[14] = {
855 0x00, 0xc2, /* TPM_TAG */
856 0x00, 0x00, 0x00, 0x00, /* parameter size */
857 0x00, 0x00, 0x00, 0x21, /* TPM_COMMAND_CODE */
858 0x00, 0x00, 0x00, 0x00, /* key handle */
860 const size_t req_size_offset
= 2;
861 const size_t req_key_handle_offset
= TPM_REQUEST_HEADER_LENGTH
;
862 const size_t res_pubkey_offset
= TPM_RESPONSE_HEADER_LENGTH
;
863 uint8_t request
[sizeof(command
) + TPM_REQUEST_AUTH_LENGTH
];
864 uint8_t response
[TPM_RESPONSE_HEADER_LENGTH
+ TPM_PUBKEY_MAX_LENGTH
865 + TPM_RESPONSE_AUTH_LENGTH
];
866 size_t response_length
= sizeof(response
);
869 if (!oiap_session
.valid
) {
870 err
= tpm_oiap(NULL
);
874 if (pack_byte_string(request
, sizeof(request
), "sdd",
875 0, command
, sizeof(command
),
877 (uint32_t)(sizeof(command
)
878 + TPM_REQUEST_AUTH_LENGTH
),
879 req_key_handle_offset
, key_handle
881 return TPM_LIB_ERROR
;
882 err
= create_request_auth(request
, sizeof(command
), 4, &oiap_session
,
883 request
+ sizeof(command
), usage_auth
);
886 err
= tpm_sendrecv_command(request
, response
, &response_length
);
888 if (err
== TPM_AUTHFAIL
)
889 oiap_session
.valid
= 0;
892 err
= verify_response_auth(0x00000021, response
,
893 response_length
- TPM_RESPONSE_AUTH_LENGTH
,
895 response
+ response_length
- TPM_RESPONSE_AUTH_LENGTH
,
901 if ((response_length
- TPM_RESPONSE_HEADER_LENGTH
902 - TPM_RESPONSE_AUTH_LENGTH
) > *pubkey_len
)
903 return TPM_LIB_ERROR
;
904 *pubkey_len
= response_length
- TPM_RESPONSE_HEADER_LENGTH
905 - TPM_RESPONSE_AUTH_LENGTH
;
906 memcpy(pubkey
, response
+ res_pubkey_offset
,
907 response_length
- TPM_RESPONSE_HEADER_LENGTH
908 - TPM_RESPONSE_AUTH_LENGTH
);
914 #endif /* CONFIG_TPM_AUTH_SESSIONS */