aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexei Fedorov <Alexei.Fedorov@arm.com>2019-10-04 16:13:47 +0100
committerAlexei Fedorov <Alexei.Fedorov@arm.com>2019-10-08 16:15:59 +0100
commitfb003380a01843d0de71ba3374394a798289c64f (patch)
tree47e9fd3c2ba55dea7e2488e68b11534e865464c6
parent1ca3102141319bd514c296ddc256f92e321780a2 (diff)
downloadtf-a-tests-fb003380a01843d0de71ba3374394a798289c64f.tar.gz
TFTF: ARMv8.3-PAuth test code enhancements
This patch provides the following feature and makes modification listed below: - ARMv8.3-PAuth tests now check for all keys being in use (e.g. APIAKey when the test suite is built with `ENABLE_PAUTH=1` option) and program new key values otherwise. Signed-off-by: Alexei Fedorov <Alexei.Fedorov@arm.com> Change-Id: Ifa4a288274822029da585073563c68a1434f5de7
-rw-r--r--plat/arm/fvp/platform.mk6
-rw-r--r--tftf/framework/framework.mk9
-rw-r--r--tftf/tests/extensions/pauth/test_pauth.c249
3 files changed, 184 insertions, 80 deletions
diff --git a/plat/arm/fvp/platform.mk b/plat/arm/fvp/platform.mk
index bf4075d..c014d6d 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 00bb84a..34601c2 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 564c56d..30b78ef 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__ */
}