1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright (c) 2013 The Chromium OS Authors.
4 * Coypright (c) 2013 Guntermann & Drunck GmbH
9 #include <asm/unaligned.h>
10 #include <u-boot/sha1.h>
11 #include <tpm-common.h>
13 #include "tpm-utils.h"
15 #ifdef CONFIG_TPM_AUTH_SESSIONS
18 #error "TPM_AUTH_SESSIONS require SHA1 to be configured, too"
19 #endif /* !CONFIG_SHA1 */
24 u8 nonce_even
[DIGEST_LENGTH
];
25 u8 nonce_odd
[DIGEST_LENGTH
];
28 static struct session_data oiap_session
= {0, };
30 #endif /* CONFIG_TPM_AUTH_SESSIONS */
32 u32
tpm_startup(enum tpm_startup_type mode
)
34 const u8 command
[12] = {
35 0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0x99, 0x0, 0x0,
37 const size_t mode_offset
= 10;
38 u8 buf
[COMMAND_BUFFER_SIZE
];
40 if (pack_byte_string(buf
, sizeof(buf
), "sw",
41 0, command
, sizeof(command
),
45 return tpm_sendrecv_command(buf
, NULL
, NULL
);
48 u32
tpm_self_test_full(void)
50 const u8 command
[10] = {
51 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x50,
53 return tpm_sendrecv_command(command
, NULL
, NULL
);
56 u32
tpm_continue_self_test(void)
58 const u8 command
[10] = {
59 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x53,
61 return tpm_sendrecv_command(command
, NULL
, NULL
);
64 u32
tpm_nv_define_space(u32 index
, u32 perm
, u32 size
)
66 const u8 command
[101] = {
67 0x0, 0xc1, /* TPM_TAG */
68 0x0, 0x0, 0x0, 0x65, /* parameter size */
69 0x0, 0x0, 0x0, 0xcc, /* TPM_COMMAND_CODE */
70 /* TPM_NV_DATA_PUBLIC->... */
71 0x0, 0x18, /* ...->TPM_STRUCTURE_TAG */
72 0, 0, 0, 0, /* ...->TPM_NV_INDEX */
73 /* TPM_NV_DATA_PUBLIC->TPM_PCR_INFO_SHORT */
77 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
78 /* TPM_NV_DATA_PUBLIC->TPM_PCR_INFO_SHORT */
82 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
83 /* TPM_NV_ATTRIBUTES->... */
84 0x0, 0x17, /* ...->TPM_STRUCTURE_TAG */
85 0, 0, 0, 0, /* ...->attributes */
86 /* End of TPM_NV_ATTRIBUTES */
88 0, /* bWriteSTClear */
90 0, 0, 0, 0, /* size */
92 const size_t index_offset
= 12;
93 const size_t perm_offset
= 70;
94 const size_t size_offset
= 77;
95 u8 buf
[COMMAND_BUFFER_SIZE
];
97 if (pack_byte_string(buf
, sizeof(buf
), "sddd",
98 0, command
, sizeof(command
),
102 return TPM_LIB_ERROR
;
104 return tpm_sendrecv_command(buf
, NULL
, NULL
);
107 u32
tpm_nv_read_value(u32 index
, void *data
, u32 count
)
109 const u8 command
[22] = {
110 0x0, 0xc1, 0x0, 0x0, 0x0, 0x16, 0x0, 0x0, 0x0, 0xcf,
112 const size_t index_offset
= 10;
113 const size_t length_offset
= 18;
114 const size_t data_size_offset
= 10;
115 const size_t data_offset
= 14;
116 u8 buf
[COMMAND_BUFFER_SIZE
], response
[COMMAND_BUFFER_SIZE
];
117 size_t response_length
= sizeof(response
);
121 if (pack_byte_string(buf
, sizeof(buf
), "sdd",
122 0, command
, sizeof(command
),
124 length_offset
, count
))
125 return TPM_LIB_ERROR
;
126 err
= tpm_sendrecv_command(buf
, response
, &response_length
);
129 if (unpack_byte_string(response
, response_length
, "d",
130 data_size_offset
, &data_size
))
131 return TPM_LIB_ERROR
;
132 if (data_size
> count
)
133 return TPM_LIB_ERROR
;
134 if (unpack_byte_string(response
, response_length
, "s",
135 data_offset
, data
, data_size
))
136 return TPM_LIB_ERROR
;
141 u32
tpm_nv_write_value(u32 index
, const void *data
, u32 length
)
143 const u8 command
[256] = {
144 0x0, 0xc1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xcd,
146 const size_t command_size_offset
= 2;
147 const size_t index_offset
= 10;
148 const size_t length_offset
= 18;
149 const size_t data_offset
= 22;
150 const size_t write_info_size
= 12;
151 const u32 total_length
=
152 TPM_REQUEST_HEADER_LENGTH
+ write_info_size
+ length
;
153 u8 buf
[COMMAND_BUFFER_SIZE
], response
[COMMAND_BUFFER_SIZE
];
154 size_t response_length
= sizeof(response
);
157 if (pack_byte_string(buf
, sizeof(buf
), "sddds",
158 0, command
, sizeof(command
),
159 command_size_offset
, total_length
,
161 length_offset
, length
,
162 data_offset
, data
, length
))
163 return TPM_LIB_ERROR
;
164 err
= tpm_sendrecv_command(buf
, response
, &response_length
);
171 u32
tpm_extend(u32 index
, const void *in_digest
, void *out_digest
)
173 const u8 command
[34] = {
174 0x0, 0xc1, 0x0, 0x0, 0x0, 0x22, 0x0, 0x0, 0x0, 0x14,
176 const size_t index_offset
= 10;
177 const size_t in_digest_offset
= 14;
178 const size_t out_digest_offset
= 10;
179 u8 buf
[COMMAND_BUFFER_SIZE
];
180 u8 response
[TPM_RESPONSE_HEADER_LENGTH
+ PCR_DIGEST_LENGTH
];
181 size_t response_length
= sizeof(response
);
184 if (pack_byte_string(buf
, sizeof(buf
), "sds",
185 0, command
, sizeof(command
),
187 in_digest_offset
, in_digest
,
189 return TPM_LIB_ERROR
;
190 err
= tpm_sendrecv_command(buf
, response
, &response_length
);
194 if (unpack_byte_string(response
, response_length
, "s",
195 out_digest_offset
, out_digest
,
197 return TPM_LIB_ERROR
;
202 u32
tpm_pcr_read(u32 index
, void *data
, size_t count
)
204 const u8 command
[14] = {
205 0x0, 0xc1, 0x0, 0x0, 0x0, 0xe, 0x0, 0x0, 0x0, 0x15,
207 const size_t index_offset
= 10;
208 const size_t out_digest_offset
= 10;
209 u8 buf
[COMMAND_BUFFER_SIZE
], response
[COMMAND_BUFFER_SIZE
];
210 size_t response_length
= sizeof(response
);
213 if (count
< PCR_DIGEST_LENGTH
)
214 return TPM_LIB_ERROR
;
216 if (pack_byte_string(buf
, sizeof(buf
), "sd",
217 0, command
, sizeof(command
),
218 index_offset
, index
))
219 return TPM_LIB_ERROR
;
220 err
= tpm_sendrecv_command(buf
, response
, &response_length
);
223 if (unpack_byte_string(response
, response_length
, "s",
224 out_digest_offset
, data
, PCR_DIGEST_LENGTH
))
225 return TPM_LIB_ERROR
;
230 u32
tpm_tsc_physical_presence(u16 presence
)
232 const u8 command
[12] = {
233 0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x40, 0x0, 0x0, 0xa, 0x0, 0x0,
235 const size_t presence_offset
= 10;
236 u8 buf
[COMMAND_BUFFER_SIZE
];
238 if (pack_byte_string(buf
, sizeof(buf
), "sw",
239 0, command
, sizeof(command
),
240 presence_offset
, presence
))
241 return TPM_LIB_ERROR
;
243 return tpm_sendrecv_command(buf
, NULL
, NULL
);
246 u32
tpm_read_pubek(void *data
, size_t count
)
248 const u8 command
[30] = {
249 0x0, 0xc1, 0x0, 0x0, 0x0, 0x1e, 0x0, 0x0, 0x0, 0x7c,
251 const size_t response_size_offset
= 2;
252 const size_t data_offset
= 10;
253 const size_t header_and_checksum_size
= TPM_RESPONSE_HEADER_LENGTH
+ 20;
254 u8 response
[COMMAND_BUFFER_SIZE
+ TPM_PUBEK_SIZE
];
255 size_t response_length
= sizeof(response
);
259 err
= tpm_sendrecv_command(command
, response
, &response_length
);
262 if (unpack_byte_string(response
, response_length
, "d",
263 response_size_offset
, &data_size
))
264 return TPM_LIB_ERROR
;
265 if (data_size
< header_and_checksum_size
)
266 return TPM_LIB_ERROR
;
267 data_size
-= header_and_checksum_size
;
268 if (data_size
> count
)
269 return TPM_LIB_ERROR
;
270 if (unpack_byte_string(response
, response_length
, "s",
271 data_offset
, data
, data_size
))
272 return TPM_LIB_ERROR
;
277 u32
tpm_force_clear(void)
279 const u8 command
[10] = {
280 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x5d,
283 return tpm_sendrecv_command(command
, NULL
, NULL
);
286 u32
tpm_physical_enable(void)
288 const u8 command
[10] = {
289 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x6f,
292 return tpm_sendrecv_command(command
, NULL
, NULL
);
295 u32
tpm_physical_disable(void)
297 const u8 command
[10] = {
298 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x70,
301 return tpm_sendrecv_command(command
, NULL
, NULL
);
304 u32
tpm_physical_set_deactivated(u8 state
)
306 const u8 command
[11] = {
307 0x0, 0xc1, 0x0, 0x0, 0x0, 0xb, 0x0, 0x0, 0x0, 0x72,
309 const size_t state_offset
= 10;
310 u8 buf
[COMMAND_BUFFER_SIZE
];
312 if (pack_byte_string(buf
, sizeof(buf
), "sb",
313 0, command
, sizeof(command
),
314 state_offset
, state
))
315 return TPM_LIB_ERROR
;
317 return tpm_sendrecv_command(buf
, NULL
, NULL
);
320 u32
tpm_get_capability(u32 cap_area
, u32 sub_cap
, void *cap
, size_t count
)
322 const u8 command
[22] = {
323 0x0, 0xc1, /* TPM_TAG */
324 0x0, 0x0, 0x0, 0x16, /* parameter size */
325 0x0, 0x0, 0x0, 0x65, /* TPM_COMMAND_CODE */
326 0x0, 0x0, 0x0, 0x0, /* TPM_CAPABILITY_AREA */
327 0x0, 0x0, 0x0, 0x4, /* subcap size */
328 0x0, 0x0, 0x0, 0x0, /* subcap value */
330 const size_t cap_area_offset
= 10;
331 const size_t sub_cap_offset
= 18;
332 const size_t cap_offset
= 14;
333 const size_t cap_size_offset
= 10;
334 u8 buf
[COMMAND_BUFFER_SIZE
], response
[COMMAND_BUFFER_SIZE
];
335 size_t response_length
= sizeof(response
);
339 if (pack_byte_string(buf
, sizeof(buf
), "sdd",
340 0, command
, sizeof(command
),
341 cap_area_offset
, cap_area
,
342 sub_cap_offset
, sub_cap
))
343 return TPM_LIB_ERROR
;
344 err
= tpm_sendrecv_command(buf
, response
, &response_length
);
347 if (unpack_byte_string(response
, response_length
, "d",
348 cap_size_offset
, &cap_size
))
349 return TPM_LIB_ERROR
;
350 if (cap_size
> response_length
|| cap_size
> count
)
351 return TPM_LIB_ERROR
;
352 if (unpack_byte_string(response
, response_length
, "s",
353 cap_offset
, cap
, cap_size
))
354 return TPM_LIB_ERROR
;
359 u32
tpm_get_permanent_flags(struct tpm_permanent_flags
*pflags
)
361 const u8 command
[22] = {
362 0x0, 0xc1, /* TPM_TAG */
363 0x0, 0x0, 0x0, 0x16, /* parameter size */
364 0x0, 0x0, 0x0, 0x65, /* TPM_COMMAND_CODE */
365 0x0, 0x0, 0x0, 0x4, /* TPM_CAP_FLAG_PERM */
366 0x0, 0x0, 0x0, 0x4, /* subcap size */
367 0x0, 0x0, 0x1, 0x8, /* subcap value */
369 const size_t data_size_offset
= TPM_HEADER_SIZE
;
370 const size_t data_offset
= TPM_HEADER_SIZE
+ sizeof(u32
);
371 u8 response
[COMMAND_BUFFER_SIZE
];
372 size_t response_length
= sizeof(response
);
376 err
= tpm_sendrecv_command(command
, response
, &response_length
);
379 if (unpack_byte_string(response
, response_length
, "d",
380 data_size_offset
, &data_size
))
381 return TPM_LIB_ERROR
;
382 if (data_size
< sizeof(*pflags
))
383 return TPM_LIB_ERROR
;
384 if (unpack_byte_string(response
, response_length
, "s",
385 data_offset
, pflags
, sizeof(*pflags
)))
386 return TPM_LIB_ERROR
;
391 u32
tpm_get_permissions(u32 index
, u32
*perm
)
393 const u8 command
[22] = {
394 0x0, 0xc1, /* TPM_TAG */
395 0x0, 0x0, 0x0, 0x16, /* parameter size */
396 0x0, 0x0, 0x0, 0x65, /* TPM_COMMAND_CODE */
400 const size_t index_offset
= 18;
401 const size_t perm_offset
= 60;
402 u8 buf
[COMMAND_BUFFER_SIZE
], response
[COMMAND_BUFFER_SIZE
];
403 size_t response_length
= sizeof(response
);
406 if (pack_byte_string(buf
, sizeof(buf
), "d", 0, command
, sizeof(command
),
407 index_offset
, index
))
408 return TPM_LIB_ERROR
;
409 err
= tpm_sendrecv_command(buf
, response
, &response_length
);
412 if (unpack_byte_string(response
, response_length
, "d",
414 return TPM_LIB_ERROR
;
419 #ifdef CONFIG_TPM_FLUSH_RESOURCES
420 u32
tpm_flush_specific(u32 key_handle
, u32 resource_type
)
422 const u8 command
[18] = {
423 0x00, 0xc1, /* TPM_TAG */
424 0x00, 0x00, 0x00, 0x12, /* parameter size */
425 0x00, 0x00, 0x00, 0xba, /* TPM_COMMAND_CODE */
426 0x00, 0x00, 0x00, 0x00, /* key handle */
427 0x00, 0x00, 0x00, 0x00, /* resource type */
429 const size_t key_handle_offset
= 10;
430 const size_t resource_type_offset
= 14;
431 u8 buf
[COMMAND_BUFFER_SIZE
], response
[COMMAND_BUFFER_SIZE
];
432 size_t response_length
= sizeof(response
);
435 if (pack_byte_string(buf
, sizeof(buf
), "sdd",
436 0, command
, sizeof(command
),
437 key_handle_offset
, key_handle
,
438 resource_type_offset
, resource_type
))
439 return TPM_LIB_ERROR
;
441 err
= tpm_sendrecv_command(buf
, response
, &response_length
);
446 #endif /* CONFIG_TPM_FLUSH_RESOURCES */
448 #ifdef CONFIG_TPM_AUTH_SESSIONS
451 * Fill an authentication block in a request.
452 * This func can create the first as well as the second auth block (for
453 * double authorized commands).
455 * @param request pointer to the request (w/ uninitialised auth data)
456 * @param request_len0 length of the request without auth data
457 * @param handles_len length of the handles area in request
458 * @param auth_session pointer to the (valid) auth session to be used
459 * @param request_auth pointer to the auth block of the request to be filled
460 * @param auth authentication data (HMAC key)
462 static u32
create_request_auth(const void *request
, size_t request_len0
,
464 struct session_data
*auth_session
,
465 void *request_auth
, const void *auth
)
467 u8 hmac_data
[DIGEST_LENGTH
* 3 + 1];
468 sha1_context hash_ctx
;
469 const size_t command_code_offset
= 6;
470 const size_t auth_nonce_odd_offset
= 4;
471 const size_t auth_continue_offset
= 24;
472 const size_t auth_auth_offset
= 25;
474 if (!auth_session
|| !auth_session
->valid
)
475 return TPM_LIB_ERROR
;
477 sha1_starts(&hash_ctx
);
478 sha1_update(&hash_ctx
, request
+ command_code_offset
, 4);
479 if (request_len0
> TPM_REQUEST_HEADER_LENGTH
+ handles_len
)
480 sha1_update(&hash_ctx
,
481 request
+ TPM_REQUEST_HEADER_LENGTH
+ handles_len
,
482 request_len0
- TPM_REQUEST_HEADER_LENGTH
484 sha1_finish(&hash_ctx
, hmac_data
);
486 sha1_starts(&hash_ctx
);
487 sha1_update(&hash_ctx
, auth_session
->nonce_odd
, DIGEST_LENGTH
);
488 sha1_update(&hash_ctx
, hmac_data
, sizeof(hmac_data
));
489 sha1_finish(&hash_ctx
, auth_session
->nonce_odd
);
491 if (pack_byte_string(request_auth
, TPM_REQUEST_AUTH_LENGTH
, "dsb",
492 0, auth_session
->handle
,
493 auth_nonce_odd_offset
, auth_session
->nonce_odd
,
495 auth_continue_offset
, 1))
496 return TPM_LIB_ERROR
;
497 if (pack_byte_string(hmac_data
, sizeof(hmac_data
), "ss",
499 auth_session
->nonce_even
,
502 request_auth
+ auth_nonce_odd_offset
,
504 return TPM_LIB_ERROR
;
505 sha1_hmac(auth
, DIGEST_LENGTH
, hmac_data
, sizeof(hmac_data
),
506 request_auth
+ auth_auth_offset
);
512 * Verify an authentication block in a response.
513 * Since this func updates the nonce_even in the session data it has to be
514 * called when receiving a succesfull AUTH response.
515 * This func can verify the first as well as the second auth block (for
516 * double authorized commands).
518 * @param command_code command code of the request
519 * @param response pointer to the request (w/ uninitialised auth data)
520 * @param handles_len length of the handles area in response
521 * @param auth_session pointer to the (valid) auth session to be used
522 * @param response_auth pointer to the auth block of the response to be verified
523 * @param auth authentication data (HMAC key)
525 static u32
verify_response_auth(u32 command_code
, const void *response
,
526 size_t response_len0
, size_t handles_len
,
527 struct session_data
*auth_session
,
528 const void *response_auth
, const void *auth
)
530 u8 hmac_data
[DIGEST_LENGTH
* 3 + 1];
531 u8 computed_auth
[DIGEST_LENGTH
];
532 sha1_context hash_ctx
;
533 const size_t return_code_offset
= 6;
534 const size_t auth_continue_offset
= 20;
535 const size_t auth_auth_offset
= 21;
538 if (!auth_session
|| !auth_session
->valid
)
540 if (pack_byte_string(hmac_data
, sizeof(hmac_data
), "d",
542 return TPM_LIB_ERROR
;
543 if (response_len0
< TPM_RESPONSE_HEADER_LENGTH
)
544 return TPM_LIB_ERROR
;
546 sha1_starts(&hash_ctx
);
547 sha1_update(&hash_ctx
, response
+ return_code_offset
, 4);
548 sha1_update(&hash_ctx
, hmac_data
, 4);
549 if (response_len0
> TPM_RESPONSE_HEADER_LENGTH
+ handles_len
)
550 sha1_update(&hash_ctx
,
551 response
+ TPM_RESPONSE_HEADER_LENGTH
+ handles_len
,
552 response_len0
- TPM_RESPONSE_HEADER_LENGTH
554 sha1_finish(&hash_ctx
, hmac_data
);
556 memcpy(auth_session
->nonce_even
, response_auth
, DIGEST_LENGTH
);
557 auth_continue
= ((u8
*)response_auth
)[auth_continue_offset
];
558 if (pack_byte_string(hmac_data
, sizeof(hmac_data
), "ssb",
563 auth_session
->nonce_odd
,
567 return TPM_LIB_ERROR
;
569 sha1_hmac(auth
, DIGEST_LENGTH
, hmac_data
, sizeof(hmac_data
),
572 if (memcmp(computed_auth
, response_auth
+ auth_auth_offset
,
579 u32
tpm_terminate_auth_session(u32 auth_handle
)
581 const u8 command
[18] = {
582 0x00, 0xc1, /* TPM_TAG */
583 0x00, 0x00, 0x00, 0x00, /* parameter size */
584 0x00, 0x00, 0x00, 0xba, /* TPM_COMMAND_CODE */
585 0x00, 0x00, 0x00, 0x00, /* TPM_HANDLE */
586 0x00, 0x00, 0x00, 0x02, /* TPM_RESOURCE_TYPE */
588 const size_t req_handle_offset
= TPM_REQUEST_HEADER_LENGTH
;
589 u8 request
[COMMAND_BUFFER_SIZE
];
591 if (pack_byte_string(request
, sizeof(request
), "sd",
592 0, command
, sizeof(command
),
593 req_handle_offset
, auth_handle
))
594 return TPM_LIB_ERROR
;
595 if (oiap_session
.valid
&& oiap_session
.handle
== auth_handle
)
596 oiap_session
.valid
= 0;
598 return tpm_sendrecv_command(request
, NULL
, NULL
);
601 u32
tpm_end_oiap(void)
603 u32 err
= TPM_SUCCESS
;
605 if (oiap_session
.valid
)
606 err
= tpm_terminate_auth_session(oiap_session
.handle
);
610 u32
tpm_oiap(u32
*auth_handle
)
612 const u8 command
[10] = {
613 0x00, 0xc1, /* TPM_TAG */
614 0x00, 0x00, 0x00, 0x0a, /* parameter size */
615 0x00, 0x00, 0x00, 0x0a, /* TPM_COMMAND_CODE */
617 const size_t res_auth_handle_offset
= TPM_RESPONSE_HEADER_LENGTH
;
618 const size_t res_nonce_even_offset
= TPM_RESPONSE_HEADER_LENGTH
+ 4;
619 u8 response
[COMMAND_BUFFER_SIZE
];
620 size_t response_length
= sizeof(response
);
623 if (oiap_session
.valid
)
624 tpm_terminate_auth_session(oiap_session
.handle
);
626 err
= tpm_sendrecv_command(command
, response
, &response_length
);
629 if (unpack_byte_string(response
, response_length
, "ds",
630 res_auth_handle_offset
, &oiap_session
.handle
,
631 res_nonce_even_offset
, &oiap_session
.nonce_even
,
633 return TPM_LIB_ERROR
;
634 oiap_session
.valid
= 1;
636 *auth_handle
= oiap_session
.handle
;
640 u32
tpm_load_key2_oiap(u32 parent_handle
, const void *key
, size_t key_length
,
641 const void *parent_key_usage_auth
, u32
*key_handle
)
643 const u8 command
[14] = {
644 0x00, 0xc2, /* TPM_TAG */
645 0x00, 0x00, 0x00, 0x00, /* parameter size */
646 0x00, 0x00, 0x00, 0x41, /* TPM_COMMAND_CODE */
647 0x00, 0x00, 0x00, 0x00, /* parent handle */
649 const size_t req_size_offset
= 2;
650 const size_t req_parent_handle_offset
= TPM_REQUEST_HEADER_LENGTH
;
651 const size_t req_key_offset
= TPM_REQUEST_HEADER_LENGTH
+ 4;
652 const size_t res_handle_offset
= TPM_RESPONSE_HEADER_LENGTH
;
653 u8 request
[sizeof(command
) + TPM_KEY12_MAX_LENGTH
+
654 TPM_REQUEST_AUTH_LENGTH
];
655 u8 response
[COMMAND_BUFFER_SIZE
];
656 size_t response_length
= sizeof(response
);
659 if (!oiap_session
.valid
) {
660 err
= tpm_oiap(NULL
);
664 if (pack_byte_string(request
, sizeof(request
), "sdds",
665 0, command
, sizeof(command
),
667 sizeof(command
) + key_length
668 + TPM_REQUEST_AUTH_LENGTH
,
669 req_parent_handle_offset
, parent_handle
,
670 req_key_offset
, key
, key_length
672 return TPM_LIB_ERROR
;
674 err
= create_request_auth(request
, sizeof(command
) + key_length
, 4,
676 request
+ sizeof(command
) + key_length
,
677 parent_key_usage_auth
);
680 err
= tpm_sendrecv_command(request
, response
, &response_length
);
682 if (err
== TPM_AUTHFAIL
)
683 oiap_session
.valid
= 0;
687 err
= verify_response_auth(0x00000041, response
,
688 response_length
- TPM_RESPONSE_AUTH_LENGTH
,
690 response
+ response_length
-
691 TPM_RESPONSE_AUTH_LENGTH
,
692 parent_key_usage_auth
);
697 if (unpack_byte_string(response
, response_length
, "d",
698 res_handle_offset
, key_handle
))
699 return TPM_LIB_ERROR
;
705 u32
tpm_get_pub_key_oiap(u32 key_handle
, const void *usage_auth
, void *pubkey
,
708 const u8 command
[14] = {
709 0x00, 0xc2, /* TPM_TAG */
710 0x00, 0x00, 0x00, 0x00, /* parameter size */
711 0x00, 0x00, 0x00, 0x21, /* TPM_COMMAND_CODE */
712 0x00, 0x00, 0x00, 0x00, /* key handle */
714 const size_t req_size_offset
= 2;
715 const size_t req_key_handle_offset
= TPM_REQUEST_HEADER_LENGTH
;
716 const size_t res_pubkey_offset
= TPM_RESPONSE_HEADER_LENGTH
;
717 u8 request
[sizeof(command
) + TPM_REQUEST_AUTH_LENGTH
];
718 u8 response
[TPM_RESPONSE_HEADER_LENGTH
+ TPM_PUBKEY_MAX_LENGTH
+
719 TPM_RESPONSE_AUTH_LENGTH
];
720 size_t response_length
= sizeof(response
);
723 if (!oiap_session
.valid
) {
724 err
= tpm_oiap(NULL
);
728 if (pack_byte_string(request
, sizeof(request
), "sdd",
729 0, command
, sizeof(command
),
731 (u32
)(sizeof(command
)
732 + TPM_REQUEST_AUTH_LENGTH
),
733 req_key_handle_offset
, key_handle
735 return TPM_LIB_ERROR
;
736 err
= create_request_auth(request
, sizeof(command
), 4, &oiap_session
,
737 request
+ sizeof(command
), usage_auth
);
740 err
= tpm_sendrecv_command(request
, response
, &response_length
);
742 if (err
== TPM_AUTHFAIL
)
743 oiap_session
.valid
= 0;
746 err
= verify_response_auth(0x00000021, response
,
747 response_length
- TPM_RESPONSE_AUTH_LENGTH
,
749 response
+ response_length
-
750 TPM_RESPONSE_AUTH_LENGTH
,
756 if ((response_length
- TPM_RESPONSE_HEADER_LENGTH
757 - TPM_RESPONSE_AUTH_LENGTH
) > *pubkey_len
)
758 return TPM_LIB_ERROR
;
759 *pubkey_len
= response_length
- TPM_RESPONSE_HEADER_LENGTH
760 - TPM_RESPONSE_AUTH_LENGTH
;
761 memcpy(pubkey
, response
+ res_pubkey_offset
,
762 response_length
- TPM_RESPONSE_HEADER_LENGTH
763 - TPM_RESPONSE_AUTH_LENGTH
);
769 #ifdef CONFIG_TPM_LOAD_KEY_BY_SHA1
770 u32
tpm_find_key_sha1(const u8 auth
[20], const u8 pubkey_digest
[20],
782 /* fetch list of already loaded keys in the TPM */
783 err
= tpm_get_capability(TPM_CAP_HANDLE
, TPM_RT_KEY
, buf
, sizeof(buf
));
786 key_count
= get_unaligned_be16(buf
);
788 for (i
= 0; i
< key_count
; ++i
, ptr
+= 4)
789 key_handles
[i
] = get_unaligned_be32(ptr
);
791 /* now search a(/ the) key which we can access with the given auth */
792 for (i
= 0; i
< key_count
; ++i
) {
793 buf_len
= sizeof(buf
);
794 err
= tpm_get_pub_key_oiap(key_handles
[i
], auth
, buf
, &buf_len
);
795 if (err
&& err
!= TPM_AUTHFAIL
)
799 sha1_csum(buf
, buf_len
, digest
);
800 if (!memcmp(digest
, pubkey_digest
, 20)) {
801 *handle
= key_handles
[i
];
807 #endif /* CONFIG_TPM_LOAD_KEY_BY_SHA1 */
809 #endif /* CONFIG_TPM_AUTH_SESSIONS */
811 u32
tpm_get_random(void *data
, u32 count
)
813 const u8 command
[14] = {
814 0x0, 0xc1, /* TPM_TAG */
815 0x0, 0x0, 0x0, 0xe, /* parameter size */
816 0x0, 0x0, 0x0, 0x46, /* TPM_COMMAND_CODE */
818 const size_t length_offset
= 10;
819 const size_t data_size_offset
= 10;
820 const size_t data_offset
= 14;
821 u8 buf
[COMMAND_BUFFER_SIZE
], response
[COMMAND_BUFFER_SIZE
];
822 size_t response_length
= sizeof(response
);
827 u32 this_bytes
= min((size_t)count
,
828 sizeof(response
) - data_offset
);
831 if (pack_byte_string(buf
, sizeof(buf
), "sd",
832 0, command
, sizeof(command
),
833 length_offset
, this_bytes
))
834 return TPM_LIB_ERROR
;
835 err
= tpm_sendrecv_command(buf
, response
, &response_length
);
838 if (unpack_byte_string(response
, response_length
, "d",
839 data_size_offset
, &data_size
))
840 return TPM_LIB_ERROR
;
841 if (data_size
> count
)
842 return TPM_LIB_ERROR
;
843 if (unpack_byte_string(response
, response_length
, "s",
844 data_offset
, out
, data_size
))
845 return TPM_LIB_ERROR
;