/* * Copyright (c) 2022 Arm Limited. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause * * DRTM measurements into TPM PCRs. * * Authors: * Lucian Paul-Trifu * */ #include #include #include #include #include "drtm_main.h" #include "drtm_measurements.h" #include /* Event Log buffer */ static uint8_t drtm_event_log[PLAT_DRTM_EVENT_LOG_MAX_SIZE]; /* * Calculate and write hash of various payloads as per DRTM specification * to Event Log. * * @param[in] data_base Address of data * @param[in] data_size Size of data * @param[in] event_type Type of Event * @param[in] event_name Name of the Event * @return: * 0 = success * < 0 = error */ static int drtm_event_log_measure_and_record(uintptr_t data_base, uint32_t data_size, uint32_t event_type, const char *event_name, unsigned int pcr) { int rc; unsigned char hash_data[CRYPTO_MD_MAX_SIZE]; event_log_metadata_t metadata = {0}; metadata.name = event_name; metadata.pcr = pcr; /* * Measure the payloads requested by D-CRTM and DCE components * Hash algorithm decided by the Event Log driver at build-time */ rc = event_log_measure(data_base, data_size, hash_data); if (rc != 0) { return rc; } /* Record the mesasurement in the EventLog buffer */ event_log_record(hash_data, event_type, &metadata); return 0; } /* * Initialise Event Log global variables, used during the recording * of various payload measurements into the Event Log buffer * * @param[in] event_log_start Base address of Event Log buffer * @param[in] event_log_finish End address of Event Log buffer, * it is a first byte past end of the * buffer */ static void drtm_event_log_init(uint8_t *event_log_start, uint8_t *event_log_finish) { event_log_buf_init(event_log_start, event_log_finish); event_log_write_specid_event(); } enum drtm_retc drtm_take_measurements(const struct_drtm_dl_args *a) { int rc; uintptr_t dlme_img_mapping; uint64_t dlme_img_ep; size_t dlme_img_mapping_bytes; uint8_t drtm_null_data = 0U; uint8_t pcr_schema = DL_ARGS_GET_PCR_SCHEMA(a); const char *drtm_event_arm_sep_data = "ARM_DRTM"; /* Initialise the EventLog driver */ drtm_event_log_init(drtm_event_log, drtm_event_log + sizeof(drtm_event_log)); /** * Measurements extended into PCR-17. * * PCR-17: Measure the DCE image. Extend digest of (char)0 into PCR-17 * since the D-CRTM and the DCE are not separate. */ rc = drtm_event_log_measure_and_record((uintptr_t)&drtm_null_data, sizeof(drtm_null_data), DRTM_EVENT_ARM_DCE, NULL, PCR_17); CHECK_RC(rc, drtm_event_log_measure_and_record(DRTM_EVENT_ARM_DCE)); /* PCR-17: Measure the PCR schema DRTM launch argument. */ rc = drtm_event_log_measure_and_record((uintptr_t)&pcr_schema, sizeof(pcr_schema), DRTM_EVENT_ARM_PCR_SCHEMA, NULL, PCR_17); CHECK_RC(rc, drtm_event_log_measure_and_record(DRTM_EVENT_ARM_PCR_SCHEMA)); /* PCR-17: Measure the enable state of external-debug, and trace. */ /* * TODO: Measure the enable state of external-debug and trace. This should * be returned through a platform-specific hook. */ /* PCR-17: Measure the security lifecycle state. */ /* * TODO: Measure the security lifecycle state. This is an implementation- * defined value, retrieved through an implementation-defined mechanisms. */ /* * PCR-17: Optionally measure the NWd DCE. * It is expected that such subsequent DCE stages are signed and verified. * Whether they are measured in addition to signing is implementation * -defined. * Here the choice is to not measure any NWd DCE, in favour of PCR value * resilience to any NWd DCE updates. */ /* PCR-17: End of DCE measurements. */ rc = drtm_event_log_measure_and_record((uintptr_t)drtm_event_arm_sep_data, strlen(drtm_event_arm_sep_data), DRTM_EVENT_ARM_SEPARATOR, NULL, PCR_17); CHECK_RC(rc, drtm_event_log_measure_and_record(DRTM_EVENT_ARM_SEPARATOR)); /** * Measurements extended into PCR-18. * * PCR-18: Measure the PCR schema DRTM launch argument. */ rc = drtm_event_log_measure_and_record((uintptr_t)&pcr_schema, sizeof(pcr_schema), DRTM_EVENT_ARM_PCR_SCHEMA, NULL, PCR_18); CHECK_RC(rc, drtm_event_log_measure_and_record(DRTM_EVENT_ARM_PCR_SCHEMA)); /* * PCR-18: Measure the public key used to verify DCE image(s) signatures. * Extend digest of (char)0, since we do not expect the NWd DCE to be * present. */ assert(a->dce_nwd_size == 0); rc = drtm_event_log_measure_and_record((uintptr_t)&drtm_null_data, sizeof(drtm_null_data), DRTM_EVENT_ARM_DCE_PUBKEY, NULL, PCR_18); CHECK_RC(rc, drtm_event_log_measure_and_record(DRTM_EVENT_ARM_DCE_PUBKEY)); /* PCR-18: Measure the DLME image. */ dlme_img_mapping_bytes = page_align(a->dlme_img_size, UP); rc = mmap_add_dynamic_region_alloc_va(a->dlme_paddr + a->dlme_img_off, &dlme_img_mapping, dlme_img_mapping_bytes, MT_RO_DATA | MT_NS); if (rc) { WARN("DRTM: %s: mmap_add_dynamic_region() failed rc=%d\n", __func__, rc); return INTERNAL_ERROR; } rc = drtm_event_log_measure_and_record(dlme_img_mapping, a->dlme_img_size, DRTM_EVENT_ARM_DLME, NULL, PCR_18); CHECK_RC(rc, drtm_event_log_measure_and_record(DRTM_EVENT_ARM_DLME)); rc = mmap_remove_dynamic_region(dlme_img_mapping, dlme_img_mapping_bytes); CHECK_RC(rc, mmap_remove_dynamic_region); /* PCR-18: Measure the DLME image entry point. */ dlme_img_ep = DL_ARGS_GET_DLME_ENTRY_POINT(a); drtm_event_log_measure_and_record((uintptr_t)&dlme_img_ep, sizeof(dlme_img_ep), DRTM_EVENT_ARM_DLME_EP, NULL, PCR_18); CHECK_RC(rc, drtm_event_log_measure_and_record(DRTM_EVENT_ARM_DLME_EP)); /* PCR-18: End of DCE measurements. */ rc = drtm_event_log_measure_and_record((uintptr_t)drtm_event_arm_sep_data, strlen(drtm_event_arm_sep_data), DRTM_EVENT_ARM_SEPARATOR, NULL, PCR_18); CHECK_RC(rc, drtm_event_log_measure_and_record(DRTM_EVENT_ARM_SEPARATOR)); /* * If the DCE is unable to log a measurement because there is no available * space in the event log region, the DCE must extend a hash of the value * 0xFF (1 byte in size) into PCR[17] and PCR[18] and enter remediation. */ return SUCCESS; } void drtm_serialise_event_log(uint8_t *dst, size_t *event_log_size_out) { *event_log_size_out = event_log_get_cur_size(drtm_event_log); memcpy(dst, drtm_event_log, *event_log_size_out); }