blob: 90e16d5bd819feb31f5f46be88922f22f3255b0b [file] [log] [blame]
Alexei Fedorov719714f2019-10-03 10:57:53 +01001/*
2 * Copyright (c) 2019, Arm Limited. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <arch_helpers.h>
8#include <cdefs.h>
Shruti Gupta9d0cfe82023-04-17 10:57:26 +01009#include <stdbool.h>
Alexei Fedorov719714f2019-10-03 10:57:53 +010010#include <stdint.h>
Shruti Gupta9d0cfe82023-04-17 10:57:26 +010011#include <debug.h>
12#include <pauth.h>
13
14/* Number of ARMv8.3-PAuth keys */
15#define NUM_KEYS 5U
16
17static const char * const key_name[] = {"IA", "IB", "DA", "DB", "GA"};
18
19static uint128_t pauth_keys_before[NUM_KEYS];
20static uint128_t pauth_keys_after[NUM_KEYS];
Alexei Fedorov719714f2019-10-03 10:57:53 +010021
22/*
23 * This is only a toy implementation to generate a seemingly random
24 * 128-bit key from sp, x30 and cntpct_el0 values.
25 */
26uint128_t init_apkey(void)
27{
28 uint64_t return_addr = (uint64_t)__builtin_return_address(0U);
29 uint64_t frame_addr = (uint64_t)__builtin_frame_address(0U);
30
31 uint64_t cntpct = read_cntpct_el0();
32
33 uint64_t key_lo = (return_addr << 13) ^ frame_addr ^ cntpct;
34 uint64_t key_hi = (frame_addr << 15) ^ return_addr ^ cntpct;
35
36 return ((uint128_t)(key_hi) << 64) | key_lo;
37}
Shruti Gupta9d0cfe82023-04-17 10:57:26 +010038
39/* Check if ARMv8.3-PAuth key is enabled */
40static bool is_pauth_key_enabled(uint64_t key_bit)
41{
42 unsigned int el = (unsigned int)GET_EL(read_CurrentEl());
43
44 if (el == 1U) {
45 return ((read_sctlr_el1() & key_bit) != 0U);
46 } else if (el == 2U) {
47 return ((read_sctlr_el2() & key_bit) != 0U);
48 }
49 return false;
50}
51
52bool pauth_test_lib_compare_template(void)
53{
54 bool result = true;
55
56 pauth_test_lib_read_keys();
57 for (unsigned int i = 0U; i < NUM_KEYS; ++i) {
58 if (pauth_keys_before[i] != pauth_keys_after[i]) {
59 ERROR("AP%sKey_EL1 read 0x%llx:%llx "
60 "expected 0x%llx:%llx\n", key_name[i],
61 (uint64_t)(pauth_keys_after[i] >> 64U),
62 (uint64_t)(pauth_keys_after[i]),
63 (uint64_t)(pauth_keys_before[i] >> 64U),
64 (uint64_t)(pauth_keys_before[i]));
65
66 result = false;
67 }
68 }
69 return result;
70}
71
72/*
73 * Program or read ARMv8.3-PAuth keys (if already enabled)
74 * and store them in <pauth_keys_before> buffer
75 */
76void pauth_test_lib_fill_regs_and_template(void)
77{
78 uint128_t plat_key;
79
80 (void)memset(pauth_keys_before, 0, NUM_KEYS * sizeof(uint128_t));
81
82 if (is_pauth_key_enabled(SCTLR_EnIA_BIT)) {
83 /* Read APIAKey_EL1 */
84 plat_key = read_apiakeylo_el1() |
85 ((uint128_t)(read_apiakeyhi_el1()) << 64U);
86 INFO("EnIA is set\n");
87 } else {
88 /* Program APIAKey_EL1 */
89 plat_key = init_apkey();
90 write_apiakeylo_el1((uint64_t)plat_key);
91 write_apiakeyhi_el1((uint64_t)(plat_key >> 64U));
92 }
93 pauth_keys_before[0] = plat_key;
94
95 if (is_pauth_key_enabled(SCTLR_EnIB_BIT)) {
96 /* Read APIBKey_EL1 */
97 plat_key = read_apibkeylo_el1() |
98 ((uint128_t)(read_apibkeyhi_el1()) << 64U);
99 INFO("EnIB is set\n");
100 } else {
101 /* Program APIBKey_EL1 */
102 plat_key = init_apkey();
103 write_apibkeylo_el1((uint64_t)plat_key);
104 write_apibkeyhi_el1((uint64_t)(plat_key >> 64U));
105 }
106 pauth_keys_before[1] = plat_key;
107
108 if (is_pauth_key_enabled(SCTLR_EnDA_BIT)) {
109 /* Read APDAKey_EL1 */
110 plat_key = read_apdakeylo_el1() |
111 ((uint128_t)(read_apdakeyhi_el1()) << 64U);
112 INFO("EnDA is set\n");
113 } else {
114 /* Program APDAKey_EL1 */
115 plat_key = init_apkey();
116 write_apdakeylo_el1((uint64_t)plat_key);
117 write_apdakeyhi_el1((uint64_t)(plat_key >> 64U));
118 }
119 pauth_keys_before[2] = plat_key;
120
121 if (is_pauth_key_enabled(SCTLR_EnDB_BIT)) {
122 /* Read APDBKey_EL1 */
123 plat_key = read_apdbkeylo_el1() |
124 ((uint128_t)(read_apdbkeyhi_el1()) << 64U);
125 INFO("EnDB is set\n");
126 } else {
127 /* Program APDBKey_EL1 */
128 plat_key = init_apkey();
129 write_apdbkeylo_el1((uint64_t)plat_key);
130 write_apdbkeyhi_el1((uint64_t)(plat_key >> 64U));
131 }
132 pauth_keys_before[3] = plat_key;
133
134 pauth_keys_before[4] = read_apgakeylo_el1() |
135 ((uint128_t)(read_apgakeyhi_el1()) << 64U);
136 if (pauth_keys_before[4] == 0ULL) {
137 /* Program APGAKey_EL1 */
138 plat_key = init_apkey();
139 write_apgakeylo_el1((uint64_t)plat_key);
140 write_apgakeyhi_el1((uint64_t)(plat_key >> 64U));
141 pauth_keys_before[4] = plat_key;
142 }
143
144 isb();
145}
146
147/*
148 * Read ARMv8.3-PAuth keys and store them in
149 * <pauth_keys_after> buffer
150 */
151void pauth_test_lib_read_keys(void)
152{
153 (void)memset(pauth_keys_after, 0, NUM_KEYS * sizeof(uint128_t));
154
155 /* Read APIAKey_EL1 */
156 pauth_keys_after[0] = read_apiakeylo_el1() |
157 ((uint128_t)(read_apiakeyhi_el1()) << 64U);
158
159 /* Read APIBKey_EL1 */
160 pauth_keys_after[1] = read_apibkeylo_el1() |
161 ((uint128_t)(read_apibkeyhi_el1()) << 64U);
162
163 /* Read APDAKey_EL1 */
164 pauth_keys_after[2] = read_apdakeylo_el1() |
165 ((uint128_t)(read_apdakeyhi_el1()) << 64U);
166
167 /* Read APDBKey_EL1 */
168 pauth_keys_after[3] = read_apdbkeylo_el1() |
169 ((uint128_t)(read_apdbkeyhi_el1()) << 64U);
170
171 /* Read APGAKey_EL1 */
172 pauth_keys_after[4] = read_apgakeylo_el1() |
173 ((uint128_t)(read_apgakeyhi_el1()) << 64U);
174}
175
176/* Test execution of ARMv8.3-PAuth instructions */
177void pauth_test_lib_test_intrs(void)
178{
179 /* Pointer authentication instructions */
180 __asm__ volatile (
181 "paciasp\n"
182 "autiasp\n"
183 "paciasp\n"
184 "xpaclri");
185}