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