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