xref: /openbmc/u-boot/lib/tpm-v1.c (revision c00d0012)
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 }
915