1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (c) 2022, Linaro Limited
4  */
5 
6 #include <assert.h>
7 #include <drivers/tpm2_chip.h>
8 #include <io.h>
9 #include <kernel/tcg.h>
10 #include <malloc.h>
11 #include <string.h>
12 #include <tpm2.h>
13 #include <trace.h>
14 
15 static struct tpm2_chip *tpm2_device;
16 
tpm2_chip_send(uint8_t * buf,uint32_t len)17 enum tpm2_result tpm2_chip_send(uint8_t *buf, uint32_t len)
18 {
19 	if (!tpm2_device || !tpm2_device->ops->send)
20 		return TPM2_ERR_NODEV;
21 
22 	return tpm2_device->ops->send(tpm2_device, buf, len);
23 }
24 
tpm2_chip_recv(uint8_t * buf,uint32_t * len,uint32_t cmd_duration)25 enum tpm2_result tpm2_chip_recv(uint8_t *buf, uint32_t *len,
26 				uint32_t cmd_duration)
27 {
28 	if (!tpm2_device || !tpm2_device->ops->recv)
29 		return TPM2_ERR_NODEV;
30 
31 	return tpm2_device->ops->recv(tpm2_device, buf, len, cmd_duration);
32 }
33 
tpm2_chip_get_caps(struct tpm2_caps * capability)34 enum tpm2_result tpm2_chip_get_caps(struct tpm2_caps *capability)
35 {
36 	if (!tpm2_device)
37 		return TPM2_ERR_NODEV;
38 
39 	memcpy(capability, &tpm2_device->capability, sizeof(struct tpm2_caps));
40 
41 	return TPM2_OK;
42 }
43 
tpm2_chip_is_active_bank(uint16_t alg)44 bool tpm2_chip_is_active_bank(uint16_t alg)
45 {
46 	uint32_t alg_mask = tpm2_alg_to_tcg_mask(alg);
47 
48 	if (!tpm2_device)
49 		return false;
50 
51 	if (alg_mask & tpm2_device->capability.active_mask)
52 		return true;
53 
54 	return false;
55 }
56 
57 /* Get value of property (TPM_PT) from capability TPM_CAP_TPM_PROPERTIES */
tpm2_get_tpm_property(uint32_t property,uint32_t * val)58 static enum tpm2_result tpm2_get_tpm_property(uint32_t property, uint32_t *val)
59 {
60 	uint8_t *prop = NULL;
61 	uint32_t prop_len = sizeof(struct tpml_tagged_tpm_property) +
62 			    sizeof(struct tpms_tagged_property);
63 	uint32_t properties_offset =
64 		offsetof(struct tpml_tagged_tpm_property, tpm_property) +
65 		offsetof(struct tpms_tagged_property, value);
66 	enum tpm2_result ret = TPM2_OK;
67 
68 	prop = malloc(prop_len);
69 	if (!prop)
70 		return TPM2_ERR_GENERIC;
71 
72 	ret = tpm2_get_capability(TPM2_CAP_TPM_PROPERTIES, property, 1, prop,
73 				  &prop_len);
74 	if (ret)
75 		goto out;
76 
77 	*val = get_be32(prop + properties_offset);
78 out:
79 	free(prop);
80 	return ret;
81 }
82 
83 /*
84  * Get the following information from TPM and store it in chip's capability
85  * structure.
86  * Number of banks available in TPM
87  * Number of active banks and the corresponding digest algo
88  */
tpm2_get_bank_info(struct tpm2_chip * chip)89 static enum tpm2_result tpm2_get_bank_info(struct tpm2_chip *chip)
90 {
91 	uint32_t i = 0;
92 	uint32_t j = 0;
93 	uint32_t num_active_banks = 0;
94 	uint32_t pcr_cap_len = 0;
95 	uint8_t *tpms_pcr_start = NULL;
96 	enum tpm2_result ret = TPM2_OK;
97 	struct tpm2_caps *caps = &chip->capability;
98 	struct tpml_pcr_selection *pcr_cap = NULL;
99 	struct tpms_pcr_selection *tmp = NULL;
100 
101 	/* Calculate maximum size of tpml_pcr_selection structure */
102 	pcr_cap_len = sizeof(struct tpml_pcr_selection);
103 
104 	pcr_cap = malloc(pcr_cap_len);
105 	if (!pcr_cap)
106 		return TPM2_ERR_GENERIC;
107 
108 	/*
109 	 * Capability category TPM2_CAP_PCRS has no property and on querying
110 	 * TPM returns type TPML_PCR_SELECTION.
111 	 */
112 	ret = tpm2_get_capability(TPM2_CAP_PCRS, 0, 1, pcr_cap, &pcr_cap_len);
113 	if (ret)
114 		goto out;
115 
116 	caps->num_banks = get_be32(&pcr_cap->count);
117 	if (caps->num_banks > TPM2_NUM_PCR_BANKS) {
118 		EMSG("Number of banks more than supported");
119 		ret = TPM2_ERR_GENERIC;
120 		goto out;
121 	}
122 
123 	tpms_pcr_start = (uint8_t *)&pcr_cap->pcr_selections[0];
124 	for (i = 0; i < caps->num_banks; i++) {
125 		tmp = (struct tpms_pcr_selection *)tpms_pcr_start;
126 
127 		if (tmp->size_of_select > TPM2_PCR_SELECT_MAX) {
128 			ret = TPM2_ERR_GENERIC;
129 			goto out;
130 		}
131 
132 		for (j = 0; j < tmp->size_of_select; j++) {
133 			uint16_t alg = get_be16(&tmp->hash);
134 			uint32_t alg_mask = tpm2_alg_to_tcg_mask(alg);
135 
136 			caps->selection_mask |= alg_mask;
137 			if (tmp->pcr_select[j]) {
138 				caps->active_mask |= alg_mask;
139 				num_active_banks++;
140 				break;
141 			}
142 		}
143 
144 		tpms_pcr_start += tmp->size_of_select * sizeof(uint8_t) +
145 				offsetof(struct tpms_pcr_selection, pcr_select);
146 	}
147 	caps->num_active_banks = num_active_banks;
148 
149 	ret = TPM2_OK;
150 out:
151 	free(pcr_cap);
152 	return ret;
153 }
154 
tpm2_populate_capability(struct tpm2_chip * chip)155 static enum tpm2_result tpm2_populate_capability(struct tpm2_chip *chip)
156 {
157 	uint32_t num_pcrs = 0;
158 	uint32_t pcr_select_min = 0;
159 	struct tpm2_caps *caps = &chip->capability;
160 	enum tpm2_result ret = TPM2_OK;
161 
162 	/* Get Bank information from TPM */
163 	ret = tpm2_get_bank_info(chip);
164 	if (ret)
165 		return ret;
166 
167 	/* Get the number of PCR's supported in this TPM */
168 	ret = tpm2_get_tpm_property(TPM2_PT_PCR_COUNT, &num_pcrs);
169 	if (ret)
170 		return ret;
171 
172 	if (num_pcrs > TPM2_MAX_PCRS)
173 		return TPM2_ERR_GENERIC;
174 
175 	caps->num_pcrs = num_pcrs;
176 
177 	/* Get the minimum number of PCR Select octets */
178 	ret = tpm2_get_tpm_property(TPM2_PT_PCR_SELECT_MIN, &pcr_select_min);
179 	if (ret)
180 		return ret;
181 
182 	if (pcr_select_min > TPM2_PCR_SELECT_MAX)
183 		return TPM2_ERR_GENERIC;
184 
185 	caps->pcr_select_min = pcr_select_min;
186 
187 	return TPM2_OK;
188 }
189 
tpm2_dump_capability(struct tpm2_chip * chip)190 static void tpm2_dump_capability(struct tpm2_chip *chip)
191 {
192 	struct tpm2_caps *caps __maybe_unused = &chip->capability;
193 
194 	DMSG("TPM2: No. of banks \t %"PRId32, caps->num_banks);
195 	DMSG("TPM2: No. of active banks \t %"PRId32, caps->num_active_banks);
196 	DMSG("TPM2: No. of PCRs \t %"PRId32, caps->num_pcrs);
197 	DMSG("TPM2: No. of PCR select octets \t %"PRId32, caps->pcr_select_min);
198 }
199 
tpm2_chip_register(struct tpm2_chip * chip)200 enum tpm2_result tpm2_chip_register(struct tpm2_chip *chip)
201 {
202 	enum tpm2_result ret = TPM2_OK;
203 	uint8_t full = 1;
204 
205 	/* Only 1 tpm2 device is supported */
206 	if (tpm2_device)
207 		return TPM2_ERR_GENERIC;
208 
209 	if (!chip || !chip->ops)
210 		return TPM2_ERR_NODEV;
211 
212 	/* Assign timeouts etc based on interface */
213 	ret = chip->ops->init(chip);
214 	if (ret)
215 		return ret;
216 
217 	tpm2_device = chip;
218 
219 	/* Now that interface is initialized do basic init of tpm */
220 	ret = tpm2_startup(TPM2_SU_CLEAR);
221 	if (ret) {
222 		EMSG("TPM2 Startup Failed");
223 		return ret;
224 	}
225 
226 	/* Self test result is informative */
227 	if (tpm2_selftest(full))
228 		EMSG("TPM2 Self Test Failed");
229 
230 	ret = tpm2_populate_capability(chip);
231 	if (!ret)
232 		tpm2_dump_capability(chip);
233 
234 	/* Register TPM2 as TCG provider */
235 	if (tpm2_tcg_register())
236 		return TPM2_ERR_GENERIC;
237 
238 	return ret;
239 }
240 
tpm2_chip_unregister(struct tpm2_chip * chip)241 enum tpm2_result tpm2_chip_unregister(struct tpm2_chip *chip)
242 {
243 	enum tpm2_result ret = TPM2_OK;
244 
245 	ret = chip->ops->end(chip);
246 
247 	tpm2_device = NULL;
248 
249 	return ret;
250 }
251