| /* |
| * Copyright (c) 2022 Arm Limited. All rights reserved. |
| * |
| * SPDX-License-Identifier: BSD-3-Clause |
| * |
| * DRTM measurements into TPM PCRs. |
| * |
| * Authors: |
| * Lucian Paul-Trifu <lucian.paultrifu@gmail.com> |
| * |
| */ |
| #include <assert.h> |
| |
| #include <common/debug.h> |
| #include <drivers/auth/crypto_mod.h> |
| #include <drivers/measured_boot/event_log/event_log.h> |
| #include "drtm_main.h" |
| #include "drtm_measurements.h" |
| #include <lib/xlat_tables/xlat_tables_v2.h> |
| |
| /* 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); |
| } |