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