1*0fca6ea1SDimitry Andric /*===---- ptrauth.h - Pointer authentication -------------------------------=== 2*0fca6ea1SDimitry Andric * 3*0fca6ea1SDimitry Andric * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0fca6ea1SDimitry Andric * See https://llvm.org/LICENSE.txt for license information. 5*0fca6ea1SDimitry Andric * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0fca6ea1SDimitry Andric * 7*0fca6ea1SDimitry Andric *===-----------------------------------------------------------------------=== 8*0fca6ea1SDimitry Andric */ 9*0fca6ea1SDimitry Andric 10*0fca6ea1SDimitry Andric #ifndef __PTRAUTH_H 11*0fca6ea1SDimitry Andric #define __PTRAUTH_H 12*0fca6ea1SDimitry Andric 13*0fca6ea1SDimitry Andric typedef enum { 14*0fca6ea1SDimitry Andric ptrauth_key_asia = 0, 15*0fca6ea1SDimitry Andric ptrauth_key_asib = 1, 16*0fca6ea1SDimitry Andric ptrauth_key_asda = 2, 17*0fca6ea1SDimitry Andric ptrauth_key_asdb = 3, 18*0fca6ea1SDimitry Andric 19*0fca6ea1SDimitry Andric /* A process-independent key which can be used to sign code pointers. */ 20*0fca6ea1SDimitry Andric ptrauth_key_process_independent_code = ptrauth_key_asia, 21*0fca6ea1SDimitry Andric 22*0fca6ea1SDimitry Andric /* A process-specific key which can be used to sign code pointers. */ 23*0fca6ea1SDimitry Andric ptrauth_key_process_dependent_code = ptrauth_key_asib, 24*0fca6ea1SDimitry Andric 25*0fca6ea1SDimitry Andric /* A process-independent key which can be used to sign data pointers. */ 26*0fca6ea1SDimitry Andric ptrauth_key_process_independent_data = ptrauth_key_asda, 27*0fca6ea1SDimitry Andric 28*0fca6ea1SDimitry Andric /* A process-specific key which can be used to sign data pointers. */ 29*0fca6ea1SDimitry Andric ptrauth_key_process_dependent_data = ptrauth_key_asdb, 30*0fca6ea1SDimitry Andric 31*0fca6ea1SDimitry Andric /* The key used to sign C function pointers. 32*0fca6ea1SDimitry Andric The extra data is always 0. */ 33*0fca6ea1SDimitry Andric ptrauth_key_function_pointer = ptrauth_key_process_independent_code, 34*0fca6ea1SDimitry Andric 35*0fca6ea1SDimitry Andric /* The key used to sign C++ v-table pointers. 36*0fca6ea1SDimitry Andric The extra data is always 0. */ 37*0fca6ea1SDimitry Andric ptrauth_key_cxx_vtable_pointer = ptrauth_key_process_independent_data, 38*0fca6ea1SDimitry Andric 39*0fca6ea1SDimitry Andric /* Other pointers signed under the ABI use private ABI rules. */ 40*0fca6ea1SDimitry Andric 41*0fca6ea1SDimitry Andric } ptrauth_key; 42*0fca6ea1SDimitry Andric 43*0fca6ea1SDimitry Andric /* An integer type of the appropriate size for a discriminator argument. */ 44*0fca6ea1SDimitry Andric typedef __UINTPTR_TYPE__ ptrauth_extra_data_t; 45*0fca6ea1SDimitry Andric 46*0fca6ea1SDimitry Andric /* An integer type of the appropriate size for a generic signature. */ 47*0fca6ea1SDimitry Andric typedef __UINTPTR_TYPE__ ptrauth_generic_signature_t; 48*0fca6ea1SDimitry Andric 49*0fca6ea1SDimitry Andric /* A signed pointer value embeds the original pointer together with 50*0fca6ea1SDimitry Andric a signature that attests to the validity of that pointer. Because 51*0fca6ea1SDimitry Andric this signature must use only "spare" bits of the pointer, a 52*0fca6ea1SDimitry Andric signature's validity is probabilistic in practice: it is unlikely 53*0fca6ea1SDimitry Andric but still plausible that an invalidly-derived signature will 54*0fca6ea1SDimitry Andric somehow equal the correct signature and therefore successfully 55*0fca6ea1SDimitry Andric authenticate. Nonetheless, this scheme provides a strong degree 56*0fca6ea1SDimitry Andric of protection against certain kinds of attacks. */ 57*0fca6ea1SDimitry Andric 58*0fca6ea1SDimitry Andric /* Authenticating a pointer that was not signed with the given key 59*0fca6ea1SDimitry Andric and extra-data value will (likely) fail by trapping. */ 60*0fca6ea1SDimitry Andric 61*0fca6ea1SDimitry Andric /* The null function pointer is always the all-zero bit pattern. 62*0fca6ea1SDimitry Andric Signing an all-zero bit pattern will embed a (likely) non-zero 63*0fca6ea1SDimitry Andric signature in the result, and so the result will not seem to be 64*0fca6ea1SDimitry Andric a null function pointer. Authenticating this value will yield 65*0fca6ea1SDimitry Andric a null function pointer back. However, authenticating an 66*0fca6ea1SDimitry Andric all-zero bit pattern will probably fail, because the 67*0fca6ea1SDimitry Andric authentication will expect a (likely) non-zero signature to 68*0fca6ea1SDimitry Andric embedded in the value. 69*0fca6ea1SDimitry Andric 70*0fca6ea1SDimitry Andric Because of this, if a pointer may validly be null, you should 71*0fca6ea1SDimitry Andric check for null before attempting to authenticate it with one 72*0fca6ea1SDimitry Andric of these intrinsics. This is not necessary when using the 73*0fca6ea1SDimitry Andric __ptrauth qualifier; the compiler will perform this check 74*0fca6ea1SDimitry Andric automatically. */ 75*0fca6ea1SDimitry Andric 76*0fca6ea1SDimitry Andric #if __has_feature(ptrauth_intrinsics) 77*0fca6ea1SDimitry Andric 78*0fca6ea1SDimitry Andric /* Strip the signature from a value without authenticating it. 79*0fca6ea1SDimitry Andric 80*0fca6ea1SDimitry Andric If the value is a function pointer, the result will not be a 81*0fca6ea1SDimitry Andric legal function pointer because of the missing signature, and 82*0fca6ea1SDimitry Andric attempting to call it will result in an authentication failure. 83*0fca6ea1SDimitry Andric 84*0fca6ea1SDimitry Andric The value must be an expression of pointer type. 85*0fca6ea1SDimitry Andric The key must be a constant expression of type ptrauth_key. 86*0fca6ea1SDimitry Andric The result will have the same type as the original value. */ 87*0fca6ea1SDimitry Andric #define ptrauth_strip(__value, __key) __builtin_ptrauth_strip(__value, __key) 88*0fca6ea1SDimitry Andric 89*0fca6ea1SDimitry Andric /* Blend a constant discriminator into the given pointer-like value 90*0fca6ea1SDimitry Andric to form a new discriminator. Not all bits of the inputs are 91*0fca6ea1SDimitry Andric guaranteed to contribute to the result. 92*0fca6ea1SDimitry Andric 93*0fca6ea1SDimitry Andric On arm64e, the integer must fall within the range of a uint16_t; 94*0fca6ea1SDimitry Andric other bits may be ignored. 95*0fca6ea1SDimitry Andric 96*0fca6ea1SDimitry Andric For the purposes of ptrauth_sign_constant, the result of calling 97*0fca6ea1SDimitry Andric this function is considered a constant expression if the arguments 98*0fca6ea1SDimitry Andric are constant. Some restrictions may be imposed on the pointer. 99*0fca6ea1SDimitry Andric 100*0fca6ea1SDimitry Andric The first argument must be an expression of pointer type. 101*0fca6ea1SDimitry Andric The second argument must be an expression of integer type. 102*0fca6ea1SDimitry Andric The result will have type uintptr_t. */ 103*0fca6ea1SDimitry Andric #define ptrauth_blend_discriminator(__pointer, __integer) \ 104*0fca6ea1SDimitry Andric __builtin_ptrauth_blend_discriminator(__pointer, __integer) 105*0fca6ea1SDimitry Andric 106*0fca6ea1SDimitry Andric /* Return a signed pointer for a constant address in a manner which guarantees 107*0fca6ea1SDimitry Andric a non-attackable sequence. 108*0fca6ea1SDimitry Andric 109*0fca6ea1SDimitry Andric The value must be a constant expression of pointer type which evaluates to 110*0fca6ea1SDimitry Andric a non-null pointer. 111*0fca6ea1SDimitry Andric The key must be a constant expression of type ptrauth_key. 112*0fca6ea1SDimitry Andric The extra data must be a constant expression of pointer or integer type; 113*0fca6ea1SDimitry Andric if an integer, it will be coerced to ptrauth_extra_data_t. 114*0fca6ea1SDimitry Andric The result will have the same type as the original value. 115*0fca6ea1SDimitry Andric 116*0fca6ea1SDimitry Andric This can be used in constant expressions. */ 117*0fca6ea1SDimitry Andric #define ptrauth_sign_constant(__value, __key, __data) \ 118*0fca6ea1SDimitry Andric __builtin_ptrauth_sign_constant(__value, __key, __data) 119*0fca6ea1SDimitry Andric 120*0fca6ea1SDimitry Andric /* Add a signature to the given pointer value using a specific key, 121*0fca6ea1SDimitry Andric using the given extra data as a salt to the signing process. 122*0fca6ea1SDimitry Andric 123*0fca6ea1SDimitry Andric This operation does not authenticate the original value and is 124*0fca6ea1SDimitry Andric therefore potentially insecure if an attacker could possibly 125*0fca6ea1SDimitry Andric control that value. 126*0fca6ea1SDimitry Andric 127*0fca6ea1SDimitry Andric The value must be an expression of pointer type. 128*0fca6ea1SDimitry Andric The key must be a constant expression of type ptrauth_key. 129*0fca6ea1SDimitry Andric The extra data must be an expression of pointer or integer type; 130*0fca6ea1SDimitry Andric if an integer, it will be coerced to ptrauth_extra_data_t. 131*0fca6ea1SDimitry Andric The result will have the same type as the original value. */ 132*0fca6ea1SDimitry Andric #define ptrauth_sign_unauthenticated(__value, __key, __data) \ 133*0fca6ea1SDimitry Andric __builtin_ptrauth_sign_unauthenticated(__value, __key, __data) 134*0fca6ea1SDimitry Andric 135*0fca6ea1SDimitry Andric /* Authenticate a pointer using one scheme and resign it using another. 136*0fca6ea1SDimitry Andric 137*0fca6ea1SDimitry Andric If the result is subsequently authenticated using the new scheme, that 138*0fca6ea1SDimitry Andric authentication is guaranteed to fail if and only if the initial 139*0fca6ea1SDimitry Andric authentication failed. 140*0fca6ea1SDimitry Andric 141*0fca6ea1SDimitry Andric The value must be an expression of pointer type. 142*0fca6ea1SDimitry Andric The key must be a constant expression of type ptrauth_key. 143*0fca6ea1SDimitry Andric The extra data must be an expression of pointer or integer type; 144*0fca6ea1SDimitry Andric if an integer, it will be coerced to ptrauth_extra_data_t. 145*0fca6ea1SDimitry Andric The result will have the same type as the original value. 146*0fca6ea1SDimitry Andric 147*0fca6ea1SDimitry Andric This operation is guaranteed to not leave the intermediate value 148*0fca6ea1SDimitry Andric available for attack before it is re-signed. 149*0fca6ea1SDimitry Andric 150*0fca6ea1SDimitry Andric Do not pass a null pointer to this function. A null pointer 151*0fca6ea1SDimitry Andric will not successfully authenticate. 152*0fca6ea1SDimitry Andric 153*0fca6ea1SDimitry Andric This operation traps if the authentication fails. */ 154*0fca6ea1SDimitry Andric #define ptrauth_auth_and_resign(__value, __old_key, __old_data, __new_key, \ 155*0fca6ea1SDimitry Andric __new_data) \ 156*0fca6ea1SDimitry Andric __builtin_ptrauth_auth_and_resign(__value, __old_key, __old_data, __new_key, \ 157*0fca6ea1SDimitry Andric __new_data) 158*0fca6ea1SDimitry Andric 159*0fca6ea1SDimitry Andric /* Authenticate a pointer using one scheme and resign it as a C 160*0fca6ea1SDimitry Andric function pointer. 161*0fca6ea1SDimitry Andric 162*0fca6ea1SDimitry Andric If the result is subsequently authenticated using the new scheme, that 163*0fca6ea1SDimitry Andric authentication is guaranteed to fail if and only if the initial 164*0fca6ea1SDimitry Andric authentication failed. 165*0fca6ea1SDimitry Andric 166*0fca6ea1SDimitry Andric The value must be an expression of function pointer type. 167*0fca6ea1SDimitry Andric The key must be a constant expression of type ptrauth_key. 168*0fca6ea1SDimitry Andric The extra data must be an expression of pointer or integer type; 169*0fca6ea1SDimitry Andric if an integer, it will be coerced to ptrauth_extra_data_t. 170*0fca6ea1SDimitry Andric The result will have the same type as the original value. 171*0fca6ea1SDimitry Andric 172*0fca6ea1SDimitry Andric This operation is guaranteed to not leave the intermediate value 173*0fca6ea1SDimitry Andric available for attack before it is re-signed. Additionally, if this 174*0fca6ea1SDimitry Andric expression is used syntactically as the function expression in a 175*0fca6ea1SDimitry Andric call, only a single authentication will be performed. */ 176*0fca6ea1SDimitry Andric #define ptrauth_auth_function(__value, __old_key, __old_data) \ 177*0fca6ea1SDimitry Andric ptrauth_auth_and_resign(__value, __old_key, __old_data, \ 178*0fca6ea1SDimitry Andric ptrauth_key_function_pointer, 0) 179*0fca6ea1SDimitry Andric 180*0fca6ea1SDimitry Andric /* Authenticate a data pointer. 181*0fca6ea1SDimitry Andric 182*0fca6ea1SDimitry Andric The value must be an expression of non-function pointer type. 183*0fca6ea1SDimitry Andric The key must be a constant expression of type ptrauth_key. 184*0fca6ea1SDimitry Andric The extra data must be an expression of pointer or integer type; 185*0fca6ea1SDimitry Andric if an integer, it will be coerced to ptrauth_extra_data_t. 186*0fca6ea1SDimitry Andric The result will have the same type as the original value. 187*0fca6ea1SDimitry Andric 188*0fca6ea1SDimitry Andric This operation traps if the authentication fails. */ 189*0fca6ea1SDimitry Andric #define ptrauth_auth_data(__value, __old_key, __old_data) \ 190*0fca6ea1SDimitry Andric __builtin_ptrauth_auth(__value, __old_key, __old_data) 191*0fca6ea1SDimitry Andric 192*0fca6ea1SDimitry Andric /* Compute a constant discriminator from the given string. 193*0fca6ea1SDimitry Andric 194*0fca6ea1SDimitry Andric The argument must be a string literal of char character type. The result 195*0fca6ea1SDimitry Andric has type ptrauth_extra_data_t. 196*0fca6ea1SDimitry Andric 197*0fca6ea1SDimitry Andric The result value is never zero and always within range for both the 198*0fca6ea1SDimitry Andric __ptrauth qualifier and ptrauth_blend_discriminator. 199*0fca6ea1SDimitry Andric 200*0fca6ea1SDimitry Andric This can be used in constant expressions. 201*0fca6ea1SDimitry Andric */ 202*0fca6ea1SDimitry Andric #define ptrauth_string_discriminator(__string) \ 203*0fca6ea1SDimitry Andric __builtin_ptrauth_string_discriminator(__string) 204*0fca6ea1SDimitry Andric 205*0fca6ea1SDimitry Andric /* Compute a signature for the given pair of pointer-sized values. 206*0fca6ea1SDimitry Andric The order of the arguments is significant. 207*0fca6ea1SDimitry Andric 208*0fca6ea1SDimitry Andric Like a pointer signature, the resulting signature depends on 209*0fca6ea1SDimitry Andric private key data and therefore should not be reliably reproducible 210*0fca6ea1SDimitry Andric by attackers. That means that this can be used to validate the 211*0fca6ea1SDimitry Andric integrity of arbitrary data by storing a signature for that data 212*0fca6ea1SDimitry Andric alongside it, then checking that the signature is still valid later. 213*0fca6ea1SDimitry Andric Data which exceeds two pointers in size can be signed by either 214*0fca6ea1SDimitry Andric computing a tree of generic signatures or just signing an ordinary 215*0fca6ea1SDimitry Andric cryptographic hash of the data. 216*0fca6ea1SDimitry Andric 217*0fca6ea1SDimitry Andric The result has type ptrauth_generic_signature_t. However, it may 218*0fca6ea1SDimitry Andric not have as many bits of entropy as that type's width would suggest; 219*0fca6ea1SDimitry Andric some implementations are known to compute a compressed signature as 220*0fca6ea1SDimitry Andric if the arguments were a pointer and a discriminator. 221*0fca6ea1SDimitry Andric 222*0fca6ea1SDimitry Andric The arguments must be either pointers or integers; if integers, they 223*0fca6ea1SDimitry Andric will be coerce to uintptr_t. */ 224*0fca6ea1SDimitry Andric #define ptrauth_sign_generic_data(__value, __data) \ 225*0fca6ea1SDimitry Andric __builtin_ptrauth_sign_generic_data(__value, __data) 226*0fca6ea1SDimitry Andric 227*0fca6ea1SDimitry Andric /* C++ vtable pointer signing class attribute */ 228*0fca6ea1SDimitry Andric #define ptrauth_cxx_vtable_pointer(key, address_discrimination, \ 229*0fca6ea1SDimitry Andric extra_discrimination...) \ 230*0fca6ea1SDimitry Andric [[clang::ptrauth_vtable_pointer(key, address_discrimination, \ 231*0fca6ea1SDimitry Andric extra_discrimination)]] 232*0fca6ea1SDimitry Andric 233*0fca6ea1SDimitry Andric #else 234*0fca6ea1SDimitry Andric 235*0fca6ea1SDimitry Andric #define ptrauth_strip(__value, __key) \ 236*0fca6ea1SDimitry Andric ({ \ 237*0fca6ea1SDimitry Andric (void)__key; \ 238*0fca6ea1SDimitry Andric __value; \ 239*0fca6ea1SDimitry Andric }) 240*0fca6ea1SDimitry Andric 241*0fca6ea1SDimitry Andric #define ptrauth_blend_discriminator(__pointer, __integer) \ 242*0fca6ea1SDimitry Andric ({ \ 243*0fca6ea1SDimitry Andric (void)__pointer; \ 244*0fca6ea1SDimitry Andric (void)__integer; \ 245*0fca6ea1SDimitry Andric ((ptrauth_extra_data_t)0); \ 246*0fca6ea1SDimitry Andric }) 247*0fca6ea1SDimitry Andric 248*0fca6ea1SDimitry Andric #define ptrauth_sign_constant(__value, __key, __data) \ 249*0fca6ea1SDimitry Andric ({ \ 250*0fca6ea1SDimitry Andric (void)__key; \ 251*0fca6ea1SDimitry Andric (void)__data; \ 252*0fca6ea1SDimitry Andric __value; \ 253*0fca6ea1SDimitry Andric }) 254*0fca6ea1SDimitry Andric 255*0fca6ea1SDimitry Andric #define ptrauth_sign_unauthenticated(__value, __key, __data) \ 256*0fca6ea1SDimitry Andric ({ \ 257*0fca6ea1SDimitry Andric (void)__key; \ 258*0fca6ea1SDimitry Andric (void)__data; \ 259*0fca6ea1SDimitry Andric __value; \ 260*0fca6ea1SDimitry Andric }) 261*0fca6ea1SDimitry Andric 262*0fca6ea1SDimitry Andric #define ptrauth_auth_and_resign(__value, __old_key, __old_data, __new_key, \ 263*0fca6ea1SDimitry Andric __new_data) \ 264*0fca6ea1SDimitry Andric ({ \ 265*0fca6ea1SDimitry Andric (void)__old_key; \ 266*0fca6ea1SDimitry Andric (void)__old_data; \ 267*0fca6ea1SDimitry Andric (void)__new_key; \ 268*0fca6ea1SDimitry Andric (void)__new_data; \ 269*0fca6ea1SDimitry Andric __value; \ 270*0fca6ea1SDimitry Andric }) 271*0fca6ea1SDimitry Andric 272*0fca6ea1SDimitry Andric #define ptrauth_auth_function(__value, __old_key, __old_data) \ 273*0fca6ea1SDimitry Andric ({ \ 274*0fca6ea1SDimitry Andric (void)__old_key; \ 275*0fca6ea1SDimitry Andric (void)__old_data; \ 276*0fca6ea1SDimitry Andric __value; \ 277*0fca6ea1SDimitry Andric }) 278*0fca6ea1SDimitry Andric 279*0fca6ea1SDimitry Andric #define ptrauth_auth_data(__value, __old_key, __old_data) \ 280*0fca6ea1SDimitry Andric ({ \ 281*0fca6ea1SDimitry Andric (void)__old_key; \ 282*0fca6ea1SDimitry Andric (void)__old_data; \ 283*0fca6ea1SDimitry Andric __value; \ 284*0fca6ea1SDimitry Andric }) 285*0fca6ea1SDimitry Andric 286*0fca6ea1SDimitry Andric #define ptrauth_string_discriminator(__string) \ 287*0fca6ea1SDimitry Andric ({ \ 288*0fca6ea1SDimitry Andric (void)__string; \ 289*0fca6ea1SDimitry Andric ((ptrauth_extra_data_t)0); \ 290*0fca6ea1SDimitry Andric }) 291*0fca6ea1SDimitry Andric 292*0fca6ea1SDimitry Andric #define ptrauth_sign_generic_data(__value, __data) \ 293*0fca6ea1SDimitry Andric ({ \ 294*0fca6ea1SDimitry Andric (void)__value; \ 295*0fca6ea1SDimitry Andric (void)__data; \ 296*0fca6ea1SDimitry Andric ((ptrauth_generic_signature_t)0); \ 297*0fca6ea1SDimitry Andric }) 298*0fca6ea1SDimitry Andric 299*0fca6ea1SDimitry Andric 300*0fca6ea1SDimitry Andric #define ptrauth_cxx_vtable_pointer(key, address_discrimination, \ 301*0fca6ea1SDimitry Andric extra_discrimination...) 302*0fca6ea1SDimitry Andric 303*0fca6ea1SDimitry Andric #endif /* __has_feature(ptrauth_intrinsics) */ 304*0fca6ea1SDimitry Andric 305*0fca6ea1SDimitry Andric #endif /* __PTRAUTH_H */ 306