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 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 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 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