diff options
author | Alexei Fedorov <Alexei.Fedorov@arm.com> | 2019-10-03 10:57:53 +0100 |
---|---|---|
committer | Alexei Fedorov <Alexei.Fedorov@arm.com> | 2019-10-04 14:20:21 +0100 |
commit | 719714f1895399e6d64049bed3b03c2597d95402 (patch) | |
tree | eb40c8e9ffd2dae7a99f42a8a72254c6152a85f3 | |
parent | e73248e004d971adb6259000d463c929f756a345 (diff) | |
download | tf-a-tests-719714f1895399e6d64049bed3b03c2597d95402.tar.gz |
TF-A Tests: Enable PAuth on warm boot path
This patch provides the following features and makes
modifications listed below:
- `plat_init_apiakey()` function is replaced with `init_apkey()`
which returns 128-bit value and uses Generic timer physical counter
value to increase the randomness of the generated key.
The new function can be used for generation of all ARMv8.3-PAuth keys.
- Source file `pauth.c` moved from `plat/common/aarch64`
to `lib/extensions/pauth/aarch64` folder which contains PAuth specific
code.
- Individual APIAKey key generation for each CPU on every warm boot.
- Per-CPU storage of APIAKey added in `tftf_suspend_context` structure.
- APIAKey key is saved/restored in arch context on entry/exit from
suspended state.
- Added `pauth_init_enable()` function which generates, programs
and enables APIAKey in EL1/EL2.
- Changes in documentation related to ARMv8.3-PAuth support.
Signed-off-by: Alexei Fedorov <Alexei.Fedorov@arm.com>
Change-Id: I964b8f964bb541cbb0b2f772cb0b07aed055fe36
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | docs/porting-guide.rst | 14 | ||||
-rw-r--r-- | docs/user-guide.rst | 2 | ||||
-rw-r--r-- | include/lib/aarch64/arch_features.h | 2 | ||||
-rw-r--r-- | include/lib/extensions/pauth.h | 20 | ||||
-rw-r--r-- | include/plat/common/platform.h | 3 | ||||
-rw-r--r-- | lib/extensions/pauth/aarch64/pauth.c | 26 | ||||
-rw-r--r-- | lib/extensions/pauth/aarch64/pauth_helpers.S | 53 | ||||
-rw-r--r-- | lib/power_management/hotplug/hotplug.c | 13 | ||||
-rw-r--r-- | lib/power_management/suspend/aarch64/asm_tftf_suspend.S | 38 | ||||
-rw-r--r-- | lib/power_management/suspend/suspend_private.h | 12 | ||||
-rw-r--r-- | plat/arm/fvp/platform.mk | 4 | ||||
-rw-r--r-- | tftf/framework/main.c | 20 |
13 files changed, 159 insertions, 50 deletions
@@ -224,7 +224,7 @@ TFTF_ASFLAGS += ${COMMON_ASFLAGS} TFTF_LDFLAGS += ${COMMON_LDFLAGS} ifeq (${ENABLE_PAUTH},1) -TFTF_CFLAGS += -msign-return-address=non-leaf +TFTF_CFLAGS += -mbranch-protection=pac-ret endif NS_BL1U_SOURCES += ${PLAT_SOURCES} ${LIBC_SRCS} diff --git a/docs/porting-guide.rst b/docs/porting-guide.rst index 6a5abb727..9759c9865 100644 --- a/docs/porting-guide.rst +++ b/docs/porting-guide.rst @@ -361,20 +361,6 @@ 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() `````````````````````````````` diff --git a/docs/user-guide.rst b/docs/user-guide.rst index ef12c90fd..2e6f7bae5 100644 --- a/docs/user-guide.rst +++ b/docs/user-guide.rst @@ -401,7 +401,7 @@ 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. + ``-mbranch-protection`` (GCC 9 and later). 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 diff --git a/include/lib/aarch64/arch_features.h b/include/lib/aarch64/arch_features.h index 5891c7a71..20240ec4d 100644 --- a/include/lib/aarch64/arch_features.h +++ b/include/lib/aarch64/arch_features.h @@ -51,7 +51,7 @@ static inline bool is_armv8_3_pauth_apa_api_present(void) static inline bool is_armv8_3_pauth_gpa_gpi_present(void) { uint64_t mask = (ID_AA64ISAR1_GPI_MASK << ID_AA64ISAR1_GPI_SHIFT) | - (ID_AA64ISAR1_GPA_MASK << ID_AA64ISAR1_GPA_SHIFT); + (ID_AA64ISAR1_GPA_MASK << ID_AA64ISAR1_GPA_SHIFT); return (read_id_aa64isar1_el1() & mask) != 0U; } diff --git a/include/lib/extensions/pauth.h b/include/lib/extensions/pauth.h new file mode 100644 index 000000000..a4da00990 --- /dev/null +++ b/include/lib/extensions/pauth.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PAUTH_H +#define PAUTH_H + +#include <stdint.h> + +#ifdef __aarch64__ +/* Initialize 128-bit ARMv8.3-PAuth key */ +uint128_t init_apkey(void); + +/* Program APIAKey_EL1 key and enable ARMv8.3-PAuth */ +void pauth_init_enable(void); +#endif /* __aarch64__ */ + +#endif /* PAUTH_H */ diff --git a/include/plat/common/platform.h b/include/plat/common/platform.h index b30c41ebd..f3536bab7 100644 --- a/include/plat/common/platform.h +++ b/include/plat/common/platform.h @@ -67,9 +67,6 @@ 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/lib/extensions/pauth/aarch64/pauth.c b/lib/extensions/pauth/aarch64/pauth.c new file mode 100644 index 000000000..03de468b4 --- /dev/null +++ b/lib/extensions/pauth/aarch64/pauth.c @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch_helpers.h> +#include <cdefs.h> +#include <stdint.h> + +/* + * This is only a toy implementation to generate a seemingly random + * 128-bit key from sp, x30 and cntpct_el0 values. + */ +uint128_t init_apkey(void) +{ + uint64_t return_addr = (uint64_t)__builtin_return_address(0U); + uint64_t frame_addr = (uint64_t)__builtin_frame_address(0U); + + uint64_t cntpct = read_cntpct_el0(); + + uint64_t key_lo = (return_addr << 13) ^ frame_addr ^ cntpct; + uint64_t key_hi = (frame_addr << 15) ^ return_addr ^ cntpct; + + return ((uint128_t)(key_hi) << 64) | key_lo; +} diff --git a/lib/extensions/pauth/aarch64/pauth_helpers.S b/lib/extensions/pauth/aarch64/pauth_helpers.S new file mode 100644 index 000000000..e15cac90f --- /dev/null +++ b/lib/extensions/pauth/aarch64/pauth_helpers.S @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch.h> +#include <asm_macros.S> + + .global pauth_init_enable + +/* ----------------------------------------------------------- + * Program APIAKey_EL1 key and enable Pointer Authentication + * of instruction addresses in the current translation regime + * for the calling CPU. + * ----------------------------------------------------------- + */ +func pauth_init_enable + stp x29, x30, [sp, #-16]! + + /* Initialize platform key */ + bl init_apkey + + /* + * Program instruction key A used by + * the Trusted Firmware Test Framework + */ + msr APIAKeyLo_EL1, x0 + msr APIAKeyHi_EL1, x1 + + /* Detect Current Exception level */ + mrs x0, CurrentEL + cmp x0, #(MODE_EL1 << MODE_EL_SHIFT) + b.eq enable_el1 + + /* Enable EL2 pointer authentication */ + mrs x0, sctlr_el2 + orr x0, x0, #SCTLR_EnIA_BIT + msr sctlr_el2, x0 + b enable_exit + + /* Enable EL1 pointer authentication */ +enable_el1: + mrs x0, sctlr_el1 + orr x0, x0, #SCTLR_EnIA_BIT + msr sctlr_el1, x0 + +enable_exit: + isb + + ldp x29, x30, [sp], #16 + ret +endfunc pauth_init_enable diff --git a/lib/power_management/hotplug/hotplug.c b/lib/power_management/hotplug/hotplug.c index 37bfc06bf..76fa287b9 100644 --- a/lib/power_management/hotplug/hotplug.c +++ b/lib/power_management/hotplug/hotplug.c @@ -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 */ @@ -11,6 +11,7 @@ #include <drivers/arm/arm_gic.h> #include <drivers/console.h> #include <irq.h> +#include <pauth.h> #include <platform.h> #include <platform_def.h> #include <power_management.h> @@ -288,6 +289,16 @@ void __dead2 tftf_warm_boot_main(void) { /* Initialise the CPU */ tftf_arch_setup(); + +#if ENABLE_PAUTH + /* + * Program APIAKey_EL1 key and enable ARMv8.3-PAuth here as this + * function doesn't return, and RETAA instuction won't be executed, + * what would cause translation fault otherwise. + */ + pauth_init_enable(); +#endif /* ENABLE_PAUTH */ + arm_gic_setup_local(); /* Enable the SGI used by the timer management framework */ diff --git a/lib/power_management/suspend/aarch64/asm_tftf_suspend.S b/lib/power_management/suspend/aarch64/asm_tftf_suspend.S index 692baded6..09950b5c0 100644 --- a/lib/power_management/suspend/aarch64/asm_tftf_suspend.S +++ b/lib/power_management/suspend/aarch64/asm_tftf_suspend.S @@ -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 */ @@ -54,6 +54,11 @@ func __tftf_suspend endfunc __tftf_suspend func __tftf_save_arch_context +#if ENABLE_PAUTH + mrs x1, APIAKeyLo_EL1 + mrs x2, APIAKeyHi_EL1 + stp x1, x2, [x0, #SUSPEND_CTX_APIAKEY_OFFSET] +#endif JUMP_EL1_OR_EL2 x1, 1f, 2f, dead 1: mrs x1, mair_el1 mrs x2, cpacr_el1 @@ -61,9 +66,9 @@ func __tftf_save_arch_context mrs x4, tcr_el1 mrs x5, vbar_el1 mrs x6, sctlr_el1 - stp x1, x2, [x0] - stp x3, x4, [x0, #16] - stp x5, x6, [x0, #32] + stp x1, x2, [x0, #SUSPEND_CTX_MAIR_OFFSET] + stp x3, x4, [x0, #SUSPEND_CTX_TTBR0_OFFSET] + stp x5, x6, [x0, #SUSPEND_CTX_VBAR_OFFSET] ret 2: mrs x1, mair_el2 @@ -72,9 +77,9 @@ func __tftf_save_arch_context mrs x4, tcr_el2 mrs x5, vbar_el2 mrs x6, sctlr_el2 - stp x1, x2, [x0] - stp x3, x4, [x0, #16] - stp x5, x6, [x0, #32] + stp x1, x2, [x0, #SUSPEND_CTX_MAIR_OFFSET] + stp x3, x4, [x0, #SUSPEND_CTX_TTBR0_OFFSET] + stp x5, x6, [x0, #SUSPEND_CTX_VBAR_OFFSET] ret endfunc __tftf_save_arch_context @@ -86,9 +91,9 @@ func __tftf_cpu_resume_ep JUMP_EL1_OR_EL2 x1, 1f, 2f, dead 1: /* Invalidate local tlb entries before turning on MMU */ tlbi vmalle1 - ldp x1, x2, [x0] - ldp x3, x4, [x0, #16] - ldp x5, x6, [x0, #32] + ldp x1, x2, [x0, #SUSPEND_CTX_MAIR_OFFSET] + ldp x3, x4, [x0, #SUSPEND_CTX_TTBR0_OFFSET] + ldp x5, x6, [x0, #SUSPEND_CTX_VBAR_OFFSET] msr mair_el1, x1 msr cpacr_el1, x2 msr ttbr0_el1, x3 @@ -101,13 +106,13 @@ func __tftf_cpu_resume_ep msr sctlr_el1, x6 /* Ensure the MMU enable takes effect immediately */ isb - b restore_callee_regs + b restore_callee_regs /* Invalidate local tlb entries before turning on MMU */ 2: tlbi alle2 - ldp x1, x2, [x0] - ldp x3, x4, [x0, #16] - ldp x5, x6, [x0, #32] + ldp x1, x2, [x0, #SUSPEND_CTX_MAIR_OFFSET] + ldp x3, x4, [x0, #SUSPEND_CTX_TTBR0_OFFSET] + ldp x5, x6, [x0, #SUSPEND_CTX_VBAR_OFFSET] msr mair_el2, x1 msr hcr_el2, x2 msr ttbr0_el2, x3 @@ -122,6 +127,11 @@ func __tftf_cpu_resume_ep isb restore_callee_regs: +#if ENABLE_PAUTH + ldp x1, x2, [x0, #SUSPEND_CTX_APIAKEY_OFFSET] + msr APIAKeyLo_EL1, x1 + msr APIAKeyHi_EL1, x2 +#endif ldr x2, [x0, #SUSPEND_CTX_SP_OFFSET] mov sp, x2 ldr w1, [x0, #SUSPEND_CTX_SAVE_SYSTEM_CTX_OFFSET] diff --git a/lib/power_management/suspend/suspend_private.h b/lib/power_management/suspend/suspend_private.h index b67bbab0b..bc2f3a600 100644 --- a/lib/power_management/suspend/suspend_private.h +++ b/lib/power_management/suspend/suspend_private.h @@ -9,11 +9,21 @@ /* * Number of system registers we need to save/restore across a CPU suspend: - * MAIR, CPACR_EL1/HCR_EL2, TTBR0, TCR, VBAR and SCTLR. + * MAIR, CPACR_EL1/HCR_EL2, TTBR0, TCR, VBAR, SCTLR, + * APIAKeyLo_EL1 and APIAKeyHi_EL1 (if enabled). */ +#if ENABLE_PAUTH +#define NR_CTX_REGS 8 +#else #define NR_CTX_REGS 6 +#endif /* Offsets of the fields in the context structure. Needed by asm code. */ +#define SUSPEND_CTX_MAIR_OFFSET 0 +#define SUSPEND_CTX_TTBR0_OFFSET 16 +#define SUSPEND_CTX_VBAR_OFFSET 32 +#define SUSPEND_CTX_APIAKEY_OFFSET 48 + #define SUSPEND_CTX_SP_OFFSET (8 * NR_CTX_REGS) #define SUSPEND_CTX_SAVE_SYSTEM_CTX_OFFSET (SUSPEND_CTX_SP_OFFSET + 8) diff --git a/plat/arm/fvp/platform.mk b/plat/arm/fvp/platform.mk index 9fb84c276..bf4075dd7 100644 --- a/plat/arm/fvp/platform.mk +++ b/plat/arm/fvp/platform.mk @@ -24,7 +24,9 @@ CACTUS_SOURCES += plat/arm/fvp/${ARCH}/plat_helpers.S FIRMWARE_UPDATE := 1 ifeq (${ARCH},aarch64) -PLAT_SOURCES += plat/common/aarch64/pauth.c +# ARMv8.3 Pointer Authentication support files +PLAT_SOURCES += lib/extensions/pauth/aarch64/pauth.c \ + lib/extensions/pauth/aarch64/pauth_helpers.S endif include plat/arm/common/arm_common.mk diff --git a/tftf/framework/main.c b/tftf/framework/main.c index e84e45070..a2e84b7ea 100644 --- a/tftf/framework/main.c +++ b/tftf/framework/main.c @@ -12,6 +12,7 @@ #include <irq.h> #include <mmio.h> #include <nvm.h> +#include <pauth.h> #include <plat_topology.h> #include <platform.h> #include <platform_def.h> @@ -528,19 +529,12 @@ void __dead2 tftf_cold_boot_main(void) #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(); + /* + * Program APIAKey_EL1 key and enable ARMv8.3-PAuth here as this + * function doesn't return, and RETAA instuction won't be executed, + * what would cause translation fault otherwise. + */ + pauth_init_enable(); #endif /* ENABLE_PAUTH */ tftf_platform_setup(); |