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