diff options
author | Sandrine Bailleux <sandrine.bailleux@arm.com> | 2019-10-08 19:16:32 +0000 |
---|---|---|
committer | TrustedFirmware Code Review <review@review.trustedfirmware.org> | 2019-10-08 19:16:32 +0000 |
commit | 6f50bd61931ad36152b2a437622593dd11633eb1 (patch) | |
tree | 1523a86b02b5349c08d546b6f3b53d47453f303b | |
parent | d5a9e7a17f687edd620cad1bfb702781de3cf92e (diff) | |
parent | fb003380a01843d0de71ba3374394a798289c64f (diff) | |
download | tf-a-tests-6f50bd61931ad36152b2a437622593dd11633eb1.tar.gz |
Merge "TFTF: ARMv8.3-PAuth test code enhancements"v2.2-rc0
-rw-r--r-- | plat/arm/fvp/platform.mk | 6 | ||||
-rw-r--r-- | tftf/framework/framework.mk | 9 | ||||
-rw-r--r-- | tftf/tests/extensions/pauth/test_pauth.c | 249 |
3 files changed, 184 insertions, 80 deletions
diff --git a/plat/arm/fvp/platform.mk b/plat/arm/fvp/platform.mk index bf4075dd7..c014d6de7 100644 --- a/plat/arm/fvp/platform.mk +++ b/plat/arm/fvp/platform.mk @@ -23,10 +23,4 @@ CACTUS_SOURCES += plat/arm/fvp/${ARCH}/plat_helpers.S # Firmware update is implemented on FVP. FIRMWARE_UPDATE := 1 -ifeq (${ARCH},aarch64) -# ARMv8.3 Pointer Authentication support files -PLAT_SOURCES += lib/extensions/pauth/aarch64/pauth.c \ - lib/extensions/pauth/aarch64/pauth_helpers.S -endif - include plat/arm/common/arm_common.mk diff --git a/tftf/framework/framework.mk b/tftf/framework/framework.mk index 00bb84aa9..34601c2d6 100644 --- a/tftf/framework/framework.mk +++ b/tftf/framework/framework.mk @@ -1,5 +1,5 @@ # -# Copyright (c) 2018, Arm Limited. All rights reserved. +# Copyright (c) 2018-2019, Arm Limited. All rights reserved. # # SPDX-License-Identifier: BSD-3-Clause # @@ -73,6 +73,13 @@ FRAMEWORK_SOURCES += \ FRAMEWORK_SOURCES += ${COMPILER_RT_SRCS} +ifeq (${ARCH},aarch64) +# ARMv8.3 Pointer Authentication support files +FRAMEWORK_SOURCES += \ + lib/extensions/pauth/aarch64/pauth.c \ + lib/extensions/pauth/aarch64/pauth_helpers.S +endif + TFTF_LINKERFILE := tftf/framework/tftf.ld.S diff --git a/tftf/tests/extensions/pauth/test_pauth.c b/tftf/tests/extensions/pauth/test_pauth.c index 564c56d9f..30b78ef19 100644 --- a/tftf/tests/extensions/pauth/test_pauth.c +++ b/tftf/tests/extensions/pauth/test_pauth.c @@ -4,6 +4,7 @@ * SPDX-License-Identifier: BSD-3-Clause */ +#include <pauth.h> #include <psci.h> #include <smccc.h> #include <test_helpers.h> @@ -12,40 +13,156 @@ #include <tsp.h> #include <string.h> -/* The length of the array used to hold the pauth keys */ -#define LENGTH_KEYS 10 +#ifdef __aarch64__ -#ifndef AARCH32 -static void read_pauth_keys(uint64_t *pauth_keys, unsigned int len) +/* Number of ARMv8.3-PAuth keys */ +#define NUM_KEYS 5 + +static const char * const key_name[] = {"IA", "IB", "DA", "DB", "GA"}; + +static uint128_t pauth_keys_before[NUM_KEYS]; +static uint128_t pauth_keys_after[NUM_KEYS]; + +/* Check if ARMv8.3-PAuth key is enabled */ +static bool is_pauth_key_enabled(uint64_t key_bit) +{ + return (IS_IN_EL2() ? + ((read_sctlr_el2() & key_bit) != 0U) : + ((read_sctlr_el1() & key_bit) != 0U)); +} + +static test_result_t compare_pauth_keys(void) { - assert(len >= LENGTH_KEYS); + test_result_t result = TEST_RESULT_SUCCESS; - memset(pauth_keys, 0, len * sizeof(uint64_t)); + for (unsigned int i = 0; i < NUM_KEYS; ++i) { + if (pauth_keys_before[i] != pauth_keys_after[i]) { + ERROR("AP%sKey_EL1 read 0x%llx:%llx " + "expected 0x%llx:%llx\n", key_name[i], + (uint64_t)(pauth_keys_after[i] >> 64), + (uint64_t)(pauth_keys_after[i]), + (uint64_t)(pauth_keys_before[i] >> 64), + (uint64_t)(pauth_keys_before[i])); + + result = TEST_RESULT_FAIL; + } + } + return result; +} + +/* + * Program or read ARMv8.3-PAuth keys (if already enabled) + * and store them in <pauth_keys_before> buffer + */ +static void set_store_pauth_keys(void) +{ + uint128_t plat_key; + + memset(pauth_keys_before, 0, NUM_KEYS * sizeof(uint128_t)); if (is_armv8_3_pauth_apa_api_present()) { - /* read instruction keys a and b (both 128 bit) */ - pauth_keys[0] = read_apiakeylo_el1(); - pauth_keys[1] = read_apiakeyhi_el1(); + if (is_pauth_key_enabled(SCTLR_EnIA_BIT)) { + /* Read APIAKey_EL1 */ + plat_key = read_apiakeylo_el1() | + ((uint128_t)(read_apiakeyhi_el1()) << 64); + INFO("EnIA is set\n"); + } else { + /* Program APIAKey_EL1 */ + plat_key = init_apkey(); + write_apiakeylo_el1((uint64_t)plat_key); + write_apiakeyhi_el1((uint64_t)(plat_key >> 64)); + } + pauth_keys_before[0] = plat_key; - pauth_keys[2] = read_apibkeylo_el1(); - pauth_keys[3] = read_apibkeyhi_el1(); + if (is_pauth_key_enabled(SCTLR_EnIB_BIT)) { + /* Read APIBKey_EL1 */ + plat_key = read_apibkeylo_el1() | + ((uint128_t)(read_apibkeyhi_el1()) << 64); + INFO("EnIB is set\n"); + } else { + /* Program APIBKey_EL1 */ + plat_key = init_apkey(); + write_apibkeylo_el1((uint64_t)plat_key); + write_apibkeyhi_el1((uint64_t)(plat_key >> 64)); + } + pauth_keys_before[1] = plat_key; - /* read data keys a and b (both 128 bit) */ - pauth_keys[4] = read_apdakeylo_el1(); - pauth_keys[5] = read_apdakeyhi_el1(); + if (is_pauth_key_enabled(SCTLR_EnDA_BIT)) { + /* Read APDAKey_EL1 */ + plat_key = read_apdakeylo_el1() | + ((uint128_t)(read_apdakeyhi_el1()) << 64); + INFO("EnDA is set\n"); + } else { + /* Program APDAKey_EL1 */ + plat_key = init_apkey(); + write_apdakeylo_el1((uint64_t)plat_key); + write_apdakeyhi_el1((uint64_t)(plat_key >> 64)); + } + pauth_keys_before[2] = plat_key; - pauth_keys[6] = read_apdbkeylo_el1(); - pauth_keys[7] = read_apdbkeyhi_el1(); + if (is_pauth_key_enabled(SCTLR_EnDB_BIT)) { + /* Read APDBKey_EL1 */ + plat_key = read_apdbkeylo_el1() | + ((uint128_t)(read_apdbkeyhi_el1()) << 64); + INFO("EnDB is set\n"); + } else { + /* Program APDBKey_EL1 */ + plat_key = init_apkey(); + write_apdbkeylo_el1((uint64_t)plat_key); + write_apdbkeyhi_el1((uint64_t)(plat_key >> 64)); + } + pauth_keys_before[3] = plat_key; } + /* + * It is safe to assume that Generic Pointer authentication code key + * APGAKey_EL1 can be re-programmed, as this key is not set in + * TF-A Test suite and PACGA instruction is not used. + */ if (is_armv8_3_pauth_gpa_gpi_present()) { - /* read generic key */ - pauth_keys[8] = read_apgakeylo_el1(); - pauth_keys[9] = read_apgakeyhi_el1(); + /* Program APGAKey_EL1 */ + plat_key = init_apkey(); + write_apgakeylo_el1((uint64_t)plat_key); + write_apgakeyhi_el1((uint64_t)(plat_key >> 64)); + pauth_keys_before[4] = plat_key; } + isb(); } -#endif + +/* + * Read ARMv8.3-PAuth keys and store them in + * <pauth_keys_after> buffer + */ +static void read_pauth_keys(void) +{ + memset(pauth_keys_after, 0, NUM_KEYS * sizeof(uint128_t)); + + if (is_armv8_3_pauth_apa_api_present()) { + /* Read APIAKey_EL1 */ + pauth_keys_after[0] = read_apiakeylo_el1() | + ((uint128_t)(read_apiakeyhi_el1()) << 64); + + /* Read APIBKey_EL1 */ + pauth_keys_after[1] = read_apibkeylo_el1() | + ((uint128_t)(read_apibkeyhi_el1()) << 64); + + /* Read APDAKey_EL1 */ + pauth_keys_after[2] = read_apdakeylo_el1() | + ((uint128_t)(read_apdakeyhi_el1()) << 64); + + /* Read APDBKey_EL1 */ + pauth_keys_after[3] = read_apdbkeylo_el1() | + ((uint128_t)(read_apdbkeyhi_el1()) << 64); + } + + if (is_armv8_3_pauth_gpa_gpi_present()) { + /* Read APGAKey_EL1 */ + pauth_keys_after[4] = read_apgakeylo_el1() | + ((uint128_t)(read_apgakeyhi_el1()) << 64); + } +} +#endif /* __aarch64__ */ /* * TF-A is expected to allow access to key registers from lower EL's, @@ -55,84 +172,73 @@ static void read_pauth_keys(uint64_t *pauth_keys, unsigned int len) test_result_t test_pauth_reg_access(void) { SKIP_TEST_IF_AARCH32(); -#ifndef AARCH32 - uint64_t pauth_keys[LENGTH_KEYS]; +#ifdef __aarch64__ SKIP_TEST_IF_PAUTH_NOT_SUPPORTED(); - read_pauth_keys(pauth_keys, LENGTH_KEYS); + read_pauth_keys(); return TEST_RESULT_SUCCESS; -#endif +#endif /* __aarch64__ */ } /* - * Makes a call to psci version, and checks that the EL3 pauth keys are not + * Makes a call to PSCI version, and checks that the EL3 pauth keys are not * leaked when it returns */ -#if (__GNUC__ > 7 || (__GNUC__ == 7 && __GNUC_MINOR__ > 0)) && AARCH64 -__attribute__((target("sign-return-address=all"))) -#endif test_result_t test_pauth_leakage(void) { SKIP_TEST_IF_AARCH32(); -#ifndef AARCH32 - uint64_t pauth_keys_before[LENGTH_KEYS]; - uint64_t pauth_keys_after[LENGTH_KEYS]; +#ifdef __aarch64__ SKIP_TEST_IF_PAUTH_NOT_SUPPORTED(); - - read_pauth_keys(pauth_keys_before, LENGTH_KEYS); + set_store_pauth_keys(); tftf_get_psci_version(); - read_pauth_keys(pauth_keys_after, LENGTH_KEYS); + read_pauth_keys(); - if (memcmp(pauth_keys_before, pauth_keys_after, - LENGTH_KEYS * sizeof(uint64_t)) != 0) - return TEST_RESULT_FAIL; - return TEST_RESULT_SUCCESS; -#endif + return compare_pauth_keys(); +#endif /* __aarch64__ */ } -/* Uses the pauth instructions, this checks the enable PAUTH bit has been set */ +/* Test execution of ARMv8.3-PAuth instructions */ test_result_t test_pauth_instructions(void) { SKIP_TEST_IF_AARCH32(); -#ifndef AARCH32 +#ifdef __aarch64__ SKIP_TEST_IF_PAUTH_NOT_SUPPORTED(); - /* - * Pointer authentication instructions (explicit encoding for compilers - * that do not recognize these instructions) - */ - /* paciasp */ - __asm__ volatile (".inst 0xD503233F"); - /* autiasp */ - __asm__ volatile (".inst 0xD50323BF"); - /* paciasp */ - __asm__ volatile (".inst 0xD503233F"); - /* xpaclri */ - __asm__ volatile (".inst 0xD50320FF"); + +#if ARM_ARCH_AT_LEAST(8, 3) + /* Pointer authentication instructions */ + __asm__ volatile ( + "paciasp\n" + "autiasp\n" + "paciasp\n" + "xpaclri" + ); return TEST_RESULT_SUCCESS; -#endif +#else + tftf_testcase_printf("Pointer Authentication instructions " + "are not supported on ARMv%u.%u\n", + ARM_ARCH_MAJOR, ARM_ARCH_MINOR); + return TEST_RESULT_SKIPPED; +#endif /* ARM_ARCH_AT_LEAST(8, 3) */ + +#endif /* __aarch64__ */ } /* * Makes a call to TSP ADD, and checks that the checks that the Secure World * pauth keys are not leaked */ -#if (__GNUC__ > 7 || (__GNUC__ == 7 && __GNUC_MINOR__ > 0)) && AARCH64 -__attribute__((target("sign-return-address=all"))) -#endif test_result_t test_pauth_leakage_tsp(void) { SKIP_TEST_IF_AARCH32(); -#ifndef AARCH32 +#ifdef __aarch64__ smc_args tsp_svc_params; smc_ret_values tsp_result = {0}; - uint64_t pauth_keys_before[LENGTH_KEYS]; - uint64_t pauth_keys_after[LENGTH_KEYS]; SKIP_TEST_IF_PAUTH_NOT_SUPPORTED(); SKIP_TEST_IF_TSP_NOT_PRESENT(); - read_pauth_keys(pauth_keys_before, LENGTH_KEYS); + set_store_pauth_keys(); /* Standard SMC to ADD two numbers */ tsp_svc_params.fid = TSP_STD_FID(TSP_ADD); @@ -145,20 +251,17 @@ test_result_t test_pauth_leakage_tsp(void) * the arguments to themselves and return */ if (tsp_result.ret0 != 0 || tsp_result.ret1 != 8 || - tsp_result.ret2 != 12) { - tftf_testcase_printf("TSP add returned wrong result:" + tsp_result.ret2 != 12) { + tftf_testcase_printf("TSP add returned wrong result: " "got %d %d %d expected: 0 8 12\n", - (unsigned int)tsp_result.ret0, - (unsigned int)tsp_result.ret1, - (unsigned int)tsp_result.ret2); - + (unsigned int)tsp_result.ret0, + (unsigned int)tsp_result.ret1, + (unsigned int)tsp_result.ret2); return TEST_RESULT_FAIL; } - read_pauth_keys(pauth_keys_after, LENGTH_KEYS); - if (memcmp(pauth_keys_before, pauth_keys_after, - LENGTH_KEYS * sizeof(uint64_t)) != 0) - return TEST_RESULT_FAIL; - return TEST_RESULT_SUCCESS; -#endif + read_pauth_keys(); + + return compare_pauth_keys(); +#endif /* __aarch64__ */ } |