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