From d72c486b52dc654e4216d41dcc1b0f87bdbdf3e9 Mon Sep 17 00:00:00 2001 From: Lucian Paul-Trifu Date: Wed, 22 Jun 2022 18:45:30 +0100 Subject: [PATCH 01/32] feat(fvp): add platform hooks for DRTM DMA protection Added necessary platform hooks for DRTM DMA protection. These calls will be used by the subsequent DRTM implementation patches. DRTM platform API declarations have been listed down in a separate header file. Signed-off-by: Manish V Badarkhe Signed-off-by: Lucian Paul-Trifu Change-Id: Ib9726d1d3570800241bde702ee7006a64f1739ec --- include/plat/common/plat_drtm.h | 17 ++++++++ include/plat/common/platform.h | 5 ++- plat/arm/board/fvp/fvp_drtm_dma_prot.c | 60 ++++++++++++++++++++++++++ plat/arm/board/fvp/platform.mk | 4 ++ 4 files changed, 85 insertions(+), 1 deletion(-) create mode 100644 include/plat/common/plat_drtm.h create mode 100644 plat/arm/board/fvp/fvp_drtm_dma_prot.c diff --git a/include/plat/common/plat_drtm.h b/include/plat/common/plat_drtm.h new file mode 100644 index 000000000..3c4e3d536 --- /dev/null +++ b/include/plat/common/plat_drtm.h @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLAT_DRTM_H +#define PLAT_DRTM_H + +/* platform-specific DMA protection functions */ +bool plat_has_non_host_platforms(void); +bool plat_has_unmanaged_dma_peripherals(void); +unsigned int plat_get_total_smmus(void); +void plat_enumerate_smmus(const uintptr_t **smmus_out, + size_t *smmu_count_out); + +#endif /* PLAT_DRTM_H */ diff --git a/include/plat/common/platform.h b/include/plat/common/platform.h index da7462467..58e08d4aa 100644 --- a/include/plat/common/platform.h +++ b/include/plat/common/platform.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2022, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2013-2022, Arm Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -20,6 +20,9 @@ #include "plat_trng.h" #endif #include +#if DRTM_SUPPORT +#include "plat_drtm.h" +#endif /* DRTM_SUPPORT */ /******************************************************************************* * Forward declarations diff --git a/plat/arm/board/fvp/fvp_drtm_dma_prot.c b/plat/arm/board/fvp/fvp_drtm_dma_prot.c new file mode 100644 index 000000000..ec9cd7a2e --- /dev/null +++ b/plat/arm/board/fvp/fvp_drtm_dma_prot.c @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include + +#include + +/** + * Array mentioning number of SMMUs supported by FVP + */ +static const uintptr_t fvp_smmus[] = { + PLAT_FVP_SMMUV3_BASE, +}; + +bool plat_has_non_host_platforms(void) +{ + /* FVP base platforms typically have GPU, as per FVP Reference guide */ + return true; +} + +bool plat_has_unmanaged_dma_peripherals(void) +{ + /* + * FVP Reference guide does not show devices that are described as + * DMA-capable but not managed by an SMMU in the FVP documentation. + * However, the SMMU seems to have only been introduced in the RevC + * revision. + */ + return (arm_config.flags & ARM_CONFIG_FVP_HAS_SMMUV3) == 0; +} + +unsigned int plat_get_total_smmus(void) +{ + if ((arm_config.flags & ARM_CONFIG_FVP_HAS_SMMUV3) != 0U) { + return ARRAY_SIZE(fvp_smmus); + } else { + return 0; + } +} + +void plat_enumerate_smmus(const uintptr_t **smmus_out, + size_t *smmu_count_out) +{ + if ((arm_config.flags & ARM_CONFIG_FVP_HAS_SMMUV3) != 0U) { + *smmus_out = fvp_smmus; + *smmu_count_out = ARRAY_SIZE(fvp_smmus); + } else { + *smmus_out = NULL; + *smmu_count_out = 0; + } +} diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk index a20343b35..811b2754b 100644 --- a/plat/arm/board/fvp/platform.mk +++ b/plat/arm/board/fvp/platform.mk @@ -413,6 +413,10 @@ endif endif +ifeq (${DRTM_SUPPORT}, 1) +BL31_SOURCES += plat/arm/board/fvp/fvp_drtm_dma_prot.c +endif + ifeq (${TRUSTED_BOARD_BOOT}, 1) BL1_SOURCES += plat/arm/board/fvp/fvp_trusted_boot.c BL2_SOURCES += plat/arm/board/fvp/fvp_trusted_boot.c From 44df105ff867aeb2aa5d20faa3e8389866099956 Mon Sep 17 00:00:00 2001 From: Lucian Paul-Trifu Date: Wed, 23 Feb 2022 09:34:45 +0000 Subject: [PATCH 02/32] feat(fvp): increase BL31's stack size for DRTM support The stack size of BL31 has been increased to accommodate the introduction of mbedTLS support for DRTM. Signed-off-by: Manish V Badarkhe Signed-off-by: Lucian Paul-Trifu Change-Id: Id0beacf4df553af4ecbe714af20e71604ccfed59 --- plat/arm/board/fvp/include/platform_def.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/plat/arm/board/fvp/include/platform_def.h b/plat/arm/board/fvp/include/platform_def.h index e1bf46d14..c41cb9511 100644 --- a/plat/arm/board/fvp/include/platform_def.h +++ b/plat/arm/board/fvp/include/platform_def.h @@ -247,7 +247,11 @@ #elif defined(IMAGE_BL2U) # define PLATFORM_STACK_SIZE UL(0x400) #elif defined(IMAGE_BL31) +# if DRTM_SUPPORT +# define PLATFORM_STACK_SIZE UL(0x1000) +# else # define PLATFORM_STACK_SIZE UL(0x800) +# endif /* DRTM_SUPPORT */ #elif defined(IMAGE_BL32) # if SPMC_AT_EL3 # define PLATFORM_STACK_SIZE UL(0x1000) From 8a8dace5a5cd3a51d67df3cea86628f29cc96013 Mon Sep 17 00:00:00 2001 From: Manish V Badarkhe Date: Wed, 23 Feb 2022 09:47:59 +0000 Subject: [PATCH 03/32] feat(fvp): increase MAX_XLAT_TABLES entries for DRTM support DRTM implementation maps the DLME data region provided by the DCE-preamble in BL31, hence increased MAX_XLAT_TABLES entries count. Signed-off-by: Manish V Badarkhe Signed-off-by: Lucian Paul-Trifu Change-Id: I5f0ac69e009c4f81d3590fdb1f4c0a7f73c5c99d --- plat/arm/board/fvp/include/platform_def.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plat/arm/board/fvp/include/platform_def.h b/plat/arm/board/fvp/include/platform_def.h index c41cb9511..efe149ab0 100644 --- a/plat/arm/board/fvp/include/platform_def.h +++ b/plat/arm/board/fvp/include/platform_def.h @@ -144,6 +144,8 @@ # else # if ENABLE_RME # define MAX_XLAT_TABLES 8 +# elif DRTM_SUPPORT +# define MAX_XLAT_TABLES 8 # else # define MAX_XLAT_TABLES 7 # endif From 7b224f19f467c11860e6a064846b02353b39575f Mon Sep 17 00:00:00 2001 From: Manish V Badarkhe Date: Mon, 27 Jun 2022 09:21:14 +0100 Subject: [PATCH 04/32] build(changelog): add new scope for DRTM service Added new scope for DRTM service. Signed-off-by: Manish V Badarkhe Change-Id: Idffb178026ef2910102b55e640d5f5bf904e6064 --- changelog.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/changelog.yaml b/changelog.yaml index d2dc992ae..ecb401eed 100644 --- a/changelog.yaml +++ b/changelog.yaml @@ -589,6 +589,9 @@ subsections: - title: SPM MM scope: spm-mm + - title: DRTM + scope: drtm + - title: Libraries subsections: From e62748e3f1f16934f0ef2d5742f3ca0b125eaea2 Mon Sep 17 00:00:00 2001 From: Manish V Badarkhe Date: Wed, 23 Feb 2022 11:26:53 +0000 Subject: [PATCH 05/32] feat(drtm): add standard DRTM service Added a dummy DRTM setup function and also, introduced DRTM SMCs handling as per DRTM spec [1]. Few basic SMCs are handled in this change such as ARM_DRTM_SVC_VERSION and ARM_DRTM_SVC_FEATURES that returns DRTM version and functions ids supported respectively, and others are dummy for now. [1]: https://developer.arm.com/documentation/den0113/latest Signed-off-by: Manish V Badarkhe Signed-off-by: Lucian Paul-Trifu Change-Id: I8c7afe920c78e064cbab2298f59e6837c70ba8ff --- bl31/bl31.mk | 4 + include/lib/smccc.h | 4 +- include/services/drtm_svc.h | 82 +++++++++++++++++ services/std_svc/drtm/drtm_main.c | 148 ++++++++++++++++++++++++++++++ services/std_svc/drtm/drtm_main.h | 24 +++++ services/std_svc/std_svc_setup.c | 14 +++ 6 files changed, 275 insertions(+), 1 deletion(-) create mode 100644 include/services/drtm_svc.h create mode 100644 services/std_svc/drtm/drtm_main.c create mode 100644 services/std_svc/drtm/drtm_main.h diff --git a/bl31/bl31.mk b/bl31/bl31.mk index 3964469eb..878cea59c 100644 --- a/bl31/bl31.mk +++ b/bl31/bl31.mk @@ -147,6 +147,10 @@ ifeq ($(FEATURE_DETECTION),1) BL31_SOURCES += common/feat_detect.c endif +ifeq (${DRTM_SUPPORT},1) +BL31_SOURCES += services/std_svc/drtm/drtm_main.c +endif + BL31_LINKERFILE := bl31/bl31.ld.S # Flag used to indicate if Crash reporting via console should be included diff --git a/include/lib/smccc.h b/include/lib/smccc.h index 1a39f24c7..9940ea90c 100644 --- a/include/lib/smccc.h +++ b/include/lib/smccc.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2021, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2016-2022, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -41,6 +41,8 @@ #define FUNCID_NUM_MASK U(0xffff) #define FUNCID_NUM_WIDTH U(16) +#define FUNCID_MASK U(0xffffffff) + #define GET_SMC_NUM(id) (((id) >> FUNCID_NUM_SHIFT) & \ FUNCID_NUM_MASK) #define GET_SMC_TYPE(id) (((id) >> FUNCID_TYPE_SHIFT) & \ diff --git a/include/services/drtm_svc.h b/include/services/drtm_svc.h new file mode 100644 index 000000000..6845ace9c --- /dev/null +++ b/include/services/drtm_svc.h @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2022 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * DRTM service + * + * Authors: + * Lucian Paul-Trifu + * Brian Nezvadovitz 2021-02-01 + * + */ + +#ifndef ARM_DRTM_SVC_H +#define ARM_DRTM_SVC_H + +/* + * SMC function IDs for DRTM Service + * Upper word bits set: Fast call, SMC64, Standard Secure Svc. Call (OEN = 4) + */ +#define DRTM_FID(func_num) \ + ((SMC_TYPE_FAST << FUNCID_TYPE_SHIFT) | \ + (SMC_64 << FUNCID_CC_SHIFT) | \ + (OEN_STD_START << FUNCID_OEN_SHIFT) | \ + ((func_num) << FUNCID_NUM_SHIFT)) + +#define DRTM_FNUM_SVC_VERSION U(0x110) +#define DRTM_FNUM_SVC_FEATURES U(0x111) +#define DRTM_FNUM_SVC_UNPROTECT_MEM U(0x113) +#define DRTM_FNUM_SVC_DYNAMIC_LAUNCH U(0x114) +#define DRTM_FNUM_SVC_CLOSE_LOCALITY U(0x115) +#define DRTM_FNUM_SVC_GET_ERROR U(0x116) +#define DRTM_FNUM_SVC_SET_ERROR U(0x117) +#define DRTM_FNUM_SVC_SET_TCB_HASH U(0x118) +#define DRTM_FNUM_SVC_LOCK_TCB_HASH U(0x119) + +#define ARM_DRTM_SVC_VERSION DRTM_FID(DRTM_FNUM_SVC_VERSION) +#define ARM_DRTM_SVC_FEATURES DRTM_FID(DRTM_FNUM_SVC_FEATURES) +#define ARM_DRTM_SVC_UNPROTECT_MEM DRTM_FID(DRTM_FNUM_SVC_UNPROTECT_MEM) +#define ARM_DRTM_SVC_DYNAMIC_LAUNCH DRTM_FID(DRTM_FNUM_SVC_DYNAMIC_LAUNCH) +#define ARM_DRTM_SVC_CLOSE_LOCALITY DRTM_FID(DRTM_FNUM_SVC_CLOSE_LOCALITY) +#define ARM_DRTM_SVC_GET_ERROR DRTM_FID(DRTM_FNUM_SVC_GET_ERROR) +#define ARM_DRTM_SVC_SET_ERROR DRTM_FID(DRTM_FNUM_SVC_SET_ERROR) +#define ARM_DRTM_SVC_SET_TCB_HASH DRTM_FID(DRTM_FNUM_SVC_SET_TCB_HASH) +#define ARM_DRTM_SVC_LOCK_TCB_HASH DRTM_FID(DRTM_FNUM_SVC_LOCK_TCB_HASH) + +#define is_drtm_fid(_fid) \ + (((_fid) >= ARM_DRTM_SVC_VERSION) && ((_fid) <= ARM_DRTM_SVC_LOCK_TCB_HASH)) + +/* ARM DRTM Service Calls version numbers */ +#define ARM_DRTM_VERSION_MAJOR U(0) +#define ARM_DRTM_VERSION_MAJOR_SHIFT 16 +#define ARM_DRTM_VERSION_MAJOR_MASK U(0x7FFF) +#define ARM_DRTM_VERSION_MINOR U(1) +#define ARM_DRTM_VERSION_MINOR_SHIFT 0 +#define ARM_DRTM_VERSION_MINOR_MASK U(0xFFFF) + +#define ARM_DRTM_VERSION \ + ((((ARM_DRTM_VERSION_MAJOR) & ARM_DRTM_VERSION_MAJOR_MASK) << \ + ARM_DRTM_VERSION_MAJOR_SHIFT) \ + | (((ARM_DRTM_VERSION_MINOR) & ARM_DRTM_VERSION_MINOR_MASK) << \ + ARM_DRTM_VERSION_MINOR_SHIFT)) + +#define ARM_DRTM_FUNC_SHIFT U(63) +#define ARM_DRTM_FUNC_MASK U(0x1) +#define ARM_DRTM_FUNC_ID U(0x0) +#define ARM_DRTM_FEAT_ID U(0x1) + +/* Initialization routine for the DRTM service */ +int drtm_setup(void); + +/* Handler to be called to handle DRTM SMC calls */ +uint64_t drtm_smc_handler(uint32_t smc_fid, + uint64_t x1, + uint64_t x2, + uint64_t x3, + uint64_t x4, + void *cookie, + void *handle, + uint64_t flags); + +#endif /* ARM_DRTM_SVC_H */ diff --git a/services/std_svc/drtm/drtm_main.c b/services/std_svc/drtm/drtm_main.c new file mode 100644 index 000000000..c7fce5e16 --- /dev/null +++ b/services/std_svc/drtm/drtm_main.c @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2022 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * DRTM service + * + * Authors: + * Lucian Paul-Trifu + * Brian Nezvadovitz 2021-02-01 + */ + +#include + +#include +#include +#include "drtm_main.h" +#include + +int drtm_setup(void) +{ + INFO("DRTM service setup\n"); + + return 0; +} + +uint64_t drtm_smc_handler(uint32_t smc_fid, + uint64_t x1, + uint64_t x2, + uint64_t x3, + uint64_t x4, + void *cookie, + void *handle, + uint64_t flags) +{ + /* Check that the SMC call is from the Normal World. */ + if (!is_caller_non_secure(flags)) { + SMC_RET1(handle, NOT_SUPPORTED); + } + + switch (smc_fid) { + case ARM_DRTM_SVC_VERSION: + INFO("DRTM service handler: version\n"); + /* Return the version of current implementation */ + SMC_RET1(handle, ARM_DRTM_VERSION); + break; /* not reached */ + + case ARM_DRTM_SVC_FEATURES: + if (((x1 >> ARM_DRTM_FUNC_SHIFT) & ARM_DRTM_FUNC_MASK) == + ARM_DRTM_FUNC_ID) { + /* Dispatch function-based queries. */ + switch (x1 & FUNCID_MASK) { + case ARM_DRTM_SVC_VERSION: + SMC_RET1(handle, SUCCESS); + break; /* not reached */ + + case ARM_DRTM_SVC_FEATURES: + SMC_RET1(handle, SUCCESS); + break; /* not reached */ + + case ARM_DRTM_SVC_UNPROTECT_MEM: + SMC_RET1(handle, SUCCESS); + break; /* not reached */ + + case ARM_DRTM_SVC_DYNAMIC_LAUNCH: + SMC_RET1(handle, SUCCESS); + break; /* not reached */ + + case ARM_DRTM_SVC_CLOSE_LOCALITY: + WARN("ARM_DRTM_SVC_CLOSE_LOCALITY feature %s", + "is not supported\n"); + SMC_RET1(handle, NOT_SUPPORTED); + break; /* not reached */ + + case ARM_DRTM_SVC_GET_ERROR: + SMC_RET1(handle, SUCCESS); + break; /* not reached */ + + case ARM_DRTM_SVC_SET_ERROR: + SMC_RET1(handle, SUCCESS); + break; /* not reached */ + + case ARM_DRTM_SVC_SET_TCB_HASH: + WARN("ARM_DRTM_SVC_TCB_HASH feature %s", + "is not supported\n"); + SMC_RET1(handle, NOT_SUPPORTED); + break; /* not reached */ + + case ARM_DRTM_SVC_LOCK_TCB_HASH: + WARN("ARM_DRTM_SVC_LOCK_TCB_HASH feature %s", + "is not supported\n"); + SMC_RET1(handle, NOT_SUPPORTED); + break; /* not reached */ + + default: + ERROR("Unknown DRTM service function\n"); + SMC_RET1(handle, NOT_SUPPORTED); + break; /* not reached */ + } + } + + case ARM_DRTM_SVC_UNPROTECT_MEM: + INFO("DRTM service handler: unprotect mem\n"); + SMC_RET1(handle, SMC_OK); + break; /* not reached */ + + case ARM_DRTM_SVC_DYNAMIC_LAUNCH: + INFO("DRTM service handler: dynamic launch\n"); + SMC_RET1(handle, SMC_OK); + break; /* not reached */ + + case ARM_DRTM_SVC_CLOSE_LOCALITY: + WARN("DRTM service handler: close locality %s\n", + "is not supported"); + SMC_RET1(handle, NOT_SUPPORTED); + break; /* not reached */ + + case ARM_DRTM_SVC_GET_ERROR: + INFO("DRTM service handler: get error\n"); + SMC_RET2(handle, SMC_OK, 0); + break; /* not reached */ + + case ARM_DRTM_SVC_SET_ERROR: + INFO("DRTM service handler: set error\n"); + SMC_RET1(handle, SMC_OK); + break; /* not reached */ + + case ARM_DRTM_SVC_SET_TCB_HASH: + WARN("DRTM service handler: set TCB hash %s\n", + "is not supported"); + SMC_RET1(handle, NOT_SUPPORTED); + break; /* not reached */ + + case ARM_DRTM_SVC_LOCK_TCB_HASH: + WARN("DRTM service handler: lock TCB hash %s\n", + "is not supported"); + SMC_RET1(handle, NOT_SUPPORTED); + break; /* not reached */ + + default: + ERROR("Unknown DRTM service function: 0x%x\n", smc_fid); + SMC_RET1(handle, SMC_UNK); + break; /* not reached */ + } + + /* not reached */ + SMC_RET1(handle, SMC_UNK); +} diff --git a/services/std_svc/drtm/drtm_main.h b/services/std_svc/drtm/drtm_main.h new file mode 100644 index 000000000..39c67cecf --- /dev/null +++ b/services/std_svc/drtm/drtm_main.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2022 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ +#ifndef DRTM_MAIN_H +#define DRTM_MAIN_H + +#include + +#include + +enum drtm_retc { + SUCCESS = SMC_OK, + NOT_SUPPORTED = SMC_UNK, + INVALID_PARAMETERS = -2, + DENIED = -3, + NOT_FOUND = -4, + INTERNAL_ERROR = -5, + MEM_PROTECT_INVALID = -6, +}; + +#endif /* DRTM_MAIN_H */ diff --git a/services/std_svc/std_svc_setup.c b/services/std_svc/std_svc_setup.c index b1e3db977..08d16e21a 100644 --- a/services/std_svc/std_svc_setup.c +++ b/services/std_svc/std_svc_setup.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -75,6 +76,12 @@ static int32_t std_svc_setup(void) trng_setup(); +#if DRTM_SUPPORT + if (drtm_setup() != 0) { + ret = 1; + } +#endif /* DRTM_SUPPORT */ + return ret; } @@ -186,6 +193,13 @@ static uintptr_t std_svc_smc_handler(uint32_t smc_fid, } #endif +#if DRTM_SUPPORT + if (is_drtm_fid(smc_fid)) { + return drtm_smc_handler(smc_fid, x1, x2, x3, x4, cookie, handle, + flags); + } +#endif /* DRTM_SUPPORT */ + switch (smc_fid) { case ARM_STD_SVC_CALL_COUNT: /* From 9e0d2bae7edfefa696c6e833fc54f23b6ce33efd Mon Sep 17 00:00:00 2001 From: Manish V Badarkhe Date: Thu, 22 Sep 2022 21:41:55 +0100 Subject: [PATCH 06/32] build(changelog): add new scope for mbedTLS and Crypto module Added new scope for mbedTLS and Crypto module. Change-Id: I127e7e32f103210e0a1c4c3072afa7249a24a7db Signed-off-by: Manish V Badarkhe --- changelog.yaml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/changelog.yaml b/changelog.yaml index ecb401eed..debbbe748 100644 --- a/changelog.yaml +++ b/changelog.yaml @@ -665,6 +665,12 @@ subsections: - title: CryptoCell-713 scope: cc-713 + - title: Crypto + scope: crypto + + - title: mbedTLS + scope: mbedtls + - title: Generic Clock scope: clk From e43caf3890817e91b3d35b5ae1149a208f1a4016 Mon Sep 17 00:00:00 2001 From: Manish V Badarkhe Date: Fri, 25 Feb 2022 08:29:35 +0000 Subject: [PATCH 07/32] feat(crypto): update crypto module for DRTM support Updated crypto module to include crypto calls necessary for a DRTM supported build. Signed-off-by: Manish V Badarkhe Change-Id: I4f945997824393f46864b7fb7fd380308a025452 --- Makefile | 2 +- drivers/auth/crypto_mod.c | 10 +++++----- include/drivers/auth/crypto_mod.h | 14 +++++++------- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Makefile b/Makefile index 6d15e27c2..bede21a10 100644 --- a/Makefile +++ b/Makefile @@ -730,7 +730,7 @@ ifeq ($(DYN_DISABLE_AUTH), 1) endif endif -ifneq ($(filter 1,${MEASURED_BOOT} ${TRUSTED_BOARD_BOOT}),) +ifneq ($(filter 1,${MEASURED_BOOT} ${TRUSTED_BOARD_BOOT} ${DRTM_SUPPORT}),) CRYPTO_SUPPORT := 1 else CRYPTO_SUPPORT := 0 diff --git a/drivers/auth/crypto_mod.c b/drivers/auth/crypto_mod.c index eada3579a..2028d53d8 100644 --- a/drivers/auth/crypto_mod.c +++ b/drivers/auth/crypto_mod.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2021, Arm Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2022, Arm Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -50,9 +50,9 @@ void crypto_mod_init(void) assert(crypto_lib_desc.verify_signature != NULL); assert(crypto_lib_desc.verify_hash != NULL); #endif /* TRUSTED_BOARD_BOOT */ -#if MEASURED_BOOT +#if MEASURED_BOOT || DRTM_SUPPORT assert(crypto_lib_desc.calc_hash != NULL); -#endif /* MEASURED_BOOT */ +#endif /* MEASURED_BOOT || DRTM_SUPPORT */ /* Initialize the cryptographic library */ crypto_lib_desc.init(); @@ -109,7 +109,7 @@ int crypto_mod_verify_hash(void *data_ptr, unsigned int data_len, digest_info_ptr, digest_info_len); } -#if MEASURED_BOOT +#if MEASURED_BOOT || DRTM_SUPPORT /* * Calculate a hash * @@ -129,7 +129,7 @@ int crypto_mod_calc_hash(enum crypto_md_algo alg, void *data_ptr, return crypto_lib_desc.calc_hash(alg, data_ptr, data_len, output); } -#endif /* MEASURED_BOOT */ +#endif /* MEASURED_BOOT || DRTM_SUPPORT */ /* * Authenticated decryption of data diff --git a/include/drivers/auth/crypto_mod.h b/include/drivers/auth/crypto_mod.h index 73b2b998c..103f08500 100644 --- a/include/drivers/auth/crypto_mod.h +++ b/include/drivers/auth/crypto_mod.h @@ -57,12 +57,12 @@ typedef struct crypto_lib_desc_s { int (*verify_hash)(void *data_ptr, unsigned int data_len, void *digest_info_ptr, unsigned int digest_info_len); -#if MEASURED_BOOT +#if MEASURED_BOOT || DRTM_SUPPORT /* Calculate a hash. Return hash value */ int (*calc_hash)(enum crypto_md_algo md_alg, void *data_ptr, unsigned int data_len, unsigned char output[CRYPTO_MD_MAX_SIZE]); -#endif /* MEASURED_BOOT */ +#endif /* MEASURED_BOOT || DRTM_SUPPORT */ /* * Authenticated decryption. Return one of the @@ -96,13 +96,13 @@ int crypto_mod_auth_decrypt(enum crypto_dec_algo dec_algo, void *data_ptr, unsigned int iv_len, const void *tag, unsigned int tag_len); -#if MEASURED_BOOT +#if MEASURED_BOOT || DRTM_SUPPORT int crypto_mod_calc_hash(enum crypto_md_algo alg, void *data_ptr, unsigned int data_len, unsigned char output[CRYPTO_MD_MAX_SIZE]); -#endif /* MEASURED_BOOT */ +#endif /* MEASURED_BOOT || DRTM_SUPPORT */ -#if MEASURED_BOOT && TRUSTED_BOARD_BOOT +#if (MEASURED_BOOT || DRTM_SUPPORT) && TRUSTED_BOARD_BOOT /* Macro to register a cryptographic library */ #define REGISTER_CRYPTO_LIB(_name, _init, _verify_signature, _verify_hash, \ _calc_hash, _auth_decrypt) \ @@ -124,14 +124,14 @@ int crypto_mod_calc_hash(enum crypto_md_algo alg, void *data_ptr, .verify_hash = _verify_hash, \ .auth_decrypt = _auth_decrypt \ } -#elif MEASURED_BOOT +#elif MEASURED_BOOT || DRTM_SUPPORT #define REGISTER_CRYPTO_LIB(_name, _init, _calc_hash) \ const crypto_lib_desc_t crypto_lib_desc = { \ .name = _name, \ .init = _init, \ .calc_hash = _calc_hash, \ } -#endif /* MEASURED_BOOT && TRUSTED_BOARD_BOOT */ +#endif /* (MEASURED_BOOT || DRTM_SUPPORT) && TRUSTED_BOARD_BOOT */ extern const crypto_lib_desc_t crypto_lib_desc; From c9bd1bacffd9697ec4ebac77e45588cf6c261a3b Mon Sep 17 00:00:00 2001 From: Manish V Badarkhe Date: Fri, 25 Feb 2022 09:06:57 +0000 Subject: [PATCH 08/32] feat(fvp): add crypto support in BL31 DRTM implementation needs crypto support in BL31 to calculate hash of various DRTM components Signed-off-by: Manish V Badarkhe Change-Id: I659ce8e54550946db253d23f150cca8b2fa7b880 --- plat/arm/board/fvp/platform.mk | 3 ++- plat/arm/common/arm_common.mk | 3 ++- plat/arm/common/arm_dyn_cfg.c | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk index 811b2754b..460227612 100644 --- a/plat/arm/board/fvp/platform.mk +++ b/plat/arm/board/fvp/platform.mk @@ -414,7 +414,8 @@ endif endif ifeq (${DRTM_SUPPORT}, 1) -BL31_SOURCES += plat/arm/board/fvp/fvp_drtm_dma_prot.c +BL31_SOURCES += plat/arm/board/fvp/fvp_drtm_dma_prot.c \ + plat/arm/common/arm_dyn_cfg.c endif ifeq (${TRUSTED_BOARD_BOOT}, 1) diff --git a/plat/arm/common/arm_common.mk b/plat/arm/common/arm_common.mk index bd59ec00a..5dda4853b 100644 --- a/plat/arm/common/arm_common.mk +++ b/plat/arm/common/arm_common.mk @@ -419,11 +419,12 @@ ifeq (${MEASURED_BOOT},1) BL2_SOURCES += ${EVENT_LOG_SOURCES} endif -ifneq ($(filter 1,${MEASURED_BOOT} ${TRUSTED_BOARD_BOOT}),) +ifneq ($(filter 1,${MEASURED_BOOT} ${TRUSTED_BOARD_BOOT} ${DRTM_SUPPORT}),) CRYPTO_SOURCES := drivers/auth/crypto_mod.c \ lib/fconf/fconf_tbbr_getter.c BL1_SOURCES += ${CRYPTO_SOURCES} BL2_SOURCES += ${CRYPTO_SOURCES} + BL31_SOURCES += drivers/auth/crypto_mod.c # We expect to locate the *.mk files under the directories specified below ifeq (${ARM_CRYPTOCELL_INTEG},0) diff --git a/plat/arm/common/arm_dyn_cfg.c b/plat/arm/common/arm_dyn_cfg.c index a62693c50..c88621e37 100644 --- a/plat/arm/common/arm_dyn_cfg.c +++ b/plat/arm/common/arm_dyn_cfg.c @@ -45,7 +45,7 @@ int arm_get_mbedtls_heap(void **heap_addr, size_t *heap_size) assert(heap_addr != NULL); assert(heap_size != NULL); -#if defined(IMAGE_BL1) || BL2_AT_EL3 +#if defined(IMAGE_BL1) || BL2_AT_EL3 || defined(IMAGE_BL31) /* If in BL1 or BL2_AT_EL3 define a heap */ static unsigned char heap[TF_MBEDTLS_HEAP_SIZE]; From 8b653909b7e2371c6dcddbeac112b9671c886f34 Mon Sep 17 00:00:00 2001 From: Manish V Badarkhe Date: Fri, 25 Feb 2022 09:11:12 +0000 Subject: [PATCH 09/32] feat(mbedtls): update mbedTLS driver for DRTM support Updated mbedTLS driver to include mbedTLS functions necessary for a DRTM supported build. Signed-off-by: Manish V Badarkhe Change-Id: If0120374a971519cf84f93e0c59e1a320a72cd97 --- bl31/bl31.mk | 3 ++- drivers/auth/mbedtls/mbedtls_crypto.c | 14 +++++++------- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/bl31/bl31.mk b/bl31/bl31.mk index 878cea59c..3e665c584 100644 --- a/bl31/bl31.mk +++ b/bl31/bl31.mk @@ -148,7 +148,8 @@ BL31_SOURCES += common/feat_detect.c endif ifeq (${DRTM_SUPPORT},1) -BL31_SOURCES += services/std_svc/drtm/drtm_main.c +BL31_SOURCES += services/std_svc/drtm/drtm_main.c \ + ${MBEDTLS_SOURCES} endif BL31_LINKERFILE := bl31/bl31.ld.S diff --git a/drivers/auth/mbedtls/mbedtls_crypto.c b/drivers/auth/mbedtls/mbedtls_crypto.c index 0901d045a..e83225c32 100644 --- a/drivers/auth/mbedtls/mbedtls_crypto.c +++ b/drivers/auth/mbedtls/mbedtls_crypto.c @@ -24,7 +24,7 @@ #define LIB_NAME "mbed TLS" -#if MEASURED_BOOT +#if MEASURED_BOOT || DRTM_SUPPORT /* * CRYPTO_MD_MAX_SIZE value is as per current stronger algorithm available * so make sure that mbed TLS MD maximum size must be lesser than this. @@ -32,7 +32,7 @@ CASSERT(CRYPTO_MD_MAX_SIZE >= MBEDTLS_MD_MAX_SIZE, assert_mbedtls_md_size_overflow); -#endif /* MEASURED_BOOT */ +#endif /* MEASURED_BOOT || DRTM_SUPPORT */ /* * AlgorithmIdentifier ::= SEQUENCE { @@ -221,7 +221,7 @@ static int verify_hash(void *data_ptr, unsigned int data_len, } #endif /* TRUSTED_BOARD_BOOT */ -#if MEASURED_BOOT +#if MEASURED_BOOT || DRTM_SUPPORT /* * Map a generic crypto message digest algorithm to the corresponding macro used * by Mbed TLS. @@ -264,7 +264,7 @@ static int calc_hash(enum crypto_md_algo md_algo, void *data_ptr, */ return mbedtls_md(md_info, data_ptr, data_len, output); } -#endif /* MEASURED_BOOT */ +#endif /* MEASURED_BOOT || DRTM_SUPPORT */ #if TF_MBEDTLS_USE_AES_GCM /* @@ -368,7 +368,7 @@ static int auth_decrypt(enum crypto_dec_algo dec_algo, void *data_ptr, /* * Register crypto library descriptor */ -#if MEASURED_BOOT && TRUSTED_BOARD_BOOT +#if (MEASURED_BOOT || DRTM_SUPPORT) && TRUSTED_BOARD_BOOT #if TF_MBEDTLS_USE_AES_GCM REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, calc_hash, auth_decrypt); @@ -383,6 +383,6 @@ REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, #else REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, NULL); #endif -#elif MEASURED_BOOT +#elif MEASURED_BOOT || DRTM_SUPPORT REGISTER_CRYPTO_LIB(LIB_NAME, init, calc_hash); -#endif /* MEASURED_BOOT && TRUSTED_BOARD_BOOT */ +#endif /* (MEASURED_BOOT || DRTM_SUPPORT) && TRUSTED_BOARD_BOOT */ From 2bf4f27f58ae510d428e3b55f020691a54bcba6f Mon Sep 17 00:00:00 2001 From: Manish V Badarkhe Date: Mon, 20 Jun 2022 15:32:38 +0100 Subject: [PATCH 10/32] refactor(crypto): change CRYPTO_SUPPORT flag to numeric Updated CRYPTO_SUPPORT flag to numeric to provide below supports - 1. CRYPTO_SUPPORT = 1 -> Authentication verification only 2. CRYPTO_SUPPORT = 2 -> Hash calculation only 3. CRYPTO_SUPPORT = 3 -> Authentication verification and hash calculation Change-Id: Ib34f31457a6c87d2356d736ad2d048dc787da56f Signed-off-by: Manish V Badarkhe --- Makefile | 14 ++++++++++-- drivers/auth/crypto_mod.c | 23 ++++++++++++++----- drivers/auth/mbedtls/mbedtls_crypto.c | 26 +++++++++++++-------- include/drivers/auth/crypto_mod.h | 33 ++++++++++++++++++++------- 4 files changed, 70 insertions(+), 26 deletions(-) diff --git a/Makefile b/Makefile index bede21a10..1edf3b80a 100644 --- a/Makefile +++ b/Makefile @@ -730,7 +730,17 @@ ifeq ($(DYN_DISABLE_AUTH), 1) endif endif -ifneq ($(filter 1,${MEASURED_BOOT} ${TRUSTED_BOARD_BOOT} ${DRTM_SUPPORT}),) +ifeq ($(MEASURED_BOOT)-$(TRUSTED_BOARD_BOOT),1-1) +# Support authentication verification and hash calculation + CRYPTO_SUPPORT := 3 +else ifeq ($(DRTM_SUPPORT)-$(TRUSTED_BOARD_BOOT),1-1) +# Support authentication verification and hash calculation + CRYPTO_SUPPORT := 3 +else ifneq ($(filter 1,${MEASURED_BOOT} ${DRTM_SUPPORT}),) +# Support hash calculation only + CRYPTO_SUPPORT := 2 +else ifeq (${TRUSTED_BOARD_BOOT},1) +# Support authentication verification only CRYPTO_SUPPORT := 1 else CRYPTO_SUPPORT := 0 @@ -1035,7 +1045,6 @@ $(eval $(call assert_booleans,\ SPMC_AT_EL3 \ SPMD_SPM_AT_SEL2 \ TRUSTED_BOARD_BOOT \ - CRYPTO_SUPPORT \ USE_COHERENT_MEM \ USE_DEBUGFS \ ARM_IO_IN_DTB \ @@ -1070,6 +1079,7 @@ $(eval $(call assert_numerics,\ CTX_INCLUDE_PAUTH_REGS \ CTX_INCLUDE_MTE_REGS \ CTX_INCLUDE_NEVE_REGS \ + CRYPTO_SUPPORT \ ENABLE_BRBE_FOR_NS \ ENABLE_TRBE_FOR_NS \ ENABLE_BTI \ diff --git a/drivers/auth/crypto_mod.c b/drivers/auth/crypto_mod.c index 2028d53d8..fa1adb4f7 100644 --- a/drivers/auth/crypto_mod.c +++ b/drivers/auth/crypto_mod.c @@ -46,19 +46,26 @@ void crypto_mod_init(void) { assert(crypto_lib_desc.name != NULL); assert(crypto_lib_desc.init != NULL); -#if TRUSTED_BOARD_BOOT +#if CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_ONLY || \ +CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC assert(crypto_lib_desc.verify_signature != NULL); assert(crypto_lib_desc.verify_hash != NULL); -#endif /* TRUSTED_BOARD_BOOT */ -#if MEASURED_BOOT || DRTM_SUPPORT +#endif /* CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_ONLY || \ + CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC */ + +#if CRYPTO_SUPPORT == CRYPTO_HASH_CALC_ONLY || \ +CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC assert(crypto_lib_desc.calc_hash != NULL); -#endif /* MEASURED_BOOT || DRTM_SUPPORT */ +#endif /* CRYPTO_SUPPORT == CRYPTO_HASH_CALC_ONLY || \ + CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC */ /* Initialize the cryptographic library */ crypto_lib_desc.init(); INFO("Using crypto library '%s'\n", crypto_lib_desc.name); } +#if CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_ONLY || \ +CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC /* * Function to verify a digital signature * @@ -108,8 +115,11 @@ int crypto_mod_verify_hash(void *data_ptr, unsigned int data_len, return crypto_lib_desc.verify_hash(data_ptr, data_len, digest_info_ptr, digest_info_len); } +#endif /* CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_ONLY || \ + CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC */ -#if MEASURED_BOOT || DRTM_SUPPORT +#if CRYPTO_SUPPORT == CRYPTO_HASH_CALC_ONLY || \ +CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC /* * Calculate a hash * @@ -129,7 +139,8 @@ int crypto_mod_calc_hash(enum crypto_md_algo alg, void *data_ptr, return crypto_lib_desc.calc_hash(alg, data_ptr, data_len, output); } -#endif /* MEASURED_BOOT || DRTM_SUPPORT */ +#endif /* CRYPTO_SUPPORT == CRYPTO_HASH_CALC_ONLY || \ + CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC */ /* * Authenticated decryption of data diff --git a/drivers/auth/mbedtls/mbedtls_crypto.c b/drivers/auth/mbedtls/mbedtls_crypto.c index e83225c32..d231179f5 100644 --- a/drivers/auth/mbedtls/mbedtls_crypto.c +++ b/drivers/auth/mbedtls/mbedtls_crypto.c @@ -24,7 +24,8 @@ #define LIB_NAME "mbed TLS" -#if MEASURED_BOOT || DRTM_SUPPORT +#if CRYPTO_SUPPORT == CRYPTO_HASH_CALC_ONLY || \ +CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC /* * CRYPTO_MD_MAX_SIZE value is as per current stronger algorithm available * so make sure that mbed TLS MD maximum size must be lesser than this. @@ -32,7 +33,8 @@ CASSERT(CRYPTO_MD_MAX_SIZE >= MBEDTLS_MD_MAX_SIZE, assert_mbedtls_md_size_overflow); -#endif /* MEASURED_BOOT || DRTM_SUPPORT */ +#endif /* CRYPTO_SUPPORT == CRYPTO_HASH_CALC_ONLY || \ + CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC */ /* * AlgorithmIdentifier ::= SEQUENCE { @@ -60,7 +62,8 @@ static void init(void) mbedtls_init(); } -#if TRUSTED_BOARD_BOOT +#if CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_ONLY || \ +CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC /* * Verify a signature. * @@ -219,9 +222,11 @@ static int verify_hash(void *data_ptr, unsigned int data_len, return CRYPTO_SUCCESS; } -#endif /* TRUSTED_BOARD_BOOT */ +#endif /* CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_ONLY || \ + CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC */ -#if MEASURED_BOOT || DRTM_SUPPORT +#if CRYPTO_SUPPORT == CRYPTO_HASH_CALC_ONLY || \ +CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC /* * Map a generic crypto message digest algorithm to the corresponding macro used * by Mbed TLS. @@ -264,7 +269,8 @@ static int calc_hash(enum crypto_md_algo md_algo, void *data_ptr, */ return mbedtls_md(md_info, data_ptr, data_len, output); } -#endif /* MEASURED_BOOT || DRTM_SUPPORT */ +#endif /* CRYPTO_SUPPORT == CRYPTO_HASH_CALC_ONLY || \ + CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC */ #if TF_MBEDTLS_USE_AES_GCM /* @@ -368,7 +374,7 @@ static int auth_decrypt(enum crypto_dec_algo dec_algo, void *data_ptr, /* * Register crypto library descriptor */ -#if (MEASURED_BOOT || DRTM_SUPPORT) && TRUSTED_BOARD_BOOT +#if CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC #if TF_MBEDTLS_USE_AES_GCM REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, calc_hash, auth_decrypt); @@ -376,13 +382,13 @@ REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, calc_hash, REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, calc_hash, NULL); #endif -#elif TRUSTED_BOARD_BOOT +#elif CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_ONLY #if TF_MBEDTLS_USE_AES_GCM REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, auth_decrypt); #else REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, NULL); #endif -#elif MEASURED_BOOT || DRTM_SUPPORT +#elif CRYPTO_SUPPORT == CRYPTO_HASH_CALC_ONLY REGISTER_CRYPTO_LIB(LIB_NAME, init, calc_hash); -#endif /* (MEASURED_BOOT || DRTM_SUPPORT) && TRUSTED_BOARD_BOOT */ +#endif /* CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC */ diff --git a/include/drivers/auth/crypto_mod.h b/include/drivers/auth/crypto_mod.h index 103f08500..3a23df4b7 100644 --- a/include/drivers/auth/crypto_mod.h +++ b/include/drivers/auth/crypto_mod.h @@ -7,6 +7,10 @@ #ifndef CRYPTO_MOD_H #define CRYPTO_MOD_H +#define CRYPTO_AUTH_VERIFY_ONLY 1 +#define CRYPTO_HASH_CALC_ONLY 2 +#define CRYPTO_AUTH_VERIFY_AND_HASH_CALC 3 + /* Return values */ enum crypto_ret_value { CRYPTO_SUCCESS = 0, @@ -48,6 +52,8 @@ typedef struct crypto_lib_desc_s { /* Verify a digital signature. Return one of the * 'enum crypto_ret_value' options */ +#if CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_ONLY || \ +CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC int (*verify_signature)(void *data_ptr, unsigned int data_len, void *sig_ptr, unsigned int sig_len, void *sig_alg, unsigned int sig_alg_len, @@ -56,13 +62,17 @@ typedef struct crypto_lib_desc_s { /* Verify a hash. Return one of the 'enum crypto_ret_value' options */ int (*verify_hash)(void *data_ptr, unsigned int data_len, void *digest_info_ptr, unsigned int digest_info_len); +#endif /* CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_ONLY || \ + CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC */ -#if MEASURED_BOOT || DRTM_SUPPORT +#if CRYPTO_SUPPORT == CRYPTO_HASH_CALC_ONLY || \ +CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC /* Calculate a hash. Return hash value */ int (*calc_hash)(enum crypto_md_algo md_alg, void *data_ptr, unsigned int data_len, unsigned char output[CRYPTO_MD_MAX_SIZE]); -#endif /* MEASURED_BOOT || DRTM_SUPPORT */ +#endif /* CRYPTO_SUPPORT == CRYPTO_HASH_CALC_ONLY || \ + CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC */ /* * Authenticated decryption. Return one of the @@ -84,25 +94,32 @@ static inline void crypto_mod_init(void) } #endif /* CRYPTO_SUPPORT */ +#if CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_ONLY || \ +CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC int crypto_mod_verify_signature(void *data_ptr, unsigned int data_len, void *sig_ptr, unsigned int sig_len, void *sig_alg_ptr, unsigned int sig_alg_len, void *pk_ptr, unsigned int pk_len); int crypto_mod_verify_hash(void *data_ptr, unsigned int data_len, void *digest_info_ptr, unsigned int digest_info_len); +#endif /* CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_ONLY || \ + CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC */ + int crypto_mod_auth_decrypt(enum crypto_dec_algo dec_algo, void *data_ptr, size_t len, const void *key, unsigned int key_len, unsigned int key_flags, const void *iv, unsigned int iv_len, const void *tag, unsigned int tag_len); -#if MEASURED_BOOT || DRTM_SUPPORT +#if CRYPTO_SUPPORT == CRYPTO_HASH_CALC_ONLY || \ +CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC int crypto_mod_calc_hash(enum crypto_md_algo alg, void *data_ptr, unsigned int data_len, unsigned char output[CRYPTO_MD_MAX_SIZE]); -#endif /* MEASURED_BOOT || DRTM_SUPPORT */ +#endif /* CRYPTO_SUPPORT == CRYPTO_HASH_CALC_ONLY || \ + CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC */ -#if (MEASURED_BOOT || DRTM_SUPPORT) && TRUSTED_BOARD_BOOT +#if CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC /* Macro to register a cryptographic library */ #define REGISTER_CRYPTO_LIB(_name, _init, _verify_signature, _verify_hash, \ _calc_hash, _auth_decrypt) \ @@ -114,7 +131,7 @@ int crypto_mod_calc_hash(enum crypto_md_algo alg, void *data_ptr, .calc_hash = _calc_hash, \ .auth_decrypt = _auth_decrypt \ } -#elif TRUSTED_BOARD_BOOT +#elif CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_ONLY #define REGISTER_CRYPTO_LIB(_name, _init, _verify_signature, _verify_hash, \ _auth_decrypt) \ const crypto_lib_desc_t crypto_lib_desc = { \ @@ -124,14 +141,14 @@ int crypto_mod_calc_hash(enum crypto_md_algo alg, void *data_ptr, .verify_hash = _verify_hash, \ .auth_decrypt = _auth_decrypt \ } -#elif MEASURED_BOOT || DRTM_SUPPORT +#elif CRYPTO_SUPPORT == CRYPTO_HASH_CALC_ONLY #define REGISTER_CRYPTO_LIB(_name, _init, _calc_hash) \ const crypto_lib_desc_t crypto_lib_desc = { \ .name = _name, \ .init = _init, \ .calc_hash = _calc_hash, \ } -#endif /* (MEASURED_BOOT || DRTM_SUPPORT) && TRUSTED_BOARD_BOOT */ +#endif /* CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC */ extern const crypto_lib_desc_t crypto_lib_desc; From d54792bd93f76b943bf0559c8373b898e0e3b93c Mon Sep 17 00:00:00 2001 From: Manish V Badarkhe Date: Thu, 24 Feb 2022 20:22:39 +0000 Subject: [PATCH 11/32] feat(drtm): update drtm setup function Updated DRTM setup functionality that mainly does below 2 things 1. Initialise the DRTM DMA protection, this function assumes the platform must support complete DMA protection. 2. Initialise the Crypto module that will be useful to calculate the hash of various DRTM element involved. Signed-off-by: Manish V Badarkhe Signed-off-by: Lucian Paul-Trifu Change-Id: I3d6e4d534686d391fa7626094d2b2535dac74e00 --- bl31/bl31.mk | 1 + services/std_svc/drtm/drtm_dma_prot.c | 61 +++++++++++++++++++++++++++ services/std_svc/drtm/drtm_dma_prot.h | 14 ++++++ services/std_svc/drtm/drtm_main.c | 22 ++++++++++ services/std_svc/drtm/drtm_main.h | 2 + 5 files changed, 100 insertions(+) create mode 100644 services/std_svc/drtm/drtm_dma_prot.c create mode 100644 services/std_svc/drtm/drtm_dma_prot.h diff --git a/bl31/bl31.mk b/bl31/bl31.mk index 3e665c584..ec7062755 100644 --- a/bl31/bl31.mk +++ b/bl31/bl31.mk @@ -149,6 +149,7 @@ endif ifeq (${DRTM_SUPPORT},1) BL31_SOURCES += services/std_svc/drtm/drtm_main.c \ + services/std_svc/drtm/drtm_dma_prot.c \ ${MBEDTLS_SOURCES} endif diff --git a/services/std_svc/drtm/drtm_dma_prot.c b/services/std_svc/drtm/drtm_dma_prot.c new file mode 100644 index 000000000..9d014a0c3 --- /dev/null +++ b/services/std_svc/drtm/drtm_dma_prot.c @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2022 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * DRTM DMA protection. + * + * Authors: + * Lucian Paul-Trifu + * + */ + +#include +#include + +#include + +#include "drtm_dma_prot.h" +#include + +/* + * This function checks that platform supports complete DMA protection. + * and returns false - if the platform supports complete DMA protection. + * and returns true - if the platform does not support complete DMA protection. + */ +bool drtm_dma_prot_init(void) +{ + bool must_init_fail = false; + const uintptr_t *smmus; + size_t num_smmus = 0; + unsigned int total_smmus; + + /* Warns presence of non-host platforms */ + if (plat_has_non_host_platforms()) { + WARN("DRTM: the platform includes trusted DMA-capable devices" + " (non-host platforms)\n"); + } + + /* + * DLME protection is uncertain on platforms with peripherals whose + * DMA is not managed by an SMMU. DRTM doesn't work on such platforms. + */ + if (plat_has_unmanaged_dma_peripherals()) { + ERROR("DRTM: this platform does not provide DMA protection\n"); + must_init_fail = true; + } + + /* + * Check that the platform reported all SMMUs. + * It is acceptable if the platform doesn't have any SMMUs when it + * doesn't have any DMA-capable devices. + */ + total_smmus = plat_get_total_smmus(); + plat_enumerate_smmus(&smmus, &num_smmus); + if (num_smmus != total_smmus) { + ERROR("DRTM: could not discover all SMMUs\n"); + must_init_fail = true; + } + + return must_init_fail; +} diff --git a/services/std_svc/drtm/drtm_dma_prot.h b/services/std_svc/drtm/drtm_dma_prot.h new file mode 100644 index 000000000..e0c58b510 --- /dev/null +++ b/services/std_svc/drtm/drtm_dma_prot.h @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2022 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ +#ifndef DRTM_DMA_PROT_H +#define DRTM_DMA_PROT_H + +#include + +bool drtm_dma_prot_init(void); + +#endif /* DRTM_DMA_PROT_H */ diff --git a/services/std_svc/drtm/drtm_main.c b/services/std_svc/drtm/drtm_main.c index c7fce5e16..adb929379 100644 --- a/services/std_svc/drtm/drtm_main.c +++ b/services/std_svc/drtm/drtm_main.c @@ -12,15 +12,37 @@ #include +#include +#include #include #include +#include #include "drtm_main.h" #include +/* This value is used by the SMC to advertise the boot PE */ +static uint64_t boot_pe_aff_value; + int drtm_setup(void) { + bool rc; + INFO("DRTM service setup\n"); + boot_pe_aff_value = read_mpidr_el1() & MPIDR_AFFINITY_MASK; + + rc = drtm_dma_prot_init(); + if (rc) { + return INTERNAL_ERROR; + } + + /* + * initialise the platform supported crypto module that will + * be used by the DRTM-service to calculate hash of DRTM- + * implementation specific components + */ + crypto_mod_init(); + return 0; } diff --git a/services/std_svc/drtm/drtm_main.h b/services/std_svc/drtm/drtm_main.h index 39c67cecf..4c1adac04 100644 --- a/services/std_svc/drtm/drtm_main.h +++ b/services/std_svc/drtm/drtm_main.h @@ -11,6 +11,8 @@ #include +#include "drtm_dma_prot.h" + enum drtm_retc { SUCCESS = SMC_OK, NOT_SUPPORTED = SMC_UNK, From ff1e42e20aa247ba11cf81742abff07ece376ba8 Mon Sep 17 00:00:00 2001 From: Manish V Badarkhe Date: Thu, 3 Mar 2022 11:42:27 +0000 Subject: [PATCH 12/32] feat(drtm): add PCR entries for DRTM Added PCR entries for the measurement performed by the DCE and D-CRTM in DRTM implementation Signed-off-by: Manish V Badarkhe Change-Id: Ib9bfafe7fa2efa1cc36d7ff138468d648235dcf1 --- include/drivers/measured_boot/event_log/tcg.h | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/include/drivers/measured_boot/event_log/tcg.h b/include/drivers/measured_boot/event_log/tcg.h index ab27a0844..4ac2c2ff3 100644 --- a/include/drivers/measured_boot/event_log/tcg.h +++ b/include/drivers/measured_boot/event_log/tcg.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Arm Limited. All rights reserved. + * Copyright (c) 2020-2022, Arm Limited. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -98,7 +98,12 @@ enum { /* 8-15: Defined for use by the Static OS */ PCR_8, /* Debug */ - PCR_16 = 16 + PCR_16 = 16, + + /* D-CRTM-measurements by DRTM implementation */ + PCR_17 = 17, + /* DCE measurements by DRTM implementation */ + PCR_18 = 18 }; #pragma pack(push, 1) From e6381f9cf8c0c62c32d5a4765aaf166f50786914 Mon Sep 17 00:00:00 2001 From: John Powell Date: Thu, 12 May 2022 12:49:55 -0500 Subject: [PATCH 13/32] feat(sdei): add a function to return total number of events registered This patch adds a public API to return the total number of registered events. The purpose of this is primarily for DRTM to ensure that no SDEI event can interfere with a dynamic launch. Signed-off-by: John Powell Change-Id: I1d1cba2da7d5566cc340620ee1ce7d7844740b86 --- include/services/sdei.h | 5 ++++- services/std_svc/sdei/sdei_event.c | 23 ++++++++++++++++++++++- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/include/services/sdei.h b/include/services/sdei.h index 063ed6f28..c12a182f0 100644 --- a/include/services/sdei.h +++ b/include/services/sdei.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2017-2022, Arm Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -137,4 +137,7 @@ void sdei_init(void); /* Public API to dispatch an event to Normal world */ int sdei_dispatch_event(int ev_num); +/* Public API to check how many SDEI events are registered. */ +int sdei_get_registered_event_count(void); + #endif /* SDEI_H */ diff --git a/services/std_svc/sdei/sdei_event.c b/services/std_svc/sdei/sdei_event.c index 0b608e1b6..e0c7971ac 100644 --- a/services/std_svc/sdei/sdei_event.c +++ b/services/std_svc/sdei/sdei_event.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2017-2022, Arm Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -99,3 +99,24 @@ sdei_ev_map_t *find_event_map(int ev_num) return NULL; } + +/* + * Return the total number of currently registered SDEI events. + */ +int sdei_get_registered_event_count(void) +{ + const sdei_mapping_t *mapping; + sdei_ev_map_t *map; + unsigned int i; + unsigned int j; + int count = 0; + + /* Add up reg counts for each mapping. */ + for_each_mapping_type(i, mapping) { + iterate_mapping(mapping, j, map) { + count += map->reg_count; + } + } + + return count; +} From 2a1cdee4f5e6fe0b90399e442075880acad1869e Mon Sep 17 00:00:00 2001 From: johpow01 Date: Fri, 11 Mar 2022 17:50:58 -0600 Subject: [PATCH 14/32] feat(drtm): add platform functions for DRTM Added platform hooks to retrieve DRTM features and address map. Additionally, implemented these hooks for the FVP platform. Signed-off-by: John Powell Signed-off-by: Manish V Badarkhe Change-Id: I5621cc9807ffff8139ae8876250147f7b2c76759 --- bl31/bl31.mk | 5 +- include/lib/xlat_tables/xlat_tables_compat.h | 7 +- include/plat/common/plat_drtm.h | 46 ++++++ include/services/drtm_svc.h | 152 +++++++++++++++++++ plat/arm/board/fvp/fvp_drtm_dma_prot.c | 16 ++ plat/arm/board/fvp/fvp_drtm_measurement.c | 29 ++++ plat/arm/board/fvp/fvp_drtm_stub.c | 35 +++++ plat/arm/board/fvp/include/platform_def.h | 10 ++ plat/arm/board/fvp/platform.mk | 2 + plat/arm/common/arm_common.c | 4 + services/std_svc/drtm/drtm_main.c | 79 +++++++++- services/std_svc/drtm/drtm_main.h | 11 ++ services/std_svc/drtm/drtm_res_address_map.c | 88 +++++++++++ 13 files changed, 478 insertions(+), 6 deletions(-) create mode 100644 plat/arm/board/fvp/fvp_drtm_measurement.c create mode 100644 plat/arm/board/fvp/fvp_drtm_stub.c create mode 100644 services/std_svc/drtm/drtm_res_address_map.c diff --git a/bl31/bl31.mk b/bl31/bl31.mk index ec7062755..f435815ce 100644 --- a/bl31/bl31.mk +++ b/bl31/bl31.mk @@ -148,8 +148,9 @@ BL31_SOURCES += common/feat_detect.c endif ifeq (${DRTM_SUPPORT},1) -BL31_SOURCES += services/std_svc/drtm/drtm_main.c \ - services/std_svc/drtm/drtm_dma_prot.c \ +BL31_SOURCES += services/std_svc/drtm/drtm_main.c \ + services/std_svc/drtm/drtm_dma_prot.c \ + services/std_svc/drtm/drtm_res_address_map.c \ ${MBEDTLS_SOURCES} endif diff --git a/include/lib/xlat_tables/xlat_tables_compat.h b/include/lib/xlat_tables/xlat_tables_compat.h index 90768db5d..5f281957a 100644 --- a/include/lib/xlat_tables/xlat_tables_compat.h +++ b/include/lib/xlat_tables/xlat_tables_compat.h @@ -1,11 +1,16 @@ /* - * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2018-2022, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ +#ifndef XLAT_TABLES_COMPAT_H +#define XLAT_TABLES_COMPAT_H + #if XLAT_TABLES_LIB_V2 #include #else #include #endif + +#endif /* XLAT_TABLES_COMPAT_H */ diff --git a/include/plat/common/plat_drtm.h b/include/plat/common/plat_drtm.h index 3c4e3d536..e9b8d6a70 100644 --- a/include/plat/common/plat_drtm.h +++ b/include/plat/common/plat_drtm.h @@ -7,11 +7,57 @@ #ifndef PLAT_DRTM_H #define PLAT_DRTM_H +#include +#include + +typedef struct { + uint8_t max_num_mem_prot_regions; + uint8_t dma_protection_support; +} plat_drtm_dma_prot_features_t; + +typedef struct { + bool tpm_based_hash_support; + uint32_t firmware_hash_algorithm; +} plat_drtm_tpm_features_t; + +typedef struct { + uint64_t region_address; + uint64_t region_size_type; +} __attribute__((packed)) drtm_mem_region_t; + +/* + * Memory region descriptor table structure as per DRTM beta0 section 3.13 + * Table 11 MEMORY_REGION_DESCRIPTOR_TABLE + */ +typedef struct { + uint16_t revision; + uint16_t reserved; + uint32_t num_regions; + drtm_mem_region_t region[]; +} __attribute__((packed)) drtm_memory_region_descriptor_table_t; + +/* platform specific address map functions */ +const mmap_region_t *plat_get_addr_mmap(void); + /* platform-specific DMA protection functions */ bool plat_has_non_host_platforms(void); bool plat_has_unmanaged_dma_peripherals(void); unsigned int plat_get_total_smmus(void); void plat_enumerate_smmus(const uintptr_t **smmus_out, size_t *smmu_count_out); +const plat_drtm_dma_prot_features_t *plat_drtm_get_dma_prot_features(void); +uint64_t plat_drtm_dma_prot_get_max_table_bytes(void); + +/* platform-specific TPM functions */ +const plat_drtm_tpm_features_t *plat_drtm_get_tpm_features(void); + +/* + * TODO: Implement these functions as per the platform use case, + * as of now none of the platform uses these functions + */ +uint64_t plat_drtm_get_min_size_normal_world_dce(void); +uint64_t plat_drtm_get_tcb_hash_table_size(void); +uint64_t plat_drtm_get_imp_def_dlme_region_size(void); +uint64_t plat_drtm_get_tcb_hash_features(void); #endif /* PLAT_DRTM_H */ diff --git a/include/services/drtm_svc.h b/include/services/drtm_svc.h index 6845ace9c..890cdbb0e 100644 --- a/include/services/drtm_svc.h +++ b/include/services/drtm_svc.h @@ -66,6 +66,158 @@ #define ARM_DRTM_FUNC_ID U(0x0) #define ARM_DRTM_FEAT_ID U(0x1) +/* + * Definitions for DRTM features as per DRTM beta0 section 3.3, + * Table 6 DRTM_FEATURES + */ +#define ARM_DRTM_TPM_FEATURES_PCR_SCHEMA_SHIFT U(33) +#define ARM_DRTM_TPM_FEATURES_PCR_SCHEMA_MASK ULL(0xF) +#define ARM_DRTM_TPM_FEATURES_PCR_SCHEMA_DEFAULT ULL(0x1) + +#define ARM_DRTM_TPM_FEATURES_TPM_HASH_SHIFT U(32) +#define ARM_DRTM_TPM_FEATURES_TPM_HASH_MASK ULL(0x1) +#define ARM_DRTM_TPM_FEATURES_TPM_HASH_NOT_SUPPORTED ULL(0x0) +#define ARM_DRTM_TPM_FEATURES_TPM_HASH_SUPPORTED ULL(0x1) + +#define ARM_DRTM_TPM_FEATURES_FW_HASH_SHIFT U(0) +#define ARM_DRTM_TPM_FEATURES_FW_HASH_MASK ULL(0xFFFFFFFF) +#define ARM_DRTM_TPM_FEATURES_FW_HASH_SHA256 ULL(0xB) +#define ARM_DRTM_TPM_FEATURES_FW_HASH_SHA384 ULL(0xC) +#define ARM_DRTM_TPM_FEATURES_FW_HASH_SHA512 ULL(0xD) + +#define ARM_DRTM_MIN_MEM_REQ_DCE_SIZE_SHIFT U(32) +#define ARM_DRTM_MIN_MEM_REQ_DCE_SIZE_MASK ULL(0xFFFFFFFF) + +#define ARM_DRTM_MIN_MEM_REQ_MIN_DLME_DATA_SIZE_SHIFT U(0) +#define ARM_DRTM_MIN_MEM_REQ_MIN_DLME_DATA_SIZE_MASK ULL(0xFFFFFFFF) + +#define ARM_DRTM_DMA_PROT_FEATURES_MAX_REGIONS_SHIFT U(8) +#define ARM_DRTM_DMA_PROT_FEATURES_MAX_REGIONS_MASK ULL(0xF) + +#define ARM_DRTM_DMA_PROT_FEATURES_DMA_SUPPORT_SHIFT U(0) +#define ARM_DRTM_DMA_PROT_FEATURES_DMA_SUPPORT_MASK ULL(0xFF) +#define ARM_DRTM_DMA_PROT_FEATURES_DMA_SUPPORT_COMPLETE ULL(0x1) +#define ARM_DRTM_DMA_PROT_FEATURES_DMA_SUPPORT_REGION ULL(0x2) + +#define ARM_DRTM_TCB_HASH_FEATURES_MAX_NUM_HASHES_SHIFT U(0) +#define ARM_DRTM_TCB_HASH_FEATURES_MAX_NUM_HASHES_MASK ULL(0xFF) + +#define ARM_DRTM_TPM_FEATURES_SET_PCR_SCHEMA(reg, val) \ + do { \ + reg = (((reg) & ~(ARM_DRTM_TPM_FEATURES_PCR_SCHEMA_MASK \ + << ARM_DRTM_TPM_FEATURES_PCR_SCHEMA_SHIFT)) | (((val) & \ + ARM_DRTM_TPM_FEATURES_PCR_SCHEMA_MASK) << \ + ARM_DRTM_TPM_FEATURES_PCR_SCHEMA_SHIFT)); \ + } while (false) + +#define ARM_DRTM_TPM_FEATURES_SET_TPM_HASH(reg, val) \ + do { \ + reg = (((reg) & ~(ARM_DRTM_TPM_FEATURES_TPM_HASH_MASK \ + << ARM_DRTM_TPM_FEATURES_TPM_HASH_SHIFT)) | (((val) & \ + ARM_DRTM_TPM_FEATURES_TPM_HASH_MASK) << \ + ARM_DRTM_TPM_FEATURES_TPM_HASH_SHIFT)); \ + } while (false) + +#define ARM_DRTM_TPM_FEATURES_SET_FW_HASH(reg, val) \ + do { \ + reg = (((reg) & ~(ARM_DRTM_TPM_FEATURES_FW_HASH_MASK \ + << ARM_DRTM_TPM_FEATURES_FW_HASH_SHIFT)) | (((val) & \ + ARM_DRTM_TPM_FEATURES_FW_HASH_MASK) << \ + ARM_DRTM_TPM_FEATURES_FW_HASH_SHIFT)); \ + } while (false) + +#define ARM_DRTM_MIN_MEM_REQ_SET_DCE_SIZE(reg, val) \ + do { \ + reg = (((reg) & ~(ARM_DRTM_MIN_MEM_REQ_DCE_SIZE_MASK \ + << ARM_DRTM_MIN_MEM_REQ_DCE_SIZE_SHIFT)) | (((val) & \ + ARM_DRTM_MIN_MEM_REQ_DCE_SIZE_MASK) << \ + ARM_DRTM_MIN_MEM_REQ_DCE_SIZE_SHIFT)); \ + } while (false) + +#define ARM_DRTM_MIN_MEM_REQ_SET_MIN_DLME_DATA_SIZE(reg, val) \ + do { \ + reg = (((reg) & \ + ~(ARM_DRTM_MIN_MEM_REQ_MIN_DLME_DATA_SIZE_MASK << \ + ARM_DRTM_MIN_MEM_REQ_MIN_DLME_DATA_SIZE_SHIFT)) | \ + (((val) & ARM_DRTM_MIN_MEM_REQ_MIN_DLME_DATA_SIZE_MASK) \ + << ARM_DRTM_MIN_MEM_REQ_MIN_DLME_DATA_SIZE_SHIFT)); \ + } while (false) + +#define ARM_DRTM_DMA_PROT_FEATURES_SET_MAX_REGIONS(reg, val) \ + do { \ + reg = (((reg) & \ + ~(ARM_DRTM_DMA_PROT_FEATURES_MAX_REGIONS_MASK << \ + ARM_DRTM_DMA_PROT_FEATURES_MAX_REGIONS_SHIFT)) | \ + (((val) & ARM_DRTM_DMA_PROT_FEATURES_MAX_REGIONS_MASK) \ + << ARM_DRTM_DMA_PROT_FEATURES_MAX_REGIONS_SHIFT)); \ + } while (false) + +#define ARM_DRTM_DMA_PROT_FEATURES_SET_DMA_SUPPORT(reg, val) \ + do { \ + reg = (((reg) & \ + ~(ARM_DRTM_DMA_PROT_FEATURES_DMA_SUPPORT_MASK << \ + ARM_DRTM_DMA_PROT_FEATURES_DMA_SUPPORT_SHIFT)) | \ + (((val) & ARM_DRTM_DMA_PROT_FEATURES_DMA_SUPPORT_MASK) \ + << ARM_DRTM_DMA_PROT_FEATURES_DMA_SUPPORT_SHIFT)); \ + } while (false) + +#define ARM_DRTM_TCB_HASH_FEATURES_SET_MAX_NUM_HASHES(reg, val) \ + do { \ + reg = (((reg) & \ + ~(ARM_DRTM_TCB_HASH_FEATURES_MAX_NUM_HASHES_MASK << \ + ARM_DRTM_TCB_HASH_FEATURES_MAX_NUM_HASHES_SHIFT)) | \ + (((val) & \ + ARM_DRTM_TCB_HASH_FEATURES_MAX_NUM_HASHES_MASK) << \ + ARM_DRTM_TCB_HASH_FEATURES_MAX_NUM_HASHES_SHIFT)); \ + } while (false) + +/* Definitions for DRTM address map */ +#define ARM_DRTM_REGION_SIZE_TYPE_CACHEABILITY_SHIFT U(55) +#define ARM_DRTM_REGION_SIZE_TYPE_CACHEABILITY_MASK ULL(0x3) +#define ARM_DRTM_REGION_SIZE_TYPE_CACHEABILITY_NC ULL(0) +#define ARM_DRTM_REGION_SIZE_TYPE_CACHEABILITY_WC ULL(1) +#define ARM_DRTM_REGION_SIZE_TYPE_CACHEABILITY_WT ULL(2) +#define ARM_DRTM_REGION_SIZE_TYPE_CACHEABILITY_WB ULL(3) + +#define ARM_DRTM_REGION_SIZE_TYPE_REGION_TYPE_SHIFT U(52) +#define ARM_DRTM_REGION_SIZE_TYPE_REGION_TYPE_MASK ULL(0x7) +#define ARM_DRTM_REGION_SIZE_TYPE_REGION_TYPE_NORMAL ULL(0) +#define ARM_DRTM_REGION_SIZE_TYPE_REGION_TYPE_NCAR ULL(1) +#define ARM_DRTM_REGION_SIZE_TYPE_REGION_TYPE_DEVICE ULL(2) +#define ARM_DRTM_REGION_SIZE_TYPE_REGION_TYPE_NV ULL(3) +#define ARM_DRTM_REGION_SIZE_TYPE_REGION_TYPE_RSVD ULL(4) + +#define ARM_DRTM_REGION_SIZE_TYPE_4K_PAGE_NUM_SHIFT U(0) +#define ARM_DRTM_REGION_SIZE_TYPE_4K_PAGE_NUM_MASK ULL(0xFFFFFFFFFFFFF) + +#define ARM_DRTM_REGION_SIZE_TYPE_SET_CACHEABILITY(reg, val) \ + do { \ + reg = (((reg) & \ + ~(ARM_DRTM_REGION_SIZE_TYPE_CACHEABILITY_MASK << \ + ARM_DRTM_REGION_SIZE_TYPE_CACHEABILITY_SHIFT)) | \ + (((val) & \ + ARM_DRTM_REGION_SIZE_TYPE_CACHEABILITY_MASK) << \ + ARM_DRTM_REGION_SIZE_TYPE_CACHEABILITY_SHIFT)); \ + } while (false) + +#define ARM_DRTM_REGION_SIZE_TYPE_SET_REGION_TYPE(reg, val) \ + do { \ + reg = (((reg) & \ + ~(ARM_DRTM_REGION_SIZE_TYPE_REGION_TYPE_MASK << \ + ARM_DRTM_REGION_SIZE_TYPE_REGION_TYPE_SHIFT)) | \ + (((val) & ARM_DRTM_REGION_SIZE_TYPE_REGION_TYPE_MASK) \ + << ARM_DRTM_REGION_SIZE_TYPE_REGION_TYPE_SHIFT)); \ + } while (false) + +#define ARM_DRTM_REGION_SIZE_TYPE_SET_4K_PAGE_NUM(reg, val) \ + do { \ + reg = (((reg) & \ + ~(ARM_DRTM_REGION_SIZE_TYPE_4K_PAGE_NUM_MASK << \ + ARM_DRTM_REGION_SIZE_TYPE_4K_PAGE_NUM_SHIFT)) | \ + (((val) & ARM_DRTM_REGION_SIZE_TYPE_4K_PAGE_NUM_MASK) \ + << ARM_DRTM_REGION_SIZE_TYPE_4K_PAGE_NUM_SHIFT)); \ + } while (false) + /* Initialization routine for the DRTM service */ int drtm_setup(void); diff --git a/plat/arm/board/fvp/fvp_drtm_dma_prot.c b/plat/arm/board/fvp/fvp_drtm_dma_prot.c index ec9cd7a2e..38ff7fe38 100644 --- a/plat/arm/board/fvp/fvp_drtm_dma_prot.c +++ b/plat/arm/board/fvp/fvp_drtm_dma_prot.c @@ -58,3 +58,19 @@ void plat_enumerate_smmus(const uintptr_t **smmus_out, *smmu_count_out = 0; } } + +/* DRTM DMA Protection Features */ +static const plat_drtm_dma_prot_features_t dma_prot_features = { + .max_num_mem_prot_regions = 0, /* No protection regions are present */ + .dma_protection_support = 0x1 /* Complete DMA protection only */ +}; + +const plat_drtm_dma_prot_features_t *plat_drtm_get_dma_prot_features(void) +{ + return &dma_prot_features; +} + +uint64_t plat_drtm_dma_prot_get_max_table_bytes(void) +{ + return 0U; +} diff --git a/plat/arm/board/fvp/fvp_drtm_measurement.c b/plat/arm/board/fvp/fvp_drtm_measurement.c new file mode 100644 index 000000000..4fbedd8bc --- /dev/null +++ b/plat/arm/board/fvp/fvp_drtm_measurement.c @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include + +#include + +/* DRTM TPM Features */ +static const plat_drtm_tpm_features_t tpm_features = { + /* No TPM-based hashing supported. */ + .tpm_based_hash_support = false, + + /* Set to decided algorithm by Event Log driver */ + .firmware_hash_algorithm = TPM_ALG_ID + +}; + +const plat_drtm_tpm_features_t *plat_drtm_get_tpm_features(void) +{ + return &tpm_features; +} diff --git a/plat/arm/board/fvp/fvp_drtm_stub.c b/plat/arm/board/fvp/fvp_drtm_stub.c new file mode 100644 index 000000000..e2bc5169a --- /dev/null +++ b/plat/arm/board/fvp/fvp_drtm_stub.c @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + + +#include + +#include + +/* + * This file contains DRTM platform functions which don't really do anything on + * FVP but are needed for DRTM to function. + */ + +uint64_t plat_drtm_get_min_size_normal_world_dce(void) +{ + return 0ULL; +} + +uint64_t plat_drtm_get_imp_def_dlme_region_size(void) +{ + return 0ULL; +} + +uint64_t plat_drtm_get_tcb_hash_features(void) +{ + return 0ULL; +} + +uint64_t plat_drtm_get_tcb_hash_table_size(void) +{ + return 0ULL; +} diff --git a/plat/arm/board/fvp/include/platform_def.h b/plat/arm/board/fvp/include/platform_def.h index efe149ab0..1ef6c87a2 100644 --- a/plat/arm/board/fvp/include/platform_def.h +++ b/plat/arm/board/fvp/include/platform_def.h @@ -403,4 +403,14 @@ */ #define PLAT_ARM_EVENT_LOG_MAX_SIZE UL(0x400) +/* + * Maximum size of Event Log buffer used for DRTM + */ +#define PLAT_DRTM_EVENT_LOG_MAX_SIZE UL(0x300) + +/* + * Number of MMAP entries used by DRTM implementation + */ +#define PLAT_DRTM_MMAP_ENTRIES PLAT_ARM_MMAP_ENTRIES + #endif /* PLATFORM_DEF_H */ diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk index 460227612..eb2b5e517 100644 --- a/plat/arm/board/fvp/platform.mk +++ b/plat/arm/board/fvp/platform.mk @@ -415,6 +415,8 @@ endif ifeq (${DRTM_SUPPORT}, 1) BL31_SOURCES += plat/arm/board/fvp/fvp_drtm_dma_prot.c \ + plat/arm/board/fvp/fvp_drtm_measurement.c \ + plat/arm/board/fvp/fvp_drtm_stub.c \ plat/arm/common/arm_dyn_cfg.c endif diff --git a/plat/arm/common/arm_common.c b/plat/arm/common/arm_common.c index 946b7329f..fc681149e 100644 --- a/plat/arm/common/arm_common.c +++ b/plat/arm/common/arm_common.c @@ -237,3 +237,7 @@ int plat_sdei_validate_entry_point(uintptr_t ep, unsigned int client_mode) } #endif +const mmap_region_t *plat_get_addr_mmap(void) +{ + return plat_arm_mmap; +} diff --git a/services/std_svc/drtm/drtm_main.c b/services/std_svc/drtm/drtm_main.c index adb929379..843fc5d35 100644 --- a/services/std_svc/drtm/drtm_main.c +++ b/services/std_svc/drtm/drtm_main.c @@ -14,22 +14,33 @@ #include #include +#include #include #include #include #include "drtm_main.h" +#include +#include #include +#include -/* This value is used by the SMC to advertise the boot PE */ -static uint64_t boot_pe_aff_value; +/* Structure to store DRTM features specific to the platform. */ +static drtm_features_t plat_drtm_features; + +/* DRTM-formatted memory map. */ +static drtm_memory_region_descriptor_table_t *plat_drtm_mem_map; int drtm_setup(void) { bool rc; + const plat_drtm_tpm_features_t *plat_tpm_feat; + const plat_drtm_dma_prot_features_t *plat_dma_prot_feat; + uint64_t dlme_data_min_size; INFO("DRTM service setup\n"); - boot_pe_aff_value = read_mpidr_el1() & MPIDR_AFFINITY_MASK; + /* Read boot PE ID from MPIDR */ + plat_drtm_features.boot_pe_id = read_mpidr_el1() & MPIDR_AFFINITY_MASK; rc = drtm_dma_prot_init(); if (rc) { @@ -43,6 +54,68 @@ int drtm_setup(void) */ crypto_mod_init(); + /* Build DRTM-compatible address map. */ + plat_drtm_mem_map = drtm_build_address_map(); + if (plat_drtm_mem_map == NULL) { + return INTERNAL_ERROR; + } + + /* Get DRTM features from platform hooks. */ + plat_tpm_feat = plat_drtm_get_tpm_features(); + if (plat_tpm_feat == NULL) { + return INTERNAL_ERROR; + } + + plat_dma_prot_feat = plat_drtm_get_dma_prot_features(); + if (plat_dma_prot_feat == NULL) { + return INTERNAL_ERROR; + } + + /* + * Add up minimum DLME data memory. + * + * For systems with complete DMA protection there is only one entry in + * the protected regions table. + */ + if (plat_dma_prot_feat->dma_protection_support == + ARM_DRTM_DMA_PROT_FEATURES_DMA_SUPPORT_COMPLETE) { + dlme_data_min_size = + sizeof(drtm_memory_region_descriptor_table_t) + + sizeof(drtm_mem_region_t); + } else { + /* + * TODO set protected regions table size based on platform DMA + * protection configuration + */ + panic(); + } + + dlme_data_min_size += (drtm_get_address_map_size() + + PLAT_DRTM_EVENT_LOG_MAX_SIZE + + plat_drtm_get_tcb_hash_table_size() + + plat_drtm_get_imp_def_dlme_region_size()); + + dlme_data_min_size = page_align(dlme_data_min_size, UP)/PAGE_SIZE; + + /* Fill out platform DRTM features structure */ + /* Only support default PCR schema (0x1) in this implementation. */ + ARM_DRTM_TPM_FEATURES_SET_PCR_SCHEMA(plat_drtm_features.tpm_features, + ARM_DRTM_TPM_FEATURES_PCR_SCHEMA_DEFAULT); + ARM_DRTM_TPM_FEATURES_SET_TPM_HASH(plat_drtm_features.tpm_features, + plat_tpm_feat->tpm_based_hash_support); + ARM_DRTM_TPM_FEATURES_SET_FW_HASH(plat_drtm_features.tpm_features, + plat_tpm_feat->firmware_hash_algorithm); + ARM_DRTM_MIN_MEM_REQ_SET_MIN_DLME_DATA_SIZE(plat_drtm_features.minimum_memory_requirement, + dlme_data_min_size); + ARM_DRTM_MIN_MEM_REQ_SET_DCE_SIZE(plat_drtm_features.minimum_memory_requirement, + plat_drtm_get_min_size_normal_world_dce()); + ARM_DRTM_DMA_PROT_FEATURES_SET_MAX_REGIONS(plat_drtm_features.dma_prot_features, + plat_dma_prot_feat->max_num_mem_prot_regions); + ARM_DRTM_DMA_PROT_FEATURES_SET_DMA_SUPPORT(plat_drtm_features.dma_prot_features, + plat_dma_prot_feat->dma_protection_support); + ARM_DRTM_TCB_HASH_FEATURES_SET_MAX_NUM_HASHES(plat_drtm_features.tcb_hash_features, + plat_drtm_get_tcb_hash_features()); + return 0; } diff --git a/services/std_svc/drtm/drtm_main.h b/services/std_svc/drtm/drtm_main.h index 4c1adac04..b60d95458 100644 --- a/services/std_svc/drtm/drtm_main.h +++ b/services/std_svc/drtm/drtm_main.h @@ -23,4 +23,15 @@ enum drtm_retc { MEM_PROTECT_INVALID = -6, }; +typedef struct { + uint64_t tpm_features; + uint64_t minimum_memory_requirement; + uint64_t dma_prot_features; + uint64_t boot_pe_id; + uint64_t tcb_hash_features; +} drtm_features_t; + +drtm_memory_region_descriptor_table_t *drtm_build_address_map(void); +uint64_t drtm_get_address_map_size(void); + #endif /* DRTM_MAIN_H */ diff --git a/services/std_svc/drtm/drtm_res_address_map.c b/services/std_svc/drtm/drtm_res_address_map.c new file mode 100644 index 000000000..86367061e --- /dev/null +++ b/services/std_svc/drtm/drtm_res_address_map.c @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2022 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +/* Address map revision generated by this code. */ +#define DRTM_ADDRESS_MAP_REVISION U(0x0001) + +/* Amount of space needed for address map based on PLAT_DRTM_MMAP_ENTRIES */ +#define DRTM_ADDRESS_MAP_SIZE (sizeof(drtm_memory_region_descriptor_table_t) + \ + (sizeof(drtm_mem_region_t) * \ + PLAT_DRTM_MMAP_ENTRIES)) + +/* Allocate space for DRTM-formatted address map to be constructed. */ +static uint8_t drtm_address_map[DRTM_ADDRESS_MAP_SIZE]; + +static uint64_t drtm_address_map_size; + +drtm_memory_region_descriptor_table_t *drtm_build_address_map(void) +{ + /* Set up pointer to DRTM memory map. */ + drtm_memory_region_descriptor_table_t *map = + (drtm_memory_region_descriptor_table_t *)drtm_address_map; + + /* Get the platform memory map. */ + const mmap_region_t *mmap = plat_get_addr_mmap(); + unsigned int i; + + /* Set up header for address map structure. */ + map->revision = DRTM_ADDRESS_MAP_REVISION; + map->reserved = 0x0000; + + /* Iterate through mmap and generate DRTM address map. */ + for (i = 0U; mmap[i].base_pa != 0UL; i++) { + /* Set PA of region. */ + map->region[i].region_address = mmap[i].base_pa; + + /* Set size of region (in 4kb chunks). */ + map->region[i].region_size_type = 0; + ARM_DRTM_REGION_SIZE_TYPE_SET_4K_PAGE_NUM( + map->region[i].region_size_type, + mmap[i].size / PAGE_SIZE_4KB); + + /* Set type and cacheability. */ + switch (MT_TYPE(mmap[i].attr)) { + case MT_DEVICE: + ARM_DRTM_REGION_SIZE_TYPE_SET_REGION_TYPE( + map->region[i].region_size_type, + ARM_DRTM_REGION_SIZE_TYPE_REGION_TYPE_DEVICE); + break; + case MT_NON_CACHEABLE: + ARM_DRTM_REGION_SIZE_TYPE_SET_REGION_TYPE( + map->region[i].region_size_type, + ARM_DRTM_REGION_SIZE_TYPE_REGION_TYPE_NCAR); + ARM_DRTM_REGION_SIZE_TYPE_SET_CACHEABILITY( + map->region[i].region_size_type, + ARM_DRTM_REGION_SIZE_TYPE_CACHEABILITY_NC); + break; + case MT_MEMORY: + ARM_DRTM_REGION_SIZE_TYPE_SET_REGION_TYPE( + map->region[i].region_size_type, + ARM_DRTM_REGION_SIZE_TYPE_REGION_TYPE_NORMAL); + break; + default: + return NULL; + } + } + + map->num_regions = i; + + /* Store total size of address map. */ + drtm_address_map_size = sizeof(drtm_memory_region_descriptor_table_t); + drtm_address_map_size += (i * sizeof(drtm_mem_region_t)); + + return map; +} + +uint64_t drtm_get_address_map_size(void) +{ + return drtm_address_map_size; +} From e9467afb2d483ccec8f816902624d848e8f21d86 Mon Sep 17 00:00:00 2001 From: Manish V Badarkhe Date: Thu, 16 Jun 2022 13:46:43 +0100 Subject: [PATCH 15/32] feat(drtm): retrieve DRTM features Retrieved below DRTM features via DRTM_FEATURES SMC call - 1. TPM features 2. Minimum memory requirement 3. Boot PE ID 4. DMA protection Change-Id: Ia6dc497259541ce30a6550afa35d95d9a9a366af Signed-off-by: Manish V Badarkhe Signed-off-by: Lucian Paul-Trifu --- include/services/drtm_svc.h | 9 ++++- services/std_svc/drtm/drtm_main.c | 67 +++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+), 1 deletion(-) diff --git a/include/services/drtm_svc.h b/include/services/drtm_svc.h index 890cdbb0e..69b314f08 100644 --- a/include/services/drtm_svc.h +++ b/include/services/drtm_svc.h @@ -44,6 +44,12 @@ #define ARM_DRTM_SVC_SET_TCB_HASH DRTM_FID(DRTM_FNUM_SVC_SET_TCB_HASH) #define ARM_DRTM_SVC_LOCK_TCB_HASH DRTM_FID(DRTM_FNUM_SVC_LOCK_TCB_HASH) +#define ARM_DRTM_FEATURES_TPM U(0x1) +#define ARM_DRTM_FEATURES_MEM_REQ U(0x2) +#define ARM_DRTM_FEATURES_DMA_PROT U(0x3) +#define ARM_DRTM_FEATURES_BOOT_PE_ID U(0x4) +#define ARM_DRTM_FEATURES_TCB_HASHES U(0x5) + #define is_drtm_fid(_fid) \ (((_fid) >= ARM_DRTM_SVC_VERSION) && ((_fid) <= ARM_DRTM_SVC_LOCK_TCB_HASH)) @@ -62,9 +68,10 @@ ARM_DRTM_VERSION_MINOR_SHIFT)) #define ARM_DRTM_FUNC_SHIFT U(63) -#define ARM_DRTM_FUNC_MASK U(0x1) +#define ARM_DRTM_FUNC_MASK ULL(0x1) #define ARM_DRTM_FUNC_ID U(0x0) #define ARM_DRTM_FEAT_ID U(0x1) +#define ARM_DRTM_FEAT_ID_MASK ULL(0xff) /* * Definitions for DRTM features as per DRTM beta0 section 3.3, diff --git a/services/std_svc/drtm/drtm_main.c b/services/std_svc/drtm/drtm_main.c index 843fc5d35..867870bb5 100644 --- a/services/std_svc/drtm/drtm_main.c +++ b/services/std_svc/drtm/drtm_main.c @@ -119,6 +119,36 @@ int drtm_setup(void) return 0; } +static inline uint64_t drtm_features_tpm(void *ctx) +{ + SMC_RET2(ctx, 1ULL, /* TPM feature is supported */ + plat_drtm_features.tpm_features); +} + +static inline uint64_t drtm_features_mem_req(void *ctx) +{ + SMC_RET2(ctx, 1ULL, /* memory req Feature is supported */ + plat_drtm_features.minimum_memory_requirement); +} + +static inline uint64_t drtm_features_boot_pe_id(void *ctx) +{ + SMC_RET2(ctx, 1ULL, /* Boot PE feature is supported */ + plat_drtm_features.boot_pe_id); +} + +static inline uint64_t drtm_features_dma_prot(void *ctx) +{ + SMC_RET2(ctx, 1ULL, /* DMA protection feature is supported */ + plat_drtm_features.dma_prot_features); +} + +static inline uint64_t drtm_features_tcb_hashes(void *ctx) +{ + SMC_RET2(ctx, 1ULL, /* TCB hash feature is supported */ + plat_drtm_features.tcb_hash_features); +} + uint64_t drtm_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, @@ -192,6 +222,43 @@ uint64_t drtm_smc_handler(uint32_t smc_fid, SMC_RET1(handle, NOT_SUPPORTED); break; /* not reached */ } + } else { + /* Dispatch feature-based queries. */ + switch (x1 & ARM_DRTM_FEAT_ID_MASK) { + case ARM_DRTM_FEATURES_TPM: + INFO("++ DRTM service handler: TPM features\n"); + return drtm_features_tpm(handle); + break; /* not reached */ + + case ARM_DRTM_FEATURES_MEM_REQ: + INFO("++ DRTM service handler: Min. mem." + " requirement features\n"); + return drtm_features_mem_req(handle); + break; /* not reached */ + + case ARM_DRTM_FEATURES_DMA_PROT: + INFO("++ DRTM service handler: " + "DMA protection features\n"); + return drtm_features_dma_prot(handle); + break; /* not reached */ + + case ARM_DRTM_FEATURES_BOOT_PE_ID: + INFO("++ DRTM service handler: " + "Boot PE ID features\n"); + return drtm_features_boot_pe_id(handle); + break; /* not reached */ + + case ARM_DRTM_FEATURES_TCB_HASHES: + INFO("++ DRTM service handler: " + "TCB-hashes features\n"); + return drtm_features_tcb_hashes(handle); + break; /* not reached */ + + default: + ERROR("Unknown ARM DRTM service feature\n"); + SMC_RET1(handle, NOT_SUPPORTED); + break; /* not reached */ + } } case ARM_DRTM_SVC_UNPROTECT_MEM: From b9b175086ce6c20480ec6bccdcf5a784f8cc8298 Mon Sep 17 00:00:00 2001 From: Manish V Badarkhe Date: Wed, 15 Jun 2022 15:06:43 +0100 Subject: [PATCH 16/32] refactor(measured-boot): split out a few Event Log driver functions Reorganized a few Event Log functions into multiple functions so that they can be used for the upcoming DRTM feature. This change mainly implements below new functions - 1. event_log_buf_init - called by 'event_log_init' to initialise Event Log buffer 2. event_log_write_specid_event - called by 'event_log_fixed_header' to write specification id event to Event Log buffer 3. event_log_measure and event_log_record - called by 'event_log_measure_and_record' to measure and record the measurement to the Event Log buffer Change-Id: I1aabb57f79bead726fcf36d59839702cd6a3521d Signed-off-by: Manish V Badarkhe --- drivers/measured_boot/event_log/event_log.c | 82 ++++++++++++------- .../measured_boot/event_log/event_log.h | 7 ++ 2 files changed, 61 insertions(+), 28 deletions(-) diff --git a/drivers/measured_boot/event_log/event_log.c b/drivers/measured_boot/event_log/event_log.c index abe469b74..d661c35e7 100644 --- a/drivers/measured_boot/event_log/event_log.c +++ b/drivers/measured_boot/event_log/event_log.c @@ -84,23 +84,26 @@ static const event2_header_t locality_event_header = { * Record a measurement as a TCG_PCR_EVENT2 event * * @param[in] hash Pointer to hash data of TCG_DIGEST_SIZE bytes + * @param[in] event_type Type of Event, Various Event Types are + * mentioned in tcg.h header * @param[in] metadata_ptr Pointer to event_log_metadata_t structure * * There must be room for storing this new event into the event log buffer. */ -static void event_log_record(const uint8_t *hash, - const event_log_metadata_t *metadata_ptr) +void event_log_record(const uint8_t *hash, uint32_t event_type, + const event_log_metadata_t *metadata_ptr) { void *ptr = log_ptr; - uint32_t name_len; + uint32_t name_len = 0U; assert(hash != NULL); assert(metadata_ptr != NULL); - assert(metadata_ptr->name != NULL); - /* event_log_init() must have been called prior to this. */ + /* event_log_buf_init() must have been called prior to this. */ assert(log_ptr != NULL); - name_len = (uint32_t)strlen(metadata_ptr->name) + 1U; + if (metadata_ptr->name != NULL) { + name_len = (uint32_t)strlen(metadata_ptr->name) + 1U; + } /* Check for space in Event Log buffer */ assert(((uintptr_t)ptr + (uint32_t)EVENT2_HDR_SIZE + name_len) < @@ -115,7 +118,7 @@ static void event_log_record(const uint8_t *hash, ((event2_header_t *)ptr)->pcr_index = metadata_ptr->pcr; /* TCG_PCR_EVENT2.EventType */ - ((event2_header_t *)ptr)->event_type = EV_POST_CODE; + ((event2_header_t *)ptr)->event_type = event_type; /* TCG_PCR_EVENT2.Digests.Count */ ptr = (uint8_t *)ptr + offsetof(event2_header_t, digests); @@ -139,14 +142,25 @@ static void event_log_record(const uint8_t *hash, ((event2_data_t *)ptr)->event_size = name_len; /* Copy event data to TCG_PCR_EVENT2.Event */ - (void)memcpy((void *)(((event2_data_t *)ptr)->event), - (const void *)metadata_ptr->name, name_len); + if (metadata_ptr->name != NULL) { + (void)memcpy((void *)(((event2_data_t *)ptr)->event), + (const void *)metadata_ptr->name, name_len); + } /* End of event data */ log_ptr = (uint8_t *)((uintptr_t)ptr + offsetof(event2_data_t, event) + name_len); } +void event_log_buf_init(uint8_t *event_log_start, uint8_t *event_log_finish) +{ + assert(event_log_start != NULL); + assert(event_log_finish > event_log_start); + + log_ptr = event_log_start; + log_end = (uintptr_t)event_log_finish; +} + /* * Initialise Event Log global variables, used during the recording * of various payload measurements into the Event Log buffer @@ -158,30 +172,20 @@ static void event_log_record(const uint8_t *hash, */ void event_log_init(uint8_t *event_log_start, uint8_t *event_log_finish) { - assert(event_log_start != NULL); - assert(event_log_finish > event_log_start); - - log_ptr = event_log_start; - log_end = (uintptr_t)event_log_finish; + event_log_buf_init(event_log_start, event_log_finish); /* Get pointer to platform's event_log_metadata_t structure */ plat_metadata_ptr = plat_event_log_get_metadata(); assert(plat_metadata_ptr != NULL); } -/* - * Initialises Event Log by writing Specification ID and - * Startup Locality events - */ -void event_log_write_header(void) +void event_log_write_specid_event(void) { - const char locality_signature[] = TCG_STARTUP_LOCALITY_SIGNATURE; void *ptr = log_ptr; - /* event_log_init() must have been called prior to this. */ + /* event_log_buf_init() must have been called prior to this. */ assert(log_ptr != NULL); - assert(((uintptr_t)log_ptr + ID_EVENT_SIZE + LOC_EVENT_SIZE) < - log_end); + assert(((uintptr_t)log_ptr + ID_EVENT_SIZE) < log_end); /* * Add Specification ID Event first @@ -202,8 +206,23 @@ void event_log_write_header(void) * No vendor data */ ((id_event_struct_data_t *)ptr)->vendor_info_size = 0; - ptr = (uint8_t *)((uintptr_t)ptr + + log_ptr = (uint8_t *)((uintptr_t)ptr + offsetof(id_event_struct_data_t, vendor_info)); +} + +/* + * Initialises Event Log by writing Specification ID and + * Startup Locality events + */ +void event_log_write_header(void) +{ + const char locality_signature[] = TCG_STARTUP_LOCALITY_SIGNATURE; + void *ptr; + + event_log_write_specid_event(); + + ptr = log_ptr; + assert(((uintptr_t)log_ptr + LOC_EVENT_SIZE) < log_end); /* * The Startup Locality event should be placed in the log before @@ -242,6 +261,14 @@ void event_log_write_header(void) log_ptr = (uint8_t *)((uintptr_t)ptr + sizeof(startup_locality_event_t)); } +int event_log_measure(uintptr_t data_base, uint32_t data_size, + unsigned char hash_data[CRYPTO_MD_MAX_SIZE]) +{ + /* Calculate hash */ + return crypto_mod_calc_hash(CRYPTO_MD_ID, + (void *)data_base, data_size, hash_data); +} + /* * Calculate and write hash of image, configuration data, etc. * to Event Log. @@ -267,14 +294,13 @@ int event_log_measure_and_record(uintptr_t data_base, uint32_t data_size, } assert(metadata_ptr->id != EVLOG_INVALID_ID); - /* Calculate hash */ - rc = crypto_mod_calc_hash(CRYPTO_MD_ID, - (void *)data_base, data_size, hash_data); + /* Measure the payload with algorithm selected by EventLog driver */ + rc = event_log_measure(data_base, data_size, hash_data); if (rc != 0) { return rc; } - event_log_record(hash_data, metadata_ptr); + event_log_record(hash_data, EV_POST_CODE, metadata_ptr); return 0; } diff --git a/include/drivers/measured_boot/event_log/event_log.h b/include/drivers/measured_boot/event_log/event_log.h index f4c4fb810..eb0e2b129 100644 --- a/include/drivers/measured_boot/event_log/event_log.h +++ b/include/drivers/measured_boot/event_log/event_log.h @@ -11,6 +11,7 @@ #include #include +#include #include /* @@ -109,10 +110,16 @@ typedef struct { sizeof(event2_data_t)) /* Functions' declarations */ +void event_log_buf_init(uint8_t *event_log_start, uint8_t *event_log_finish); void event_log_init(uint8_t *event_log_start, uint8_t *event_log_finish); +void event_log_write_specid_event(void); void event_log_write_header(void); void dump_event_log(uint8_t *log_addr, size_t log_size); const event_log_metadata_t *plat_event_log_get_metadata(void); +int event_log_measure(uintptr_t data_base, uint32_t data_size, + unsigned char hash_data[CRYPTO_MD_MAX_SIZE]); +void event_log_record(const uint8_t *hash, uint32_t event_type, + const event_log_metadata_t *metadata_ptr); int event_log_measure_and_record(uintptr_t data_base, uint32_t data_size, uint32_t data_id); size_t event_log_get_cur_size(uint8_t *event_log_start); From bd6cc0b2388c52f2b232427be61ff52c042d724a Mon Sep 17 00:00:00 2001 From: Manish Pandey Date: Mon, 20 Jun 2022 17:42:41 +0100 Subject: [PATCH 17/32] feat(drtm): introduce drtm dynamic launch function This function is placeholder for checking all the necessary conditions before doing drtm dynamic launch. In this patch following conditions are checked (based on Table 31 of DRTM spec beta0), rest of the conditions will be added in later patches. - Only boot PE is online - Caller execution state is AArch64 - Caller exception level is NS-EL2 or NS-EL1 Signed-off-by: Manish Pandey Change-Id: I622b946bc191bb39f828831336ceafbc10834c19 --- services/std_svc/drtm/drtm_main.c | 69 ++++++++++++++++++++++++++++++- 1 file changed, 68 insertions(+), 1 deletion(-) diff --git a/services/std_svc/drtm/drtm_main.c b/services/std_svc/drtm/drtm_main.c index 867870bb5..f05a231f7 100644 --- a/services/std_svc/drtm/drtm_main.c +++ b/services/std_svc/drtm/drtm_main.c @@ -19,6 +19,7 @@ #include #include #include "drtm_main.h" +#include #include #include #include @@ -149,6 +150,72 @@ static inline uint64_t drtm_features_tcb_hashes(void *ctx) plat_drtm_features.tcb_hash_features); } +static enum drtm_retc drtm_dl_check_caller_el(void *ctx) +{ + uint64_t spsr_el3 = read_ctx_reg(get_el3state_ctx(ctx), CTX_SPSR_EL3); + uint64_t dl_caller_el; + uint64_t dl_caller_aarch; + + dl_caller_el = spsr_el3 >> MODE_EL_SHIFT & MODE_EL_MASK; + dl_caller_aarch = spsr_el3 >> MODE_RW_SHIFT & MODE_RW_MASK; + + /* Caller's security state is checked from drtm_smc_handle function */ + + /* Caller can be NS-EL2/EL1 */ + if (dl_caller_el == MODE_EL3) { + ERROR("DRTM: invalid launch from EL3\n"); + return DENIED; + } + + if (dl_caller_aarch != MODE_RW_64) { + ERROR("DRTM: invalid launch from non-AArch64 execution state\n"); + return DENIED; + } + + return SUCCESS; +} + +static enum drtm_retc drtm_dl_check_cores(void) +{ + bool running_on_single_core; + uint64_t this_pe_aff_value = read_mpidr_el1() & MPIDR_AFFINITY_MASK; + + if (this_pe_aff_value != plat_drtm_features.boot_pe_id) { + ERROR("DRTM: invalid launch on a non-boot PE\n"); + return DENIED; + } + + running_on_single_core = psci_is_last_on_cpu_safe(); + if (!running_on_single_core) { + ERROR("DRTM: invalid launch due to non-boot PE not being turned off\n"); + return DENIED; + } + + return SUCCESS; +} + +static uint64_t drtm_dynamic_launch(uint64_t x1, void *handle) +{ + enum drtm_retc ret = SUCCESS; + + /* Ensure that only boot PE is powered on */ + ret = drtm_dl_check_cores(); + if (ret != SUCCESS) { + SMC_RET1(handle, ret); + } + + /* + * Ensure that execution state is AArch64 and the caller + * is highest non-secure exception level + */ + ret = drtm_dl_check_caller_el(handle); + if (ret != SUCCESS) { + SMC_RET1(handle, ret); + } + + SMC_RET1(handle, ret); +} + uint64_t drtm_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, @@ -268,7 +335,7 @@ uint64_t drtm_smc_handler(uint32_t smc_fid, case ARM_DRTM_SVC_DYNAMIC_LAUNCH: INFO("DRTM service handler: dynamic launch\n"); - SMC_RET1(handle, SMC_OK); + return drtm_dynamic_launch(x1, handle); break; /* not reached */ case ARM_DRTM_SVC_CLOSE_LOCALITY: From 40e1fad69b9f28ab5e57cea33261bf629b05519c Mon Sep 17 00:00:00 2001 From: Manish Pandey Date: Tue, 21 Jun 2022 15:36:45 +0100 Subject: [PATCH 18/32] feat(drtm): check drtm arguments during dynamic launch Check the sanity of arguments before dynamic launch. Change-Id: Iad68f852b09851b0c55a55df6ba16576e105758a Signed-off-by: Manish Pandey Signed-off-by: Lucian Paul-Trifu --- services/std_svc/drtm/drtm_dma_prot.h | 8 ++ services/std_svc/drtm/drtm_main.c | 166 ++++++++++++++++++++++++++ services/std_svc/drtm/drtm_main.h | 39 ++++++ 3 files changed, 213 insertions(+) diff --git a/services/std_svc/drtm/drtm_dma_prot.h b/services/std_svc/drtm/drtm_dma_prot.h index e0c58b510..e9b1fe94d 100644 --- a/services/std_svc/drtm/drtm_dma_prot.h +++ b/services/std_svc/drtm/drtm_dma_prot.h @@ -9,6 +9,14 @@ #include +struct __packed drtm_dl_dma_prot_args_v1 { + uint64_t dma_prot_table_paddr; + uint64_t dma_prot_table_size; +}; + +/* Opaque / encapsulated type. */ +typedef struct drtm_dl_dma_prot_args_v1 drtm_dl_dma_prot_args_v1_t; + bool drtm_dma_prot_init(void); #endif /* DRTM_DMA_PROT_H */ diff --git a/services/std_svc/drtm/drtm_main.c b/services/std_svc/drtm/drtm_main.c index f05a231f7..d971901a7 100644 --- a/services/std_svc/drtm/drtm_main.c +++ b/services/std_svc/drtm/drtm_main.c @@ -194,9 +194,170 @@ static enum drtm_retc drtm_dl_check_cores(void) return SUCCESS; } +static enum drtm_retc drtm_dl_prepare_dlme_data(const struct_drtm_dl_args *args, + size_t *dlme_data_size_out) +{ + size_t dlme_data_total_bytes_req = 0; + + *dlme_data_size_out = dlme_data_total_bytes_req; + + return SUCCESS; +} + +/* + * Note: accesses to the dynamic launch args, and to the DLME data are + * little-endian as required, thanks to TF-A BL31 init requirements. + */ +static enum drtm_retc drtm_dl_check_args(uint64_t x1, + struct_drtm_dl_args *a_out) +{ + uint64_t dlme_start, dlme_end; + uint64_t dlme_img_start, dlme_img_ep, dlme_img_end; + uint64_t dlme_data_start, dlme_data_end; + uintptr_t args_mapping; + size_t args_mapping_size; + struct_drtm_dl_args *a; + struct_drtm_dl_args args_buf; + size_t dlme_data_size_req; + int rc; + + if (x1 % DRTM_PAGE_SIZE != 0) { + ERROR("DRTM: parameters structure is not " + DRTM_PAGE_SIZE_STR "-aligned\n"); + return INVALID_PARAMETERS; + } + + args_mapping_size = ALIGNED_UP(sizeof(struct_drtm_dl_args), DRTM_PAGE_SIZE); + rc = mmap_add_dynamic_region_alloc_va(x1, &args_mapping, args_mapping_size, + MT_MEMORY | MT_NS | MT_RO | + MT_SHAREABILITY_ISH); + if (rc != 0) { + WARN("DRTM: %s: mmap_add_dynamic_region() failed rc=%d\n", + __func__, rc); + return INTERNAL_ERROR; + } + a = (struct_drtm_dl_args *)args_mapping; + /* + * TODO: invalidate all data cache before reading the data passed by the + * DCE Preamble. This is required to avoid / defend against racing with + * cache evictions. + */ + args_buf = *a; + + rc = mmap_remove_dynamic_region(args_mapping, args_mapping_size); + if (rc) { + ERROR("%s(): mmap_remove_dynamic_region() failed unexpectedly" + " rc=%d\n", __func__, rc); + panic(); + } + a = &args_buf; + + if (a->version != 1) { + ERROR("DRTM: parameters structure incompatible with major version %d\n", + ARM_DRTM_VERSION_MAJOR); + return NOT_SUPPORTED; + } + + if (!(a->dlme_img_off < a->dlme_size && + a->dlme_data_off < a->dlme_size)) { + ERROR("DRTM: argument offset is outside of the DLME region\n"); + return INVALID_PARAMETERS; + } + dlme_start = a->dlme_paddr; + dlme_end = a->dlme_paddr + a->dlme_size; + dlme_img_start = a->dlme_paddr + a->dlme_img_off; + dlme_img_ep = dlme_img_start + a->dlme_img_ep_off; + dlme_img_end = dlme_img_start + a->dlme_img_size; + dlme_data_start = a->dlme_paddr + a->dlme_data_off; + dlme_data_end = dlme_end; + + /* + * TODO: validate that the DLME physical address range is all NS memory, + * return INVALID_PARAMETERS if it is not. + * Note that this check relies on platform-specific information. For + * examples, see psci_plat_pm_ops->validate_ns_entrypoint() or + * arm_validate_ns_entrypoint(). + */ + + /* Check the DLME regions arguments. */ + if ((dlme_start % DRTM_PAGE_SIZE) != 0) { + ERROR("DRTM: argument DLME region is not " + DRTM_PAGE_SIZE_STR "-aligned\n"); + return INVALID_PARAMETERS; + } + + if (!(dlme_start < dlme_end && + dlme_start <= dlme_img_start && dlme_img_start < dlme_img_end && + dlme_start <= dlme_data_start && dlme_data_start < dlme_data_end)) { + ERROR("DRTM: argument DLME region is discontiguous\n"); + return INVALID_PARAMETERS; + } + + if (dlme_img_start < dlme_data_end && dlme_data_start < dlme_img_end) { + ERROR("DRTM: argument DLME regions overlap\n"); + return INVALID_PARAMETERS; + } + + /* Check the DLME image region arguments. */ + if ((dlme_img_start % DRTM_PAGE_SIZE) != 0) { + ERROR("DRTM: argument DLME image region is not " + DRTM_PAGE_SIZE_STR "-aligned\n"); + return INVALID_PARAMETERS; + } + + if (!(dlme_img_start <= dlme_img_ep && dlme_img_ep < dlme_img_end)) { + ERROR("DRTM: DLME entry point is outside of the DLME image region\n"); + return INVALID_PARAMETERS; + } + + if ((dlme_img_ep % 4) != 0) { + ERROR("DRTM: DLME image entry point is not 4-byte-aligned\n"); + return INVALID_PARAMETERS; + } + + /* Check the DLME data region arguments. */ + if ((dlme_data_start % DRTM_PAGE_SIZE) != 0) { + ERROR("DRTM: argument DLME data region is not " + DRTM_PAGE_SIZE_STR "-aligned\n"); + return INVALID_PARAMETERS; + } + + rc = drtm_dl_prepare_dlme_data(NULL, &dlme_data_size_req); + if (rc) { + ERROR("%s: drtm_dl_prepare_dlme_data() failed unexpectedly rc=%d\n", + __func__, rc); + panic(); + } + if (dlme_data_end - dlme_data_start < dlme_data_size_req) { + ERROR("DRTM: argument DLME data region is short of %lu bytes\n", + dlme_data_size_req - (size_t)(dlme_data_end - dlme_data_start)); + return INVALID_PARAMETERS; + } + + /* Check the Normal World DCE region arguments. */ + if (a->dce_nwd_paddr != 0) { + uint32_t dce_nwd_start = a->dce_nwd_paddr; + uint32_t dce_nwd_end = dce_nwd_start + a->dce_nwd_size; + + if (!(dce_nwd_start < dce_nwd_end)) { + ERROR("DRTM: argument Normal World DCE region is dicontiguous\n"); + return INVALID_PARAMETERS; + } + + if (dce_nwd_start < dlme_end && dlme_start < dce_nwd_end) { + ERROR("DRTM: argument Normal World DCE regions overlap\n"); + return INVALID_PARAMETERS; + } + } + + *a_out = *a; + return SUCCESS; +} + static uint64_t drtm_dynamic_launch(uint64_t x1, void *handle) { enum drtm_retc ret = SUCCESS; + struct_drtm_dl_args args; /* Ensure that only boot PE is powered on */ ret = drtm_dl_check_cores(); @@ -213,6 +374,11 @@ static uint64_t drtm_dynamic_launch(uint64_t x1, void *handle) SMC_RET1(handle, ret); } + ret = drtm_dl_check_args(x1, &args); + if (ret != SUCCESS) { + SMC_RET1(handle, ret); + } + SMC_RET1(handle, ret); } diff --git a/services/std_svc/drtm/drtm_main.h b/services/std_svc/drtm/drtm_main.h index b60d95458..59e56080a 100644 --- a/services/std_svc/drtm/drtm_main.h +++ b/services/std_svc/drtm/drtm_main.h @@ -9,10 +9,28 @@ #include +#include #include #include "drtm_dma_prot.h" +#define ALIGNED_UP(x, a) __extension__ ({ \ + __typeof__(a) _a = (a); \ + __typeof__(a) _one = 1; \ + assert(IS_POWER_OF_TWO(_a)); \ + ((x) + (_a - _one)) & ~(_a - _one); \ +}) + +#define ALIGNED_DOWN(x, a) __extension__ ({ \ + __typeof__(a) _a = (a); \ + __typeof__(a) _one = 1; \ + assert(IS_POWER_OF_TWO(_a)); \ + (x) & ~(_a - _one); \ +}) + +#define DRTM_PAGE_SIZE (4 * (1 << 10)) +#define DRTM_PAGE_SIZE_STR "4-KiB" + enum drtm_retc { SUCCESS = SMC_OK, NOT_SUPPORTED = SMC_UNK, @@ -31,7 +49,28 @@ typedef struct { uint64_t tcb_hash_features; } drtm_features_t; +struct __packed drtm_dl_args_v1 { + uint16_t version; /* Must be 1. */ + uint8_t __res[2]; + uint32_t features; + uint64_t dlme_paddr; + uint64_t dlme_size; + uint64_t dlme_img_off; + uint64_t dlme_img_ep_off; + uint64_t dlme_img_size; + uint64_t dlme_data_off; + uint64_t dce_nwd_paddr; + uint64_t dce_nwd_size; + drtm_dl_dma_prot_args_v1_t dma_prot_args; +} __aligned(__alignof(uint16_t /* First member's type, `uint16_t version' */)); + drtm_memory_region_descriptor_table_t *drtm_build_address_map(void); uint64_t drtm_get_address_map_size(void); +/* + * Version-independent type. May be used to avoid excessive line of code + * changes when migrating to new struct versions. + */ +typedef struct drtm_dl_args_v1 struct_drtm_dl_args; + #endif /* DRTM_MAIN_H */ From 40814266d53b7154daf5d212de481b397db43823 Mon Sep 17 00:00:00 2001 From: Manish V Badarkhe Date: Fri, 17 Jun 2022 11:42:17 +0100 Subject: [PATCH 19/32] feat(drtm): add Event Log driver support for DRTM Added Event Log driver support for DRTM. This driver is responsible for the doing the hash measurement of various DRTM components as per [1], and putting these measurements in the Event Log buffer. [1]: https://developer.arm.com/documentation/den0113/a, section 3.16 Change-Id: I9892c313cf6640b82e261738116fe00f7975ee12 Signed-off-by: Manish V Badarkhe --- bl31/bl31.mk | 1 + plat/arm/common/arm_common.mk | 12 +- services/std_svc/drtm/drtm_main.h | 4 + services/std_svc/drtm/drtm_measurements.c | 214 ++++++++++++++++++++++ services/std_svc/drtm/drtm_measurements.h | 40 ++++ 5 files changed, 268 insertions(+), 3 deletions(-) create mode 100644 services/std_svc/drtm/drtm_measurements.c create mode 100644 services/std_svc/drtm/drtm_measurements.h diff --git a/bl31/bl31.mk b/bl31/bl31.mk index f435815ce..9f7d96e86 100644 --- a/bl31/bl31.mk +++ b/bl31/bl31.mk @@ -151,6 +151,7 @@ ifeq (${DRTM_SUPPORT},1) BL31_SOURCES += services/std_svc/drtm/drtm_main.c \ services/std_svc/drtm/drtm_dma_prot.c \ services/std_svc/drtm/drtm_res_address_map.c \ + services/std_svc/drtm/drtm_measurements.c \ ${MBEDTLS_SOURCES} endif diff --git a/plat/arm/common/arm_common.mk b/plat/arm/common/arm_common.mk index 5dda4853b..ccf2b4597 100644 --- a/plat/arm/common/arm_common.mk +++ b/plat/arm/common/arm_common.mk @@ -406,7 +406,7 @@ endif # Include Measured Boot makefile before any Crypto library makefile. # Crypto library makefile may need default definitions of Measured Boot build # flags present in Measured Boot makefile. -ifeq (${MEASURED_BOOT},1) +ifneq ($(filter 1,${MEASURED_BOOT} ${DRTM_SUPPORT}),) MEASURED_BOOT_MK := drivers/measured_boot/event_log/event_log.mk $(info Including ${MEASURED_BOOT_MK}) include ${MEASURED_BOOT_MK} @@ -415,8 +415,14 @@ ifeq (${MEASURED_BOOT},1) $(eval $(call add_define,TF_MBEDTLS_MBOOT_USE_SHA512)) endif - BL1_SOURCES += ${EVENT_LOG_SOURCES} - BL2_SOURCES += ${EVENT_LOG_SOURCES} + ifeq (${MEASURED_BOOT},1) + BL1_SOURCES += ${EVENT_LOG_SOURCES} + BL2_SOURCES += ${EVENT_LOG_SOURCES} + endif + + ifeq (${DRTM_SUPPORT},1) + BL31_SOURCES += ${EVENT_LOG_SOURCES} + endif endif ifneq ($(filter 1,${MEASURED_BOOT} ${TRUSTED_BOARD_BOOT} ${DRTM_SUPPORT}),) diff --git a/services/std_svc/drtm/drtm_main.h b/services/std_svc/drtm/drtm_main.h index 59e56080a..cccc14f96 100644 --- a/services/std_svc/drtm/drtm_main.h +++ b/services/std_svc/drtm/drtm_main.h @@ -31,6 +31,10 @@ #define DRTM_PAGE_SIZE (4 * (1 << 10)) #define DRTM_PAGE_SIZE_STR "4-KiB" +#define DL_ARGS_GET_PCR_SCHEMA(a) (((a)->features >> 1) & 0x3U) +#define DL_ARGS_GET_DLME_ENTRY_POINT(a) \ + (((a)->dlme_paddr + (a)->dlme_img_off + (a)->dlme_img_ep_off)) + enum drtm_retc { SUCCESS = SMC_OK, NOT_SUPPORTED = SMC_UNK, diff --git a/services/std_svc/drtm/drtm_measurements.c b/services/std_svc/drtm/drtm_measurements.c new file mode 100644 index 000000000..a8f2b3267 --- /dev/null +++ b/services/std_svc/drtm/drtm_measurements.c @@ -0,0 +1,214 @@ +/* + * 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 commponents + * 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); +} diff --git a/services/std_svc/drtm/drtm_measurements.h b/services/std_svc/drtm/drtm_measurements.h new file mode 100644 index 000000000..6d7a84e93 --- /dev/null +++ b/services/std_svc/drtm/drtm_measurements.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2022 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ +#ifndef DRTM_MEASUREMENTS_H +#define DRTM_MEASUREMENTS_H + +#include + +#include "drtm_main.h" +#include + +#define DRTM_EVENT_ARM_BASE 0x9000U +#define DRTM_EVENT_TYPE(n) (DRTM_EVENT_ARM_BASE + (unsigned int)(n)) + +#define DRTM_EVENT_ARM_PCR_SCHEMA DRTM_EVENT_TYPE(1) +#define DRTM_EVENT_ARM_DCE DRTM_EVENT_TYPE(2) +#define DRTM_EVENT_ARM_DCE_PUBKEY DRTM_EVENT_TYPE(3) +#define DRTM_EVENT_ARM_DLME DRTM_EVENT_TYPE(4) +#define DRTM_EVENT_ARM_DLME_EP DRTM_EVENT_TYPE(5) +#define DRTM_EVENT_ARM_DEBUG_CONFIG DRTM_EVENT_TYPE(6) +#define DRTM_EVENT_ARM_NONSECURE_CONFIG DRTM_EVENT_TYPE(7) +#define DRTM_EVENT_ARM_DCE_SECONDARY DRTM_EVENT_TYPE(8) +#define DRTM_EVENT_ARM_TZFW DRTM_EVENT_TYPE(9) +#define DRTM_EVENT_ARM_SEPARATOR DRTM_EVENT_TYPE(10) + +#define CHECK_RC(rc, func_call) { \ + if (rc != 0) { \ + ERROR("%s(): " #func_call "failed unexpectedly rc=%d\n", \ + __func__, rc); \ + panic(); \ + } \ +} + +enum drtm_retc drtm_take_measurements(const struct_drtm_dl_args *a); +void drtm_serialise_event_log(uint8_t *dst, size_t *event_log_size_out); + +#endif /* DRTM_MEASUREMENTS_H */ From 586f60cc571f0f3b6d20eb5033717e9b0cc66af4 Mon Sep 17 00:00:00 2001 From: Manish V Badarkhe Date: Tue, 12 Jul 2022 21:48:04 +0100 Subject: [PATCH 20/32] feat(fvp): add plat API to set and get the DRTM error Added a platform function to set and get DRTM error. Also, added a platform function to reset the system. Signed-off-by: Manish V Badarkhe Change-Id: I471f2387f8c78b21a06af063a6fa02cda3646557 --- include/plat/arm/common/plat_arm.h | 1 + include/plat/common/plat_drtm.h | 4 ++++ include/plat/common/platform.h | 1 + plat/arm/board/fvp/fvp_drtm_err.c | 22 ++++++++++++++++++++++ plat/arm/board/fvp/fvp_err.c | 12 ++++++++++++ plat/arm/board/fvp/platform.mk | 7 +++++-- plat/arm/common/arm_common.mk | 4 ++++ plat/arm/common/arm_err.c | 5 +++++ 8 files changed, 54 insertions(+), 2 deletions(-) create mode 100644 plat/arm/board/fvp/fvp_drtm_err.c diff --git a/include/plat/arm/common/plat_arm.h b/include/plat/arm/common/plat_arm.h index d06033286..6c0d91d1f 100644 --- a/include/plat/arm/common/plat_arm.h +++ b/include/plat/arm/common/plat_arm.h @@ -297,6 +297,7 @@ void plat_arm_interconnect_exit_coherency(void); void plat_arm_program_trusted_mailbox(uintptr_t address); bool plat_arm_bl1_fwu_needed(void); __dead2 void plat_arm_error_handler(int err); +__dead2 void plat_arm_system_reset(void); /* * Optional functions in ARM standard platforms diff --git a/include/plat/common/plat_drtm.h b/include/plat/common/plat_drtm.h index e9b8d6a70..754fa1a40 100644 --- a/include/plat/common/plat_drtm.h +++ b/include/plat/common/plat_drtm.h @@ -60,4 +60,8 @@ uint64_t plat_drtm_get_tcb_hash_table_size(void); uint64_t plat_drtm_get_imp_def_dlme_region_size(void); uint64_t plat_drtm_get_tcb_hash_features(void); +/* DRTM error handling functions */ +int plat_set_drtm_error(uint64_t error_code); +int plat_get_drtm_error(uint64_t *error_code); + #endif /* PLAT_DRTM_H */ diff --git a/include/plat/common/platform.h b/include/plat/common/platform.h index 58e08d4aa..c90441c67 100644 --- a/include/plat/common/platform.h +++ b/include/plat/common/platform.h @@ -128,6 +128,7 @@ int plat_crash_console_putc(int c); void plat_crash_console_flush(void); void plat_error_handler(int err) __dead2; void plat_panic_handler(void) __dead2; +void plat_system_reset(void) __dead2; const char *plat_log_get_prefix(unsigned int log_level); void bl2_plat_preload_setup(void); int plat_try_next_boot_source(void); diff --git a/plat/arm/board/fvp/fvp_drtm_err.c b/plat/arm/board/fvp/fvp_drtm_err.c new file mode 100644 index 000000000..95259fa82 --- /dev/null +++ b/plat/arm/board/fvp/fvp_drtm_err.c @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +int plat_set_drtm_error(uint64_t error_code) +{ + /* TODO: Set DRTM error in NV-storage */ + return 0; +} + +int plat_get_drtm_error(uint64_t *error_code) +{ + /* TODO: Get DRTM error from NV-storage */ + *error_code = 0; + return 0; +} diff --git a/plat/arm/board/fvp/fvp_err.c b/plat/arm/board/fvp/fvp_err.c index 1f9f0dd14..244659ab7 100644 --- a/plat/arm/board/fvp/fvp_err.c +++ b/plat/arm/board/fvp/fvp_err.c @@ -29,3 +29,15 @@ __dead2 void plat_arm_error_handler(int err) for (;;) wfi(); } + +void __dead2 plat_arm_system_reset(void) +{ + /* Write the System Configuration Control Register */ + mmio_write_32(V2M_SYSREGS_BASE + V2M_SYS_CFGCTRL, + V2M_CFGCTRL_START | + V2M_CFGCTRL_RW | + V2M_CFGCTRL_FUNC(V2M_FUNC_REBOOT)); + wfi(); + ERROR("FVP System Reset: operation not handled.\n"); + panic(); +} diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk index eb2b5e517..5a21ff666 100644 --- a/plat/arm/board/fvp/platform.mk +++ b/plat/arm/board/fvp/platform.mk @@ -414,10 +414,13 @@ endif endif ifeq (${DRTM_SUPPORT}, 1) -BL31_SOURCES += plat/arm/board/fvp/fvp_drtm_dma_prot.c \ +BL31_SOURCES += plat/arm/board/fvp/fvp_drtm_addr.c \ + plat/arm/board/fvp/fvp_drtm_dma_prot.c \ + plat/arm/board/fvp/fvp_drtm_err.c \ plat/arm/board/fvp/fvp_drtm_measurement.c \ plat/arm/board/fvp/fvp_drtm_stub.c \ - plat/arm/common/arm_dyn_cfg.c + plat/arm/common/arm_dyn_cfg.c \ + plat/arm/board/fvp/fvp_err.c endif ifeq (${TRUSTED_BOARD_BOOT}, 1) diff --git a/plat/arm/common/arm_common.mk b/plat/arm/common/arm_common.mk index ccf2b4597..6f3b889c3 100644 --- a/plat/arm/common/arm_common.mk +++ b/plat/arm/common/arm_common.mk @@ -363,6 +363,10 @@ BL31_SOURCES += plat/common/plat_spmd_manifest.c \ BL31_SOURCES += ${FDT_WRAPPERS_SOURCES} endif +ifeq (${DRTM_SUPPORT},1) +BL31_SOURCES += plat/arm/common/arm_err.c +endif + ifneq (${TRUSTED_BOARD_BOOT},0) # Include common TBB sources diff --git a/plat/arm/common/arm_err.c b/plat/arm/common/arm_err.c index f80ba78c7..fa36e8d3a 100644 --- a/plat/arm/common/arm_err.c +++ b/plat/arm/common/arm_err.c @@ -13,3 +13,8 @@ void __dead2 plat_error_handler(int err) { plat_arm_error_handler(err); } + +void __dead2 plat_system_reset(void) +{ + plat_arm_system_reset(); +} From 1436e37dcb894a539a22da48a34ef01566ae728b Mon Sep 17 00:00:00 2001 From: Manish V Badarkhe Date: Tue, 21 Jun 2022 09:41:32 +0100 Subject: [PATCH 21/32] feat(drtm): add remediation driver support in DRTM Added remediation driver for DRTM to set/get the error from non-volatile memory Change-Id: I8f0873dcef4936693e0f39a3c95096cb689c04b7 Signed-off-by: Manish V Badarkhe Signed-off-by: Lucian Paul-Trifu --- bl31/bl31.mk | 1 + services/std_svc/drtm/drtm_main.c | 5 +- services/std_svc/drtm/drtm_remediation.c | 59 ++++++++++++++++++++++++ services/std_svc/drtm/drtm_remediation.h | 15 ++++++ 4 files changed, 78 insertions(+), 2 deletions(-) create mode 100644 services/std_svc/drtm/drtm_remediation.c create mode 100644 services/std_svc/drtm/drtm_remediation.h diff --git a/bl31/bl31.mk b/bl31/bl31.mk index 9f7d96e86..4c93a55ad 100644 --- a/bl31/bl31.mk +++ b/bl31/bl31.mk @@ -152,6 +152,7 @@ BL31_SOURCES += services/std_svc/drtm/drtm_main.c \ services/std_svc/drtm/drtm_dma_prot.c \ services/std_svc/drtm/drtm_res_address_map.c \ services/std_svc/drtm/drtm_measurements.c \ + services/std_svc/drtm/drtm_remediation.c \ ${MBEDTLS_SOURCES} endif diff --git a/services/std_svc/drtm/drtm_main.c b/services/std_svc/drtm/drtm_main.c index d971901a7..9878887e5 100644 --- a/services/std_svc/drtm/drtm_main.c +++ b/services/std_svc/drtm/drtm_main.c @@ -19,6 +19,7 @@ #include #include #include "drtm_main.h" +#include "drtm_remediation.h" #include #include #include @@ -512,12 +513,12 @@ uint64_t drtm_smc_handler(uint32_t smc_fid, case ARM_DRTM_SVC_GET_ERROR: INFO("DRTM service handler: get error\n"); - SMC_RET2(handle, SMC_OK, 0); + drtm_get_error(handle); break; /* not reached */ case ARM_DRTM_SVC_SET_ERROR: INFO("DRTM service handler: set error\n"); - SMC_RET1(handle, SMC_OK); + drtm_set_error(x1, handle); break; /* not reached */ case ARM_DRTM_SVC_SET_TCB_HASH: diff --git a/services/std_svc/drtm/drtm_remediation.c b/services/std_svc/drtm/drtm_remediation.c new file mode 100644 index 000000000..696b4ea6a --- /dev/null +++ b/services/std_svc/drtm/drtm_remediation.c @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2022 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * DRTM support for DRTM error remediation. + * + */ +#include +#include + +#include +#include +#include "drtm_main.h" +#include + +uint64_t drtm_set_error(uint64_t x1, void *ctx) +{ + int rc; + + rc = plat_set_drtm_error(x1); + + if (rc != 0) { + SMC_RET1(ctx, INTERNAL_ERROR); + } + + SMC_RET1(ctx, SUCCESS); +} + +uint64_t drtm_get_error(void *ctx) +{ + uint64_t error_code; + int rc; + + rc = plat_get_drtm_error(&error_code); + + if (rc != 0) { + SMC_RET1(ctx, INTERNAL_ERROR); + } + + SMC_RET2(ctx, SUCCESS, error_code); +} + +void drtm_enter_remediation(uint64_t err_code, const char *err_str) +{ + int rc = plat_set_drtm_error(err_code); + + if (rc != 0) { + ERROR("%s(): drtm_error_set() failed unexpectedly rc=%d\n", + __func__, rc); + panic(); + } + + ERROR("DRTM: entering remediation of error:\n%" PRIu64 "\t\'%s\'\n", + err_code, err_str); + + ERROR("%s(): system reset is not yet supported\n", __func__); + plat_system_reset(); +} diff --git a/services/std_svc/drtm/drtm_remediation.h b/services/std_svc/drtm/drtm_remediation.h new file mode 100644 index 000000000..8f965f1cd --- /dev/null +++ b/services/std_svc/drtm/drtm_remediation.h @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2022 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ +#ifndef DRTM_REMEDIATION_H +#define DRTM_REMEDIATION_H + +uint64_t drtm_set_error(uint64_t x1, void *ctx); +uint64_t drtm_get_error(void *ctx); + +void drtm_enter_remediation(uint64_t error_code, const char *error_str); + +#endif /* DRTM_REMEDIATION_H */ From 2b13a985994213f766ada197427f96e064f1b59b Mon Sep 17 00:00:00 2001 From: Manish V Badarkhe Date: Tue, 21 Jun 2022 18:08:50 +0100 Subject: [PATCH 22/32] feat(drtm): add a few DRTM DMA protection APIs Added DRTM DMA protections APIs, and called them during the DLME launch and DRTM SMC handling. Change-Id: I29e7238c04e2ca9f26600276c5c05bff5387789e Signed-off-by: Manish V Badarkhe --- services/std_svc/drtm/drtm_dma_prot.c | 204 +++++++++++++++++++++++++- services/std_svc/drtm/drtm_dma_prot.h | 28 ++++ services/std_svc/drtm/drtm_main.c | 14 +- services/std_svc/drtm/drtm_main.h | 1 + 4 files changed, 245 insertions(+), 2 deletions(-) diff --git a/services/std_svc/drtm/drtm_dma_prot.c b/services/std_svc/drtm/drtm_dma_prot.c index 9d014a0c3..48317fdc4 100644 --- a/services/std_svc/drtm/drtm_dma_prot.c +++ b/services/std_svc/drtm/drtm_dma_prot.c @@ -14,9 +14,30 @@ #include #include - +#include #include "drtm_dma_prot.h" +#include "drtm_main.h" +#include "drtm_remediation.h" #include +#include + +/* + * ________________________ LAUNCH success ________________________ + * | Initial | -------------------> | Prot engaged | + * |````````````````````````| |````````````````````````| + * | request.type == NONE | | request.type != NONE | + * | | <------------------- | | + * `________________________' UNPROTECT_MEM `________________________' + * + * Transitions that are not shown correspond to ABI calls that do not change + * state and result in an error being returned to the caller. + */ +static struct dma_prot active_prot = { + .type = PROTECT_NONE, +}; + +/* Version-independent type. */ +typedef struct drtm_dl_dma_prot_args_v1 struct_drtm_dl_dma_prot_args; /* * This function checks that platform supports complete DMA protection. @@ -59,3 +80,184 @@ bool drtm_dma_prot_init(void) return must_init_fail; } + +/* + * Checks that the DMA protection arguments are valid and that the given + * protected regions are covered by DMA protection. + */ +enum drtm_retc drtm_dma_prot_check_args(const struct_drtm_dl_dma_prot_args *a, + int a_dma_prot_type, + drtm_mem_region_t p) +{ + switch ((enum dma_prot_type)a_dma_prot_type) { + case PROTECT_MEM_ALL: + if (a->dma_prot_table_paddr || a->dma_prot_table_size) { + ERROR("DRTM: invalid launch due to inconsistent" + " DMA protection arguments\n"); + return MEM_PROTECT_INVALID; + } + /* + * Full DMA protection ought to ensure that the DLME and NWd + * DCE regions are protected, no further checks required. + */ + return SUCCESS; + + default: + ERROR("DRTM: invalid launch due to unsupported DMA protection type\n"); + return MEM_PROTECT_INVALID; + } +} + +enum drtm_retc drtm_dma_prot_engage(const struct_drtm_dl_dma_prot_args *a, + int a_dma_prot_type) +{ + const uintptr_t *smmus; + size_t num_smmus = 0; + + if (active_prot.type != PROTECT_NONE) { + ERROR("DRTM: launch denied as previous DMA protection" + " is still engaged\n"); + return DENIED; + } + + if (a_dma_prot_type == PROTECT_NONE) { + return SUCCESS; + /* Only PROTECT_MEM_ALL is supported currently. */ + } else if (a_dma_prot_type != PROTECT_MEM_ALL) { + ERROR("%s(): unimplemented DMA protection type\n", __func__); + panic(); + } + + /* + * Engage SMMUs in accordance with the request we have previously received. + * Only PROTECT_MEM_ALL is implemented currently. + */ + plat_enumerate_smmus(&smmus, &num_smmus); + for (const uintptr_t *smmu = smmus; smmu < smmus+num_smmus; smmu++) { + /* + * TODO: Invalidate SMMU's Stage-1 and Stage-2 TLB entries. This ensures + * that any outstanding device transactions are completed, see Section + * 3.21.1, specification IHI_0070_C_a for an approximate reference. + */ + int rc = smmuv3_ns_set_abort_all(*smmu); + if (rc != 0) { + ERROR("DRTM: SMMU at PA 0x%lx failed to engage DMA protection" + " rc=%d\n", *smmu, rc); + return INTERNAL_ERROR; + } + } + + /* + * TODO: Restrict DMA from the GIC. + * + * Full DMA protection may be achieved as follows: + * + * With a GICv3: + * - Set GICR_CTLR.EnableLPIs to 0, for each GICR; + * GICR_CTLR.RWP == 0 must be the case before finishing, for each GICR. + * - Set GITS_CTLR.Enabled to 0; + * GITS_CTLR.Quiescent == 1 must be the case before finishing. + * + * In addition, with a GICv4: + * - Set GICR_VPENDBASER.Valid to 0, for each GICR; + * GICR_CTLR.RWP == 0 must be the case before finishing, for each GICR. + * + * Alternatively, e.g. if some bit values cannot be changed at runtime, + * this procedure should return an error if the LPI Pending and + * Configuration tables overlap the regions being protected. + */ + + active_prot.type = a_dma_prot_type; + + return SUCCESS; +} + +/* + * Undo what has previously been done in drtm_dma_prot_engage(), or enter + * remediation if it is not possible. + */ +enum drtm_retc drtm_dma_prot_disengage(void) +{ + const uintptr_t *smmus; + size_t num_smmus = 0; + const char *err_str = "cannot undo PROTECT_MEM_ALL SMMU config"; + + if (active_prot.type == PROTECT_NONE) { + return SUCCESS; + /* Only PROTECT_MEM_ALL is supported currently. */ + } else if (active_prot.type != PROTECT_MEM_ALL) { + ERROR("%s(): unimplemented DMA protection type\n", __func__); + panic(); + } + + /* + * For PROTECT_MEM_ALL, undo the SMMU configuration for "abort all" mode + * done during engage(). + */ + /* Simply enter remediation for now. */ + (void)smmus; + (void)num_smmus; + drtm_enter_remediation(1ULL, err_str); + + /* TODO: Undo GIC DMA restrictions. */ + + active_prot.type = PROTECT_NONE; + + return SUCCESS; +} + +uint64_t drtm_unprotect_mem(void *ctx) +{ + enum drtm_retc ret; + + switch (active_prot.type) { + case PROTECT_NONE: + ERROR("DRTM: invalid UNPROTECT_MEM, no DMA protection has" + " previously been engaged\n"); + ret = DENIED; + break; + + case PROTECT_MEM_ALL: + /* + * UNPROTECT_MEM is a no-op for PROTECT_MEM_ALL: DRTM must not touch + * the NS SMMU as it is expected that the DLME has configured it. + */ + active_prot.type = PROTECT_NONE; + + ret = SUCCESS; + break; + + default: + ret = drtm_dma_prot_disengage(); + break; + } + + SMC_RET1(ctx, ret); +} + +void drtm_dma_prot_serialise_table(uint8_t *dst, size_t *size_out) +{ + if (active_prot.type == PROTECT_NONE) { + return; + } else if (active_prot.type != PROTECT_MEM_ALL) { + ERROR("%s(): unimplemented DMA protection type\n", __func__); + panic(); + } + + struct __packed descr_table_1 { + drtm_memory_region_descriptor_table_t header; + drtm_mem_region_t regions[1]; + } prot_table = { + .header = { + .revision = 1, + .num_regions = sizeof(((struct descr_table_1 *)NULL)->regions) / + sizeof(((struct descr_table_1 *)NULL)->regions[0]) + }, + .regions = { + {.region_address = 0, PAGES_AND_TYPE(UINT64_MAX, 0x3)}, + } + }; + + memcpy(dst, &prot_table, sizeof(prot_table)); + *size_out = sizeof(prot_table); +} diff --git a/services/std_svc/drtm/drtm_dma_prot.h b/services/std_svc/drtm/drtm_dma_prot.h index e9b1fe94d..79dc9cb49 100644 --- a/services/std_svc/drtm/drtm_dma_prot.h +++ b/services/std_svc/drtm/drtm_dma_prot.h @@ -8,15 +8,43 @@ #define DRTM_DMA_PROT_H #include +#include +#include struct __packed drtm_dl_dma_prot_args_v1 { uint64_t dma_prot_table_paddr; uint64_t dma_prot_table_size; }; +/* Values for DRTM_PROTECT_MEMORY */ +enum dma_prot_type { + PROTECT_NONE = -1, + PROTECT_MEM_ALL = 0, + PROTECT_MEM_REGION = 2, +}; + +struct dma_prot { + enum dma_prot_type type; +}; + +#define DRTM_MEM_REGION_PAGES_AND_TYPE(pages, type) \ + (((uint64_t)(pages) & (((uint64_t)1 << 52) - 1)) \ + | (((uint64_t)(type) & 0x7) << 52)) + +#define PAGES_AND_TYPE(pages, type) \ + .region_size_type = DRTM_MEM_REGION_PAGES_AND_TYPE(pages, type) + /* Opaque / encapsulated type. */ typedef struct drtm_dl_dma_prot_args_v1 drtm_dl_dma_prot_args_v1_t; bool drtm_dma_prot_init(void); +enum drtm_retc drtm_dma_prot_check_args(const drtm_dl_dma_prot_args_v1_t *a, + int a_dma_prot_type, + drtm_mem_region_t p); +enum drtm_retc drtm_dma_prot_engage(const drtm_dl_dma_prot_args_v1_t *a, + int a_dma_prot_type); +enum drtm_retc drtm_dma_prot_disengage(void); +uint64_t drtm_unprotect_mem(void *ctx); +void drtm_dma_prot_serialise_table(uint8_t *dst, size_t *size_out); #endif /* DRTM_DMA_PROT_H */ diff --git a/services/std_svc/drtm/drtm_main.c b/services/std_svc/drtm/drtm_main.c index 9878887e5..53aafeb4b 100644 --- a/services/std_svc/drtm/drtm_main.c +++ b/services/std_svc/drtm/drtm_main.c @@ -358,6 +358,7 @@ static enum drtm_retc drtm_dl_check_args(uint64_t x1, static uint64_t drtm_dynamic_launch(uint64_t x1, void *handle) { enum drtm_retc ret = SUCCESS; + enum drtm_retc dma_prot_ret; struct_drtm_dl_args args; /* Ensure that only boot PE is powered on */ @@ -380,6 +381,17 @@ static uint64_t drtm_dynamic_launch(uint64_t x1, void *handle) SMC_RET1(handle, ret); } + /* + * Engage the DMA protections. The launch cannot proceed without the DMA + * protections due to potential TOC/TOU vulnerabilities w.r.t. the DLME + * region (and to the NWd DCE region). + */ + ret = drtm_dma_prot_engage(&args.dma_prot_args, + DL_ARGS_GET_DMA_PROT_TYPE(&args)); + if (ret != SUCCESS) { + SMC_RET1(handle, ret); + } + SMC_RET1(handle, ret); } @@ -497,7 +509,7 @@ uint64_t drtm_smc_handler(uint32_t smc_fid, case ARM_DRTM_SVC_UNPROTECT_MEM: INFO("DRTM service handler: unprotect mem\n"); - SMC_RET1(handle, SMC_OK); + return drtm_unprotect_mem(handle); break; /* not reached */ case ARM_DRTM_SVC_DYNAMIC_LAUNCH: diff --git a/services/std_svc/drtm/drtm_main.h b/services/std_svc/drtm/drtm_main.h index cccc14f96..9bf5400b8 100644 --- a/services/std_svc/drtm/drtm_main.h +++ b/services/std_svc/drtm/drtm_main.h @@ -31,6 +31,7 @@ #define DRTM_PAGE_SIZE (4 * (1 << 10)) #define DRTM_PAGE_SIZE_STR "4-KiB" +#define DL_ARGS_GET_DMA_PROT_TYPE(a) (((a)->features >> 3) & 0x7U) #define DL_ARGS_GET_PCR_SCHEMA(a) (((a)->features >> 1) & 0x3U) #define DL_ARGS_GET_DLME_ENTRY_POINT(a) \ (((a)->dlme_paddr + (a)->dlme_img_off + (a)->dlme_img_ep_off)) From 2090e55283c4bf85c7a61735ca0e872745c55896 Mon Sep 17 00:00:00 2001 From: Manish V Badarkhe Date: Tue, 21 Jun 2022 18:11:53 +0100 Subject: [PATCH 23/32] feat(drtm): take DRTM components measurements before DLME launch Taken measurement of various DRTM components in the Event Log buffer to pass it to DLME. Change-Id: Ic56620161f42596d22bf40d5c83c041cbce0b618 Signed-off-by: Manish V Badarkhe --- services/std_svc/drtm/drtm_main.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/services/std_svc/drtm/drtm_main.c b/services/std_svc/drtm/drtm_main.c index 53aafeb4b..a96706d59 100644 --- a/services/std_svc/drtm/drtm_main.c +++ b/services/std_svc/drtm/drtm_main.c @@ -19,6 +19,7 @@ #include #include #include "drtm_main.h" +#include "drtm_measurements.h" #include "drtm_remediation.h" #include #include @@ -392,6 +393,27 @@ static uint64_t drtm_dynamic_launch(uint64_t x1, void *handle) SMC_RET1(handle, ret); } + /* + * The DMA protection is now engaged. Note that any failure mode that + * returns an error to the DRTM-launch caller must now disengage DMA + * protections before returning to the caller. + */ + + ret = drtm_take_measurements(&args); + if (ret != SUCCESS) { + goto err_undo_dma_prot; + } + + SMC_RET1(handle, ret); + +err_undo_dma_prot: + dma_prot_ret = drtm_dma_prot_disengage(); + if (dma_prot_ret != SUCCESS) { + ERROR("%s(): drtm_dma_prot_disengage() failed unexpectedly" + " rc=%d\n", __func__, ret); + panic(); + } + SMC_RET1(handle, ret); } From d42119cc294fbca2afc263fe5e44538a0ca5e7b8 Mon Sep 17 00:00:00 2001 From: Manish V Badarkhe Date: Wed, 22 Jun 2022 13:11:14 +0100 Subject: [PATCH 24/32] feat(drtm): prepare DLME data for DLME launch Prepared DLME data before DLME launch Change-Id: I28e2132d9c832ab5bd25cf884925b99cc48258ea Signed-off-by: Manish V Badarkhe --- services/std_svc/drtm/drtm_main.c | 131 ++++++++++++++++++++++++++---- services/std_svc/drtm/drtm_main.h | 16 +++- 2 files changed, 128 insertions(+), 19 deletions(-) diff --git a/services/std_svc/drtm/drtm_main.c b/services/std_svc/drtm/drtm_main.c index a96706d59..ad2b774a0 100644 --- a/services/std_svc/drtm/drtm_main.c +++ b/services/std_svc/drtm/drtm_main.c @@ -33,12 +33,17 @@ static drtm_features_t plat_drtm_features; /* DRTM-formatted memory map. */ static drtm_memory_region_descriptor_table_t *plat_drtm_mem_map; +/* DLME header */ +struct_dlme_data_header dlme_data_hdr_init; + +/* Minimum data memory requirement */ +uint64_t dlme_data_min_size; + int drtm_setup(void) { bool rc; const plat_drtm_tpm_features_t *plat_tpm_feat; const plat_drtm_dma_prot_features_t *plat_dma_prot_feat; - uint64_t dlme_data_min_size; INFO("DRTM service setup\n"); @@ -85,6 +90,7 @@ int drtm_setup(void) dlme_data_min_size = sizeof(drtm_memory_region_descriptor_table_t) + sizeof(drtm_mem_region_t); + dlme_data_hdr_init.dlme_prot_regions_size = dlme_data_min_size; } else { /* * TODO set protected regions table size based on platform DMA @@ -93,10 +99,16 @@ int drtm_setup(void) panic(); } - dlme_data_min_size += (drtm_get_address_map_size() + - PLAT_DRTM_EVENT_LOG_MAX_SIZE + - plat_drtm_get_tcb_hash_table_size() + - plat_drtm_get_imp_def_dlme_region_size()); + dlme_data_hdr_init.dlme_addr_map_size = drtm_get_address_map_size(); + dlme_data_hdr_init.dlme_tcb_hashes_table_size = + plat_drtm_get_tcb_hash_table_size(); + dlme_data_hdr_init.dlme_impdef_region_size = + plat_drtm_get_imp_def_dlme_region_size(); + + dlme_data_min_size += dlme_data_hdr_init.dlme_addr_map_size + + PLAT_DRTM_EVENT_LOG_MAX_SIZE + + dlme_data_hdr_init.dlme_tcb_hashes_table_size + + dlme_data_hdr_init.dlme_impdef_region_size; dlme_data_min_size = page_align(dlme_data_min_size, UP)/PAGE_SIZE; @@ -196,12 +208,97 @@ static enum drtm_retc drtm_dl_check_cores(void) return SUCCESS; } -static enum drtm_retc drtm_dl_prepare_dlme_data(const struct_drtm_dl_args *args, - size_t *dlme_data_size_out) +static enum drtm_retc drtm_dl_prepare_dlme_data(const struct_drtm_dl_args *args) { - size_t dlme_data_total_bytes_req = 0; + int rc; + uint64_t dlme_data_paddr; + size_t dlme_data_max_size; + uintptr_t dlme_data_mapping; + struct_dlme_data_header *dlme_data_hdr; + uint8_t *dlme_data_cursor; + size_t dlme_data_mapping_bytes; + size_t serialised_bytes_actual; - *dlme_data_size_out = dlme_data_total_bytes_req; + dlme_data_paddr = args->dlme_paddr + args->dlme_data_off; + dlme_data_max_size = args->dlme_size - args->dlme_data_off; + + /* + * The capacity of the given DLME data region is checked when + * the other dynamic launch arguments are. + */ + if (dlme_data_max_size < dlme_data_min_size) { + ERROR("%s: assertion failed:" + " dlme_data_max_size (%ld) < dlme_data_total_bytes_req (%ld)\n", + __func__, dlme_data_max_size, dlme_data_min_size); + panic(); + } + + /* Map the DLME data region as NS memory. */ + dlme_data_mapping_bytes = ALIGNED_UP(dlme_data_max_size, DRTM_PAGE_SIZE); + rc = mmap_add_dynamic_region_alloc_va(dlme_data_paddr, + &dlme_data_mapping, + dlme_data_mapping_bytes, + MT_RW_DATA | MT_NS | + MT_SHAREABILITY_ISH); + if (rc != 0) { + WARN("DRTM: %s: mmap_add_dynamic_region() failed rc=%d\n", + __func__, rc); + return INTERNAL_ERROR; + } + dlme_data_hdr = (struct_dlme_data_header *)dlme_data_mapping; + dlme_data_cursor = (uint8_t *)dlme_data_hdr + sizeof(*dlme_data_hdr); + + memcpy(dlme_data_hdr, (const void *)&dlme_data_hdr_init, + sizeof(*dlme_data_hdr)); + + /* Set the header version and size. */ + dlme_data_hdr->version = 1; + dlme_data_hdr->this_hdr_size = sizeof(*dlme_data_hdr); + + /* Prepare DLME protected regions. */ + drtm_dma_prot_serialise_table(dlme_data_cursor, + &serialised_bytes_actual); + assert(serialised_bytes_actual == + dlme_data_hdr->dlme_prot_regions_size); + dlme_data_cursor += serialised_bytes_actual; + + /* Prepare DLME address map. */ + if (plat_drtm_mem_map != NULL) { + memcpy(dlme_data_cursor, plat_drtm_mem_map, + dlme_data_hdr->dlme_addr_map_size); + } else { + WARN("DRTM: DLME address map is not in the cache\n"); + } + dlme_data_cursor += dlme_data_hdr->dlme_addr_map_size; + + /* Prepare DRTM event log for DLME. */ + drtm_serialise_event_log(dlme_data_cursor, &serialised_bytes_actual); + assert(serialised_bytes_actual <= PLAT_DRTM_EVENT_LOG_MAX_SIZE); + dlme_data_hdr->dlme_tpm_log_size = serialised_bytes_actual; + dlme_data_cursor += serialised_bytes_actual; + + /* + * TODO: Prepare the TCB hashes for DLME, currently its size + * 0 + */ + dlme_data_cursor += dlme_data_hdr->dlme_tcb_hashes_table_size; + + /* Implementation-specific region size is unused. */ + dlme_data_cursor += dlme_data_hdr->dlme_impdef_region_size; + + /* + * Prepare DLME data size, includes all data region referenced above + * alongwith the DLME data header + */ + dlme_data_hdr->dlme_data_size = dlme_data_cursor - (uint8_t *)dlme_data_hdr; + + /* Unmap the DLME data region. */ + rc = mmap_remove_dynamic_region(dlme_data_mapping, dlme_data_mapping_bytes); + if (rc != 0) { + ERROR("%s(): mmap_remove_dynamic_region() failed" + " unexpectedly rc=%d\n", __func__, rc); + panic(); + } return SUCCESS; } @@ -220,7 +317,6 @@ static enum drtm_retc drtm_dl_check_args(uint64_t x1, size_t args_mapping_size; struct_drtm_dl_args *a; struct_drtm_dl_args args_buf; - size_t dlme_data_size_req; int rc; if (x1 % DRTM_PAGE_SIZE != 0) { @@ -324,15 +420,9 @@ static enum drtm_retc drtm_dl_check_args(uint64_t x1, return INVALID_PARAMETERS; } - rc = drtm_dl_prepare_dlme_data(NULL, &dlme_data_size_req); - if (rc) { - ERROR("%s: drtm_dl_prepare_dlme_data() failed unexpectedly rc=%d\n", - __func__, rc); - panic(); - } - if (dlme_data_end - dlme_data_start < dlme_data_size_req) { + if (dlme_data_end - dlme_data_start < dlme_data_min_size) { ERROR("DRTM: argument DLME data region is short of %lu bytes\n", - dlme_data_size_req - (size_t)(dlme_data_end - dlme_data_start)); + dlme_data_min_size - (size_t)(dlme_data_end - dlme_data_start)); return INVALID_PARAMETERS; } @@ -404,6 +494,11 @@ static uint64_t drtm_dynamic_launch(uint64_t x1, void *handle) goto err_undo_dma_prot; } + ret = drtm_dl_prepare_dlme_data(&args); + if (ret != SUCCESS) { + goto err_undo_dma_prot; + } + SMC_RET1(handle, ret); err_undo_dma_prot: diff --git a/services/std_svc/drtm/drtm_main.h b/services/std_svc/drtm/drtm_main.h index 9bf5400b8..230cbcfbf 100644 --- a/services/std_svc/drtm/drtm_main.h +++ b/services/std_svc/drtm/drtm_main.h @@ -55,7 +55,7 @@ typedef struct { } drtm_features_t; struct __packed drtm_dl_args_v1 { - uint16_t version; /* Must be 1. */ + uint16_t version; /* Must be 1. */ uint8_t __res[2]; uint32_t features; uint64_t dlme_paddr; @@ -69,6 +69,20 @@ struct __packed drtm_dl_args_v1 { drtm_dl_dma_prot_args_v1_t dma_prot_args; } __aligned(__alignof(uint16_t /* First member's type, `uint16_t version' */)); +struct __packed dlme_data_header_v1 { + uint16_t version; /* Must be 1. */ + uint16_t this_hdr_size; + uint8_t __res[4]; + uint64_t dlme_data_size; + uint64_t dlme_prot_regions_size; + uint64_t dlme_addr_map_size; + uint64_t dlme_tpm_log_size; + uint64_t dlme_tcb_hashes_table_size; + uint64_t dlme_impdef_region_size; +} __aligned(__alignof(uint16_t /* First member's type, `uint16_t version'. */)); + +typedef struct dlme_data_header_v1 struct_dlme_data_header; + drtm_memory_region_descriptor_table_t *drtm_build_address_map(void); uint64_t drtm_get_address_map_size(void); From d1747e1b8e617ad024456791ce0ab8950bb282ca Mon Sep 17 00:00:00 2001 From: Manish Pandey Date: Thu, 23 Jun 2022 10:43:31 +0100 Subject: [PATCH 25/32] feat(drtm): prepare EL state during dynamic launch Prepared EL state before dynamic launch Change-Id: I3940cd7fc74da1a1addbeb08ae34f16771395e61 Signed-off-by: Manish Pandey Signed-off-by: Lucian Paul-Trifu --- include/arch/aarch64/arch_helpers.h | 2 + services/std_svc/drtm/drtm_main.c | 129 +++++++++++++++++++++++++++- services/std_svc/drtm/drtm_main.h | 5 ++ 3 files changed, 135 insertions(+), 1 deletion(-) diff --git a/include/arch/aarch64/arch_helpers.h b/include/arch/aarch64/arch_helpers.h index 2a3eb7266..50a5ad4ad 100644 --- a/include/arch/aarch64/arch_helpers.h +++ b/include/arch/aarch64/arch_helpers.h @@ -267,6 +267,8 @@ DEFINE_SYSREG_RW_FUNCS(elr_el3) DEFINE_SYSREG_RW_FUNCS(mdccsr_el0) DEFINE_SYSREG_RW_FUNCS(dbgdtrrx_el0) DEFINE_SYSREG_RW_FUNCS(dbgdtrtx_el0) +DEFINE_SYSREG_RW_FUNCS(sp_el1) +DEFINE_SYSREG_RW_FUNCS(sp_el2) DEFINE_SYSOP_FUNC(wfi) DEFINE_SYSOP_FUNC(wfe) diff --git a/services/std_svc/drtm/drtm_main.c b/services/std_svc/drtm/drtm_main.c index ad2b774a0..9237d82a5 100644 --- a/services/std_svc/drtm/drtm_main.c +++ b/services/std_svc/drtm/drtm_main.c @@ -21,6 +21,7 @@ #include "drtm_main.h" #include "drtm_measurements.h" #include "drtm_remediation.h" +#include #include #include #include @@ -446,11 +447,107 @@ static enum drtm_retc drtm_dl_check_args(uint64_t x1, return SUCCESS; } +static void drtm_dl_reset_dlme_el_state(enum drtm_dlme_el dlme_el) +{ + uint64_t sctlr; + + /* + * TODO: Set PE state according to the PSCI's specification of the initial + * state after CPU_ON, or to reset values if unspecified, where they exist, + * or define sensible values otherwise. + */ + + switch (dlme_el) { + case DLME_AT_EL1: + sctlr = read_sctlr_el1(); + break; + + case DLME_AT_EL2: + sctlr = read_sctlr_el2(); + break; + + default: /* Not reached */ + ERROR("%s(): dlme_el has the unexpected value %d\n", + __func__, dlme_el); + panic(); + } + + sctlr &= ~(/* Disable DLME's EL MMU, since the existing page-tables are untrusted. */ + SCTLR_M_BIT + | SCTLR_EE_BIT /* Little-endian data accesses. */ + ); + + sctlr |= SCTLR_C_BIT | SCTLR_I_BIT; /* Allow instruction and data caching. */ + + switch (dlme_el) { + case DLME_AT_EL1: + write_sctlr_el1(sctlr); + break; + + case DLME_AT_EL2: + write_sctlr_el2(sctlr); + break; + } +} + +static void drtm_dl_reset_dlme_context(enum drtm_dlme_el dlme_el) +{ + void *ns_ctx = cm_get_context(NON_SECURE); + gp_regs_t *gpregs = get_gpregs_ctx(ns_ctx); + uint64_t spsr_el3 = read_ctx_reg(get_el3state_ctx(ns_ctx), CTX_SPSR_EL3); + + /* Reset all gpregs, including SP_EL0. */ + memset(gpregs, 0, sizeof(*gpregs)); + + /* Reset SP_ELx. */ + switch (dlme_el) { + case DLME_AT_EL1: + write_sp_el1(0); + break; + + case DLME_AT_EL2: + write_sp_el2(0); + break; + } + + /* + * DLME's async exceptions are masked to avoid a NWd attacker's timed + * interference with any state we established trust in or measured. + */ + spsr_el3 |= SPSR_DAIF_MASK << SPSR_DAIF_SHIFT; + + write_ctx_reg(get_el3state_ctx(ns_ctx), CTX_SPSR_EL3, spsr_el3); +} + +static void drtm_dl_prepare_eret_to_dlme(const struct_drtm_dl_args *args, enum drtm_dlme_el dlme_el) +{ + void *ctx = cm_get_context(NON_SECURE); + uint64_t dlme_ep = DL_ARGS_GET_DLME_ENTRY_POINT(args); + uint64_t spsr_el3 = read_ctx_reg(get_el3state_ctx(ctx), CTX_SPSR_EL3); + + /* Next ERET is to the DLME's EL. */ + spsr_el3 &= ~(MODE_EL_MASK << MODE_EL_SHIFT); + switch (dlme_el) { + case DLME_AT_EL1: + spsr_el3 |= MODE_EL1 << MODE_EL_SHIFT; + break; + + case DLME_AT_EL2: + spsr_el3 |= MODE_EL2 << MODE_EL_SHIFT; + break; + } + + /* Next ERET is to the DLME entry point. */ + cm_set_elr_spsr_el3(NON_SECURE, dlme_ep, spsr_el3); +} + static uint64_t drtm_dynamic_launch(uint64_t x1, void *handle) { enum drtm_retc ret = SUCCESS; enum drtm_retc dma_prot_ret; struct_drtm_dl_args args; + /* DLME should be highest NS exception level */ + enum drtm_dlme_el dlme_el = (el_implemented(2) != EL_IMPL_NONE) ? MODE_EL2 : MODE_EL1; /* Ensure that only boot PE is powered on */ ret = drtm_dl_check_cores(); @@ -499,7 +596,37 @@ static uint64_t drtm_dynamic_launch(uint64_t x1, void *handle) goto err_undo_dma_prot; } - SMC_RET1(handle, ret); + /* + * Note that, at the time of writing, the DRTM spec allows a successful + * launch from NS-EL1 to return to a DLME in NS-EL2. The practical risk + * of a privilege escalation, e.g. due to a compromised hypervisor, is + * considered small enough not to warrant the specification of additional + * DRTM conduits that would be necessary to maintain OSs' abstraction from + * the presence of EL2 were the dynamic launch only be allowed from the + * highest NS EL. + */ + + dlme_el = (el_implemented(2) != EL_IMPL_NONE) ? MODE_EL2 : MODE_EL1; + + drtm_dl_reset_dlme_el_state(dlme_el); + drtm_dl_reset_dlme_context(dlme_el); + + /* + * TODO: Reset all SDEI event handlers, since they are untrusted. Both + * private and shared events for all cores must be unregistered. + * Note that simply calling SDEI ABIs would not be adequate for this, since + * there is currently no SDEI operation that clears private data for all PEs. + */ + + drtm_dl_prepare_eret_to_dlme(&args, dlme_el); + + /* + * TODO: invalidate the instruction cache before jumping to the DLME. + * This is required to defend against potentially-malicious cache contents. + */ + + /* Return the DLME region's address in x0, and the DLME data offset in x1.*/ + SMC_RET2(handle, args.dlme_paddr, args.dlme_data_off); err_undo_dma_prot: dma_prot_ret = drtm_dma_prot_disengage(); diff --git a/services/std_svc/drtm/drtm_main.h b/services/std_svc/drtm/drtm_main.h index 230cbcfbf..baa37ae7d 100644 --- a/services/std_svc/drtm/drtm_main.h +++ b/services/std_svc/drtm/drtm_main.h @@ -36,6 +36,11 @@ #define DL_ARGS_GET_DLME_ENTRY_POINT(a) \ (((a)->dlme_paddr + (a)->dlme_img_off + (a)->dlme_img_ep_off)) +enum drtm_dlme_el { + DLME_AT_EL1 = MODE_EL1, + DLME_AT_EL2 = MODE_EL2 +}; + enum drtm_retc { SUCCESS = SMC_OK, NOT_SUPPORTED = SMC_UNK, From b1392f429cdd368ea2b8e183a1ac0fb31deaf694 Mon Sep 17 00:00:00 2001 From: Manish Pandey Date: Thu, 23 Jun 2022 13:11:48 +0100 Subject: [PATCH 26/32] feat(drtm): ensure that no SDEI event registered during dynamic launch Ensured no SDEI event are registered during dynamic launch. Signed-off-by: Manish Pandey Change-Id: Ied3b2d389aa3d9a96ace9078581d5e691f0b38a7 --- services/std_svc/drtm/drtm_main.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/services/std_svc/drtm/drtm_main.c b/services/std_svc/drtm/drtm_main.c index 9237d82a5..bec4b72f1 100644 --- a/services/std_svc/drtm/drtm_main.c +++ b/services/std_svc/drtm/drtm_main.c @@ -26,6 +26,7 @@ #include #include #include +#include #include /* Structure to store DRTM features specific to the platform. */ @@ -569,6 +570,13 @@ static uint64_t drtm_dynamic_launch(uint64_t x1, void *handle) SMC_RET1(handle, ret); } + /* Ensure that there are no SDEI event registered */ +#if SDEI_SUPPORT + if (sdei_get_registered_event_count() != 0) { + SMC_RET1(handle, DENIED); + } +#endif /* SDEI_SUPPORT */ + /* * Engage the DMA protections. The launch cannot proceed without the DMA * protections due to potential TOC/TOU vulnerabilities w.r.t. the DLME @@ -611,13 +619,6 @@ static uint64_t drtm_dynamic_launch(uint64_t x1, void *handle) drtm_dl_reset_dlme_el_state(dlme_el); drtm_dl_reset_dlme_context(dlme_el); - /* - * TODO: Reset all SDEI event handlers, since they are untrusted. Both - * private and shared events for all cores must be unregistered. - * Note that simply calling SDEI ABIs would not be adequate for this, since - * there is currently no SDEI operation that clears private data for all PEs. - */ - drtm_dl_prepare_eret_to_dlme(&args, dlme_el); /* From d5f225d95d3dc7473340ffebfcb9068b54f91a17 Mon Sep 17 00:00:00 2001 From: Manish V Badarkhe Date: Mon, 4 Jul 2022 14:51:07 +0100 Subject: [PATCH 27/32] feat(fvp): add plat API to validate that passed region is non-secure Added a platform function to check passed region is within the Non-Secure region of DRAM. Signed-off-by: Manish V Badarkhe Change-Id: Ie5808fa6a1b6e6bc99f4185fa8acc52af0d5f14d --- include/plat/common/plat_drtm.h | 7 ++++++ plat/arm/board/fvp/fvp_drtm_addr.c | 36 ++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 plat/arm/board/fvp/fvp_drtm_addr.c diff --git a/include/plat/common/plat_drtm.h b/include/plat/common/plat_drtm.h index 754fa1a40..e96e71958 100644 --- a/include/plat/common/plat_drtm.h +++ b/include/plat/common/plat_drtm.h @@ -64,4 +64,11 @@ uint64_t plat_drtm_get_tcb_hash_features(void); int plat_set_drtm_error(uint64_t error_code); int plat_get_drtm_error(uint64_t *error_code); +/* + * Platform-specific function to ensure passed region lies within + * Non-Secure region of DRAM + */ +int plat_drtm_validate_ns_region(uintptr_t region_start, + size_t region_size); + #endif /* PLAT_DRTM_H */ diff --git a/plat/arm/board/fvp/fvp_drtm_addr.c b/plat/arm/board/fvp/fvp_drtm_addr.c new file mode 100644 index 000000000..eeaa3425b --- /dev/null +++ b/plat/arm/board/fvp/fvp_drtm_addr.c @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2022 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include + +#include +#include + +/******************************************************************************* + * Check passed region is within Non-Secure region of DRAM + ******************************************************************************/ +int plat_drtm_validate_ns_region(uintptr_t region_start, + size_t region_size) +{ + uintptr_t region_end = region_start + region_size - 1; + + if (region_start >= region_end) { + return -1; + } else if ((region_start >= ARM_NS_DRAM1_BASE) && + (region_start < (ARM_NS_DRAM1_BASE + ARM_NS_DRAM1_SIZE)) && + (region_end >= ARM_NS_DRAM1_BASE) && + (region_end < (ARM_NS_DRAM1_BASE + ARM_NS_DRAM1_SIZE))) { + return 0; + } else if ((region_start >= ARM_DRAM2_BASE) && + (region_start < (ARM_DRAM2_BASE + ARM_DRAM2_SIZE)) && + (region_end >= ARM_DRAM2_BASE) && + (region_end < (ARM_DRAM2_BASE + ARM_DRAM2_SIZE))) { + return 0; + } + + return -1; +} From 764aa951b2ca451694c74791964a712d423d8206 Mon Sep 17 00:00:00 2001 From: Manish V Badarkhe Date: Wed, 13 Jul 2022 09:47:03 +0100 Subject: [PATCH 28/32] feat(drtm): ensure that passed region lies within Non-Secure region of DRAM Ensured DLME data region and DRTM parameters are lies within Non-Secure region of DRAM by calling platform function 'plat_drtm_validate_ns_region'. Signed-off-by: Manish V Badarkhe Change-Id: I93ead775f45ca7748193631f8f9eec4326fcf20a --- services/std_svc/drtm/drtm_main.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/services/std_svc/drtm/drtm_main.c b/services/std_svc/drtm/drtm_main.c index bec4b72f1..443516d28 100644 --- a/services/std_svc/drtm/drtm_main.c +++ b/services/std_svc/drtm/drtm_main.c @@ -328,6 +328,14 @@ static enum drtm_retc drtm_dl_check_args(uint64_t x1, } args_mapping_size = ALIGNED_UP(sizeof(struct_drtm_dl_args), DRTM_PAGE_SIZE); + + /* check DRTM parameters are within NS address region */ + rc = plat_drtm_validate_ns_region(x1, args_mapping_size); + if (rc != 0) { + ERROR("DRTM: parameters lies within secure memory\n"); + return INVALID_PARAMETERS; + } + rc = mmap_add_dynamic_region_alloc_va(x1, &args_mapping, args_mapping_size, MT_MEMORY | MT_NS | MT_RO | MT_SHAREABILITY_ISH); @@ -371,14 +379,6 @@ static enum drtm_retc drtm_dl_check_args(uint64_t x1, dlme_data_start = a->dlme_paddr + a->dlme_data_off; dlme_data_end = dlme_end; - /* - * TODO: validate that the DLME physical address range is all NS memory, - * return INVALID_PARAMETERS if it is not. - * Note that this check relies on platform-specific information. For - * examples, see psci_plat_pm_ops->validate_ns_entrypoint() or - * arm_validate_ns_entrypoint(). - */ - /* Check the DLME regions arguments. */ if ((dlme_start % DRTM_PAGE_SIZE) != 0) { ERROR("DRTM: argument DLME region is not " @@ -428,6 +428,13 @@ static enum drtm_retc drtm_dl_check_args(uint64_t x1, return INVALID_PARAMETERS; } + /* check DLME region (paddr + size) is within a NS address region */ + rc = plat_drtm_validate_ns_region(dlme_start, (size_t)a->dlme_size); + if (rc != 0) { + ERROR("DRTM: DLME region lies within secure memory\n"); + return INVALID_PARAMETERS; + } + /* Check the Normal World DCE region arguments. */ if (a->dce_nwd_paddr != 0) { uint32_t dce_nwd_start = a->dce_nwd_paddr; From 2c265975a76977c6373636f5f28e114d1b73e10e Mon Sep 17 00:00:00 2001 From: Manish Pandey Date: Tue, 19 Jul 2022 14:35:00 +0100 Subject: [PATCH 29/32] feat(drtm): invalidate icache before DLME launch As per DRTM beta0 spec table #28, Before the DLME is called the DCE must invalidate all instruction caches. Signed-off-by: Manish Pandey Change-Id: I7efbb03d1d13346a8d898882fdbd7bbe8f1d49b2 --- services/std_svc/drtm/drtm_main.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/services/std_svc/drtm/drtm_main.c b/services/std_svc/drtm/drtm_main.c index 443516d28..c98d829b3 100644 --- a/services/std_svc/drtm/drtm_main.c +++ b/services/std_svc/drtm/drtm_main.c @@ -136,6 +136,13 @@ int drtm_setup(void) return 0; } +static inline void invalidate_icache_all(void) +{ + __asm__ volatile("ic ialluis"); + dsb(); + isb(); +} + static inline uint64_t drtm_features_tpm(void *ctx) { SMC_RET2(ctx, 1ULL, /* TPM feature is supported */ @@ -629,9 +636,11 @@ static uint64_t drtm_dynamic_launch(uint64_t x1, void *handle) drtm_dl_prepare_eret_to_dlme(&args, dlme_el); /* - * TODO: invalidate the instruction cache before jumping to the DLME. - * This is required to defend against potentially-malicious cache contents. + * As per DRTM beta0 spec table #28 invalidate the instruction cache + * before jumping to the DLME. This is required to defend against + * potentially-malicious cache contents. */ + invalidate_icache_all(); /* Return the DLME region's address in x0, and the DLME data offset in x1.*/ SMC_RET2(handle, args.dlme_paddr, args.dlme_data_off); From 67471e75b3cf48c361e71894a666bce4395bbb35 Mon Sep 17 00:00:00 2001 From: Manish Pandey Date: Thu, 21 Jul 2022 13:07:07 +0100 Subject: [PATCH 30/32] feat(drtm): flush dcache before DLME launch Flush the data cache range before DLME launch to ensure that data passed by DCE preamble is committed. Signed-off-by: Manish Pandey Change-Id: I9946fd3420a17b86d9f1483e8b2cd5880033454e --- services/std_svc/drtm/drtm_main.c | 45 ++++++++++++++++++++++--------- 1 file changed, 33 insertions(+), 12 deletions(-) diff --git a/services/std_svc/drtm/drtm_main.c b/services/std_svc/drtm/drtm_main.c index c98d829b3..e0f5c1784 100644 --- a/services/std_svc/drtm/drtm_main.c +++ b/services/std_svc/drtm/drtm_main.c @@ -322,8 +322,8 @@ static enum drtm_retc drtm_dl_check_args(uint64_t x1, uint64_t dlme_start, dlme_end; uint64_t dlme_img_start, dlme_img_ep, dlme_img_end; uint64_t dlme_data_start, dlme_data_end; - uintptr_t args_mapping; - size_t args_mapping_size; + uintptr_t va_mapping; + size_t va_mapping_size; struct_drtm_dl_args *a; struct_drtm_dl_args args_buf; int rc; @@ -334,16 +334,16 @@ static enum drtm_retc drtm_dl_check_args(uint64_t x1, return INVALID_PARAMETERS; } - args_mapping_size = ALIGNED_UP(sizeof(struct_drtm_dl_args), DRTM_PAGE_SIZE); + va_mapping_size = ALIGNED_UP(sizeof(struct_drtm_dl_args), DRTM_PAGE_SIZE); /* check DRTM parameters are within NS address region */ - rc = plat_drtm_validate_ns_region(x1, args_mapping_size); + rc = plat_drtm_validate_ns_region(x1, va_mapping_size); if (rc != 0) { ERROR("DRTM: parameters lies within secure memory\n"); return INVALID_PARAMETERS; } - rc = mmap_add_dynamic_region_alloc_va(x1, &args_mapping, args_mapping_size, + rc = mmap_add_dynamic_region_alloc_va(x1, &va_mapping, va_mapping_size, MT_MEMORY | MT_NS | MT_RO | MT_SHAREABILITY_ISH); if (rc != 0) { @@ -351,15 +351,14 @@ static enum drtm_retc drtm_dl_check_args(uint64_t x1, __func__, rc); return INTERNAL_ERROR; } - a = (struct_drtm_dl_args *)args_mapping; - /* - * TODO: invalidate all data cache before reading the data passed by the - * DCE Preamble. This is required to avoid / defend against racing with - * cache evictions. - */ + a = (struct_drtm_dl_args *)va_mapping; + + /* Sanitize cache of data passed in args by the DCE Preamble. */ + flush_dcache_range(va_mapping, va_mapping_size); + args_buf = *a; - rc = mmap_remove_dynamic_region(args_mapping, args_mapping_size); + rc = mmap_remove_dynamic_region(va_mapping, va_mapping_size); if (rc) { ERROR("%s(): mmap_remove_dynamic_region() failed unexpectedly" " rc=%d\n", __func__, rc); @@ -458,6 +457,28 @@ static enum drtm_retc drtm_dl_check_args(uint64_t x1, } } + /* + * Map and sanitize the cache of data range passed by DCE Preamble. This + * is required to avoid / defend against racing with cache evictions + */ + va_mapping_size = ALIGNED_UP((dlme_end - dlme_start), DRTM_PAGE_SIZE); + rc = mmap_add_dynamic_region_alloc_va(dlme_img_start, &va_mapping, va_mapping_size, + MT_MEMORY | MT_NS | MT_RO | + MT_SHAREABILITY_ISH); + if (rc != 0) { + ERROR("DRTM: %s: mmap_add_dynamic_region_alloc_va() failed rc=%d\n", + __func__, rc); + return INTERNAL_ERROR; + } + flush_dcache_range(va_mapping, va_mapping_size); + + rc = mmap_remove_dynamic_region(va_mapping, va_mapping_size); + if (rc) { + ERROR("%s(): mmap_remove_dynamic_region() failed unexpectedly" + " rc=%d\n", __func__, rc); + panic(); + } + *a_out = *a; return SUCCESS; } From b3b227ff200b9b02590062f05add1affb7177f71 Mon Sep 17 00:00:00 2001 From: Lucian Paul-Trifu Date: Wed, 22 Jun 2022 18:45:36 +0100 Subject: [PATCH 31/32] docs(drtm): add platform APIs for DRTM Documented platform APIs for DRTM Signed-off-by: Lucian Paul-Trifu Signed-off-by: Manish V Badarkhe Change-Id: I22749c26bbe7b3271705dd3db07e8597fce6225b --- docs/getting_started/porting-guide.rst | 210 +++++++++++++++++++++++++ 1 file changed, 210 insertions(+) diff --git a/docs/getting_started/porting-guide.rst b/docs/getting_started/porting-guide.rst index 992aca1b9..c4686f6f1 100644 --- a/docs/getting_started/porting-guide.rst +++ b/docs/getting_started/porting-guide.rst @@ -564,6 +564,21 @@ behaviour of the ``assert()`` function (for example, to save memory). doesn't print anything to the console. If ``PLAT_LOG_LEVEL_ASSERT`` isn't defined, it defaults to ``LOG_LEVEL``. +If the platform port uses the DRTM feature, the following constants must be +defined: + +- **#define : PLAT_DRTM_EVENT_LOG_MAX_SIZE** + + Maximum Event Log size used by the platform. Platform can decide the maximum + size of the Event Log buffer, depending upon the highest hash algorithm + chosen and the number of components selected to measure during the DRTM + execution flow. + +- **#define : PLAT_DRTM_MMAP_ENTRIES** + + Number of the MMAP entries used by the DRTM implementation to calculate the + size of address map region of the platform. + File : plat_macros.S [mandatory] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -789,6 +804,186 @@ The function returns 0 on success. Any other value means the counter value either could not be updated or the authentication image descriptor indicates that it is not allowed to be updated. +Dynamic Root of Trust for Measurement support (in BL31) +------------------------------------------------------- + +The functions mentioned in this section are mandatory, when platform enables +DRTM_SUPPORT build flag. + +Function : plat_get_addr_mmap() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : const mmap_region_t * + +This function is used to return the address of the platform *address-map* table, +which describes the regions of normal memory, memory mapped I/O +and non-volatile memory. + +Function : plat_has_non_host_platforms() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : bool + +This function returns *true* if the platform has any trusted devices capable of +DMA, otherwise returns *false*. + +Function : plat_has_unmanaged_dma_peripherals() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : bool + +This function returns *true* if platform uses peripherals whose DMA is not +managed by an SMMU, otherwise returns *false*. + +Note - +If the platform has peripherals that are not managed by the SMMU, then the +platform should investigate such peripherals to determine whether they can +be trusted, and such peripherals should be moved under "Non-host platforms" +if they can be trusted. + +Function : plat_get_total_num_smmus() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : unsigned int + +This function returns the total number of SMMUs in the platform. + +Function : plat_enumerate_smmus() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +:: + + + Argument : void + Return : const uintptr_t *, size_t + +This function returns an array of SMMU addresses and the actual number of SMMUs +reported by the platform. + +Function : plat_drtm_get_dma_prot_features() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : const plat_drtm_dma_prot_features_t* + +This function returns the address of plat_drtm_dma_prot_features_t structure +containing the maximum number of protected regions and bitmap with the types +of DMA protection supported by the platform. +For more details see section 3.3 Table 6 of `DRTM`_ specification. + +Function : plat_drtm_dma_prot_get_max_table_bytes() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : uint64_t + +This function returns the maximum size of DMA protected regions table in +bytes. + +Function : plat_drtm_get_tpm_features() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : const plat_drtm_tpm_features_t* + +This function returns the address of *plat_drtm_tpm_features_t* structure +containing PCR usage schema, TPM-based hash, and firmware hash algorithm +supported by the platform. + +Function : plat_drtm_get_min_size_normal_world_dce() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : uint64_t + +This function returns the size normal-world DCE of the platform. + +Function : plat_drtm_get_imp_def_dlme_region_size() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : uint64_t + +This function returns the size of implementation defined DLME region +of the platform. + +Function : plat_drtm_get_tcb_hash_table_size() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : uint64_t + +This function returns the size of TCB hash table of the platform. + +Function : plat_drtm_get_tcb_hash_features() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : uint64_t + +This function returns the Maximum number of TCB hashes recorded by the +platform. +For more details see section 3.3 Table 6 of `DRTM`_ specification. + +Function : plat_drtm_validate_ns_region() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : uintptr_t, uintptr_t + Return : int + +This function validates that given region is within the Non-Secure region +of DRAM. This function takes a region start address and size an input +arguments, and returns 0 on success and -1 on failure. + +Function : plat_set_drtm_error() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : uint64_t + Return : int + +This function writes a 64 bit error code received as input into +non-volatile storage and returns 0 on success and -1 on failure. + +Function : plat_get_drtm_error() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : uint64_t* + Return : int + +This function reads a 64 bit error code from the non-volatile storage +into the received address, and returns 0 on success and -1 on failure. + Common mandatory function modifications --------------------------------------- @@ -1097,6 +1292,20 @@ environment is initialized. The address from where it was called is stored in x30 (Link Register). The default implementation simply spins. +Function : plat_system_reset() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : void + +This function is used by the platform to resets the system. It can be used +in any specific use-case where system needs to be resetted. For example, +in case of DRTM implementation this function reset the system after +writing the DRTM error code in the non-volatile storage. This function +never returns. Failure in reset results in panic. + Function : plat_get_bl_image_load_info() ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -3225,3 +3434,4 @@ amount of open resources per driver. .. _3.0 (GICv3): http://infocenter.arm.com/help/topic/com.arm.doc.ihi0069b/index.html .. _FreeBSD: https://www.freebsd.org .. _SCC: http://www.simple-cc.org/ +.. _DRTM: https://developer.arm.com/documentation/den0113/a From 50a43b0f6491a7ea76c23edf0c20a2c3699d7b87 Mon Sep 17 00:00:00 2001 From: Manish V Badarkhe Date: Wed, 29 Jun 2022 14:09:47 +0100 Subject: [PATCH 32/32] docs(drtm): steps to run DRTM implementation Documented steps to run DRTM implementation. Signed-off-by: Manish V Badarkhe Change-Id: I30dd8c1088a54a8906389c2584d922862610dae0 --- docs/design_documents/drtm_poc.rst | 132 +++++++++++++++++++++++++++++ docs/design_documents/index.rst | 3 +- docs/glossary.rst | 15 ++++ 3 files changed, 149 insertions(+), 1 deletion(-) create mode 100644 docs/design_documents/drtm_poc.rst diff --git a/docs/design_documents/drtm_poc.rst b/docs/design_documents/drtm_poc.rst new file mode 100644 index 000000000..79e11429d --- /dev/null +++ b/docs/design_documents/drtm_poc.rst @@ -0,0 +1,132 @@ +DRTM Proof of Concept +===================== + +Dynamic Root of Trust for Measurement (DRTM) begins a new trust environment +by measuring and executing a protected payload. + +Static Root of Trust for Measurement (SRTM)/Measured Boot implementation, +currently used by TF-A covers all firmwares, from the boot ROM to the normal +world bootloader. As a whole, they make up the system's TCB. These boot +measurements allow attesting to what software is running on the system and +enable enforcing security policies. + +As the boot chain grows or firmware becomes dynamically extensible, +establishing an attestable TCB becomes more challenging. DRTM provides a +solution to this problem by allowing measurement chains to be started at +any time. As these measurements are stored separately from the boot-time +measurements, they reduce the size of the TCB, which helps reduce the attack +surface and the risk of untrusted code executing, which could compromise +the security of the system. + +Components +~~~~~~~~~~ + + - **DCE-Preamble**: The DCE Preamble prepares the platform for DRTM by + doing any needed configuration, loading the target payload image(DLME), + and preparing input parameters needed by DRTM. Finally, it invokes the + DL Event to start the dynamic launch. + + - **D-CRTM**: The D-CRTM is the trust anchor (or root of trust) for the + DRTM boot sequence and is where the dynamic launch starts. The D-CRTM + must be implemented as a trusted agent in the system. The D-CRTM + initializes the TPM for DRTM and prepares the environment for the next + stage of DRTM, the DCE. The D-CRTM measures the DCE, verifies its + signature, and transfers control to it. + + - **DCE**: The DCE executes on an application core. The DCE verifies the + system’s state, measures security-critical attributes of the system, + prepares the memory region for the target payload, measures the payload, + and finally transfers control to the payload. + + - **DLME**: The protected payload is referred to as the Dynamically Launched + Measured Environment, or DLME. The DLME begins execution in a safe state, + with a single thread of execution, DMA protections, and interrupts + disabled. The DCE provides data to the DLME that it can use to verify the + configuration of the system. + +In this proof of concept, DCE and D-CRTM are implemented in BL31 and +DCE-Preamble and DLME are implemented in UEFI application. A DL Event is +triggered as a SMC by DCE-Preamble and handled by D-CRTM, which launches the +DLME via DCE. + +This manual provides instructions to build TF-A code with pre-buit EDK2 +and DRTM UEFI application. + +Building the PoC for the Arm FVP platform +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +(1) Use the below command to clone TF-A source code - + +.. code:: shell + + $ git clone https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git + +(2) There are prebuilt binaries required to execute the DRTM implementation + in the `prebuilts-drtm-bins`_. + Download EDK2 *FVP_AARCH64_EFI.fd* and UEFI DRTM application *test-disk.img* + binary from `prebuilts-drtm-bins`_. + +(3) Build the TF-A code using below command + +.. code:: shell + + $ make CROSS_COMPILE=aarch64-none-elf- ARM_ROTPK_LOCATION=devel_rsa + DEBUG=1 V=1 BL33= DRTM_SUPPORT=1 + MBEDTLS_DIR= USE_ROMLIB=1 all fip + +Running DRTM UEFI application on the Armv8-A AEM FVP +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +To run the DRTM test application along with DRTM implementation in BL31, +you need an FVP model. Please use the version of FVP_Base_RevC-2xAEMvA model +advertised in the TF-A documentation. + +.. code:: shell + + FVP_Base_RevC-2xAEMvA \ + --data cluster0.cpu0=@0x03ff2000 \ + --stat \ + -C bp.flashloader0.fname= \ + -C bp.secureflashloader.fname= \ + -C bp.ve_sysregs.exit_on_shutdown=1 \ + -C bp.virtioblockdevice.image_path= \ + -C cache_state_modelled=1 \ + -C cluster0.check_memory_attributes=0 \ + -C cluster0.cpu0.etm-present=0 \ + -C cluster0.cpu1.etm-present=0 \ + -C cluster0.cpu2.etm-present=0 \ + -C cluster0.cpu3.etm-present=0 \ + -C cluster0.stage12_tlb_size=1024 \ + -C cluster1.check_memory_attributes=0 \ + -C cluster1.cpu0.etm-present=0 \ + -C cluster1.cpu1.etm-present=0 \ + -C cluster1.cpu2.etm-present=0 \ + -C cluster1.cpu3.etm-present=0 \ + -C cluster1.stage12_tlb_size=1024 \ + -C pctl.startup=0.0.0.0 \ + -Q 1000 \ + "$@" + +The bottom of the output from *uart1* should look something like the +following to indicate that the last SMC to unprotect memory has been fired +successfully. + +.. code-block:: shell + + ... + + INFO: DRTM service handler: version + INFO: ++ DRTM service handler: TPM features + INFO: ++ DRTM service handler: Min. mem. requirement features + INFO: ++ DRTM service handler: DMA protection features + INFO: ++ DRTM service handler: Boot PE ID features + INFO: ++ DRTM service handler: TCB-hashes features + INFO: DRTM service handler: dynamic launch + WARNING: DRTM service handler: close locality is not supported + INFO: DRTM service handler: unprotect mem + +-------------- + +*Copyright (c) 2022, Arm Limited. All rights reserved.* + +.. _prebuilts-drtm-bins: https://downloads.trustedfirmware.org/tf-a/drtm +.. _DRTM-specification: https://developer.arm.com/documentation/den0113/a diff --git a/docs/design_documents/index.rst b/docs/design_documents/index.rst index 257a510d0..765efe6c3 100644 --- a/docs/design_documents/index.rst +++ b/docs/design_documents/index.rst @@ -9,7 +9,8 @@ Design Documents cmake_framework context_mgmt_rework measured_boot_poc + drtm_poc -------------- -*Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.* +*Copyright (c) 2020-2022, Arm Limited and Contributors. All rights reserved.* diff --git a/docs/glossary.rst b/docs/glossary.rst index aeeb133cb..e5d379c1d 100644 --- a/docs/glossary.rst +++ b/docs/glossary.rst @@ -40,6 +40,18 @@ You can find additional definitions in the `Arm Glossary`_. Common Vulnerabilities and Exposures. A CVE document is commonly used to describe a publicly-known security vulnerability. + DCE + DRTM Configuration Environment + + D-CRTM + Dynamic Code Root of Trust for Measurement + + DLME + Dynamically Launched Measured Environment + + DRTM + Dynamic Root of Trust for Measurement + DS-5 Arm Development Studio 5 @@ -186,6 +198,9 @@ You can find additional definitions in the `Arm Glossary`_. TBBR Trusted Board Boot Requirements + TCB + Trusted Compute Base + TEE Trusted Execution Environment