1 /*
2 * Copyright (c) 2022-2025 Arm Limited. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 * DRTM measurements into TPM PCRs.
7 *
8 * Authors:
9 * Lucian Paul-Trifu <lucian.paultrifu@gmail.com>
10 *
11 */
12 #include <assert.h>
13
14 #include <common/debug.h>
15 #include <drivers/auth/crypto_mod.h>
16 #include <event_measure.h>
17 #include <event_print.h>
18 #include <lib/xlat_tables/xlat_tables_v2.h>
19
20 #include "drtm_main.h"
21 #include "drtm_measurements.h"
22
23 /* Event Log buffer */
24 static uint8_t drtm_event_log[PLAT_DRTM_EVENT_LOG_MAX_SIZE];
25
26 /*
27 * Calculate and write hash of various payloads as per DRTM specification
28 * to Event Log.
29 *
30 * @param[in] data_base Address of data
31 * @param[in] data_size Size of data
32 * @param[in] event_type Type of Event
33 * @param[in] event_name Name of the Event
34 * @return:
35 * 0 = success
36 * < 0 = error
37 */
drtm_event_log_measure_and_record(uintptr_t data_base,uint32_t data_size,uint32_t event_type,const char * event_name,unsigned int pcr)38 static int drtm_event_log_measure_and_record(uintptr_t data_base,
39 uint32_t data_size,
40 uint32_t event_type,
41 const char *event_name,
42 unsigned int pcr)
43 {
44 int rc;
45 unsigned char hash_data[MAX_TPML_BUFFER_SIZE];
46 size_t event_data_size =
47 (event_name != NULL) ? (strlen(event_name) + 1U) : 0U;
48
49 /*
50 * Measure the payloads requested by D-CRTM and DCE components
51 * Hash algorithm decided by the Event Log driver at build-time
52 */
53 rc = event_log_measure(data_base, data_size, hash_data,
54 sizeof(hash_data));
55 if (rc != 0) {
56 return rc;
57 }
58
59 /* Record the measurement in the EventLog buffer */
60 rc = event_log_write_pcr_event2(pcr, event_type,
61 (const tpml_digest_values *)hash_data,
62 (const uint8_t *)event_name,
63 event_data_size);
64 if (rc != 0) {
65 return rc;
66 }
67
68 return 0;
69 }
70
71 /*
72 * Initialise Event Log global variables, used during the recording
73 * of various payload measurements into the Event Log buffer
74 *
75 * @param[in] event_log_start Base address of Event Log buffer
76 * @param[in] event_log_finish End address of Event Log buffer,
77 * it is a first byte past end of the
78 * buffer
79 */
drtm_event_log_init(uint8_t * event_log_start,uint8_t * event_log_finish)80 static void drtm_event_log_init(uint8_t *event_log_start,
81 uint8_t *event_log_finish)
82 {
83 int rc;
84 tpm_alg_id algorithms[] = {
85 TPM_ALG_ID,
86 };
87
88 rc = event_log_init_and_reg(
89 drtm_event_log, drtm_event_log + PLAT_DRTM_EVENT_LOG_MAX_SIZE,
90 0U, crypto_mod_tcg_hash);
91 if (rc < 0) {
92 ERROR("Failed to initialize event log (%d).\n", rc);
93 panic();
94 }
95
96 rc = event_log_write_header(algorithms, ARRAY_SIZE(algorithms), 0, NULL,
97 0);
98 if (rc < 0) {
99 ERROR("Failed to write event log header (%d).\n", rc);
100 panic();
101 }
102 }
103
drtm_take_measurements(const struct_drtm_dl_args * a)104 enum drtm_retc drtm_take_measurements(const struct_drtm_dl_args *a)
105 {
106 int rc;
107 uintptr_t dlme_img_mapping;
108 uint64_t dlme_img_ep;
109 size_t dlme_img_mapping_bytes;
110 uint8_t drtm_null_data = 0U;
111 uint8_t pcr_schema = DL_ARGS_GET_PCR_SCHEMA(a);
112 const char *drtm_event_arm_sep_data = "ARM_DRTM";
113
114 /* Initialise the EventLog driver */
115 drtm_event_log_init(drtm_event_log, drtm_event_log +
116 sizeof(drtm_event_log));
117
118 /**
119 * Measurements extended into PCR-17.
120 *
121 * PCR-17: Measure the DCE image. Extend digest of (char)0 into PCR-17
122 * since the D-CRTM and the DCE are not separate.
123 */
124 rc = drtm_event_log_measure_and_record((uintptr_t)&drtm_null_data,
125 sizeof(drtm_null_data),
126 DRTM_EVENT_ARM_DCE, NULL,
127 PCR_17);
128 CHECK_RC(rc, drtm_event_log_measure_and_record(DRTM_EVENT_ARM_DCE));
129
130 /* PCR-17: Measure the PCR schema DRTM launch argument. */
131 rc = drtm_event_log_measure_and_record((uintptr_t)&pcr_schema,
132 sizeof(pcr_schema),
133 DRTM_EVENT_ARM_PCR_SCHEMA,
134 NULL, PCR_17);
135 CHECK_RC(rc,
136 drtm_event_log_measure_and_record(DRTM_EVENT_ARM_PCR_SCHEMA));
137
138 /* PCR-17: Measure the enable state of external-debug, and trace. */
139 /*
140 * TODO: Measure the enable state of external-debug and trace. This should
141 * be returned through a platform-specific hook.
142 */
143
144 /* PCR-17: Measure the security lifecycle state. */
145 /*
146 * TODO: Measure the security lifecycle state. This is an implementation-
147 * defined value, retrieved through an implementation-defined mechanisms.
148 */
149
150 /*
151 * PCR-17: Optionally measure the NWd DCE.
152 * It is expected that such subsequent DCE stages are signed and verified.
153 * Whether they are measured in addition to signing is implementation
154 * -defined.
155 * Here the choice is to not measure any NWd DCE, in favour of PCR value
156 * resilience to any NWd DCE updates.
157 */
158
159 /* PCR-17: End of DCE measurements. */
160 rc = drtm_event_log_measure_and_record((uintptr_t)drtm_event_arm_sep_data,
161 strlen(drtm_event_arm_sep_data),
162 DRTM_EVENT_ARM_SEPARATOR,
163 drtm_event_arm_sep_data,
164 PCR_17);
165 CHECK_RC(rc, drtm_event_log_measure_and_record(DRTM_EVENT_ARM_SEPARATOR));
166
167 /**
168 * Measurements extended into PCR-18.
169 *
170 * PCR-18: Measure the PCR schema DRTM launch argument.
171 */
172 rc = drtm_event_log_measure_and_record((uintptr_t)&pcr_schema,
173 sizeof(pcr_schema),
174 DRTM_EVENT_ARM_PCR_SCHEMA,
175 NULL, PCR_18);
176 CHECK_RC(rc,
177 drtm_event_log_measure_and_record(DRTM_EVENT_ARM_PCR_SCHEMA));
178
179 /*
180 * PCR-18: Measure the public key used to verify DCE image(s) signatures.
181 * Extend digest of (char)0, since we do not expect the NWd DCE to be
182 * present.
183 */
184 assert(a->dce_nwd_size == 0);
185 rc = drtm_event_log_measure_and_record((uintptr_t)&drtm_null_data,
186 sizeof(drtm_null_data),
187 DRTM_EVENT_ARM_DCE_PUBKEY,
188 NULL, PCR_18);
189 CHECK_RC(rc,
190 drtm_event_log_measure_and_record(DRTM_EVENT_ARM_DCE_PUBKEY));
191
192 /* PCR-18: Measure the DLME image. */
193 dlme_img_mapping_bytes = page_align(a->dlme_img_size, UP);
194 rc = mmap_add_dynamic_region_alloc_va(a->dlme_paddr + a->dlme_img_off,
195 &dlme_img_mapping,
196 dlme_img_mapping_bytes, MT_RO_DATA | MT_NS);
197 if (rc) {
198 WARN("DRTM: %s: mmap_add_dynamic_region() failed rc=%d\n",
199 __func__, rc);
200 return INTERNAL_ERROR;
201 }
202
203 rc = drtm_event_log_measure_and_record(dlme_img_mapping, a->dlme_img_size,
204 DRTM_EVENT_ARM_DLME, NULL,
205 PCR_18);
206 CHECK_RC(rc, drtm_event_log_measure_and_record(DRTM_EVENT_ARM_DLME));
207
208 rc = mmap_remove_dynamic_region(dlme_img_mapping, dlme_img_mapping_bytes);
209 CHECK_RC(rc, mmap_remove_dynamic_region);
210
211 /* PCR-18: Measure the DLME image entry point. */
212 dlme_img_ep = DL_ARGS_GET_DLME_ENTRY_POINT(a);
213 drtm_event_log_measure_and_record((uintptr_t)&(a->dlme_img_ep_off),
214 sizeof(dlme_img_ep),
215 DRTM_EVENT_ARM_DLME_EP, NULL,
216 PCR_18);
217 CHECK_RC(rc, drtm_event_log_measure_and_record(DRTM_EVENT_ARM_DLME_EP));
218
219 /* PCR-18: End of DCE measurements. */
220 rc = drtm_event_log_measure_and_record((uintptr_t)drtm_event_arm_sep_data,
221 strlen(drtm_event_arm_sep_data),
222 DRTM_EVENT_ARM_SEPARATOR,
223 drtm_event_arm_sep_data,
224 PCR_18);
225 CHECK_RC(rc,
226 drtm_event_log_measure_and_record(DRTM_EVENT_ARM_SEPARATOR));
227
228 /* Measure no Action event but not extend it in PCR */
229 CHECK_RC(rc,
230 drtm_event_log_measure_and_record(DRTM_EVENT_ARM_NO_ACTION));
231 /*
232 * If the DCE is unable to log a measurement because there is no available
233 * space in the event log region, the DCE must extend a hash of the value
234 * 0xFF (1 byte in size) into PCR[17] and PCR[18] and enter remediation.
235 */
236
237 return SUCCESS;
238 }
239
drtm_serialise_event_log(uint8_t * dst,size_t * event_log_size_out)240 void drtm_serialise_event_log(uint8_t *dst, size_t *event_log_size_out)
241 {
242 *event_log_size_out = event_log_get_cur_size(drtm_event_log);
243 memcpy(dst, drtm_event_log, *event_log_size_out);
244 }
245