From 4d1ccf0ecc7d90df438148c633291723d095f979 Mon Sep 17 00:00:00 2001 From: Antonio Nino Diaz Date: Wed, 30 Jan 2019 20:41:31 +0000 Subject: [PATCH 1/9] Cleanup context handling library Minor style cleanup. Change-Id: Ief19dece41a989e2e8157859a265701549f6c585 Signed-off-by: Antonio Nino Diaz --- include/lib/el3_runtime/aarch64/context.h | 46 +++++++++++------------ lib/el3_runtime/aarch64/context.S | 22 ++++++----- 2 files changed, 34 insertions(+), 34 deletions(-) diff --git a/include/lib/el3_runtime/aarch64/context.h b/include/lib/el3_runtime/aarch64/context.h index 70c50aae2..786dcf5b0 100644 --- a/include/lib/el3_runtime/aarch64/context.h +++ b/include/lib/el3_runtime/aarch64/context.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -104,25 +104,30 @@ #define CTX_SPSR_FIQ U(0xd8) #define CTX_DACR32_EL2 U(0xe0) #define CTX_IFSR32_EL2 U(0xe8) -#define CTX_TIMER_SYSREGS_OFF U(0xf0) /* Align to the next 16 byte boundary */ +#define CTX_AARCH32_END U(0xf0) /* Align to the next 16 byte boundary */ #else -#define CTX_TIMER_SYSREGS_OFF U(0xc0) /* Align to the next 16 byte boundary */ -#endif /* __CTX_INCLUDE_AARCH32_REGS__ */ +#define CTX_AARCH32_END U(0xc0) /* Align to the next 16 byte boundary */ +#endif /* CTX_INCLUDE_AARCH32_REGS */ /* * If the timer registers aren't saved and restored, we don't have to reserve * space for them in the context */ #if NS_TIMER_SWITCH -#define CTX_CNTP_CTL_EL0 (CTX_TIMER_SYSREGS_OFF + U(0x0)) -#define CTX_CNTP_CVAL_EL0 (CTX_TIMER_SYSREGS_OFF + U(0x8)) -#define CTX_CNTV_CTL_EL0 (CTX_TIMER_SYSREGS_OFF + U(0x10)) -#define CTX_CNTV_CVAL_EL0 (CTX_TIMER_SYSREGS_OFF + U(0x18)) -#define CTX_CNTKCTL_EL1 (CTX_TIMER_SYSREGS_OFF + U(0x20)) -#define CTX_SYSREGS_END (CTX_TIMER_SYSREGS_OFF + U(0x30)) /* Align to the next 16 byte boundary */ +#define CTX_CNTP_CTL_EL0 (CTX_AARCH32_END + U(0x0)) +#define CTX_CNTP_CVAL_EL0 (CTX_AARCH32_END + U(0x8)) +#define CTX_CNTV_CTL_EL0 (CTX_AARCH32_END + U(0x10)) +#define CTX_CNTV_CVAL_EL0 (CTX_AARCH32_END + U(0x18)) +#define CTX_CNTKCTL_EL1 (CTX_AARCH32_END + U(0x20)) +#define CTX_TIMER_SYSREGS_END (CTX_AARCH32_END + U(0x30)) /* Align to the next 16 byte boundary */ #else -#define CTX_SYSREGS_END CTX_TIMER_SYSREGS_OFF -#endif /* __NS_TIMER_SWITCH__ */ +#define CTX_TIMER_SYSREGS_END CTX_AARCH32_END +#endif /* NS_TIMER_SWITCH */ + +/* + * End of system registers. + */ +#define CTX_SYSREGS_END CTX_TIMER_SYSREGS_END /******************************************************************************* * Constants that allow assembler code to access members of and the 'fp_regs' @@ -174,6 +179,9 @@ #define CTX_FPREGS_END U(0) #endif +/******************************************************************************* + * Registers related to CVE-2018-3639 + ******************************************************************************/ #define CTX_CVE_2018_3639_OFFSET (CTX_FPREGS_OFFSET + CTX_FPREGS_END) #define CTX_CVE_2018_3639_DISABLE U(0) #define CTX_CVE_2018_3639_END U(0x10) /* Align to the next 16 byte boundary */ @@ -182,8 +190,6 @@ #include -#include /* for CACHE_WRITEBACK_GRANULE */ - #include /* @@ -200,7 +206,7 @@ #define CTX_GPREG_ALL (CTX_GPREGS_END >> DWORD_SHIFT) #define CTX_SYSREG_ALL (CTX_SYSREGS_END >> DWORD_SHIFT) #if CTX_INCLUDE_FPREGS -#define CTX_FPREG_ALL (CTX_FPREGS_END >> DWORD_SHIFT) +# define CTX_FPREG_ALL (CTX_FPREGS_END >> DWORD_SHIFT) #endif #define CTX_EL3STATE_ALL (CTX_EL3STATE_END >> DWORD_SHIFT) #define CTX_CVE_2018_3639_ALL (CTX_CVE_2018_3639_END >> DWORD_SHIFT) @@ -269,7 +275,7 @@ typedef struct cpu_context { /* Macros to access members of the 'cpu_context_t' structure */ #define get_el3state_ctx(h) (&((cpu_context_t *) h)->el3state_ctx) #if CTX_INCLUDE_FPREGS -#define get_fpregs_ctx(h) (&((cpu_context_t *) h)->fpregs_ctx) +# define get_fpregs_ctx(h) (&((cpu_context_t *) h)->fpregs_ctx) #endif #define get_sysregs_ctx(h) (&((cpu_context_t *) h)->sysregs_ctx) #define get_gpregs_ctx(h) (&((cpu_context_t *) h)->gpregs_ctx) @@ -339,14 +345,6 @@ void fpregs_context_save(fp_regs_t *regs); void fpregs_context_restore(fp_regs_t *regs); #endif - -#undef CTX_SYSREG_ALL -#if CTX_INCLUDE_FPREGS -#undef CTX_FPREG_ALL -#endif -#undef CTX_GPREG_ALL -#undef CTX_EL3STATE_ALL - #endif /* __ASSEMBLY__ */ #endif /* CONTEXT_H */ diff --git a/lib/el3_runtime/aarch64/context.S b/lib/el3_runtime/aarch64/context.S index 707e6dbd4..1f8e23d27 100644 --- a/lib/el3_runtime/aarch64/context.S +++ b/lib/el3_runtime/aarch64/context.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -332,9 +332,10 @@ func save_gp_registers ret endfunc save_gp_registers -/* +/* ----------------------------------------------------- * This function restores all general purpose registers except x30 from the * CPU context. x30 register must be explicitly restored by the caller. + * ----------------------------------------------------- */ func restore_gp_registers ldp x0, x1, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X0] @@ -357,9 +358,10 @@ func restore_gp_registers ret endfunc restore_gp_registers -/* +/* ----------------------------------------------------- * Restore general purpose registers (including x30), and exit EL3 via. ERET to * a lower exception level. + * ----------------------------------------------------- */ func restore_gp_registers_eret bl restore_gp_registers @@ -377,12 +379,12 @@ func restore_gp_registers_eret eret endfunc restore_gp_registers_eret - /* ----------------------------------------------------- - * This routine assumes that the SP_EL3 is pointing to - * a valid context structure from where the gp regs and - * other special registers can be retrieved. - * ----------------------------------------------------- - */ +/* ----------------------------------------------------- + * This routine assumes that the SP_EL3 is pointing to + * a valid context structure from where the gp regs and + * other special registers can be retrieved. + * ----------------------------------------------------- + */ func el3_exit /* ----------------------------------------------------- * Save the current SP_EL0 i.e. the EL3 runtime stack @@ -410,9 +412,9 @@ func el3_exit cmp x17, xzr beq 1f blr x17 +1: #endif -1: /* Restore saved general purpose registers and return */ b restore_gp_registers_eret endfunc el3_exit From 5283962ebaf77850d68bb457608ede5174e43159 Mon Sep 17 00:00:00 2001 From: Antonio Nino Diaz Date: Thu, 31 Jan 2019 11:58:00 +0000 Subject: [PATCH 2/9] Add ARMv8.3-PAuth registers to CPU context 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 feature adds several registers to EL1. A new option called CTX_INCLUDE_PAUTH_REGS has been added to select if the TF needs to save them during Non-secure <-> Secure world switches. This option must be enabled if the hardware has the registers or the values will be leaked during world switches. To prevent leaks, this patch also disables pointer authentication in the Secure world if CTX_INCLUDE_PAUTH_REGS is 0. Any attempt to use it will be trapped in EL3. Change-Id: I27beba9907b9a86c6df1d0c5bf6180c972830855 Signed-off-by: Antonio Nino Diaz --- Makefile | 2 + bl31/aarch64/ea_delegate.S | 10 ++- bl31/aarch64/runtime_exceptions.S | 17 ++++- docs/firmware-design.rst | 9 ++- docs/user-guide.rst | 6 ++ include/arch/aarch64/arch.h | 29 +++++---- include/arch/aarch64/el3_common_macros.S | 11 +++- include/lib/el3_runtime/aarch64/context.h | 39 +++++++++++ lib/el3_runtime/aarch64/context.S | 79 +++++++++++++++++++++++ lib/el3_runtime/aarch64/context_mgmt.c | 14 ++++ make_helpers/defaults.mk | 5 ++ 11 files changed, 201 insertions(+), 20 deletions(-) diff --git a/Makefile b/Makefile index 34f6890bb..ebc885091 100644 --- a/Makefile +++ b/Makefile @@ -580,6 +580,7 @@ $(eval $(call assert_boolean,COLD_BOOT_SINGLE_CPU)) $(eval $(call assert_boolean,CREATE_KEYS)) $(eval $(call assert_boolean,CTX_INCLUDE_AARCH32_REGS)) $(eval $(call assert_boolean,CTX_INCLUDE_FPREGS)) +$(eval $(call assert_boolean,CTX_INCLUDE_PAUTH_REGS)) $(eval $(call assert_boolean,DEBUG)) $(eval $(call assert_boolean,DYN_DISABLE_AUTH)) $(eval $(call assert_boolean,EL3_EXCEPTION_HANDLING)) @@ -633,6 +634,7 @@ $(eval $(call add_define,ARM_ARCH_MINOR)) $(eval $(call add_define,COLD_BOOT_SINGLE_CPU)) $(eval $(call add_define,CTX_INCLUDE_AARCH32_REGS)) $(eval $(call add_define,CTX_INCLUDE_FPREGS)) +$(eval $(call add_define,CTX_INCLUDE_PAUTH_REGS)) $(eval $(call add_define,EL3_EXCEPTION_HANDLING)) $(eval $(call add_define,ENABLE_AMU)) $(eval $(call add_define,ENABLE_ASSERTIONS)) diff --git a/bl31/aarch64/ea_delegate.S b/bl31/aarch64/ea_delegate.S index 0c8cfa8f9..d5ecfc50e 100644 --- a/bl31/aarch64/ea_delegate.S +++ b/bl31/aarch64/ea_delegate.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -68,6 +68,10 @@ func enter_lower_el_sync_ea /* Save GP registers */ bl save_gp_registers +#if CTX_INCLUDE_PAUTH_REGS + bl pauth_context_save +#endif + /* Setup exception class and syndrome arguments for platform handler */ mov x0, #ERROR_EA_SYNC mrs x1, esr_el3 @@ -98,6 +102,10 @@ func enter_lower_el_async_ea /* Save GP registers */ bl save_gp_registers +#if CTX_INCLUDE_PAUTH_REGS + bl pauth_context_save +#endif + /* Setup exception class and syndrome arguments for platform handler */ mov x0, #ERROR_EA_ASYNC mrs x1, esr_el3 diff --git a/bl31/aarch64/runtime_exceptions.S b/bl31/aarch64/runtime_exceptions.S index 4f53b8e70..cea7a8a1e 100644 --- a/bl31/aarch64/runtime_exceptions.S +++ b/bl31/aarch64/runtime_exceptions.S @@ -120,7 +120,13 @@ * --------------------------------------------------------------------- */ .macro handle_interrupt_exception label + bl save_gp_registers + +#if CTX_INCLUDE_PAUTH_REGS + bl pauth_context_save +#endif + /* Save the EL3 system registers needed to return from this exception */ mrs x0, spsr_el3 mrs x1, elr_el3 @@ -320,14 +326,21 @@ smc_handler32: tbnz x0, #FUNCID_CC_SHIFT, smc_prohibited smc_handler64: + /* NOTE: The code below must preserve x0-x4 */ + + /* Save general purpose registers */ + bl save_gp_registers + +#if CTX_INCLUDE_PAUTH_REGS + bl pauth_context_save +#endif + /* * Populate the parameters for the SMC handler. * We already have x0-x4 in place. x5 will point to a cookie (not used * now). x6 will point to the context structure (SP_EL3) and x7 will * contain flags we need to pass to the handler. */ - bl save_gp_registers - mov x5, xzr mov x6, sp diff --git a/docs/firmware-design.rst b/docs/firmware-design.rst index 299654fc2..808afeedb 100644 --- a/docs/firmware-design.rst +++ b/docs/firmware-design.rst @@ -2558,8 +2558,13 @@ Armv8.2-A Armv8.3-A ~~~~~~~~~ -- Pointer Authentication features of Armv8.3-A are unconditionally enabled so - that lower ELs are allowed to use them without causing a trap to EL3. +- Pointer authentication features of Armv8.3-A are unconditionally enabled in + the Non-secure world so that lower ELs are allowed to use them without + causing a trap to EL3. + + In order to enable the Secure world to use it, ``CTX_INCLUDE_PAUTH_REGS`` + must be set to 1. This will add all pointer authentication system registers + to the context that is saved when doing a world switch. Armv7-A ~~~~~~~ diff --git a/docs/user-guide.rst b/docs/user-guide.rst index 4ff1c7270..70c1d5a91 100644 --- a/docs/user-guide.rst +++ b/docs/user-guide.rst @@ -358,6 +358,12 @@ Common build options registers to be included when saving and restoring the CPU context. Default is 0. +- ``CTX_INCLUDE_PAUTH_REGS``: Boolean option that, when set to 1, will cause + the ARMv8.3-PAuth registers to be included when saving and restoring the CPU + context. Note that if the hardware supports this extension and this option is + set to 0 the value of the registers will be leaked between Secure and + Non-secure worlds. The default is 0. + - ``DEBUG``: Chooses between a debug and release build. It can take either 0 (release) or 1 (debug) as values. 0 is the default. diff --git a/include/arch/aarch64/arch.h b/include/arch/aarch64/arch.h index c65b3a3b9..b9d1f9fae 100644 --- a/include/arch/aarch64/arch.h +++ b/include/arch/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 @@ -823,7 +817,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/arch/aarch64/el3_common_macros.S b/include/arch/aarch64/el3_common_macros.S index 5f5e0c69b..22b32b491 100644 --- a/include/arch/aarch64/el3_common_macros.S +++ b/include/arch/aarch64/el3_common_macros.S @@ -76,9 +76,16 @@ * authentication instructions from lower ELs. * --------------------------------------------------------------------- */ - mov_imm x0, ((SCR_RESET_VAL | SCR_EA_BIT | SCR_SIF_BIT | \ - SCR_API_BIT | SCR_APK_BIT) \ + mov_imm x0, ((SCR_RESET_VAL | SCR_EA_BIT | SCR_SIF_BIT) \ & ~(SCR_TWE_BIT | SCR_TWI_BIT | SCR_SMD_BIT)) +#if CTX_INCLUDE_PAUTH_REGS + /* + * If the pointer authentication registers are saved during world + * switches, enable pointer authentication everywhere, as it is safe to + * do so. + */ + orr x0, x0, #(SCR_API_BIT | SCR_APK_BIT) +#endif msr scr_el3, x0 /* --------------------------------------------------------------------- diff --git a/include/lib/el3_runtime/aarch64/context.h b/include/lib/el3_runtime/aarch64/context.h index 786dcf5b0..5bd0de424 100644 --- a/include/lib/el3_runtime/aarch64/context.h +++ b/include/lib/el3_runtime/aarch64/context.h @@ -186,6 +186,27 @@ #define CTX_CVE_2018_3639_DISABLE U(0) #define CTX_CVE_2018_3639_END U(0x10) /* Align to the next 16 byte boundary */ +/******************************************************************************* + * Registers related to ARMv8.3-PAuth. + ******************************************************************************/ +#define CTX_PAUTH_REGS_OFFSET (CTX_CVE_2018_3639_OFFSET + CTX_CVE_2018_3639_END) +#if CTX_INCLUDE_PAUTH_REGS +#define CTX_PACIAKEY_LO U(0x0) +#define CTX_PACIAKEY_HI U(0x8) +#define CTX_PACIBKEY_LO U(0x10) +#define CTX_PACIBKEY_HI U(0x18) +#define CTX_PACDAKEY_LO U(0x20) +#define CTX_PACDAKEY_HI U(0x28) +#define CTX_PACDBKEY_LO U(0x30) +#define CTX_PACDBKEY_HI U(0x38) +#define CTX_PACGAKEY_LO U(0x40) +#define CTX_PACGAKEY_HI U(0x48) +#define CTX_PACGAKEY_END U(0x50) +#define CTX_PAUTH_REGS_END U(0x60) /* Align to the next 16 byte boundary */ +#else +#define CTX_PAUTH_REGS_END U(0) +#endif /* CTX_INCLUDE_PAUTH_REGS */ + #ifndef __ASSEMBLY__ #include @@ -210,6 +231,9 @@ #endif #define CTX_EL3STATE_ALL (CTX_EL3STATE_END >> DWORD_SHIFT) #define CTX_CVE_2018_3639_ALL (CTX_CVE_2018_3639_END >> DWORD_SHIFT) +#if CTX_INCLUDE_PAUTH_REGS +# define CTX_PAUTH_REGS_ALL (CTX_PAUTH_REGS_END >> DWORD_SHIFT) +#endif /* * AArch64 general purpose register context structure. Usually x0-x18, @@ -245,6 +269,11 @@ DEFINE_REG_STRUCT(el3_state, CTX_EL3STATE_ALL); /* Function pointer used by CVE-2018-3639 dynamic mitigation */ DEFINE_REG_STRUCT(cve_2018_3639, CTX_CVE_2018_3639_ALL); +/* Registers associated to ARMv8.3-PAuth */ +#if CTX_INCLUDE_PAUTH_REGS +DEFINE_REG_STRUCT(pauth, CTX_PAUTH_REGS_ALL); +#endif + /* * Macros to access members of any of the above structures using their * offsets @@ -270,6 +299,9 @@ typedef struct cpu_context { fp_regs_t fpregs_ctx; #endif cve_2018_3639_t cve_2018_3639_ctx; +#if CTX_INCLUDE_PAUTH_REGS + pauth_t pauth_ctx; +#endif } cpu_context_t; /* Macros to access members of the 'cpu_context_t' structure */ @@ -280,6 +312,9 @@ typedef struct cpu_context { #define get_sysregs_ctx(h) (&((cpu_context_t *) h)->sysregs_ctx) #define get_gpregs_ctx(h) (&((cpu_context_t *) h)->gpregs_ctx) #define get_cve_2018_3639_ctx(h) (&((cpu_context_t *) h)->cve_2018_3639_ctx) +#if CTX_INCLUDE_PAUTH_REGS +# define get_pauth_ctx(h) (&((cpu_context_t *) h)->pauth_ctx) +#endif /* * Compile time assertions related to the 'cpu_context' structure to @@ -298,6 +333,10 @@ CASSERT(CTX_EL3STATE_OFFSET == __builtin_offsetof(cpu_context_t, el3state_ctx), assert_core_context_el3state_offset_mismatch); CASSERT(CTX_CVE_2018_3639_OFFSET == __builtin_offsetof(cpu_context_t, cve_2018_3639_ctx), \ assert_core_context_cve_2018_3639_offset_mismatch); +#if CTX_INCLUDE_PAUTH_REGS +CASSERT(CTX_PAUTH_REGS_OFFSET == __builtin_offsetof(cpu_context_t, pauth_ctx), \ + assert_core_context_pauth_offset_mismatch); +#endif /* * Helper macro to set the general purpose registers that correspond to diff --git a/lib/el3_runtime/aarch64/context.S b/lib/el3_runtime/aarch64/context.S index 1f8e23d27..f5fed72d0 100644 --- a/lib/el3_runtime/aarch64/context.S +++ b/lib/el3_runtime/aarch64/context.S @@ -13,6 +13,10 @@ #if CTX_INCLUDE_FPREGS .global fpregs_context_save .global fpregs_context_restore +#endif +#if CTX_INCLUDE_PAUTH_REGS + .global pauth_context_restore + .global pauth_context_save #endif .global save_gp_registers .global restore_gp_registers @@ -299,6 +303,76 @@ func fpregs_context_restore endfunc fpregs_context_restore #endif /* CTX_INCLUDE_FPREGS */ +#if CTX_INCLUDE_PAUTH_REGS +/* ----------------------------------------------------- + * The following function strictly follows the AArch64 + * PCS to use x9-x17 (temporary caller-saved registers) + * to save the ARMv8.3-PAuth register context. It assumes + * that 'sp' is pointing to a 'cpu_context_t' structure + * to where the register context will be saved. + * ----------------------------------------------------- + */ +func pauth_context_save + add x11, sp, #CTX_PAUTH_REGS_OFFSET + + mrs x9, APIAKeyLo_EL1 + mrs x10, APIAKeyHi_EL1 + stp x9, x10, [x11, #CTX_PACIAKEY_LO] + + mrs x9, APIBKeyLo_EL1 + mrs x10, APIBKeyHi_EL1 + stp x9, x10, [x11, #CTX_PACIBKEY_LO] + + mrs x9, APDAKeyLo_EL1 + mrs x10, APDAKeyHi_EL1 + stp x9, x10, [x11, #CTX_PACDAKEY_LO] + + mrs x9, APDBKeyLo_EL1 + mrs x10, APDBKeyHi_EL1 + stp x9, x10, [x11, #CTX_PACDBKEY_LO] + + mrs x9, APGAKeyLo_EL1 + mrs x10, APGAKeyHi_EL1 + stp x9, x10, [x11, #CTX_PACGAKEY_LO] + + ret +endfunc pauth_context_save + +/* ----------------------------------------------------- + * The following function strictly follows the AArch64 + * PCS to use x9-x17 (temporary caller-saved registers) + * to restore the ARMv8.3-PAuth register context. It assumes + * that 'sp' is pointing to a 'cpu_context_t' structure + * from where the register context will be restored. + * ----------------------------------------------------- + */ +func pauth_context_restore + add x11, sp, #CTX_PAUTH_REGS_OFFSET + + ldp x9, x10, [x11, #CTX_PACIAKEY_LO] + msr APIAKeyLo_EL1, x9 + msr APIAKeyHi_EL1, x10 + + ldp x9, x10, [x11, #CTX_PACIAKEY_LO] + msr APIBKeyLo_EL1, x9 + msr APIBKeyHi_EL1, x10 + + ldp x9, x10, [x11, #CTX_PACDAKEY_LO] + msr APDAKeyLo_EL1, x9 + msr APDAKeyHi_EL1, x10 + + ldp x9, x10, [x11, #CTX_PACDBKEY_LO] + msr APDBKeyLo_EL1, x9 + msr APDBKeyHi_EL1, x10 + + ldp x9, x10, [x11, #CTX_PACGAKEY_LO] + msr APGAKeyLo_EL1, x9 + msr APGAKeyHi_EL1, x10 + + ret +endfunc pauth_context_restore +#endif /* CTX_INCLUDE_PAUTH_REGS */ + /* ----------------------------------------------------- * The following functions are used to save and restore * all the general purpose registers. Ideally we would @@ -415,6 +489,11 @@ func el3_exit 1: #endif +#if CTX_INCLUDE_PAUTH_REGS + /* Restore ARMv8.3-PAuth registers */ + bl pauth_context_restore +#endif + /* Restore saved general purpose registers and return */ b restore_gp_registers_eret endfunc el3_exit diff --git a/lib/el3_runtime/aarch64/context_mgmt.c b/lib/el3_runtime/aarch64/context_mgmt.c index b956491e3..83f6e4895 100644 --- a/lib/el3_runtime/aarch64/context_mgmt.c +++ b/lib/el3_runtime/aarch64/context_mgmt.c @@ -122,6 +122,20 @@ void cm_setup_context(cpu_context_t *ctx, const entry_point_info_t *ep) scr_el3 |= SCR_FIEN_BIT; #endif +#if !CTX_INCLUDE_PAUTH_REGS + /* + * If the pointer authentication registers aren't saved during world + * switches the value of the registers can be leaked from the Secure to + * the Non-secure world. To prevent this, rather than enabling pointer + * authentication everywhere, we only enable it in the Non-secure world. + * + * If the Secure world wants to use pointer authentication, + * CTX_INCLUDE_PAUTH_REGS must be set to 1. + */ + if (security_state == NON_SECURE) + scr_el3 |= SCR_API_BIT | SCR_APK_BIT; +#endif /* !CTX_INCLUDE_PAUTH_REGS */ + #ifdef IMAGE_BL31 /* * SCR_EL3.IRQ, SCR_EL3.FIQ: Enable the physical FIQ and IRQ routing as diff --git a/make_helpers/defaults.mk b/make_helpers/defaults.mk index 76a9fd4fa..642239771 100644 --- a/make_helpers/defaults.mk +++ b/make_helpers/defaults.mk @@ -51,6 +51,11 @@ CTX_INCLUDE_AARCH32_REGS := 1 # Include FP registers in cpu context CTX_INCLUDE_FPREGS := 0 +# Include pointer authentication (ARMv8.3-PAuth) registers in cpu context. This +# must be set to 1 if the platform wants to use this feature in the Secure +# world. It is not needed to use it in the Non-secure world. +CTX_INCLUDE_PAUTH_REGS := 0 + # Debug build DEBUG := 0 From b86048c40cb7d9ccd7aeac1681945676a6dc36ff Mon Sep 17 00:00:00 2001 From: Antonio Nino Diaz Date: Tue, 19 Feb 2019 11:53:51 +0000 Subject: [PATCH 3/9] Add support for pointer authentication The previous commit added the infrastructure to load and save ARMv8.3-PAuth registers during Non-secure <-> Secure world switches, but didn't actually enable pointer authentication in the firmware. This patch adds the functionality needed for platforms to provide authentication keys for the firmware, and a new option (ENABLE_PAUTH) to enable pointer authentication in the firmware itself. This option is disabled by default, and it requires CTX_INCLUDE_PAUTH_REGS to be enabled. Change-Id: I35127ec271e1198d43209044de39fa712ef202a5 Signed-off-by: Antonio Nino Diaz --- Makefile | 19 ++++++++++ bl31/aarch64/ea_delegate.S | 8 +++++ bl31/aarch64/runtime_exceptions.S | 8 +++++ common/bl_common.c | 53 +++++++++++++++++++++++++++- docs/firmware-design.rst | 5 +++ docs/porting-guide.rst | 16 +++++++++ docs/user-guide.rst | 9 ++++- include/arch/aarch64/arch_features.h | 17 +++++++++ include/arch/aarch64/arch_helpers.h | 3 +- include/common/bl_common.h | 4 ++- include/plat/common/platform.h | 3 +- lib/el3_runtime/aarch64/context.S | 23 ++++++++++++ make_helpers/defaults.mk | 3 ++ 13 files changed, 166 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index ebc885091..7b0ef5b42 100644 --- a/Makefile +++ b/Makefile @@ -184,6 +184,14 @@ TF_CFLAGS_aarch64 += -mgeneral-regs-only -mstrict-align ASFLAGS_aarch32 = $(march32-directive) ASFLAGS_aarch64 = -march=armv8-a +# Set the compiler to ARMv8.3 mode so that it uses all the ARMv8.3-PAuth +# instructions. Keeping it in 8.0 would make the compiler emit +# backwards-compatible hint instructions, which needs more space. +ifeq (${ENABLE_PAUTH},1) +TF_CFLAGS_aarch64 += -march=armv8.3-a +ASFLAGS_aarch64 += -march=armv8.3-a +endif + WARNING1 := -Wextra WARNING1 += -Wunused -Wno-unused-parameter WARNING1 += -Wmissing-declarations @@ -459,6 +467,15 @@ ifeq ($(DYN_DISABLE_AUTH), 1) endif endif +# If pointer authentication is used in the firmware, make sure that all the +# registers associated to it are also saved and restored. Not doing it would +# leak the value of the key used by EL3 to EL1 and S-EL1. +ifeq ($(ENABLE_PAUTH),1) + ifeq ($(CTX_INCLUDE_PAUTH_REGS),0) + $(error ENABLE_PAUTH=1 requires CTX_INCLUDE_PAUTH_REGS=1) + endif +endif + ################################################################################ # Process platform overrideable behaviour ################################################################################ @@ -587,6 +604,7 @@ $(eval $(call assert_boolean,EL3_EXCEPTION_HANDLING)) $(eval $(call assert_boolean,ENABLE_AMU)) $(eval $(call assert_boolean,ENABLE_ASSERTIONS)) $(eval $(call assert_boolean,ENABLE_MPAM_FOR_LOWER_ELS)) +$(eval $(call assert_boolean,ENABLE_PAUTH)) $(eval $(call assert_boolean,ENABLE_PIE)) $(eval $(call assert_boolean,ENABLE_PMF)) $(eval $(call assert_boolean,ENABLE_PSCI_STAT)) @@ -639,6 +657,7 @@ $(eval $(call add_define,EL3_EXCEPTION_HANDLING)) $(eval $(call add_define,ENABLE_AMU)) $(eval $(call add_define,ENABLE_ASSERTIONS)) $(eval $(call add_define,ENABLE_MPAM_FOR_LOWER_ELS)) +$(eval $(call add_define,ENABLE_PAUTH)) $(eval $(call add_define,ENABLE_PIE)) $(eval $(call add_define,ENABLE_PMF)) $(eval $(call add_define,ENABLE_PSCI_STAT)) diff --git a/bl31/aarch64/ea_delegate.S b/bl31/aarch64/ea_delegate.S index d5ecfc50e..40c3191ac 100644 --- a/bl31/aarch64/ea_delegate.S +++ b/bl31/aarch64/ea_delegate.S @@ -68,9 +68,13 @@ func enter_lower_el_sync_ea /* Save GP registers */ bl save_gp_registers + /* Save ARMv8.3-PAuth registers and load firmware key */ #if CTX_INCLUDE_PAUTH_REGS bl pauth_context_save #endif +#if ENABLE_PAUTH + bl pauth_load_bl_apiakey +#endif /* Setup exception class and syndrome arguments for platform handler */ mov x0, #ERROR_EA_SYNC @@ -102,9 +106,13 @@ func enter_lower_el_async_ea /* Save GP registers */ bl save_gp_registers + /* Save ARMv8.3-PAuth registers and load firmware key */ #if CTX_INCLUDE_PAUTH_REGS bl pauth_context_save #endif +#if ENABLE_PAUTH + bl pauth_load_bl_apiakey +#endif /* Setup exception class and syndrome arguments for platform handler */ mov x0, #ERROR_EA_ASYNC diff --git a/bl31/aarch64/runtime_exceptions.S b/bl31/aarch64/runtime_exceptions.S index cea7a8a1e..aa9d0079b 100644 --- a/bl31/aarch64/runtime_exceptions.S +++ b/bl31/aarch64/runtime_exceptions.S @@ -123,9 +123,13 @@ bl save_gp_registers + /* Save ARMv8.3-PAuth registers and load firmware key */ #if CTX_INCLUDE_PAUTH_REGS bl pauth_context_save #endif +#if ENABLE_PAUTH + bl pauth_load_bl_apiakey +#endif /* Save the EL3 system registers needed to return from this exception */ mrs x0, spsr_el3 @@ -331,9 +335,13 @@ smc_handler64: /* Save general purpose registers */ bl save_gp_registers + /* Save ARMv8.3-PAuth registers and load firmware key */ #if CTX_INCLUDE_PAUTH_REGS bl pauth_context_save #endif +#if ENABLE_PAUTH + bl pauth_load_bl_apiakey +#endif /* * Populate the parameters for the SMC handler. diff --git a/common/bl_common.c b/common/bl_common.c index 84ff99c8e..4e76dd3e6 100644 --- a/common/bl_common.c +++ b/common/bl_common.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -9,6 +9,7 @@ #include #include +#include #include #include #include @@ -243,3 +244,53 @@ void print_entry_point_info(const entry_point_info_t *ep_info) #endif #undef PRINT_IMAGE_ARG } + +#ifdef AARCH64 +/******************************************************************************* + * Handle all possible cases regarding ARMv8.3-PAuth. + ******************************************************************************/ +void bl_handle_pauth(void) +{ +#if ENABLE_PAUTH + /* + * ENABLE_PAUTH = 1 && CTX_INCLUDE_PAUTH_REGS = 1 + * + * Check that the system supports address authentication to avoid + * getting an access fault when accessing the registers. This is all + * that is needed to check. If any of the authentication mechanisms is + * supported, the system knows about ARMv8.3-PAuth, so all the registers + * are available and accessing them won't generate a fault. + * + * Obtain 128-bit instruction key A from the platform and save it to the + * system registers. Pointer authentication can't be enabled here or the + * authentication will fail when returning from this function. + */ + assert(is_armv8_3_pauth_api_present()); + + uint64_t *apiakey = plat_init_apiakey(); + + write_apiakeylo_el1(apiakey[0]); + write_apiakeyhi_el1(apiakey[1]); +#else /* if !ENABLE_PAUTH */ + +# if CTX_INCLUDE_PAUTH_REGS + /* + * ENABLE_PAUTH = 0 && CTX_INCLUDE_PAUTH_REGS = 1 + * + * Assert that the ARMv8.3-PAuth registers are present or an access + * fault will be triggered when they are being saved or restored. + */ + assert(is_armv8_3_pauth_present()); +# else + /* + * ENABLE_PAUTH = 0 && CTX_INCLUDE_PAUTH_REGS = 0 + * + * Pointer authentication is allowed in the Non-secure world, but + * prohibited in the Secure world. The Trusted Firmware doesn't save the + * registers during a world switch. No check needed. + */ +# endif /* CTX_INCLUDE_PAUTH_REGS */ + +#endif /* ENABLE_PAUTH */ +} +#endif /* AARCH64 */ diff --git a/docs/firmware-design.rst b/docs/firmware-design.rst index 808afeedb..ead7297d9 100644 --- a/docs/firmware-design.rst +++ b/docs/firmware-design.rst @@ -2566,6 +2566,11 @@ Armv8.3-A must be set to 1. This will add all pointer authentication system registers to the context that is saved when doing a world switch. + The Trusted Firmware itself has support for pointer authentication at runtime + that can be enabled by setting both options ``ENABLE_PAUTH`` and + ``CTX_INCLUDE_PAUTH_REGS`` to 1. This enables pointer authentication in BL1, + BL2, BL31, and the TSP if it is used. + Armv7-A ~~~~~~~ diff --git a/docs/porting-guide.rst b/docs/porting-guide.rst index 7a3963bda..c3df389f8 100644 --- a/docs/porting-guide.rst +++ b/docs/porting-guide.rst @@ -1792,6 +1792,22 @@ defined by the translation library, and can be found in the file On DynamIQ systems, this function must not use stack while enabling MMU, which is how the function in xlat table library version 2 is implemented. +Function : plat_init_apiakey [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : uint64_t * + +This function populates the ``plat_apiakey`` array that contains the values used +to set the ``APIAKey{Hi,Lo}_EL1`` registers. It returns a pointer to this array. + +The value should be obtained from a reliable source of randomness. + +This function is only needed if ARMv8.3 pointer authentication is used in the +Trusted Firmware by building with ``ENABLE_PAUTH=1``. + Function : plat_get_syscnt_freq2() [mandatory] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/docs/user-guide.rst b/docs/user-guide.rst index 70c1d5a91..b42012757 100644 --- a/docs/user-guide.rst +++ b/docs/user-guide.rst @@ -362,7 +362,7 @@ Common build options the ARMv8.3-PAuth registers to be included when saving and restoring the CPU context. Note that if the hardware supports this extension and this option is set to 0 the value of the registers will be leaked between Secure and - Non-secure worlds. The default is 0. + Non-secure worlds if PAuth is used on both sides. The default is 0. - ``DEBUG``: Chooses between a debug and release build. It can take either 0 (release) or 1 (debug) as values. 0 is the default. @@ -411,6 +411,13 @@ Common build options partitioning in EL3, however. Platform initialisation code should configure and use partitions in EL3 as required. This option defaults to ``0``. +- ``ENABLE_PAUTH``: Boolean option to enable ARMv8.3 Pointer Authentication + (``ARMv8.3-PAuth``) support in the Trusted Firmware itself. Note that this + option doesn't affect the saving of the registers introduced with this + extension, they are always saved if they are detected regardless of the value + of this option. If enabled, it is needed to use a compiler that supports the + option ``-msign-return-address``. It defaults to 0. + - ``ENABLE_PIE``: Boolean option to enable Position Independent Executable(PIE) support within generic code in TF-A. This option is currently only supported in BL31. Default is 0. diff --git a/include/arch/aarch64/arch_features.h b/include/arch/aarch64/arch_features.h index da8b6e4f1..495ecb3a2 100644 --- a/include/arch/aarch64/arch_features.h +++ b/include/arch/aarch64/arch_features.h @@ -23,6 +23,23 @@ 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_api_present(void) +{ + return ((read_id_aa64isar1_el1() >> ID_AA64ISAR1_API_SHIFT) & + ID_AA64ISAR1_API_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/arch/aarch64/arch_helpers.h b/include/arch/aarch64/arch_helpers.h index 4e459bbb9..e07db300b 100644 --- a/include/arch/aarch64/arch_helpers.h +++ b/include/arch/aarch64/arch_helpers.h @@ -454,7 +454,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/common/bl_common.h b/include/common/bl_common.h index fd7656eb5..9817ec7fa 100644 --- a/include/common/bl_common.h +++ b/include/common/bl_common.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -207,6 +207,8 @@ struct mmap_region; void setup_page_tables(const struct mmap_region *bl_regions, const struct mmap_region *plat_regions); +void bl_handle_pauth(void); + #endif /*__ASSEMBLY__*/ #endif /* BL_COMMON_H */ diff --git a/include/plat/common/platform.h b/include/plat/common/platform.h index 13767ff0a..4832e491c 100644 --- a/include/plat/common/platform.h +++ b/include/plat/common/platform.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -104,6 +104,7 @@ const char *plat_log_get_prefix(unsigned int log_level); void bl2_plat_preload_setup(void); int plat_try_next_boot_source(void); int plat_get_mbedtls_heap(void **heap_addr, size_t *heap_size); +uint64_t *plat_init_apiakey(void); /******************************************************************************* * Mandatory BL1 functions diff --git a/lib/el3_runtime/aarch64/context.S b/lib/el3_runtime/aarch64/context.S index f5fed72d0..4489e908b 100644 --- a/lib/el3_runtime/aarch64/context.S +++ b/lib/el3_runtime/aarch64/context.S @@ -17,6 +17,9 @@ #if CTX_INCLUDE_PAUTH_REGS .global pauth_context_restore .global pauth_context_save +#endif +#if ENABLE_PAUTH + .global pauth_load_bl_apiakey #endif .global save_gp_registers .global restore_gp_registers @@ -373,6 +376,26 @@ func pauth_context_restore endfunc pauth_context_restore #endif /* CTX_INCLUDE_PAUTH_REGS */ +/* ----------------------------------------------------- + * The following function strictly follows the AArch64 + * PCS to use x9-x17 (temporary caller-saved registers) + * to load the APIA key used by the firmware. + * ----------------------------------------------------- + */ +#if ENABLE_PAUTH +func pauth_load_bl_apiakey + /* Load instruction key A used by the Trusted Firmware. */ + adrp x11, plat_apiakey + add x11, x11, :lo12:plat_apiakey + ldp x9, x10, [x11, #0] + + msr APIAKeyLo_EL1, x9 + msr APIAKeyHi_EL1, x10 + + ret +endfunc pauth_load_bl_apiakey +#endif /* ENABLE_PAUTH */ + /* ----------------------------------------------------- * The following functions are used to save and restore * all the general purpose registers. Ideally we would diff --git a/make_helpers/defaults.mk b/make_helpers/defaults.mk index 642239771..819abcd18 100644 --- a/make_helpers/defaults.mk +++ b/make_helpers/defaults.mk @@ -87,6 +87,9 @@ ENABLE_STACK_PROTECTOR := 0 # Flag to enable exception handling in EL3 EL3_EXCEPTION_HANDLING := 0 +# Flag to enable Pointer Authentication +ENABLE_PAUTH := 0 + # Build flag to treat usage of deprecated platform and framework APIs as error. ERROR_DEPRECATED := 0 From ff6844c3de9b34a09f358a3204264059834e2b1d Mon Sep 17 00:00:00 2001 From: Antonio Nino Diaz Date: Thu, 31 Jan 2019 11:01:10 +0000 Subject: [PATCH 4/9] plat/arm: Implement ARMv8.3-PAuth interfaces This feature is only supported on FVP. Change-Id: I4e265610211d92a84bd2773c34acfbe02a1a1826 Signed-off-by: Antonio Nino Diaz --- plat/arm/common/aarch64/arm_pauth.c | 32 +++++++++++++++++++++++++++++ plat/arm/common/arm_common.mk | 5 +++++ 2 files changed, 37 insertions(+) create mode 100644 plat/arm/common/aarch64/arm_pauth.c diff --git a/plat/arm/common/aarch64/arm_pauth.c b/plat/arm/common/aarch64/arm_pauth.c new file mode 100644 index 000000000..c8471190a --- /dev/null +++ b/plat/arm/common/aarch64/arm_pauth.c @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +/* + * Instruction pointer authentication key A. The low 64-bit are at [0], and the + * high bits at [1]. They are run-time constants so they are placed in the + * rodata section. They are written before MMU is turned on and the permissions + * are effective. + */ +uint64_t plat_apiakey[2] __section("rodata.apiakey"); + +/* + * This is only a toy implementation to generate a seemingly random 128-bit key + * from sp and x30 values. A production system must re-implement this function + * to generate keys from a reliable randomness source. + */ +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/plat/arm/common/arm_common.mk b/plat/arm/common/arm_common.mk index f18a9af69..5e890ed17 100644 --- a/plat/arm/common/arm_common.mk +++ b/plat/arm/common/arm_common.mk @@ -236,6 +236,11 @@ BL31_SOURCES += lib/extensions/ras/std_err_record.c \ lib/extensions/ras/ras_common.c endif +# Pointer Authentication sources +ifeq (${ENABLE_PAUTH}, 1) +PLAT_BL_COMMON_SOURCES += plat/arm/common/aarch64/arm_pauth.c +endif + # SPM uses libfdt in Arm platforms ifeq (${SPM_MM},0) ifeq (${ENABLE_SPM},1) From cd7d6b0eb161c4b24f4ff19822cbb26c3f59a3f5 Mon Sep 17 00:00:00 2001 From: Antonio Nino Diaz Date: Wed, 30 Jan 2019 20:29:50 +0000 Subject: [PATCH 5/9] BL1: Enable pointer authentication support The size increase after enabling options related to ARMv8.3-PAuth is: +----------------------------+-------+-------+-------+--------+ | | text | bss | data | rodata | +----------------------------+-------+-------+-------+--------+ | CTX_INCLUDE_PAUTH_REGS = 1 | +108 | +192 | +0 | +0 | | | 0.5% | 0.8% | | | +----------------------------+-------+-------+-------+--------+ | ENABLE_PAUTH = 1 | +748 | +192 | +16 | +0 | | | 3.7% | 0.8% | 7.0% | | +----------------------------+-------+-------+-------+--------+ Results calculated with the following build configuration: make PLAT=fvp SPD=tspd DEBUG=1 \ SDEI_SUPPORT=1 \ EL3_EXCEPTION_HANDLING=1 \ TSP_NS_INTR_ASYNC_PREEMPT=1 \ CTX_INCLUDE_PAUTH_REGS=1 \ ENABLE_PAUTH=1 Change-Id: I3a7d02feb6a6d212be32a01432b0c7c1a261f567 Signed-off-by: Antonio Nino Diaz --- bl1/aarch32/bl1_entrypoint.S | 8 +++---- bl1/aarch64/bl1_entrypoint.S | 42 +++++++++++++++++++++++++----------- bl1/bl1.mk | 6 +++++- bl1/bl1_main.c | 24 ++++++++++++++++++++- include/bl1/bl1.h | 3 ++- 5 files changed, 63 insertions(+), 20 deletions(-) diff --git a/bl1/aarch32/bl1_entrypoint.S b/bl1/aarch32/bl1_entrypoint.S index 3f0cbaf4b..6a155660b 100644 --- a/bl1/aarch32/bl1_entrypoint.S +++ b/bl1/aarch32/bl1_entrypoint.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -52,12 +52,10 @@ func bl1_entrypoint _exception_vectors=bl1_vector_table /* ----------------------------------------------------- - * Perform early platform setup & platform - * specific early arch. setup e.g. mmu setup + * Perform BL1 setup * ----------------------------------------------------- */ - bl bl1_early_platform_setup - bl bl1_plat_arch_setup + bl bl1_setup /* ----------------------------------------------------- * Jump to main function. diff --git a/bl1/aarch64/bl1_entrypoint.S b/bl1/aarch64/bl1_entrypoint.S index f7e02e974..0f8d5aaca 100644 --- a/bl1/aarch64/bl1_entrypoint.S +++ b/bl1/aarch64/bl1_entrypoint.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -32,24 +32,42 @@ func bl1_entrypoint _init_c_runtime=1 \ _exception_vectors=bl1_exceptions - /* --------------------------------------------- - * Architectural init. can be generic e.g. - * enabling stack alignment and platform spec- - * ific e.g. MMU & page table setup as per the - * platform memory map. Perform the latter here - * and the former in bl1_main. - * --------------------------------------------- + /* -------------------------------------------------------------------- + * Perform BL1 setup + * -------------------------------------------------------------------- */ - bl bl1_early_platform_setup - bl bl1_plat_arch_setup + bl bl1_setup - /* -------------------------------------------------- + /* -------------------------------------------------------------------- + * Enable pointer authentication + * -------------------------------------------------------------------- + */ +#if ENABLE_PAUTH + mrs x0, sctlr_el3 + orr x0, x0, #SCTLR_EnIA_BIT + msr sctlr_el3, x0 + isb +#endif /* ENABLE_PAUTH */ + + /* -------------------------------------------------------------------- * Initialize platform and jump to our c-entry point * for this type of reset. - * -------------------------------------------------- + * -------------------------------------------------------------------- */ bl bl1_main + /* -------------------------------------------------------------------- + * Disable pointer authentication before jumping to BL31 or that will + * cause an authentication failure during the early platform init. + * -------------------------------------------------------------------- + */ +#if ENABLE_PAUTH + mrs x0, sctlr_el3 + bic x0, x0, #SCTLR_EnIA_BIT + msr sctlr_el3, x0 + isb +#endif /* ENABLE_PAUTH */ + /* -------------------------------------------------- * Do the transition to next boot image. * -------------------------------------------------- diff --git a/bl1/bl1.mk b/bl1/bl1.mk index ec7d7280b..7f1a82306 100644 --- a/bl1/bl1.mk +++ b/bl1/bl1.mk @@ -1,5 +1,5 @@ # -# Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved. +# Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved. # # SPDX-License-Identifier: BSD-3-Clause # @@ -21,6 +21,10 @@ BL1_SOURCES += lib/cpus/aarch64/dsu_helpers.S \ lib/el3_runtime/aarch64/context.S endif +ifeq (${ENABLE_PAUTH},1) +BL1_CFLAGS += -msign-return-address=non-leaf +endif + ifeq (${TRUSTED_BOARD_BOOT},1) BL1_SOURCES += bl1/bl1_fwu.c endif diff --git a/bl1/bl1_main.c b/bl1/bl1_main.c index d2c2b4173..fce14f55f 100644 --- a/bl1/bl1_main.c +++ b/bl1/bl1_main.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -51,6 +51,28 @@ void bl1_calc_bl2_mem_layout(const meminfo_t *bl1_mem_layout, flush_dcache_range((unsigned long)bl2_mem_layout, sizeof(meminfo_t)); } +/******************************************************************************* + * Setup function for BL1. + ******************************************************************************/ +void bl1_setup(void) +{ + /* Perform early platform-specific setup */ + bl1_early_platform_setup(); + +#ifdef AARCH64 + /* + * Update pointer authentication key before the MMU is enabled. It is + * saved in the rodata section, that can be writen before enabling the + * MMU. This function must be called after the console is initialized + * in the early platform setup. + */ + bl_handle_pauth(); +#endif /* AARCH64 */ + + /* Perform late platform-specific setup */ + bl1_plat_arch_setup(); +} + /******************************************************************************* * Function to perform late architectural and platform specific initialization. * It also queries the platform to load and run next BL image. Only called diff --git a/include/bl1/bl1.h b/include/bl1/bl1.h index 7b5d87572..937b8c7e8 100644 --- a/include/bl1/bl1.h +++ b/include/bl1/bl1.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -83,6 +83,7 @@ register_t bl1_smc_handler(unsigned int smc_fid, void bl1_print_next_bl_ep_info(const struct entry_point_info *bl_ep_info); +void bl1_setup(void); void bl1_main(void); void bl1_plat_prepare_exit(entry_point_info_t *ep_info); From 9d93fc2f89a00e104bfe6be31f87861c26ba2bf0 Mon Sep 17 00:00:00 2001 From: Antonio Nino Diaz Date: Thu, 31 Jan 2019 10:48:47 +0000 Subject: [PATCH 6/9] BL2: Enable pointer authentication support The size increase after enabling options related to ARMv8.3-PAuth is: +----------------------------+-------+-------+-------+--------+ | | text | bss | data | rodata | +----------------------------+-------+-------+-------+--------+ | CTX_INCLUDE_PAUTH_REGS = 1 | +40 | +0 | +0 | +0 | | | 0.2% | | | | +----------------------------+-------+-------+-------+--------+ | ENABLE_PAUTH = 1 | +664 | +0 | +16 | +0 | | | 3.1% | | 0.9% | | +----------------------------+-------+-------+-------+--------+ Results calculated with the following build configuration: make PLAT=fvp SPD=tspd DEBUG=1 \ SDEI_SUPPORT=1 \ EL3_EXCEPTION_HANDLING=1 \ TSP_NS_INTR_ASYNC_PREEMPT=1 \ CTX_INCLUDE_PAUTH_REGS=1 \ ENABLE_PAUTH=1 The changes for BL2_AT_EL3 aren't done in this commit. Change-Id: I8c803b40c7160525a06173bc6cdca21c4505837d Signed-off-by: Antonio Nino Diaz --- bl2/aarch32/bl2_entrypoint.S | 9 ++++----- bl2/aarch64/bl2_entrypoint.S | 18 +++++++++++++----- bl2/bl2.mk | 9 ++++++--- bl2/bl2_main.c | 25 ++++++++++++++++++++++++- include/bl2/bl2.h | 6 +++++- 5 files changed, 52 insertions(+), 15 deletions(-) diff --git a/bl2/aarch32/bl2_entrypoint.S b/bl2/aarch32/bl2_entrypoint.S index e7b98af32..23d151356 100644 --- a/bl2/aarch32/bl2_entrypoint.S +++ b/bl2/aarch32/bl2_entrypoint.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -108,16 +108,15 @@ func bl2_entrypoint #endif /* --------------------------------------------- - * Perform early platform setup & platform - * specific early arch. setup e.g. mmu setup + * Perform BL2 setup * --------------------------------------------- */ mov r0, r9 mov r1, r10 mov r2, r11 mov r3, r12 - bl bl2_early_platform_setup2 - bl bl2_plat_arch_setup + + bl bl2_setup /* --------------------------------------------- * Jump to main function. diff --git a/bl2/aarch64/bl2_entrypoint.S b/bl2/aarch64/bl2_entrypoint.S index d938947c1..611b8076d 100644 --- a/bl2/aarch64/bl2_entrypoint.S +++ b/bl2/aarch64/bl2_entrypoint.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -106,17 +106,25 @@ func bl2_entrypoint #endif /* --------------------------------------------- - * Perform early platform setup & platform - * specific early arch. setup e.g. mmu setup + * Perform BL2 setup * --------------------------------------------- */ mov x0, x20 mov x1, x21 mov x2, x22 mov x3, x23 - bl bl2_early_platform_setup2 + bl bl2_setup - bl bl2_plat_arch_setup + /* --------------------------------------------- + * Enable pointer authentication + * --------------------------------------------- + */ +#if ENABLE_PAUTH + mrs x0, sctlr_el1 + orr x0, x0, #SCTLR_EnIA_BIT + msr sctlr_el1, x0 + isb +#endif /* ENABLE_PAUTH */ /* --------------------------------------------- * Jump to main function. diff --git a/bl2/bl2.mk b/bl2/bl2.mk index f905bc235..9523918bc 100644 --- a/bl2/bl2.mk +++ b/bl2/bl2.mk @@ -1,10 +1,11 @@ # -# Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved. +# Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved. # # SPDX-License-Identifier: BSD-3-Clause # -BL2_SOURCES += bl2/bl2_main.c \ +BL2_SOURCES += bl2/bl2_image_load_v2.c \ + bl2/bl2_main.c \ bl2/${ARCH}/bl2_arch_setup.c \ lib/locks/exclusive/${ARCH}/spinlock.S \ plat/common/${ARCH}/platform_up_stack.S \ @@ -14,7 +15,9 @@ ifeq (${ARCH},aarch64) BL2_SOURCES += common/aarch64/early_exceptions.S endif -BL2_SOURCES += bl2/bl2_image_load_v2.c +ifeq (${ENABLE_PAUTH},1) +BL2_CFLAGS += -msign-return-address=non-leaf +endif ifeq (${BL2_AT_EL3},0) BL2_SOURCES += bl2/${ARCH}/bl2_entrypoint.S diff --git a/bl2/bl2_main.c b/bl2/bl2_main.c index 019088dc1..e7ab7bb71 100644 --- a/bl2/bl2_main.c +++ b/bl2/bl2_main.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -21,6 +21,29 @@ #define NEXT_IMAGE "BL31" #endif +/******************************************************************************* + * Setup function for BL2. + ******************************************************************************/ +void bl2_setup(u_register_t arg0, u_register_t arg1, u_register_t arg2, + u_register_t arg3) +{ + /* Perform early platform-specific setup */ + bl2_early_platform_setup2(arg0, arg1, arg2, arg3); + +#ifdef AARCH64 + /* + * Update pointer authentication key before the MMU is enabled. It is + * saved in the rodata section, that can be writen before enabling the + * MMU. This function must be called after the console is initialized + * in the early platform setup. + */ + bl_handle_pauth(); +#endif /* AARCH64 */ + + /* Perform late platform-specific setup */ + bl2_plat_arch_setup(); +} + /******************************************************************************* * The only thing to do in BL2 is to load further images and pass control to * next BL. The memory occupied by BL2 will be reclaimed by BL3x stages. BL2 diff --git a/include/bl2/bl2.h b/include/bl2/bl2.h index 8ec080c0a..b3f9a879a 100644 --- a/include/bl2/bl2.h +++ b/include/bl2/bl2.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -7,6 +7,10 @@ #ifndef BL2_H #define BL2_H +#include + +void bl2_setup(u_register_t arg0, u_register_t arg1, u_register_t arg2, + u_register_t arg3); void bl2_main(void); #endif /* BL2_H */ From dcbfa11bd96af98dbb93df3410008f025a131d59 Mon Sep 17 00:00:00 2001 From: Antonio Nino Diaz Date: Thu, 31 Jan 2019 17:40:44 +0000 Subject: [PATCH 7/9] BL2_AT_EL3: Enable pointer authentication support The size increase after enabling options related to ARMv8.3-PAuth is: +----------------------------+-------+-------+-------+--------+ | | text | bss | data | rodata | +----------------------------+-------+-------+-------+--------+ | CTX_INCLUDE_PAUTH_REGS = 1 | +44 | +0 | +0 | +0 | | | 0.2% | | | | +----------------------------+-------+-------+-------+--------+ | ENABLE_PAUTH = 1 | +712 | +0 | +16 | +0 | | | 3.1% | | 0.9% | | +----------------------------+-------+-------+-------+--------+ The results are valid for the following build configuration: make PLAT=fvp SPD=tspd DEBUG=1 \ BL2_AT_EL3=1 \ CTX_INCLUDE_PAUTH_REGS=1 \ ENABLE_PAUTH=1 Change-Id: I1c0616e7dea30962a92b4fd113428bc30a018320 Signed-off-by: Antonio Nino Diaz --- bl2/aarch32/bl2_el3_entrypoint.S | 9 ++++-- bl2/aarch64/bl2_el3_entrypoint.S | 48 +++++++++++++++++++++++++------- bl2/bl2_main.c | 30 ++++++++++++++++++-- include/bl2/bl2.h | 2 ++ 4 files changed, 74 insertions(+), 15 deletions(-) diff --git a/bl2/aarch32/bl2_el3_entrypoint.S b/bl2/aarch32/bl2_el3_entrypoint.S index cc846ddf1..35da133f7 100644 --- a/bl2/aarch32/bl2_el3_entrypoint.S +++ b/bl2/aarch32/bl2_el3_entrypoint.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -36,8 +36,11 @@ func bl2_entrypoint mov r2, r11 mov r3, r12 - bl bl2_el3_early_platform_setup - bl bl2_el3_plat_arch_setup + /* --------------------------------------------- + * Perform BL2 setup + * --------------------------------------------- + */ + bl bl2_el3_setup /* --------------------------------------------- * Jump to main function. diff --git a/bl2/aarch64/bl2_el3_entrypoint.S b/bl2/aarch64/bl2_el3_entrypoint.S index 16b7c0d5f..d1e424718 100644 --- a/bl2/aarch64/bl2_el3_entrypoint.S +++ b/bl2/aarch64/bl2_el3_entrypoint.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -29,16 +29,31 @@ func bl2_entrypoint _init_c_runtime=1 \ _exception_vectors=bl2_el3_exceptions - /* + /* --------------------------------------------- * Restore parameters of boot rom + * --------------------------------------------- */ mov x0, x20 mov x1, x21 mov x2, x22 mov x3, x23 - bl bl2_el3_early_platform_setup - bl bl2_el3_plat_arch_setup + /* --------------------------------------------- + * Perform BL2 setup + * --------------------------------------------- + */ + bl bl2_el3_setup + + /* --------------------------------------------- + * Enable pointer authentication + * --------------------------------------------- + */ +#if ENABLE_PAUTH + mrs x0, sctlr_el3 + orr x0, x0, #SCTLR_EnIA_BIT + msr sctlr_el3, x0 + isb +#endif /* ENABLE_PAUTH */ /* --------------------------------------------- * Jump to main function. @@ -55,16 +70,29 @@ endfunc bl2_entrypoint func bl2_run_next_image mov x20,x0 - /* - * MMU needs to be disabled because both BL2 and BL31 execute - * in EL3, and therefore share the same address space. - * BL31 will initialize the address space according to its - * own requirement. - */ + /* --------------------------------------------- + * MMU needs to be disabled because both BL2 and BL31 execute + * in EL3, and therefore share the same address space. + * BL31 will initialize the address space according to its + * own requirement. + * --------------------------------------------- + */ bl disable_mmu_icache_el3 tlbi alle3 bl bl2_el3_plat_prepare_exit + /* --------------------------------------------- + * Disable pointer authentication before jumping to BL31 or that will + * cause an authentication failure during the early platform init. + * --------------------------------------------- + */ +#if ENABLE_PAUTH + mrs x0, sctlr_el3 + bic x0, x0, #SCTLR_EnIA_BIT + msr sctlr_el3, x0 + isb +#endif /* ENABLE_PAUTH */ + ldp x0, x1, [x20, #ENTRY_POINT_INFO_PC_OFFSET] msr elr_el3, x0 msr spsr_el3, x1 diff --git a/bl2/bl2_main.c b/bl2/bl2_main.c index e7ab7bb71..7d8d60c19 100644 --- a/bl2/bl2_main.c +++ b/bl2/bl2_main.c @@ -21,6 +21,7 @@ #define NEXT_IMAGE "BL31" #endif +#if !BL2_AT_EL3 /******************************************************************************* * Setup function for BL2. ******************************************************************************/ @@ -44,6 +45,31 @@ void bl2_setup(u_register_t arg0, u_register_t arg1, u_register_t arg2, bl2_plat_arch_setup(); } +#else /* if BL2_AT_EL3 */ +/******************************************************************************* + * Setup function for BL2 when BL2_AT_EL3=1. + ******************************************************************************/ +void bl2_el3_setup(u_register_t arg0, u_register_t arg1, u_register_t arg2, + u_register_t arg3) +{ + /* Perform early platform-specific setup */ + bl2_el3_early_platform_setup(arg0, arg1, arg2, arg3); + +#ifdef AARCH64 + /* + * Update pointer authentication key before the MMU is enabled. It is + * saved in the rodata section, that can be writen before enabling the + * MMU. This function must be called after the console is initialized + * in the early platform setup. + */ + bl_handle_pauth(); +#endif /* AARCH64 */ + + /* Perform late platform-specific setup */ + bl2_el3_plat_arch_setup(); +} +#endif /* BL2_AT_EL3 */ + /******************************************************************************* * The only thing to do in BL2 is to load further images and pass control to * next BL. The memory occupied by BL2 will be reclaimed by BL3x stages. BL2 @@ -88,11 +114,11 @@ void bl2_main(void) * be passed to next BL image as an argument. */ smc(BL1_SMC_RUN_IMAGE, (unsigned long)next_bl_ep_info, 0, 0, 0, 0, 0, 0); -#else +#else /* if BL2_AT_EL3 */ NOTICE("BL2: Booting " NEXT_IMAGE "\n"); print_entry_point_info(next_bl_ep_info); console_flush(); bl2_run_next_image(next_bl_ep_info); -#endif +#endif /* BL2_AT_EL3 */ } diff --git a/include/bl2/bl2.h b/include/bl2/bl2.h index b3f9a879a..73f5ac7a1 100644 --- a/include/bl2/bl2.h +++ b/include/bl2/bl2.h @@ -11,6 +11,8 @@ void bl2_setup(u_register_t arg0, u_register_t arg1, u_register_t arg2, u_register_t arg3); +void bl2_el3_setup(u_register_t arg0, u_register_t arg1, u_register_t arg2, + u_register_t arg3); void bl2_main(void); #endif /* BL2_H */ From 88cfd9a604cee29cc6536a43cd136b7eef0b78b9 Mon Sep 17 00:00:00 2001 From: Antonio Nino Diaz Date: Thu, 31 Jan 2019 11:01:26 +0000 Subject: [PATCH 8/9] BL31: Enable pointer authentication support The size increase after enabling options related to ARMv8.3-PAuth is: +----------------------------+-------+-------+-------+--------+ | | text | bss | data | rodata | +----------------------------+-------+-------+-------+--------+ | CTX_INCLUDE_PAUTH_REGS = 1 | +192 | +1536 | +0 | +0 | | | 0.3% | 3.1% | | | +----------------------------+-------+-------+-------+--------+ | ENABLE_PAUTH = 1 | +1848 | +1536 | +16 | +0 | | | 3.3% | 3.1% | 3.1% | | +----------------------------+-------+-------+-------+--------+ Results calculated with the following build configuration: make PLAT=fvp SPD=tspd DEBUG=1 \ SDEI_SUPPORT=1 \ EL3_EXCEPTION_HANDLING=1 \ TSP_NS_INTR_ASYNC_PREEMPT=1 \ CTX_INCLUDE_PAUTH_REGS=1 \ ENABLE_PAUTH=1 Change-Id: I43db7e509a4f39da6599ec2faa690d197573ec1b Signed-off-by: Antonio Nino Diaz --- bl31/aarch64/bl31_entrypoint.S | 30 ++++++++++++++++++++---------- bl31/bl31.mk | 4 ++++ bl31/bl31_main.c | 21 +++++++++++++++++++++ include/bl31/bl31.h | 4 +++- 4 files changed, 48 insertions(+), 11 deletions(-) diff --git a/bl31/aarch64/bl31_entrypoint.S b/bl31/aarch64/bl31_entrypoint.S index c41773b88..8e9528b47 100644 --- a/bl31/aarch64/bl31_entrypoint.S +++ b/bl31/aarch64/bl31_entrypoint.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -87,29 +87,39 @@ func bl31_entrypoint bl fixup_gdt_reloc #endif /* ENABLE_PIE */ - /* --------------------------------------------- - * Perform platform specific early arch. setup - * --------------------------------------------- + /* -------------------------------------------------------------------- + * Perform BL31 setup + * -------------------------------------------------------------------- */ mov x0, x20 mov x1, x21 mov x2, x22 mov x3, x23 - bl bl31_early_platform_setup2 - bl bl31_plat_arch_setup + bl bl31_setup - /* --------------------------------------------- + /* -------------------------------------------------------------------- + * Enable pointer authentication + * -------------------------------------------------------------------- + */ +#if ENABLE_PAUTH + mrs x0, sctlr_el3 + orr x0, x0, #SCTLR_EnIA_BIT + msr sctlr_el3, x0 + isb +#endif /* ENABLE_PAUTH */ + + /* -------------------------------------------------------------------- * Jump to main function. - * --------------------------------------------- + * -------------------------------------------------------------------- */ bl bl31_main - /* ------------------------------------------------------------- + /* -------------------------------------------------------------------- * Clean the .data & .bss sections to main memory. This ensures * that any global data which was initialised by the primary CPU * is visible to secondary CPUs before they enable their data * caches and participate in coherency. - * ------------------------------------------------------------- + * -------------------------------------------------------------------- */ adr x0, __DATA_START__ adr x1, __DATA_END__ diff --git a/bl31/bl31.mk b/bl31/bl31.mk index c9ba926c5..10feae161 100644 --- a/bl31/bl31.mk +++ b/bl31/bl31.mk @@ -75,6 +75,10 @@ ifeq (${ENABLE_MPAM_FOR_LOWER_ELS},1) BL31_SOURCES += lib/extensions/mpam/mpam.c endif +ifeq (${ENABLE_PAUTH},1) +BL31_CFLAGS += -msign-return-address=non-leaf +endif + ifeq (${WORKAROUND_CVE_2017_5715},1) BL31_SOURCES += lib/cpus/aarch64/wa_cve_2017_5715_bpiall.S \ lib/cpus/aarch64/wa_cve_2017_5715_mmu.S diff --git a/bl31/bl31_main.c b/bl31/bl31_main.c index da35f75ed..aca16d677 100644 --- a/bl31/bl31_main.c +++ b/bl31/bl31_main.c @@ -63,6 +63,27 @@ void __init bl31_lib_init(void) cm_init(); } +/******************************************************************************* + * Setup function for BL31. + ******************************************************************************/ +void bl31_setup(u_register_t arg0, u_register_t arg1, u_register_t arg2, + u_register_t arg3) +{ + /* Perform early platform-specific setup */ + bl31_early_platform_setup2(arg0, arg1, arg2, arg3); + + /* + * Update pointer authentication key before the MMU is enabled. It is + * saved in the rodata section, that can be writen before enabling the + * MMU. This function must be called after the console is initialized + * in the early platform setup. + */ + bl_handle_pauth(); + + /* Perform late platform-specific setup */ + bl31_plat_arch_setup(); +} + /******************************************************************************* * BL31 is responsible for setting up the runtime services for the primary cpu * before passing control to the bootloader or an Operating System. This diff --git a/include/bl31/bl31.h b/include/bl31/bl31.h index 08c555d90..3deb0a51d 100644 --- a/include/bl31/bl31.h +++ b/include/bl31/bl31.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -12,6 +12,8 @@ /******************************************************************************* * Function prototypes ******************************************************************************/ +void bl31_setup(u_register_t arg0, u_register_t arg1, u_register_t arg2, + u_register_t arg3); void bl31_next_el_arch_setup(uint32_t security_state); void bl31_set_next_image_type(uint32_t security_state); uint32_t bl31_get_next_image_type(void); From 67b6ff9f8ccd84cea1627d738f3e2d4eb0a789e1 Mon Sep 17 00:00:00 2001 From: Antonio Nino Diaz Date: Tue, 26 Feb 2019 11:41:03 +0000 Subject: [PATCH 9/9] TSP: Enable pointer authentication support The size increase after enabling options related to ARMv8.3-PAuth is: +----------------------------+-------+-------+-------+--------+ | | text | bss | data | rodata | +----------------------------+-------+-------+-------+--------+ | CTX_INCLUDE_PAUTH_REGS = 1 | +40 | +0 | +0 | +0 | | | 0.4% | | | | +----------------------------+-------+-------+-------+--------+ | ENABLE_PAUTH = 1 | +352 | +0 | +16 | +0 | | | 3.1% | | 15.8% | | +----------------------------+-------+-------+-------+--------+ Results calculated with the following build configuration: make PLAT=fvp SPD=tspd DEBUG=1 \ SDEI_SUPPORT=1 \ EL3_EXCEPTION_HANDLING=1 \ TSP_NS_INTR_ASYNC_PREEMPT=1 \ CTX_INCLUDE_PAUTH_REGS=1 \ ENABLE_PAUTH=1 Change-Id: I6cc1fe0b2345c547dcef66f98758c4eb55fe5ee4 Signed-off-by: Antonio Nino Diaz --- bl32/tsp/aarch64/tsp_entrypoint.S | 19 ++++++++++++++----- bl32/tsp/tsp.mk | 7 ++++++- bl32/tsp/tsp_main.c | 20 ++++++++++++++++++++ include/bl32/tsp/tsp.h | 3 ++- 4 files changed, 42 insertions(+), 7 deletions(-) diff --git a/bl32/tsp/aarch64/tsp_entrypoint.S b/bl32/tsp/aarch64/tsp_entrypoint.S index 48f6981bb..710b45884 100644 --- a/bl32/tsp/aarch64/tsp_entrypoint.S +++ b/bl32/tsp/aarch64/tsp_entrypoint.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -122,12 +122,21 @@ func tsp_entrypoint _align=3 #endif /* --------------------------------------------- - * Perform early platform setup & platform - * specific early arch. setup e.g. mmu setup + * Perform TSP setup * --------------------------------------------- */ - bl tsp_early_platform_setup - bl tsp_plat_arch_setup + bl tsp_setup + + /* --------------------------------------------- + * Enable pointer authentication + * --------------------------------------------- + */ +#if ENABLE_PAUTH + mrs x0, sctlr_el1 + orr x0, x0, #SCTLR_EnIA_BIT + msr sctlr_el1, x0 + isb +#endif /* ENABLE_PAUTH */ /* --------------------------------------------- * Jump to main function. diff --git a/bl32/tsp/tsp.mk b/bl32/tsp/tsp.mk index 4ea3dfb9f..b1fe7ff60 100644 --- a/bl32/tsp/tsp.mk +++ b/bl32/tsp/tsp.mk @@ -1,5 +1,5 @@ # -# Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved. +# Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved. # # SPDX-License-Identifier: BSD-3-Clause # @@ -17,6 +17,11 @@ BL32_SOURCES += bl32/tsp/tsp_main.c \ BL32_LINKERFILE := bl32/tsp/tsp.ld.S +# This flag determines whether pointer authentication is used in the TSP or not +ifeq ($(ENABLE_PAUTH),1) +BL32_CFLAGS += -msign-return-address=non-leaf +endif + # This flag determines if the TSPD initializes BL32 in tspd_init() (synchronous # method) or configures BL31 to pass control to BL32 instead of BL33 # (asynchronous method). diff --git a/bl32/tsp/tsp_main.c b/bl32/tsp/tsp_main.c index 407ed4788..30bf6ffc8 100644 --- a/bl32/tsp/tsp_main.c +++ b/bl32/tsp/tsp_main.c @@ -71,6 +71,26 @@ static tsp_args_t *set_smc_args(uint64_t arg0, return pcpu_smc_args; } +/******************************************************************************* + * Setup function for TSP. + ******************************************************************************/ +void tsp_setup(void) +{ + /* Perform early platform-specific setup */ + tsp_early_platform_setup(); + + /* + * Update pointer authentication key before the MMU is enabled. It is + * saved in the rodata section, that can be writen before enabling the + * MMU. This function must be called after the console is initialized + * in the early platform setup. + */ + bl_handle_pauth(); + + /* Perform late platform-specific setup */ + tsp_plat_arch_setup(); +} + /******************************************************************************* * TSP main entry point where it gets the opportunity to initialize its secure * state/applications. Once the state is initialized, it must return to the diff --git a/include/bl32/tsp/tsp.h b/include/bl32/tsp/tsp.h index ed4792e58..18d3079e2 100644 --- a/include/bl32/tsp/tsp.h +++ b/include/bl32/tsp/tsp.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -104,6 +104,7 @@ typedef struct tsp_vectors { tsp_vector_isn_t abort_yield_smc_entry; } tsp_vectors_t; +void tsp_setup(void); #endif /* __ASSEMBLY__ */