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