2 * Copyright (c) 2013 The Chromium OS Authors.
3 * Coypright (c) 2013 Guntermann & Drunck GmbH
5 * SPDX-License-Identifier: GPL-2.0+
11 #include <asm/unaligned.h>
12 #include <u-boot/sha1.h>
14 /* Internal error of TPM command library */
15 #define TPM_LIB_ERROR ((uint32_t)~0u)
17 /* Useful constants */
19 COMMAND_BUFFER_SIZE
= 256,
20 TPM_REQUEST_HEADER_LENGTH
= 10,
21 TPM_RESPONSE_HEADER_LENGTH
= 10,
22 PCR_DIGEST_LENGTH
= 20,
24 TPM_REQUEST_AUTH_LENGTH
= 45,
25 TPM_RESPONSE_AUTH_LENGTH
= 41,
26 /* some max lengths, valid for RSA keys <= 2048 bits */
27 TPM_KEY12_MAX_LENGTH
= 618,
28 TPM_PUBKEY_MAX_LENGTH
= 288,
31 #ifdef CONFIG_TPM_AUTH_SESSIONS
34 #error "TPM_AUTH_SESSIONS require SHA1 to be configured, too"
35 #endif /* !CONFIG_SHA1 */
40 uint8_t nonce_even
[DIGEST_LENGTH
];
41 uint8_t nonce_odd
[DIGEST_LENGTH
];
44 static struct session_data oiap_session
= {0, };
46 #endif /* CONFIG_TPM_AUTH_SESSIONS */
49 * Pack data into a byte string. The data types are specified in
50 * the format string: 'b' means unsigned byte, 'w' unsigned word,
51 * 'd' unsigned double word, and 's' byte string. The data are a
52 * series of offsets and values (for type byte string there are also
53 * lengths). The data values are packed into the byte string
54 * sequentially, and so a latter value could over-write a former
57 * @param str output string
58 * @param size size of output string
59 * @param format format string
60 * @param ... data points
61 * @return 0 on success, non-0 on error
63 int pack_byte_string(uint8_t *str
, size_t size
, const char *format
, ...)
66 size_t offset
= 0, length
= 0;
70 va_start(args
, format
);
71 for (; *format
; format
++) {
74 offset
= va_arg(args
, size_t);
75 value
= va_arg(args
, int);
79 offset
= va_arg(args
, size_t);
80 value
= va_arg(args
, int);
84 offset
= va_arg(args
, size_t);
85 value
= va_arg(args
, uint32_t);
89 offset
= va_arg(args
, size_t);
90 data
= va_arg(args
, uint8_t *);
91 length
= va_arg(args
, uint32_t);
94 debug("Couldn't recognize format string\n");
98 if (offset
+ length
> size
)
106 put_unaligned_be16(value
, str
+ offset
);
109 put_unaligned_be32(value
, str
+ offset
);
112 memcpy(str
+ offset
, data
, length
);
122 * Unpack data from a byte string. The data types are specified in
123 * the format string: 'b' means unsigned byte, 'w' unsigned word,
124 * 'd' unsigned double word, and 's' byte string. The data are a
125 * series of offsets and pointers (for type byte string there are also
128 * @param str output string
129 * @param size size of output string
130 * @param format format string
131 * @param ... data points
132 * @return 0 on success, non-0 on error
134 int unpack_byte_string(const uint8_t *str
, size_t size
, const char *format
, ...)
137 size_t offset
= 0, length
= 0;
138 uint8_t *ptr8
= NULL
;
139 uint16_t *ptr16
= NULL
;
140 uint32_t *ptr32
= NULL
;
142 va_start(args
, format
);
143 for (; *format
; format
++) {
146 offset
= va_arg(args
, size_t);
147 ptr8
= va_arg(args
, uint8_t *);
151 offset
= va_arg(args
, size_t);
152 ptr16
= va_arg(args
, uint16_t *);
156 offset
= va_arg(args
, size_t);
157 ptr32
= va_arg(args
, uint32_t *);
161 offset
= va_arg(args
, size_t);
162 ptr8
= va_arg(args
, uint8_t *);
163 length
= va_arg(args
, uint32_t);
166 debug("Couldn't recognize format string\n");
170 if (offset
+ length
> size
)
178 *ptr16
= get_unaligned_be16(str
+ offset
);
181 *ptr32
= get_unaligned_be32(str
+ offset
);
184 memcpy(ptr8
, str
+ offset
, length
);
194 * Get TPM command size.
196 * @param command byte string of TPM command
197 * @return command size of the TPM command
199 static uint32_t tpm_command_size(const void *command
)
201 const size_t command_size_offset
= 2;
202 return get_unaligned_be32(command
+ command_size_offset
);
206 * Get TPM response return code, which is one of TPM_RESULT values.
208 * @param response byte string of TPM response
209 * @return return code of the TPM response
211 static uint32_t tpm_return_code(const void *response
)
213 const size_t return_code_offset
= 6;
214 return get_unaligned_be32(response
+ return_code_offset
);
218 * Send a TPM command and return response's return code, and optionally
219 * return response to caller.
221 * @param command byte string of TPM command
222 * @param response output buffer for TPM response, or NULL if the
223 * caller does not care about it
224 * @param size_ptr output buffer size (input parameter) and TPM
225 * response length (output parameter); this parameter
227 * @return return code of the TPM response
229 static uint32_t tpm_sendrecv_command(const void *command
,
230 void *response
, size_t *size_ptr
)
234 uint8_t response_buffer
[COMMAND_BUFFER_SIZE
];
235 size_t response_length
;
239 response_length
= *size_ptr
;
241 response
= response_buffer
;
242 response_length
= sizeof(response_buffer
);
245 ret
= uclass_first_device_err(UCLASS_TPM
, &dev
);
248 err
= tpm_xfer(dev
, command
, tpm_command_size(command
),
249 response
, &response_length
);
252 return TPM_LIB_ERROR
;
254 *size_ptr
= response_length
;
256 return tpm_return_code(response
);
264 err
= uclass_first_device_err(UCLASS_TPM
, &dev
);
267 return tpm_open(dev
);
270 uint32_t tpm_startup(enum tpm_startup_type mode
)
272 const uint8_t command
[12] = {
273 0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0x99, 0x0, 0x0,
275 const size_t mode_offset
= 10;
276 uint8_t buf
[COMMAND_BUFFER_SIZE
];
278 if (pack_byte_string(buf
, sizeof(buf
), "sw",
279 0, command
, sizeof(command
),
281 return TPM_LIB_ERROR
;
283 return tpm_sendrecv_command(buf
, NULL
, NULL
);
286 uint32_t tpm_self_test_full(void)
288 const uint8_t command
[10] = {
289 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x50,
291 return tpm_sendrecv_command(command
, NULL
, NULL
);
294 uint32_t tpm_continue_self_test(void)
296 const uint8_t command
[10] = {
297 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x53,
299 return tpm_sendrecv_command(command
, NULL
, NULL
);
302 uint32_t tpm_nv_define_space(uint32_t index
, uint32_t perm
, uint32_t size
)
304 const uint8_t command
[101] = {
305 0x0, 0xc1, /* TPM_TAG */
306 0x0, 0x0, 0x0, 0x65, /* parameter size */
307 0x0, 0x0, 0x0, 0xcc, /* TPM_COMMAND_CODE */
308 /* TPM_NV_DATA_PUBLIC->... */
309 0x0, 0x18, /* ...->TPM_STRUCTURE_TAG */
310 0, 0, 0, 0, /* ...->TPM_NV_INDEX */
311 /* TPM_NV_DATA_PUBLIC->TPM_PCR_INFO_SHORT */
315 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
316 /* TPM_NV_DATA_PUBLIC->TPM_PCR_INFO_SHORT */
320 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
321 /* TPM_NV_ATTRIBUTES->... */
322 0x0, 0x17, /* ...->TPM_STRUCTURE_TAG */
323 0, 0, 0, 0, /* ...->attributes */
324 /* End of TPM_NV_ATTRIBUTES */
325 0, /* bReadSTClear */
326 0, /* bWriteSTClear */
327 0, /* bWriteDefine */
328 0, 0, 0, 0, /* size */
330 const size_t index_offset
= 12;
331 const size_t perm_offset
= 70;
332 const size_t size_offset
= 77;
333 uint8_t buf
[COMMAND_BUFFER_SIZE
];
335 if (pack_byte_string(buf
, sizeof(buf
), "sddd",
336 0, command
, sizeof(command
),
340 return TPM_LIB_ERROR
;
342 return tpm_sendrecv_command(buf
, NULL
, NULL
);
345 uint32_t tpm_nv_read_value(uint32_t index
, void *data
, uint32_t count
)
347 const uint8_t command
[22] = {
348 0x0, 0xc1, 0x0, 0x0, 0x0, 0x16, 0x0, 0x0, 0x0, 0xcf,
350 const size_t index_offset
= 10;
351 const size_t length_offset
= 18;
352 const size_t data_size_offset
= 10;
353 const size_t data_offset
= 14;
354 uint8_t buf
[COMMAND_BUFFER_SIZE
], response
[COMMAND_BUFFER_SIZE
];
355 size_t response_length
= sizeof(response
);
359 if (pack_byte_string(buf
, sizeof(buf
), "sdd",
360 0, command
, sizeof(command
),
362 length_offset
, count
))
363 return TPM_LIB_ERROR
;
364 err
= tpm_sendrecv_command(buf
, response
, &response_length
);
367 if (unpack_byte_string(response
, response_length
, "d",
368 data_size_offset
, &data_size
))
369 return TPM_LIB_ERROR
;
370 if (data_size
> count
)
371 return TPM_LIB_ERROR
;
372 if (unpack_byte_string(response
, response_length
, "s",
373 data_offset
, data
, data_size
))
374 return TPM_LIB_ERROR
;
379 uint32_t tpm_nv_write_value(uint32_t index
, const void *data
, uint32_t length
)
381 const uint8_t command
[256] = {
382 0x0, 0xc1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xcd,
384 const size_t command_size_offset
= 2;
385 const size_t index_offset
= 10;
386 const size_t length_offset
= 18;
387 const size_t data_offset
= 22;
388 const size_t write_info_size
= 12;
389 const uint32_t total_length
=
390 TPM_REQUEST_HEADER_LENGTH
+ write_info_size
+ length
;
391 uint8_t buf
[COMMAND_BUFFER_SIZE
], response
[COMMAND_BUFFER_SIZE
];
392 size_t response_length
= sizeof(response
);
395 if (pack_byte_string(buf
, sizeof(buf
), "sddds",
396 0, command
, sizeof(command
),
397 command_size_offset
, total_length
,
399 length_offset
, length
,
400 data_offset
, data
, length
))
401 return TPM_LIB_ERROR
;
402 err
= tpm_sendrecv_command(buf
, response
, &response_length
);
409 uint32_t tpm_extend(uint32_t index
, const void *in_digest
, void *out_digest
)
411 const uint8_t command
[34] = {
412 0x0, 0xc1, 0x0, 0x0, 0x0, 0x22, 0x0, 0x0, 0x0, 0x14,
414 const size_t index_offset
= 10;
415 const size_t in_digest_offset
= 14;
416 const size_t out_digest_offset
= 10;
417 uint8_t buf
[COMMAND_BUFFER_SIZE
];
418 uint8_t response
[TPM_RESPONSE_HEADER_LENGTH
+ PCR_DIGEST_LENGTH
];
419 size_t response_length
= sizeof(response
);
422 if (pack_byte_string(buf
, sizeof(buf
), "sds",
423 0, command
, sizeof(command
),
425 in_digest_offset
, in_digest
,
427 return TPM_LIB_ERROR
;
428 err
= tpm_sendrecv_command(buf
, response
, &response_length
);
432 if (unpack_byte_string(response
, response_length
, "s",
433 out_digest_offset
, out_digest
,
435 return TPM_LIB_ERROR
;
440 uint32_t tpm_pcr_read(uint32_t index
, void *data
, size_t count
)
442 const uint8_t command
[14] = {
443 0x0, 0xc1, 0x0, 0x0, 0x0, 0xe, 0x0, 0x0, 0x0, 0x15,
445 const size_t index_offset
= 10;
446 const size_t out_digest_offset
= 10;
447 uint8_t buf
[COMMAND_BUFFER_SIZE
], response
[COMMAND_BUFFER_SIZE
];
448 size_t response_length
= sizeof(response
);
451 if (count
< PCR_DIGEST_LENGTH
)
452 return TPM_LIB_ERROR
;
454 if (pack_byte_string(buf
, sizeof(buf
), "sd",
455 0, command
, sizeof(command
),
456 index_offset
, index
))
457 return TPM_LIB_ERROR
;
458 err
= tpm_sendrecv_command(buf
, response
, &response_length
);
461 if (unpack_byte_string(response
, response_length
, "s",
462 out_digest_offset
, data
, PCR_DIGEST_LENGTH
))
463 return TPM_LIB_ERROR
;
468 uint32_t tpm_tsc_physical_presence(uint16_t presence
)
470 const uint8_t command
[12] = {
471 0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x40, 0x0, 0x0, 0xa, 0x0, 0x0,
473 const size_t presence_offset
= 10;
474 uint8_t buf
[COMMAND_BUFFER_SIZE
];
476 if (pack_byte_string(buf
, sizeof(buf
), "sw",
477 0, command
, sizeof(command
),
478 presence_offset
, presence
))
479 return TPM_LIB_ERROR
;
481 return tpm_sendrecv_command(buf
, NULL
, NULL
);
484 uint32_t tpm_read_pubek(void *data
, size_t count
)
486 const uint8_t command
[30] = {
487 0x0, 0xc1, 0x0, 0x0, 0x0, 0x1e, 0x0, 0x0, 0x0, 0x7c,
489 const size_t response_size_offset
= 2;
490 const size_t data_offset
= 10;
491 const size_t header_and_checksum_size
= TPM_RESPONSE_HEADER_LENGTH
+ 20;
492 uint8_t response
[COMMAND_BUFFER_SIZE
+ TPM_PUBEK_SIZE
];
493 size_t response_length
= sizeof(response
);
497 err
= tpm_sendrecv_command(command
, response
, &response_length
);
500 if (unpack_byte_string(response
, response_length
, "d",
501 response_size_offset
, &data_size
))
502 return TPM_LIB_ERROR
;
503 if (data_size
< header_and_checksum_size
)
504 return TPM_LIB_ERROR
;
505 data_size
-= header_and_checksum_size
;
506 if (data_size
> count
)
507 return TPM_LIB_ERROR
;
508 if (unpack_byte_string(response
, response_length
, "s",
509 data_offset
, data
, data_size
))
510 return TPM_LIB_ERROR
;
515 uint32_t tpm_force_clear(void)
517 const uint8_t command
[10] = {
518 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x5d,
521 return tpm_sendrecv_command(command
, NULL
, NULL
);
524 uint32_t tpm_physical_enable(void)
526 const uint8_t command
[10] = {
527 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x6f,
530 return tpm_sendrecv_command(command
, NULL
, NULL
);
533 uint32_t tpm_physical_disable(void)
535 const uint8_t command
[10] = {
536 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x70,
539 return tpm_sendrecv_command(command
, NULL
, NULL
);
542 uint32_t tpm_physical_set_deactivated(uint8_t state
)
544 const uint8_t command
[11] = {
545 0x0, 0xc1, 0x0, 0x0, 0x0, 0xb, 0x0, 0x0, 0x0, 0x72,
547 const size_t state_offset
= 10;
548 uint8_t buf
[COMMAND_BUFFER_SIZE
];
550 if (pack_byte_string(buf
, sizeof(buf
), "sb",
551 0, command
, sizeof(command
),
552 state_offset
, state
))
553 return TPM_LIB_ERROR
;
555 return tpm_sendrecv_command(buf
, NULL
, NULL
);
558 uint32_t tpm_get_capability(uint32_t cap_area
, uint32_t sub_cap
,
559 void *cap
, size_t count
)
561 const uint8_t command
[22] = {
562 0x0, 0xc1, /* TPM_TAG */
563 0x0, 0x0, 0x0, 0x16, /* parameter size */
564 0x0, 0x0, 0x0, 0x65, /* TPM_COMMAND_CODE */
565 0x0, 0x0, 0x0, 0x0, /* TPM_CAPABILITY_AREA */
566 0x0, 0x0, 0x0, 0x4, /* subcap size */
567 0x0, 0x0, 0x0, 0x0, /* subcap value */
569 const size_t cap_area_offset
= 10;
570 const size_t sub_cap_offset
= 18;
571 const size_t cap_offset
= 14;
572 const size_t cap_size_offset
= 10;
573 uint8_t buf
[COMMAND_BUFFER_SIZE
], response
[COMMAND_BUFFER_SIZE
];
574 size_t response_length
= sizeof(response
);
578 if (pack_byte_string(buf
, sizeof(buf
), "sdd",
579 0, command
, sizeof(command
),
580 cap_area_offset
, cap_area
,
581 sub_cap_offset
, sub_cap
))
582 return TPM_LIB_ERROR
;
583 err
= tpm_sendrecv_command(buf
, response
, &response_length
);
586 if (unpack_byte_string(response
, response_length
, "d",
587 cap_size_offset
, &cap_size
))
588 return TPM_LIB_ERROR
;
589 if (cap_size
> response_length
|| cap_size
> count
)
590 return TPM_LIB_ERROR
;
591 if (unpack_byte_string(response
, response_length
, "s",
592 cap_offset
, cap
, cap_size
))
593 return TPM_LIB_ERROR
;
598 uint32_t tpm_get_permanent_flags(struct tpm_permanent_flags
*pflags
)
600 const uint8_t command
[22] = {
601 0x0, 0xc1, /* TPM_TAG */
602 0x0, 0x0, 0x0, 0x16, /* parameter size */
603 0x0, 0x0, 0x0, 0x65, /* TPM_COMMAND_CODE */
604 0x0, 0x0, 0x0, 0x4, /* TPM_CAP_FLAG_PERM */
605 0x0, 0x0, 0x0, 0x4, /* subcap size */
606 0x0, 0x0, 0x1, 0x8, /* subcap value */
608 uint8_t response
[COMMAND_BUFFER_SIZE
];
609 size_t response_length
= sizeof(response
);
612 err
= tpm_sendrecv_command(command
, response
, &response_length
);
615 memcpy(pflags
, response
+ TPM_HEADER_SIZE
, sizeof(*pflags
));
620 uint32_t tpm_get_permissions(uint32_t index
, uint32_t *perm
)
622 const uint8_t command
[22] = {
623 0x0, 0xc1, /* TPM_TAG */
624 0x0, 0x0, 0x0, 0x16, /* parameter size */
625 0x0, 0x0, 0x0, 0x65, /* TPM_COMMAND_CODE */
629 const size_t index_offset
= 18;
630 const size_t perm_offset
= 60;
631 uint8_t buf
[COMMAND_BUFFER_SIZE
], response
[COMMAND_BUFFER_SIZE
];
632 size_t response_length
= sizeof(response
);
635 if (pack_byte_string(buf
, sizeof(buf
), "d", 0, command
, sizeof(command
),
636 index_offset
, index
))
637 return TPM_LIB_ERROR
;
638 err
= tpm_sendrecv_command(buf
, response
, &response_length
);
641 if (unpack_byte_string(response
, response_length
, "d",
643 return TPM_LIB_ERROR
;
648 #ifdef CONFIG_TPM_FLUSH_RESOURCES
649 uint32_t tpm_flush_specific(uint32_t key_handle
, uint32_t resource_type
)
651 const uint8_t command
[18] = {
652 0x00, 0xc1, /* TPM_TAG */
653 0x00, 0x00, 0x00, 0x12, /* parameter size */
654 0x00, 0x00, 0x00, 0xba, /* TPM_COMMAND_CODE */
655 0x00, 0x00, 0x00, 0x00, /* key handle */
656 0x00, 0x00, 0x00, 0x00, /* resource type */
658 const size_t key_handle_offset
= 10;
659 const size_t resource_type_offset
= 14;
660 uint8_t buf
[COMMAND_BUFFER_SIZE
], response
[COMMAND_BUFFER_SIZE
];
661 size_t response_length
= sizeof(response
);
664 if (pack_byte_string(buf
, sizeof(buf
), "sdd",
665 0, command
, sizeof(command
),
666 key_handle_offset
, key_handle
,
667 resource_type_offset
, resource_type
))
668 return TPM_LIB_ERROR
;
670 err
= tpm_sendrecv_command(buf
, response
, &response_length
);
675 #endif /* CONFIG_TPM_FLUSH_RESOURCES */
677 #ifdef CONFIG_TPM_AUTH_SESSIONS
680 * Fill an authentication block in a request.
681 * This func can create the first as well as the second auth block (for
682 * double authorized commands).
684 * @param request pointer to the request (w/ uninitialised auth data)
685 * @param request_len0 length of the request without auth data
686 * @param handles_len length of the handles area in request
687 * @param auth_session pointer to the (valid) auth session to be used
688 * @param request_auth pointer to the auth block of the request to be filled
689 * @param auth authentication data (HMAC key)
691 static uint32_t create_request_auth(const void *request
, size_t request_len0
,
693 struct session_data
*auth_session
,
694 void *request_auth
, const void *auth
)
696 uint8_t hmac_data
[DIGEST_LENGTH
* 3 + 1];
697 sha1_context hash_ctx
;
698 const size_t command_code_offset
= 6;
699 const size_t auth_nonce_odd_offset
= 4;
700 const size_t auth_continue_offset
= 24;
701 const size_t auth_auth_offset
= 25;
703 if (!auth_session
|| !auth_session
->valid
)
704 return TPM_LIB_ERROR
;
706 sha1_starts(&hash_ctx
);
707 sha1_update(&hash_ctx
, request
+ command_code_offset
, 4);
708 if (request_len0
> TPM_REQUEST_HEADER_LENGTH
+ handles_len
)
709 sha1_update(&hash_ctx
,
710 request
+ TPM_REQUEST_HEADER_LENGTH
+ handles_len
,
711 request_len0
- TPM_REQUEST_HEADER_LENGTH
713 sha1_finish(&hash_ctx
, hmac_data
);
715 sha1_starts(&hash_ctx
);
716 sha1_update(&hash_ctx
, auth_session
->nonce_odd
, DIGEST_LENGTH
);
717 sha1_update(&hash_ctx
, hmac_data
, sizeof(hmac_data
));
718 sha1_finish(&hash_ctx
, auth_session
->nonce_odd
);
720 if (pack_byte_string(request_auth
, TPM_REQUEST_AUTH_LENGTH
, "dsb",
721 0, auth_session
->handle
,
722 auth_nonce_odd_offset
, auth_session
->nonce_odd
,
724 auth_continue_offset
, 1))
725 return TPM_LIB_ERROR
;
726 if (pack_byte_string(hmac_data
, sizeof(hmac_data
), "ss",
728 auth_session
->nonce_even
,
731 request_auth
+ auth_nonce_odd_offset
,
733 return TPM_LIB_ERROR
;
734 sha1_hmac(auth
, DIGEST_LENGTH
, hmac_data
, sizeof(hmac_data
),
735 request_auth
+ auth_auth_offset
);
741 * Verify an authentication block in a response.
742 * Since this func updates the nonce_even in the session data it has to be
743 * called when receiving a succesfull AUTH response.
744 * This func can verify the first as well as the second auth block (for
745 * double authorized commands).
747 * @param command_code command code of the request
748 * @param response pointer to the request (w/ uninitialised auth data)
749 * @param handles_len length of the handles area in response
750 * @param auth_session pointer to the (valid) auth session to be used
751 * @param response_auth pointer to the auth block of the response to be verified
752 * @param auth authentication data (HMAC key)
754 static uint32_t verify_response_auth(uint32_t command_code
,
755 const void *response
, size_t response_len0
,
757 struct session_data
*auth_session
,
758 const void *response_auth
, const void *auth
)
760 uint8_t hmac_data
[DIGEST_LENGTH
* 3 + 1];
761 uint8_t computed_auth
[DIGEST_LENGTH
];
762 sha1_context hash_ctx
;
763 const size_t return_code_offset
= 6;
764 const size_t auth_continue_offset
= 20;
765 const size_t auth_auth_offset
= 21;
766 uint8_t auth_continue
;
768 if (!auth_session
|| !auth_session
->valid
)
770 if (pack_byte_string(hmac_data
, sizeof(hmac_data
), "d",
772 return TPM_LIB_ERROR
;
773 if (response_len0
< TPM_RESPONSE_HEADER_LENGTH
)
774 return TPM_LIB_ERROR
;
776 sha1_starts(&hash_ctx
);
777 sha1_update(&hash_ctx
, response
+ return_code_offset
, 4);
778 sha1_update(&hash_ctx
, hmac_data
, 4);
779 if (response_len0
> TPM_RESPONSE_HEADER_LENGTH
+ handles_len
)
780 sha1_update(&hash_ctx
,
781 response
+ TPM_RESPONSE_HEADER_LENGTH
+ handles_len
,
782 response_len0
- TPM_RESPONSE_HEADER_LENGTH
784 sha1_finish(&hash_ctx
, hmac_data
);
786 memcpy(auth_session
->nonce_even
, response_auth
, DIGEST_LENGTH
);
787 auth_continue
= ((uint8_t *)response_auth
)[auth_continue_offset
];
788 if (pack_byte_string(hmac_data
, sizeof(hmac_data
), "ssb",
793 auth_session
->nonce_odd
,
797 return TPM_LIB_ERROR
;
799 sha1_hmac(auth
, DIGEST_LENGTH
, hmac_data
, sizeof(hmac_data
),
802 if (memcmp(computed_auth
, response_auth
+ auth_auth_offset
,
810 uint32_t tpm_terminate_auth_session(uint32_t auth_handle
)
812 const uint8_t command
[18] = {
813 0x00, 0xc1, /* TPM_TAG */
814 0x00, 0x00, 0x00, 0x00, /* parameter size */
815 0x00, 0x00, 0x00, 0xba, /* TPM_COMMAND_CODE */
816 0x00, 0x00, 0x00, 0x00, /* TPM_HANDLE */
817 0x00, 0x00, 0x00, 0x02, /* TPM_RESSOURCE_TYPE */
819 const size_t req_handle_offset
= TPM_REQUEST_HEADER_LENGTH
;
820 uint8_t request
[COMMAND_BUFFER_SIZE
];
822 if (pack_byte_string(request
, sizeof(request
), "sd",
823 0, command
, sizeof(command
),
824 req_handle_offset
, auth_handle
))
825 return TPM_LIB_ERROR
;
826 if (oiap_session
.valid
&& oiap_session
.handle
== auth_handle
)
827 oiap_session
.valid
= 0;
829 return tpm_sendrecv_command(request
, NULL
, NULL
);
832 uint32_t tpm_end_oiap(void)
834 uint32_t err
= TPM_SUCCESS
;
835 if (oiap_session
.valid
)
836 err
= tpm_terminate_auth_session(oiap_session
.handle
);
840 uint32_t tpm_oiap(uint32_t *auth_handle
)
842 const uint8_t command
[10] = {
843 0x00, 0xc1, /* TPM_TAG */
844 0x00, 0x00, 0x00, 0x0a, /* parameter size */
845 0x00, 0x00, 0x00, 0x0a, /* TPM_COMMAND_CODE */
847 const size_t res_auth_handle_offset
= TPM_RESPONSE_HEADER_LENGTH
;
848 const size_t res_nonce_even_offset
= TPM_RESPONSE_HEADER_LENGTH
+ 4;
849 uint8_t response
[COMMAND_BUFFER_SIZE
];
850 size_t response_length
= sizeof(response
);
853 if (oiap_session
.valid
)
854 tpm_terminate_auth_session(oiap_session
.handle
);
856 err
= tpm_sendrecv_command(command
, response
, &response_length
);
859 if (unpack_byte_string(response
, response_length
, "ds",
860 res_auth_handle_offset
, &oiap_session
.handle
,
861 res_nonce_even_offset
, &oiap_session
.nonce_even
,
862 (uint32_t)DIGEST_LENGTH
))
863 return TPM_LIB_ERROR
;
864 oiap_session
.valid
= 1;
866 *auth_handle
= oiap_session
.handle
;
870 uint32_t tpm_load_key2_oiap(uint32_t parent_handle
,
871 const void *key
, size_t key_length
,
872 const void *parent_key_usage_auth
,
873 uint32_t *key_handle
)
875 const uint8_t command
[14] = {
876 0x00, 0xc2, /* TPM_TAG */
877 0x00, 0x00, 0x00, 0x00, /* parameter size */
878 0x00, 0x00, 0x00, 0x41, /* TPM_COMMAND_CODE */
879 0x00, 0x00, 0x00, 0x00, /* parent handle */
881 const size_t req_size_offset
= 2;
882 const size_t req_parent_handle_offset
= TPM_REQUEST_HEADER_LENGTH
;
883 const size_t req_key_offset
= TPM_REQUEST_HEADER_LENGTH
+ 4;
884 const size_t res_handle_offset
= TPM_RESPONSE_HEADER_LENGTH
;
885 uint8_t request
[sizeof(command
) + TPM_KEY12_MAX_LENGTH
886 + TPM_REQUEST_AUTH_LENGTH
];
887 uint8_t response
[COMMAND_BUFFER_SIZE
];
888 size_t response_length
= sizeof(response
);
891 if (!oiap_session
.valid
) {
892 err
= tpm_oiap(NULL
);
896 if (pack_byte_string(request
, sizeof(request
), "sdds",
897 0, command
, sizeof(command
),
899 sizeof(command
) + key_length
900 + TPM_REQUEST_AUTH_LENGTH
,
901 req_parent_handle_offset
, parent_handle
,
902 req_key_offset
, key
, key_length
904 return TPM_LIB_ERROR
;
906 err
= create_request_auth(request
, sizeof(command
) + key_length
, 4,
908 request
+ sizeof(command
) + key_length
,
909 parent_key_usage_auth
);
912 err
= tpm_sendrecv_command(request
, response
, &response_length
);
914 if (err
== TPM_AUTHFAIL
)
915 oiap_session
.valid
= 0;
919 err
= verify_response_auth(0x00000041, response
,
920 response_length
- TPM_RESPONSE_AUTH_LENGTH
,
922 response
+ response_length
- TPM_RESPONSE_AUTH_LENGTH
,
923 parent_key_usage_auth
);
928 if (unpack_byte_string(response
, response_length
, "d",
929 res_handle_offset
, key_handle
))
930 return TPM_LIB_ERROR
;
936 uint32_t tpm_get_pub_key_oiap(uint32_t key_handle
, const void *usage_auth
,
937 void *pubkey
, size_t *pubkey_len
)
939 const uint8_t command
[14] = {
940 0x00, 0xc2, /* TPM_TAG */
941 0x00, 0x00, 0x00, 0x00, /* parameter size */
942 0x00, 0x00, 0x00, 0x21, /* TPM_COMMAND_CODE */
943 0x00, 0x00, 0x00, 0x00, /* key handle */
945 const size_t req_size_offset
= 2;
946 const size_t req_key_handle_offset
= TPM_REQUEST_HEADER_LENGTH
;
947 const size_t res_pubkey_offset
= TPM_RESPONSE_HEADER_LENGTH
;
948 uint8_t request
[sizeof(command
) + TPM_REQUEST_AUTH_LENGTH
];
949 uint8_t response
[TPM_RESPONSE_HEADER_LENGTH
+ TPM_PUBKEY_MAX_LENGTH
950 + TPM_RESPONSE_AUTH_LENGTH
];
951 size_t response_length
= sizeof(response
);
954 if (!oiap_session
.valid
) {
955 err
= tpm_oiap(NULL
);
959 if (pack_byte_string(request
, sizeof(request
), "sdd",
960 0, command
, sizeof(command
),
962 (uint32_t)(sizeof(command
)
963 + TPM_REQUEST_AUTH_LENGTH
),
964 req_key_handle_offset
, key_handle
966 return TPM_LIB_ERROR
;
967 err
= create_request_auth(request
, sizeof(command
), 4, &oiap_session
,
968 request
+ sizeof(command
), usage_auth
);
971 err
= tpm_sendrecv_command(request
, response
, &response_length
);
973 if (err
== TPM_AUTHFAIL
)
974 oiap_session
.valid
= 0;
977 err
= verify_response_auth(0x00000021, response
,
978 response_length
- TPM_RESPONSE_AUTH_LENGTH
,
980 response
+ response_length
- TPM_RESPONSE_AUTH_LENGTH
,
986 if ((response_length
- TPM_RESPONSE_HEADER_LENGTH
987 - TPM_RESPONSE_AUTH_LENGTH
) > *pubkey_len
)
988 return TPM_LIB_ERROR
;
989 *pubkey_len
= response_length
- TPM_RESPONSE_HEADER_LENGTH
990 - TPM_RESPONSE_AUTH_LENGTH
;
991 memcpy(pubkey
, response
+ res_pubkey_offset
,
992 response_length
- TPM_RESPONSE_HEADER_LENGTH
993 - TPM_RESPONSE_AUTH_LENGTH
);
999 #endif /* CONFIG_TPM_AUTH_SESSIONS */