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
) {
108 put_unaligned_be16(value
, str
+ offset
);
111 put_unaligned_be32(value
, str
+ offset
);
114 memcpy(str
+ offset
, data
, length
);
124 * Unpack data from a byte string. The data types are specified in
125 * the format string: 'b' means unsigned byte, 'w' unsigned word,
126 * 'd' unsigned double word, and 's' byte string. The data are a
127 * series of offsets and pointers (for type byte string there are also
130 * @param str output string
131 * @param size size of output string
132 * @param format format string
133 * @param ... data points
134 * @return 0 on success, non-0 on error
136 int unpack_byte_string(const uint8_t *str
, size_t size
, const char *format
, ...)
139 size_t offset
= 0, length
= 0;
140 uint8_t *ptr8
= NULL
;
141 uint16_t *ptr16
= NULL
;
142 uint32_t *ptr32
= NULL
;
144 va_start(args
, format
);
145 for (; *format
; format
++) {
148 offset
= va_arg(args
, size_t);
149 ptr8
= va_arg(args
, uint8_t *);
153 offset
= va_arg(args
, size_t);
154 ptr16
= va_arg(args
, uint16_t *);
158 offset
= va_arg(args
, size_t);
159 ptr32
= va_arg(args
, uint32_t *);
163 offset
= va_arg(args
, size_t);
164 ptr8
= va_arg(args
, uint8_t *);
165 length
= va_arg(args
, uint32_t);
169 debug("Couldn't recognize format string\n");
173 if (offset
+ length
> size
)
181 *ptr16
= get_unaligned_be16(str
+ offset
);
184 *ptr32
= get_unaligned_be32(str
+ offset
);
187 memcpy(ptr8
, str
+ offset
, length
);
197 * Get TPM command size.
199 * @param command byte string of TPM command
200 * @return command size of the TPM command
202 static uint32_t tpm_command_size(const void *command
)
204 const size_t command_size_offset
= 2;
205 return get_unaligned_be32(command
+ command_size_offset
);
209 * Get TPM response return code, which is one of TPM_RESULT values.
211 * @param response byte string of TPM response
212 * @return return code of the TPM response
214 static uint32_t tpm_return_code(const void *response
)
216 const size_t return_code_offset
= 6;
217 return get_unaligned_be32(response
+ return_code_offset
);
221 * Send a TPM command and return response's return code, and optionally
222 * return response to caller.
224 * @param command byte string of TPM command
225 * @param response output buffer for TPM response, or NULL if the
226 * caller does not care about it
227 * @param size_ptr output buffer size (input parameter) and TPM
228 * response length (output parameter); this parameter
230 * @return return code of the TPM response
232 static uint32_t tpm_sendrecv_command(const void *command
,
233 void *response
, size_t *size_ptr
)
237 uint8_t response_buffer
[COMMAND_BUFFER_SIZE
];
238 size_t response_length
;
241 response_length
= *size_ptr
;
243 response
= response_buffer
;
244 response_length
= sizeof(response_buffer
);
247 ret
= uclass_first_device_err(UCLASS_TPM
, &dev
);
250 err
= tpm_xfer(dev
, command
, tpm_command_size(command
),
251 response
, &response_length
);
254 return TPM_LIB_ERROR
;
256 *size_ptr
= response_length
;
258 return tpm_return_code(response
);
266 err
= uclass_first_device_err(UCLASS_TPM
, &dev
);
269 return tpm_open(dev
);
272 uint32_t tpm_startup(enum tpm_startup_type mode
)
274 const uint8_t command
[12] = {
275 0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0x99, 0x0, 0x0,
277 const size_t mode_offset
= 10;
278 uint8_t buf
[COMMAND_BUFFER_SIZE
];
280 if (pack_byte_string(buf
, sizeof(buf
), "sw",
281 0, command
, sizeof(command
),
283 return TPM_LIB_ERROR
;
285 return tpm_sendrecv_command(buf
, NULL
, NULL
);
288 uint32_t tpm_self_test_full(void)
290 const uint8_t command
[10] = {
291 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x50,
293 return tpm_sendrecv_command(command
, NULL
, NULL
);
296 uint32_t tpm_continue_self_test(void)
298 const uint8_t command
[10] = {
299 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x53,
301 return tpm_sendrecv_command(command
, NULL
, NULL
);
304 uint32_t tpm_nv_define_space(uint32_t index
, uint32_t perm
, uint32_t size
)
306 const uint8_t command
[101] = {
307 0x0, 0xc1, /* TPM_TAG */
308 0x0, 0x0, 0x0, 0x65, /* parameter size */
309 0x0, 0x0, 0x0, 0xcc, /* TPM_COMMAND_CODE */
310 /* TPM_NV_DATA_PUBLIC->... */
311 0x0, 0x18, /* ...->TPM_STRUCTURE_TAG */
312 0, 0, 0, 0, /* ...->TPM_NV_INDEX */
313 /* TPM_NV_DATA_PUBLIC->TPM_PCR_INFO_SHORT */
317 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
318 /* TPM_NV_DATA_PUBLIC->TPM_PCR_INFO_SHORT */
322 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
323 /* TPM_NV_ATTRIBUTES->... */
324 0x0, 0x17, /* ...->TPM_STRUCTURE_TAG */
325 0, 0, 0, 0, /* ...->attributes */
326 /* End of TPM_NV_ATTRIBUTES */
327 0, /* bReadSTClear */
328 0, /* bWriteSTClear */
329 0, /* bWriteDefine */
330 0, 0, 0, 0, /* size */
332 const size_t index_offset
= 12;
333 const size_t perm_offset
= 70;
334 const size_t size_offset
= 77;
335 uint8_t buf
[COMMAND_BUFFER_SIZE
];
337 if (pack_byte_string(buf
, sizeof(buf
), "sddd",
338 0, command
, sizeof(command
),
342 return TPM_LIB_ERROR
;
344 return tpm_sendrecv_command(buf
, NULL
, NULL
);
347 uint32_t tpm_nv_read_value(uint32_t index
, void *data
, uint32_t count
)
349 const uint8_t command
[22] = {
350 0x0, 0xc1, 0x0, 0x0, 0x0, 0x16, 0x0, 0x0, 0x0, 0xcf,
352 const size_t index_offset
= 10;
353 const size_t length_offset
= 18;
354 const size_t data_size_offset
= 10;
355 const size_t data_offset
= 14;
356 uint8_t buf
[COMMAND_BUFFER_SIZE
], response
[COMMAND_BUFFER_SIZE
];
357 size_t response_length
= sizeof(response
);
361 if (pack_byte_string(buf
, sizeof(buf
), "sdd",
362 0, command
, sizeof(command
),
364 length_offset
, count
))
365 return TPM_LIB_ERROR
;
366 err
= tpm_sendrecv_command(buf
, response
, &response_length
);
369 if (unpack_byte_string(response
, response_length
, "d",
370 data_size_offset
, &data_size
))
371 return TPM_LIB_ERROR
;
372 if (data_size
> count
)
373 return TPM_LIB_ERROR
;
374 if (unpack_byte_string(response
, response_length
, "s",
375 data_offset
, data
, data_size
))
376 return TPM_LIB_ERROR
;
381 uint32_t tpm_nv_write_value(uint32_t index
, const void *data
, uint32_t length
)
383 const uint8_t command
[256] = {
384 0x0, 0xc1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xcd,
386 const size_t command_size_offset
= 2;
387 const size_t index_offset
= 10;
388 const size_t length_offset
= 18;
389 const size_t data_offset
= 22;
390 const size_t write_info_size
= 12;
391 const uint32_t total_length
=
392 TPM_REQUEST_HEADER_LENGTH
+ write_info_size
+ length
;
393 uint8_t buf
[COMMAND_BUFFER_SIZE
], response
[COMMAND_BUFFER_SIZE
];
394 size_t response_length
= sizeof(response
);
397 if (pack_byte_string(buf
, sizeof(buf
), "sddds",
398 0, command
, sizeof(command
),
399 command_size_offset
, total_length
,
401 length_offset
, length
,
402 data_offset
, data
, length
))
403 return TPM_LIB_ERROR
;
404 err
= tpm_sendrecv_command(buf
, response
, &response_length
);
411 uint32_t tpm_extend(uint32_t index
, const void *in_digest
, void *out_digest
)
413 const uint8_t command
[34] = {
414 0x0, 0xc1, 0x0, 0x0, 0x0, 0x22, 0x0, 0x0, 0x0, 0x14,
416 const size_t index_offset
= 10;
417 const size_t in_digest_offset
= 14;
418 const size_t out_digest_offset
= 10;
419 uint8_t buf
[COMMAND_BUFFER_SIZE
];
420 uint8_t response
[TPM_RESPONSE_HEADER_LENGTH
+ PCR_DIGEST_LENGTH
];
421 size_t response_length
= sizeof(response
);
424 if (pack_byte_string(buf
, sizeof(buf
), "sds",
425 0, command
, sizeof(command
),
427 in_digest_offset
, in_digest
,
429 return TPM_LIB_ERROR
;
430 err
= tpm_sendrecv_command(buf
, response
, &response_length
);
434 if (unpack_byte_string(response
, response_length
, "s",
435 out_digest_offset
, out_digest
,
437 return TPM_LIB_ERROR
;
442 uint32_t tpm_pcr_read(uint32_t index
, void *data
, size_t count
)
444 const uint8_t command
[14] = {
445 0x0, 0xc1, 0x0, 0x0, 0x0, 0xe, 0x0, 0x0, 0x0, 0x15,
447 const size_t index_offset
= 10;
448 const size_t out_digest_offset
= 10;
449 uint8_t buf
[COMMAND_BUFFER_SIZE
], response
[COMMAND_BUFFER_SIZE
];
450 size_t response_length
= sizeof(response
);
453 if (count
< PCR_DIGEST_LENGTH
)
454 return TPM_LIB_ERROR
;
456 if (pack_byte_string(buf
, sizeof(buf
), "sd",
457 0, command
, sizeof(command
),
458 index_offset
, index
))
459 return TPM_LIB_ERROR
;
460 err
= tpm_sendrecv_command(buf
, response
, &response_length
);
463 if (unpack_byte_string(response
, response_length
, "s",
464 out_digest_offset
, data
, PCR_DIGEST_LENGTH
))
465 return TPM_LIB_ERROR
;
470 uint32_t tpm_tsc_physical_presence(uint16_t presence
)
472 const uint8_t command
[12] = {
473 0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x40, 0x0, 0x0, 0xa, 0x0, 0x0,
475 const size_t presence_offset
= 10;
476 uint8_t buf
[COMMAND_BUFFER_SIZE
];
478 if (pack_byte_string(buf
, sizeof(buf
), "sw",
479 0, command
, sizeof(command
),
480 presence_offset
, presence
))
481 return TPM_LIB_ERROR
;
483 return tpm_sendrecv_command(buf
, NULL
, NULL
);
486 uint32_t tpm_read_pubek(void *data
, size_t count
)
488 const uint8_t command
[30] = {
489 0x0, 0xc1, 0x0, 0x0, 0x0, 0x1e, 0x0, 0x0, 0x0, 0x7c,
491 const size_t response_size_offset
= 2;
492 const size_t data_offset
= 10;
493 const size_t header_and_checksum_size
= TPM_RESPONSE_HEADER_LENGTH
+ 20;
494 uint8_t response
[COMMAND_BUFFER_SIZE
+ TPM_PUBEK_SIZE
];
495 size_t response_length
= sizeof(response
);
499 err
= tpm_sendrecv_command(command
, response
, &response_length
);
502 if (unpack_byte_string(response
, response_length
, "d",
503 response_size_offset
, &data_size
))
504 return TPM_LIB_ERROR
;
505 if (data_size
< header_and_checksum_size
)
506 return TPM_LIB_ERROR
;
507 data_size
-= header_and_checksum_size
;
508 if (data_size
> count
)
509 return TPM_LIB_ERROR
;
510 if (unpack_byte_string(response
, response_length
, "s",
511 data_offset
, data
, data_size
))
512 return TPM_LIB_ERROR
;
517 uint32_t tpm_force_clear(void)
519 const uint8_t command
[10] = {
520 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x5d,
523 return tpm_sendrecv_command(command
, NULL
, NULL
);
526 uint32_t tpm_physical_enable(void)
528 const uint8_t command
[10] = {
529 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x6f,
532 return tpm_sendrecv_command(command
, NULL
, NULL
);
535 uint32_t tpm_physical_disable(void)
537 const uint8_t command
[10] = {
538 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x70,
541 return tpm_sendrecv_command(command
, NULL
, NULL
);
544 uint32_t tpm_physical_set_deactivated(uint8_t state
)
546 const uint8_t command
[11] = {
547 0x0, 0xc1, 0x0, 0x0, 0x0, 0xb, 0x0, 0x0, 0x0, 0x72,
549 const size_t state_offset
= 10;
550 uint8_t buf
[COMMAND_BUFFER_SIZE
];
552 if (pack_byte_string(buf
, sizeof(buf
), "sb",
553 0, command
, sizeof(command
),
554 state_offset
, state
))
555 return TPM_LIB_ERROR
;
557 return tpm_sendrecv_command(buf
, NULL
, NULL
);
560 uint32_t tpm_get_capability(uint32_t cap_area
, uint32_t sub_cap
,
561 void *cap
, size_t count
)
563 const uint8_t command
[22] = {
564 0x0, 0xc1, /* TPM_TAG */
565 0x0, 0x0, 0x0, 0x16, /* parameter size */
566 0x0, 0x0, 0x0, 0x65, /* TPM_COMMAND_CODE */
567 0x0, 0x0, 0x0, 0x0, /* TPM_CAPABILITY_AREA */
568 0x0, 0x0, 0x0, 0x4, /* subcap size */
569 0x0, 0x0, 0x0, 0x0, /* subcap value */
571 const size_t cap_area_offset
= 10;
572 const size_t sub_cap_offset
= 18;
573 const size_t cap_offset
= 14;
574 const size_t cap_size_offset
= 10;
575 uint8_t buf
[COMMAND_BUFFER_SIZE
], response
[COMMAND_BUFFER_SIZE
];
576 size_t response_length
= sizeof(response
);
580 if (pack_byte_string(buf
, sizeof(buf
), "sdd",
581 0, command
, sizeof(command
),
582 cap_area_offset
, cap_area
,
583 sub_cap_offset
, sub_cap
))
584 return TPM_LIB_ERROR
;
585 err
= tpm_sendrecv_command(buf
, response
, &response_length
);
588 if (unpack_byte_string(response
, response_length
, "d",
589 cap_size_offset
, &cap_size
))
590 return TPM_LIB_ERROR
;
591 if (cap_size
> response_length
|| cap_size
> count
)
592 return TPM_LIB_ERROR
;
593 if (unpack_byte_string(response
, response_length
, "s",
594 cap_offset
, cap
, cap_size
))
595 return TPM_LIB_ERROR
;
600 uint32_t tpm_get_permanent_flags(struct tpm_permanent_flags
*pflags
)
602 const uint8_t command
[22] = {
603 0x0, 0xc1, /* TPM_TAG */
604 0x0, 0x0, 0x0, 0x16, /* parameter size */
605 0x0, 0x0, 0x0, 0x65, /* TPM_COMMAND_CODE */
606 0x0, 0x0, 0x0, 0x4, /* TPM_CAP_FLAG_PERM */
607 0x0, 0x0, 0x0, 0x4, /* subcap size */
608 0x0, 0x0, 0x1, 0x8, /* subcap value */
610 uint8_t response
[COMMAND_BUFFER_SIZE
];
611 size_t response_length
= sizeof(response
);
614 err
= tpm_sendrecv_command(command
, response
, &response_length
);
617 memcpy(pflags
, response
+ TPM_HEADER_SIZE
, sizeof(*pflags
));
622 uint32_t tpm_get_permissions(uint32_t index
, uint32_t *perm
)
624 const uint8_t command
[22] = {
625 0x0, 0xc1, /* TPM_TAG */
626 0x0, 0x0, 0x0, 0x16, /* parameter size */
627 0x0, 0x0, 0x0, 0x65, /* TPM_COMMAND_CODE */
631 const size_t index_offset
= 18;
632 const size_t perm_offset
= 60;
633 uint8_t buf
[COMMAND_BUFFER_SIZE
], response
[COMMAND_BUFFER_SIZE
];
634 size_t response_length
= sizeof(response
);
637 if (pack_byte_string(buf
, sizeof(buf
), "d", 0, command
, sizeof(command
),
638 index_offset
, index
))
639 return TPM_LIB_ERROR
;
640 err
= tpm_sendrecv_command(buf
, response
, &response_length
);
643 if (unpack_byte_string(response
, response_length
, "d",
645 return TPM_LIB_ERROR
;
650 #ifdef CONFIG_TPM_FLUSH_RESOURCES
651 uint32_t tpm_flush_specific(uint32_t key_handle
, uint32_t resource_type
)
653 const uint8_t command
[18] = {
654 0x00, 0xc1, /* TPM_TAG */
655 0x00, 0x00, 0x00, 0x12, /* parameter size */
656 0x00, 0x00, 0x00, 0xba, /* TPM_COMMAND_CODE */
657 0x00, 0x00, 0x00, 0x00, /* key handle */
658 0x00, 0x00, 0x00, 0x00, /* resource type */
660 const size_t key_handle_offset
= 10;
661 const size_t resource_type_offset
= 14;
662 uint8_t buf
[COMMAND_BUFFER_SIZE
], response
[COMMAND_BUFFER_SIZE
];
663 size_t response_length
= sizeof(response
);
666 if (pack_byte_string(buf
, sizeof(buf
), "sdd",
667 0, command
, sizeof(command
),
668 key_handle_offset
, key_handle
,
669 resource_type_offset
, resource_type
))
670 return TPM_LIB_ERROR
;
672 err
= tpm_sendrecv_command(buf
, response
, &response_length
);
677 #endif /* CONFIG_TPM_FLUSH_RESOURCES */
679 #ifdef CONFIG_TPM_AUTH_SESSIONS
682 * Fill an authentication block in a request.
683 * This func can create the first as well as the second auth block (for
684 * double authorized commands).
686 * @param request pointer to the request (w/ uninitialised auth data)
687 * @param request_len0 length of the request without auth data
688 * @param handles_len length of the handles area in request
689 * @param auth_session pointer to the (valid) auth session to be used
690 * @param request_auth pointer to the auth block of the request to be filled
691 * @param auth authentication data (HMAC key)
693 static uint32_t create_request_auth(const void *request
, size_t request_len0
,
695 struct session_data
*auth_session
,
696 void *request_auth
, const void *auth
)
698 uint8_t hmac_data
[DIGEST_LENGTH
* 3 + 1];
699 sha1_context hash_ctx
;
700 const size_t command_code_offset
= 6;
701 const size_t auth_nonce_odd_offset
= 4;
702 const size_t auth_continue_offset
= 24;
703 const size_t auth_auth_offset
= 25;
705 if (!auth_session
|| !auth_session
->valid
)
706 return TPM_LIB_ERROR
;
708 sha1_starts(&hash_ctx
);
709 sha1_update(&hash_ctx
, request
+ command_code_offset
, 4);
710 if (request_len0
> TPM_REQUEST_HEADER_LENGTH
+ handles_len
)
711 sha1_update(&hash_ctx
,
712 request
+ TPM_REQUEST_HEADER_LENGTH
+ handles_len
,
713 request_len0
- TPM_REQUEST_HEADER_LENGTH
715 sha1_finish(&hash_ctx
, hmac_data
);
717 sha1_starts(&hash_ctx
);
718 sha1_update(&hash_ctx
, auth_session
->nonce_odd
, DIGEST_LENGTH
);
719 sha1_update(&hash_ctx
, hmac_data
, sizeof(hmac_data
));
720 sha1_finish(&hash_ctx
, auth_session
->nonce_odd
);
722 if (pack_byte_string(request_auth
, TPM_REQUEST_AUTH_LENGTH
, "dsb",
723 0, auth_session
->handle
,
724 auth_nonce_odd_offset
, auth_session
->nonce_odd
,
726 auth_continue_offset
, 1))
727 return TPM_LIB_ERROR
;
728 if (pack_byte_string(hmac_data
, sizeof(hmac_data
), "ss",
730 auth_session
->nonce_even
,
733 request_auth
+ auth_nonce_odd_offset
,
735 return TPM_LIB_ERROR
;
736 sha1_hmac(auth
, DIGEST_LENGTH
, hmac_data
, sizeof(hmac_data
),
737 request_auth
+ auth_auth_offset
);
743 * Verify an authentication block in a response.
744 * Since this func updates the nonce_even in the session data it has to be
745 * called when receiving a succesfull AUTH response.
746 * This func can verify the first as well as the second auth block (for
747 * double authorized commands).
749 * @param command_code command code of the request
750 * @param response pointer to the request (w/ uninitialised auth data)
751 * @param handles_len length of the handles area in response
752 * @param auth_session pointer to the (valid) auth session to be used
753 * @param response_auth pointer to the auth block of the response to be verified
754 * @param auth authentication data (HMAC key)
756 static uint32_t verify_response_auth(uint32_t command_code
,
757 const void *response
, size_t response_len0
,
759 struct session_data
*auth_session
,
760 const void *response_auth
, const void *auth
)
762 uint8_t hmac_data
[DIGEST_LENGTH
* 3 + 1];
763 uint8_t computed_auth
[DIGEST_LENGTH
];
764 sha1_context hash_ctx
;
765 const size_t return_code_offset
= 6;
766 const size_t auth_continue_offset
= 20;
767 const size_t auth_auth_offset
= 21;
768 uint8_t auth_continue
;
770 if (!auth_session
|| !auth_session
->valid
)
772 if (pack_byte_string(hmac_data
, sizeof(hmac_data
), "d",
774 return TPM_LIB_ERROR
;
775 if (response_len0
< TPM_RESPONSE_HEADER_LENGTH
)
776 return TPM_LIB_ERROR
;
778 sha1_starts(&hash_ctx
);
779 sha1_update(&hash_ctx
, response
+ return_code_offset
, 4);
780 sha1_update(&hash_ctx
, hmac_data
, 4);
781 if (response_len0
> TPM_RESPONSE_HEADER_LENGTH
+ handles_len
)
782 sha1_update(&hash_ctx
,
783 response
+ TPM_RESPONSE_HEADER_LENGTH
+ handles_len
,
784 response_len0
- TPM_RESPONSE_HEADER_LENGTH
786 sha1_finish(&hash_ctx
, hmac_data
);
788 memcpy(auth_session
->nonce_even
, response_auth
, DIGEST_LENGTH
);
789 auth_continue
= ((uint8_t *)response_auth
)[auth_continue_offset
];
790 if (pack_byte_string(hmac_data
, sizeof(hmac_data
), "ssb",
795 auth_session
->nonce_odd
,
799 return TPM_LIB_ERROR
;
801 sha1_hmac(auth
, DIGEST_LENGTH
, hmac_data
, sizeof(hmac_data
),
804 if (memcmp(computed_auth
, response_auth
+ auth_auth_offset
,
812 uint32_t tpm_terminate_auth_session(uint32_t auth_handle
)
814 const uint8_t command
[18] = {
815 0x00, 0xc1, /* TPM_TAG */
816 0x00, 0x00, 0x00, 0x00, /* parameter size */
817 0x00, 0x00, 0x00, 0xba, /* TPM_COMMAND_CODE */
818 0x00, 0x00, 0x00, 0x00, /* TPM_HANDLE */
819 0x00, 0x00, 0x00, 0x02, /* TPM_RESSOURCE_TYPE */
821 const size_t req_handle_offset
= TPM_REQUEST_HEADER_LENGTH
;
822 uint8_t request
[COMMAND_BUFFER_SIZE
];
824 if (pack_byte_string(request
, sizeof(request
), "sd",
825 0, command
, sizeof(command
),
826 req_handle_offset
, auth_handle
))
827 return TPM_LIB_ERROR
;
828 if (oiap_session
.valid
&& oiap_session
.handle
== auth_handle
)
829 oiap_session
.valid
= 0;
831 return tpm_sendrecv_command(request
, NULL
, NULL
);
834 uint32_t tpm_end_oiap(void)
836 uint32_t err
= TPM_SUCCESS
;
837 if (oiap_session
.valid
)
838 err
= tpm_terminate_auth_session(oiap_session
.handle
);
842 uint32_t tpm_oiap(uint32_t *auth_handle
)
844 const uint8_t command
[10] = {
845 0x00, 0xc1, /* TPM_TAG */
846 0x00, 0x00, 0x00, 0x0a, /* parameter size */
847 0x00, 0x00, 0x00, 0x0a, /* TPM_COMMAND_CODE */
849 const size_t res_auth_handle_offset
= TPM_RESPONSE_HEADER_LENGTH
;
850 const size_t res_nonce_even_offset
= TPM_RESPONSE_HEADER_LENGTH
+ 4;
851 uint8_t response
[COMMAND_BUFFER_SIZE
];
852 size_t response_length
= sizeof(response
);
855 if (oiap_session
.valid
)
856 tpm_terminate_auth_session(oiap_session
.handle
);
858 err
= tpm_sendrecv_command(command
, response
, &response_length
);
861 if (unpack_byte_string(response
, response_length
, "ds",
862 res_auth_handle_offset
, &oiap_session
.handle
,
863 res_nonce_even_offset
, &oiap_session
.nonce_even
,
864 (uint32_t)DIGEST_LENGTH
))
865 return TPM_LIB_ERROR
;
866 oiap_session
.valid
= 1;
868 *auth_handle
= oiap_session
.handle
;
872 uint32_t tpm_load_key2_oiap(uint32_t parent_handle
,
873 const void *key
, size_t key_length
,
874 const void *parent_key_usage_auth
,
875 uint32_t *key_handle
)
877 const uint8_t command
[14] = {
878 0x00, 0xc2, /* TPM_TAG */
879 0x00, 0x00, 0x00, 0x00, /* parameter size */
880 0x00, 0x00, 0x00, 0x41, /* TPM_COMMAND_CODE */
881 0x00, 0x00, 0x00, 0x00, /* parent handle */
883 const size_t req_size_offset
= 2;
884 const size_t req_parent_handle_offset
= TPM_REQUEST_HEADER_LENGTH
;
885 const size_t req_key_offset
= TPM_REQUEST_HEADER_LENGTH
+ 4;
886 const size_t res_handle_offset
= TPM_RESPONSE_HEADER_LENGTH
;
887 uint8_t request
[sizeof(command
) + TPM_KEY12_MAX_LENGTH
888 + TPM_REQUEST_AUTH_LENGTH
];
889 uint8_t response
[COMMAND_BUFFER_SIZE
];
890 size_t response_length
= sizeof(response
);
893 if (!oiap_session
.valid
) {
894 err
= tpm_oiap(NULL
);
898 if (pack_byte_string(request
, sizeof(request
), "sdds",
899 0, command
, sizeof(command
),
901 sizeof(command
) + key_length
902 + TPM_REQUEST_AUTH_LENGTH
,
903 req_parent_handle_offset
, parent_handle
,
904 req_key_offset
, key
, key_length
906 return TPM_LIB_ERROR
;
908 err
= create_request_auth(request
, sizeof(command
) + key_length
, 4,
910 request
+ sizeof(command
) + key_length
,
911 parent_key_usage_auth
);
914 err
= tpm_sendrecv_command(request
, response
, &response_length
);
916 if (err
== TPM_AUTHFAIL
)
917 oiap_session
.valid
= 0;
921 err
= verify_response_auth(0x00000041, response
,
922 response_length
- TPM_RESPONSE_AUTH_LENGTH
,
924 response
+ response_length
- TPM_RESPONSE_AUTH_LENGTH
,
925 parent_key_usage_auth
);
930 if (unpack_byte_string(response
, response_length
, "d",
931 res_handle_offset
, key_handle
))
932 return TPM_LIB_ERROR
;
938 uint32_t tpm_get_pub_key_oiap(uint32_t key_handle
, const void *usage_auth
,
939 void *pubkey
, size_t *pubkey_len
)
941 const uint8_t command
[14] = {
942 0x00, 0xc2, /* TPM_TAG */
943 0x00, 0x00, 0x00, 0x00, /* parameter size */
944 0x00, 0x00, 0x00, 0x21, /* TPM_COMMAND_CODE */
945 0x00, 0x00, 0x00, 0x00, /* key handle */
947 const size_t req_size_offset
= 2;
948 const size_t req_key_handle_offset
= TPM_REQUEST_HEADER_LENGTH
;
949 const size_t res_pubkey_offset
= TPM_RESPONSE_HEADER_LENGTH
;
950 uint8_t request
[sizeof(command
) + TPM_REQUEST_AUTH_LENGTH
];
951 uint8_t response
[TPM_RESPONSE_HEADER_LENGTH
+ TPM_PUBKEY_MAX_LENGTH
952 + TPM_RESPONSE_AUTH_LENGTH
];
953 size_t response_length
= sizeof(response
);
956 if (!oiap_session
.valid
) {
957 err
= tpm_oiap(NULL
);
961 if (pack_byte_string(request
, sizeof(request
), "sdd",
962 0, command
, sizeof(command
),
964 (uint32_t)(sizeof(command
)
965 + TPM_REQUEST_AUTH_LENGTH
),
966 req_key_handle_offset
, key_handle
968 return TPM_LIB_ERROR
;
969 err
= create_request_auth(request
, sizeof(command
), 4, &oiap_session
,
970 request
+ sizeof(command
), usage_auth
);
973 err
= tpm_sendrecv_command(request
, response
, &response_length
);
975 if (err
== TPM_AUTHFAIL
)
976 oiap_session
.valid
= 0;
979 err
= verify_response_auth(0x00000021, response
,
980 response_length
- TPM_RESPONSE_AUTH_LENGTH
,
982 response
+ response_length
- TPM_RESPONSE_AUTH_LENGTH
,
988 if ((response_length
- TPM_RESPONSE_HEADER_LENGTH
989 - TPM_RESPONSE_AUTH_LENGTH
) > *pubkey_len
)
990 return TPM_LIB_ERROR
;
991 *pubkey_len
= response_length
- TPM_RESPONSE_HEADER_LENGTH
992 - TPM_RESPONSE_AUTH_LENGTH
;
993 memcpy(pubkey
, response
+ res_pubkey_offset
,
994 response_length
- TPM_RESPONSE_HEADER_LENGTH
995 - TPM_RESPONSE_AUTH_LENGTH
);
1001 #ifdef CONFIG_TPM_LOAD_KEY_BY_SHA1
1002 uint32_t tpm_find_key_sha1(const uint8_t auth
[20], const uint8_t
1003 pubkey_digest
[20], uint32_t *handle
)
1006 uint32_t key_handles
[10];
1014 /* fetch list of already loaded keys in the TPM */
1015 err
= tpm_get_capability(TPM_CAP_HANDLE
, TPM_RT_KEY
, buf
, sizeof(buf
));
1018 key_count
= get_unaligned_be16(buf
);
1020 for (i
= 0; i
< key_count
; ++i
, ptr
+= 4)
1021 key_handles
[i
] = get_unaligned_be32(ptr
);
1023 /* now search a(/ the) key which we can access with the given auth */
1024 for (i
= 0; i
< key_count
; ++i
) {
1025 buf_len
= sizeof(buf
);
1026 err
= tpm_get_pub_key_oiap(key_handles
[i
], auth
, buf
, &buf_len
);
1027 if (err
&& err
!= TPM_AUTHFAIL
)
1031 sha1_csum(buf
, buf_len
, digest
);
1032 if (!memcmp(digest
, pubkey_digest
, 20)) {
1033 *handle
= key_handles
[i
];
1039 #endif /* CONFIG_TPM_LOAD_KEY_BY_SHA1 */
1041 #endif /* CONFIG_TPM_AUTH_SESSIONS */