mirror of
https://github.com/ARM-software/arm-trusted-firmware.git
synced 2025-04-13 08:04:27 +00:00
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 <antonio.ninodiaz@arm.com>
This commit is contained in:
parent
5283962eba
commit
b86048c40c
13 changed files with 166 additions and 5 deletions
19
Makefile
19
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))
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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 <string.h>
|
||||
|
||||
#include <arch.h>
|
||||
#include <arch_features.h>
|
||||
#include <arch_helpers.h>
|
||||
#include <common/bl_common.h>
|
||||
#include <common/debug.h>
|
||||
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
~~~~~~~
|
||||
|
||||
|
|
|
@ -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]
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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) &
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue