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