1*d67ebadaSRichard Henderson #include <stdint.h> 2*d67ebadaSRichard Henderson #include <assert.h> 3*d67ebadaSRichard Henderson 4*d67ebadaSRichard Henderson asm(".arch armv8.4-a"); 5*d67ebadaSRichard Henderson 6*d67ebadaSRichard Henderson void do_test(uint64_t value) 7*d67ebadaSRichard Henderson { 8*d67ebadaSRichard Henderson uint64_t salt1, salt2; 9*d67ebadaSRichard Henderson uint64_t encode, decode; 10*d67ebadaSRichard Henderson 11*d67ebadaSRichard Henderson /* 12*d67ebadaSRichard Henderson * With TBI enabled and a 48-bit VA, there are 7 bits of auth, 13*d67ebadaSRichard Henderson * and so a 1/128 chance of encode = pac(value,key,salt) producing 14*d67ebadaSRichard Henderson * an auth for which leaves value unchanged. 15*d67ebadaSRichard Henderson * Iterate until we find a salt for which encode != value. 16*d67ebadaSRichard Henderson */ 17*d67ebadaSRichard Henderson for (salt1 = 1; ; salt1++) { 18*d67ebadaSRichard Henderson asm volatile("pacda %0, %2" : "=r"(encode) : "0"(value), "r"(salt1)); 19*d67ebadaSRichard Henderson if (encode != value) { 20*d67ebadaSRichard Henderson break; 21*d67ebadaSRichard Henderson } 22*d67ebadaSRichard Henderson } 23*d67ebadaSRichard Henderson 24*d67ebadaSRichard Henderson /* A valid salt must produce a valid authorization. */ 25*d67ebadaSRichard Henderson asm volatile("autda %0, %2" : "=r"(decode) : "0"(encode), "r"(salt1)); 26*d67ebadaSRichard Henderson assert(decode == value); 27*d67ebadaSRichard Henderson 28*d67ebadaSRichard Henderson /* 29*d67ebadaSRichard Henderson * An invalid salt usually fails authorization, but again there 30*d67ebadaSRichard Henderson * is a chance of choosing another salt that works. 31*d67ebadaSRichard Henderson * Iterate until we find another salt which does fail. 32*d67ebadaSRichard Henderson */ 33*d67ebadaSRichard Henderson for (salt2 = salt1 + 1; ; salt2++) { 34*d67ebadaSRichard Henderson asm volatile("autda %0, %2" : "=r"(decode) : "0"(encode), "r"(salt2)); 35*d67ebadaSRichard Henderson if (decode != value) { 36*d67ebadaSRichard Henderson break; 37*d67ebadaSRichard Henderson } 38*d67ebadaSRichard Henderson } 39*d67ebadaSRichard Henderson 40*d67ebadaSRichard Henderson /* The VA bits, bit 55, and the TBI bits, should be unchanged. */ 41*d67ebadaSRichard Henderson assert(((decode ^ value) & 0xff80ffffffffffffull) == 0); 42*d67ebadaSRichard Henderson 43*d67ebadaSRichard Henderson /* 44*d67ebadaSRichard Henderson * Bits [54:53] are an error indicator based on the key used; 45*d67ebadaSRichard Henderson * the DA key above is keynumber 0, so error == 0b01. Otherwise 46*d67ebadaSRichard Henderson * bit 55 of the original is sign-extended into the rest of the auth. 47*d67ebadaSRichard Henderson */ 48*d67ebadaSRichard Henderson if ((value >> 55) & 1) { 49*d67ebadaSRichard Henderson assert(((decode >> 48) & 0xff) == 0b10111111); 50*d67ebadaSRichard Henderson } else { 51*d67ebadaSRichard Henderson assert(((decode >> 48) & 0xff) == 0b00100000); 52*d67ebadaSRichard Henderson } 53*d67ebadaSRichard Henderson } 54*d67ebadaSRichard Henderson 55*d67ebadaSRichard Henderson int main() 56*d67ebadaSRichard Henderson { 57*d67ebadaSRichard Henderson do_test(0); 58*d67ebadaSRichard Henderson do_test(-1); 59*d67ebadaSRichard Henderson do_test(0xda004acedeadbeefull); 60*d67ebadaSRichard Henderson return 0; 61*d67ebadaSRichard Henderson } 62