diff options
author | Lucian Paul-Trifu <lucian.paultrifu@gmail.com> | 2022-03-08 15:02:31 +0000 |
---|---|---|
committer | Lucian Paul-Trifu <lucian.paultrifu@gmail.com> | 2022-03-09 18:38:04 +0000 |
commit | 3519afe0f6911cbf49ccb335b2fb6f5154b603e7 (patch) | |
tree | 7f4d303c12ac25ff597e699d397c07bed0a8b47d /services/std_svc/drtm/drtm_res_tcb_hashes.c | |
parent | c158878249f1bd930906ebd744b90d3f2a8265f1 (diff) | |
download | arm-trusted-firmware-3519afe0f6911cbf49ccb335b2fb6f5154b603e7.tar.gz |
Add PoC of Arm DRTM specification version Beta-0topics/arm-drtm-poc
Change-Id: I26e6f2d4b2299edc246f5e8504d5d15b1399f640
Diffstat (limited to 'services/std_svc/drtm/drtm_res_tcb_hashes.c')
-rw-r--r-- | services/std_svc/drtm/drtm_res_tcb_hashes.c | 183 |
1 files changed, 183 insertions, 0 deletions
diff --git a/services/std_svc/drtm/drtm_res_tcb_hashes.c b/services/std_svc/drtm/drtm_res_tcb_hashes.c new file mode 100644 index 000000000..afa49da6f --- /dev/null +++ b/services/std_svc/drtm/drtm_res_tcb_hashes.c @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2021 Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * DRTM resource: TCB hashes. + * + */ +#include <assert.h> +#include <errno.h> +#include <stdbool.h> + +#include <common/runtime_svc.h> +#include <services/drtm_svc_plat.h> + +#include "drtm_measurements.h" /* DRTM_TPM_HASH_ALG and _DSIZE */ +#include "drtm_remediation.h" + + +struct __packed drtm_tcb_hash_v1 { + uint32_t hash_id; + uint8_t hash_val[DRTM_TPM_HASH_ALG_DSIZE]; +}; + +struct __packed drtm_tcb_hash_table_hdr_v1 { + uint16_t version; /* Must be 1. */ + uint16_t num_hashes; + uint32_t hashing_alg; +}; + +/* Version-agnostic types. */ +typedef struct drtm_tcb_hash_table_hdr_v1 struct_drtm_tcb_hash_table_hdr; +typedef struct drtm_tcb_hash_v1 struct_drtm_tcb_hash; + +CASSERT(sizeof(((struct plat_drtm_tcb_hash *)NULL)->hash_val) + == sizeof(((struct_drtm_tcb_hash *)NULL)->hash_val), + bad_plat_drtm_tcb_digest_buffer_size +); + + +static bool tcb_hashes_set_at_runtime; +static bool tcb_hashes_locked; + + +/* Default platform's DRTM TCB hashes enumeration -- no hashes. */ +void plat_enumerate_drtm_tcb_hashes(const struct plat_drtm_tcb_hash **hashes_out, + size_t *hashes_count_out) +{ + *hashes_out = NULL; + *hashes_count_out = 0; +} +#pragma weak plat_enumerate_drtm_tcb_hashes + + +int drtm_tcb_hashes_init(void) +{ + const struct plat_drtm_tcb_hash *init_hashes; + size_t num_init_hashes; + bool init_hashes_invalid = false; + + plat_enumerate_drtm_tcb_hashes(&init_hashes, &num_init_hashes); + if (!init_hashes) { + return 0; + } + + /* Validate the platform DRTM TCB hashes. */ + for (size_t j = 0; j < num_init_hashes; j++) { + const struct plat_drtm_tcb_hash *plat_h = init_hashes + j; + + if (plat_h->hash_bytes != DRTM_TPM_HASH_ALG_DSIZE) { + ERROR("DRTM: invalid hash value size of platform TCB hash" + " at index %ld\n", j); + init_hashes_invalid = true; + } + + + for (size_t i = 0; i < j; i++) { + const struct plat_drtm_tcb_hash *prev_h = init_hashes + i; + + if (plat_h->hash_id.uint32 == prev_h->hash_id.uint32) { + ERROR("DRTM: duplicate hash value ID of platform TCB hash" + " at index %ld (duplicates ID at index %ld)\n", j, i); + init_hashes_invalid = true; + } + } + } + if (init_hashes_invalid) { + return -EINVAL; + } + + return 0; +} + +uint64_t drtm_features_tcb_hashes(void *ctx) +{ + SMC_RET2(ctx, 1, /* TCB hashes supported. */ + (uint64_t)0 << 8 /* MBZ */ + | (uint8_t)0 /* TCB hashes may not be recorded at runtime. */ + ); +} + +void drtm_dl_ensure_tcb_hashes_are_final(void) +{ + if (!tcb_hashes_set_at_runtime || tcb_hashes_locked) { + return; + } + + /* + * Some runtime TCB hashes were set, but the set of TCB hashes hasn't been + * locked / frozen by trusted Normal World firmware. Therefore there is no + * way to guarantee that the set of TCB hashes doesn't contain malicious + * ones from an untrusted Normal World component. + * Refuse to complete the dynamic launch, and reboot the system. + */ + drtm_enter_remediation(0x4, "TCB hashes are still open (missing LOCK call)"); +} + +/* + * enum drtm_retc drtm_set_tcb_hash(uint64_t x1) + * { + * // Sets `tcb_hashes_set_at_runtime' when it succeeds + * } + */ + +/* + * enum drtm_retc drtm_lock_tcb_hashes(void) + * { + * // Sets `tcb_hashes_locked' when it succeeds + * } + */ + +void drtm_serialise_tcb_hashes_table(char *dst, size_t *size_out) +{ + const struct plat_drtm_tcb_hash *init_hashes; + size_t num_init_hashes; + size_t num_hashes_total = 0; + uintptr_t table_cur = (uintptr_t)dst; + + /* Enumerate all available TCB hashes. */ + plat_enumerate_drtm_tcb_hashes(&init_hashes, &num_init_hashes); + num_hashes_total += num_init_hashes; + + if (num_hashes_total == 0) { + goto serialise_tcb_hashes_table_done; + } + + /* Serialise DRTM TCB_HASHES_TABLE header. */ + struct_drtm_tcb_hash_table_hdr hdr; + hdr.version = 1; + hdr.num_hashes = 0; + hdr.num_hashes += num_init_hashes; + hdr.hashing_alg = DRTM_TPM_HASH_ALG; + + if (dst) { + memcpy((char *)table_cur, &hdr, sizeof(hdr)); + } + table_cur += sizeof(hdr); + + /* Serialise platform DRTM TCB hashes. */ + for (const struct plat_drtm_tcb_hash *plat_h = init_hashes; + plat_h < init_hashes + num_init_hashes; + plat_h++) { + struct_drtm_tcb_hash drtm_h; + + drtm_h.hash_id = plat_h->hash_id.uint32; + /* This assertion follows from the init-time check. */ + assert(plat_h->hash_bytes == sizeof(drtm_h.hash_val)); + /* This assertion follows from the one above and the compile-time one.*/ + assert(plat_h->hash_bytes <= sizeof(plat_h->hash_val)); + memcpy(&drtm_h.hash_val, plat_h->hash_val, plat_h->hash_bytes); + + if (dst) { + memcpy((char *)table_cur, &drtm_h, sizeof(drtm_h)); + } + table_cur += sizeof(drtm_h); + } + +serialise_tcb_hashes_table_done: + /* Return the number of bytes serialised. */ + if (size_out) { + *size_out = table_cur - (uintptr_t)dst; + } +} |