1 /*
2 * Copyright (c) 2022-2025, Arm Limited. All rights reserved.
3 * Copyright (c) 2022-2023, Linaro.
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 */
7
8 #include <assert.h>
9 #include <stdint.h>
10
11 #include <plat/common/common_def.h>
12 #include <plat/common/platform.h>
13
14 #include <common/debug.h>
15 #include <common/measured_boot.h>
16 #include <drivers/auth/crypto_mod.h>
17 #include <drivers/measured_boot/metadata.h>
18 #include <event_measure.h>
19 #include <event_print.h>
20 #include <tcg.h>
21 #include <tools_share/tbbr_oid.h>
22
23 #include "../common/qemu_private.h"
24
25 /* Event Log data */
26 static uint8_t event_log[PLAT_EVENT_LOG_MAX_SIZE];
27 static uint64_t event_log_base;
28
29 /* QEMU table with platform specific image IDs, names and PCRs */
30 static const event_log_metadata_t qemu_event_log_metadata[] = {
31 { BL31_IMAGE_ID, MBOOT_BL31_IMAGE_STRING, PCR_0 },
32 { BL32_IMAGE_ID, MBOOT_BL32_IMAGE_STRING, PCR_0 },
33 { BL32_EXTRA1_IMAGE_ID, MBOOT_BL32_EXTRA1_IMAGE_STRING, PCR_0 },
34 { BL32_EXTRA2_IMAGE_ID, MBOOT_BL32_EXTRA2_IMAGE_STRING, PCR_0 },
35 { BL33_IMAGE_ID, MBOOT_BL33_IMAGE_STRING, PCR_0 },
36 { HW_CONFIG_ID, MBOOT_HW_CONFIG_STRING, PCR_0 },
37 { NT_FW_CONFIG_ID, MBOOT_NT_FW_CONFIG_STRING, PCR_0 },
38 { SCP_BL2_IMAGE_ID, MBOOT_SCP_BL2_IMAGE_STRING, PCR_0 },
39 { SOC_FW_CONFIG_ID, MBOOT_SOC_FW_CONFIG_STRING, PCR_0 },
40 { TOS_FW_CONFIG_ID, MBOOT_TOS_FW_CONFIG_STRING, PCR_0 },
41
42 { EVLOG_INVALID_ID, NULL, (unsigned int)(-1) } /* Terminator */
43 };
44
bl2_plat_mboot_init(void)45 void bl2_plat_mboot_init(void)
46 {
47 int rc;
48 tpm_alg_id algos[] = {
49 #ifdef TPM_ALG_ID
50 TPM_ALG_ID,
51 #else
52 /*
53 * TODO: with MEASURED_BOOT=1 several algorithms are now compiled into
54 * Mbed-TLS, we ought to query the backend to figure out what algorithms
55 * to use.
56 */
57 TPM_ALG_SHA256,
58 TPM_ALG_SHA384,
59 TPM_ALG_SHA512,
60 #endif
61 };
62
63 /*
64 * Here we assume that BL1/ROM code doesn't have the driver
65 * to measure the BL2 code which is a common case for
66 * already existing platforms
67 */
68 rc = event_log_init_and_reg(event_log, event_log + sizeof(event_log),
69 0U, crypto_mod_tcg_hash);
70 if (rc < 0) {
71 ERROR("Failed to initialize event log (%d).\n", rc);
72 panic();
73 }
74
75 rc = event_log_write_header(algos, ARRAY_SIZE(algos), 0, NULL, 0);
76 if (rc < 0) {
77 ERROR("Failed to write event log header (%d).\n", rc);
78 panic();
79 }
80
81 /*
82 * TBD - Add code to do self measurement of BL2 code and add an
83 * event for BL2 measurement
84 */
85
86 event_log_base = (uintptr_t)event_log;
87 }
88
bl2_plat_mboot_finish(void)89 void bl2_plat_mboot_finish(void)
90 {
91 int rc;
92
93 /* Event Log address in Non-Secure memory */
94 uintptr_t ns_log_addr;
95
96 /* Event Log filled size */
97 size_t event_log_cur_size;
98
99 event_log_cur_size = event_log_get_cur_size((uint8_t *)event_log_base);
100
101 event_log_dump((uint8_t *)event_log_base, event_log_cur_size);
102
103 #if TRANSFER_LIST
104 if (!plat_handoff_mboot((void *)event_log_base, event_log_cur_size,
105 (void *)(uintptr_t)FW_HANDOFF_BASE))
106 return;
107 #endif
108
109 rc = qemu_set_nt_fw_info(
110 #ifdef SPD_opteed
111 (uintptr_t)event_log_base,
112 #endif
113 event_log_cur_size, &ns_log_addr);
114 if (rc != 0) {
115 ERROR("%s(): Unable to update %s_FW_CONFIG\n",
116 __func__, "NT");
117 /*
118 * It is a non-fatal error because on QEMU secure world software
119 * assumes that a valid event log exists and will use it to
120 * record the measurements into the fTPM or sw-tpm, but the boot
121 * can also happen without TPM on the platform. It's up to
122 * higher layer in boot sequence to decide if this is fatal or
123 * not, e.g. by not providing access to TPM encrypted storage.
124 * Note: In QEMU platform, OP-TEE uses nt_fw_config to get the
125 * secure Event Log buffer address.
126 */
127 WARN("Ignoring TPM errors, continuing without\n");
128 return;
129 }
130
131 /* Copy Event Log to Non-secure memory */
132 (void)memcpy((void *)ns_log_addr, (const void *)event_log_base,
133 event_log_cur_size);
134
135 /* Ensure that the Event Log is visible in Non-secure memory */
136 flush_dcache_range(ns_log_addr, event_log_cur_size);
137
138 #if defined(SPD_tspd) || defined(SPD_spmd)
139 /* Set Event Log data in TOS_FW_CONFIG */
140 rc = qemu_set_tos_fw_info((uintptr_t)event_log_base,
141 event_log_cur_size);
142 if (rc != 0) {
143 ERROR("%s(): Unable to update %s_FW_CONFIG\n",
144 __func__, "TOS");
145 panic();
146 }
147 #endif /* defined(SPD_tspd) || defined(SPD_spmd) */
148
149 }
150
plat_mboot_measure_image(unsigned int image_id,image_info_t * image_data)151 int plat_mboot_measure_image(unsigned int image_id, image_info_t *image_data)
152 {
153 const event_log_metadata_t *metadata_ptr;
154 int err;
155
156 metadata_ptr = mboot_find_event_log_metadata(qemu_event_log_metadata,
157 image_id);
158 if (metadata_ptr == NULL) {
159 ERROR("Unable to find metadata for image %u.\n", image_id);
160 return -1;
161 }
162
163 /* Calculate image hash and record data in Event Log */
164 err = event_log_measure_and_record(metadata_ptr->pcr,
165 image_data->image_base,
166 image_data->image_size,
167 metadata_ptr->name,
168 strlen(metadata_ptr->name) + 1U);
169 if (err != 0) {
170 ERROR("%s%s image id %u (%i)\n",
171 "Failed to ", "record", image_id, err);
172 return err;
173 }
174
175 return 0;
176 }
177
plat_mboot_measure_key(const void * pk_oid,const void * pk_ptr,size_t pk_len)178 int plat_mboot_measure_key(const void *pk_oid, const void *pk_ptr,
179 size_t pk_len)
180 {
181 return 0;
182 }
183