1 // SPDX-License-Identifier: BSD-3-Clause
2 /*
3 * Copyright (c) 2022, Linaro Limited
4 */
5
6 #include <compiler.h>
7 #include <drivers/tpm2_chip.h>
8 #include <initcall.h>
9 #include <io.h>
10 #include <kernel/tcg.h>
11 #include <kernel/tpm.h>
12 #include <malloc.h>
13 #include <string.h>
14 #include <tpm2.h>
15 #include <trace.h>
16
17 static struct tcg_pcr_ops *pcr_provider;
18
tcg_get_pcr_info(uint32_t * selection_mask,uint32_t * active_mask,uint32_t * num_pcr)19 static TEE_Result tcg_get_pcr_info(uint32_t *selection_mask,
20 uint32_t *active_mask, uint32_t *num_pcr)
21 {
22 if (!pcr_provider || !pcr_provider->pcr_info)
23 return TEE_ERROR_GENERIC;
24
25 return pcr_provider->pcr_info(selection_mask, active_mask, num_pcr);
26 }
27
tcg_pcr_extend(uint32_t pcr_index,struct tpml_digest_values * digest_list)28 static TEE_Result tcg_pcr_extend(uint32_t pcr_index,
29 struct tpml_digest_values *digest_list)
30 {
31 uint32_t i = 0;
32
33 if (!pcr_provider || !pcr_provider->pcr_extend)
34 return TEE_ERROR_GENERIC;
35
36 for (i = 0; i < digest_list->count; i++) {
37 uint32_t alg = digest_list->digests[i].hash_alg;
38 uint8_t *digest = (uint8_t *)&digest_list->digests[i].digest;
39
40 if (pcr_provider->pcr_extend(pcr_index, alg, digest,
41 tpm2_get_alg_len(alg))) {
42 EMSG("Failed to extend PCR");
43 return TEE_ERROR_COMMUNICATION;
44 }
45 }
46
47 return TEE_SUCCESS;
48 }
49
tcg_event_final_size(struct tpml_digest_values * digest_list)50 static uint32_t tcg_event_final_size(struct tpml_digest_values *digest_list)
51 {
52 uint32_t len = 0;
53 size_t i = 0;
54
55 len = offsetof(struct tcg_pcr_event2, digests);
56 len += offsetof(struct tpml_digest_values, digests);
57 for (i = 0; i < digest_list->count; i++) {
58 uint16_t hash_alg = digest_list->digests[i].hash_alg;
59
60 len += offsetof(struct tpmt_ha, digest);
61 len += tpm2_get_alg_len(hash_alg);
62 }
63 len += sizeof(uint32_t); /* tcg_pcr_event2 event_size*/
64
65 return len;
66 }
67
68 /*
69 * tcg_parse_event_log_header() - Parse and verify the event log header fields
70 *
71 * @buffer: Pointer to the start of the eventlog
72 * @size: Size of the eventlog
73 * @pos: Return offset of the next event in buffer right
74 * after the event header i.e specID
75 *
76 * Return: status code
77 */
tcg_parse_event_log_header(void * buffer,uint32_t size,uint32_t * pos)78 static TEE_Result tcg_parse_event_log_header(void *buffer, uint32_t size,
79 uint32_t *pos)
80 {
81 struct tcg_pcr_event *event_header = (struct tcg_pcr_event *)buffer;
82 uint32_t i = 0;
83
84 if (size < sizeof(*event_header))
85 return TEE_ERROR_BAD_FORMAT;
86
87 if (get_unaligned_le32(&event_header->pcr_index) != 0 ||
88 get_unaligned_le32(&event_header->event_type) != EV_NO_ACTION)
89 return TEE_ERROR_BAD_FORMAT;
90
91 for (i = 0; i < sizeof(event_header->digest); i++) {
92 if (event_header->digest[i])
93 return TEE_ERROR_BAD_FORMAT;
94 }
95
96 *pos += sizeof(*event_header);
97
98 return TEE_SUCCESS;
99 }
100
101 /*
102 * tcg_parse_specid_event() - Parse and verify the specID Event in the eventlog
103 *
104 * @buffer: Pointer to the start of the eventlog
105 * @log_size: Size of the eventlog
106 * @pos: [in] Offset of specID event in the eventlog buffer
107 * [out] Return offset of the next event in the buffer
108 * after the specID
109 * @digest_list: list of digests in the event
110 *
111 * Return: status code
112 */
tcg_parse_specid_event(void * buffer,uint32_t log_size,uint32_t * pos,struct tpml_digest_values * digest_list)113 static TEE_Result tcg_parse_specid_event(void *buffer, uint32_t log_size,
114 uint32_t *pos,
115 struct tpml_digest_values *digest_list)
116 {
117 struct tcg_efi_spec_id_event *spec_event = NULL;
118 struct tcg_pcr_event *event_header = buffer;
119 uint8_t vendor_sz = 0;
120 uint16_t hash_alg = 0;
121 uint32_t active = 0;
122 uint32_t alg_count = 0;
123 uint32_t i = 0;
124 uint32_t pcr_count = 0;
125 uint32_t spec_active = 0;
126 uint32_t supported = 0;
127 size_t spec_event_size = 0;
128
129 if ((*pos + sizeof(*spec_event)) > log_size)
130 return TEE_ERROR_BAD_FORMAT;
131
132 /* Check specID event data */
133 spec_event = (struct tcg_efi_spec_id_event *)((uintptr_t)buffer + *pos);
134 /* Check for signature */
135 if (memcmp(spec_event->signature, TCG_EFI_SPEC_ID_EVENT_SIGNATURE_03,
136 sizeof(TCG_EFI_SPEC_ID_EVENT_SIGNATURE_03))) {
137 EMSG("specID Event: Signature mismatch");
138 return TEE_ERROR_BAD_FORMAT;
139 }
140
141 if (spec_event->spec_version_minor !=
142 TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MINOR_TPM2 ||
143 spec_event->spec_version_major !=
144 TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MAJOR_TPM2)
145 return TEE_ERROR_BAD_FORMAT;
146
147 if (!spec_event->number_of_algorithms) {
148 EMSG("specID Event: Number of algorithms incorrect");
149 return TEE_ERROR_BAD_FORMAT;
150 }
151
152 alg_count = spec_event->number_of_algorithms;
153
154 if (alg_count > TPM2_NUM_PCR_BANKS)
155 return TEE_ERROR_BAD_FORMAT;
156
157 if (tcg_get_pcr_info(&supported, &active, &pcr_count))
158 return TEE_ERROR_COMMUNICATION;
159
160 digest_list->count = 0;
161 /*
162 * We have to take care that the sequence of algorithms that we record
163 * in digest_list matches the sequence in eventlog.
164 */
165 for (i = 0; i < alg_count; i++) {
166 hash_alg =
167 get_unaligned_le16(&spec_event->digest_sizes[i].algorithm_id);
168
169 if (!(supported & tpm2_alg_to_tcg_mask(hash_alg))) {
170 EMSG("specID Event: Unsupported algorithm");
171 return TEE_ERROR_BAD_FORMAT;
172 }
173 digest_list->digests[digest_list->count++].hash_alg = hash_alg;
174
175 spec_active |= tpm2_alg_to_tcg_mask(hash_alg);
176 }
177
178 /*
179 * TCG specification expects the event log to have hashes for all
180 * active PCR's
181 */
182 if (spec_active != active) {
183 /*
184 * Previous stage bootloader should know all the active PCR's
185 * and use them in the Eventlog.
186 */
187 EMSG("specID Event: All active hash alg not present");
188 return TEE_ERROR_BAD_FORMAT;
189 }
190
191 /*
192 * the size of the spec event and placement of vendor_info_size
193 * depends on supported algorithms
194 */
195 spec_event_size =
196 offsetof(struct tcg_efi_spec_id_event, digest_sizes) +
197 alg_count * sizeof(spec_event->digest_sizes[0]);
198
199 if (*pos + spec_event_size >= log_size)
200 return TEE_ERROR_BAD_FORMAT;
201
202 vendor_sz = *(uint8_t *)((uintptr_t)buffer + *pos + spec_event_size);
203
204 spec_event_size += sizeof(vendor_sz) + vendor_sz;
205 *pos += spec_event_size;
206
207 if (get_unaligned_le32(&event_header->event_size) != spec_event_size) {
208 EMSG("specID event: header event size mismatch");
209 /* Right way to handle this can be to call SetActive PCR's */
210 return TEE_ERROR_BAD_FORMAT;
211 }
212
213 return TEE_SUCCESS;
214 }
215
216 /*
217 * tcg_parse_event() - Parse the event in the eventlog
218 *
219 * @buffer: Pointer to the start of the eventlog
220 * @log_size: Size of the eventlog
221 * @offset: [in] Offset of the event in the eventlog buffer
222 * [out] Return offset of the next event in the buffer
223 * @digest_list: list of digests in the event.
224 * @pcr Index of the PCR in the event
225 *
226 * Return: status code
227 */
tcg_parse_event(void * buffer,uint32_t log_size,uint32_t * offset,struct tpml_digest_values * digest_list,uint32_t * pcr)228 static TEE_Result tcg_parse_event(void *buffer, uint32_t log_size,
229 uint32_t *offset,
230 struct tpml_digest_values *digest_list,
231 uint32_t *pcr)
232 {
233 struct tcg_pcr_event2 *event = NULL;
234 uint32_t count = 0, size = 0, event_size = 0;
235 uint32_t i = 0;
236 size_t pos = 0;
237
238 event_size = tcg_event_final_size(digest_list);
239 if (*offset >= log_size || *offset + event_size > log_size) {
240 EMSG("Event exceeds log size");
241 return TEE_ERROR_BAD_FORMAT;
242 }
243
244 event = (struct tcg_pcr_event2 *)((uintptr_t)buffer + *offset);
245 *pcr = get_unaligned_le32(&event->pcr_index);
246
247 /* get the count */
248 count = get_unaligned_le32(&event->digests.count);
249 if (count != digest_list->count)
250 return TEE_ERROR_BAD_FORMAT;
251
252 /*
253 * Element 'digests' of type tpml_digest_values in struct tcg_pcr_event2
254 * is a list of digests. The count of digests in this list depends on
255 * the number of active PCR banks. Further this list contains elements
256 * of type tpmt_ha whose size depends on the hash algorithm. So, the
257 * position of each of the element in the list (of type tpmt_ha) needs
258 * to be calculated.
259 */
260 pos = offsetof(struct tcg_pcr_event2, digests);
261
262 /* Position of first element of type tpmt_ha in the digest list */
263 pos += offsetof(struct tpml_digest_values, digests);
264
265 for (i = 0; i < digest_list->count; i++) {
266 uint16_t alg = 0;
267 uint16_t hash_alg = digest_list->digests[i].hash_alg;
268 uint8_t *digest = (uint8_t *)&digest_list->digests[i].digest;
269
270 /* Element hash_alg in struct tpmt_ha */
271 alg = get_unaligned_le16((void *)((uintptr_t)event + pos));
272
273 /*
274 * The sequence of algorithm must match that from digest list
275 * in spec ID event.
276 */
277 if (alg != hash_alg)
278 return TEE_ERROR_BAD_FORMAT;
279
280 pos += offsetof(struct tpmt_ha, digest);
281 memcpy(digest, (void *)((uintptr_t)event + pos),
282 tpm2_get_alg_len(hash_alg));
283
284 /* Calculate position of next tpmt_ha element in the event */
285 pos += tpm2_get_alg_len(hash_alg);
286 }
287
288 /* WARNING - Since size of digest lists can vary, the
289 * position of event and event_size elements in tcg_pcr_event2 needs to
290 * be determined dynamically.
291 */
292 size = get_unaligned_le32((void *)((uintptr_t)event + pos));
293 event_size += size;
294 pos += sizeof(uint32_t); /* tcg_pcr_event2 event_size*/
295 pos += size;
296
297 /* make sure the calculated buffer is what we checked against */
298 if (pos != event_size)
299 return TEE_ERROR_BAD_FORMAT;
300
301 if (pos > log_size)
302 return TEE_ERROR_BAD_FORMAT;
303
304 *offset += pos;
305
306 return TEE_SUCCESS;
307 }
308
309 /**
310 * tcg_process_fw_eventlog() - Parse the eventlog and extend the PCR's
311 *
312 * Return: status code
313 */
tcg_process_fw_eventlog(void)314 TEE_Result tcg_process_fw_eventlog(void)
315 {
316 void *buffer = NULL;
317 void *tmp = NULL;
318 uint32_t i = 0, pcr = 0, pos = 0;
319 size_t digest_list_sz = 0;
320 size_t sz = TPM2_EVENT_LOG_SIZE;
321 TEE_Result ret = TEE_SUCCESS;
322 struct tpml_digest_values *digest_list = NULL;
323
324 if (!pcr_provider) {
325 EMSG("No provider available for PCR's");
326 return TEE_ERROR_GENERIC;
327 }
328
329 buffer = malloc(TPM2_EVENT_LOG_SIZE);
330 if (!buffer) {
331 EMSG("Error allocating mem");
332 return TEE_ERROR_OUT_OF_MEMORY;
333 }
334
335 ret = tpm_get_event_log(buffer, &sz);
336 if (ret == TEE_ERROR_SHORT_BUFFER) {
337 tmp = realloc(buffer, sz);
338 if (!tmp)
339 goto out;
340
341 buffer = tmp;
342 /* Try to get the eventlog again */
343 ret = tpm_get_event_log(buffer, &sz);
344 }
345
346 if (ret)
347 goto out;
348
349 pos = 0;
350 /* Parse the eventlog to check for its validity */
351 ret = tcg_parse_event_log_header(buffer, sz, &pos);
352 if (ret) {
353 EMSG("Error parsing event log header");
354 goto out;
355 }
356
357 digest_list_sz = sizeof(struct tpml_digest_values);
358 digest_list = malloc(digest_list_sz);
359 if (!digest_list) {
360 EMSG("Error allocating mem");
361 ret = TEE_ERROR_OUT_OF_MEMORY;
362 goto out;
363 }
364
365 /* Populate the digest_list with digest algs by parsing specid event */
366 ret = tcg_parse_specid_event(buffer, sz, &pos, digest_list);
367 if (ret) {
368 EMSG("Error parsing SPEC ID Event");
369 goto out;
370 }
371
372 while (pos < sz) {
373 ret = tcg_parse_event(buffer, sz, &pos, digest_list,
374 &pcr);
375 if (ret) {
376 EMSG("Error parsing event");
377 goto out;
378 }
379
380 ret = tcg_pcr_extend(pcr, digest_list);
381 if (ret != TEE_SUCCESS) {
382 EMSG("Error in extending PCR");
383 goto out;
384 }
385
386 /* Clear the digest for next event */
387 for (i = 0; i < digest_list->count; i++) {
388 uint16_t hash_alg = digest_list->digests[i].hash_alg;
389 uint8_t *digest =
390 (uint8_t *)&digest_list->digests[i].digest;
391
392 /* Clear the digest in the digest_list */
393 memset(digest, 0, tpm2_get_alg_len(hash_alg));
394 }
395 }
396
397 out:
398 free(digest_list);
399 free(buffer);
400
401 return ret;
402 }
403
404 boot_final(tcg_process_fw_eventlog);
405
register_tcg_pcr_provider(struct tcg_pcr_ops * ops)406 TEE_Result register_tcg_pcr_provider(struct tcg_pcr_ops *ops)
407 {
408 /* Only 1 PCR provider is supported */
409 if (pcr_provider) {
410 EMSG("Provider already registered");
411 return TEE_ERROR_GENERIC;
412 }
413
414 if (!ops)
415 return TEE_ERROR_GENERIC;
416
417 pcr_provider = ops;
418
419 return TEE_SUCCESS;
420 }
421