Commit b86048c4 authored by Antonio Nino Diaz's avatar Antonio Nino Diaz
Browse files

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: default avatarAntonio Nino Diaz <antonio.ninodiaz@arm.com>
parent 5283962e
...@@ -184,6 +184,14 @@ TF_CFLAGS_aarch64 += -mgeneral-regs-only -mstrict-align ...@@ -184,6 +184,14 @@ TF_CFLAGS_aarch64 += -mgeneral-regs-only -mstrict-align
ASFLAGS_aarch32 = $(march32-directive) ASFLAGS_aarch32 = $(march32-directive)
ASFLAGS_aarch64 = -march=armv8-a 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 := -Wextra
WARNING1 += -Wunused -Wno-unused-parameter WARNING1 += -Wunused -Wno-unused-parameter
WARNING1 += -Wmissing-declarations WARNING1 += -Wmissing-declarations
...@@ -459,6 +467,15 @@ ifeq ($(DYN_DISABLE_AUTH), 1) ...@@ -459,6 +467,15 @@ ifeq ($(DYN_DISABLE_AUTH), 1)
endif endif
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 # Process platform overrideable behaviour
################################################################################ ################################################################################
...@@ -587,6 +604,7 @@ $(eval $(call assert_boolean,EL3_EXCEPTION_HANDLING)) ...@@ -587,6 +604,7 @@ $(eval $(call assert_boolean,EL3_EXCEPTION_HANDLING))
$(eval $(call assert_boolean,ENABLE_AMU)) $(eval $(call assert_boolean,ENABLE_AMU))
$(eval $(call assert_boolean,ENABLE_ASSERTIONS)) $(eval $(call assert_boolean,ENABLE_ASSERTIONS))
$(eval $(call assert_boolean,ENABLE_MPAM_FOR_LOWER_ELS)) $(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_PIE))
$(eval $(call assert_boolean,ENABLE_PMF)) $(eval $(call assert_boolean,ENABLE_PMF))
$(eval $(call assert_boolean,ENABLE_PSCI_STAT)) $(eval $(call assert_boolean,ENABLE_PSCI_STAT))
...@@ -639,6 +657,7 @@ $(eval $(call add_define,EL3_EXCEPTION_HANDLING)) ...@@ -639,6 +657,7 @@ $(eval $(call add_define,EL3_EXCEPTION_HANDLING))
$(eval $(call add_define,ENABLE_AMU)) $(eval $(call add_define,ENABLE_AMU))
$(eval $(call add_define,ENABLE_ASSERTIONS)) $(eval $(call add_define,ENABLE_ASSERTIONS))
$(eval $(call add_define,ENABLE_MPAM_FOR_LOWER_ELS)) $(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_PIE))
$(eval $(call add_define,ENABLE_PMF)) $(eval $(call add_define,ENABLE_PMF))
$(eval $(call add_define,ENABLE_PSCI_STAT)) $(eval $(call add_define,ENABLE_PSCI_STAT))
......
...@@ -68,9 +68,13 @@ func enter_lower_el_sync_ea ...@@ -68,9 +68,13 @@ func enter_lower_el_sync_ea
/* Save GP registers */ /* Save GP registers */
bl save_gp_registers bl save_gp_registers
/* Save ARMv8.3-PAuth registers and load firmware key */
#if CTX_INCLUDE_PAUTH_REGS #if CTX_INCLUDE_PAUTH_REGS
bl pauth_context_save bl pauth_context_save
#endif #endif
#if ENABLE_PAUTH
bl pauth_load_bl_apiakey
#endif
/* Setup exception class and syndrome arguments for platform handler */ /* Setup exception class and syndrome arguments for platform handler */
mov x0, #ERROR_EA_SYNC mov x0, #ERROR_EA_SYNC
...@@ -102,9 +106,13 @@ func enter_lower_el_async_ea ...@@ -102,9 +106,13 @@ func enter_lower_el_async_ea
/* Save GP registers */ /* Save GP registers */
bl save_gp_registers bl save_gp_registers
/* Save ARMv8.3-PAuth registers and load firmware key */
#if CTX_INCLUDE_PAUTH_REGS #if CTX_INCLUDE_PAUTH_REGS
bl pauth_context_save bl pauth_context_save
#endif #endif
#if ENABLE_PAUTH
bl pauth_load_bl_apiakey
#endif
/* Setup exception class and syndrome arguments for platform handler */ /* Setup exception class and syndrome arguments for platform handler */
mov x0, #ERROR_EA_ASYNC mov x0, #ERROR_EA_ASYNC
......
...@@ -123,9 +123,13 @@ ...@@ -123,9 +123,13 @@
bl save_gp_registers bl save_gp_registers
/* Save ARMv8.3-PAuth registers and load firmware key */
#if CTX_INCLUDE_PAUTH_REGS #if CTX_INCLUDE_PAUTH_REGS
bl pauth_context_save bl pauth_context_save
#endif #endif
#if ENABLE_PAUTH
bl pauth_load_bl_apiakey
#endif
/* Save the EL3 system registers needed to return from this exception */ /* Save the EL3 system registers needed to return from this exception */
mrs x0, spsr_el3 mrs x0, spsr_el3
...@@ -331,9 +335,13 @@ smc_handler64: ...@@ -331,9 +335,13 @@ smc_handler64:
/* Save general purpose registers */ /* Save general purpose registers */
bl save_gp_registers bl save_gp_registers
/* Save ARMv8.3-PAuth registers and load firmware key */
#if CTX_INCLUDE_PAUTH_REGS #if CTX_INCLUDE_PAUTH_REGS
bl pauth_context_save bl pauth_context_save
#endif #endif
#if ENABLE_PAUTH
bl pauth_load_bl_apiakey
#endif
/* /*
* Populate the parameters for the SMC handler. * Populate the parameters for the SMC handler.
......
/* /*
* 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 * SPDX-License-Identifier: BSD-3-Clause
*/ */
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include <string.h> #include <string.h>
#include <arch.h> #include <arch.h>
#include <arch_features.h>
#include <arch_helpers.h> #include <arch_helpers.h>
#include <common/bl_common.h> #include <common/bl_common.h>
#include <common/debug.h> #include <common/debug.h>
...@@ -243,3 +244,53 @@ void print_entry_point_info(const entry_point_info_t *ep_info) ...@@ -243,3 +244,53 @@ void print_entry_point_info(const entry_point_info_t *ep_info)
#endif #endif
#undef PRINT_IMAGE_ARG #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 */
...@@ -2566,6 +2566,11 @@ Armv8.3-A ...@@ -2566,6 +2566,11 @@ Armv8.3-A
must be set to 1. This will add all pointer authentication system registers must be set to 1. This will add all pointer authentication system registers
to the context that is saved when doing a world switch. 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 Armv7-A
~~~~~~~ ~~~~~~~
......
...@@ -1792,6 +1792,22 @@ defined by the translation library, and can be found in the file ...@@ -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 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. 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] Function : plat_get_syscnt_freq2() [mandatory]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
......
...@@ -362,7 +362,7 @@ Common build options ...@@ -362,7 +362,7 @@ Common build options
the ARMv8.3-PAuth registers to be included when saving and restoring the CPU 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 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 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 - ``DEBUG``: Chooses between a debug and release build. It can take either 0
(release) or 1 (debug) as values. 0 is the default. (release) or 1 (debug) as values. 0 is the default.
...@@ -411,6 +411,13 @@ Common build options ...@@ -411,6 +411,13 @@ Common build options
partitioning in EL3, however. Platform initialisation code should configure partitioning in EL3, however. Platform initialisation code should configure
and use partitions in EL3 as required. This option defaults to ``0``. 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) - ``ENABLE_PIE``: Boolean option to enable Position Independent Executable(PIE)
support within generic code in TF-A. This option is currently only supported support within generic code in TF-A. This option is currently only supported
in BL31. Default is 0. in BL31. Default is 0.
......
...@@ -23,6 +23,23 @@ static inline bool is_armv8_2_ttcnp_present(void) ...@@ -23,6 +23,23 @@ static inline bool is_armv8_2_ttcnp_present(void)
ID_AA64MMFR2_EL1_CNP_MASK) != 0U; 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) static inline bool is_armv8_4_ttst_present(void)
{ {
return ((read_id_aa64mmfr2_el1() >> ID_AA64MMFR2_EL1_ST_SHIFT) & return ((read_id_aa64mmfr2_el1() >> ID_AA64MMFR2_EL1_ST_SHIFT) &
......
...@@ -454,7 +454,8 @@ DEFINE_RENAME_SYSREG_READ_FUNC(erxmisc1_el1, ERXMISC1_EL1) ...@@ -454,7 +454,8 @@ DEFINE_RENAME_SYSREG_READ_FUNC(erxmisc1_el1, ERXMISC1_EL1)
DEFINE_RENAME_SYSREG_READ_FUNC(id_aa64mmfr2_el1, ID_AA64MMFR2_EL1) DEFINE_RENAME_SYSREG_READ_FUNC(id_aa64mmfr2_el1, ID_AA64MMFR2_EL1)
/* Armv8.3 Pointer Authentication Registers */ /* 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) \ #define IS_IN_EL(x) \
(GET_EL(read_CurrentEl()) == MODE_EL##x) (GET_EL(read_CurrentEl()) == MODE_EL##x)
......
/* /*
* 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 * SPDX-License-Identifier: BSD-3-Clause
*/ */
...@@ -207,6 +207,8 @@ struct mmap_region; ...@@ -207,6 +207,8 @@ struct mmap_region;
void setup_page_tables(const struct mmap_region *bl_regions, void setup_page_tables(const struct mmap_region *bl_regions,
const struct mmap_region *plat_regions); const struct mmap_region *plat_regions);
void bl_handle_pauth(void);
#endif /*__ASSEMBLY__*/ #endif /*__ASSEMBLY__*/
#endif /* BL_COMMON_H */ #endif /* BL_COMMON_H */
/* /*
* 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 * SPDX-License-Identifier: BSD-3-Clause
*/ */
...@@ -104,6 +104,7 @@ const char *plat_log_get_prefix(unsigned int log_level); ...@@ -104,6 +104,7 @@ const char *plat_log_get_prefix(unsigned int log_level);
void bl2_plat_preload_setup(void); void bl2_plat_preload_setup(void);
int plat_try_next_boot_source(void); int plat_try_next_boot_source(void);
int plat_get_mbedtls_heap(void **heap_addr, size_t *heap_size); int plat_get_mbedtls_heap(void **heap_addr, size_t *heap_size);
uint64_t *plat_init_apiakey(void);
/******************************************************************************* /*******************************************************************************
* Mandatory BL1 functions * Mandatory BL1 functions
......
...@@ -17,6 +17,9 @@ ...@@ -17,6 +17,9 @@
#if CTX_INCLUDE_PAUTH_REGS #if CTX_INCLUDE_PAUTH_REGS
.global pauth_context_restore .global pauth_context_restore
.global pauth_context_save .global pauth_context_save
#endif
#if ENABLE_PAUTH
.global pauth_load_bl_apiakey
#endif #endif
.global save_gp_registers .global save_gp_registers
.global restore_gp_registers .global restore_gp_registers
...@@ -373,6 +376,26 @@ func pauth_context_restore ...@@ -373,6 +376,26 @@ func pauth_context_restore
endfunc pauth_context_restore endfunc pauth_context_restore
#endif /* CTX_INCLUDE_PAUTH_REGS */ #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 * The following functions are used to save and restore
* all the general purpose registers. Ideally we would * all the general purpose registers. Ideally we would
......
...@@ -87,6 +87,9 @@ ENABLE_STACK_PROTECTOR := 0 ...@@ -87,6 +87,9 @@ ENABLE_STACK_PROTECTOR := 0
# Flag to enable exception handling in EL3 # Flag to enable exception handling in EL3
EL3_EXCEPTION_HANDLING := 0 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. # Build flag to treat usage of deprecated platform and framework APIs as error.
ERROR_DEPRECATED := 0 ERROR_DEPRECATED := 0
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment