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");
99 if (offset
+ length
> size
) {
109 put_unaligned_be16(value
, str
+ offset
);
112 put_unaligned_be32(value
, str
+ offset
);
115 memcpy(str
+ offset
, data
, length
);
125 * Unpack data from a byte string. The data types are specified in
126 * the format string: 'b' means unsigned byte, 'w' unsigned word,
127 * 'd' unsigned double word, and 's' byte string. The data are a
128 * series of offsets and pointers (for type byte string there are also
131 * @param str output string
132 * @param size size of output string
133 * @param format format string
134 * @param ... data points
135 * @return 0 on success, non-0 on error
137 int unpack_byte_string(const uint8_t *str
, size_t size
, const char *format
, ...)
140 size_t offset
= 0, length
= 0;
141 uint8_t *ptr8
= NULL
;
142 uint16_t *ptr16
= NULL
;
143 uint32_t *ptr32
= NULL
;
145 va_start(args
, format
);
146 for (; *format
; format
++) {
149 offset
= va_arg(args
, size_t);
150 ptr8
= va_arg(args
, uint8_t *);
154 offset
= va_arg(args
, size_t);
155 ptr16
= va_arg(args
, uint16_t *);
159 offset
= va_arg(args
, size_t);
160 ptr32
= va_arg(args
, uint32_t *);
164 offset
= va_arg(args
, size_t);
165 ptr8
= va_arg(args
, uint8_t *);
166 length
= va_arg(args
, uint32_t);
170 debug("Couldn't recognize format string\n");
174 if (offset
+ length
> size
) {
184 *ptr16
= get_unaligned_be16(str
+ offset
);
187 *ptr32
= get_unaligned_be32(str
+ offset
);
190 memcpy(ptr8
, str
+ offset
, length
);
200 * Get TPM command size.
202 * @param command byte string of TPM command
203 * @return command size of the TPM command
205 static uint32_t tpm_command_size(const void *command
)
207 const size_t command_size_offset
= 2;
208 return get_unaligned_be32(command
+ command_size_offset
);
212 * Get TPM response return code, which is one of TPM_RESULT values.
214 * @param response byte string of TPM response
215 * @return return code of the TPM response
217 static uint32_t tpm_return_code(const void *response
)
219 const size_t return_code_offset
= 6;
220 return get_unaligned_be32(response
+ return_code_offset
);
224 * Send a TPM command and return response's return code, and optionally
225 * return response to caller.
227 * @param command byte string of TPM command
228 * @param response output buffer for TPM response, or NULL if the
229 * caller does not care about it
230 * @param size_ptr output buffer size (input parameter) and TPM
231 * response length (output parameter); this parameter
233 * @return return code of the TPM response
235 static uint32_t tpm_sendrecv_command(const void *command
,
236 void *response
, size_t *size_ptr
)
240 uint8_t response_buffer
[COMMAND_BUFFER_SIZE
];
241 size_t response_length
;
244 response_length
= *size_ptr
;
246 response
= response_buffer
;
247 response_length
= sizeof(response_buffer
);
250 ret
= uclass_first_device_err(UCLASS_TPM
, &dev
);
253 err
= tpm_xfer(dev
, command
, tpm_command_size(command
),
254 response
, &response_length
);
257 return TPM_LIB_ERROR
;
259 *size_ptr
= response_length
;
261 return tpm_return_code(response
);
269 err
= uclass_first_device_err(UCLASS_TPM
, &dev
);
272 return tpm_open(dev
);
275 uint32_t tpm_startup(enum tpm_startup_type mode
)
277 const uint8_t command
[12] = {
278 0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0x99, 0x0, 0x0,
280 const size_t mode_offset
= 10;
281 uint8_t buf
[COMMAND_BUFFER_SIZE
];
283 if (pack_byte_string(buf
, sizeof(buf
), "sw",
284 0, command
, sizeof(command
),
286 return TPM_LIB_ERROR
;
288 return tpm_sendrecv_command(buf
, NULL
, NULL
);
291 uint32_t tpm_self_test_full(void)
293 const uint8_t command
[10] = {
294 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x50,
296 return tpm_sendrecv_command(command
, NULL
, NULL
);
299 uint32_t tpm_continue_self_test(void)
301 const uint8_t command
[10] = {
302 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x53,
304 return tpm_sendrecv_command(command
, NULL
, NULL
);
307 uint32_t tpm_nv_define_space(uint32_t index
, uint32_t perm
, uint32_t size
)
309 const uint8_t command
[101] = {
310 0x0, 0xc1, /* TPM_TAG */
311 0x0, 0x0, 0x0, 0x65, /* parameter size */
312 0x0, 0x0, 0x0, 0xcc, /* TPM_COMMAND_CODE */
313 /* TPM_NV_DATA_PUBLIC->... */
314 0x0, 0x18, /* ...->TPM_STRUCTURE_TAG */
315 0, 0, 0, 0, /* ...->TPM_NV_INDEX */
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_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_ATTRIBUTES->... */
327 0x0, 0x17, /* ...->TPM_STRUCTURE_TAG */
328 0, 0, 0, 0, /* ...->attributes */
329 /* End of TPM_NV_ATTRIBUTES */
330 0, /* bReadSTClear */
331 0, /* bWriteSTClear */
332 0, /* bWriteDefine */
333 0, 0, 0, 0, /* size */
335 const size_t index_offset
= 12;
336 const size_t perm_offset
= 70;
337 const size_t size_offset
= 77;
338 uint8_t buf
[COMMAND_BUFFER_SIZE
];
340 if (pack_byte_string(buf
, sizeof(buf
), "sddd",
341 0, command
, sizeof(command
),
345 return TPM_LIB_ERROR
;
347 return tpm_sendrecv_command(buf
, NULL
, NULL
);
350 uint32_t tpm_nv_read_value(uint32_t index
, void *data
, uint32_t count
)
352 const uint8_t command
[22] = {
353 0x0, 0xc1, 0x0, 0x0, 0x0, 0x16, 0x0, 0x0, 0x0, 0xcf,
355 const size_t index_offset
= 10;
356 const size_t length_offset
= 18;
357 const size_t data_size_offset
= 10;
358 const size_t data_offset
= 14;
359 uint8_t buf
[COMMAND_BUFFER_SIZE
], response
[COMMAND_BUFFER_SIZE
];
360 size_t response_length
= sizeof(response
);
364 if (pack_byte_string(buf
, sizeof(buf
), "sdd",
365 0, command
, sizeof(command
),
367 length_offset
, count
))
368 return TPM_LIB_ERROR
;
369 err
= tpm_sendrecv_command(buf
, response
, &response_length
);
372 if (unpack_byte_string(response
, response_length
, "d",
373 data_size_offset
, &data_size
))
374 return TPM_LIB_ERROR
;
375 if (data_size
> count
)
376 return TPM_LIB_ERROR
;
377 if (unpack_byte_string(response
, response_length
, "s",
378 data_offset
, data
, data_size
))
379 return TPM_LIB_ERROR
;
384 uint32_t tpm_nv_write_value(uint32_t index
, const void *data
, uint32_t length
)
386 const uint8_t command
[256] = {
387 0x0, 0xc1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xcd,
389 const size_t command_size_offset
= 2;
390 const size_t index_offset
= 10;
391 const size_t length_offset
= 18;
392 const size_t data_offset
= 22;
393 const size_t write_info_size
= 12;
394 const uint32_t total_length
=
395 TPM_REQUEST_HEADER_LENGTH
+ write_info_size
+ length
;
396 uint8_t buf
[COMMAND_BUFFER_SIZE
], response
[COMMAND_BUFFER_SIZE
];
397 size_t response_length
= sizeof(response
);
400 if (pack_byte_string(buf
, sizeof(buf
), "sddds",
401 0, command
, sizeof(command
),
402 command_size_offset
, total_length
,
404 length_offset
, length
,
405 data_offset
, data
, length
))
406 return TPM_LIB_ERROR
;
407 err
= tpm_sendrecv_command(buf
, response
, &response_length
);
414 uint32_t tpm_extend(uint32_t index
, const void *in_digest
, void *out_digest
)
416 const uint8_t command
[34] = {
417 0x0, 0xc1, 0x0, 0x0, 0x0, 0x22, 0x0, 0x0, 0x0, 0x14,
419 const size_t index_offset
= 10;
420 const size_t in_digest_offset
= 14;
421 const size_t out_digest_offset
= 10;
422 uint8_t buf
[COMMAND_BUFFER_SIZE
];
423 uint8_t response
[TPM_RESPONSE_HEADER_LENGTH
+ PCR_DIGEST_LENGTH
];
424 size_t response_length
= sizeof(response
);
427 if (pack_byte_string(buf
, sizeof(buf
), "sds",
428 0, command
, sizeof(command
),
430 in_digest_offset
, in_digest
,
432 return TPM_LIB_ERROR
;
433 err
= tpm_sendrecv_command(buf
, response
, &response_length
);
437 if (unpack_byte_string(response
, response_length
, "s",
438 out_digest_offset
, out_digest
,
440 return TPM_LIB_ERROR
;
445 uint32_t tpm_pcr_read(uint32_t index
, void *data
, size_t count
)
447 const uint8_t command
[14] = {
448 0x0, 0xc1, 0x0, 0x0, 0x0, 0xe, 0x0, 0x0, 0x0, 0x15,
450 const size_t index_offset
= 10;
451 const size_t out_digest_offset
= 10;
452 uint8_t buf
[COMMAND_BUFFER_SIZE
], response
[COMMAND_BUFFER_SIZE
];
453 size_t response_length
= sizeof(response
);
456 if (count
< PCR_DIGEST_LENGTH
)
457 return TPM_LIB_ERROR
;
459 if (pack_byte_string(buf
, sizeof(buf
), "sd",
460 0, command
, sizeof(command
),
461 index_offset
, index
))
462 return TPM_LIB_ERROR
;
463 err
= tpm_sendrecv_command(buf
, response
, &response_length
);
466 if (unpack_byte_string(response
, response_length
, "s",
467 out_digest_offset
, data
, PCR_DIGEST_LENGTH
))
468 return TPM_LIB_ERROR
;
473 uint32_t tpm_tsc_physical_presence(uint16_t presence
)
475 const uint8_t command
[12] = {
476 0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x40, 0x0, 0x0, 0xa, 0x0, 0x0,
478 const size_t presence_offset
= 10;
479 uint8_t buf
[COMMAND_BUFFER_SIZE
];
481 if (pack_byte_string(buf
, sizeof(buf
), "sw",
482 0, command
, sizeof(command
),
483 presence_offset
, presence
))
484 return TPM_LIB_ERROR
;
486 return tpm_sendrecv_command(buf
, NULL
, NULL
);
489 uint32_t tpm_read_pubek(void *data
, size_t count
)
491 const uint8_t command
[30] = {
492 0x0, 0xc1, 0x0, 0x0, 0x0, 0x1e, 0x0, 0x0, 0x0, 0x7c,
494 const size_t response_size_offset
= 2;
495 const size_t data_offset
= 10;
496 const size_t header_and_checksum_size
= TPM_RESPONSE_HEADER_LENGTH
+ 20;
497 uint8_t response
[COMMAND_BUFFER_SIZE
+ TPM_PUBEK_SIZE
];
498 size_t response_length
= sizeof(response
);
502 err
= tpm_sendrecv_command(command
, response
, &response_length
);
505 if (unpack_byte_string(response
, response_length
, "d",
506 response_size_offset
, &data_size
))
507 return TPM_LIB_ERROR
;
508 if (data_size
< header_and_checksum_size
)
509 return TPM_LIB_ERROR
;
510 data_size
-= header_and_checksum_size
;
511 if (data_size
> count
)
512 return TPM_LIB_ERROR
;
513 if (unpack_byte_string(response
, response_length
, "s",
514 data_offset
, data
, data_size
))
515 return TPM_LIB_ERROR
;
520 uint32_t tpm_force_clear(void)
522 const uint8_t command
[10] = {
523 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x5d,
526 return tpm_sendrecv_command(command
, NULL
, NULL
);
529 uint32_t tpm_physical_enable(void)
531 const uint8_t command
[10] = {
532 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x6f,
535 return tpm_sendrecv_command(command
, NULL
, NULL
);
538 uint32_t tpm_physical_disable(void)
540 const uint8_t command
[10] = {
541 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x70,
544 return tpm_sendrecv_command(command
, NULL
, NULL
);
547 uint32_t tpm_physical_set_deactivated(uint8_t state
)
549 const uint8_t command
[11] = {
550 0x0, 0xc1, 0x0, 0x0, 0x0, 0xb, 0x0, 0x0, 0x0, 0x72,
552 const size_t state_offset
= 10;
553 uint8_t buf
[COMMAND_BUFFER_SIZE
];
555 if (pack_byte_string(buf
, sizeof(buf
), "sb",
556 0, command
, sizeof(command
),
557 state_offset
, state
))
558 return TPM_LIB_ERROR
;
560 return tpm_sendrecv_command(buf
, NULL
, NULL
);
563 uint32_t tpm_get_capability(uint32_t cap_area
, uint32_t sub_cap
,
564 void *cap
, size_t count
)
566 const uint8_t command
[22] = {
567 0x0, 0xc1, /* TPM_TAG */
568 0x0, 0x0, 0x0, 0x16, /* parameter size */
569 0x0, 0x0, 0x0, 0x65, /* TPM_COMMAND_CODE */
570 0x0, 0x0, 0x0, 0x0, /* TPM_CAPABILITY_AREA */
571 0x0, 0x0, 0x0, 0x4, /* subcap size */
572 0x0, 0x0, 0x0, 0x0, /* subcap value */
574 const size_t cap_area_offset
= 10;
575 const size_t sub_cap_offset
= 18;
576 const size_t cap_offset
= 14;
577 const size_t cap_size_offset
= 10;
578 uint8_t buf
[COMMAND_BUFFER_SIZE
], response
[COMMAND_BUFFER_SIZE
];
579 size_t response_length
= sizeof(response
);
583 if (pack_byte_string(buf
, sizeof(buf
), "sdd",
584 0, command
, sizeof(command
),
585 cap_area_offset
, cap_area
,
586 sub_cap_offset
, sub_cap
))
587 return TPM_LIB_ERROR
;
588 err
= tpm_sendrecv_command(buf
, response
, &response_length
);
591 if (unpack_byte_string(response
, response_length
, "d",
592 cap_size_offset
, &cap_size
))
593 return TPM_LIB_ERROR
;
594 if (cap_size
> response_length
|| cap_size
> count
)
595 return TPM_LIB_ERROR
;
596 if (unpack_byte_string(response
, response_length
, "s",
597 cap_offset
, cap
, cap_size
))
598 return TPM_LIB_ERROR
;
603 uint32_t tpm_get_permanent_flags(struct tpm_permanent_flags
*pflags
)
605 const uint8_t command
[22] = {
606 0x0, 0xc1, /* TPM_TAG */
607 0x0, 0x0, 0x0, 0x16, /* parameter size */
608 0x0, 0x0, 0x0, 0x65, /* TPM_COMMAND_CODE */
609 0x0, 0x0, 0x0, 0x4, /* TPM_CAP_FLAG_PERM */
610 0x0, 0x0, 0x0, 0x4, /* subcap size */
611 0x0, 0x0, 0x1, 0x8, /* subcap value */
613 const size_t data_size_offset
= TPM_HEADER_SIZE
;
614 const size_t data_offset
= TPM_HEADER_SIZE
+ sizeof (uint32_t);
615 uint8_t response
[COMMAND_BUFFER_SIZE
];
616 size_t response_length
= sizeof(response
);
620 err
= tpm_sendrecv_command(command
, response
, &response_length
);
623 if (unpack_byte_string(response
, response_length
, "d",
624 data_size_offset
, &data_size
))
625 return TPM_LIB_ERROR
;
626 if (data_size
< sizeof(*pflags
))
627 return TPM_LIB_ERROR
;
628 if (unpack_byte_string(response
, response_length
, "s",
629 data_offset
, pflags
, sizeof(*pflags
)))
630 return TPM_LIB_ERROR
;
635 uint32_t tpm_get_permissions(uint32_t index
, uint32_t *perm
)
637 const uint8_t command
[22] = {
638 0x0, 0xc1, /* TPM_TAG */
639 0x0, 0x0, 0x0, 0x16, /* parameter size */
640 0x0, 0x0, 0x0, 0x65, /* TPM_COMMAND_CODE */
644 const size_t index_offset
= 18;
645 const size_t perm_offset
= 60;
646 uint8_t buf
[COMMAND_BUFFER_SIZE
], response
[COMMAND_BUFFER_SIZE
];
647 size_t response_length
= sizeof(response
);
650 if (pack_byte_string(buf
, sizeof(buf
), "d", 0, command
, sizeof(command
),
651 index_offset
, index
))
652 return TPM_LIB_ERROR
;
653 err
= tpm_sendrecv_command(buf
, response
, &response_length
);
656 if (unpack_byte_string(response
, response_length
, "d",
658 return TPM_LIB_ERROR
;
663 #ifdef CONFIG_TPM_FLUSH_RESOURCES
664 uint32_t tpm_flush_specific(uint32_t key_handle
, uint32_t resource_type
)
666 const uint8_t command
[18] = {
667 0x00, 0xc1, /* TPM_TAG */
668 0x00, 0x00, 0x00, 0x12, /* parameter size */
669 0x00, 0x00, 0x00, 0xba, /* TPM_COMMAND_CODE */
670 0x00, 0x00, 0x00, 0x00, /* key handle */
671 0x00, 0x00, 0x00, 0x00, /* resource type */
673 const size_t key_handle_offset
= 10;
674 const size_t resource_type_offset
= 14;
675 uint8_t buf
[COMMAND_BUFFER_SIZE
], response
[COMMAND_BUFFER_SIZE
];
676 size_t response_length
= sizeof(response
);
679 if (pack_byte_string(buf
, sizeof(buf
), "sdd",
680 0, command
, sizeof(command
),
681 key_handle_offset
, key_handle
,
682 resource_type_offset
, resource_type
))
683 return TPM_LIB_ERROR
;
685 err
= tpm_sendrecv_command(buf
, response
, &response_length
);
690 #endif /* CONFIG_TPM_FLUSH_RESOURCES */
692 #ifdef CONFIG_TPM_AUTH_SESSIONS
695 * Fill an authentication block in a request.
696 * This func can create the first as well as the second auth block (for
697 * double authorized commands).
699 * @param request pointer to the request (w/ uninitialised auth data)
700 * @param request_len0 length of the request without auth data
701 * @param handles_len length of the handles area in request
702 * @param auth_session pointer to the (valid) auth session to be used
703 * @param request_auth pointer to the auth block of the request to be filled
704 * @param auth authentication data (HMAC key)
706 static uint32_t create_request_auth(const void *request
, size_t request_len0
,
708 struct session_data
*auth_session
,
709 void *request_auth
, const void *auth
)
711 uint8_t hmac_data
[DIGEST_LENGTH
* 3 + 1];
712 sha1_context hash_ctx
;
713 const size_t command_code_offset
= 6;
714 const size_t auth_nonce_odd_offset
= 4;
715 const size_t auth_continue_offset
= 24;
716 const size_t auth_auth_offset
= 25;
718 if (!auth_session
|| !auth_session
->valid
)
719 return TPM_LIB_ERROR
;
721 sha1_starts(&hash_ctx
);
722 sha1_update(&hash_ctx
, request
+ command_code_offset
, 4);
723 if (request_len0
> TPM_REQUEST_HEADER_LENGTH
+ handles_len
)
724 sha1_update(&hash_ctx
,
725 request
+ TPM_REQUEST_HEADER_LENGTH
+ handles_len
,
726 request_len0
- TPM_REQUEST_HEADER_LENGTH
728 sha1_finish(&hash_ctx
, hmac_data
);
730 sha1_starts(&hash_ctx
);
731 sha1_update(&hash_ctx
, auth_session
->nonce_odd
, DIGEST_LENGTH
);
732 sha1_update(&hash_ctx
, hmac_data
, sizeof(hmac_data
));
733 sha1_finish(&hash_ctx
, auth_session
->nonce_odd
);
735 if (pack_byte_string(request_auth
, TPM_REQUEST_AUTH_LENGTH
, "dsb",
736 0, auth_session
->handle
,
737 auth_nonce_odd_offset
, auth_session
->nonce_odd
,
739 auth_continue_offset
, 1))
740 return TPM_LIB_ERROR
;
741 if (pack_byte_string(hmac_data
, sizeof(hmac_data
), "ss",
743 auth_session
->nonce_even
,
746 request_auth
+ auth_nonce_odd_offset
,
748 return TPM_LIB_ERROR
;
749 sha1_hmac(auth
, DIGEST_LENGTH
, hmac_data
, sizeof(hmac_data
),
750 request_auth
+ auth_auth_offset
);
756 * Verify an authentication block in a response.
757 * Since this func updates the nonce_even in the session data it has to be
758 * called when receiving a succesfull AUTH response.
759 * This func can verify the first as well as the second auth block (for
760 * double authorized commands).
762 * @param command_code command code of the request
763 * @param response pointer to the request (w/ uninitialised auth data)
764 * @param handles_len length of the handles area in response
765 * @param auth_session pointer to the (valid) auth session to be used
766 * @param response_auth pointer to the auth block of the response to be verified
767 * @param auth authentication data (HMAC key)
769 static uint32_t verify_response_auth(uint32_t command_code
,
770 const void *response
, size_t response_len0
,
772 struct session_data
*auth_session
,
773 const void *response_auth
, const void *auth
)
775 uint8_t hmac_data
[DIGEST_LENGTH
* 3 + 1];
776 uint8_t computed_auth
[DIGEST_LENGTH
];
777 sha1_context hash_ctx
;
778 const size_t return_code_offset
= 6;
779 const size_t auth_continue_offset
= 20;
780 const size_t auth_auth_offset
= 21;
781 uint8_t auth_continue
;
783 if (!auth_session
|| !auth_session
->valid
)
785 if (pack_byte_string(hmac_data
, sizeof(hmac_data
), "d",
787 return TPM_LIB_ERROR
;
788 if (response_len0
< TPM_RESPONSE_HEADER_LENGTH
)
789 return TPM_LIB_ERROR
;
791 sha1_starts(&hash_ctx
);
792 sha1_update(&hash_ctx
, response
+ return_code_offset
, 4);
793 sha1_update(&hash_ctx
, hmac_data
, 4);
794 if (response_len0
> TPM_RESPONSE_HEADER_LENGTH
+ handles_len
)
795 sha1_update(&hash_ctx
,
796 response
+ TPM_RESPONSE_HEADER_LENGTH
+ handles_len
,
797 response_len0
- TPM_RESPONSE_HEADER_LENGTH
799 sha1_finish(&hash_ctx
, hmac_data
);
801 memcpy(auth_session
->nonce_even
, response_auth
, DIGEST_LENGTH
);
802 auth_continue
= ((uint8_t *)response_auth
)[auth_continue_offset
];
803 if (pack_byte_string(hmac_data
, sizeof(hmac_data
), "ssb",
808 auth_session
->nonce_odd
,
812 return TPM_LIB_ERROR
;
814 sha1_hmac(auth
, DIGEST_LENGTH
, hmac_data
, sizeof(hmac_data
),
817 if (memcmp(computed_auth
, response_auth
+ auth_auth_offset
,
825 uint32_t tpm_terminate_auth_session(uint32_t auth_handle
)
827 const uint8_t command
[18] = {
828 0x00, 0xc1, /* TPM_TAG */
829 0x00, 0x00, 0x00, 0x00, /* parameter size */
830 0x00, 0x00, 0x00, 0xba, /* TPM_COMMAND_CODE */
831 0x00, 0x00, 0x00, 0x00, /* TPM_HANDLE */
832 0x00, 0x00, 0x00, 0x02, /* TPM_RESSOURCE_TYPE */
834 const size_t req_handle_offset
= TPM_REQUEST_HEADER_LENGTH
;
835 uint8_t request
[COMMAND_BUFFER_SIZE
];
837 if (pack_byte_string(request
, sizeof(request
), "sd",
838 0, command
, sizeof(command
),
839 req_handle_offset
, auth_handle
))
840 return TPM_LIB_ERROR
;
841 if (oiap_session
.valid
&& oiap_session
.handle
== auth_handle
)
842 oiap_session
.valid
= 0;
844 return tpm_sendrecv_command(request
, NULL
, NULL
);
847 uint32_t tpm_end_oiap(void)
849 uint32_t err
= TPM_SUCCESS
;
850 if (oiap_session
.valid
)
851 err
= tpm_terminate_auth_session(oiap_session
.handle
);
855 uint32_t tpm_oiap(uint32_t *auth_handle
)
857 const uint8_t command
[10] = {
858 0x00, 0xc1, /* TPM_TAG */
859 0x00, 0x00, 0x00, 0x0a, /* parameter size */
860 0x00, 0x00, 0x00, 0x0a, /* TPM_COMMAND_CODE */
862 const size_t res_auth_handle_offset
= TPM_RESPONSE_HEADER_LENGTH
;
863 const size_t res_nonce_even_offset
= TPM_RESPONSE_HEADER_LENGTH
+ 4;
864 uint8_t response
[COMMAND_BUFFER_SIZE
];
865 size_t response_length
= sizeof(response
);
868 if (oiap_session
.valid
)
869 tpm_terminate_auth_session(oiap_session
.handle
);
871 err
= tpm_sendrecv_command(command
, response
, &response_length
);
874 if (unpack_byte_string(response
, response_length
, "ds",
875 res_auth_handle_offset
, &oiap_session
.handle
,
876 res_nonce_even_offset
, &oiap_session
.nonce_even
,
877 (uint32_t)DIGEST_LENGTH
))
878 return TPM_LIB_ERROR
;
879 oiap_session
.valid
= 1;
881 *auth_handle
= oiap_session
.handle
;
885 uint32_t tpm_load_key2_oiap(uint32_t parent_handle
,
886 const void *key
, size_t key_length
,
887 const void *parent_key_usage_auth
,
888 uint32_t *key_handle
)
890 const uint8_t command
[14] = {
891 0x00, 0xc2, /* TPM_TAG */
892 0x00, 0x00, 0x00, 0x00, /* parameter size */
893 0x00, 0x00, 0x00, 0x41, /* TPM_COMMAND_CODE */
894 0x00, 0x00, 0x00, 0x00, /* parent handle */
896 const size_t req_size_offset
= 2;
897 const size_t req_parent_handle_offset
= TPM_REQUEST_HEADER_LENGTH
;
898 const size_t req_key_offset
= TPM_REQUEST_HEADER_LENGTH
+ 4;
899 const size_t res_handle_offset
= TPM_RESPONSE_HEADER_LENGTH
;
900 uint8_t request
[sizeof(command
) + TPM_KEY12_MAX_LENGTH
901 + TPM_REQUEST_AUTH_LENGTH
];
902 uint8_t response
[COMMAND_BUFFER_SIZE
];
903 size_t response_length
= sizeof(response
);
906 if (!oiap_session
.valid
) {
907 err
= tpm_oiap(NULL
);
911 if (pack_byte_string(request
, sizeof(request
), "sdds",
912 0, command
, sizeof(command
),
914 sizeof(command
) + key_length
915 + TPM_REQUEST_AUTH_LENGTH
,
916 req_parent_handle_offset
, parent_handle
,
917 req_key_offset
, key
, key_length
919 return TPM_LIB_ERROR
;
921 err
= create_request_auth(request
, sizeof(command
) + key_length
, 4,
923 request
+ sizeof(command
) + key_length
,
924 parent_key_usage_auth
);
927 err
= tpm_sendrecv_command(request
, response
, &response_length
);
929 if (err
== TPM_AUTHFAIL
)
930 oiap_session
.valid
= 0;
934 err
= verify_response_auth(0x00000041, response
,
935 response_length
- TPM_RESPONSE_AUTH_LENGTH
,
937 response
+ response_length
- TPM_RESPONSE_AUTH_LENGTH
,
938 parent_key_usage_auth
);
943 if (unpack_byte_string(response
, response_length
, "d",
944 res_handle_offset
, key_handle
))
945 return TPM_LIB_ERROR
;
951 uint32_t tpm_get_pub_key_oiap(uint32_t key_handle
, const void *usage_auth
,
952 void *pubkey
, size_t *pubkey_len
)
954 const uint8_t command
[14] = {
955 0x00, 0xc2, /* TPM_TAG */
956 0x00, 0x00, 0x00, 0x00, /* parameter size */
957 0x00, 0x00, 0x00, 0x21, /* TPM_COMMAND_CODE */
958 0x00, 0x00, 0x00, 0x00, /* key handle */
960 const size_t req_size_offset
= 2;
961 const size_t req_key_handle_offset
= TPM_REQUEST_HEADER_LENGTH
;
962 const size_t res_pubkey_offset
= TPM_RESPONSE_HEADER_LENGTH
;
963 uint8_t request
[sizeof(command
) + TPM_REQUEST_AUTH_LENGTH
];
964 uint8_t response
[TPM_RESPONSE_HEADER_LENGTH
+ TPM_PUBKEY_MAX_LENGTH
965 + TPM_RESPONSE_AUTH_LENGTH
];
966 size_t response_length
= sizeof(response
);
969 if (!oiap_session
.valid
) {
970 err
= tpm_oiap(NULL
);
974 if (pack_byte_string(request
, sizeof(request
), "sdd",
975 0, command
, sizeof(command
),
977 (uint32_t)(sizeof(command
)
978 + TPM_REQUEST_AUTH_LENGTH
),
979 req_key_handle_offset
, key_handle
981 return TPM_LIB_ERROR
;
982 err
= create_request_auth(request
, sizeof(command
), 4, &oiap_session
,
983 request
+ sizeof(command
), usage_auth
);
986 err
= tpm_sendrecv_command(request
, response
, &response_length
);
988 if (err
== TPM_AUTHFAIL
)
989 oiap_session
.valid
= 0;
992 err
= verify_response_auth(0x00000021, response
,
993 response_length
- TPM_RESPONSE_AUTH_LENGTH
,
995 response
+ response_length
- TPM_RESPONSE_AUTH_LENGTH
,
1001 if ((response_length
- TPM_RESPONSE_HEADER_LENGTH
1002 - TPM_RESPONSE_AUTH_LENGTH
) > *pubkey_len
)
1003 return TPM_LIB_ERROR
;
1004 *pubkey_len
= response_length
- TPM_RESPONSE_HEADER_LENGTH
1005 - TPM_RESPONSE_AUTH_LENGTH
;
1006 memcpy(pubkey
, response
+ res_pubkey_offset
,
1007 response_length
- TPM_RESPONSE_HEADER_LENGTH
1008 - TPM_RESPONSE_AUTH_LENGTH
);
1014 #ifdef CONFIG_TPM_LOAD_KEY_BY_SHA1
1015 uint32_t tpm_find_key_sha1(const uint8_t auth
[20], const uint8_t
1016 pubkey_digest
[20], uint32_t *handle
)
1019 uint32_t key_handles
[10];
1027 /* fetch list of already loaded keys in the TPM */
1028 err
= tpm_get_capability(TPM_CAP_HANDLE
, TPM_RT_KEY
, buf
, sizeof(buf
));
1031 key_count
= get_unaligned_be16(buf
);
1033 for (i
= 0; i
< key_count
; ++i
, ptr
+= 4)
1034 key_handles
[i
] = get_unaligned_be32(ptr
);
1036 /* now search a(/ the) key which we can access with the given auth */
1037 for (i
= 0; i
< key_count
; ++i
) {
1038 buf_len
= sizeof(buf
);
1039 err
= tpm_get_pub_key_oiap(key_handles
[i
], auth
, buf
, &buf_len
);
1040 if (err
&& err
!= TPM_AUTHFAIL
)
1044 sha1_csum(buf
, buf_len
, digest
);
1045 if (!memcmp(digest
, pubkey_digest
, 20)) {
1046 *handle
= key_handles
[i
];
1052 #endif /* CONFIG_TPM_LOAD_KEY_BY_SHA1 */
1054 #endif /* CONFIG_TPM_AUTH_SESSIONS */
1056 uint32_t tpm_get_random(void *data
, uint32_t count
)
1058 const uint8_t command
[14] = {
1059 0x0, 0xc1, /* TPM_TAG */
1060 0x0, 0x0, 0x0, 0xe, /* parameter size */
1061 0x0, 0x0, 0x0, 0x46, /* TPM_COMMAND_CODE */
1063 const size_t length_offset
= 10;
1064 const size_t data_size_offset
= 10;
1065 const size_t data_offset
= 14;
1066 uint8_t buf
[COMMAND_BUFFER_SIZE
], response
[COMMAND_BUFFER_SIZE
];
1067 size_t response_length
= sizeof(response
);
1069 uint8_t *out
= data
;
1072 uint32_t this_bytes
= min((size_t)count
,
1073 sizeof (response
) - data_offset
);
1076 if (pack_byte_string(buf
, sizeof(buf
), "sd",
1077 0, command
, sizeof(command
),
1078 length_offset
, this_bytes
))
1079 return TPM_LIB_ERROR
;
1080 err
= tpm_sendrecv_command(buf
, response
, &response_length
);
1083 if (unpack_byte_string(response
, response_length
, "d",
1084 data_size_offset
, &data_size
))
1085 return TPM_LIB_ERROR
;
1086 if (data_size
> count
)
1087 return TPM_LIB_ERROR
;
1088 if (unpack_byte_string(response
, response_length
, "s",
1089 data_offset
, out
, data_size
))
1090 return TPM_LIB_ERROR
;