xref: /OK3568_Linux_fs/u-boot/lib/tpm.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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  */
pack_byte_string(uint8_t * str,size_t size,const char * format,...)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  */
unpack_byte_string(const uint8_t * str,size_t size,const char * format,...)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  */
tpm_command_size(const void * command)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  */
tpm_return_code(const void * response)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  */
tpm_sendrecv_command(const void * command,void * response,size_t * size_ptr)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 
tpm_init(void)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 
tpm_startup(enum tpm_startup_type mode)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 
tpm_self_test_full(void)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 
tpm_continue_self_test(void)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 
tpm_nv_define_space(uint32_t index,uint32_t perm,uint32_t size)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 
tpm_nv_read_value(uint32_t index,void * data,uint32_t count)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 
tpm_nv_write_value(uint32_t index,const void * data,uint32_t length)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 
tpm_extend(uint32_t index,const void * in_digest,void * out_digest)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 
tpm_pcr_read(uint32_t index,void * data,size_t count)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 
tpm_tsc_physical_presence(uint16_t presence)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 
tpm_read_pubek(void * data,size_t count)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 
tpm_force_clear(void)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 
tpm_physical_enable(void)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 
tpm_physical_disable(void)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 
tpm_physical_set_deactivated(uint8_t state)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 
tpm_get_capability(uint32_t cap_area,uint32_t sub_cap,void * cap,size_t count)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 
tpm_get_permanent_flags(struct tpm_permanent_flags * pflags)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 	const size_t data_size_offset = TPM_HEADER_SIZE;
611 	const size_t data_offset = TPM_HEADER_SIZE + sizeof (uint32_t);
612 	uint8_t response[COMMAND_BUFFER_SIZE];
613 	size_t response_length = sizeof(response);
614 	uint32_t err;
615 	uint32_t data_size;
616 
617 	err = tpm_sendrecv_command(command, response, &response_length);
618 	if (err)
619 		return err;
620 	if (unpack_byte_string(response, response_length, "d",
621 			       data_size_offset, &data_size))
622 		return TPM_LIB_ERROR;
623 	if (data_size < sizeof(*pflags))
624 		return TPM_LIB_ERROR;
625 	if (unpack_byte_string(response, response_length, "s",
626 			       data_offset, pflags, sizeof(*pflags)))
627 		return TPM_LIB_ERROR;
628 
629 	return 0;
630 }
631 
tpm_get_permissions(uint32_t index,uint32_t * perm)632 uint32_t tpm_get_permissions(uint32_t index, uint32_t *perm)
633 {
634 	const uint8_t command[22] = {
635 		0x0, 0xc1,		/* TPM_TAG */
636 		0x0, 0x0, 0x0, 0x16,	/* parameter size */
637 		0x0, 0x0, 0x0, 0x65,	/* TPM_COMMAND_CODE */
638 		0x0, 0x0, 0x0, 0x11,
639 		0x0, 0x0, 0x0, 0x4,
640 	};
641 	const size_t index_offset = 18;
642 	const size_t perm_offset = 60;
643 	uint8_t buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
644 	size_t response_length = sizeof(response);
645 	uint32_t err;
646 
647 	if (pack_byte_string(buf, sizeof(buf), "d", 0, command, sizeof(command),
648 			     index_offset, index))
649 		return TPM_LIB_ERROR;
650 	err = tpm_sendrecv_command(buf, response, &response_length);
651 	if (err)
652 		return err;
653 	if (unpack_byte_string(response, response_length, "d",
654 			       perm_offset, perm))
655 		return TPM_LIB_ERROR;
656 
657 	return 0;
658 }
659 
660 #ifdef CONFIG_TPM_FLUSH_RESOURCES
tpm_flush_specific(uint32_t key_handle,uint32_t resource_type)661 uint32_t tpm_flush_specific(uint32_t key_handle, uint32_t resource_type)
662 {
663 	const uint8_t command[18] = {
664 		0x00, 0xc1,             /* TPM_TAG */
665 		0x00, 0x00, 0x00, 0x12, /* parameter size */
666 		0x00, 0x00, 0x00, 0xba, /* TPM_COMMAND_CODE */
667 		0x00, 0x00, 0x00, 0x00, /* key handle */
668 		0x00, 0x00, 0x00, 0x00, /* resource type */
669 	};
670 	const size_t key_handle_offset = 10;
671 	const size_t resource_type_offset = 14;
672 	uint8_t buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
673 	size_t response_length = sizeof(response);
674 	uint32_t err;
675 
676 	if (pack_byte_string(buf, sizeof(buf), "sdd",
677 			     0, command, sizeof(command),
678 			     key_handle_offset, key_handle,
679 			     resource_type_offset, resource_type))
680 		return TPM_LIB_ERROR;
681 
682 	err = tpm_sendrecv_command(buf, response, &response_length);
683 	if (err)
684 		return err;
685 	return 0;
686 }
687 #endif /* CONFIG_TPM_FLUSH_RESOURCES */
688 
689 #ifdef CONFIG_TPM_AUTH_SESSIONS
690 
691 /**
692  * Fill an authentication block in a request.
693  * This func can create the first as well as the second auth block (for
694  * double authorized commands).
695  *
696  * @param request	pointer to the request (w/ uninitialised auth data)
697  * @param request_len0	length of the request without auth data
698  * @param handles_len	length of the handles area in request
699  * @param auth_session	pointer to the (valid) auth session to be used
700  * @param request_auth	pointer to the auth block of the request to be filled
701  * @param auth		authentication data (HMAC key)
702  */
create_request_auth(const void * request,size_t request_len0,size_t handles_len,struct session_data * auth_session,void * request_auth,const void * auth)703 static uint32_t create_request_auth(const void *request, size_t request_len0,
704 	size_t handles_len,
705 	struct session_data *auth_session,
706 	void *request_auth, const void *auth)
707 {
708 	uint8_t hmac_data[DIGEST_LENGTH * 3 + 1];
709 	sha1_context hash_ctx;
710 	const size_t command_code_offset = 6;
711 	const size_t auth_nonce_odd_offset = 4;
712 	const size_t auth_continue_offset = 24;
713 	const size_t auth_auth_offset = 25;
714 
715 	if (!auth_session || !auth_session->valid)
716 		return TPM_LIB_ERROR;
717 
718 	sha1_starts(&hash_ctx);
719 	sha1_update(&hash_ctx, request + command_code_offset, 4);
720 	if (request_len0 > TPM_REQUEST_HEADER_LENGTH + handles_len)
721 		sha1_update(&hash_ctx,
722 			    request + TPM_REQUEST_HEADER_LENGTH + handles_len,
723 			    request_len0 - TPM_REQUEST_HEADER_LENGTH
724 			    - handles_len);
725 	sha1_finish(&hash_ctx, hmac_data);
726 
727 	sha1_starts(&hash_ctx);
728 	sha1_update(&hash_ctx, auth_session->nonce_odd, DIGEST_LENGTH);
729 	sha1_update(&hash_ctx, hmac_data, sizeof(hmac_data));
730 	sha1_finish(&hash_ctx, auth_session->nonce_odd);
731 
732 	if (pack_byte_string(request_auth, TPM_REQUEST_AUTH_LENGTH, "dsb",
733 			     0, auth_session->handle,
734 			     auth_nonce_odd_offset, auth_session->nonce_odd,
735 			     DIGEST_LENGTH,
736 			     auth_continue_offset, 1))
737 		return TPM_LIB_ERROR;
738 	if (pack_byte_string(hmac_data, sizeof(hmac_data), "ss",
739 			     DIGEST_LENGTH,
740 			     auth_session->nonce_even,
741 			     DIGEST_LENGTH,
742 			     2 * DIGEST_LENGTH,
743 			     request_auth + auth_nonce_odd_offset,
744 			     DIGEST_LENGTH + 1))
745 		return TPM_LIB_ERROR;
746 	sha1_hmac(auth, DIGEST_LENGTH, hmac_data, sizeof(hmac_data),
747 		  request_auth + auth_auth_offset);
748 
749 	return TPM_SUCCESS;
750 }
751 
752 /**
753  * Verify an authentication block in a response.
754  * Since this func updates the nonce_even in the session data it has to be
755  * called when receiving a succesfull AUTH response.
756  * This func can verify the first as well as the second auth block (for
757  * double authorized commands).
758  *
759  * @param command_code	command code of the request
760  * @param response	pointer to the request (w/ uninitialised auth data)
761  * @param handles_len	length of the handles area in response
762  * @param auth_session	pointer to the (valid) auth session to be used
763  * @param response_auth	pointer to the auth block of the response to be verified
764  * @param auth		authentication data (HMAC key)
765  */
verify_response_auth(uint32_t command_code,const void * response,size_t response_len0,size_t handles_len,struct session_data * auth_session,const void * response_auth,const void * auth)766 static uint32_t verify_response_auth(uint32_t command_code,
767 	const void *response, size_t response_len0,
768 	size_t handles_len,
769 	struct session_data *auth_session,
770 	const void *response_auth, const void *auth)
771 {
772 	uint8_t hmac_data[DIGEST_LENGTH * 3 + 1];
773 	uint8_t computed_auth[DIGEST_LENGTH];
774 	sha1_context hash_ctx;
775 	const size_t return_code_offset = 6;
776 	const size_t auth_continue_offset = 20;
777 	const size_t auth_auth_offset = 21;
778 	uint8_t auth_continue;
779 
780 	if (!auth_session || !auth_session->valid)
781 		return TPM_AUTHFAIL;
782 	if (pack_byte_string(hmac_data, sizeof(hmac_data), "d",
783 			     0, command_code))
784 		return TPM_LIB_ERROR;
785 	if (response_len0 < TPM_RESPONSE_HEADER_LENGTH)
786 		return TPM_LIB_ERROR;
787 
788 	sha1_starts(&hash_ctx);
789 	sha1_update(&hash_ctx, response + return_code_offset, 4);
790 	sha1_update(&hash_ctx, hmac_data, 4);
791 	if (response_len0 > TPM_RESPONSE_HEADER_LENGTH + handles_len)
792 		sha1_update(&hash_ctx,
793 			    response + TPM_RESPONSE_HEADER_LENGTH + handles_len,
794 			    response_len0 - TPM_RESPONSE_HEADER_LENGTH
795 			    - handles_len);
796 	sha1_finish(&hash_ctx, hmac_data);
797 
798 	memcpy(auth_session->nonce_even, response_auth, DIGEST_LENGTH);
799 	auth_continue = ((uint8_t *)response_auth)[auth_continue_offset];
800 	if (pack_byte_string(hmac_data, sizeof(hmac_data), "ssb",
801 			     DIGEST_LENGTH,
802 			     response_auth,
803 			     DIGEST_LENGTH,
804 			     2 * DIGEST_LENGTH,
805 			     auth_session->nonce_odd,
806 			     DIGEST_LENGTH,
807 			     3 * DIGEST_LENGTH,
808 			     auth_continue))
809 		return TPM_LIB_ERROR;
810 
811 	sha1_hmac(auth, DIGEST_LENGTH, hmac_data, sizeof(hmac_data),
812 		  computed_auth);
813 
814 	if (memcmp(computed_auth, response_auth + auth_auth_offset,
815 		   DIGEST_LENGTH))
816 		return TPM_AUTHFAIL;
817 
818 	return TPM_SUCCESS;
819 }
820 
821 
tpm_terminate_auth_session(uint32_t auth_handle)822 uint32_t tpm_terminate_auth_session(uint32_t auth_handle)
823 {
824 	const uint8_t command[18] = {
825 		0x00, 0xc1,		/* TPM_TAG */
826 		0x00, 0x00, 0x00, 0x00,	/* parameter size */
827 		0x00, 0x00, 0x00, 0xba,	/* TPM_COMMAND_CODE */
828 		0x00, 0x00, 0x00, 0x00,	/* TPM_HANDLE */
829 		0x00, 0x00, 0x00, 0x02,	/* TPM_RESSOURCE_TYPE */
830 	};
831 	const size_t req_handle_offset = TPM_REQUEST_HEADER_LENGTH;
832 	uint8_t request[COMMAND_BUFFER_SIZE];
833 
834 	if (pack_byte_string(request, sizeof(request), "sd",
835 			     0, command, sizeof(command),
836 			     req_handle_offset, auth_handle))
837 		return TPM_LIB_ERROR;
838 	if (oiap_session.valid && oiap_session.handle == auth_handle)
839 		oiap_session.valid = 0;
840 
841 	return tpm_sendrecv_command(request, NULL, NULL);
842 }
843 
tpm_end_oiap(void)844 uint32_t tpm_end_oiap(void)
845 {
846 	uint32_t err = TPM_SUCCESS;
847 	if (oiap_session.valid)
848 		err = tpm_terminate_auth_session(oiap_session.handle);
849 	return err;
850 }
851 
tpm_oiap(uint32_t * auth_handle)852 uint32_t tpm_oiap(uint32_t *auth_handle)
853 {
854 	const uint8_t command[10] = {
855 		0x00, 0xc1,		/* TPM_TAG */
856 		0x00, 0x00, 0x00, 0x0a,	/* parameter size */
857 		0x00, 0x00, 0x00, 0x0a,	/* TPM_COMMAND_CODE */
858 	};
859 	const size_t res_auth_handle_offset = TPM_RESPONSE_HEADER_LENGTH;
860 	const size_t res_nonce_even_offset = TPM_RESPONSE_HEADER_LENGTH + 4;
861 	uint8_t response[COMMAND_BUFFER_SIZE];
862 	size_t response_length = sizeof(response);
863 	uint32_t err;
864 
865 	if (oiap_session.valid)
866 		tpm_terminate_auth_session(oiap_session.handle);
867 
868 	err = tpm_sendrecv_command(command, response, &response_length);
869 	if (err)
870 		return err;
871 	if (unpack_byte_string(response, response_length, "ds",
872 			       res_auth_handle_offset, &oiap_session.handle,
873 			       res_nonce_even_offset, &oiap_session.nonce_even,
874 			       (uint32_t)DIGEST_LENGTH))
875 		return TPM_LIB_ERROR;
876 	oiap_session.valid = 1;
877 	if (auth_handle)
878 		*auth_handle = oiap_session.handle;
879 	return 0;
880 }
881 
tpm_load_key2_oiap(uint32_t parent_handle,const void * key,size_t key_length,const void * parent_key_usage_auth,uint32_t * key_handle)882 uint32_t tpm_load_key2_oiap(uint32_t parent_handle,
883 		const void *key, size_t key_length,
884 		const void *parent_key_usage_auth,
885 		uint32_t *key_handle)
886 {
887 	const uint8_t command[14] = {
888 		0x00, 0xc2,		/* TPM_TAG */
889 		0x00, 0x00, 0x00, 0x00,	/* parameter size */
890 		0x00, 0x00, 0x00, 0x41,	/* TPM_COMMAND_CODE */
891 		0x00, 0x00, 0x00, 0x00,	/* parent handle */
892 	};
893 	const size_t req_size_offset = 2;
894 	const size_t req_parent_handle_offset = TPM_REQUEST_HEADER_LENGTH;
895 	const size_t req_key_offset = TPM_REQUEST_HEADER_LENGTH + 4;
896 	const size_t res_handle_offset = TPM_RESPONSE_HEADER_LENGTH;
897 	uint8_t request[sizeof(command) + TPM_KEY12_MAX_LENGTH
898 			+ TPM_REQUEST_AUTH_LENGTH];
899 	uint8_t response[COMMAND_BUFFER_SIZE];
900 	size_t response_length = sizeof(response);
901 	uint32_t err;
902 
903 	if (!oiap_session.valid) {
904 		err = tpm_oiap(NULL);
905 		if (err)
906 			return err;
907 	}
908 	if (pack_byte_string(request, sizeof(request), "sdds",
909 			     0, command, sizeof(command),
910 			     req_size_offset,
911 			     sizeof(command) + key_length
912 			     + TPM_REQUEST_AUTH_LENGTH,
913 			     req_parent_handle_offset, parent_handle,
914 			     req_key_offset, key, key_length
915 		))
916 		return TPM_LIB_ERROR;
917 
918 	err = create_request_auth(request, sizeof(command) + key_length, 4,
919 				&oiap_session,
920 				request + sizeof(command) + key_length,
921 				parent_key_usage_auth);
922 	if (err)
923 		return err;
924 	err = tpm_sendrecv_command(request, response, &response_length);
925 	if (err) {
926 		if (err == TPM_AUTHFAIL)
927 			oiap_session.valid = 0;
928 		return err;
929 	}
930 
931 	err = verify_response_auth(0x00000041, response,
932 			response_length - TPM_RESPONSE_AUTH_LENGTH,
933 			4, &oiap_session,
934 			response + response_length - TPM_RESPONSE_AUTH_LENGTH,
935 			parent_key_usage_auth);
936 	if (err)
937 		return err;
938 
939 	if (key_handle) {
940 		if (unpack_byte_string(response, response_length, "d",
941 				       res_handle_offset, key_handle))
942 			return TPM_LIB_ERROR;
943 	}
944 
945 	return 0;
946 }
947 
tpm_get_pub_key_oiap(uint32_t key_handle,const void * usage_auth,void * pubkey,size_t * pubkey_len)948 uint32_t tpm_get_pub_key_oiap(uint32_t key_handle, const void *usage_auth,
949 			void *pubkey, size_t *pubkey_len)
950 {
951 	const uint8_t command[14] = {
952 		0x00, 0xc2,		/* TPM_TAG */
953 		0x00, 0x00, 0x00, 0x00,	/* parameter size */
954 		0x00, 0x00, 0x00, 0x21,	/* TPM_COMMAND_CODE */
955 		0x00, 0x00, 0x00, 0x00,	/* key handle */
956 	};
957 	const size_t req_size_offset = 2;
958 	const size_t req_key_handle_offset = TPM_REQUEST_HEADER_LENGTH;
959 	const size_t res_pubkey_offset = TPM_RESPONSE_HEADER_LENGTH;
960 	uint8_t request[sizeof(command) + TPM_REQUEST_AUTH_LENGTH];
961 	uint8_t response[TPM_RESPONSE_HEADER_LENGTH + TPM_PUBKEY_MAX_LENGTH
962 			+ TPM_RESPONSE_AUTH_LENGTH];
963 	size_t response_length = sizeof(response);
964 	uint32_t err;
965 
966 	if (!oiap_session.valid) {
967 		err = tpm_oiap(NULL);
968 		if (err)
969 			return err;
970 	}
971 	if (pack_byte_string(request, sizeof(request), "sdd",
972 			     0, command, sizeof(command),
973 			     req_size_offset,
974 			     (uint32_t)(sizeof(command)
975 			     + TPM_REQUEST_AUTH_LENGTH),
976 			     req_key_handle_offset, key_handle
977 		))
978 		return TPM_LIB_ERROR;
979 	err = create_request_auth(request, sizeof(command), 4, &oiap_session,
980 			request + sizeof(command), usage_auth);
981 	if (err)
982 		return err;
983 	err = tpm_sendrecv_command(request, response, &response_length);
984 	if (err) {
985 		if (err == TPM_AUTHFAIL)
986 			oiap_session.valid = 0;
987 		return err;
988 	}
989 	err = verify_response_auth(0x00000021, response,
990 			response_length - TPM_RESPONSE_AUTH_LENGTH,
991 			0, &oiap_session,
992 			response + response_length - TPM_RESPONSE_AUTH_LENGTH,
993 			usage_auth);
994 	if (err)
995 		return err;
996 
997 	if (pubkey) {
998 		if ((response_length - TPM_RESPONSE_HEADER_LENGTH
999 			- TPM_RESPONSE_AUTH_LENGTH) > *pubkey_len)
1000 			return TPM_LIB_ERROR;
1001 		*pubkey_len = response_length - TPM_RESPONSE_HEADER_LENGTH
1002 			- TPM_RESPONSE_AUTH_LENGTH;
1003 		memcpy(pubkey, response + res_pubkey_offset,
1004 		       response_length - TPM_RESPONSE_HEADER_LENGTH
1005 		       - TPM_RESPONSE_AUTH_LENGTH);
1006 	}
1007 
1008 	return 0;
1009 }
1010 
1011 #ifdef CONFIG_TPM_LOAD_KEY_BY_SHA1
tpm_find_key_sha1(const uint8_t auth[20],const uint8_t pubkey_digest[20],uint32_t * handle)1012 uint32_t tpm_find_key_sha1(const uint8_t auth[20], const uint8_t
1013 			   pubkey_digest[20], uint32_t *handle)
1014 {
1015 	uint16_t key_count;
1016 	uint32_t key_handles[10];
1017 	uint8_t buf[288];
1018 	uint8_t *ptr;
1019 	uint32_t err;
1020 	uint8_t digest[20];
1021 	size_t buf_len;
1022 	unsigned int i;
1023 
1024 	/* fetch list of already loaded keys in the TPM */
1025 	err = tpm_get_capability(TPM_CAP_HANDLE, TPM_RT_KEY, buf, sizeof(buf));
1026 	if (err)
1027 		return -1;
1028 	key_count = get_unaligned_be16(buf);
1029 	ptr = buf + 2;
1030 	for (i = 0; i < key_count; ++i, ptr += 4)
1031 		key_handles[i] = get_unaligned_be32(ptr);
1032 
1033 	/* now search a(/ the) key which we can access with the given auth */
1034 	for (i = 0; i < key_count; ++i) {
1035 		buf_len = sizeof(buf);
1036 		err = tpm_get_pub_key_oiap(key_handles[i], auth, buf, &buf_len);
1037 		if (err && err != TPM_AUTHFAIL)
1038 			return -1;
1039 		if (err)
1040 			continue;
1041 		sha1_csum(buf, buf_len, digest);
1042 		if (!memcmp(digest, pubkey_digest, 20)) {
1043 			*handle = key_handles[i];
1044 			return 0;
1045 		}
1046 	}
1047 	return 1;
1048 }
1049 #endif /* CONFIG_TPM_LOAD_KEY_BY_SHA1 */
1050 
1051 #endif /* CONFIG_TPM_AUTH_SESSIONS */
1052