| 1 | #include <assert.h> |
| 2 | #include "pauth.h" |
| 3 | |
| 4 | static int x; |
| 5 | |
| 6 | int main() |
| 7 | { |
| 8 | int *p0 = &x, *p1, *p2, *p3; |
| 9 | unsigned long salt = 0; |
| 10 | int pac_feature = get_pac_feature(); |
| 11 | |
| 12 | /* |
| 13 | * Exit if no PAuth or FEAT_FPAC, which will SIGILL on AUTDA failure |
| 14 | * rather than return an error for us to check below. |
| 15 | */ |
| 16 | if (pac_feature == 0 || pac_feature >= 4) { |
| 17 | return 0; |
| 18 | } |
| 19 | |
| 20 | /* |
| 21 | * With TBI enabled and a 48-bit VA, there are 7 bits of auth, and so |
| 22 | * a 1/128 chance of auth = pac(ptr,key,salt) producing zero. |
| 23 | * Find a salt that creates auth != 0. |
| 24 | */ |
| 25 | do { |
| 26 | salt++; |
| 27 | asm("pacda %0, %1" : "=r"(p1) : "r"(salt), "0"(p0)); |
| 28 | } while (p0 == p1); |
| 29 | |
| 30 | /* |
| 31 | * This pac must fail, because the input pointer bears an encryption, |
| 32 | * and so is not properly extended within bits [55:47]. This will |
| 33 | * toggle bit 54 in the output... |
| 34 | */ |
| 35 | asm("pacda %0, %1" : "=r"(p2) : "r"(salt), "0"(p1)); |
| 36 | |
| 37 | /* ... so that the aut must fail, setting bit 53 in the output ... */ |
| 38 | asm("autda %0, %1" : "=r"(p3) : "r"(salt), "0"(p2)); |
| 39 | |
| 40 | /* ... which means this equality must not hold. */ |
| 41 | assert(p3 != p0); |
| 42 | return 0; |
| 43 | } |