diff options
author | Antonio Nino Diaz <antonio.ninodiaz@arm.com> | 2019-03-13 13:57:39 +0000 |
---|---|---|
committer | Antonio Nino Diaz <antonio.ninodiaz@arm.com> | 2019-03-13 13:57:39 +0000 |
commit | 9c9f92c4c4cd07ea75ea72a42f15b32ed4c01bf0 (patch) | |
tree | 50e83b79b1c811db525e3c2e64b99951a59fed4e | |
parent | 4ac64eb32c8fcb3a00aecda6c943768505e3282a (diff) |
Add ARMv8.3 pointer authentication support
ARMv8.3-PAuth adds functionality that supports address authentication of
the contents of a register before that register is used as the target of
an indirect branch, or as a load.
This feature is supported only in AArch64 state.
This feature is mandatory in ARMv8.3 implementations.
This patch adds the functionality needed for platforms to provide
authentication keys for the TF-A Test Framework, and a new option
(ENABLE_PAUTH) to enable pointer authentication in the framework itself.
This option is disabled by default.
Pointer authentication support has been added to FVP.
Change-Id: Id2d5c978deb68ae60107879f1c3d0b231cba9f42
Signed-off-by: Antonio Nino Diaz <antonio.ninodiaz@arm.com>
-rw-r--r-- | Makefile | 8 | ||||
-rw-r--r-- | defaults.mk | 5 | ||||
-rw-r--r-- | docs/porting-guide.rst | 16 | ||||
-rw-r--r-- | docs/user-guide.rst | 5 | ||||
-rw-r--r-- | include/lib/aarch64/arch.h | 29 | ||||
-rw-r--r-- | include/lib/aarch64/arch_features.h | 19 | ||||
-rw-r--r-- | include/lib/aarch64/arch_helpers.h | 3 | ||||
-rw-r--r-- | include/plat/common/platform.h | 5 | ||||
-rw-r--r-- | plat/arm/fvp/platform.mk | 6 | ||||
-rw-r--r-- | plat/common/aarch64/pauth.c | 29 | ||||
-rw-r--r-- | tftf/framework/main.c | 27 |
11 files changed, 132 insertions, 20 deletions
@@ -1,5 +1,5 @@ # -# Copyright (c) 2018, Arm Limited. All rights reserved. +# Copyright (c) 2018-2019, Arm Limited. All rights reserved. # # SPDX-License-Identifier: BSD-3-Clause # @@ -134,6 +134,7 @@ include ${PLAT_MAKEFILE_FULL} ################################################################################ $(eval $(call assert_boolean,DEBUG)) $(eval $(call assert_boolean,ENABLE_ASSERTIONS)) +$(eval $(call assert_boolean,ENABLE_PAUTH)) $(eval $(call assert_boolean,FIRMWARE_UPDATE)) $(eval $(call assert_boolean,FWU_BL_TEST)) $(eval $(call assert_boolean,NEW_TEST_SESSION)) @@ -148,6 +149,7 @@ $(eval $(call add_define,TFTF_DEFINES,ARM_ARCH_MAJOR)) $(eval $(call add_define,TFTF_DEFINES,ARM_ARCH_MINOR)) $(eval $(call add_define,TFTF_DEFINES,DEBUG)) $(eval $(call add_define,TFTF_DEFINES,ENABLE_ASSERTIONS)) +$(eval $(call add_define,TFTF_DEFINES,ENABLE_PAUTH)) $(eval $(call add_define,TFTF_DEFINES,LOG_LEVEL)) $(eval $(call add_define,TFTF_DEFINES,NEW_TEST_SESSION)) $(eval $(call add_define,TFTF_DEFINES,PLAT_${PLAT})) @@ -210,6 +212,10 @@ TFTF_CFLAGS += ${COMMON_CFLAGS} TFTF_ASFLAGS += ${COMMON_ASFLAGS} TFTF_LDFLAGS += ${COMMON_LDFLAGS} +ifeq (${ENABLE_PAUTH},1) +TFTF_CFLAGS += -msign-return-address=non-leaf +endif + NS_BL1U_SOURCES += ${PLAT_SOURCES} ${LIBC_SRCS} NS_BL1U_INCLUDES += ${PLAT_INCLUDES} NS_BL1U_CFLAGS += ${COMMON_CFLAGS} diff --git a/defaults.mk b/defaults.mk index 0f74652..cf90aaf 100644 --- a/defaults.mk +++ b/defaults.mk @@ -1,5 +1,5 @@ # -# Copyright (c) 2018, Arm Limited. All rights reserved. +# Copyright (c) 2018-2019, Arm Limited. All rights reserved. # # SPDX-License-Identifier: BSD-3-Clause # @@ -26,6 +26,9 @@ DEBUG := 0 # Build platform DEFAULT_PLAT := fvp +# Enable Pointer Authentication support in the TFTF +ENABLE_PAUTH := 0 + # Whether the Firmware Update images (i.e. NS_BL1U and NS_BL2U images) should be # built. The platform makefile is free to override this value. FIRMWARE_UPDATE := 0 diff --git a/docs/porting-guide.rst b/docs/porting-guide.rst index 9c0812f..0decf1a 100644 --- a/docs/porting-guide.rst +++ b/docs/porting-guide.rst @@ -361,6 +361,20 @@ each CPU is specified by the platform defined constant ``PLATFORM_STACK_SIZE``. Common implementation of this function is provided in ``plat/common/aarch64/platform_mp_stack.S``. +Function : plat_init_apiakey +```````````````````````````` + +:: + + Argument : void + Return : uint64_t * + +This function returns a pointer to an array with the values used to set the +``APIAKey{Hi,Lo}_EL1`` registers. + +This function is only needed if ARMv8.3 pointer authentication is used by +building with ``ENABLE_PAUTH=1``. + Function : tftf_platform_end() `````````````````````````````` @@ -433,7 +447,7 @@ point to a text file which follows the following criteria: -------------- -*Copyright (c) 2018, Arm Limited. All rights reserved.* +*Copyright (c) 2018-2019, Arm Limited. All rights reserved.* .. _docs/psci-pd-tree.rst: https://github.com/ARM-software/arm-trusted-firmware/blob/master/docs/psci-pd-tree.rst .. _SP805: https://static.docs.arm.com/ddi0270/b/DDI0270.pdf diff --git a/docs/user-guide.rst b/docs/user-guide.rst index c9559d2..5bfab79 100644 --- a/docs/user-guide.rst +++ b/docs/user-guide.rst @@ -362,6 +362,11 @@ payload, whose simplistic build system is mostly independent. TFTF build options '''''''''''''''''' +- ``ENABLE_PAUTH``: Boolean option to enable ARMv8.3 Pointer Authentication + (``ARMv8.3-PAuth``) support in the Trusted Firmware-A Test Framework itself. + If enabled, it is needed to use a compiler that supports the option + ``-msign-return-address``. It defaults to 0. + - ``NEW_TEST_SESSION``: Choose whether a new test session should be started every time or whether the framework should determine whether a previous session was interrupted and resume it. It can take either 1 (always diff --git a/include/lib/aarch64/arch.h b/include/lib/aarch64/arch.h index 39b2a42..c4ec4ff 100644 --- a/include/lib/aarch64/arch.h +++ b/include/lib/aarch64/arch.h @@ -154,26 +154,22 @@ #define ID_AA64PFR0_GIC_SHIFT U(24) #define ID_AA64PFR0_GIC_WIDTH U(4) -#define ID_AA64PFR0_GIC_MASK ((ULL(1) << ID_AA64PFR0_GIC_WIDTH) - ULL(1)) +#define ID_AA64PFR0_GIC_MASK ULL(0xf) /* ID_AA64ISAR1_EL1 definitions */ +#define ID_AA64ISAR1_EL1 S3_0_C0_C6_1 #define ID_AA64ISAR1_GPI_SHIFT U(28) #define ID_AA64ISAR1_GPI_WIDTH U(4) +#define ID_AA64ISAR1_GPI_MASK ULL(0xf) #define ID_AA64ISAR1_GPA_SHIFT U(24) #define ID_AA64ISAR1_GPA_WIDTH U(4) +#define ID_AA64ISAR1_GPA_MASK ULL(0xf) #define ID_AA64ISAR1_API_SHIFT U(8) #define ID_AA64ISAR1_API_WIDTH U(4) +#define ID_AA64ISAR1_API_MASK ULL(0xf) #define ID_AA64ISAR1_APA_SHIFT U(4) #define ID_AA64ISAR1_APA_WIDTH U(4) - -#define ID_AA64ISAR1_GPI_MASK \ - (((ULL(1) << ID_AA64ISAR1_GPI_WIDTH) - ULL(1)) << ID_AA64ISAR1_GPI_SHIFT) -#define ID_AA64ISAR1_GPA_MASK \ - (((ULL(1) << ID_AA64ISAR1_GPA_WIDTH) - ULL(1)) << ID_AA64ISAR1_GPA_SHIFT) -#define ID_AA64ISAR1_API_MASK \ - (((ULL(1) << ID_AA64ISAR1_API_WIDTH) - ULL(1)) << ID_AA64ISAR1_API_SHIFT) -#define ID_AA64ISAR1_APA_MASK \ - (((ULL(1) << ID_AA64ISAR1_APA_WIDTH) - ULL(1)) << ID_AA64ISAR1_APA_SHIFT) +#define ID_AA64ISAR1_APA_MASK ULL(0xf) /* ID_AA64MMFR0_EL1 definitions */ #define ID_AA64MMFR0_EL1_PARANGE_SHIFT U(0) @@ -258,9 +254,7 @@ #define SCTLR_E0E_BIT (ULL(1) << 24) #define SCTLR_EE_BIT (ULL(1) << 25) #define SCTLR_UCI_BIT (ULL(1) << 26) -#define SCTLR_TRE_BIT (ULL(1) << 28) -#define SCTLR_AFE_BIT (ULL(1) << 29) -#define SCTLR_TE_BIT (ULL(1) << 30) +#define SCTLR_EnIA_BIT (ULL(1) << 31) #define SCTLR_DSSBS_BIT (ULL(1) << 44) #define SCTLR_RESET_VAL SCTLR_EL3_RES1 @@ -822,7 +816,16 @@ /******************************************************************************* * Armv8.3 Pointer Authentication Registers ******************************************************************************/ +#define APIAKeyLo_EL1 S3_0_C2_C1_0 +#define APIAKeyHi_EL1 S3_0_C2_C1_1 +#define APIBKeyLo_EL1 S3_0_C2_C1_2 +#define APIBKeyHi_EL1 S3_0_C2_C1_3 +#define APDAKeyLo_EL1 S3_0_C2_C2_0 +#define APDAKeyHi_EL1 S3_0_C2_C2_1 +#define APDBKeyLo_EL1 S3_0_C2_C2_2 +#define APDBKeyHi_EL1 S3_0_C2_C2_3 #define APGAKeyLo_EL1 S3_0_C2_C3_0 +#define APGAKeyHi_EL1 S3_0_C2_C3_1 /******************************************************************************* * Armv8.4 Data Independent Timing Registers diff --git a/include/lib/aarch64/arch_features.h b/include/lib/aarch64/arch_features.h index da8b6e4..6af1d03 100644 --- a/include/lib/aarch64/arch_features.h +++ b/include/lib/aarch64/arch_features.h @@ -23,6 +23,25 @@ static inline bool is_armv8_2_ttcnp_present(void) ID_AA64MMFR2_EL1_CNP_MASK) != 0U; } +static inline bool is_armv8_3_pauth_present(void) +{ + uint64_t mask = (ID_AA64ISAR1_GPI_MASK << ID_AA64ISAR1_GPI_SHIFT) | + (ID_AA64ISAR1_GPA_MASK << ID_AA64ISAR1_GPA_SHIFT) | + (ID_AA64ISAR1_API_MASK << ID_AA64ISAR1_API_SHIFT) | + (ID_AA64ISAR1_APA_MASK << ID_AA64ISAR1_APA_SHIFT); + + /* If any of the fields is not zero, PAuth is present */ + return (read_id_aa64isar1_el1() & mask) != 0U; +} + +static inline bool is_armv8_3_pauth_apa_api_present(void) +{ + uint64_t mask = (ID_AA64ISAR1_API_MASK << ID_AA64ISAR1_API_SHIFT) | + (ID_AA64ISAR1_APA_MASK << ID_AA64ISAR1_APA_SHIFT); + + return (read_id_aa64isar1_el1() & mask) != 0U; +} + static inline bool is_armv8_4_ttst_present(void) { return ((read_id_aa64mmfr2_el1() >> ID_AA64MMFR2_EL1_ST_SHIFT) & diff --git a/include/lib/aarch64/arch_helpers.h b/include/lib/aarch64/arch_helpers.h index 750bbbd..cdb01f0 100644 --- a/include/lib/aarch64/arch_helpers.h +++ b/include/lib/aarch64/arch_helpers.h @@ -444,7 +444,8 @@ DEFINE_RENAME_SYSREG_READ_FUNC(erxmisc1_el1, ERXMISC1_EL1) DEFINE_RENAME_SYSREG_READ_FUNC(id_aa64mmfr2_el1, ID_AA64MMFR2_EL1) /* Armv8.3 Pointer Authentication Registers */ -DEFINE_RENAME_SYSREG_RW_FUNCS(apgakeylo_el1, APGAKeyLo_EL1) +DEFINE_RENAME_SYSREG_RW_FUNCS(apiakeyhi_el1, APIAKeyHi_EL1) +DEFINE_RENAME_SYSREG_RW_FUNCS(apiakeylo_el1, APIAKeyLo_EL1) #define IS_IN_EL(x) \ (GET_EL(read_CurrentEl()) == MODE_EL##x) diff --git a/include/plat/common/platform.h b/include/plat/common/platform.h index 3f452ad..b30c41e 100644 --- a/include/plat/common/platform.h +++ b/include/plat/common/platform.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Arm Limited. All rights reserved. + * Copyright (c) 2018-2019, Arm Limited. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -67,6 +67,9 @@ int plat_crash_console_flush(void); /* Gets a handle for the initialised IO entity */ void plat_get_nvm_handle(uintptr_t *handle); +/* Initialize and get a pointer to a uint64_t[2] array with a 128-key */ +uint64_t *plat_init_apiakey(void); + /* * Returns the platform topology description array. The size of this * array should be PLATFORM_NUM_AFFS - PLATFORM_CORE_COUNT + 1. diff --git a/plat/arm/fvp/platform.mk b/plat/arm/fvp/platform.mk index 0230124..9fb84c2 100644 --- a/plat/arm/fvp/platform.mk +++ b/plat/arm/fvp/platform.mk @@ -1,5 +1,5 @@ # -# Copyright (c) 2018, Arm Limited. All rights reserved. +# Copyright (c) 2018-2019, Arm Limited. All rights reserved. # # SPDX-License-Identifier: BSD-3-Clause # @@ -23,4 +23,8 @@ CACTUS_SOURCES += plat/arm/fvp/${ARCH}/plat_helpers.S # Firmware update is implemented on FVP. FIRMWARE_UPDATE := 1 +ifeq (${ARCH},aarch64) +PLAT_SOURCES += plat/common/aarch64/pauth.c +endif + include plat/arm/common/arm_common.mk diff --git a/plat/common/aarch64/pauth.c b/plat/common/aarch64/pauth.c new file mode 100644 index 0000000..7555740 --- /dev/null +++ b/plat/common/aarch64/pauth.c @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <cdefs.h> +#include <stdint.h> + +/* + * Instruction pointer authentication key A. The low 64-bit are at [0], and the + * high bits at [1]. + */ +static uint64_t plat_apiakey[2]; + +/* + * This is only a toy implementation to generate a seemingly random 128-bit key + * from sp and x30 values. + */ +uint64_t *plat_init_apiakey(void) +{ + uintptr_t return_addr = (uintptr_t)__builtin_return_address(0U); + uintptr_t frame_addr = (uintptr_t)__builtin_frame_address(0U); + + plat_apiakey[0] = (return_addr << 13) ^ frame_addr; + plat_apiakey[1] = (frame_addr << 15) ^ return_addr; + + return plat_apiakey; +} diff --git a/tftf/framework/main.c b/tftf/framework/main.c index 67f565d..e84e450 100644 --- a/tftf/framework/main.c +++ b/tftf/framework/main.c @@ -1,10 +1,11 @@ /* - * Copyright (c) 2018, Arm Limited. All rights reserved. + * Copyright (c) 2018-2019, Arm Limited. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ #include <arch_helpers.h> +#include <arch_features.h> #include <assert.h> #include <debug.h> #include <drivers/arm/arm_gic.h> @@ -518,6 +519,30 @@ void __dead2 tftf_cold_boot_main(void) #endif tftf_arch_setup(); + + /* + * Enable pointer authentication. tftf_cold_boot_main() never returns, + * so it is safe to do it here. If this function was to return, the + * authentication would fail then. + */ +#if ENABLE_PAUTH + assert(is_armv8_3_pauth_apa_api_present()); + + uint64_t *apiakey = plat_init_apiakey(); + + write_apiakeylo_el1(apiakey[0]); + write_apiakeyhi_el1(apiakey[1]); + + if (IS_IN_EL2()) { + write_sctlr_el2(read_sctlr_el2() | SCTLR_EnIA_BIT); + } else { + assert(IS_IN_EL1()); + write_sctlr_el1(read_sctlr_el1() | SCTLR_EnIA_BIT); + } + + isb(); +#endif /* ENABLE_PAUTH */ + tftf_platform_setup(); tftf_init_topology(); |