1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (c) 2018, Bootlin
4  * Author: Miquel Raynal <miquel.raynal@bootlin.com>
5  */
6 
7 #include <common.h>
8 #include <dm.h>
9 #include <tpm-v2.h>
10 #include <asm/state.h>
11 #include <asm/unaligned.h>
12 #include <linux/bitops.h>
13 #include <u-boot/crc.h>
14 
15 /* Hierarchies */
16 enum tpm2_hierarchy {
17 	TPM2_HIERARCHY_LOCKOUT = 0,
18 	TPM2_HIERARCHY_ENDORSEMENT,
19 	TPM2_HIERARCHY_PLATFORM,
20 	TPM2_HIERARCHY_NB,
21 };
22 
23 /* Subset of supported capabilities */
24 enum tpm2_capability {
25 	TPM_CAP_TPM_PROPERTIES = 0x6,
26 };
27 
28 /* Subset of supported properties */
29 #define TPM2_PROPERTIES_OFFSET 0x0000020E
30 
31 enum tpm2_cap_tpm_property {
32 	TPM2_FAIL_COUNTER = 0,
33 	TPM2_PROP_MAX_TRIES,
34 	TPM2_RECOVERY_TIME,
35 	TPM2_LOCKOUT_RECOVERY,
36 	TPM2_PROPERTY_NB,
37 };
38 
39 #define SANDBOX_TPM_PCR_NB 1
40 
41 static const u8 sandbox_extended_once_pcr[] = {
42 	0xf5, 0xa5, 0xfd, 0x42, 0xd1, 0x6a, 0x20, 0x30,
43 	0x27, 0x98, 0xef, 0x6e, 0xd3, 0x09, 0x97, 0x9b,
44 	0x43, 0x00, 0x3d, 0x23, 0x20, 0xd9, 0xf0, 0xe8,
45 	0xea, 0x98, 0x31, 0xa9, 0x27, 0x59, 0xfb, 0x4b,
46 };
47 
48 struct sandbox_tpm2 {
49 	/* TPM internal states */
50 	bool init_done;
51 	bool startup_done;
52 	bool tests_done;
53 	/* TPM password per hierarchy */
54 	char pw[TPM2_HIERARCHY_NB][TPM2_DIGEST_LEN + 1];
55 	int pw_sz[TPM2_HIERARCHY_NB];
56 	/* TPM properties */
57 	u32 properties[TPM2_PROPERTY_NB];
58 	/* TPM PCRs */
59 	u8 pcr[SANDBOX_TPM_PCR_NB][TPM2_DIGEST_LEN];
60 	/* TPM PCR extensions */
61 	u32 pcr_extensions[SANDBOX_TPM_PCR_NB];
62 };
63 
64 /*
65  * Check the tag validity depending on the command (authentication required or
66  * not). If authentication is required, check it is valid. Update the auth
67  * pointer to point to the next chunk of data to process if needed.
68  */
sandbox_tpm2_check_session(struct udevice * dev,u32 command,u16 tag,const u8 ** auth,enum tpm2_hierarchy * hierarchy)69 static int sandbox_tpm2_check_session(struct udevice *dev, u32 command, u16 tag,
70 				      const u8 **auth,
71 				      enum tpm2_hierarchy *hierarchy)
72 {
73 	struct sandbox_tpm2 *tpm = dev_get_priv(dev);
74 	u32 handle, auth_sz, session_handle;
75 	u16 nonce_sz, pw_sz;
76 	const char *pw;
77 
78 	switch (command) {
79 	case TPM2_CC_STARTUP:
80 	case TPM2_CC_SELF_TEST:
81 	case TPM2_CC_GET_CAPABILITY:
82 	case TPM2_CC_PCR_READ:
83 		if (tag != TPM2_ST_NO_SESSIONS) {
84 			printf("No session required for command 0x%x\n",
85 			       command);
86 			return TPM2_RC_BAD_TAG;
87 		}
88 
89 		return 0;
90 
91 	case TPM2_CC_CLEAR:
92 	case TPM2_CC_HIERCHANGEAUTH:
93 	case TPM2_CC_DAM_RESET:
94 	case TPM2_CC_DAM_PARAMETERS:
95 	case TPM2_CC_PCR_EXTEND:
96 		if (tag != TPM2_ST_SESSIONS) {
97 			printf("Session required for command 0x%x\n", command);
98 			return TPM2_RC_AUTH_CONTEXT;
99 		}
100 
101 		handle = get_unaligned_be32(*auth);
102 		*auth += sizeof(handle);
103 
104 		/*
105 		 * PCR_Extend had a different protection mechanism and does not
106 		 * use the same standards as other commands.
107 		 */
108 		if (command == TPM2_CC_PCR_EXTEND)
109 			break;
110 
111 		switch (handle) {
112 		case TPM2_RH_LOCKOUT:
113 			*hierarchy = TPM2_HIERARCHY_LOCKOUT;
114 			break;
115 		case TPM2_RH_ENDORSEMENT:
116 			if (command == TPM2_CC_CLEAR) {
117 				printf("Endorsement hierarchy unsupported\n");
118 				return TPM2_RC_AUTH_MISSING;
119 			}
120 			*hierarchy = TPM2_HIERARCHY_ENDORSEMENT;
121 			break;
122 		case TPM2_RH_PLATFORM:
123 			*hierarchy = TPM2_HIERARCHY_PLATFORM;
124 			break;
125 		default:
126 			printf("Wrong handle 0x%x\n", handle);
127 			return TPM2_RC_VALUE;
128 		}
129 
130 		break;
131 
132 	default:
133 		printf("Command code not recognized: 0x%x\n", command);
134 		return TPM2_RC_COMMAND_CODE;
135 	}
136 
137 	auth_sz = get_unaligned_be32(*auth);
138 	*auth += sizeof(auth_sz);
139 
140 	session_handle = get_unaligned_be32(*auth);
141 	*auth += sizeof(session_handle);
142 	if (session_handle != TPM2_RS_PW) {
143 		printf("Wrong session handle 0x%x\n", session_handle);
144 		return TPM2_RC_VALUE;
145 	}
146 
147 	nonce_sz = get_unaligned_be16(*auth);
148 	*auth += sizeof(nonce_sz);
149 	if (nonce_sz) {
150 		printf("Nonces not supported in Sandbox, aborting\n");
151 		return TPM2_RC_HANDLE;
152 	}
153 
154 	/* Ignore attributes */
155 	*auth += sizeof(u8);
156 
157 	pw_sz = get_unaligned_be16(*auth);
158 	*auth += sizeof(pw_sz);
159 	if (auth_sz != (9 + nonce_sz + pw_sz)) {
160 		printf("Authentication size (%d) do not match %d\n",
161 		       auth_sz, 9 + nonce_sz + pw_sz);
162 		return TPM2_RC_SIZE;
163 	}
164 
165 	/* No passwork is acceptable */
166 	if (!pw_sz && !tpm->pw_sz[*hierarchy])
167 		return TPM2_RC_SUCCESS;
168 
169 	/* Password is too long */
170 	if (pw_sz > TPM2_DIGEST_LEN) {
171 		printf("Password should not be more than %dB\n",
172 		       TPM2_DIGEST_LEN);
173 		return TPM2_RC_AUTHSIZE;
174 	}
175 
176 	pw = (const char *)*auth;
177 	*auth += pw_sz;
178 
179 	/* Password is wrong */
180 	if (pw_sz != tpm->pw_sz[*hierarchy] ||
181 	    strncmp(pw, tpm->pw[*hierarchy], tpm->pw_sz[*hierarchy])) {
182 		printf("Authentication failed: wrong password.\n");
183 		return TPM2_RC_BAD_AUTH;
184 	}
185 
186 	return TPM2_RC_SUCCESS;
187 }
188 
sandbox_tpm2_check_readyness(struct udevice * dev,int command)189 static int sandbox_tpm2_check_readyness(struct udevice *dev, int command)
190 {
191 	struct sandbox_tpm2 *tpm = dev_get_priv(dev);
192 
193 	switch (command) {
194 	case TPM2_CC_STARTUP:
195 		if (!tpm->init_done || tpm->startup_done)
196 			return TPM2_RC_INITIALIZE;
197 
198 		break;
199 	case TPM2_CC_GET_CAPABILITY:
200 		if (!tpm->init_done || !tpm->startup_done)
201 			return TPM2_RC_INITIALIZE;
202 
203 		break;
204 	case TPM2_CC_SELF_TEST:
205 		if (!tpm->startup_done)
206 			return TPM2_RC_INITIALIZE;
207 
208 		break;
209 	default:
210 		if (!tpm->tests_done)
211 			return TPM2_RC_NEEDS_TEST;
212 
213 		break;
214 	}
215 
216 	return 0;
217 }
218 
sandbox_tpm2_fill_buf(u8 * recv,size_t * recv_len,u16 tag,u32 rc)219 static int sandbox_tpm2_fill_buf(u8 *recv, size_t *recv_len, u16 tag, u32 rc)
220 {
221 	*recv_len = sizeof(tag) + sizeof(u32) + sizeof(rc);
222 
223 	/* Write tag */
224 	put_unaligned_be16(tag, recv);
225 	recv += sizeof(tag);
226 
227 	/* Write length */
228 	put_unaligned_be32(*recv_len, recv);
229 	recv += sizeof(u32);
230 
231 	/* Write return code */
232 	put_unaligned_be32(rc, recv);
233 	recv += sizeof(rc);
234 
235 	/* Add trailing \0 */
236 	*recv = '\0';
237 
238 	return 0;
239 }
240 
sandbox_tpm2_extend(struct udevice * dev,int pcr_index,const u8 * extension)241 static int sandbox_tpm2_extend(struct udevice *dev, int pcr_index,
242 			       const u8 *extension)
243 {
244 	struct sandbox_tpm2 *tpm = dev_get_priv(dev);
245 	int i;
246 
247 	/* Only simulate the first extensions from all '0' with only '0' */
248 	for (i = 0; i < TPM2_DIGEST_LEN; i++)
249 		if (tpm->pcr[pcr_index][i] || extension[i])
250 			return TPM2_RC_FAILURE;
251 
252 	memcpy(tpm->pcr[pcr_index], sandbox_extended_once_pcr,
253 	       TPM2_DIGEST_LEN);
254 	tpm->pcr_extensions[pcr_index]++;
255 
256 	return 0;
257 };
258 
sandbox_tpm2_xfer(struct udevice * dev,const u8 * sendbuf,size_t send_size,u8 * recvbuf,size_t * recv_len)259 static int sandbox_tpm2_xfer(struct udevice *dev, const u8 *sendbuf,
260 			     size_t send_size, u8 *recvbuf,
261 			     size_t *recv_len)
262 {
263 	struct sandbox_tpm2 *tpm = dev_get_priv(dev);
264 	enum tpm2_hierarchy hierarchy = 0;
265 	const u8 *sent = sendbuf;
266 	u8 *recv = recvbuf;
267 	u32 length, command, rc = 0;
268 	u16 tag, mode, new_pw_sz;
269 	u8 yes_no;
270 	int i, j;
271 
272 	/* TPM2_GetProperty */
273 	u32 capability, property, property_count;
274 
275 	/* TPM2_PCR_Read/Extend variables */
276 	int pcr_index = 0;
277 	u64 pcr_map = 0;
278 	u32 selections, pcr_nb;
279 	u16 alg;
280 	u8 pcr_array_sz;
281 
282 	tag = get_unaligned_be16(sent);
283 	sent += sizeof(tag);
284 
285 	length = get_unaligned_be32(sent);
286 	sent += sizeof(length);
287 	if (length != send_size) {
288 		printf("TPM2: Unmatching length, received: %zd, expected: %d\n",
289 		       send_size, length);
290 		rc = TPM2_RC_SIZE;
291 		sandbox_tpm2_fill_buf(recv, recv_len, tag, rc);
292 		return 0;
293 	}
294 
295 	command = get_unaligned_be32(sent);
296 	sent += sizeof(command);
297 	rc = sandbox_tpm2_check_readyness(dev, command);
298 	if (rc) {
299 		sandbox_tpm2_fill_buf(recv, recv_len, tag, rc);
300 		return 0;
301 	}
302 
303 	rc = sandbox_tpm2_check_session(dev, command, tag, &sent, &hierarchy);
304 	if (rc) {
305 		sandbox_tpm2_fill_buf(recv, recv_len, tag, rc);
306 		return 0;
307 	}
308 
309 	switch (command) {
310 	case TPM2_CC_STARTUP:
311 		mode = get_unaligned_be16(sent);
312 		sent += sizeof(mode);
313 		switch (mode) {
314 		case TPM2_SU_CLEAR:
315 		case TPM2_SU_STATE:
316 			break;
317 		default:
318 			rc = TPM2_RC_VALUE;
319 		}
320 
321 		tpm->startup_done = true;
322 
323 		sandbox_tpm2_fill_buf(recv, recv_len, tag, rc);
324 		break;
325 
326 	case TPM2_CC_SELF_TEST:
327 		yes_no = *sent;
328 		sent += sizeof(yes_no);
329 		switch (yes_no) {
330 		case TPMI_YES:
331 		case TPMI_NO:
332 			break;
333 		default:
334 			rc = TPM2_RC_VALUE;
335 		}
336 
337 		tpm->tests_done = true;
338 
339 		sandbox_tpm2_fill_buf(recv, recv_len, tag, rc);
340 		break;
341 
342 	case TPM2_CC_CLEAR:
343 		/* Reset this hierarchy password */
344 		tpm->pw_sz[hierarchy] = 0;
345 
346 		/* Reset all password if thisis the PLATFORM hierarchy */
347 		if (hierarchy == TPM2_HIERARCHY_PLATFORM)
348 			for (i = 0; i < TPM2_HIERARCHY_NB; i++)
349 				tpm->pw_sz[i] = 0;
350 
351 		/* Reset the properties */
352 		for (i = 0; i < TPM2_PROPERTY_NB; i++)
353 			tpm->properties[i] = 0;
354 
355 		/* Reset the PCRs and their number of extensions */
356 		for (i = 0; i < SANDBOX_TPM_PCR_NB; i++) {
357 			tpm->pcr_extensions[i] = 0;
358 			for (j = 0; j < TPM2_DIGEST_LEN; j++)
359 				tpm->pcr[i][j] = 0;
360 		}
361 
362 		sandbox_tpm2_fill_buf(recv, recv_len, tag, rc);
363 		break;
364 
365 	case TPM2_CC_HIERCHANGEAUTH:
366 		new_pw_sz = get_unaligned_be16(sent);
367 		sent += sizeof(new_pw_sz);
368 		if (new_pw_sz > TPM2_DIGEST_LEN) {
369 			rc = TPM2_RC_SIZE;
370 		} else if (new_pw_sz) {
371 			tpm->pw_sz[hierarchy] = new_pw_sz;
372 			memcpy(tpm->pw[hierarchy], sent, new_pw_sz);
373 			sent += new_pw_sz;
374 		}
375 
376 		sandbox_tpm2_fill_buf(recv, recv_len, tag, rc);
377 		break;
378 
379 	case TPM2_CC_GET_CAPABILITY:
380 		capability = get_unaligned_be32(sent);
381 		sent += sizeof(capability);
382 		if (capability != TPM_CAP_TPM_PROPERTIES) {
383 			printf("Sandbox TPM only support TPM_CAPABILITIES\n");
384 			return TPM2_RC_HANDLE;
385 		}
386 
387 		property = get_unaligned_be32(sent);
388 		sent += sizeof(property);
389 		property -= TPM2_PROPERTIES_OFFSET;
390 
391 		property_count = get_unaligned_be32(sent);
392 		sent += sizeof(property_count);
393 		if (!property_count ||
394 		    property + property_count > TPM2_PROPERTY_NB) {
395 			rc = TPM2_RC_HANDLE;
396 			return sandbox_tpm2_fill_buf(recv, recv_len, tag, rc);
397 		}
398 
399 		/* Write tag */
400 		put_unaligned_be16(tag, recv);
401 		recv += sizeof(tag);
402 
403 		/* Ignore length for now */
404 		recv += sizeof(u32);
405 
406 		/* Write return code */
407 		put_unaligned_be32(rc, recv);
408 		recv += sizeof(rc);
409 
410 		/* Tell there is more data to read */
411 		*recv = TPMI_YES;
412 		recv += sizeof(yes_no);
413 
414 		/* Repeat the capability */
415 		put_unaligned_be32(capability, recv);
416 		recv += sizeof(capability);
417 
418 		/* Give the number of properties that follow */
419 		put_unaligned_be32(property_count, recv);
420 		recv += sizeof(property_count);
421 
422 		/* Fill with the properties */
423 		for (i = 0; i < property_count; i++) {
424 			put_unaligned_be32(TPM2_PROPERTIES_OFFSET + property +
425 					   i, recv);
426 			recv += sizeof(property);
427 			put_unaligned_be32(tpm->properties[property + i],
428 					   recv);
429 			recv += sizeof(property);
430 		}
431 
432 		/* Add trailing \0 */
433 		*recv = '\0';
434 
435 		/* Write response length */
436 		*recv_len = recv - recvbuf;
437 		put_unaligned_be32(*recv_len, recvbuf + sizeof(tag));
438 
439 		break;
440 
441 	case TPM2_CC_DAM_PARAMETERS:
442 		tpm->properties[TPM2_PROP_MAX_TRIES] = get_unaligned_be32(sent);
443 		sent += sizeof(*tpm->properties);
444 		tpm->properties[TPM2_RECOVERY_TIME] = get_unaligned_be32(sent);
445 		sent += sizeof(*tpm->properties);
446 		tpm->properties[TPM2_LOCKOUT_RECOVERY] = get_unaligned_be32(sent);
447 		sent += sizeof(*tpm->properties);
448 
449 		sandbox_tpm2_fill_buf(recv, recv_len, tag, rc);
450 		break;
451 
452 	case TPM2_CC_PCR_READ:
453 		selections = get_unaligned_be32(sent);
454 		sent += sizeof(selections);
455 		if (selections != 1) {
456 			printf("Sandbox cannot handle more than one PCR\n");
457 			rc = TPM2_RC_VALUE;
458 			return sandbox_tpm2_fill_buf(recv, recv_len, tag, rc);
459 		}
460 
461 		alg = get_unaligned_be16(sent);
462 		sent += sizeof(alg);
463 		if (alg != TPM2_ALG_SHA256) {
464 			printf("Sandbox TPM only handle SHA256 algorithm\n");
465 			rc = TPM2_RC_VALUE;
466 			return sandbox_tpm2_fill_buf(recv, recv_len, tag, rc);
467 		}
468 
469 		pcr_array_sz = *sent;
470 		sent += sizeof(pcr_array_sz);
471 		if (!pcr_array_sz || pcr_array_sz > 8) {
472 			printf("Sandbox TPM cannot handle so much PCRs\n");
473 			rc = TPM2_RC_VALUE;
474 			return sandbox_tpm2_fill_buf(recv, recv_len, tag, rc);
475 		}
476 
477 		for (i = 0; i < pcr_array_sz; i++)
478 			pcr_map += (u64)sent[i] << (i * 8);
479 
480 		if (pcr_map >> SANDBOX_TPM_PCR_NB) {
481 			printf("Sandbox TPM handles up to %d PCR(s)\n",
482 			       SANDBOX_TPM_PCR_NB);
483 			rc = TPM2_RC_VALUE;
484 			return sandbox_tpm2_fill_buf(recv, recv_len, tag, rc);
485 		}
486 
487 		if (!pcr_map) {
488 			printf("Empty PCR map.\n");
489 			rc = TPM2_RC_VALUE;
490 			return sandbox_tpm2_fill_buf(recv, recv_len, tag, rc);
491 		}
492 
493 		for (i = 0; i < SANDBOX_TPM_PCR_NB; i++)
494 			if (pcr_map & BIT(i))
495 				pcr_index = i;
496 
497 		/* Write tag */
498 		put_unaligned_be16(tag, recv);
499 		recv += sizeof(tag);
500 
501 		/* Ignore length for now */
502 		recv += sizeof(u32);
503 
504 		/* Write return code */
505 		put_unaligned_be32(rc, recv);
506 		recv += sizeof(rc);
507 
508 		/* Number of extensions */
509 		put_unaligned_be32(tpm->pcr_extensions[pcr_index], recv);
510 		recv += sizeof(u32);
511 
512 		/* Copy the PCR */
513 		memcpy(recv, tpm->pcr[pcr_index], TPM2_DIGEST_LEN);
514 		recv += TPM2_DIGEST_LEN;
515 
516 		/* Add trailing \0 */
517 		*recv = '\0';
518 
519 		/* Write response length */
520 		*recv_len = recv - recvbuf;
521 		put_unaligned_be32(*recv_len, recvbuf + sizeof(tag));
522 
523 		break;
524 
525 	case TPM2_CC_PCR_EXTEND:
526 		/* Get the PCR index */
527 		pcr_index = get_unaligned_be32(sendbuf + sizeof(tag) +
528 					       sizeof(length) +
529 					       sizeof(command));
530 		if (pcr_index > SANDBOX_TPM_PCR_NB) {
531 			printf("Sandbox TPM handles up to %d PCR(s)\n",
532 			       SANDBOX_TPM_PCR_NB);
533 			rc = TPM2_RC_VALUE;
534 		}
535 
536 		/* Check the number of hashes */
537 		pcr_nb = get_unaligned_be32(sent);
538 		sent += sizeof(pcr_nb);
539 		if (pcr_nb != 1) {
540 			printf("Sandbox cannot handle more than one PCR\n");
541 			rc = TPM2_RC_VALUE;
542 			return sandbox_tpm2_fill_buf(recv, recv_len, tag, rc);
543 		}
544 
545 		/* Check the hash algorithm */
546 		alg = get_unaligned_be16(sent);
547 		sent += sizeof(alg);
548 		if (alg != TPM2_ALG_SHA256) {
549 			printf("Sandbox TPM only handle SHA256 algorithm\n");
550 			rc = TPM2_RC_VALUE;
551 			return sandbox_tpm2_fill_buf(recv, recv_len, tag, rc);
552 		}
553 
554 		/* Extend the PCR */
555 		rc = sandbox_tpm2_extend(dev, pcr_index, sent);
556 
557 		sandbox_tpm2_fill_buf(recv, recv_len, tag, rc);
558 		break;
559 
560 	default:
561 		printf("TPM2 command %02x unknown in Sandbox\n", command);
562 		rc = TPM2_RC_COMMAND_CODE;
563 		sandbox_tpm2_fill_buf(recv, recv_len, tag, rc);
564 	}
565 
566 	return 0;
567 }
568 
sandbox_tpm2_get_desc(struct udevice * dev,char * buf,int size)569 static int sandbox_tpm2_get_desc(struct udevice *dev, char *buf, int size)
570 {
571 	if (size < 15)
572 		return -ENOSPC;
573 
574 	return snprintf(buf, size, "Sandbox TPM2.x");
575 }
576 
sandbox_tpm2_open(struct udevice * dev)577 static int sandbox_tpm2_open(struct udevice *dev)
578 {
579 	struct sandbox_tpm2 *tpm = dev_get_priv(dev);
580 
581 	if (tpm->init_done)
582 		return -EIO;
583 
584 	tpm->init_done = true;
585 
586 	return 0;
587 }
588 
sandbox_tpm2_probe(struct udevice * dev)589 static int sandbox_tpm2_probe(struct udevice *dev)
590 {
591 	struct sandbox_tpm2 *tpm = dev_get_priv(dev);
592 	struct tpm_chip_priv *priv = dev_get_uclass_priv(dev);
593 
594 	/* Use the TPM v2 stack */
595 	priv->version = TPM_V2;
596 
597 	memset(tpm, 0, sizeof(*tpm));
598 
599 	priv->pcr_count = 32;
600 	priv->pcr_select_min = 2;
601 
602 	return 0;
603 }
604 
sandbox_tpm2_close(struct udevice * dev)605 static int sandbox_tpm2_close(struct udevice *dev)
606 {
607 	return 0;
608 }
609 
610 static const struct tpm_ops sandbox_tpm2_ops = {
611 	.open		= sandbox_tpm2_open,
612 	.close		= sandbox_tpm2_close,
613 	.get_desc	= sandbox_tpm2_get_desc,
614 	.xfer		= sandbox_tpm2_xfer,
615 };
616 
617 static const struct udevice_id sandbox_tpm2_ids[] = {
618 	{ .compatible = "sandbox,tpm2" },
619 	{ }
620 };
621 
622 U_BOOT_DRIVER(sandbox_tpm2) = {
623 	.name   = "sandbox_tpm2",
624 	.id     = UCLASS_TPM,
625 	.of_match = sandbox_tpm2_ids,
626 	.ops    = &sandbox_tpm2_ops,
627 	.probe	= sandbox_tpm2_probe,
628 	.priv_auto	= sizeof(struct sandbox_tpm2),
629 };
630