| 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 return addresses on the stack. |
| 32 | The extra data is based on the storage address of the return address. |
| 33 | On AArch64, that is always the storage address of the return address + 8 |
| 34 | (or, in other words, the value of the stack pointer on function entry) */ |
| 35 | ptrauth_key_return_address = ptrauth_key_process_dependent_code, |
| 36 | |
| 37 | /* The key used to sign C function pointers. |
| 38 | The extra data is always 0. */ |
| 39 | ptrauth_key_function_pointer = ptrauth_key_process_independent_code, |
| 40 | |
| 41 | /* The key used to sign C++ v-table pointers. |
| 42 | The extra data is always 0. */ |
| 43 | ptrauth_key_cxx_vtable_pointer = ptrauth_key_process_independent_data, |
| 44 | |
| 45 | /* The key used to sign metadata pointers to Objective-C method-lists. */ |
| 46 | ptrauth_key_method_list_pointer = ptrauth_key_asda, |
| 47 | |
| 48 | /* The key used to sign Objective-C isa and super pointers. */ |
| 49 | ptrauth_key_objc_isa_pointer = ptrauth_key_process_independent_data, |
| 50 | ptrauth_key_objc_super_pointer = ptrauth_key_process_independent_data, |
| 51 | |
| 52 | /* The key used to sign selector pointers */ |
| 53 | ptrauth_key_objc_sel_pointer = ptrauth_key_process_dependent_data, |
| 54 | |
| 55 | /* The key used to sign Objective-C class_ro_t pointers. */ |
| 56 | ptrauth_key_objc_class_ro_pointer = ptrauth_key_process_independent_data, |
| 57 | |
| 58 | /* The key used to sign pointers in ELF .init_array/.fini_array. */ |
| 59 | ptrauth_key_init_fini_pointer = ptrauth_key_process_independent_code, |
| 60 | |
| 61 | /* Other pointers signed under the ABI use private ABI rules. */ |
| 62 | |
| 63 | } ptrauth_key; |
| 64 | |
| 65 | /* An integer type of the appropriate size for a discriminator argument. */ |
| 66 | typedef __UINTPTR_TYPE__ ptrauth_extra_data_t; |
| 67 | |
| 68 | /* An integer type of the appropriate size for a generic signature. */ |
| 69 | typedef __UINTPTR_TYPE__ ptrauth_generic_signature_t; |
| 70 | |
| 71 | /* A signed pointer value embeds the original pointer together with |
| 72 | a signature that attests to the validity of that pointer. Because |
| 73 | this signature must use only "spare" bits of the pointer, a |
| 74 | signature's validity is probabilistic in practice: it is unlikely |
| 75 | but still plausible that an invalidly-derived signature will |
| 76 | somehow equal the correct signature and therefore successfully |
| 77 | authenticate. Nonetheless, this scheme provides a strong degree |
| 78 | of protection against certain kinds of attacks. */ |
| 79 | |
| 80 | /* Authenticating a pointer that was not signed with the given key |
| 81 | and extra-data value will (likely) fail by trapping. */ |
| 82 | |
| 83 | /* The null function pointer is always the all-zero bit pattern. |
| 84 | Signing an all-zero bit pattern will embed a (likely) non-zero |
| 85 | signature in the result, and so the result will not seem to be |
| 86 | a null function pointer. Authenticating this value will yield |
| 87 | a null function pointer back. However, authenticating an |
| 88 | all-zero bit pattern will probably fail, because the |
| 89 | authentication will expect a (likely) non-zero signature to |
| 90 | embedded in the value. |
| 91 | |
| 92 | Because of this, if a pointer may validly be null, you should |
| 93 | check for null before attempting to authenticate it with one |
| 94 | of these intrinsics. This is not necessary when using the |
| 95 | __ptrauth qualifier; the compiler will perform this check |
| 96 | automatically. */ |
| 97 | |
| 98 | #if __has_feature(ptrauth_intrinsics) || defined(__PTRAUTH__) |
| 99 | |
| 100 | /* Strip the signature from a value without authenticating it. |
| 101 | |
| 102 | If the value is a function pointer, the result will not be a |
| 103 | legal function pointer because of the missing signature, and |
| 104 | attempting to call it will result in an authentication failure. |
| 105 | |
| 106 | The value must be an expression of pointer type. |
| 107 | The key must be a constant expression of type ptrauth_key. |
| 108 | The result will have the same type as the original value. */ |
| 109 | #define ptrauth_strip(__value, __key) __builtin_ptrauth_strip(__value, __key) |
| 110 | |
| 111 | /* Blend a constant discriminator into the given pointer-like value |
| 112 | to form a new discriminator. Not all bits of the inputs are |
| 113 | guaranteed to contribute to the result. |
| 114 | |
| 115 | On arm64e, the integer must fall within the range of a uint16_t; |
| 116 | other bits may be ignored. |
| 117 | |
| 118 | For the purposes of ptrauth_sign_constant, the result of calling |
| 119 | this function is considered a constant expression if the arguments |
| 120 | are constant. Some restrictions may be imposed on the pointer. |
| 121 | |
| 122 | The first argument must be an expression of pointer type. |
| 123 | The second argument must be an expression of integer type. |
| 124 | The result will have type uintptr_t. */ |
| 125 | #define ptrauth_blend_discriminator(__pointer, __integer) \ |
| 126 | __builtin_ptrauth_blend_discriminator(__pointer, __integer) |
| 127 | |
| 128 | /* Return a signed pointer for a constant address in a manner which guarantees |
| 129 | a non-attackable sequence. |
| 130 | |
| 131 | The value must be a constant expression of pointer type which evaluates to |
| 132 | a non-null pointer. |
| 133 | The key must be a constant expression of type ptrauth_key. |
| 134 | The extra data must be a constant expression of pointer or integer type; |
| 135 | if an integer, it will be coerced to ptrauth_extra_data_t. |
| 136 | The result will have the same type as the original value. |
| 137 | |
| 138 | This can be used in constant expressions. */ |
| 139 | #define ptrauth_sign_constant(__value, __key, __data) \ |
| 140 | __builtin_ptrauth_sign_constant(__value, __key, __data) |
| 141 | |
| 142 | /* Add a signature to the given pointer value using a specific key, |
| 143 | using the given extra data as a salt to the signing process. |
| 144 | |
| 145 | This operation does not authenticate the original value and is |
| 146 | therefore potentially insecure if an attacker could possibly |
| 147 | control that value. |
| 148 | |
| 149 | The value must be an expression of pointer type. |
| 150 | The key must be a constant expression of type ptrauth_key. |
| 151 | The extra data must be an expression of pointer or integer type; |
| 152 | if an integer, it will be coerced to ptrauth_extra_data_t. |
| 153 | The result will have the same type as the original value. */ |
| 154 | #define ptrauth_sign_unauthenticated(__value, __key, __data) \ |
| 155 | __builtin_ptrauth_sign_unauthenticated(__value, __key, __data) |
| 156 | |
| 157 | /* Authenticate a pointer using one scheme and resign it using another. |
| 158 | |
| 159 | If the result is subsequently authenticated using the new scheme, that |
| 160 | authentication is guaranteed to fail if and only if the initial |
| 161 | authentication failed. |
| 162 | |
| 163 | The value must be an expression of pointer type. |
| 164 | The key must be a constant expression of type ptrauth_key. |
| 165 | The extra data must be an expression of pointer or integer type; |
| 166 | if an integer, it will be coerced to ptrauth_extra_data_t. |
| 167 | The result will have the same type as the original value. |
| 168 | |
| 169 | This operation is guaranteed to not leave the intermediate value |
| 170 | available for attack before it is re-signed. |
| 171 | |
| 172 | Do not pass a null pointer to this function. A null pointer |
| 173 | will not successfully authenticate. |
| 174 | |
| 175 | This operation traps if the authentication fails. */ |
| 176 | #define ptrauth_auth_and_resign(__value, __old_key, __old_data, __new_key, \ |
| 177 | __new_data) \ |
| 178 | __builtin_ptrauth_auth_and_resign(__value, __old_key, __old_data, __new_key, \ |
| 179 | __new_data) |
| 180 | |
| 181 | /* Authenticate a pointer using one scheme and resign it as a C |
| 182 | function pointer. |
| 183 | |
| 184 | If the result is subsequently authenticated using the new scheme, that |
| 185 | authentication is guaranteed to fail if and only if the initial |
| 186 | authentication failed. |
| 187 | |
| 188 | The value must be an expression of function pointer type. |
| 189 | The key must be a constant expression of type ptrauth_key. |
| 190 | The extra data must be an expression of pointer or integer type; |
| 191 | if an integer, it will be coerced to ptrauth_extra_data_t. |
| 192 | The result will have the same type as the original value. |
| 193 | |
| 194 | This operation is guaranteed to not leave the intermediate value |
| 195 | available for attack before it is re-signed. Additionally, if this |
| 196 | expression is used syntactically as the function expression in a |
| 197 | call, only a single authentication will be performed. */ |
| 198 | #define ptrauth_auth_function(__value, __old_key, __old_data) \ |
| 199 | ptrauth_auth_and_resign(__value, __old_key, __old_data, \ |
| 200 | ptrauth_key_function_pointer, 0) |
| 201 | |
| 202 | /* Authenticate a data pointer. |
| 203 | |
| 204 | The value must be an expression of non-function pointer type. |
| 205 | The key must be a constant expression of type ptrauth_key. |
| 206 | The extra data must be an expression of pointer or integer type; |
| 207 | if an integer, it will be coerced to ptrauth_extra_data_t. |
| 208 | The result will have the same type as the original value. |
| 209 | |
| 210 | This operation traps if the authentication fails. */ |
| 211 | #define ptrauth_auth_data(__value, __old_key, __old_data) \ |
| 212 | __builtin_ptrauth_auth(__value, __old_key, __old_data) |
| 213 | |
| 214 | /* Compute a constant discriminator from the given string. |
| 215 | |
| 216 | The argument must be a string literal of char character type. The result |
| 217 | has type ptrauth_extra_data_t. |
| 218 | |
| 219 | The result value is never zero and always within range for both the |
| 220 | __ptrauth qualifier and ptrauth_blend_discriminator. |
| 221 | |
| 222 | This can be used in constant expressions. |
| 223 | */ |
| 224 | #define ptrauth_string_discriminator(__string) \ |
| 225 | __builtin_ptrauth_string_discriminator(__string) |
| 226 | |
| 227 | /* Compute a constant discriminator from the given type. |
| 228 | |
| 229 | The result can be used as the second argument to |
| 230 | ptrauth_blend_discriminator or the third argument to the |
| 231 | __ptrauth qualifier. It has type size_t. |
| 232 | |
| 233 | If the type is a C++ member function pointer type, the result is |
| 234 | the discriminator used to signed member function pointers of that |
| 235 | type. If the type is a function, function pointer, or function |
| 236 | reference type, the result is the discriminator used to sign |
| 237 | functions of that type. It is ill-formed to use this macro with any |
| 238 | other type. |
| 239 | |
| 240 | A call to this function is an integer constant expression. */ |
| 241 | #define ptrauth_type_discriminator(__type) \ |
| 242 | __builtin_ptrauth_type_discriminator(__type) |
| 243 | |
| 244 | /* Compute the constant discriminator used by Clang to sign pointers with the |
| 245 | given C function pointer type. |
| 246 | |
| 247 | A call to this function is an integer constant expression. */ |
| 248 | #if __has_feature(ptrauth_function_pointer_type_discrimination) |
| 249 | #define ptrauth_function_pointer_type_discriminator(__type) \ |
| 250 | __builtin_ptrauth_type_discriminator(__type) |
| 251 | #else |
| 252 | #define ptrauth_function_pointer_type_discriminator(__type) \ |
| 253 | ((ptrauth_extra_data_t)0) |
| 254 | #endif |
| 255 | |
| 256 | /* Compute a signature for the given pair of pointer-sized values. |
| 257 | The order of the arguments is significant. |
| 258 | |
| 259 | Like a pointer signature, the resulting signature depends on |
| 260 | private key data and therefore should not be reliably reproducible |
| 261 | by attackers. That means that this can be used to validate the |
| 262 | integrity of arbitrary data by storing a signature for that data |
| 263 | alongside it, then checking that the signature is still valid later. |
| 264 | Data which exceeds two pointers in size can be signed by either |
| 265 | computing a tree of generic signatures or just signing an ordinary |
| 266 | cryptographic hash of the data. |
| 267 | |
| 268 | The result has type ptrauth_generic_signature_t. However, it may |
| 269 | not have as many bits of entropy as that type's width would suggest; |
| 270 | some implementations are known to compute a compressed signature as |
| 271 | if the arguments were a pointer and a discriminator. |
| 272 | |
| 273 | The arguments must be either pointers or integers; if integers, they |
| 274 | will be coerce to uintptr_t. */ |
| 275 | #define ptrauth_sign_generic_data(__value, __data) \ |
| 276 | __builtin_ptrauth_sign_generic_data(__value, __data) |
| 277 | |
| 278 | /* C++ vtable pointer signing class attribute */ |
| 279 | #define ptrauth_cxx_vtable_pointer(key, address_discrimination, \ |
| 280 | extra_discrimination...) \ |
| 281 | [[clang::ptrauth_vtable_pointer(key, address_discrimination, \ |
| 282 | extra_discrimination)]] |
| 283 | |
| 284 | /* The value is ptrauth_string_discriminator("init_fini") */ |
| 285 | #define __ptrauth_init_fini_discriminator 0xd9d4 |
| 286 | |
| 287 | /* Objective-C pointer auth ABI qualifiers */ |
| 288 | #define __ptrauth_objc_method_list_imp \ |
| 289 | __ptrauth(ptrauth_key_function_pointer, 1, 0) |
| 290 | |
| 291 | #if __has_feature(ptrauth_objc_method_list_pointer) |
| 292 | #define __ptrauth_objc_method_list_pointer \ |
| 293 | __ptrauth(ptrauth_key_method_list_pointer, 1, 0xC310) |
| 294 | #else |
| 295 | #define __ptrauth_objc_method_list_pointer |
| 296 | #endif |
| 297 | |
| 298 | #define __ptrauth_isa_discriminator 0x6AE1 |
| 299 | #define __ptrauth_super_discriminator 0xB5AB |
| 300 | #define __ptrauth_objc_isa_pointer \ |
| 301 | __ptrauth(ptrauth_key_objc_isa_pointer, 1, __ptrauth_isa_discriminator) |
| 302 | #if __has_feature(ptrauth_restricted_intptr_qualifier) |
| 303 | #define __ptrauth_objc_isa_uintptr \ |
| 304 | __ptrauth_restricted_intptr(ptrauth_key_objc_isa_pointer, 1, \ |
| 305 | __ptrauth_isa_discriminator) |
| 306 | #else |
| 307 | #define __ptrauth_objc_isa_uintptr \ |
| 308 | __ptrauth(ptrauth_key_objc_isa_pointer, 1, __ptrauth_isa_discriminator) |
| 309 | #endif |
| 310 | |
| 311 | #define __ptrauth_objc_super_pointer \ |
| 312 | __ptrauth(ptrauth_key_objc_super_pointer, 1, __ptrauth_super_discriminator) |
| 313 | |
| 314 | #define __ptrauth_objc_sel_discriminator 0x57c2 |
| 315 | #if __has_feature(ptrauth_objc_interface_sel) |
| 316 | #define __ptrauth_objc_sel \ |
| 317 | __ptrauth(ptrauth_key_objc_sel_pointer, 1, __ptrauth_objc_sel_discriminator) |
| 318 | #else |
| 319 | #define __ptrauth_objc_sel |
| 320 | #endif |
| 321 | |
| 322 | #define __ptrauth_objc_class_ro_discriminator 0x61f8 |
| 323 | #define __ptrauth_objc_class_ro \ |
| 324 | __ptrauth(ptrauth_key_objc_class_ro_pointer, 1, \ |
| 325 | __ptrauth_objc_class_ro_discriminator) |
| 326 | |
| 327 | #else |
| 328 | |
| 329 | #define ptrauth_strip(__value, __key) \ |
| 330 | ({ \ |
| 331 | (void)__key; \ |
| 332 | __value; \ |
| 333 | }) |
| 334 | |
| 335 | #define ptrauth_blend_discriminator(__pointer, __integer) \ |
| 336 | ({ \ |
| 337 | (void)__pointer; \ |
| 338 | (void)__integer; \ |
| 339 | ((ptrauth_extra_data_t)0); \ |
| 340 | }) |
| 341 | |
| 342 | #define ptrauth_sign_constant(__value, __key, __data) \ |
| 343 | ({ \ |
| 344 | (void)__key; \ |
| 345 | (void)__data; \ |
| 346 | __value; \ |
| 347 | }) |
| 348 | |
| 349 | #define ptrauth_sign_unauthenticated(__value, __key, __data) \ |
| 350 | ({ \ |
| 351 | (void)__key; \ |
| 352 | (void)__data; \ |
| 353 | __value; \ |
| 354 | }) |
| 355 | |
| 356 | #define ptrauth_auth_and_resign(__value, __old_key, __old_data, __new_key, \ |
| 357 | __new_data) \ |
| 358 | ({ \ |
| 359 | (void)__old_key; \ |
| 360 | (void)__old_data; \ |
| 361 | (void)__new_key; \ |
| 362 | (void)__new_data; \ |
| 363 | __value; \ |
| 364 | }) |
| 365 | |
| 366 | #define ptrauth_auth_function(__value, __old_key, __old_data) \ |
| 367 | ({ \ |
| 368 | (void)__old_key; \ |
| 369 | (void)__old_data; \ |
| 370 | __value; \ |
| 371 | }) |
| 372 | |
| 373 | #define ptrauth_auth_data(__value, __old_key, __old_data) \ |
| 374 | ({ \ |
| 375 | (void)__old_key; \ |
| 376 | (void)__old_data; \ |
| 377 | __value; \ |
| 378 | }) |
| 379 | |
| 380 | #define ptrauth_string_discriminator(__string) \ |
| 381 | ({ \ |
| 382 | (void)__string; \ |
| 383 | ((ptrauth_extra_data_t)0); \ |
| 384 | }) |
| 385 | |
| 386 | #define ptrauth_type_discriminator(__type) ((ptrauth_extra_data_t)0) |
| 387 | #define ptrauth_function_pointer_type_discriminator(__type) \ |
| 388 | ((ptrauth_extra_data_t)0) |
| 389 | |
| 390 | #define ptrauth_sign_generic_data(__value, __data) \ |
| 391 | ({ \ |
| 392 | (void)__value; \ |
| 393 | (void)__data; \ |
| 394 | ((ptrauth_generic_signature_t)0); \ |
| 395 | }) |
| 396 | |
| 397 | |
| 398 | #define ptrauth_cxx_vtable_pointer(key, address_discrimination, \ |
| 399 | extra_discrimination...) |
| 400 | |
| 401 | #define __ptrauth_objc_isa_pointer |
| 402 | #define __ptrauth_objc_isa_uintptr |
| 403 | #define __ptrauth_objc_super_pointer |
| 404 | |
| 405 | #endif /* __has_feature(ptrauth_intrinsics) || defined(__PTRAUTH__) */ |
| 406 | |
| 407 | #endif /* __PTRAUTH_H */ |