]> git.ipfire.org Git - thirdparty/u-boot.git/blob - lib/tpm-v1.c
9d45c3d3bf66a163c86b29617c00dca8c9d0614f
[thirdparty/u-boot.git] / lib / tpm-v1.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3 * Copyright (c) 2013 The Chromium OS Authors.
4 * Coypright (c) 2013 Guntermann & Drunck GmbH
5 */
6
7 #define LOG_CATEGORY UCLASS_TPM
8
9 #include <common.h>
10 #include <dm.h>
11 #include <asm/unaligned.h>
12 #include <u-boot/sha1.h>
13 #include <tpm-common.h>
14 #include <tpm-v1.h>
15 #include "tpm-utils.h"
16
17 #ifdef CONFIG_TPM_AUTH_SESSIONS
18
19 #ifndef CONFIG_SHA1
20 #error "TPM_AUTH_SESSIONS require SHA1 to be configured, too"
21 #endif /* !CONFIG_SHA1 */
22
23 struct session_data {
24 int valid;
25 u32 handle;
26 u8 nonce_even[DIGEST_LENGTH];
27 u8 nonce_odd[DIGEST_LENGTH];
28 };
29
30 static struct session_data oiap_session = {0, };
31
32 #endif /* CONFIG_TPM_AUTH_SESSIONS */
33
34 u32 tpm_startup(enum tpm_startup_type mode)
35 {
36 const u8 command[12] = {
37 0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0x99, 0x0, 0x0,
38 };
39 const size_t mode_offset = 10;
40 u8 buf[COMMAND_BUFFER_SIZE];
41
42 if (pack_byte_string(buf, sizeof(buf), "sw",
43 0, command, sizeof(command),
44 mode_offset, mode))
45 return TPM_LIB_ERROR;
46
47 return tpm_sendrecv_command(buf, NULL, NULL);
48 }
49
50 u32 tpm_resume(void)
51 {
52 return tpm_startup(TPM_ST_STATE);
53 }
54
55 u32 tpm_self_test_full(void)
56 {
57 const u8 command[10] = {
58 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x50,
59 };
60 return tpm_sendrecv_command(command, NULL, NULL);
61 }
62
63 u32 tpm_continue_self_test(void)
64 {
65 const u8 command[10] = {
66 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x53,
67 };
68 return tpm_sendrecv_command(command, NULL, NULL);
69 }
70
71 u32 tpm_clear_and_reenable(void)
72 {
73 u32 ret;
74
75 log_info("TPM: Clear and re-enable\n");
76 ret = tpm_force_clear();
77 if (ret != TPM_SUCCESS) {
78 log_err("Can't initiate a force clear\n");
79 return ret;
80 }
81
82 #if IS_ENABLED(CONFIG_TPM_V1)
83 ret = tpm_physical_enable();
84 if (ret != TPM_SUCCESS) {
85 log_err("TPM: Can't set enabled state\n");
86 return ret;
87 }
88
89 ret = tpm_physical_set_deactivated(0);
90 if (ret != TPM_SUCCESS) {
91 log_err("TPM: Can't set deactivated state\n");
92 return ret;
93 }
94 #endif
95
96 return TPM_SUCCESS;
97 }
98
99 u32 tpm_nv_define_space(u32 index, u32 perm, u32 size)
100 {
101 const u8 command[101] = {
102 0x0, 0xc1, /* TPM_TAG */
103 0x0, 0x0, 0x0, 0x65, /* parameter size */
104 0x0, 0x0, 0x0, 0xcc, /* TPM_COMMAND_CODE */
105 /* TPM_NV_DATA_PUBLIC->... */
106 0x0, 0x18, /* ...->TPM_STRUCTURE_TAG */
107 0, 0, 0, 0, /* ...->TPM_NV_INDEX */
108 /* TPM_NV_DATA_PUBLIC->TPM_PCR_INFO_SHORT */
109 0x0, 0x3,
110 0, 0, 0,
111 0x1f,
112 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
113 /* TPM_NV_DATA_PUBLIC->TPM_PCR_INFO_SHORT */
114 0x0, 0x3,
115 0, 0, 0,
116 0x1f,
117 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
118 /* TPM_NV_ATTRIBUTES->... */
119 0x0, 0x17, /* ...->TPM_STRUCTURE_TAG */
120 0, 0, 0, 0, /* ...->attributes */
121 /* End of TPM_NV_ATTRIBUTES */
122 0, /* bReadSTClear */
123 0, /* bWriteSTClear */
124 0, /* bWriteDefine */
125 0, 0, 0, 0, /* size */
126 };
127 const size_t index_offset = 12;
128 const size_t perm_offset = 70;
129 const size_t size_offset = 77;
130 u8 buf[COMMAND_BUFFER_SIZE];
131
132 if (pack_byte_string(buf, sizeof(buf), "sddd",
133 0, command, sizeof(command),
134 index_offset, index,
135 perm_offset, perm,
136 size_offset, size))
137 return TPM_LIB_ERROR;
138
139 return tpm_sendrecv_command(buf, NULL, NULL);
140 }
141
142 u32 tpm_nv_set_locked(void)
143 {
144 return tpm_nv_define_space(TPM_NV_INDEX_LOCK, 0, 0);
145 }
146
147 u32 tpm_nv_read_value(u32 index, void *data, u32 count)
148 {
149 const u8 command[22] = {
150 0x0, 0xc1, 0x0, 0x0, 0x0, 0x16, 0x0, 0x0, 0x0, 0xcf,
151 };
152 const size_t index_offset = 10;
153 const size_t length_offset = 18;
154 const size_t data_size_offset = 10;
155 const size_t data_offset = 14;
156 u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
157 size_t response_length = sizeof(response);
158 u32 data_size;
159 u32 err;
160
161 if (pack_byte_string(buf, sizeof(buf), "sdd",
162 0, command, sizeof(command),
163 index_offset, index,
164 length_offset, count))
165 return TPM_LIB_ERROR;
166 err = tpm_sendrecv_command(buf, response, &response_length);
167 if (err)
168 return err;
169 if (unpack_byte_string(response, response_length, "d",
170 data_size_offset, &data_size))
171 return TPM_LIB_ERROR;
172 if (data_size > count)
173 return TPM_LIB_ERROR;
174 if (unpack_byte_string(response, response_length, "s",
175 data_offset, data, data_size))
176 return TPM_LIB_ERROR;
177
178 return 0;
179 }
180
181 u32 tpm_nv_write_value(u32 index, const void *data, u32 length)
182 {
183 const u8 command[256] = {
184 0x0, 0xc1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xcd,
185 };
186 const size_t command_size_offset = 2;
187 const size_t index_offset = 10;
188 const size_t length_offset = 18;
189 const size_t data_offset = 22;
190 const size_t write_info_size = 12;
191 const u32 total_length =
192 TPM_REQUEST_HEADER_LENGTH + write_info_size + length;
193 u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
194 size_t response_length = sizeof(response);
195 u32 err;
196
197 if (pack_byte_string(buf, sizeof(buf), "sddds",
198 0, command, sizeof(command),
199 command_size_offset, total_length,
200 index_offset, index,
201 length_offset, length,
202 data_offset, data, length))
203 return TPM_LIB_ERROR;
204 err = tpm_sendrecv_command(buf, response, &response_length);
205 if (err)
206 return err;
207
208 return 0;
209 }
210
211 uint32_t tpm_set_global_lock(void)
212 {
213 u32 x;
214
215 return tpm_nv_write_value(TPM_NV_INDEX_0, (uint8_t *)&x, 0);
216 }
217
218 u32 tpm_extend(u32 index, const void *in_digest, void *out_digest)
219 {
220 const u8 command[34] = {
221 0x0, 0xc1, 0x0, 0x0, 0x0, 0x22, 0x0, 0x0, 0x0, 0x14,
222 };
223 const size_t index_offset = 10;
224 const size_t in_digest_offset = 14;
225 const size_t out_digest_offset = 10;
226 u8 buf[COMMAND_BUFFER_SIZE];
227 u8 response[TPM_RESPONSE_HEADER_LENGTH + PCR_DIGEST_LENGTH];
228 size_t response_length = sizeof(response);
229 u32 err;
230
231 if (pack_byte_string(buf, sizeof(buf), "sds",
232 0, command, sizeof(command),
233 index_offset, index,
234 in_digest_offset, in_digest,
235 PCR_DIGEST_LENGTH))
236 return TPM_LIB_ERROR;
237 err = tpm_sendrecv_command(buf, response, &response_length);
238 if (err)
239 return err;
240
241 if (unpack_byte_string(response, response_length, "s",
242 out_digest_offset, out_digest,
243 PCR_DIGEST_LENGTH))
244 return TPM_LIB_ERROR;
245
246 return 0;
247 }
248
249 u32 tpm_pcr_read(u32 index, void *data, size_t count)
250 {
251 const u8 command[14] = {
252 0x0, 0xc1, 0x0, 0x0, 0x0, 0xe, 0x0, 0x0, 0x0, 0x15,
253 };
254 const size_t index_offset = 10;
255 const size_t out_digest_offset = 10;
256 u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
257 size_t response_length = sizeof(response);
258 u32 err;
259
260 if (count < PCR_DIGEST_LENGTH)
261 return TPM_LIB_ERROR;
262
263 if (pack_byte_string(buf, sizeof(buf), "sd",
264 0, command, sizeof(command),
265 index_offset, index))
266 return TPM_LIB_ERROR;
267 err = tpm_sendrecv_command(buf, response, &response_length);
268 if (err)
269 return err;
270 if (unpack_byte_string(response, response_length, "s",
271 out_digest_offset, data, PCR_DIGEST_LENGTH))
272 return TPM_LIB_ERROR;
273
274 return 0;
275 }
276
277 u32 tpm_tsc_physical_presence(u16 presence)
278 {
279 const u8 command[12] = {
280 0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x40, 0x0, 0x0, 0xa, 0x0, 0x0,
281 };
282 const size_t presence_offset = 10;
283 u8 buf[COMMAND_BUFFER_SIZE];
284
285 if (pack_byte_string(buf, sizeof(buf), "sw",
286 0, command, sizeof(command),
287 presence_offset, presence))
288 return TPM_LIB_ERROR;
289
290 return tpm_sendrecv_command(buf, NULL, NULL);
291 }
292
293 u32 tpm_finalise_physical_presence(void)
294 {
295 const u8 command[12] = {
296 0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x40, 0x0, 0x0, 0xa, 0x2, 0xa0,
297 };
298
299 return tpm_sendrecv_command(command, NULL, NULL);
300 }
301
302 u32 tpm_read_pubek(void *data, size_t count)
303 {
304 const u8 command[30] = {
305 0x0, 0xc1, 0x0, 0x0, 0x0, 0x1e, 0x0, 0x0, 0x0, 0x7c,
306 };
307 const size_t response_size_offset = 2;
308 const size_t data_offset = 10;
309 const size_t header_and_checksum_size = TPM_RESPONSE_HEADER_LENGTH + 20;
310 u8 response[COMMAND_BUFFER_SIZE + TPM_PUBEK_SIZE];
311 size_t response_length = sizeof(response);
312 u32 data_size;
313 u32 err;
314
315 err = tpm_sendrecv_command(command, response, &response_length);
316 if (err)
317 return err;
318 if (unpack_byte_string(response, response_length, "d",
319 response_size_offset, &data_size))
320 return TPM_LIB_ERROR;
321 if (data_size < header_and_checksum_size)
322 return TPM_LIB_ERROR;
323 data_size -= header_and_checksum_size;
324 if (data_size > count)
325 return TPM_LIB_ERROR;
326 if (unpack_byte_string(response, response_length, "s",
327 data_offset, data, data_size))
328 return TPM_LIB_ERROR;
329
330 return 0;
331 }
332
333 u32 tpm_force_clear(void)
334 {
335 const u8 command[10] = {
336 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x5d,
337 };
338
339 return tpm_sendrecv_command(command, NULL, NULL);
340 }
341
342 u32 tpm_physical_enable(void)
343 {
344 const u8 command[10] = {
345 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x6f,
346 };
347
348 return tpm_sendrecv_command(command, NULL, NULL);
349 }
350
351 u32 tpm_physical_disable(void)
352 {
353 const u8 command[10] = {
354 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x70,
355 };
356
357 return tpm_sendrecv_command(command, NULL, NULL);
358 }
359
360 u32 tpm_physical_set_deactivated(u8 state)
361 {
362 const u8 command[11] = {
363 0x0, 0xc1, 0x0, 0x0, 0x0, 0xb, 0x0, 0x0, 0x0, 0x72,
364 };
365 const size_t state_offset = 10;
366 u8 buf[COMMAND_BUFFER_SIZE];
367
368 if (pack_byte_string(buf, sizeof(buf), "sb",
369 0, command, sizeof(command),
370 state_offset, state))
371 return TPM_LIB_ERROR;
372
373 return tpm_sendrecv_command(buf, NULL, NULL);
374 }
375
376 u32 tpm_get_capability(u32 cap_area, u32 sub_cap, void *cap, size_t count)
377 {
378 const u8 command[22] = {
379 0x0, 0xc1, /* TPM_TAG */
380 0x0, 0x0, 0x0, 0x16, /* parameter size */
381 0x0, 0x0, 0x0, 0x65, /* TPM_COMMAND_CODE */
382 0x0, 0x0, 0x0, 0x0, /* TPM_CAPABILITY_AREA */
383 0x0, 0x0, 0x0, 0x4, /* subcap size */
384 0x0, 0x0, 0x0, 0x0, /* subcap value */
385 };
386 const size_t cap_area_offset = 10;
387 const size_t sub_cap_offset = 18;
388 const size_t cap_offset = 14;
389 const size_t cap_size_offset = 10;
390 u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
391 size_t response_length = sizeof(response);
392 u32 cap_size;
393 u32 err;
394
395 if (pack_byte_string(buf, sizeof(buf), "sdd",
396 0, command, sizeof(command),
397 cap_area_offset, cap_area,
398 sub_cap_offset, sub_cap))
399 return TPM_LIB_ERROR;
400 err = tpm_sendrecv_command(buf, response, &response_length);
401 if (err)
402 return err;
403 if (unpack_byte_string(response, response_length, "d",
404 cap_size_offset, &cap_size))
405 return TPM_LIB_ERROR;
406 if (cap_size > response_length || cap_size > count)
407 return TPM_LIB_ERROR;
408 if (unpack_byte_string(response, response_length, "s",
409 cap_offset, cap, cap_size))
410 return TPM_LIB_ERROR;
411
412 return 0;
413 }
414
415 u32 tpm_get_permanent_flags(struct tpm_permanent_flags *pflags)
416 {
417 const u8 command[22] = {
418 0x0, 0xc1, /* TPM_TAG */
419 0x0, 0x0, 0x0, 0x16, /* parameter size */
420 0x0, 0x0, 0x0, 0x65, /* TPM_COMMAND_CODE */
421 0x0, 0x0, 0x0, 0x4, /* TPM_CAP_FLAG_PERM */
422 0x0, 0x0, 0x0, 0x4, /* subcap size */
423 0x0, 0x0, 0x1, 0x8, /* subcap value */
424 };
425 const size_t data_size_offset = TPM_HEADER_SIZE;
426 const size_t data_offset = TPM_HEADER_SIZE + sizeof(u32);
427 u8 response[COMMAND_BUFFER_SIZE];
428 size_t response_length = sizeof(response);
429 u32 err;
430 u32 data_size;
431
432 err = tpm_sendrecv_command(command, response, &response_length);
433 if (err)
434 return err;
435 if (unpack_byte_string(response, response_length, "d",
436 data_size_offset, &data_size)) {
437 log_err("Cannot unpack data size\n");
438 return TPM_LIB_ERROR;
439 }
440 if (data_size < sizeof(*pflags)) {
441 log_err("Data size too small\n");
442 return TPM_LIB_ERROR;
443 }
444 if (unpack_byte_string(response, response_length, "s",
445 data_offset, pflags, sizeof(*pflags))) {
446 log_err("Cannot unpack pflags\n");
447 return TPM_LIB_ERROR;
448 }
449
450 return 0;
451 }
452
453 u32 tpm_get_permissions(u32 index, u32 *perm)
454 {
455 const u8 command[22] = {
456 0x0, 0xc1, /* TPM_TAG */
457 0x0, 0x0, 0x0, 0x16, /* parameter size */
458 0x0, 0x0, 0x0, 0x65, /* TPM_COMMAND_CODE */
459 0x0, 0x0, 0x0, 0x11,
460 0x0, 0x0, 0x0, 0x4,
461 };
462 const size_t index_offset = 18;
463 const size_t perm_offset = 60;
464 u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
465 size_t response_length = sizeof(response);
466 u32 err;
467
468 if (pack_byte_string(buf, sizeof(buf), "d", 0, command, sizeof(command),
469 index_offset, index))
470 return TPM_LIB_ERROR;
471 err = tpm_sendrecv_command(buf, response, &response_length);
472 if (err)
473 return err;
474 if (unpack_byte_string(response, response_length, "d",
475 perm_offset, perm))
476 return TPM_LIB_ERROR;
477
478 return 0;
479 }
480
481 #ifdef CONFIG_TPM_FLUSH_RESOURCES
482 u32 tpm_flush_specific(u32 key_handle, u32 resource_type)
483 {
484 const u8 command[18] = {
485 0x00, 0xc1, /* TPM_TAG */
486 0x00, 0x00, 0x00, 0x12, /* parameter size */
487 0x00, 0x00, 0x00, 0xba, /* TPM_COMMAND_CODE */
488 0x00, 0x00, 0x00, 0x00, /* key handle */
489 0x00, 0x00, 0x00, 0x00, /* resource type */
490 };
491 const size_t key_handle_offset = 10;
492 const size_t resource_type_offset = 14;
493 u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
494 size_t response_length = sizeof(response);
495 u32 err;
496
497 if (pack_byte_string(buf, sizeof(buf), "sdd",
498 0, command, sizeof(command),
499 key_handle_offset, key_handle,
500 resource_type_offset, resource_type))
501 return TPM_LIB_ERROR;
502
503 err = tpm_sendrecv_command(buf, response, &response_length);
504 if (err)
505 return err;
506 return 0;
507 }
508 #endif /* CONFIG_TPM_FLUSH_RESOURCES */
509
510 #ifdef CONFIG_TPM_AUTH_SESSIONS
511
512 /**
513 * Fill an authentication block in a request.
514 * This func can create the first as well as the second auth block (for
515 * double authorized commands).
516 *
517 * @param request pointer to the request (w/ uninitialised auth data)
518 * @param request_len0 length of the request without auth data
519 * @param handles_len length of the handles area in request
520 * @param auth_session pointer to the (valid) auth session to be used
521 * @param request_auth pointer to the auth block of the request to be filled
522 * @param auth authentication data (HMAC key)
523 */
524 static u32 create_request_auth(const void *request, size_t request_len0,
525 size_t handles_len,
526 struct session_data *auth_session,
527 void *request_auth, const void *auth)
528 {
529 u8 hmac_data[DIGEST_LENGTH * 3 + 1];
530 sha1_context hash_ctx;
531 const size_t command_code_offset = 6;
532 const size_t auth_nonce_odd_offset = 4;
533 const size_t auth_continue_offset = 24;
534 const size_t auth_auth_offset = 25;
535
536 if (!auth_session || !auth_session->valid)
537 return TPM_LIB_ERROR;
538
539 sha1_starts(&hash_ctx);
540 sha1_update(&hash_ctx, request + command_code_offset, 4);
541 if (request_len0 > TPM_REQUEST_HEADER_LENGTH + handles_len)
542 sha1_update(&hash_ctx,
543 request + TPM_REQUEST_HEADER_LENGTH + handles_len,
544 request_len0 - TPM_REQUEST_HEADER_LENGTH
545 - handles_len);
546 sha1_finish(&hash_ctx, hmac_data);
547
548 sha1_starts(&hash_ctx);
549 sha1_update(&hash_ctx, auth_session->nonce_odd, DIGEST_LENGTH);
550 sha1_update(&hash_ctx, hmac_data, sizeof(hmac_data));
551 sha1_finish(&hash_ctx, auth_session->nonce_odd);
552
553 if (pack_byte_string(request_auth, TPM_REQUEST_AUTH_LENGTH, "dsb",
554 0, auth_session->handle,
555 auth_nonce_odd_offset, auth_session->nonce_odd,
556 DIGEST_LENGTH,
557 auth_continue_offset, 1))
558 return TPM_LIB_ERROR;
559 if (pack_byte_string(hmac_data, sizeof(hmac_data), "ss",
560 DIGEST_LENGTH,
561 auth_session->nonce_even,
562 DIGEST_LENGTH,
563 2 * DIGEST_LENGTH,
564 request_auth + auth_nonce_odd_offset,
565 DIGEST_LENGTH + 1))
566 return TPM_LIB_ERROR;
567 sha1_hmac(auth, DIGEST_LENGTH, hmac_data, sizeof(hmac_data),
568 request_auth + auth_auth_offset);
569
570 return TPM_SUCCESS;
571 }
572
573 /**
574 * Verify an authentication block in a response.
575 * Since this func updates the nonce_even in the session data it has to be
576 * called when receiving a succesfull AUTH response.
577 * This func can verify the first as well as the second auth block (for
578 * double authorized commands).
579 *
580 * @param command_code command code of the request
581 * @param response pointer to the request (w/ uninitialised auth data)
582 * @param handles_len length of the handles area in response
583 * @param auth_session pointer to the (valid) auth session to be used
584 * @param response_auth pointer to the auth block of the response to be verified
585 * @param auth authentication data (HMAC key)
586 */
587 static u32 verify_response_auth(u32 command_code, const void *response,
588 size_t response_len0, size_t handles_len,
589 struct session_data *auth_session,
590 const void *response_auth, const void *auth)
591 {
592 u8 hmac_data[DIGEST_LENGTH * 3 + 1];
593 u8 computed_auth[DIGEST_LENGTH];
594 sha1_context hash_ctx;
595 const size_t return_code_offset = 6;
596 const size_t auth_continue_offset = 20;
597 const size_t auth_auth_offset = 21;
598 u8 auth_continue;
599
600 if (!auth_session || !auth_session->valid)
601 return TPM_AUTHFAIL;
602 if (pack_byte_string(hmac_data, sizeof(hmac_data), "d",
603 0, command_code))
604 return TPM_LIB_ERROR;
605 if (response_len0 < TPM_RESPONSE_HEADER_LENGTH)
606 return TPM_LIB_ERROR;
607
608 sha1_starts(&hash_ctx);
609 sha1_update(&hash_ctx, response + return_code_offset, 4);
610 sha1_update(&hash_ctx, hmac_data, 4);
611 if (response_len0 > TPM_RESPONSE_HEADER_LENGTH + handles_len)
612 sha1_update(&hash_ctx,
613 response + TPM_RESPONSE_HEADER_LENGTH + handles_len,
614 response_len0 - TPM_RESPONSE_HEADER_LENGTH
615 - handles_len);
616 sha1_finish(&hash_ctx, hmac_data);
617
618 memcpy(auth_session->nonce_even, response_auth, DIGEST_LENGTH);
619 auth_continue = ((u8 *)response_auth)[auth_continue_offset];
620 if (pack_byte_string(hmac_data, sizeof(hmac_data), "ssb",
621 DIGEST_LENGTH,
622 response_auth,
623 DIGEST_LENGTH,
624 2 * DIGEST_LENGTH,
625 auth_session->nonce_odd,
626 DIGEST_LENGTH,
627 3 * DIGEST_LENGTH,
628 auth_continue))
629 return TPM_LIB_ERROR;
630
631 sha1_hmac(auth, DIGEST_LENGTH, hmac_data, sizeof(hmac_data),
632 computed_auth);
633
634 if (memcmp(computed_auth, response_auth + auth_auth_offset,
635 DIGEST_LENGTH))
636 return TPM_AUTHFAIL;
637
638 return TPM_SUCCESS;
639 }
640
641 u32 tpm_terminate_auth_session(u32 auth_handle)
642 {
643 const u8 command[18] = {
644 0x00, 0xc1, /* TPM_TAG */
645 0x00, 0x00, 0x00, 0x00, /* parameter size */
646 0x00, 0x00, 0x00, 0xba, /* TPM_COMMAND_CODE */
647 0x00, 0x00, 0x00, 0x00, /* TPM_HANDLE */
648 0x00, 0x00, 0x00, 0x02, /* TPM_RESOURCE_TYPE */
649 };
650 const size_t req_handle_offset = TPM_REQUEST_HEADER_LENGTH;
651 u8 request[COMMAND_BUFFER_SIZE];
652
653 if (pack_byte_string(request, sizeof(request), "sd",
654 0, command, sizeof(command),
655 req_handle_offset, auth_handle))
656 return TPM_LIB_ERROR;
657 if (oiap_session.valid && oiap_session.handle == auth_handle)
658 oiap_session.valid = 0;
659
660 return tpm_sendrecv_command(request, NULL, NULL);
661 }
662
663 u32 tpm_end_oiap(void)
664 {
665 u32 err = TPM_SUCCESS;
666
667 if (oiap_session.valid)
668 err = tpm_terminate_auth_session(oiap_session.handle);
669 return err;
670 }
671
672 u32 tpm_oiap(u32 *auth_handle)
673 {
674 const u8 command[10] = {
675 0x00, 0xc1, /* TPM_TAG */
676 0x00, 0x00, 0x00, 0x0a, /* parameter size */
677 0x00, 0x00, 0x00, 0x0a, /* TPM_COMMAND_CODE */
678 };
679 const size_t res_auth_handle_offset = TPM_RESPONSE_HEADER_LENGTH;
680 const size_t res_nonce_even_offset = TPM_RESPONSE_HEADER_LENGTH + 4;
681 u8 response[COMMAND_BUFFER_SIZE];
682 size_t response_length = sizeof(response);
683 u32 err;
684
685 if (oiap_session.valid)
686 tpm_terminate_auth_session(oiap_session.handle);
687
688 err = tpm_sendrecv_command(command, response, &response_length);
689 if (err)
690 return err;
691 if (unpack_byte_string(response, response_length, "ds",
692 res_auth_handle_offset, &oiap_session.handle,
693 res_nonce_even_offset, &oiap_session.nonce_even,
694 (u32)DIGEST_LENGTH))
695 return TPM_LIB_ERROR;
696 oiap_session.valid = 1;
697 if (auth_handle)
698 *auth_handle = oiap_session.handle;
699 return 0;
700 }
701
702 u32 tpm_load_key2_oiap(u32 parent_handle, const void *key, size_t key_length,
703 const void *parent_key_usage_auth, u32 *key_handle)
704 {
705 const u8 command[14] = {
706 0x00, 0xc2, /* TPM_TAG */
707 0x00, 0x00, 0x00, 0x00, /* parameter size */
708 0x00, 0x00, 0x00, 0x41, /* TPM_COMMAND_CODE */
709 0x00, 0x00, 0x00, 0x00, /* parent handle */
710 };
711 const size_t req_size_offset = 2;
712 const size_t req_parent_handle_offset = TPM_REQUEST_HEADER_LENGTH;
713 const size_t req_key_offset = TPM_REQUEST_HEADER_LENGTH + 4;
714 const size_t res_handle_offset = TPM_RESPONSE_HEADER_LENGTH;
715 u8 request[sizeof(command) + TPM_KEY12_MAX_LENGTH +
716 TPM_REQUEST_AUTH_LENGTH];
717 u8 response[COMMAND_BUFFER_SIZE];
718 size_t response_length = sizeof(response);
719 u32 err;
720
721 if (!oiap_session.valid) {
722 err = tpm_oiap(NULL);
723 if (err)
724 return err;
725 }
726 if (pack_byte_string(request, sizeof(request), "sdds",
727 0, command, sizeof(command),
728 req_size_offset,
729 sizeof(command) + key_length
730 + TPM_REQUEST_AUTH_LENGTH,
731 req_parent_handle_offset, parent_handle,
732 req_key_offset, key, key_length
733 ))
734 return TPM_LIB_ERROR;
735
736 err = create_request_auth(request, sizeof(command) + key_length, 4,
737 &oiap_session,
738 request + sizeof(command) + key_length,
739 parent_key_usage_auth);
740 if (err)
741 return err;
742 err = tpm_sendrecv_command(request, response, &response_length);
743 if (err) {
744 if (err == TPM_AUTHFAIL)
745 oiap_session.valid = 0;
746 return err;
747 }
748
749 err = verify_response_auth(0x00000041, response,
750 response_length - TPM_RESPONSE_AUTH_LENGTH,
751 4, &oiap_session,
752 response + response_length -
753 TPM_RESPONSE_AUTH_LENGTH,
754 parent_key_usage_auth);
755 if (err)
756 return err;
757
758 if (key_handle) {
759 if (unpack_byte_string(response, response_length, "d",
760 res_handle_offset, key_handle))
761 return TPM_LIB_ERROR;
762 }
763
764 return 0;
765 }
766
767 u32 tpm_get_pub_key_oiap(u32 key_handle, const void *usage_auth, void *pubkey,
768 size_t *pubkey_len)
769 {
770 const u8 command[14] = {
771 0x00, 0xc2, /* TPM_TAG */
772 0x00, 0x00, 0x00, 0x00, /* parameter size */
773 0x00, 0x00, 0x00, 0x21, /* TPM_COMMAND_CODE */
774 0x00, 0x00, 0x00, 0x00, /* key handle */
775 };
776 const size_t req_size_offset = 2;
777 const size_t req_key_handle_offset = TPM_REQUEST_HEADER_LENGTH;
778 const size_t res_pubkey_offset = TPM_RESPONSE_HEADER_LENGTH;
779 u8 request[sizeof(command) + TPM_REQUEST_AUTH_LENGTH];
780 u8 response[TPM_RESPONSE_HEADER_LENGTH + TPM_PUBKEY_MAX_LENGTH +
781 TPM_RESPONSE_AUTH_LENGTH];
782 size_t response_length = sizeof(response);
783 u32 err;
784
785 if (!oiap_session.valid) {
786 err = tpm_oiap(NULL);
787 if (err)
788 return err;
789 }
790 if (pack_byte_string(request, sizeof(request), "sdd",
791 0, command, sizeof(command),
792 req_size_offset,
793 (u32)(sizeof(command)
794 + TPM_REQUEST_AUTH_LENGTH),
795 req_key_handle_offset, key_handle
796 ))
797 return TPM_LIB_ERROR;
798 err = create_request_auth(request, sizeof(command), 4, &oiap_session,
799 request + sizeof(command), usage_auth);
800 if (err)
801 return err;
802 err = tpm_sendrecv_command(request, response, &response_length);
803 if (err) {
804 if (err == TPM_AUTHFAIL)
805 oiap_session.valid = 0;
806 return err;
807 }
808 err = verify_response_auth(0x00000021, response,
809 response_length - TPM_RESPONSE_AUTH_LENGTH,
810 0, &oiap_session,
811 response + response_length -
812 TPM_RESPONSE_AUTH_LENGTH,
813 usage_auth);
814 if (err)
815 return err;
816
817 if (pubkey) {
818 if ((response_length - TPM_RESPONSE_HEADER_LENGTH
819 - TPM_RESPONSE_AUTH_LENGTH) > *pubkey_len)
820 return TPM_LIB_ERROR;
821 *pubkey_len = response_length - TPM_RESPONSE_HEADER_LENGTH
822 - TPM_RESPONSE_AUTH_LENGTH;
823 memcpy(pubkey, response + res_pubkey_offset,
824 response_length - TPM_RESPONSE_HEADER_LENGTH
825 - TPM_RESPONSE_AUTH_LENGTH);
826 }
827
828 return 0;
829 }
830
831 #ifdef CONFIG_TPM_LOAD_KEY_BY_SHA1
832 u32 tpm_find_key_sha1(const u8 auth[20], const u8 pubkey_digest[20],
833 u32 *handle)
834 {
835 u16 key_count;
836 u32 key_handles[10];
837 u8 buf[288];
838 u8 *ptr;
839 u32 err;
840 u8 digest[20];
841 size_t buf_len;
842 unsigned int i;
843
844 /* fetch list of already loaded keys in the TPM */
845 err = tpm_get_capability(TPM_CAP_HANDLE, TPM_RT_KEY, buf, sizeof(buf));
846 if (err)
847 return -1;
848 key_count = get_unaligned_be16(buf);
849 ptr = buf + 2;
850 for (i = 0; i < key_count; ++i, ptr += 4)
851 key_handles[i] = get_unaligned_be32(ptr);
852
853 /* now search a(/ the) key which we can access with the given auth */
854 for (i = 0; i < key_count; ++i) {
855 buf_len = sizeof(buf);
856 err = tpm_get_pub_key_oiap(key_handles[i], auth, buf, &buf_len);
857 if (err && err != TPM_AUTHFAIL)
858 return -1;
859 if (err)
860 continue;
861 sha1_csum(buf, buf_len, digest);
862 if (!memcmp(digest, pubkey_digest, 20)) {
863 *handle = key_handles[i];
864 return 0;
865 }
866 }
867 return 1;
868 }
869 #endif /* CONFIG_TPM_LOAD_KEY_BY_SHA1 */
870
871 #endif /* CONFIG_TPM_AUTH_SESSIONS */
872
873 u32 tpm_get_random(void *data, u32 count)
874 {
875 const u8 command[14] = {
876 0x0, 0xc1, /* TPM_TAG */
877 0x0, 0x0, 0x0, 0xe, /* parameter size */
878 0x0, 0x0, 0x0, 0x46, /* TPM_COMMAND_CODE */
879 };
880 const size_t length_offset = 10;
881 const size_t data_size_offset = 10;
882 const size_t data_offset = 14;
883 u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
884 size_t response_length = sizeof(response);
885 u32 data_size;
886 u8 *out = data;
887
888 while (count > 0) {
889 u32 this_bytes = min((size_t)count,
890 sizeof(response) - data_offset);
891 u32 err;
892
893 if (pack_byte_string(buf, sizeof(buf), "sd",
894 0, command, sizeof(command),
895 length_offset, this_bytes))
896 return TPM_LIB_ERROR;
897 err = tpm_sendrecv_command(buf, response, &response_length);
898 if (err)
899 return err;
900 if (unpack_byte_string(response, response_length, "d",
901 data_size_offset, &data_size))
902 return TPM_LIB_ERROR;
903 if (data_size > count)
904 return TPM_LIB_ERROR;
905 if (unpack_byte_string(response, response_length, "s",
906 data_offset, out, data_size))
907 return TPM_LIB_ERROR;
908
909 count -= data_size;
910 out += data_size;
911 }
912
913 return 0;
914 }