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