xref: /rk3399_ARM-atf/services/std_svc/drtm/drtm_measurements.c (revision 30a60389204f9ec44c890854e62ec1e0506cb9b9)
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  */
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  */
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 
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 
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