xref: /rk3399_rockchip-uboot/lib/tpm.c (revision 78757d52c8b27f7f33ab4035706796a414c81128)
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_AUTH_SESSIONS
649 
650 /**
651  * Fill an authentication block in a request.
652  * This func can create the first as well as the second auth block (for
653  * double authorized commands).
654  *
655  * @param request	pointer to the request (w/ uninitialised auth data)
656  * @param request_len0	length of the request without auth data
657  * @param handles_len	length of the handles area in request
658  * @param auth_session	pointer to the (valid) auth session to be used
659  * @param request_auth	pointer to the auth block of the request to be filled
660  * @param auth		authentication data (HMAC key)
661  */
662 static uint32_t create_request_auth(const void *request, size_t request_len0,
663 	size_t handles_len,
664 	struct session_data *auth_session,
665 	void *request_auth, const void *auth)
666 {
667 	uint8_t hmac_data[DIGEST_LENGTH * 3 + 1];
668 	sha1_context hash_ctx;
669 	const size_t command_code_offset = 6;
670 	const size_t auth_nonce_odd_offset = 4;
671 	const size_t auth_continue_offset = 24;
672 	const size_t auth_auth_offset = 25;
673 
674 	if (!auth_session || !auth_session->valid)
675 		return TPM_LIB_ERROR;
676 
677 	sha1_starts(&hash_ctx);
678 	sha1_update(&hash_ctx, request + command_code_offset, 4);
679 	if (request_len0 > TPM_REQUEST_HEADER_LENGTH + handles_len)
680 		sha1_update(&hash_ctx,
681 			    request + TPM_REQUEST_HEADER_LENGTH + handles_len,
682 			    request_len0 - TPM_REQUEST_HEADER_LENGTH
683 			    - handles_len);
684 	sha1_finish(&hash_ctx, hmac_data);
685 
686 	sha1_starts(&hash_ctx);
687 	sha1_update(&hash_ctx, auth_session->nonce_odd, DIGEST_LENGTH);
688 	sha1_update(&hash_ctx, hmac_data, sizeof(hmac_data));
689 	sha1_finish(&hash_ctx, auth_session->nonce_odd);
690 
691 	if (pack_byte_string(request_auth, TPM_REQUEST_AUTH_LENGTH, "dsb",
692 			     0, auth_session->handle,
693 			     auth_nonce_odd_offset, auth_session->nonce_odd,
694 			     DIGEST_LENGTH,
695 			     auth_continue_offset, 1))
696 		return TPM_LIB_ERROR;
697 	if (pack_byte_string(hmac_data, sizeof(hmac_data), "ss",
698 			     DIGEST_LENGTH,
699 			     auth_session->nonce_even,
700 			     DIGEST_LENGTH,
701 			     2 * DIGEST_LENGTH,
702 			     request_auth + auth_nonce_odd_offset,
703 			     DIGEST_LENGTH + 1))
704 		return TPM_LIB_ERROR;
705 	sha1_hmac(auth, DIGEST_LENGTH, hmac_data, sizeof(hmac_data),
706 		  request_auth + auth_auth_offset);
707 
708 	return TPM_SUCCESS;
709 }
710 
711 /**
712  * Verify an authentication block in a response.
713  * Since this func updates the nonce_even in the session data it has to be
714  * called when receiving a succesfull AUTH response.
715  * This func can verify the first as well as the second auth block (for
716  * double authorized commands).
717  *
718  * @param command_code	command code of the request
719  * @param response	pointer to the request (w/ uninitialised auth data)
720  * @param handles_len	length of the handles area in response
721  * @param auth_session	pointer to the (valid) auth session to be used
722  * @param response_auth	pointer to the auth block of the response to be verified
723  * @param auth		authentication data (HMAC key)
724  */
725 static uint32_t verify_response_auth(uint32_t command_code,
726 	const void *response, size_t response_len0,
727 	size_t handles_len,
728 	struct session_data *auth_session,
729 	const void *response_auth, const void *auth)
730 {
731 	uint8_t hmac_data[DIGEST_LENGTH * 3 + 1];
732 	uint8_t computed_auth[DIGEST_LENGTH];
733 	sha1_context hash_ctx;
734 	const size_t return_code_offset = 6;
735 	const size_t auth_continue_offset = 20;
736 	const size_t auth_auth_offset = 21;
737 	uint8_t auth_continue;
738 
739 	if (!auth_session || !auth_session->valid)
740 		return TPM_AUTHFAIL;
741 	if (pack_byte_string(hmac_data, sizeof(hmac_data), "d",
742 			     0, command_code))
743 		return TPM_LIB_ERROR;
744 	if (response_len0 < TPM_RESPONSE_HEADER_LENGTH)
745 		return TPM_LIB_ERROR;
746 
747 	sha1_starts(&hash_ctx);
748 	sha1_update(&hash_ctx, response + return_code_offset, 4);
749 	sha1_update(&hash_ctx, hmac_data, 4);
750 	if (response_len0 > TPM_RESPONSE_HEADER_LENGTH + handles_len)
751 		sha1_update(&hash_ctx,
752 			    response + TPM_RESPONSE_HEADER_LENGTH + handles_len,
753 			    response_len0 - TPM_RESPONSE_HEADER_LENGTH
754 			    - handles_len);
755 	sha1_finish(&hash_ctx, hmac_data);
756 
757 	memcpy(auth_session->nonce_even, response_auth, DIGEST_LENGTH);
758 	auth_continue = ((uint8_t *)response_auth)[auth_continue_offset];
759 	if (pack_byte_string(hmac_data, sizeof(hmac_data), "ssb",
760 			     DIGEST_LENGTH,
761 			     response_auth,
762 			     DIGEST_LENGTH,
763 			     2 * DIGEST_LENGTH,
764 			     auth_session->nonce_odd,
765 			     DIGEST_LENGTH,
766 			     3 * DIGEST_LENGTH,
767 			     auth_continue))
768 		return TPM_LIB_ERROR;
769 
770 	sha1_hmac(auth, DIGEST_LENGTH, hmac_data, sizeof(hmac_data),
771 		  computed_auth);
772 
773 	if (memcmp(computed_auth, response_auth + auth_auth_offset,
774 		   DIGEST_LENGTH))
775 		return TPM_AUTHFAIL;
776 
777 	return TPM_SUCCESS;
778 }
779 
780 
781 uint32_t tpm_terminate_auth_session(uint32_t auth_handle)
782 {
783 	const uint8_t command[18] = {
784 		0x00, 0xc1,		/* TPM_TAG */
785 		0x00, 0x00, 0x00, 0x00,	/* parameter size */
786 		0x00, 0x00, 0x00, 0xba,	/* TPM_COMMAND_CODE */
787 		0x00, 0x00, 0x00, 0x00,	/* TPM_HANDLE */
788 		0x00, 0x00, 0x00, 0x02,	/* TPM_RESSOURCE_TYPE */
789 	};
790 	const size_t req_handle_offset = TPM_REQUEST_HEADER_LENGTH;
791 	uint8_t request[COMMAND_BUFFER_SIZE];
792 
793 	if (pack_byte_string(request, sizeof(request), "sd",
794 			     0, command, sizeof(command),
795 			     req_handle_offset, auth_handle))
796 		return TPM_LIB_ERROR;
797 	if (oiap_session.valid && oiap_session.handle == auth_handle)
798 		oiap_session.valid = 0;
799 
800 	return tpm_sendrecv_command(request, NULL, NULL);
801 }
802 
803 uint32_t tpm_end_oiap(void)
804 {
805 	uint32_t err = TPM_SUCCESS;
806 	if (oiap_session.valid)
807 		err = tpm_terminate_auth_session(oiap_session.handle);
808 	return err;
809 }
810 
811 uint32_t tpm_oiap(uint32_t *auth_handle)
812 {
813 	const uint8_t command[10] = {
814 		0x00, 0xc1,		/* TPM_TAG */
815 		0x00, 0x00, 0x00, 0x0a,	/* parameter size */
816 		0x00, 0x00, 0x00, 0x0a,	/* TPM_COMMAND_CODE */
817 	};
818 	const size_t res_auth_handle_offset = TPM_RESPONSE_HEADER_LENGTH;
819 	const size_t res_nonce_even_offset = TPM_RESPONSE_HEADER_LENGTH + 4;
820 	uint8_t response[COMMAND_BUFFER_SIZE];
821 	size_t response_length = sizeof(response);
822 	uint32_t err;
823 
824 	if (oiap_session.valid)
825 		tpm_terminate_auth_session(oiap_session.handle);
826 
827 	err = tpm_sendrecv_command(command, response, &response_length);
828 	if (err)
829 		return err;
830 	if (unpack_byte_string(response, response_length, "ds",
831 			       res_auth_handle_offset, &oiap_session.handle,
832 			       res_nonce_even_offset, &oiap_session.nonce_even,
833 			       (uint32_t)DIGEST_LENGTH))
834 		return TPM_LIB_ERROR;
835 	oiap_session.valid = 1;
836 	if (auth_handle)
837 		*auth_handle = oiap_session.handle;
838 	return 0;
839 }
840 
841 uint32_t tpm_load_key2_oiap(uint32_t parent_handle,
842 		const void *key, size_t key_length,
843 		const void *parent_key_usage_auth,
844 		uint32_t *key_handle)
845 {
846 	const uint8_t command[14] = {
847 		0x00, 0xc2,		/* TPM_TAG */
848 		0x00, 0x00, 0x00, 0x00,	/* parameter size */
849 		0x00, 0x00, 0x00, 0x41,	/* TPM_COMMAND_CODE */
850 		0x00, 0x00, 0x00, 0x00,	/* parent handle */
851 	};
852 	const size_t req_size_offset = 2;
853 	const size_t req_parent_handle_offset = TPM_REQUEST_HEADER_LENGTH;
854 	const size_t req_key_offset = TPM_REQUEST_HEADER_LENGTH + 4;
855 	const size_t res_handle_offset = TPM_RESPONSE_HEADER_LENGTH;
856 	uint8_t request[sizeof(command) + TPM_KEY12_MAX_LENGTH
857 			+ TPM_REQUEST_AUTH_LENGTH];
858 	uint8_t response[COMMAND_BUFFER_SIZE];
859 	size_t response_length = sizeof(response);
860 	uint32_t err;
861 
862 	if (!oiap_session.valid) {
863 		err = tpm_oiap(NULL);
864 		if (err)
865 			return err;
866 	}
867 	if (pack_byte_string(request, sizeof(request), "sdds",
868 			     0, command, sizeof(command),
869 			     req_size_offset,
870 			     sizeof(command) + key_length
871 			     + TPM_REQUEST_AUTH_LENGTH,
872 			     req_parent_handle_offset, parent_handle,
873 			     req_key_offset, key, key_length
874 		))
875 		return TPM_LIB_ERROR;
876 
877 	err = create_request_auth(request, sizeof(command) + key_length, 4,
878 				&oiap_session,
879 				request + sizeof(command) + key_length,
880 				parent_key_usage_auth);
881 	if (err)
882 		return err;
883 	err = tpm_sendrecv_command(request, response, &response_length);
884 	if (err) {
885 		if (err == TPM_AUTHFAIL)
886 			oiap_session.valid = 0;
887 		return err;
888 	}
889 
890 	err = verify_response_auth(0x00000041, response,
891 			response_length - TPM_RESPONSE_AUTH_LENGTH,
892 			4, &oiap_session,
893 			response + response_length - TPM_RESPONSE_AUTH_LENGTH,
894 			parent_key_usage_auth);
895 	if (err)
896 		return err;
897 
898 	if (key_handle) {
899 		if (unpack_byte_string(response, response_length, "d",
900 				       res_handle_offset, key_handle))
901 			return TPM_LIB_ERROR;
902 	}
903 
904 	return 0;
905 }
906 
907 uint32_t tpm_get_pub_key_oiap(uint32_t key_handle, const void *usage_auth,
908 			void *pubkey, size_t *pubkey_len)
909 {
910 	const uint8_t command[14] = {
911 		0x00, 0xc2,		/* TPM_TAG */
912 		0x00, 0x00, 0x00, 0x00,	/* parameter size */
913 		0x00, 0x00, 0x00, 0x21,	/* TPM_COMMAND_CODE */
914 		0x00, 0x00, 0x00, 0x00,	/* key handle */
915 	};
916 	const size_t req_size_offset = 2;
917 	const size_t req_key_handle_offset = TPM_REQUEST_HEADER_LENGTH;
918 	const size_t res_pubkey_offset = TPM_RESPONSE_HEADER_LENGTH;
919 	uint8_t request[sizeof(command) + TPM_REQUEST_AUTH_LENGTH];
920 	uint8_t response[TPM_RESPONSE_HEADER_LENGTH + TPM_PUBKEY_MAX_LENGTH
921 			+ TPM_RESPONSE_AUTH_LENGTH];
922 	size_t response_length = sizeof(response);
923 	uint32_t err;
924 
925 	if (!oiap_session.valid) {
926 		err = tpm_oiap(NULL);
927 		if (err)
928 			return err;
929 	}
930 	if (pack_byte_string(request, sizeof(request), "sdd",
931 			     0, command, sizeof(command),
932 			     req_size_offset,
933 			     (uint32_t)(sizeof(command)
934 			     + TPM_REQUEST_AUTH_LENGTH),
935 			     req_key_handle_offset, key_handle
936 		))
937 		return TPM_LIB_ERROR;
938 	err = create_request_auth(request, sizeof(command), 4, &oiap_session,
939 			request + sizeof(command), usage_auth);
940 	if (err)
941 		return err;
942 	err = tpm_sendrecv_command(request, response, &response_length);
943 	if (err) {
944 		if (err == TPM_AUTHFAIL)
945 			oiap_session.valid = 0;
946 		return err;
947 	}
948 	err = verify_response_auth(0x00000021, response,
949 			response_length - TPM_RESPONSE_AUTH_LENGTH,
950 			0, &oiap_session,
951 			response + response_length - TPM_RESPONSE_AUTH_LENGTH,
952 			usage_auth);
953 	if (err)
954 		return err;
955 
956 	if (pubkey) {
957 		if ((response_length - TPM_RESPONSE_HEADER_LENGTH
958 			- TPM_RESPONSE_AUTH_LENGTH) > *pubkey_len)
959 			return TPM_LIB_ERROR;
960 		*pubkey_len = response_length - TPM_RESPONSE_HEADER_LENGTH
961 			- TPM_RESPONSE_AUTH_LENGTH;
962 		memcpy(pubkey, response + res_pubkey_offset,
963 		       response_length - TPM_RESPONSE_HEADER_LENGTH
964 		       - TPM_RESPONSE_AUTH_LENGTH);
965 	}
966 
967 	return 0;
968 }
969 
970 #endif /* CONFIG_TPM_AUTH_SESSIONS */
971