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