1d67ebadaSRichard Henderson #include <stdint.h>
2*871a7f6aSRichard Henderson #include <signal.h>
3*871a7f6aSRichard Henderson #include <stdlib.h>
4d67ebadaSRichard Henderson #include <assert.h>
5*871a7f6aSRichard Henderson #include "pauth.h"
6*871a7f6aSRichard Henderson
7*871a7f6aSRichard Henderson
sigill(int sig,siginfo_t * info,void * vuc)8*871a7f6aSRichard Henderson static void sigill(int sig, siginfo_t *info, void *vuc)
9*871a7f6aSRichard Henderson {
10*871a7f6aSRichard Henderson ucontext_t *uc = vuc;
11*871a7f6aSRichard Henderson uint64_t test;
12*871a7f6aSRichard Henderson
13*871a7f6aSRichard Henderson /* There is only one insn below that is allowed to fault. */
14*871a7f6aSRichard Henderson asm volatile("adr %0, auth2_insn" : "=r"(test));
15*871a7f6aSRichard Henderson assert(test == uc->uc_mcontext.pc);
16*871a7f6aSRichard Henderson exit(0);
17*871a7f6aSRichard Henderson }
18*871a7f6aSRichard Henderson
19*871a7f6aSRichard Henderson static int pac_feature;
20d67ebadaSRichard Henderson
do_test(uint64_t value)21d67ebadaSRichard Henderson void do_test(uint64_t value)
22d67ebadaSRichard Henderson {
23d67ebadaSRichard Henderson uint64_t salt1, salt2;
24d67ebadaSRichard Henderson uint64_t encode, decode;
25d67ebadaSRichard Henderson
26d67ebadaSRichard Henderson /*
27d67ebadaSRichard Henderson * With TBI enabled and a 48-bit VA, there are 7 bits of auth,
28d67ebadaSRichard Henderson * and so a 1/128 chance of encode = pac(value,key,salt) producing
29d67ebadaSRichard Henderson * an auth for which leaves value unchanged.
30d67ebadaSRichard Henderson * Iterate until we find a salt for which encode != value.
31d67ebadaSRichard Henderson */
32d67ebadaSRichard Henderson for (salt1 = 1; ; salt1++) {
33d67ebadaSRichard Henderson asm volatile("pacda %0, %2" : "=r"(encode) : "0"(value), "r"(salt1));
34d67ebadaSRichard Henderson if (encode != value) {
35d67ebadaSRichard Henderson break;
36d67ebadaSRichard Henderson }
37d67ebadaSRichard Henderson }
38d67ebadaSRichard Henderson
39d67ebadaSRichard Henderson /* A valid salt must produce a valid authorization. */
40d67ebadaSRichard Henderson asm volatile("autda %0, %2" : "=r"(decode) : "0"(encode), "r"(salt1));
41d67ebadaSRichard Henderson assert(decode == value);
42d67ebadaSRichard Henderson
43d67ebadaSRichard Henderson /*
44d67ebadaSRichard Henderson * An invalid salt usually fails authorization, but again there
45d67ebadaSRichard Henderson * is a chance of choosing another salt that works.
46d67ebadaSRichard Henderson * Iterate until we find another salt which does fail.
47*871a7f6aSRichard Henderson *
48*871a7f6aSRichard Henderson * With FEAT_FPAC, this will SIGILL instead of producing a result.
49d67ebadaSRichard Henderson */
50d67ebadaSRichard Henderson for (salt2 = salt1 + 1; ; salt2++) {
51*871a7f6aSRichard Henderson asm volatile("auth2_insn: autda %0, %2"
52*871a7f6aSRichard Henderson : "=r"(decode) : "0"(encode), "r"(salt2));
53d67ebadaSRichard Henderson if (decode != value) {
54d67ebadaSRichard Henderson break;
55d67ebadaSRichard Henderson }
56d67ebadaSRichard Henderson }
57d67ebadaSRichard Henderson
58*871a7f6aSRichard Henderson assert(pac_feature < 4); /* No FEAT_FPAC */
59*871a7f6aSRichard Henderson
60d67ebadaSRichard Henderson /* The VA bits, bit 55, and the TBI bits, should be unchanged. */
61d67ebadaSRichard Henderson assert(((decode ^ value) & 0xff80ffffffffffffull) == 0);
62d67ebadaSRichard Henderson
63d67ebadaSRichard Henderson /*
64*871a7f6aSRichard Henderson * Without FEAT_Pauth2, bits [54:53] are an error indicator based on
65*871a7f6aSRichard Henderson * the key used; the DA key above is keynumber 0, so error == 0b01.
66*871a7f6aSRichard Henderson * Otherwise, bit 55 of the original is sign-extended into the rest
67*871a7f6aSRichard Henderson * of the auth.
68d67ebadaSRichard Henderson */
69*871a7f6aSRichard Henderson if (pac_feature < 3) {
70d67ebadaSRichard Henderson if ((value >> 55) & 1) {
71d67ebadaSRichard Henderson assert(((decode >> 48) & 0xff) == 0b10111111);
72d67ebadaSRichard Henderson } else {
73d67ebadaSRichard Henderson assert(((decode >> 48) & 0xff) == 0b00100000);
74d67ebadaSRichard Henderson }
75d67ebadaSRichard Henderson }
76*871a7f6aSRichard Henderson }
77d67ebadaSRichard Henderson
main()78d67ebadaSRichard Henderson int main()
79d67ebadaSRichard Henderson {
80*871a7f6aSRichard Henderson static const struct sigaction sa = {
81*871a7f6aSRichard Henderson .sa_sigaction = sigill,
82*871a7f6aSRichard Henderson .sa_flags = SA_SIGINFO
83*871a7f6aSRichard Henderson };
84*871a7f6aSRichard Henderson
85*871a7f6aSRichard Henderson pac_feature = get_pac_feature();
86*871a7f6aSRichard Henderson assert(pac_feature != 0);
87*871a7f6aSRichard Henderson
88*871a7f6aSRichard Henderson if (pac_feature >= 4) {
89*871a7f6aSRichard Henderson /* FEAT_FPAC */
90*871a7f6aSRichard Henderson sigaction(SIGILL, &sa, NULL);
91*871a7f6aSRichard Henderson }
92*871a7f6aSRichard Henderson
93d67ebadaSRichard Henderson do_test(0);
94d67ebadaSRichard Henderson do_test(0xda004acedeadbeefull);
95d67ebadaSRichard Henderson return 0;
96d67ebadaSRichard Henderson }
97