1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (c) 2023 Linaro Limited
4  * Copyright (c) 2018 Bootlin
5  * Author: Miquel Raynal <miquel.raynal@bootlin.com>
6  */
7 
8 #include <dm.h>
9 #include <dm/of_access.h>
10 #include <tpm_api.h>
11 #include <tpm-common.h>
12 #include <tpm-v2.h>
13 #include <tpm_tcg2.h>
14 #include <u-boot/sha1.h>
15 #include <u-boot/sha256.h>
16 #include <u-boot/sha512.h>
17 #include <version_string.h>
18 #include <asm/io.h>
19 #include <linux/bitops.h>
20 #include <linux/unaligned/be_byteshift.h>
21 #include <linux/unaligned/generic.h>
22 #include <linux/unaligned/le_byteshift.h>
23 
24 #include "tpm-utils.h"
25 
tpm2_update_active_banks(struct udevice * dev)26 static int tpm2_update_active_banks(struct udevice *dev)
27 {
28 	struct tpm_chip_priv *priv = dev_get_uclass_priv(dev);
29 	struct tpml_pcr_selection pcrs;
30 	int ret, i;
31 
32 	ret = tpm2_get_pcr_info(dev, &pcrs);
33 	if (ret)
34 		return ret;
35 
36 	priv->active_bank_count = 0;
37 	for (i = 0; i < pcrs.count; i++) {
38 		if (!tpm2_is_active_bank(&pcrs.selection[i]))
39 			continue;
40 		priv->active_banks[priv->active_bank_count] = pcrs.selection[i].hash;
41 		priv->active_bank_count++;
42 	}
43 
44 	return 0;
45 }
46 
tpm2_print_selected_algorithm_name(u32 selected)47 static void tpm2_print_selected_algorithm_name(u32 selected)
48 {
49 	size_t i;
50 	const char *str;
51 
52 	for (i = 0; i < ARRAY_SIZE(hash_algo_list); i++) {
53 		const struct digest_info *algo = &hash_algo_list[i];
54 
55 		if (!(selected & algo->hash_mask))
56 			continue;
57 
58 		str = tpm2_algorithm_name(algo->hash_alg);
59 		if (str)
60 			log_info("%s\n", str);
61 	}
62 }
63 
tpm2_scan_masks(struct udevice * dev,u32 log_active,u32 * mask)64 int tpm2_scan_masks(struct udevice *dev, u32 log_active, u32 *mask)
65 {
66 	struct tpml_pcr_selection pcrs;
67 	u32 active = 0;
68 	u32 supported = 0;
69 	int rc, i;
70 
71 	*mask = 0;
72 
73 	rc = tpm2_get_pcr_info(dev, &pcrs);
74 	if (rc)
75 		return rc;
76 
77 	for (i = 0; i < pcrs.count; i++) {
78 		struct tpms_pcr_selection *sel = &pcrs.selection[i];
79 		size_t j;
80 		u32 hash_mask = 0;
81 
82 		for (j = 0; j < ARRAY_SIZE(hash_algo_list); j++) {
83 			if (hash_algo_list[j].hash_alg == sel->hash)
84 				hash_mask = hash_algo_list[j].hash_mask;
85 		}
86 
87 		if (tpm2_algorithm_supported(sel->hash))
88 			supported |= hash_mask;
89 
90 		if (tpm2_is_active_bank(sel))
91 			active |= hash_mask;
92 	}
93 
94 	/* All eventlog algorithm(s) must be supported */
95 	if (log_active & ~supported) {
96 		log_err("EventLog contains U-Boot unsupported algorithm(s)\n");
97 		tpm2_print_selected_algorithm_name(log_active & ~supported);
98 		rc = -1;
99 	}
100 	if (log_active && active & ~log_active) {
101 		log_warning("TPM active algorithm(s) not exist in eventlog\n");
102 		tpm2_print_selected_algorithm_name(active & ~log_active);
103 		*mask = log_active;
104 	}
105 
106 	/* Any active algorithm(s) which are not supported must be removed */
107 	if (active & ~supported) {
108 		log_warning("TPM active algorithm(s) unsupported by u-boot\n");
109 		tpm2_print_selected_algorithm_name(active & ~supported);
110 		if (*mask)
111 			*mask = active & supported & *mask;
112 		else
113 			*mask = active & supported;
114 	}
115 
116 	return rc;
117 }
118 
tpm2_pcr_allocate(struct udevice * dev,u32 algo_mask)119 static int tpm2_pcr_allocate(struct udevice *dev, u32 algo_mask)
120 {
121 	struct tpml_pcr_selection pcr = { 0 };
122 	u32 pcr_len = 0;
123 	int rc;
124 
125 	rc = tpm2_get_pcr_info(dev, &pcr);
126 	if (rc)
127 		return rc;
128 
129 	rc = tpm2_pcr_config_algo(dev, algo_mask, &pcr, &pcr_len);
130 	if (rc)
131 		return rc;
132 
133 	/* Assume no password */
134 	rc = tpm2_send_pcr_allocate(dev, NULL, 0, &pcr, pcr_len);
135 	if (rc)
136 		return rc;
137 
138 	/* Send TPM2_Shutdown, assume mode = TPM2_SU_CLEAR */
139 	return tpm2_startup(dev, false, TPM2_SU_CLEAR);
140 }
141 
tpm2_activate_banks(struct udevice * dev,u32 log_active)142 int tpm2_activate_banks(struct udevice *dev, u32 log_active)
143 {
144 	u32 algo_mask = 0;
145 	int rc;
146 
147 	rc = tpm2_scan_masks(dev, log_active, &algo_mask);
148 	if (rc)
149 		return rc;
150 
151 	if (algo_mask) {
152 		if (!IS_ENABLED(CONFIG_TPM_PCR_ALLOCATE))
153 			return -1;
154 
155 		rc = tpm2_pcr_allocate(dev, algo_mask);
156 		if (rc)
157 			return rc;
158 
159 		log_info("PCR allocate done, shutdown TPM and reboot\n");
160 		do_reset(NULL, 0, 0, NULL);
161 		log_err("reset does not work!\n");
162 		return -1;
163 	}
164 
165 	return 0;
166 }
167 
tpm2_startup(struct udevice * dev,bool bon,enum tpm2_startup_types mode)168 u32 tpm2_startup(struct udevice *dev, bool bon, enum tpm2_startup_types mode)
169 {
170 	int op = bon ? TPM2_CC_STARTUP : TPM2_CC_SHUTDOWN;
171 	const u8 command_v2[12] = {
172 		tpm_u16(TPM2_ST_NO_SESSIONS),
173 		tpm_u32(12),
174 		tpm_u32(op),
175 		tpm_u16(mode),
176 	};
177 	int ret;
178 
179 	/*
180 	 * Note TPM2_Startup command will return RC_SUCCESS the first time,
181 	 * but will return RC_INITIALIZE otherwise.
182 	 */
183 	ret = tpm_sendrecv_command(dev, command_v2, NULL, NULL);
184 	if ((ret && ret != TPM2_RC_INITIALIZE) || !bon)
185 		return ret;
186 
187 	return tpm2_update_active_banks(dev);
188 }
189 
tpm2_self_test(struct udevice * dev,enum tpm2_yes_no full_test)190 u32 tpm2_self_test(struct udevice *dev, enum tpm2_yes_no full_test)
191 {
192 	const u8 command_v2[12] = {
193 		tpm_u16(TPM2_ST_NO_SESSIONS),
194 		tpm_u32(11),
195 		tpm_u32(TPM2_CC_SELF_TEST),
196 		full_test,
197 	};
198 
199 	return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
200 }
201 
tpm2_auto_start(struct udevice * dev)202 u32 tpm2_auto_start(struct udevice *dev)
203 {
204 	u32 rc;
205 
206 	rc = tpm2_self_test(dev, TPMI_YES);
207 
208 	if (rc == TPM2_RC_INITIALIZE) {
209 		rc = tpm2_startup(dev, true, TPM2_SU_CLEAR);
210 		if (rc)
211 			return rc;
212 
213 		rc = tpm2_self_test(dev, TPMI_YES);
214 	}
215 	if (rc)
216 		return rc;
217 
218 	return tpm2_update_active_banks(dev);
219 }
220 
tpm2_clear(struct udevice * dev,u32 handle,const char * pw,const ssize_t pw_sz)221 u32 tpm2_clear(struct udevice *dev, u32 handle, const char *pw,
222 	       const ssize_t pw_sz)
223 {
224 	/* Length of the message header, up to start of password */
225 	uint offset = 27;
226 	u8 command_v2[COMMAND_BUFFER_SIZE] = {
227 		tpm_u16(TPM2_ST_SESSIONS),	/* TAG */
228 		tpm_u32(offset + pw_sz),	/* Length */
229 		tpm_u32(TPM2_CC_CLEAR),		/* Command code */
230 
231 		/* HANDLE */
232 		tpm_u32(handle),		/* TPM resource handle */
233 
234 		/* AUTH_SESSION */
235 		tpm_u32(9 + pw_sz),		/* Authorization size */
236 		tpm_u32(TPM2_RS_PW),		/* Session handle */
237 		tpm_u16(0),			/* Size of <nonce> */
238 						/* <nonce> (if any) */
239 		0,				/* Attributes: Cont/Excl/Rst */
240 		tpm_u16(pw_sz),			/* Size of <hmac/password> */
241 		/* STRING(pw)			   <hmac/password> (if any) */
242 	};
243 	int ret;
244 
245 	/*
246 	 * Fill the command structure starting from the first buffer:
247 	 *     - the password (if any)
248 	 */
249 	ret = pack_byte_string(command_v2, sizeof(command_v2), "s",
250 			       offset, pw, pw_sz);
251 	offset += pw_sz;
252 	if (ret)
253 		return TPM_LIB_ERROR;
254 
255 	return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
256 }
257 
tpm2_nv_define_space(struct udevice * dev,u32 space_index,size_t space_size,u32 nv_attributes,const u8 * nv_policy,size_t nv_policy_size)258 u32 tpm2_nv_define_space(struct udevice *dev, u32 space_index,
259 			 size_t space_size, u32 nv_attributes,
260 			 const u8 *nv_policy, size_t nv_policy_size)
261 {
262 	/*
263 	 * Calculate the offset of the nv_policy piece by adding each of the
264 	 * chunks below.
265 	 */
266 	const int platform_len = sizeof(u32);
267 	const int session_hdr_len = 13;
268 	const int message_len = 14;
269 	uint offset = TPM2_HDR_LEN + platform_len + session_hdr_len +
270 		message_len;
271 	u8 command_v2[COMMAND_BUFFER_SIZE] = {
272 		/* header 10 bytes */
273 		tpm_u16(TPM2_ST_SESSIONS),	/* TAG */
274 		tpm_u32(offset + nv_policy_size + 2),/* Length */
275 		tpm_u32(TPM2_CC_NV_DEFINE_SPACE),/* Command code */
276 
277 		/* handles 4 bytes */
278 		tpm_u32(TPM2_RH_PLATFORM),	/* Primary platform seed */
279 
280 		/* session header 13 bytes */
281 		tpm_u32(9),			/* Header size */
282 		tpm_u32(TPM2_RS_PW),		/* Password authorisation */
283 		tpm_u16(0),			/* nonce_size */
284 		0,				/* session_attrs */
285 		tpm_u16(0),			/* auth_size */
286 
287 		/* message 14 bytes + policy */
288 		tpm_u16(message_len + nv_policy_size),	/* size */
289 		tpm_u32(space_index),
290 		tpm_u16(TPM2_ALG_SHA256),
291 		tpm_u32(nv_attributes),
292 		tpm_u16(nv_policy_size),
293 		/*
294 		 * nv_policy
295 		 * space_size
296 		 */
297 	};
298 	int ret;
299 
300 	/*
301 	 * Fill the command structure starting from the first buffer:
302 	 *     - the password (if any)
303 	 */
304 	ret = pack_byte_string(command_v2, sizeof(command_v2), "sw",
305 			       offset, nv_policy, nv_policy_size,
306 			       offset + nv_policy_size, space_size);
307 	if (ret)
308 		return TPM_LIB_ERROR;
309 
310 	return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
311 }
312 
tpm2_pcr_extend(struct udevice * dev,u32 index,u32 algorithm,const u8 * digest,u32 digest_len)313 u32 tpm2_pcr_extend(struct udevice *dev, u32 index, u32 algorithm,
314 		    const u8 *digest, u32 digest_len)
315 {
316 	/* Length of the message header, up to start of digest */
317 	uint offset = 33;
318 	u8 command_v2[COMMAND_BUFFER_SIZE] = {
319 		tpm_u16(TPM2_ST_SESSIONS),	/* TAG */
320 		tpm_u32(offset + digest_len),	/* Length */
321 		tpm_u32(TPM2_CC_PCR_EXTEND),	/* Command code */
322 
323 		/* HANDLE */
324 		tpm_u32(index),			/* Handle (PCR Index) */
325 
326 		/* AUTH_SESSION */
327 		tpm_u32(9),			/* Authorization size */
328 		tpm_u32(TPM2_RS_PW),		/* Session handle */
329 		tpm_u16(0),			/* Size of <nonce> */
330 						/* <nonce> (if any) */
331 		0,				/* Attributes: Cont/Excl/Rst */
332 		tpm_u16(0),			/* Size of <hmac/password> */
333 						/* <hmac/password> (if any) */
334 
335 		/* hashes */
336 		tpm_u32(1),			/* Count (number of hashes) */
337 		tpm_u16(algorithm),	/* Algorithm of the hash */
338 		/* STRING(digest)		   Digest */
339 	};
340 	int ret;
341 
342 	if (!digest)
343 		return -EINVAL;
344 
345 	if (!tpm2_check_active_banks(dev)) {
346 		log_err("Cannot extend PCRs if all the TPM enabled algorithms are not supported\n");
347 
348 		ret = tpm2_pcr_allocate(dev, 0);
349 		if (ret)
350 			return -EINVAL;
351 	}
352 	/*
353 	 * Fill the command structure starting from the first buffer:
354 	 *     - the digest
355 	 */
356 	ret = pack_byte_string(command_v2, sizeof(command_v2), "s",
357 			       offset, digest, digest_len);
358 	if (ret)
359 		return TPM_LIB_ERROR;
360 
361 	return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
362 }
363 
tpm2_nv_read_value(struct udevice * dev,u32 index,void * data,u32 count)364 u32 tpm2_nv_read_value(struct udevice *dev, u32 index, void *data, u32 count)
365 {
366 	u8 command_v2[COMMAND_BUFFER_SIZE] = {
367 		/* header 10 bytes */
368 		tpm_u16(TPM2_ST_SESSIONS),	/* TAG */
369 		tpm_u32(10 + 8 + 4 + 9 + 4),	/* Length */
370 		tpm_u32(TPM2_CC_NV_READ),	/* Command code */
371 
372 		/* handles 8 bytes */
373 		tpm_u32(TPM2_RH_PLATFORM),	/* Primary platform seed */
374 		tpm_u32(HR_NV_INDEX + index),	/* Password authorisation */
375 
376 		/* AUTH_SESSION */
377 		tpm_u32(9),			/* Authorization size */
378 		tpm_u32(TPM2_RS_PW),		/* Session handle */
379 		tpm_u16(0),			/* Size of <nonce> */
380 						/* <nonce> (if any) */
381 		0,				/* Attributes: Cont/Excl/Rst */
382 		tpm_u16(0),			/* Size of <hmac/password> */
383 						/* <hmac/password> (if any) */
384 
385 		tpm_u16(count),			/* Number of bytes */
386 		tpm_u16(0),			/* Offset */
387 	};
388 	size_t response_len = COMMAND_BUFFER_SIZE;
389 	u8 response[COMMAND_BUFFER_SIZE];
390 	int ret;
391 	u16 tag;
392 	u32 size, code;
393 
394 	ret = tpm_sendrecv_command(dev, command_v2, response, &response_len);
395 	if (ret)
396 		return log_msg_ret("read", ret);
397 	if (unpack_byte_string(response, response_len, "wdds",
398 			       0, &tag, 2, &size, 6, &code,
399 			       16, data, count))
400 		return TPM_LIB_ERROR;
401 
402 	return 0;
403 }
404 
tpm2_nv_write_value(struct udevice * dev,u32 index,const void * data,u32 count)405 u32 tpm2_nv_write_value(struct udevice *dev, u32 index, const void *data,
406 			u32 count)
407 {
408 	struct tpm_chip_priv *priv = dev_get_uclass_priv(dev);
409 	uint offset = 10 + 8 + 4 + 9 + 2;
410 	uint len = offset + count + 2;
411 	/* Use empty password auth if platform hierarchy is disabled */
412 	u32 auth = priv->plat_hier_disabled ? HR_NV_INDEX + index :
413 		TPM2_RH_PLATFORM;
414 	u8 command_v2[COMMAND_BUFFER_SIZE] = {
415 		/* header 10 bytes */
416 		tpm_u16(TPM2_ST_SESSIONS),	/* TAG */
417 		tpm_u32(len),			/* Length */
418 		tpm_u32(TPM2_CC_NV_WRITE),	/* Command code */
419 
420 		/* handles 8 bytes */
421 		tpm_u32(auth),			/* Primary platform seed */
422 		tpm_u32(HR_NV_INDEX + index),	/* Password authorisation */
423 
424 		/* AUTH_SESSION */
425 		tpm_u32(9),			/* Authorization size */
426 		tpm_u32(TPM2_RS_PW),		/* Session handle */
427 		tpm_u16(0),			/* Size of <nonce> */
428 						/* <nonce> (if any) */
429 		0,				/* Attributes: Cont/Excl/Rst */
430 		tpm_u16(0),			/* Size of <hmac/password> */
431 						/* <hmac/password> (if any) */
432 
433 		tpm_u16(count),
434 	};
435 	size_t response_len = COMMAND_BUFFER_SIZE;
436 	u8 response[COMMAND_BUFFER_SIZE];
437 	int ret;
438 
439 	ret = pack_byte_string(command_v2, sizeof(command_v2), "sw",
440 			       offset, data, count,
441 			       offset + count, 0);
442 	if (ret)
443 		return TPM_LIB_ERROR;
444 
445 	return tpm_sendrecv_command(dev, command_v2, response, &response_len);
446 }
447 
tpm2_pcr_read(struct udevice * dev,u32 idx,unsigned int idx_min_sz,u16 algorithm,void * data,u32 digest_len,unsigned int * updates)448 u32 tpm2_pcr_read(struct udevice *dev, u32 idx, unsigned int idx_min_sz,
449 		  u16 algorithm, void *data, u32 digest_len,
450 		  unsigned int *updates)
451 {
452 	u8 idx_array_sz = max(idx_min_sz, DIV_ROUND_UP(idx, 8));
453 	u8 command_v2[COMMAND_BUFFER_SIZE] = {
454 		tpm_u16(TPM2_ST_NO_SESSIONS),	/* TAG */
455 		tpm_u32(17 + idx_array_sz),	/* Length */
456 		tpm_u32(TPM2_CC_PCR_READ),	/* Command code */
457 
458 		/* TPML_PCR_SELECTION */
459 		tpm_u32(1),			/* Number of selections */
460 		tpm_u16(algorithm),		/* Algorithm of the hash */
461 		idx_array_sz,			/* Array size for selection */
462 		/* bitmap(idx)			   Selected PCR bitmap */
463 	};
464 	size_t response_len = COMMAND_BUFFER_SIZE;
465 	u8 response[COMMAND_BUFFER_SIZE];
466 	unsigned int pcr_sel_idx = idx / 8;
467 	u8 pcr_sel_bit = BIT(idx % 8);
468 	unsigned int counter = 0;
469 	int ret;
470 
471 	if (pack_byte_string(command_v2, COMMAND_BUFFER_SIZE, "b",
472 			     17 + pcr_sel_idx, pcr_sel_bit))
473 		return TPM_LIB_ERROR;
474 
475 	ret = tpm_sendrecv_command(dev, command_v2, response, &response_len);
476 	if (ret)
477 		return ret;
478 
479 	if (digest_len > response_len)
480 		return TPM_LIB_ERROR;
481 
482 	if (unpack_byte_string(response, response_len, "ds",
483 			       10, &counter,
484 			       response_len - digest_len, data,
485 			       digest_len))
486 		return TPM_LIB_ERROR;
487 
488 	if (updates)
489 		*updates = counter;
490 
491 	return 0;
492 }
493 
tpm2_get_capability(struct udevice * dev,u32 capability,u32 property,void * buf,size_t prop_count)494 u32 tpm2_get_capability(struct udevice *dev, u32 capability, u32 property,
495 			void *buf, size_t prop_count)
496 {
497 	u8 command_v2[COMMAND_BUFFER_SIZE] = {
498 		tpm_u16(TPM2_ST_NO_SESSIONS),		/* TAG */
499 		tpm_u32(22),				/* Length */
500 		tpm_u32(TPM2_CC_GET_CAPABILITY),	/* Command code */
501 
502 		tpm_u32(capability),			/* Capability */
503 		tpm_u32(property),			/* Property */
504 		tpm_u32(prop_count),			/* Property count */
505 	};
506 	u8 response[COMMAND_BUFFER_SIZE];
507 	size_t response_len = COMMAND_BUFFER_SIZE;
508 	unsigned int properties_off;
509 	int ret;
510 
511 	ret = tpm_sendrecv_command(dev, command_v2, response, &response_len);
512 	if (ret)
513 		return ret;
514 
515 	/*
516 	 * In the response buffer, the properties are located after the:
517 	 * tag (u16), response size (u32), response code (u32),
518 	 * YES/NO flag (u8), TPM_CAP (u32).
519 	 */
520 	properties_off = sizeof(u16) + sizeof(u32) + sizeof(u32) +
521 			 sizeof(u8) + sizeof(u32);
522 	memcpy(buf, &response[properties_off], response_len - properties_off);
523 
524 	return 0;
525 }
526 
tpm2_pcr_config_algo(struct udevice * dev,u32 algo_mask,struct tpml_pcr_selection * pcr,u32 * pcr_len)527 u32 tpm2_pcr_config_algo(struct udevice *dev, u32 algo_mask,
528 			 struct tpml_pcr_selection *pcr, u32 *pcr_len)
529 {
530 	int i;
531 
532 	if (pcr->count > TPM2_NUM_PCR_BANKS)
533 		return TPM_LIB_ERROR;
534 
535 	*pcr_len = sizeof(pcr->count);
536 
537 	for (i = 0; i < pcr->count; i++) {
538 		struct tpms_pcr_selection *sel = &pcr->selection[i];
539 		u8 pad = 0;
540 		int j;
541 
542 		if (sel->size_of_select > TPM2_PCR_SELECT_MAX)
543 			return TPM_LIB_ERROR;
544 
545 		/*
546 		 * Found the algorithm (bank) that matches, and enable all PCR
547 		 * bits.
548 		 * TODO: only select the bits needed
549 		 */
550 		for (j = 0; j < ARRAY_SIZE(hash_algo_list); j++) {
551 			if (hash_algo_list[j].hash_alg != sel->hash)
552 				continue;
553 
554 			if (algo_mask & hash_algo_list[j].hash_mask)
555 				pad = 0xff;
556 		}
557 
558 		for (j = 0; j < sel->size_of_select; j++)
559 			sel->pcr_select[j] = pad;
560 
561 		log_info("set bank[%d] %s %s\n", i,
562 			 tpm2_algorithm_name(sel->hash),
563 			 tpm2_is_active_bank(sel) ? "on" : "off");
564 
565 		*pcr_len += sizeof(sel->hash) + sizeof(sel->size_of_select) +
566 			    sel->size_of_select;
567 	}
568 
569 	return 0;
570 }
571 
tpm2_send_pcr_allocate(struct udevice * dev,const char * pw,const ssize_t pw_sz,struct tpml_pcr_selection * pcr,u32 pcr_len)572 u32 tpm2_send_pcr_allocate(struct udevice *dev, const char *pw,
573 			   const ssize_t pw_sz, struct tpml_pcr_selection *pcr,
574 			   u32 pcr_len)
575 {
576 	/* Length of the message header, up to start of password */
577 	uint offset = 27;
578 	u8 command_v2[COMMAND_BUFFER_SIZE] = {
579 		tpm_u16(TPM2_ST_SESSIONS),   /* TAG */
580 		tpm_u32(offset + pw_sz + pcr_len), /* Length */
581 		tpm_u32(TPM2_CC_PCR_ALLOCATE),  /* Command code */
582 
583 		/* handles 4 bytes */
584 		tpm_u32(TPM2_RH_PLATFORM),	/* Primary platform seed */
585 
586 		/* AUTH_SESSION */
587 		tpm_u32(9 + pw_sz),		/* Authorization size */
588 		tpm_u32(TPM2_RS_PW),		/* Session handle */
589 		tpm_u16(0),			/* Size of <nonce> */
590 						/* <nonce> (if any) */
591 		0,				/* Attributes: Cont/Excl/Rst */
592 		tpm_u16(pw_sz),			/* Size of <hmac/password> */
593 		/* STRING(pw)			   <hmac/password> (if any) */
594 
595 		/* TPML_PCR_SELECTION */
596 	};
597 	u8 response[COMMAND_BUFFER_SIZE];
598 	size_t response_len = COMMAND_BUFFER_SIZE;
599 	u32 i;
600 	int ret;
601 
602 	/*
603 	 * Fill the command structure starting from the first buffer:
604 	 * the password (if any)
605 	 */
606 	if (pack_byte_string(command_v2, sizeof(command_v2), "s", offset, pw,
607 			     pw_sz))
608 		return TPM_LIB_ERROR;
609 
610 	offset += pw_sz;
611 
612 	/* Pack the count field */
613 	if (pack_byte_string(command_v2, sizeof(command_v2), "d", offset, pcr->count))
614 		return TPM_LIB_ERROR;
615 
616 	offset += sizeof(pcr->count);
617 
618 	/* Pack each tpms_pcr_selection */
619 	for (i = 0; i < pcr->count; i++) {
620 		struct tpms_pcr_selection *sel = &pcr->selection[i];
621 
622 		/* Pack hash (16-bit) */
623 		if (pack_byte_string(command_v2, sizeof(command_v2), "w", offset,
624 				     sel->hash))
625 			return TPM_LIB_ERROR;
626 
627 		offset += sizeof(sel->hash);
628 
629 		/* Pack size_of_select (8-bit) */
630 		if (pack_byte_string(command_v2, sizeof(command_v2), "b", offset,
631 				     sel->size_of_select))
632 			return TPM_LIB_ERROR;
633 
634 		offset += sizeof(sel->size_of_select);
635 
636 		/* Pack pcr_select array */
637 		if (pack_byte_string(command_v2, sizeof(command_v2), "s", offset,
638 				     sel->pcr_select, sel->size_of_select))
639 			return TPM_LIB_ERROR;
640 
641 		offset += sel->size_of_select;
642 	}
643 
644 	ret = tpm_sendrecv_command(dev, command_v2, response, &response_len);
645 	if (!ret)
646 		tpm_init(dev);
647 
648 	return ret;
649 }
650 
tpm2_get_num_pcr(struct udevice * dev,u32 * num_pcr)651 static int tpm2_get_num_pcr(struct udevice *dev, u32 *num_pcr)
652 {
653 	u8 response[(sizeof(struct tpms_capability_data) -
654 		offsetof(struct tpms_capability_data, data))];
655 	u32 properties_offset =
656 		offsetof(struct tpml_tagged_tpm_property, tpm_property) +
657 		offsetof(struct tpms_tagged_property, value);
658 	u32 ret;
659 
660 	memset(response, 0, sizeof(response));
661 	ret = tpm2_get_capability(dev, TPM2_CAP_TPM_PROPERTIES,
662 				  TPM2_PT_PCR_COUNT, response, 1);
663 	if (ret)
664 		return ret;
665 
666 	*num_pcr = get_unaligned_be32(response + properties_offset);
667 	if (*num_pcr > TPM2_MAX_PCRS) {
668 		printf("%s: too many pcrs: %u\n", __func__, *num_pcr);
669 		return -E2BIG;
670 	}
671 
672 	return 0;
673 }
674 
tpm2_get_pcr_info(struct udevice * dev,struct tpml_pcr_selection * pcrs)675 int tpm2_get_pcr_info(struct udevice *dev, struct tpml_pcr_selection *pcrs)
676 {
677 	u8 response[(sizeof(struct tpms_capability_data) -
678 		offsetof(struct tpms_capability_data, data))];
679 	u32 num_pcr;
680 	size_t i;
681 	u32 ret;
682 
683 	ret = tpm2_get_capability(dev, TPM2_CAP_PCRS, 0, response, 1);
684 	if (ret)
685 		return ret;
686 
687 	pcrs->count = get_unaligned_be32(response);
688 	/*
689 	 * We only support 4 algorithms for now so check against that
690 	 * instead of TPM2_NUM_PCR_BANKS
691 	 */
692 	if (pcrs->count > 4 || pcrs->count < 1) {
693 		printf("%s: too many pcrs: %u\n", __func__, pcrs->count);
694 		return -EMSGSIZE;
695 	}
696 
697 	ret = tpm2_get_num_pcr(dev, &num_pcr);
698 	if (ret)
699 		return ret;
700 
701 	for (i = 0; i < pcrs->count; i++) {
702 		/*
703 		 * Definition of TPMS_PCR_SELECTION Structure
704 		 * hash: u16
705 		 * size_of_select: u8
706 		 * pcr_select: u8 array
707 		 *
708 		 * The offsets depend on the number of the device PCRs
709 		 * so we have to calculate them based on that
710 		 */
711 		u32 hash_offset = offsetof(struct tpml_pcr_selection, selection) +
712 			i * offsetof(struct tpms_pcr_selection, pcr_select) +
713 			i * ((num_pcr + 7) / 8);
714 		u32 size_select_offset =
715 			hash_offset + offsetof(struct tpms_pcr_selection,
716 					       size_of_select);
717 		u32 pcr_select_offset =
718 			hash_offset + offsetof(struct tpms_pcr_selection,
719 					       pcr_select);
720 
721 		pcrs->selection[i].hash =
722 			get_unaligned_be16(response + hash_offset);
723 		pcrs->selection[i].size_of_select =
724 			__get_unaligned_be(response + size_select_offset);
725 		if (pcrs->selection[i].size_of_select > TPM2_PCR_SELECT_MAX) {
726 			printf("%s: pcrs selection too large: %u\n", __func__,
727 			       pcrs->selection[i].size_of_select);
728 			return -ENOBUFS;
729 		}
730 		/* copy the array of pcr_select */
731 		memcpy(pcrs->selection[i].pcr_select, response + pcr_select_offset,
732 		       pcrs->selection[i].size_of_select);
733 	}
734 
735 	return 0;
736 }
737 
tpm2_dam_reset(struct udevice * dev,const char * pw,const ssize_t pw_sz)738 u32 tpm2_dam_reset(struct udevice *dev, const char *pw, const ssize_t pw_sz)
739 {
740 	u8 command_v2[COMMAND_BUFFER_SIZE] = {
741 		tpm_u16(TPM2_ST_SESSIONS),	/* TAG */
742 		tpm_u32(27 + pw_sz),		/* Length */
743 		tpm_u32(TPM2_CC_DAM_RESET),	/* Command code */
744 
745 		/* HANDLE */
746 		tpm_u32(TPM2_RH_LOCKOUT),	/* TPM resource handle */
747 
748 		/* AUTH_SESSION */
749 		tpm_u32(9 + pw_sz),		/* Authorization size */
750 		tpm_u32(TPM2_RS_PW),		/* Session handle */
751 		tpm_u16(0),			/* Size of <nonce> */
752 						/* <nonce> (if any) */
753 		0,				/* Attributes: Cont/Excl/Rst */
754 		tpm_u16(pw_sz),			/* Size of <hmac/password> */
755 		/* STRING(pw)			   <hmac/password> (if any) */
756 	};
757 	unsigned int offset = 27;
758 	int ret;
759 
760 	/*
761 	 * Fill the command structure starting from the first buffer:
762 	 *     - the password (if any)
763 	 */
764 	ret = pack_byte_string(command_v2, sizeof(command_v2), "s",
765 			       offset, pw, pw_sz);
766 	offset += pw_sz;
767 	if (ret)
768 		return TPM_LIB_ERROR;
769 
770 	return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
771 }
772 
tpm2_dam_parameters(struct udevice * dev,const char * pw,const ssize_t pw_sz,unsigned int max_tries,unsigned int recovery_time,unsigned int lockout_recovery)773 u32 tpm2_dam_parameters(struct udevice *dev, const char *pw,
774 			const ssize_t pw_sz, unsigned int max_tries,
775 			unsigned int recovery_time,
776 			unsigned int lockout_recovery)
777 {
778 	u8 command_v2[COMMAND_BUFFER_SIZE] = {
779 		tpm_u16(TPM2_ST_SESSIONS),	/* TAG */
780 		tpm_u32(27 + pw_sz + 12),	/* Length */
781 		tpm_u32(TPM2_CC_DAM_PARAMETERS), /* Command code */
782 
783 		/* HANDLE */
784 		tpm_u32(TPM2_RH_LOCKOUT),	/* TPM resource handle */
785 
786 		/* AUTH_SESSION */
787 		tpm_u32(9 + pw_sz),		/* Authorization size */
788 		tpm_u32(TPM2_RS_PW),		/* Session handle */
789 		tpm_u16(0),			/* Size of <nonce> */
790 						/* <nonce> (if any) */
791 		0,				/* Attributes: Cont/Excl/Rst */
792 		tpm_u16(pw_sz),			/* Size of <hmac/password> */
793 		/* STRING(pw)			   <hmac/password> (if any) */
794 
795 		/* LOCKOUT PARAMETERS */
796 		/* tpm_u32(max_tries)		   Max tries (0, always lock) */
797 		/* tpm_u32(recovery_time)	   Recovery time (0, no lock) */
798 		/* tpm_u32(lockout_recovery)	   Lockout recovery */
799 	};
800 	unsigned int offset = 27;
801 	int ret;
802 
803 	/*
804 	 * Fill the command structure starting from the first buffer:
805 	 *     - the password (if any)
806 	 *     - max tries
807 	 *     - recovery time
808 	 *     - lockout recovery
809 	 */
810 	ret = pack_byte_string(command_v2, sizeof(command_v2), "sddd",
811 			       offset, pw, pw_sz,
812 			       offset + pw_sz, max_tries,
813 			       offset + pw_sz + 4, recovery_time,
814 			       offset + pw_sz + 8, lockout_recovery);
815 	offset += pw_sz + 12;
816 	if (ret)
817 		return TPM_LIB_ERROR;
818 
819 	return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
820 }
821 
tpm2_change_auth(struct udevice * dev,u32 handle,const char * newpw,const ssize_t newpw_sz,const char * oldpw,const ssize_t oldpw_sz)822 int tpm2_change_auth(struct udevice *dev, u32 handle, const char *newpw,
823 		     const ssize_t newpw_sz, const char *oldpw,
824 		     const ssize_t oldpw_sz)
825 {
826 	unsigned int offset = 27;
827 	u8 command_v2[COMMAND_BUFFER_SIZE] = {
828 		tpm_u16(TPM2_ST_SESSIONS),	/* TAG */
829 		tpm_u32(offset + oldpw_sz + 2 + newpw_sz), /* Length */
830 		tpm_u32(TPM2_CC_HIERCHANGEAUTH), /* Command code */
831 
832 		/* HANDLE */
833 		tpm_u32(handle),		/* TPM resource handle */
834 
835 		/* AUTH_SESSION */
836 		tpm_u32(9 + oldpw_sz),		/* Authorization size */
837 		tpm_u32(TPM2_RS_PW),		/* Session handle */
838 		tpm_u16(0),			/* Size of <nonce> */
839 						/* <nonce> (if any) */
840 		0,				/* Attributes: Cont/Excl/Rst */
841 		tpm_u16(oldpw_sz)		/* Size of <hmac/password> */
842 		/* STRING(oldpw)		   <hmac/password> (if any) */
843 
844 		/* TPM2B_AUTH (TPM2B_DIGEST) */
845 		/* tpm_u16(newpw_sz)		   Digest size, new pw length */
846 		/* STRING(newpw)		   Digest buffer, new pw */
847 	};
848 	int ret;
849 
850 	/*
851 	 * Fill the command structure starting from the first buffer:
852 	 *     - the old password (if any)
853 	 *     - size of the new password
854 	 *     - new password
855 	 */
856 	ret = pack_byte_string(command_v2, sizeof(command_v2), "sws",
857 			       offset, oldpw, oldpw_sz,
858 			       offset + oldpw_sz, newpw_sz,
859 			       offset + oldpw_sz + 2, newpw, newpw_sz);
860 	offset += oldpw_sz + 2 + newpw_sz;
861 	if (ret)
862 		return TPM_LIB_ERROR;
863 
864 	return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
865 }
866 
tpm2_pcr_setauthpolicy(struct udevice * dev,const char * pw,const ssize_t pw_sz,u32 index,const char * key)867 u32 tpm2_pcr_setauthpolicy(struct udevice *dev, const char *pw,
868 			   const ssize_t pw_sz, u32 index, const char *key)
869 {
870 	u8 command_v2[COMMAND_BUFFER_SIZE] = {
871 		tpm_u16(TPM2_ST_SESSIONS),	/* TAG */
872 		tpm_u32(35 + pw_sz + TPM2_DIGEST_LEN), /* Length */
873 		tpm_u32(TPM2_CC_PCR_SETAUTHPOL), /* Command code */
874 
875 		/* HANDLE */
876 		tpm_u32(TPM2_RH_PLATFORM),	/* TPM resource handle */
877 
878 		/* AUTH_SESSION */
879 		tpm_u32(9 + pw_sz),		/* Authorization size */
880 		tpm_u32(TPM2_RS_PW),		/* session handle */
881 		tpm_u16(0),			/* Size of <nonce> */
882 						/* <nonce> (if any) */
883 		0,				/* Attributes: Cont/Excl/Rst */
884 		tpm_u16(pw_sz)			/* Size of <hmac/password> */
885 		/* STRING(pw)			   <hmac/password> (if any) */
886 
887 		/* TPM2B_AUTH (TPM2B_DIGEST) */
888 		/* tpm_u16(TPM2_DIGEST_LEN)	   Digest size length */
889 		/* STRING(key)			   Digest buffer (PCR key) */
890 
891 		/* TPMI_ALG_HASH */
892 		/* tpm_u16(TPM2_ALG_SHA256)   Algorithm of the hash */
893 
894 		/* TPMI_DH_PCR */
895 		/* tpm_u32(index),		   PCR Index */
896 	};
897 	unsigned int offset = 27;
898 	int ret;
899 
900 	/*
901 	 * Fill the command structure starting from the first buffer:
902 	 *     - the password (if any)
903 	 *     - the PCR key length
904 	 *     - the PCR key
905 	 *     - the hash algorithm
906 	 *     - the PCR index
907 	 */
908 	ret = pack_byte_string(command_v2, sizeof(command_v2), "swswd",
909 			       offset, pw, pw_sz,
910 			       offset + pw_sz, TPM2_DIGEST_LEN,
911 			       offset + pw_sz + 2, key, TPM2_DIGEST_LEN,
912 			       offset + pw_sz + 2 + TPM2_DIGEST_LEN,
913 			       TPM2_ALG_SHA256,
914 			       offset + pw_sz + 4 + TPM2_DIGEST_LEN, index);
915 	offset += pw_sz + 2 + TPM2_DIGEST_LEN + 2 + 4;
916 	if (ret)
917 		return TPM_LIB_ERROR;
918 
919 	return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
920 }
921 
tpm2_pcr_setauthvalue(struct udevice * dev,const char * pw,const ssize_t pw_sz,u32 index,const char * key,const ssize_t key_sz)922 u32 tpm2_pcr_setauthvalue(struct udevice *dev, const char *pw,
923 			  const ssize_t pw_sz, u32 index, const char *key,
924 			  const ssize_t key_sz)
925 {
926 	u8 command_v2[COMMAND_BUFFER_SIZE] = {
927 		tpm_u16(TPM2_ST_SESSIONS),	/* TAG */
928 		tpm_u32(33 + pw_sz + TPM2_DIGEST_LEN), /* Length */
929 		tpm_u32(TPM2_CC_PCR_SETAUTHVAL), /* Command code */
930 
931 		/* HANDLE */
932 		tpm_u32(index),			/* Handle (PCR Index) */
933 
934 		/* AUTH_SESSION */
935 		tpm_u32(9 + pw_sz),		/* Authorization size */
936 		tpm_u32(TPM2_RS_PW),		/* session handle */
937 		tpm_u16(0),			/* Size of <nonce> */
938 						/* <nonce> (if any) */
939 		0,				/* Attributes: Cont/Excl/Rst */
940 		tpm_u16(pw_sz),			/* Size of <hmac/password> */
941 		/* STRING(pw)			   <hmac/password> (if any) */
942 
943 		/* TPM2B_DIGEST */
944 		/* tpm_u16(key_sz)		   Key length */
945 		/* STRING(key)			   Key */
946 	};
947 	unsigned int offset = 27;
948 	int ret;
949 
950 	/*
951 	 * Fill the command structure starting from the first buffer:
952 	 *     - the password (if any)
953 	 *     - the number of digests, 1 in our case
954 	 *     - the algorithm, sha256 in our case
955 	 *     - the digest (64 bytes)
956 	 */
957 	ret = pack_byte_string(command_v2, sizeof(command_v2), "sws",
958 			       offset, pw, pw_sz,
959 			       offset + pw_sz, key_sz,
960 			       offset + pw_sz + 2, key, key_sz);
961 	offset += pw_sz + 2 + key_sz;
962 	if (ret)
963 		return TPM_LIB_ERROR;
964 
965 	return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
966 }
967 
tpm2_get_random(struct udevice * dev,void * data,u32 count)968 u32 tpm2_get_random(struct udevice *dev, void *data, u32 count)
969 {
970 	const u8 command_v2[10] = {
971 		tpm_u16(TPM2_ST_NO_SESSIONS),
972 		tpm_u32(12),
973 		tpm_u32(TPM2_CC_GET_RANDOM),
974 	};
975 	u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
976 
977 	const size_t data_size_offset = 10;
978 	const size_t data_offset = 12;
979 	size_t response_length = sizeof(response);
980 	u32 data_size;
981 	u8 *out = data;
982 
983 	while (count > 0) {
984 		u32 this_bytes = min((size_t)count,
985 				     sizeof(response) - data_offset);
986 		u32 err;
987 
988 		if (pack_byte_string(buf, sizeof(buf), "sw",
989 				     0, command_v2, sizeof(command_v2),
990 				     sizeof(command_v2), this_bytes))
991 			return TPM_LIB_ERROR;
992 		err = tpm_sendrecv_command(dev, buf, response,
993 					   &response_length);
994 		if (err)
995 			return err;
996 		if (unpack_byte_string(response, response_length, "w",
997 				       data_size_offset, &data_size))
998 			return TPM_LIB_ERROR;
999 		if (data_size > this_bytes)
1000 			return TPM_LIB_ERROR;
1001 		if (unpack_byte_string(response, response_length, "s",
1002 				       data_offset, out, data_size))
1003 			return TPM_LIB_ERROR;
1004 
1005 		count -= data_size;
1006 		out += data_size;
1007 	}
1008 
1009 	return 0;
1010 }
1011 
tpm2_write_lock(struct udevice * dev,u32 index)1012 u32 tpm2_write_lock(struct udevice *dev, u32 index)
1013 {
1014 	u8 command_v2[COMMAND_BUFFER_SIZE] = {
1015 		/* header 10 bytes */
1016 		tpm_u16(TPM2_ST_SESSIONS),	/* TAG */
1017 		tpm_u32(10 + 8 + 13), /* Length */
1018 		tpm_u32(TPM2_CC_NV_WRITELOCK), /* Command code */
1019 
1020 		/* handles 8 bytes */
1021 		tpm_u32(TPM2_RH_PLATFORM),	/* Primary platform seed */
1022 		tpm_u32(HR_NV_INDEX + index),	/* Password authorisation */
1023 
1024 		/* session header 9 bytes */
1025 		tpm_u32(9),			/* Header size */
1026 		tpm_u32(TPM2_RS_PW),		/* Password authorisation */
1027 		tpm_u16(0),			/* nonce_size */
1028 		0,				/* session_attrs */
1029 		tpm_u16(0),			/* auth_size */
1030 	};
1031 
1032 	return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
1033 }
1034 
tpm2_disable_platform_hierarchy(struct udevice * dev)1035 u32 tpm2_disable_platform_hierarchy(struct udevice *dev)
1036 {
1037 	struct tpm_chip_priv *priv = dev_get_uclass_priv(dev);
1038 	u8 command_v2[COMMAND_BUFFER_SIZE] = {
1039 		/* header 10 bytes */
1040 		tpm_u16(TPM2_ST_SESSIONS),	/* TAG */
1041 		tpm_u32(10 + 4 + 13 + 5),	/* Length */
1042 		tpm_u32(TPM2_CC_HIER_CONTROL),	/* Command code */
1043 
1044 		/* 4 bytes */
1045 		tpm_u32(TPM2_RH_PLATFORM),	/* Primary platform seed */
1046 
1047 		/* session header 9 bytes */
1048 		tpm_u32(9),			/* Header size */
1049 		tpm_u32(TPM2_RS_PW),		/* Password authorisation */
1050 		tpm_u16(0),			/* nonce_size */
1051 		0,				/* session_attrs */
1052 		tpm_u16(0),			/* auth_size */
1053 
1054 		/* payload 5 bytes */
1055 		tpm_u32(TPM2_RH_PLATFORM),	/* Hierarchy to disable */
1056 		0,				/* 0=disable */
1057 	};
1058 	int ret;
1059 
1060 	ret = tpm_sendrecv_command(dev, command_v2, NULL, NULL);
1061 	log_info("ret=%s, %x\n", dev->name, ret);
1062 	if (ret)
1063 		return ret;
1064 
1065 	priv->plat_hier_disabled = true;
1066 
1067 	return 0;
1068 }
1069 
tpm2_submit_command(struct udevice * dev,const u8 * sendbuf,u8 * recvbuf,size_t * recv_size)1070 u32 tpm2_submit_command(struct udevice *dev, const u8 *sendbuf,
1071 			u8 *recvbuf, size_t *recv_size)
1072 {
1073 	return tpm_sendrecv_command(dev, sendbuf, recvbuf, recv_size);
1074 }
1075 
tpm2_report_state(struct udevice * dev,uint vendor_cmd,uint vendor_subcmd,u8 * recvbuf,size_t * recv_size)1076 u32 tpm2_report_state(struct udevice *dev, uint vendor_cmd, uint vendor_subcmd,
1077 		      u8 *recvbuf, size_t *recv_size)
1078 {
1079 	u8 command_v2[COMMAND_BUFFER_SIZE] = {
1080 		/* header 10 bytes */
1081 		tpm_u16(TPM2_ST_NO_SESSIONS),		/* TAG */
1082 		tpm_u32(10 + 2),			/* Length */
1083 		tpm_u32(vendor_cmd),	/* Command code */
1084 
1085 		tpm_u16(vendor_subcmd),
1086 	};
1087 	int ret;
1088 
1089 	ret = tpm_sendrecv_command(dev, command_v2, recvbuf, recv_size);
1090 	log_debug("ret=%s, %x\n", dev->name, ret);
1091 	if (ret)
1092 		return ret;
1093 	if (*recv_size < 12)
1094 		return -ENODATA;
1095 	*recv_size -= 12;
1096 	memmove(recvbuf, recvbuf + 12, *recv_size);
1097 
1098 	return 0;
1099 }
1100 
tpm2_enable_nvcommits(struct udevice * dev,uint vendor_cmd,uint vendor_subcmd)1101 u32 tpm2_enable_nvcommits(struct udevice *dev, uint vendor_cmd,
1102 			  uint vendor_subcmd)
1103 {
1104 	u8 command_v2[COMMAND_BUFFER_SIZE] = {
1105 		/* header 10 bytes */
1106 		tpm_u16(TPM2_ST_NO_SESSIONS),		/* TAG */
1107 		tpm_u32(10 + 2),			/* Length */
1108 		tpm_u32(vendor_cmd),	/* Command code */
1109 
1110 		tpm_u16(vendor_subcmd),
1111 	};
1112 	int ret;
1113 
1114 	ret = tpm_sendrecv_command(dev, command_v2, NULL, NULL);
1115 	log_debug("ret=%s, %x\n", dev->name, ret);
1116 	if (ret)
1117 		return ret;
1118 
1119 	return 0;
1120 }
1121 
tpm2_is_active_bank(struct tpms_pcr_selection * selection)1122 bool tpm2_is_active_bank(struct tpms_pcr_selection *selection)
1123 {
1124 	int i;
1125 
1126 	for (i = 0; i < selection->size_of_select; i++) {
1127 		if (selection->pcr_select[i])
1128 			return true;
1129 	}
1130 
1131 	return false;
1132 }
1133 
tpm2_name_to_algorithm(const char * name)1134 enum tpm2_algorithms tpm2_name_to_algorithm(const char *name)
1135 {
1136 	size_t i;
1137 
1138 	for (i = 0; i < ARRAY_SIZE(hash_algo_list); ++i) {
1139 		if (!strcasecmp(name, hash_algo_list[i].hash_name))
1140 			return hash_algo_list[i].hash_alg;
1141 	}
1142 	printf("%s: unsupported algorithm %s\n", __func__, name);
1143 
1144 	return TPM2_ALG_INVAL;
1145 }
1146 
tpm2_algorithm_name(enum tpm2_algorithms algo)1147 const char *tpm2_algorithm_name(enum tpm2_algorithms algo)
1148 {
1149 	size_t i;
1150 
1151 	for (i = 0; i < ARRAY_SIZE(hash_algo_list); ++i) {
1152 		if (hash_algo_list[i].hash_alg == algo)
1153 			return hash_algo_list[i].hash_name;
1154 	}
1155 
1156 	return "";
1157 }
1158 
tpm2_algorithm_supported(enum tpm2_algorithms algo)1159 bool tpm2_algorithm_supported(enum tpm2_algorithms algo)
1160 {
1161 	size_t i;
1162 
1163 	for (i = 0; i < ARRAY_SIZE(hash_algo_list); ++i) {
1164 		if (hash_algo_list[i].hash_alg == algo)
1165 			return hash_algo_list[i].supported;
1166 	}
1167 
1168 	return false;
1169 }
1170 
tpm2_algorithm_to_len(enum tpm2_algorithms algo)1171 u16 tpm2_algorithm_to_len(enum tpm2_algorithms algo)
1172 {
1173 	size_t i;
1174 
1175 	for (i = 0; i < ARRAY_SIZE(hash_algo_list); ++i) {
1176 		if (hash_algo_list[i].hash_alg == algo)
1177 			return hash_algo_list[i].hash_len;
1178 	}
1179 
1180 	return 0;
1181 }
1182 
tpm2_check_active_banks(struct udevice * dev)1183 bool tpm2_check_active_banks(struct udevice *dev)
1184 {
1185 	struct tpml_pcr_selection pcrs;
1186 	size_t i;
1187 	int rc;
1188 
1189 	rc = tpm2_get_pcr_info(dev, &pcrs);
1190 	if (rc)
1191 		return false;
1192 
1193 	for (i = 0; i < pcrs.count; i++) {
1194 		if (tpm2_is_active_bank(&pcrs.selection[i]) &&
1195 		    !tpm2_algorithm_supported(pcrs.selection[i].hash))
1196 			return false;
1197 	}
1198 
1199 	return true;
1200 }
1201 
tpm2_print_active_banks(struct udevice * dev)1202 void tpm2_print_active_banks(struct udevice *dev)
1203 {
1204 	struct tpml_pcr_selection pcrs;
1205 	size_t i;
1206 	int rc;
1207 
1208 	rc = tpm2_get_pcr_info(dev, &pcrs);
1209 	if (rc) {
1210 		log_err("Can't retrieve active PCRs\n");
1211 		return;
1212 	}
1213 
1214 	for (i = 0; i < pcrs.count; i++) {
1215 		if (tpm2_is_active_bank(&pcrs.selection[i])) {
1216 			const char *str;
1217 
1218 			str = tpm2_algorithm_name(pcrs.selection[i].hash);
1219 			if (str)
1220 				log_info("%s\n", str);
1221 		}
1222 	}
1223 }
1224