2 * Copyright (c) 2013 The Chromium OS Authors.
3 * Coypright (c) 2013 Guntermann & Drunck GmbH
5 * SPDX-License-Identifier: GPL-2.0+
12 #include <asm/unaligned.h>
13 #include <u-boot/sha1.h>
15 /* Internal error of TPM command library */
16 #define TPM_LIB_ERROR ((uint32_t)~0u)
18 /* Useful constants */
20 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
);
247 ret
= uclass_first_device(UCLASS_TPM
, &dev
);
250 err
= tpm_xfer(dev
, command
, tpm_command_size(command
),
251 response
, &response_length
);
253 err
= tis_sendrecv(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
);
271 err
= uclass_first_device(UCLASS_TPM
, &dev
);
274 return tpm_open(dev
);
284 uint32_t tpm_startup(enum tpm_startup_type mode
)
286 const uint8_t command
[12] = {
287 0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0x99, 0x0, 0x0,
289 const size_t mode_offset
= 10;
290 uint8_t buf
[COMMAND_BUFFER_SIZE
];
292 if (pack_byte_string(buf
, sizeof(buf
), "sw",
293 0, command
, sizeof(command
),
295 return TPM_LIB_ERROR
;
297 return tpm_sendrecv_command(buf
, NULL
, NULL
);
300 uint32_t tpm_self_test_full(void)
302 const uint8_t command
[10] = {
303 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x50,
305 return tpm_sendrecv_command(command
, NULL
, NULL
);
308 uint32_t tpm_continue_self_test(void)
310 const uint8_t command
[10] = {
311 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x53,
313 return tpm_sendrecv_command(command
, NULL
, NULL
);
316 uint32_t tpm_nv_define_space(uint32_t index
, uint32_t perm
, uint32_t size
)
318 const uint8_t command
[101] = {
319 0x0, 0xc1, /* TPM_TAG */
320 0x0, 0x0, 0x0, 0x65, /* parameter size */
321 0x0, 0x0, 0x0, 0xcc, /* TPM_COMMAND_CODE */
322 /* TPM_NV_DATA_PUBLIC->... */
323 0x0, 0x18, /* ...->TPM_STRUCTURE_TAG */
324 0, 0, 0, 0, /* ...->TPM_NV_INDEX */
325 /* TPM_NV_DATA_PUBLIC->TPM_PCR_INFO_SHORT */
329 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
330 /* TPM_NV_DATA_PUBLIC->TPM_PCR_INFO_SHORT */
334 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
335 /* TPM_NV_ATTRIBUTES->... */
336 0x0, 0x17, /* ...->TPM_STRUCTURE_TAG */
337 0, 0, 0, 0, /* ...->attributes */
338 /* End of TPM_NV_ATTRIBUTES */
339 0, /* bReadSTClear */
340 0, /* bWriteSTClear */
341 0, /* bWriteDefine */
342 0, 0, 0, 0, /* size */
344 const size_t index_offset
= 12;
345 const size_t perm_offset
= 70;
346 const size_t size_offset
= 77;
347 uint8_t buf
[COMMAND_BUFFER_SIZE
];
349 if (pack_byte_string(buf
, sizeof(buf
), "sddd",
350 0, command
, sizeof(command
),
354 return TPM_LIB_ERROR
;
356 return tpm_sendrecv_command(buf
, NULL
, NULL
);
359 uint32_t tpm_nv_read_value(uint32_t index
, void *data
, uint32_t count
)
361 const uint8_t command
[22] = {
362 0x0, 0xc1, 0x0, 0x0, 0x0, 0x16, 0x0, 0x0, 0x0, 0xcf,
364 const size_t index_offset
= 10;
365 const size_t length_offset
= 18;
366 const size_t data_size_offset
= 10;
367 const size_t data_offset
= 14;
368 uint8_t buf
[COMMAND_BUFFER_SIZE
], response
[COMMAND_BUFFER_SIZE
];
369 size_t response_length
= sizeof(response
);
373 if (pack_byte_string(buf
, sizeof(buf
), "sdd",
374 0, command
, sizeof(command
),
376 length_offset
, count
))
377 return TPM_LIB_ERROR
;
378 err
= tpm_sendrecv_command(buf
, response
, &response_length
);
381 if (unpack_byte_string(response
, response_length
, "d",
382 data_size_offset
, &data_size
))
383 return TPM_LIB_ERROR
;
384 if (data_size
> count
)
385 return TPM_LIB_ERROR
;
386 if (unpack_byte_string(response
, response_length
, "s",
387 data_offset
, data
, data_size
))
388 return TPM_LIB_ERROR
;
393 uint32_t tpm_nv_write_value(uint32_t index
, const void *data
, uint32_t length
)
395 const uint8_t command
[256] = {
396 0x0, 0xc1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xcd,
398 const size_t command_size_offset
= 2;
399 const size_t index_offset
= 10;
400 const size_t length_offset
= 18;
401 const size_t data_offset
= 22;
402 const size_t write_info_size
= 12;
403 const uint32_t total_length
=
404 TPM_REQUEST_HEADER_LENGTH
+ write_info_size
+ length
;
405 uint8_t buf
[COMMAND_BUFFER_SIZE
], response
[COMMAND_BUFFER_SIZE
];
406 size_t response_length
= sizeof(response
);
409 if (pack_byte_string(buf
, sizeof(buf
), "sddds",
410 0, command
, sizeof(command
),
411 command_size_offset
, total_length
,
413 length_offset
, length
,
414 data_offset
, data
, length
))
415 return TPM_LIB_ERROR
;
416 err
= tpm_sendrecv_command(buf
, response
, &response_length
);
423 uint32_t tpm_extend(uint32_t index
, const void *in_digest
, void *out_digest
)
425 const uint8_t command
[34] = {
426 0x0, 0xc1, 0x0, 0x0, 0x0, 0x22, 0x0, 0x0, 0x0, 0x14,
428 const size_t index_offset
= 10;
429 const size_t in_digest_offset
= 14;
430 const size_t out_digest_offset
= 10;
431 uint8_t buf
[COMMAND_BUFFER_SIZE
];
432 uint8_t response
[TPM_RESPONSE_HEADER_LENGTH
+ PCR_DIGEST_LENGTH
];
433 size_t response_length
= sizeof(response
);
436 if (pack_byte_string(buf
, sizeof(buf
), "sds",
437 0, command
, sizeof(command
),
439 in_digest_offset
, in_digest
,
441 return TPM_LIB_ERROR
;
442 err
= tpm_sendrecv_command(buf
, response
, &response_length
);
446 if (unpack_byte_string(response
, response_length
, "s",
447 out_digest_offset
, out_digest
,
449 return TPM_LIB_ERROR
;
454 uint32_t tpm_pcr_read(uint32_t index
, void *data
, size_t count
)
456 const uint8_t command
[14] = {
457 0x0, 0xc1, 0x0, 0x0, 0x0, 0xe, 0x0, 0x0, 0x0, 0x15,
459 const size_t index_offset
= 10;
460 const size_t out_digest_offset
= 10;
461 uint8_t buf
[COMMAND_BUFFER_SIZE
], response
[COMMAND_BUFFER_SIZE
];
462 size_t response_length
= sizeof(response
);
465 if (count
< PCR_DIGEST_LENGTH
)
466 return TPM_LIB_ERROR
;
468 if (pack_byte_string(buf
, sizeof(buf
), "sd",
469 0, command
, sizeof(command
),
470 index_offset
, index
))
471 return TPM_LIB_ERROR
;
472 err
= tpm_sendrecv_command(buf
, response
, &response_length
);
475 if (unpack_byte_string(response
, response_length
, "s",
476 out_digest_offset
, data
, PCR_DIGEST_LENGTH
))
477 return TPM_LIB_ERROR
;
482 uint32_t tpm_tsc_physical_presence(uint16_t presence
)
484 const uint8_t command
[12] = {
485 0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x40, 0x0, 0x0, 0xa, 0x0, 0x0,
487 const size_t presence_offset
= 10;
488 uint8_t buf
[COMMAND_BUFFER_SIZE
];
490 if (pack_byte_string(buf
, sizeof(buf
), "sw",
491 0, command
, sizeof(command
),
492 presence_offset
, presence
))
493 return TPM_LIB_ERROR
;
495 return tpm_sendrecv_command(buf
, NULL
, NULL
);
498 uint32_t tpm_read_pubek(void *data
, size_t count
)
500 const uint8_t command
[30] = {
501 0x0, 0xc1, 0x0, 0x0, 0x0, 0x1e, 0x0, 0x0, 0x0, 0x7c,
503 const size_t response_size_offset
= 2;
504 const size_t data_offset
= 10;
505 const size_t header_and_checksum_size
= TPM_RESPONSE_HEADER_LENGTH
+ 20;
506 uint8_t response
[COMMAND_BUFFER_SIZE
+ TPM_PUBEK_SIZE
];
507 size_t response_length
= sizeof(response
);
511 err
= tpm_sendrecv_command(command
, response
, &response_length
);
514 if (unpack_byte_string(response
, response_length
, "d",
515 response_size_offset
, &data_size
))
516 return TPM_LIB_ERROR
;
517 if (data_size
< header_and_checksum_size
)
518 return TPM_LIB_ERROR
;
519 data_size
-= header_and_checksum_size
;
520 if (data_size
> count
)
521 return TPM_LIB_ERROR
;
522 if (unpack_byte_string(response
, response_length
, "s",
523 data_offset
, data
, data_size
))
524 return TPM_LIB_ERROR
;
529 uint32_t tpm_force_clear(void)
531 const uint8_t command
[10] = {
532 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x5d,
535 return tpm_sendrecv_command(command
, NULL
, NULL
);
538 uint32_t tpm_physical_enable(void)
540 const uint8_t command
[10] = {
541 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x6f,
544 return tpm_sendrecv_command(command
, NULL
, NULL
);
547 uint32_t tpm_physical_disable(void)
549 const uint8_t command
[10] = {
550 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x70,
553 return tpm_sendrecv_command(command
, NULL
, NULL
);
556 uint32_t tpm_physical_set_deactivated(uint8_t state
)
558 const uint8_t command
[11] = {
559 0x0, 0xc1, 0x0, 0x0, 0x0, 0xb, 0x0, 0x0, 0x0, 0x72,
561 const size_t state_offset
= 10;
562 uint8_t buf
[COMMAND_BUFFER_SIZE
];
564 if (pack_byte_string(buf
, sizeof(buf
), "sb",
565 0, command
, sizeof(command
),
566 state_offset
, state
))
567 return TPM_LIB_ERROR
;
569 return tpm_sendrecv_command(buf
, NULL
, NULL
);
572 uint32_t tpm_get_capability(uint32_t cap_area
, uint32_t sub_cap
,
573 void *cap
, size_t count
)
575 const uint8_t command
[22] = {
576 0x0, 0xc1, /* TPM_TAG */
577 0x0, 0x0, 0x0, 0x16, /* parameter size */
578 0x0, 0x0, 0x0, 0x65, /* TPM_COMMAND_CODE */
579 0x0, 0x0, 0x0, 0x0, /* TPM_CAPABILITY_AREA */
580 0x0, 0x0, 0x0, 0x4, /* subcap size */
581 0x0, 0x0, 0x0, 0x0, /* subcap value */
583 const size_t cap_area_offset
= 10;
584 const size_t sub_cap_offset
= 18;
585 const size_t cap_offset
= 14;
586 const size_t cap_size_offset
= 10;
587 uint8_t buf
[COMMAND_BUFFER_SIZE
], response
[COMMAND_BUFFER_SIZE
];
588 size_t response_length
= sizeof(response
);
592 if (pack_byte_string(buf
, sizeof(buf
), "sdd",
593 0, command
, sizeof(command
),
594 cap_area_offset
, cap_area
,
595 sub_cap_offset
, sub_cap
))
596 return TPM_LIB_ERROR
;
597 err
= tpm_sendrecv_command(buf
, response
, &response_length
);
600 if (unpack_byte_string(response
, response_length
, "d",
601 cap_size_offset
, &cap_size
))
602 return TPM_LIB_ERROR
;
603 if (cap_size
> response_length
|| cap_size
> count
)
604 return TPM_LIB_ERROR
;
605 if (unpack_byte_string(response
, response_length
, "s",
606 cap_offset
, cap
, cap_size
))
607 return TPM_LIB_ERROR
;
612 uint32_t tpm_get_permanent_flags(struct tpm_permanent_flags
*pflags
)
614 const uint8_t command
[22] = {
615 0x0, 0xc1, /* TPM_TAG */
616 0x0, 0x0, 0x0, 0x16, /* parameter size */
617 0x0, 0x0, 0x0, 0x65, /* TPM_COMMAND_CODE */
618 0x0, 0x0, 0x0, 0x4, /* TPM_CAP_FLAG_PERM */
619 0x0, 0x0, 0x0, 0x4, /* subcap size */
620 0x0, 0x0, 0x1, 0x8, /* subcap value */
622 uint8_t response
[COMMAND_BUFFER_SIZE
];
623 size_t response_length
= sizeof(response
);
626 err
= tpm_sendrecv_command(command
, response
, &response_length
);
629 memcpy(pflags
, response
+ TPM_HEADER_SIZE
, sizeof(*pflags
));
634 uint32_t tpm_get_permissions(uint32_t index
, uint32_t *perm
)
636 const uint8_t command
[22] = {
637 0x0, 0xc1, /* TPM_TAG */
638 0x0, 0x0, 0x0, 0x16, /* parameter size */
639 0x0, 0x0, 0x0, 0x65, /* TPM_COMMAND_CODE */
643 const size_t index_offset
= 18;
644 const size_t perm_offset
= 60;
645 uint8_t buf
[COMMAND_BUFFER_SIZE
], response
[COMMAND_BUFFER_SIZE
];
646 size_t response_length
= sizeof(response
);
649 if (pack_byte_string(buf
, sizeof(buf
), "d", 0, command
, sizeof(command
),
650 index_offset
, index
))
651 return TPM_LIB_ERROR
;
652 err
= tpm_sendrecv_command(buf
, response
, &response_length
);
655 if (unpack_byte_string(response
, response_length
, "d",
657 return TPM_LIB_ERROR
;
662 #ifdef CONFIG_TPM_AUTH_SESSIONS
665 * Fill an authentication block in a request.
666 * This func can create the first as well as the second auth block (for
667 * double authorized commands).
669 * @param request pointer to the request (w/ uninitialised auth data)
670 * @param request_len0 length of the request without auth data
671 * @param handles_len length of the handles area in request
672 * @param auth_session pointer to the (valid) auth session to be used
673 * @param request_auth pointer to the auth block of the request to be filled
674 * @param auth authentication data (HMAC key)
676 static uint32_t create_request_auth(const void *request
, size_t request_len0
,
678 struct session_data
*auth_session
,
679 void *request_auth
, const void *auth
)
681 uint8_t hmac_data
[DIGEST_LENGTH
* 3 + 1];
682 sha1_context hash_ctx
;
683 const size_t command_code_offset
= 6;
684 const size_t auth_nonce_odd_offset
= 4;
685 const size_t auth_continue_offset
= 24;
686 const size_t auth_auth_offset
= 25;
688 if (!auth_session
|| !auth_session
->valid
)
689 return TPM_LIB_ERROR
;
691 sha1_starts(&hash_ctx
);
692 sha1_update(&hash_ctx
, request
+ command_code_offset
, 4);
693 if (request_len0
> TPM_REQUEST_HEADER_LENGTH
+ handles_len
)
694 sha1_update(&hash_ctx
,
695 request
+ TPM_REQUEST_HEADER_LENGTH
+ handles_len
,
696 request_len0
- TPM_REQUEST_HEADER_LENGTH
698 sha1_finish(&hash_ctx
, hmac_data
);
700 sha1_starts(&hash_ctx
);
701 sha1_update(&hash_ctx
, auth_session
->nonce_odd
, DIGEST_LENGTH
);
702 sha1_update(&hash_ctx
, hmac_data
, sizeof(hmac_data
));
703 sha1_finish(&hash_ctx
, auth_session
->nonce_odd
);
705 if (pack_byte_string(request_auth
, TPM_REQUEST_AUTH_LENGTH
, "dsb",
706 0, auth_session
->handle
,
707 auth_nonce_odd_offset
, auth_session
->nonce_odd
,
709 auth_continue_offset
, 1))
710 return TPM_LIB_ERROR
;
711 if (pack_byte_string(hmac_data
, sizeof(hmac_data
), "ss",
713 auth_session
->nonce_even
,
716 request_auth
+ auth_nonce_odd_offset
,
718 return TPM_LIB_ERROR
;
719 sha1_hmac(auth
, DIGEST_LENGTH
, hmac_data
, sizeof(hmac_data
),
720 request_auth
+ auth_auth_offset
);
726 * Verify an authentication block in a response.
727 * Since this func updates the nonce_even in the session data it has to be
728 * called when receiving a succesfull AUTH response.
729 * This func can verify the first as well as the second auth block (for
730 * double authorized commands).
732 * @param command_code command code of the request
733 * @param response pointer to the request (w/ uninitialised auth data)
734 * @param handles_len length of the handles area in response
735 * @param auth_session pointer to the (valid) auth session to be used
736 * @param response_auth pointer to the auth block of the response to be verified
737 * @param auth authentication data (HMAC key)
739 static uint32_t verify_response_auth(uint32_t command_code
,
740 const void *response
, size_t response_len0
,
742 struct session_data
*auth_session
,
743 const void *response_auth
, const void *auth
)
745 uint8_t hmac_data
[DIGEST_LENGTH
* 3 + 1];
746 uint8_t computed_auth
[DIGEST_LENGTH
];
747 sha1_context hash_ctx
;
748 const size_t return_code_offset
= 6;
749 const size_t auth_continue_offset
= 20;
750 const size_t auth_auth_offset
= 21;
751 uint8_t auth_continue
;
753 if (!auth_session
|| !auth_session
->valid
)
755 if (pack_byte_string(hmac_data
, sizeof(hmac_data
), "d",
757 return TPM_LIB_ERROR
;
758 if (response_len0
< TPM_RESPONSE_HEADER_LENGTH
)
759 return TPM_LIB_ERROR
;
761 sha1_starts(&hash_ctx
);
762 sha1_update(&hash_ctx
, response
+ return_code_offset
, 4);
763 sha1_update(&hash_ctx
, hmac_data
, 4);
764 if (response_len0
> TPM_RESPONSE_HEADER_LENGTH
+ handles_len
)
765 sha1_update(&hash_ctx
,
766 response
+ TPM_RESPONSE_HEADER_LENGTH
+ handles_len
,
767 response_len0
- TPM_RESPONSE_HEADER_LENGTH
769 sha1_finish(&hash_ctx
, hmac_data
);
771 memcpy(auth_session
->nonce_even
, response_auth
, DIGEST_LENGTH
);
772 auth_continue
= ((uint8_t *)response_auth
)[auth_continue_offset
];
773 if (pack_byte_string(hmac_data
, sizeof(hmac_data
), "ssb",
778 auth_session
->nonce_odd
,
782 return TPM_LIB_ERROR
;
784 sha1_hmac(auth
, DIGEST_LENGTH
, hmac_data
, sizeof(hmac_data
),
787 if (memcmp(computed_auth
, response_auth
+ auth_auth_offset
,
795 uint32_t tpm_terminate_auth_session(uint32_t auth_handle
)
797 const uint8_t command
[18] = {
798 0x00, 0xc1, /* TPM_TAG */
799 0x00, 0x00, 0x00, 0x00, /* parameter size */
800 0x00, 0x00, 0x00, 0xba, /* TPM_COMMAND_CODE */
801 0x00, 0x00, 0x00, 0x00, /* TPM_HANDLE */
802 0x00, 0x00, 0x00, 0x02, /* TPM_RESSOURCE_TYPE */
804 const size_t req_handle_offset
= TPM_REQUEST_HEADER_LENGTH
;
805 uint8_t request
[COMMAND_BUFFER_SIZE
];
807 if (pack_byte_string(request
, sizeof(request
), "sd",
808 0, command
, sizeof(command
),
809 req_handle_offset
, auth_handle
))
810 return TPM_LIB_ERROR
;
811 if (oiap_session
.valid
&& oiap_session
.handle
== auth_handle
)
812 oiap_session
.valid
= 0;
814 return tpm_sendrecv_command(request
, NULL
, NULL
);
817 uint32_t tpm_end_oiap(void)
819 uint32_t err
= TPM_SUCCESS
;
820 if (oiap_session
.valid
)
821 err
= tpm_terminate_auth_session(oiap_session
.handle
);
825 uint32_t tpm_oiap(uint32_t *auth_handle
)
827 const uint8_t command
[10] = {
828 0x00, 0xc1, /* TPM_TAG */
829 0x00, 0x00, 0x00, 0x0a, /* parameter size */
830 0x00, 0x00, 0x00, 0x0a, /* TPM_COMMAND_CODE */
832 const size_t res_auth_handle_offset
= TPM_RESPONSE_HEADER_LENGTH
;
833 const size_t res_nonce_even_offset
= TPM_RESPONSE_HEADER_LENGTH
+ 4;
834 uint8_t response
[COMMAND_BUFFER_SIZE
];
835 size_t response_length
= sizeof(response
);
838 if (oiap_session
.valid
)
839 tpm_terminate_auth_session(oiap_session
.handle
);
841 err
= tpm_sendrecv_command(command
, response
, &response_length
);
844 if (unpack_byte_string(response
, response_length
, "ds",
845 res_auth_handle_offset
, &oiap_session
.handle
,
846 res_nonce_even_offset
, &oiap_session
.nonce_even
,
847 (uint32_t)DIGEST_LENGTH
))
848 return TPM_LIB_ERROR
;
849 oiap_session
.valid
= 1;
851 *auth_handle
= oiap_session
.handle
;
855 uint32_t tpm_load_key2_oiap(uint32_t parent_handle
,
856 const void *key
, size_t key_length
,
857 const void *parent_key_usage_auth
,
858 uint32_t *key_handle
)
860 const uint8_t command
[14] = {
861 0x00, 0xc2, /* TPM_TAG */
862 0x00, 0x00, 0x00, 0x00, /* parameter size */
863 0x00, 0x00, 0x00, 0x41, /* TPM_COMMAND_CODE */
864 0x00, 0x00, 0x00, 0x00, /* parent handle */
866 const size_t req_size_offset
= 2;
867 const size_t req_parent_handle_offset
= TPM_REQUEST_HEADER_LENGTH
;
868 const size_t req_key_offset
= TPM_REQUEST_HEADER_LENGTH
+ 4;
869 const size_t res_handle_offset
= TPM_RESPONSE_HEADER_LENGTH
;
870 uint8_t request
[sizeof(command
) + TPM_KEY12_MAX_LENGTH
871 + TPM_REQUEST_AUTH_LENGTH
];
872 uint8_t response
[COMMAND_BUFFER_SIZE
];
873 size_t response_length
= sizeof(response
);
876 if (!oiap_session
.valid
) {
877 err
= tpm_oiap(NULL
);
881 if (pack_byte_string(request
, sizeof(request
), "sdds",
882 0, command
, sizeof(command
),
884 sizeof(command
) + key_length
885 + TPM_REQUEST_AUTH_LENGTH
,
886 req_parent_handle_offset
, parent_handle
,
887 req_key_offset
, key
, key_length
889 return TPM_LIB_ERROR
;
891 err
= create_request_auth(request
, sizeof(command
) + key_length
, 4,
893 request
+ sizeof(command
) + key_length
,
894 parent_key_usage_auth
);
897 err
= tpm_sendrecv_command(request
, response
, &response_length
);
899 if (err
== TPM_AUTHFAIL
)
900 oiap_session
.valid
= 0;
904 err
= verify_response_auth(0x00000041, response
,
905 response_length
- TPM_RESPONSE_AUTH_LENGTH
,
907 response
+ response_length
- TPM_RESPONSE_AUTH_LENGTH
,
908 parent_key_usage_auth
);
913 if (unpack_byte_string(response
, response_length
, "d",
914 res_handle_offset
, key_handle
))
915 return TPM_LIB_ERROR
;
921 uint32_t tpm_get_pub_key_oiap(uint32_t key_handle
, const void *usage_auth
,
922 void *pubkey
, size_t *pubkey_len
)
924 const uint8_t command
[14] = {
925 0x00, 0xc2, /* TPM_TAG */
926 0x00, 0x00, 0x00, 0x00, /* parameter size */
927 0x00, 0x00, 0x00, 0x21, /* TPM_COMMAND_CODE */
928 0x00, 0x00, 0x00, 0x00, /* key handle */
930 const size_t req_size_offset
= 2;
931 const size_t req_key_handle_offset
= TPM_REQUEST_HEADER_LENGTH
;
932 const size_t res_pubkey_offset
= TPM_RESPONSE_HEADER_LENGTH
;
933 uint8_t request
[sizeof(command
) + TPM_REQUEST_AUTH_LENGTH
];
934 uint8_t response
[TPM_RESPONSE_HEADER_LENGTH
+ TPM_PUBKEY_MAX_LENGTH
935 + TPM_RESPONSE_AUTH_LENGTH
];
936 size_t response_length
= sizeof(response
);
939 if (!oiap_session
.valid
) {
940 err
= tpm_oiap(NULL
);
944 if (pack_byte_string(request
, sizeof(request
), "sdd",
945 0, command
, sizeof(command
),
947 (uint32_t)(sizeof(command
)
948 + TPM_REQUEST_AUTH_LENGTH
),
949 req_key_handle_offset
, key_handle
951 return TPM_LIB_ERROR
;
952 err
= create_request_auth(request
, sizeof(command
), 4, &oiap_session
,
953 request
+ sizeof(command
), usage_auth
);
956 err
= tpm_sendrecv_command(request
, response
, &response_length
);
958 if (err
== TPM_AUTHFAIL
)
959 oiap_session
.valid
= 0;
962 err
= verify_response_auth(0x00000021, response
,
963 response_length
- TPM_RESPONSE_AUTH_LENGTH
,
965 response
+ response_length
- TPM_RESPONSE_AUTH_LENGTH
,
971 if ((response_length
- TPM_RESPONSE_HEADER_LENGTH
972 - TPM_RESPONSE_AUTH_LENGTH
) > *pubkey_len
)
973 return TPM_LIB_ERROR
;
974 *pubkey_len
= response_length
- TPM_RESPONSE_HEADER_LENGTH
975 - TPM_RESPONSE_AUTH_LENGTH
;
976 memcpy(pubkey
, response
+ res_pubkey_offset
,
977 response_length
- TPM_RESPONSE_HEADER_LENGTH
978 - TPM_RESPONSE_AUTH_LENGTH
);
984 #endif /* CONFIG_TPM_AUTH_SESSIONS */