]> git.ipfire.org Git - thirdparty/u-boot.git/blob - lib/tpm-v1.c
Merge git://git.denx.de/u-boot-fsl-qoriq
[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(struct udevice *dev, 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(dev, buf, NULL, NULL);
48 }
49
50 u32 tpm_resume(struct udevice *dev)
51 {
52 return tpm_startup(dev, TPM_ST_STATE);
53 }
54
55 u32 tpm_self_test_full(struct udevice *dev)
56 {
57 const u8 command[10] = {
58 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x50,
59 };
60 return tpm_sendrecv_command(dev, command, NULL, NULL);
61 }
62
63 u32 tpm_continue_self_test(struct udevice *dev)
64 {
65 const u8 command[10] = {
66 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x53,
67 };
68 return tpm_sendrecv_command(dev, command, NULL, NULL);
69 }
70
71 u32 tpm_clear_and_reenable(struct udevice *dev)
72 {
73 u32 ret;
74
75 log_info("TPM: Clear and re-enable\n");
76 ret = tpm_force_clear(dev);
77 if (ret != TPM_SUCCESS) {
78 log_err("Can't initiate a force clear\n");
79 return ret;
80 }
81
82 if (tpm_get_version(dev) == TPM_V1) {
83 ret = tpm_physical_enable(dev);
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(dev, 0);
90 if (ret != TPM_SUCCESS) {
91 log_err("TPM: Can't set deactivated state\n");
92 return ret;
93 }
94 }
95
96 return TPM_SUCCESS;
97 }
98
99 u32 tpm_nv_define_space(struct udevice *dev, 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(dev, buf, NULL, NULL);
140 }
141
142 u32 tpm_nv_set_locked(struct udevice *dev)
143 {
144 return tpm_nv_define_space(dev, TPM_NV_INDEX_LOCK, 0, 0);
145 }
146
147 u32 tpm_nv_read_value(struct udevice *dev, 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(dev, 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(struct udevice *dev, u32 index, const void *data,
182 u32 length)
183 {
184 const u8 command[256] = {
185 0x0, 0xc1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xcd,
186 };
187 const size_t command_size_offset = 2;
188 const size_t index_offset = 10;
189 const size_t length_offset = 18;
190 const size_t data_offset = 22;
191 const size_t write_info_size = 12;
192 const u32 total_length =
193 TPM_REQUEST_HEADER_LENGTH + write_info_size + length;
194 u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
195 size_t response_length = sizeof(response);
196 u32 err;
197
198 if (pack_byte_string(buf, sizeof(buf), "sddds",
199 0, command, sizeof(command),
200 command_size_offset, total_length,
201 index_offset, index,
202 length_offset, length,
203 data_offset, data, length))
204 return TPM_LIB_ERROR;
205 err = tpm_sendrecv_command(dev, buf, response, &response_length);
206 if (err)
207 return err;
208
209 return 0;
210 }
211
212 uint32_t tpm_set_global_lock(struct udevice *dev)
213 {
214 return tpm_nv_write_value(dev, TPM_NV_INDEX_0, NULL, 0);
215 }
216
217 u32 tpm_extend(struct udevice *dev, u32 index, const void *in_digest,
218 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(dev, 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(struct udevice *dev, 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(dev, 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(struct udevice *dev, 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(dev, buf, NULL, NULL);
291 }
292
293 u32 tpm_finalise_physical_presence(struct udevice *dev)
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(dev, command, NULL, NULL);
300 }
301
302 u32 tpm_read_pubek(struct udevice *dev, 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(dev, 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(struct udevice *dev)
334 {
335 const u8 command[10] = {
336 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x5d,
337 };
338
339 return tpm_sendrecv_command(dev, command, NULL, NULL);
340 }
341
342 u32 tpm_physical_enable(struct udevice *dev)
343 {
344 const u8 command[10] = {
345 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x6f,
346 };
347
348 return tpm_sendrecv_command(dev, command, NULL, NULL);
349 }
350
351 u32 tpm_physical_disable(struct udevice *dev)
352 {
353 const u8 command[10] = {
354 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x70,
355 };
356
357 return tpm_sendrecv_command(dev, command, NULL, NULL);
358 }
359
360 u32 tpm_physical_set_deactivated(struct udevice *dev, 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(dev, buf, NULL, NULL);
374 }
375
376 u32 tpm_get_capability(struct udevice *dev, u32 cap_area, u32 sub_cap,
377 void *cap, size_t count)
378 {
379 const u8 command[22] = {
380 0x0, 0xc1, /* TPM_TAG */
381 0x0, 0x0, 0x0, 0x16, /* parameter size */
382 0x0, 0x0, 0x0, 0x65, /* TPM_COMMAND_CODE */
383 0x0, 0x0, 0x0, 0x0, /* TPM_CAPABILITY_AREA */
384 0x0, 0x0, 0x0, 0x4, /* subcap size */
385 0x0, 0x0, 0x0, 0x0, /* subcap value */
386 };
387 const size_t cap_area_offset = 10;
388 const size_t sub_cap_offset = 18;
389 const size_t cap_offset = 14;
390 const size_t cap_size_offset = 10;
391 u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
392 size_t response_length = sizeof(response);
393 u32 cap_size;
394 u32 err;
395
396 if (pack_byte_string(buf, sizeof(buf), "sdd",
397 0, command, sizeof(command),
398 cap_area_offset, cap_area,
399 sub_cap_offset, sub_cap))
400 return TPM_LIB_ERROR;
401 err = tpm_sendrecv_command(dev, buf, response, &response_length);
402 if (err)
403 return err;
404 if (unpack_byte_string(response, response_length, "d",
405 cap_size_offset, &cap_size))
406 return TPM_LIB_ERROR;
407 if (cap_size > response_length || cap_size > count)
408 return TPM_LIB_ERROR;
409 if (unpack_byte_string(response, response_length, "s",
410 cap_offset, cap, cap_size))
411 return TPM_LIB_ERROR;
412
413 return 0;
414 }
415
416 u32 tpm_get_permanent_flags(struct udevice *dev,
417 struct tpm_permanent_flags *pflags)
418 {
419 const u8 command[22] = {
420 0x0, 0xc1, /* TPM_TAG */
421 0x0, 0x0, 0x0, 0x16, /* parameter size */
422 0x0, 0x0, 0x0, 0x65, /* TPM_COMMAND_CODE */
423 0x0, 0x0, 0x0, 0x4, /* TPM_CAP_FLAG_PERM */
424 0x0, 0x0, 0x0, 0x4, /* subcap size */
425 0x0, 0x0, 0x1, 0x8, /* subcap value */
426 };
427 const size_t data_size_offset = TPM_HEADER_SIZE;
428 const size_t data_offset = TPM_HEADER_SIZE + sizeof(u32);
429 u8 response[COMMAND_BUFFER_SIZE];
430 size_t response_length = sizeof(response);
431 u32 err;
432 u32 data_size;
433
434 err = tpm_sendrecv_command(dev, command, response, &response_length);
435 if (err)
436 return err;
437 if (unpack_byte_string(response, response_length, "d",
438 data_size_offset, &data_size)) {
439 log_err("Cannot unpack data size\n");
440 return TPM_LIB_ERROR;
441 }
442 if (data_size < sizeof(*pflags)) {
443 log_err("Data size too small\n");
444 return TPM_LIB_ERROR;
445 }
446 if (unpack_byte_string(response, response_length, "s",
447 data_offset, pflags, sizeof(*pflags))) {
448 log_err("Cannot unpack pflags\n");
449 return TPM_LIB_ERROR;
450 }
451
452 return 0;
453 }
454
455 u32 tpm_get_permissions(struct udevice *dev, u32 index, u32 *perm)
456 {
457 const u8 command[22] = {
458 0x0, 0xc1, /* TPM_TAG */
459 0x0, 0x0, 0x0, 0x16, /* parameter size */
460 0x0, 0x0, 0x0, 0x65, /* TPM_COMMAND_CODE */
461 0x0, 0x0, 0x0, 0x11,
462 0x0, 0x0, 0x0, 0x4,
463 };
464 const size_t index_offset = 18;
465 const size_t perm_offset = 60;
466 u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
467 size_t response_length = sizeof(response);
468 u32 err;
469
470 if (pack_byte_string(buf, sizeof(buf), "d", 0, command, sizeof(command),
471 index_offset, index))
472 return TPM_LIB_ERROR;
473 err = tpm_sendrecv_command(dev, buf, response, &response_length);
474 if (err)
475 return err;
476 if (unpack_byte_string(response, response_length, "d",
477 perm_offset, perm))
478 return TPM_LIB_ERROR;
479
480 return 0;
481 }
482
483 #ifdef CONFIG_TPM_FLUSH_RESOURCES
484 u32 tpm_flush_specific(struct udevice *dev, u32 key_handle, u32 resource_type)
485 {
486 const u8 command[18] = {
487 0x00, 0xc1, /* TPM_TAG */
488 0x00, 0x00, 0x00, 0x12, /* parameter size */
489 0x00, 0x00, 0x00, 0xba, /* TPM_COMMAND_CODE */
490 0x00, 0x00, 0x00, 0x00, /* key handle */
491 0x00, 0x00, 0x00, 0x00, /* resource type */
492 };
493 const size_t key_handle_offset = 10;
494 const size_t resource_type_offset = 14;
495 u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
496 size_t response_length = sizeof(response);
497 u32 err;
498
499 if (pack_byte_string(buf, sizeof(buf), "sdd",
500 0, command, sizeof(command),
501 key_handle_offset, key_handle,
502 resource_type_offset, resource_type))
503 return TPM_LIB_ERROR;
504
505 err = tpm_sendrecv_command(dev, buf, response, &response_length);
506 if (err)
507 return err;
508 return 0;
509 }
510 #endif /* CONFIG_TPM_FLUSH_RESOURCES */
511
512 #ifdef CONFIG_TPM_AUTH_SESSIONS
513
514 /**
515 * Fill an authentication block in a request.
516 * This func can create the first as well as the second auth block (for
517 * double authorized commands).
518 *
519 * @param request pointer to the request (w/ uninitialised auth data)
520 * @param request_len0 length of the request without auth data
521 * @param handles_len length of the handles area in request
522 * @param auth_session pointer to the (valid) auth session to be used
523 * @param request_auth pointer to the auth block of the request to be filled
524 * @param auth authentication data (HMAC key)
525 */
526 static u32 create_request_auth(const void *request, size_t request_len0,
527 size_t handles_len,
528 struct session_data *auth_session,
529 void *request_auth, const void *auth)
530 {
531 u8 hmac_data[DIGEST_LENGTH * 3 + 1];
532 sha1_context hash_ctx;
533 const size_t command_code_offset = 6;
534 const size_t auth_nonce_odd_offset = 4;
535 const size_t auth_continue_offset = 24;
536 const size_t auth_auth_offset = 25;
537
538 if (!auth_session || !auth_session->valid)
539 return TPM_LIB_ERROR;
540
541 sha1_starts(&hash_ctx);
542 sha1_update(&hash_ctx, request + command_code_offset, 4);
543 if (request_len0 > TPM_REQUEST_HEADER_LENGTH + handles_len)
544 sha1_update(&hash_ctx,
545 request + TPM_REQUEST_HEADER_LENGTH + handles_len,
546 request_len0 - TPM_REQUEST_HEADER_LENGTH
547 - handles_len);
548 sha1_finish(&hash_ctx, hmac_data);
549
550 sha1_starts(&hash_ctx);
551 sha1_update(&hash_ctx, auth_session->nonce_odd, DIGEST_LENGTH);
552 sha1_update(&hash_ctx, hmac_data, sizeof(hmac_data));
553 sha1_finish(&hash_ctx, auth_session->nonce_odd);
554
555 if (pack_byte_string(request_auth, TPM_REQUEST_AUTH_LENGTH, "dsb",
556 0, auth_session->handle,
557 auth_nonce_odd_offset, auth_session->nonce_odd,
558 DIGEST_LENGTH,
559 auth_continue_offset, 1))
560 return TPM_LIB_ERROR;
561 if (pack_byte_string(hmac_data, sizeof(hmac_data), "ss",
562 DIGEST_LENGTH,
563 auth_session->nonce_even,
564 DIGEST_LENGTH,
565 2 * DIGEST_LENGTH,
566 request_auth + auth_nonce_odd_offset,
567 DIGEST_LENGTH + 1))
568 return TPM_LIB_ERROR;
569 sha1_hmac(auth, DIGEST_LENGTH, hmac_data, sizeof(hmac_data),
570 request_auth + auth_auth_offset);
571
572 return TPM_SUCCESS;
573 }
574
575 /**
576 * Verify an authentication block in a response.
577 * Since this func updates the nonce_even in the session data it has to be
578 * called when receiving a succesfull AUTH response.
579 * This func can verify the first as well as the second auth block (for
580 * double authorized commands).
581 *
582 * @param command_code command code of the request
583 * @param response pointer to the request (w/ uninitialised auth data)
584 * @param handles_len length of the handles area in response
585 * @param auth_session pointer to the (valid) auth session to be used
586 * @param response_auth pointer to the auth block of the response to be verified
587 * @param auth authentication data (HMAC key)
588 */
589 static u32 verify_response_auth(u32 command_code, const void *response,
590 size_t response_len0, size_t handles_len,
591 struct session_data *auth_session,
592 const void *response_auth, const void *auth)
593 {
594 u8 hmac_data[DIGEST_LENGTH * 3 + 1];
595 u8 computed_auth[DIGEST_LENGTH];
596 sha1_context hash_ctx;
597 const size_t return_code_offset = 6;
598 const size_t auth_continue_offset = 20;
599 const size_t auth_auth_offset = 21;
600 u8 auth_continue;
601
602 if (!auth_session || !auth_session->valid)
603 return TPM_AUTHFAIL;
604 if (pack_byte_string(hmac_data, sizeof(hmac_data), "d",
605 0, command_code))
606 return TPM_LIB_ERROR;
607 if (response_len0 < TPM_RESPONSE_HEADER_LENGTH)
608 return TPM_LIB_ERROR;
609
610 sha1_starts(&hash_ctx);
611 sha1_update(&hash_ctx, response + return_code_offset, 4);
612 sha1_update(&hash_ctx, hmac_data, 4);
613 if (response_len0 > TPM_RESPONSE_HEADER_LENGTH + handles_len)
614 sha1_update(&hash_ctx,
615 response + TPM_RESPONSE_HEADER_LENGTH + handles_len,
616 response_len0 - TPM_RESPONSE_HEADER_LENGTH
617 - handles_len);
618 sha1_finish(&hash_ctx, hmac_data);
619
620 memcpy(auth_session->nonce_even, response_auth, DIGEST_LENGTH);
621 auth_continue = ((u8 *)response_auth)[auth_continue_offset];
622 if (pack_byte_string(hmac_data, sizeof(hmac_data), "ssb",
623 DIGEST_LENGTH,
624 response_auth,
625 DIGEST_LENGTH,
626 2 * DIGEST_LENGTH,
627 auth_session->nonce_odd,
628 DIGEST_LENGTH,
629 3 * DIGEST_LENGTH,
630 auth_continue))
631 return TPM_LIB_ERROR;
632
633 sha1_hmac(auth, DIGEST_LENGTH, hmac_data, sizeof(hmac_data),
634 computed_auth);
635
636 if (memcmp(computed_auth, response_auth + auth_auth_offset,
637 DIGEST_LENGTH))
638 return TPM_AUTHFAIL;
639
640 return TPM_SUCCESS;
641 }
642
643 u32 tpm_terminate_auth_session(struct udevice *dev, u32 auth_handle)
644 {
645 const u8 command[18] = {
646 0x00, 0xc1, /* TPM_TAG */
647 0x00, 0x00, 0x00, 0x00, /* parameter size */
648 0x00, 0x00, 0x00, 0xba, /* TPM_COMMAND_CODE */
649 0x00, 0x00, 0x00, 0x00, /* TPM_HANDLE */
650 0x00, 0x00, 0x00, 0x02, /* TPM_RESOURCE_TYPE */
651 };
652 const size_t req_handle_offset = TPM_REQUEST_HEADER_LENGTH;
653 u8 request[COMMAND_BUFFER_SIZE];
654
655 if (pack_byte_string(request, sizeof(request), "sd",
656 0, command, sizeof(command),
657 req_handle_offset, auth_handle))
658 return TPM_LIB_ERROR;
659 if (oiap_session.valid && oiap_session.handle == auth_handle)
660 oiap_session.valid = 0;
661
662 return tpm_sendrecv_command(dev, request, NULL, NULL);
663 }
664
665 u32 tpm_end_oiap(struct udevice *dev)
666 {
667 u32 err = TPM_SUCCESS;
668
669 if (oiap_session.valid)
670 err = tpm_terminate_auth_session(dev, oiap_session.handle);
671 return err;
672 }
673
674 u32 tpm_oiap(struct udevice *dev, u32 *auth_handle)
675 {
676 const u8 command[10] = {
677 0x00, 0xc1, /* TPM_TAG */
678 0x00, 0x00, 0x00, 0x0a, /* parameter size */
679 0x00, 0x00, 0x00, 0x0a, /* TPM_COMMAND_CODE */
680 };
681 const size_t res_auth_handle_offset = TPM_RESPONSE_HEADER_LENGTH;
682 const size_t res_nonce_even_offset = TPM_RESPONSE_HEADER_LENGTH + 4;
683 u8 response[COMMAND_BUFFER_SIZE];
684 size_t response_length = sizeof(response);
685 u32 err;
686
687 if (oiap_session.valid)
688 tpm_terminate_auth_session(dev, oiap_session.handle);
689
690 err = tpm_sendrecv_command(dev, command, response, &response_length);
691 if (err)
692 return err;
693 if (unpack_byte_string(response, response_length, "ds",
694 res_auth_handle_offset, &oiap_session.handle,
695 res_nonce_even_offset, &oiap_session.nonce_even,
696 (u32)DIGEST_LENGTH))
697 return TPM_LIB_ERROR;
698 oiap_session.valid = 1;
699 if (auth_handle)
700 *auth_handle = oiap_session.handle;
701 return 0;
702 }
703
704 u32 tpm_load_key2_oiap(struct udevice *dev, u32 parent_handle, const void *key,
705 size_t key_length, const void *parent_key_usage_auth,
706 u32 *key_handle)
707 {
708 const u8 command[14] = {
709 0x00, 0xc2, /* TPM_TAG */
710 0x00, 0x00, 0x00, 0x00, /* parameter size */
711 0x00, 0x00, 0x00, 0x41, /* TPM_COMMAND_CODE */
712 0x00, 0x00, 0x00, 0x00, /* parent handle */
713 };
714 const size_t req_size_offset = 2;
715 const size_t req_parent_handle_offset = TPM_REQUEST_HEADER_LENGTH;
716 const size_t req_key_offset = TPM_REQUEST_HEADER_LENGTH + 4;
717 const size_t res_handle_offset = TPM_RESPONSE_HEADER_LENGTH;
718 u8 request[sizeof(command) + TPM_KEY12_MAX_LENGTH +
719 TPM_REQUEST_AUTH_LENGTH];
720 u8 response[COMMAND_BUFFER_SIZE];
721 size_t response_length = sizeof(response);
722 u32 err;
723
724 if (!oiap_session.valid) {
725 err = tpm_oiap(dev, NULL);
726 if (err)
727 return err;
728 }
729 if (pack_byte_string(request, sizeof(request), "sdds",
730 0, command, sizeof(command),
731 req_size_offset,
732 sizeof(command) + key_length
733 + TPM_REQUEST_AUTH_LENGTH,
734 req_parent_handle_offset, parent_handle,
735 req_key_offset, key, key_length
736 ))
737 return TPM_LIB_ERROR;
738
739 err = create_request_auth(request, sizeof(command) + key_length, 4,
740 &oiap_session,
741 request + sizeof(command) + key_length,
742 parent_key_usage_auth);
743 if (err)
744 return err;
745 err = tpm_sendrecv_command(dev, request, response, &response_length);
746 if (err) {
747 if (err == TPM_AUTHFAIL)
748 oiap_session.valid = 0;
749 return err;
750 }
751
752 err = verify_response_auth(0x00000041, response,
753 response_length - TPM_RESPONSE_AUTH_LENGTH,
754 4, &oiap_session,
755 response + response_length -
756 TPM_RESPONSE_AUTH_LENGTH,
757 parent_key_usage_auth);
758 if (err)
759 return err;
760
761 if (key_handle) {
762 if (unpack_byte_string(response, response_length, "d",
763 res_handle_offset, key_handle))
764 return TPM_LIB_ERROR;
765 }
766
767 return 0;
768 }
769
770 u32 tpm_get_pub_key_oiap(struct udevice *dev, u32 key_handle,
771 const void *usage_auth, void *pubkey,
772 size_t *pubkey_len)
773 {
774 const u8 command[14] = {
775 0x00, 0xc2, /* TPM_TAG */
776 0x00, 0x00, 0x00, 0x00, /* parameter size */
777 0x00, 0x00, 0x00, 0x21, /* TPM_COMMAND_CODE */
778 0x00, 0x00, 0x00, 0x00, /* key handle */
779 };
780 const size_t req_size_offset = 2;
781 const size_t req_key_handle_offset = TPM_REQUEST_HEADER_LENGTH;
782 const size_t res_pubkey_offset = TPM_RESPONSE_HEADER_LENGTH;
783 u8 request[sizeof(command) + TPM_REQUEST_AUTH_LENGTH];
784 u8 response[TPM_RESPONSE_HEADER_LENGTH + TPM_PUBKEY_MAX_LENGTH +
785 TPM_RESPONSE_AUTH_LENGTH];
786 size_t response_length = sizeof(response);
787 u32 err;
788
789 if (!oiap_session.valid) {
790 err = tpm_oiap(dev, NULL);
791 if (err)
792 return err;
793 }
794 if (pack_byte_string(request, sizeof(request), "sdd",
795 0, command, sizeof(command),
796 req_size_offset,
797 (u32)(sizeof(command)
798 + TPM_REQUEST_AUTH_LENGTH),
799 req_key_handle_offset, key_handle
800 ))
801 return TPM_LIB_ERROR;
802 err = create_request_auth(request, sizeof(command), 4, &oiap_session,
803 request + sizeof(command), usage_auth);
804 if (err)
805 return err;
806 err = tpm_sendrecv_command(dev, request, response, &response_length);
807 if (err) {
808 if (err == TPM_AUTHFAIL)
809 oiap_session.valid = 0;
810 return err;
811 }
812 err = verify_response_auth(0x00000021, response,
813 response_length - TPM_RESPONSE_AUTH_LENGTH,
814 0, &oiap_session,
815 response + response_length -
816 TPM_RESPONSE_AUTH_LENGTH,
817 usage_auth);
818 if (err)
819 return err;
820
821 if (pubkey) {
822 if ((response_length - TPM_RESPONSE_HEADER_LENGTH
823 - TPM_RESPONSE_AUTH_LENGTH) > *pubkey_len)
824 return TPM_LIB_ERROR;
825 *pubkey_len = response_length - TPM_RESPONSE_HEADER_LENGTH
826 - TPM_RESPONSE_AUTH_LENGTH;
827 memcpy(pubkey, response + res_pubkey_offset,
828 response_length - TPM_RESPONSE_HEADER_LENGTH
829 - TPM_RESPONSE_AUTH_LENGTH);
830 }
831
832 return 0;
833 }
834
835 #ifdef CONFIG_TPM_LOAD_KEY_BY_SHA1
836 u32 tpm_find_key_sha1(struct udevice *dev, const u8 auth[20],
837 const u8 pubkey_digest[20], u32 *handle)
838 {
839 u16 key_count;
840 u32 key_handles[10];
841 u8 buf[288];
842 u8 *ptr;
843 u32 err;
844 u8 digest[20];
845 size_t buf_len;
846 unsigned int i;
847
848 /* fetch list of already loaded keys in the TPM */
849 err = tpm_get_capability(dev, TPM_CAP_HANDLE, TPM_RT_KEY, buf,
850 sizeof(buf));
851 if (err)
852 return -1;
853 key_count = get_unaligned_be16(buf);
854 ptr = buf + 2;
855 for (i = 0; i < key_count; ++i, ptr += 4)
856 key_handles[i] = get_unaligned_be32(ptr);
857
858 /* now search a(/ the) key which we can access with the given auth */
859 for (i = 0; i < key_count; ++i) {
860 buf_len = sizeof(buf);
861 err = tpm_get_pub_key_oiap(key_handles[i], auth, buf, &buf_len);
862 if (err && err != TPM_AUTHFAIL)
863 return -1;
864 if (err)
865 continue;
866 sha1_csum(buf, buf_len, digest);
867 if (!memcmp(digest, pubkey_digest, 20)) {
868 *handle = key_handles[i];
869 return 0;
870 }
871 }
872 return 1;
873 }
874 #endif /* CONFIG_TPM_LOAD_KEY_BY_SHA1 */
875
876 #endif /* CONFIG_TPM_AUTH_SESSIONS */
877
878 u32 tpm_get_random(struct udevice *dev, void *data, u32 count)
879 {
880 const u8 command[14] = {
881 0x0, 0xc1, /* TPM_TAG */
882 0x0, 0x0, 0x0, 0xe, /* parameter size */
883 0x0, 0x0, 0x0, 0x46, /* TPM_COMMAND_CODE */
884 };
885 const size_t length_offset = 10;
886 const size_t data_size_offset = 10;
887 const size_t data_offset = 14;
888 u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
889 size_t response_length = sizeof(response);
890 u32 data_size;
891 u8 *out = data;
892
893 while (count > 0) {
894 u32 this_bytes = min((size_t)count,
895 sizeof(response) - data_offset);
896 u32 err;
897
898 if (pack_byte_string(buf, sizeof(buf), "sd",
899 0, command, sizeof(command),
900 length_offset, this_bytes))
901 return TPM_LIB_ERROR;
902 err = tpm_sendrecv_command(dev, buf, response,
903 &response_length);
904 if (err)
905 return err;
906 if (unpack_byte_string(response, response_length, "d",
907 data_size_offset, &data_size))
908 return TPM_LIB_ERROR;
909 if (data_size > count)
910 return TPM_LIB_ERROR;
911 if (unpack_byte_string(response, response_length, "s",
912 data_offset, out, data_size))
913 return TPM_LIB_ERROR;
914
915 count -= data_size;
916 out += data_size;
917 }
918
919 return 0;
920 }