aboutsummaryrefslogtreecommitdiff
path: root/tftf/tests/extensions/pauth/test_pauth.c
blob: 564c56d9fd68abf8ba1757058da5920ead717a31 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
/*
 * Copyright (c) 2019, Arm Limited. All rights reserved.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

#include <psci.h>
#include <smccc.h>
#include <test_helpers.h>
#include <tftf_lib.h>
#include <tftf.h>
#include <tsp.h>
#include <string.h>

/* The length of the array used to hold the pauth keys */
#define LENGTH_KEYS 10

#ifndef AARCH32
static void read_pauth_keys(uint64_t *pauth_keys, unsigned int len)
{
	assert(len >= LENGTH_KEYS);

	memset(pauth_keys, 0, len * sizeof(uint64_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();

		pauth_keys[2] = read_apibkeylo_el1();
		pauth_keys[3] = read_apibkeyhi_el1();

		/* read data keys a and b (both 128 bit) */
		pauth_keys[4] = read_apdakeylo_el1();
		pauth_keys[5] = read_apdakeyhi_el1();

		pauth_keys[6] = read_apdbkeylo_el1();
		pauth_keys[7] = read_apdbkeyhi_el1();
	}

	if (is_armv8_3_pauth_gpa_gpi_present()) {
		/* read generic key */
		pauth_keys[8] = read_apgakeylo_el1();
		pauth_keys[9] = read_apgakeyhi_el1();
	}

}
#endif

/*
 * TF-A is expected to allow access to key registers from lower EL's,
 * reading the keys excercises this, on failure this will trap to
 * EL3 and crash.
 */
test_result_t test_pauth_reg_access(void)
{
	SKIP_TEST_IF_AARCH32();
#ifndef AARCH32
	uint64_t pauth_keys[LENGTH_KEYS];
	SKIP_TEST_IF_PAUTH_NOT_SUPPORTED();
	read_pauth_keys(pauth_keys, LENGTH_KEYS);
	return TEST_RESULT_SUCCESS;
#endif
}

/*
 * 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];
	SKIP_TEST_IF_PAUTH_NOT_SUPPORTED();

	read_pauth_keys(pauth_keys_before, LENGTH_KEYS);

	tftf_get_psci_version();

	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
}

/* Uses the pauth instructions, this checks the enable PAUTH bit has been set */
test_result_t test_pauth_instructions(void)
{
	SKIP_TEST_IF_AARCH32();
#ifndef AARCH32
	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");
	return TEST_RESULT_SUCCESS;
#endif
}

/*
 * 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
	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);

	/* Standard SMC to ADD two numbers */
	tsp_svc_params.fid = TSP_STD_FID(TSP_ADD);
	tsp_svc_params.arg1 = 4;
	tsp_svc_params.arg2 = 6;
	tsp_result = tftf_smc(&tsp_svc_params);

	/*
	 * Check the result of the addition-TSP_ADD will add
	 * 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:"
				     "got %d %d %d expected: 0 8 12\n",
						(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
}