xref: /freebsd/contrib/llvm-project/clang/lib/Headers/ptrauth.h (revision 36b606ae6aa4b24061096ba18582e0a08ccd5dba)
10fca6ea1SDimitry Andric /*===---- ptrauth.h - Pointer authentication -------------------------------===
20fca6ea1SDimitry Andric  *
30fca6ea1SDimitry Andric  * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40fca6ea1SDimitry Andric  * See https://llvm.org/LICENSE.txt for license information.
50fca6ea1SDimitry Andric  * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60fca6ea1SDimitry Andric  *
70fca6ea1SDimitry Andric  *===-----------------------------------------------------------------------===
80fca6ea1SDimitry Andric  */
90fca6ea1SDimitry Andric 
100fca6ea1SDimitry Andric #ifndef __PTRAUTH_H
110fca6ea1SDimitry Andric #define __PTRAUTH_H
120fca6ea1SDimitry Andric 
130fca6ea1SDimitry Andric typedef enum {
140fca6ea1SDimitry Andric   ptrauth_key_asia = 0,
150fca6ea1SDimitry Andric   ptrauth_key_asib = 1,
160fca6ea1SDimitry Andric   ptrauth_key_asda = 2,
170fca6ea1SDimitry Andric   ptrauth_key_asdb = 3,
180fca6ea1SDimitry Andric 
190fca6ea1SDimitry Andric   /* A process-independent key which can be used to sign code pointers. */
200fca6ea1SDimitry Andric   ptrauth_key_process_independent_code = ptrauth_key_asia,
210fca6ea1SDimitry Andric 
220fca6ea1SDimitry Andric   /* A process-specific key which can be used to sign code pointers. */
230fca6ea1SDimitry Andric   ptrauth_key_process_dependent_code = ptrauth_key_asib,
240fca6ea1SDimitry Andric 
250fca6ea1SDimitry Andric   /* A process-independent key which can be used to sign data pointers. */
260fca6ea1SDimitry Andric   ptrauth_key_process_independent_data = ptrauth_key_asda,
270fca6ea1SDimitry Andric 
280fca6ea1SDimitry Andric   /* A process-specific key which can be used to sign data pointers. */
290fca6ea1SDimitry Andric   ptrauth_key_process_dependent_data = ptrauth_key_asdb,
300fca6ea1SDimitry Andric 
310fca6ea1SDimitry Andric   /* The key used to sign C function pointers.
320fca6ea1SDimitry Andric      The extra data is always 0. */
330fca6ea1SDimitry Andric   ptrauth_key_function_pointer = ptrauth_key_process_independent_code,
340fca6ea1SDimitry Andric 
350fca6ea1SDimitry Andric   /* The key used to sign C++ v-table pointers.
360fca6ea1SDimitry Andric      The extra data is always 0. */
370fca6ea1SDimitry Andric   ptrauth_key_cxx_vtable_pointer = ptrauth_key_process_independent_data,
380fca6ea1SDimitry Andric 
390fca6ea1SDimitry Andric   /* Other pointers signed under the ABI use private ABI rules. */
400fca6ea1SDimitry Andric 
410fca6ea1SDimitry Andric } ptrauth_key;
420fca6ea1SDimitry Andric 
430fca6ea1SDimitry Andric /* An integer type of the appropriate size for a discriminator argument. */
440fca6ea1SDimitry Andric typedef __UINTPTR_TYPE__ ptrauth_extra_data_t;
450fca6ea1SDimitry Andric 
460fca6ea1SDimitry Andric /* An integer type of the appropriate size for a generic signature. */
470fca6ea1SDimitry Andric typedef __UINTPTR_TYPE__ ptrauth_generic_signature_t;
480fca6ea1SDimitry Andric 
490fca6ea1SDimitry Andric /* A signed pointer value embeds the original pointer together with
500fca6ea1SDimitry Andric    a signature that attests to the validity of that pointer.  Because
510fca6ea1SDimitry Andric    this signature must use only "spare" bits of the pointer, a
520fca6ea1SDimitry Andric    signature's validity is probabilistic in practice: it is unlikely
530fca6ea1SDimitry Andric    but still plausible that an invalidly-derived signature will
540fca6ea1SDimitry Andric    somehow equal the correct signature and therefore successfully
550fca6ea1SDimitry Andric    authenticate.  Nonetheless, this scheme provides a strong degree
560fca6ea1SDimitry Andric    of protection against certain kinds of attacks. */
570fca6ea1SDimitry Andric 
580fca6ea1SDimitry Andric /* Authenticating a pointer that was not signed with the given key
590fca6ea1SDimitry Andric    and extra-data value will (likely) fail by trapping. */
600fca6ea1SDimitry Andric 
610fca6ea1SDimitry Andric /* The null function pointer is always the all-zero bit pattern.
620fca6ea1SDimitry Andric    Signing an all-zero bit pattern will embed a (likely) non-zero
630fca6ea1SDimitry Andric    signature in the result, and so the result will not seem to be
640fca6ea1SDimitry Andric    a null function pointer.  Authenticating this value will yield
650fca6ea1SDimitry Andric    a null function pointer back.  However, authenticating an
660fca6ea1SDimitry Andric    all-zero bit pattern will probably fail, because the
670fca6ea1SDimitry Andric    authentication will expect a (likely) non-zero signature to
680fca6ea1SDimitry Andric    embedded in the value.
690fca6ea1SDimitry Andric 
700fca6ea1SDimitry Andric    Because of this, if a pointer may validly be null, you should
710fca6ea1SDimitry Andric    check for null before attempting to authenticate it with one
720fca6ea1SDimitry Andric    of these intrinsics.  This is not necessary when using the
730fca6ea1SDimitry Andric    __ptrauth qualifier; the compiler will perform this check
740fca6ea1SDimitry Andric    automatically. */
750fca6ea1SDimitry Andric 
760fca6ea1SDimitry Andric #if __has_feature(ptrauth_intrinsics)
770fca6ea1SDimitry Andric 
780fca6ea1SDimitry Andric /* Strip the signature from a value without authenticating it.
790fca6ea1SDimitry Andric 
800fca6ea1SDimitry Andric    If the value is a function pointer, the result will not be a
810fca6ea1SDimitry Andric    legal function pointer because of the missing signature, and
820fca6ea1SDimitry Andric    attempting to call it will result in an authentication failure.
830fca6ea1SDimitry Andric 
840fca6ea1SDimitry Andric    The value must be an expression of pointer type.
850fca6ea1SDimitry Andric    The key must be a constant expression of type ptrauth_key.
860fca6ea1SDimitry Andric    The result will have the same type as the original value. */
870fca6ea1SDimitry Andric #define ptrauth_strip(__value, __key) __builtin_ptrauth_strip(__value, __key)
880fca6ea1SDimitry Andric 
890fca6ea1SDimitry Andric /* Blend a constant discriminator into the given pointer-like value
900fca6ea1SDimitry Andric    to form a new discriminator.  Not all bits of the inputs are
910fca6ea1SDimitry Andric    guaranteed to contribute to the result.
920fca6ea1SDimitry Andric 
930fca6ea1SDimitry Andric    On arm64e, the integer must fall within the range of a uint16_t;
940fca6ea1SDimitry Andric    other bits may be ignored.
950fca6ea1SDimitry Andric 
960fca6ea1SDimitry Andric    For the purposes of ptrauth_sign_constant, the result of calling
970fca6ea1SDimitry Andric    this function is considered a constant expression if the arguments
980fca6ea1SDimitry Andric    are constant.  Some restrictions may be imposed on the pointer.
990fca6ea1SDimitry Andric 
1000fca6ea1SDimitry Andric    The first argument must be an expression of pointer type.
1010fca6ea1SDimitry Andric    The second argument must be an expression of integer type.
1020fca6ea1SDimitry Andric    The result will have type uintptr_t. */
1030fca6ea1SDimitry Andric #define ptrauth_blend_discriminator(__pointer, __integer)                      \
1040fca6ea1SDimitry Andric   __builtin_ptrauth_blend_discriminator(__pointer, __integer)
1050fca6ea1SDimitry Andric 
1060fca6ea1SDimitry Andric /* Return a signed pointer for a constant address in a manner which guarantees
1070fca6ea1SDimitry Andric    a non-attackable sequence.
1080fca6ea1SDimitry Andric 
1090fca6ea1SDimitry Andric    The value must be a constant expression of pointer type which evaluates to
1100fca6ea1SDimitry Andric    a non-null pointer.
1110fca6ea1SDimitry Andric    The key must be a constant expression of type ptrauth_key.
1120fca6ea1SDimitry Andric    The extra data must be a constant expression of pointer or integer type;
1130fca6ea1SDimitry Andric    if an integer, it will be coerced to ptrauth_extra_data_t.
1140fca6ea1SDimitry Andric    The result will have the same type as the original value.
1150fca6ea1SDimitry Andric 
1160fca6ea1SDimitry Andric    This can be used in constant expressions.  */
1170fca6ea1SDimitry Andric #define ptrauth_sign_constant(__value, __key, __data)                          \
1180fca6ea1SDimitry Andric   __builtin_ptrauth_sign_constant(__value, __key, __data)
1190fca6ea1SDimitry Andric 
1200fca6ea1SDimitry Andric /* Add a signature to the given pointer value using a specific key,
1210fca6ea1SDimitry Andric    using the given extra data as a salt to the signing process.
1220fca6ea1SDimitry Andric 
1230fca6ea1SDimitry Andric    This operation does not authenticate the original value and is
1240fca6ea1SDimitry Andric    therefore potentially insecure if an attacker could possibly
1250fca6ea1SDimitry Andric    control that value.
1260fca6ea1SDimitry Andric 
1270fca6ea1SDimitry Andric    The value must be an expression of pointer type.
1280fca6ea1SDimitry Andric    The key must be a constant expression of type ptrauth_key.
1290fca6ea1SDimitry Andric    The extra data must be an expression of pointer or integer type;
1300fca6ea1SDimitry Andric    if an integer, it will be coerced to ptrauth_extra_data_t.
1310fca6ea1SDimitry Andric    The result will have the same type as the original value. */
1320fca6ea1SDimitry Andric #define ptrauth_sign_unauthenticated(__value, __key, __data)                   \
1330fca6ea1SDimitry Andric   __builtin_ptrauth_sign_unauthenticated(__value, __key, __data)
1340fca6ea1SDimitry Andric 
1350fca6ea1SDimitry Andric /* Authenticate a pointer using one scheme and resign it using another.
1360fca6ea1SDimitry Andric 
1370fca6ea1SDimitry Andric    If the result is subsequently authenticated using the new scheme, that
1380fca6ea1SDimitry Andric    authentication is guaranteed to fail if and only if the initial
1390fca6ea1SDimitry Andric    authentication failed.
1400fca6ea1SDimitry Andric 
1410fca6ea1SDimitry Andric    The value must be an expression of pointer type.
1420fca6ea1SDimitry Andric    The key must be a constant expression of type ptrauth_key.
1430fca6ea1SDimitry Andric    The extra data must be an expression of pointer or integer type;
1440fca6ea1SDimitry Andric    if an integer, it will be coerced to ptrauth_extra_data_t.
1450fca6ea1SDimitry Andric    The result will have the same type as the original value.
1460fca6ea1SDimitry Andric 
1470fca6ea1SDimitry Andric    This operation is guaranteed to not leave the intermediate value
1480fca6ea1SDimitry Andric    available for attack before it is re-signed.
1490fca6ea1SDimitry Andric 
1500fca6ea1SDimitry Andric    Do not pass a null pointer to this function. A null pointer
1510fca6ea1SDimitry Andric    will not successfully authenticate.
1520fca6ea1SDimitry Andric 
1530fca6ea1SDimitry Andric    This operation traps if the authentication fails. */
1540fca6ea1SDimitry Andric #define ptrauth_auth_and_resign(__value, __old_key, __old_data, __new_key,     \
1550fca6ea1SDimitry Andric                                 __new_data)                                    \
1560fca6ea1SDimitry Andric   __builtin_ptrauth_auth_and_resign(__value, __old_key, __old_data, __new_key, \
1570fca6ea1SDimitry Andric                                     __new_data)
1580fca6ea1SDimitry Andric 
1590fca6ea1SDimitry Andric /* Authenticate a pointer using one scheme and resign it as a C
1600fca6ea1SDimitry Andric    function pointer.
1610fca6ea1SDimitry Andric 
1620fca6ea1SDimitry Andric    If the result is subsequently authenticated using the new scheme, that
1630fca6ea1SDimitry Andric    authentication is guaranteed to fail if and only if the initial
1640fca6ea1SDimitry Andric    authentication failed.
1650fca6ea1SDimitry Andric 
1660fca6ea1SDimitry Andric    The value must be an expression of function pointer type.
1670fca6ea1SDimitry Andric    The key must be a constant expression of type ptrauth_key.
1680fca6ea1SDimitry Andric    The extra data must be an expression of pointer or integer type;
1690fca6ea1SDimitry Andric    if an integer, it will be coerced to ptrauth_extra_data_t.
1700fca6ea1SDimitry Andric    The result will have the same type as the original value.
1710fca6ea1SDimitry Andric 
1720fca6ea1SDimitry Andric    This operation is guaranteed to not leave the intermediate value
1730fca6ea1SDimitry Andric    available for attack before it is re-signed. Additionally, if this
1740fca6ea1SDimitry Andric    expression is used syntactically as the function expression in a
1750fca6ea1SDimitry Andric    call, only a single authentication will be performed. */
1760fca6ea1SDimitry Andric #define ptrauth_auth_function(__value, __old_key, __old_data)                  \
1770fca6ea1SDimitry Andric   ptrauth_auth_and_resign(__value, __old_key, __old_data,                      \
1780fca6ea1SDimitry Andric                           ptrauth_key_function_pointer, 0)
1790fca6ea1SDimitry Andric 
1800fca6ea1SDimitry Andric /* Authenticate a data pointer.
1810fca6ea1SDimitry Andric 
1820fca6ea1SDimitry Andric    The value must be an expression of non-function pointer type.
1830fca6ea1SDimitry Andric    The key must be a constant expression of type ptrauth_key.
1840fca6ea1SDimitry Andric    The extra data must be an expression of pointer or integer type;
1850fca6ea1SDimitry Andric    if an integer, it will be coerced to ptrauth_extra_data_t.
1860fca6ea1SDimitry Andric    The result will have the same type as the original value.
1870fca6ea1SDimitry Andric 
1880fca6ea1SDimitry Andric    This operation traps if the authentication fails. */
1890fca6ea1SDimitry Andric #define ptrauth_auth_data(__value, __old_key, __old_data)                      \
1900fca6ea1SDimitry Andric   __builtin_ptrauth_auth(__value, __old_key, __old_data)
1910fca6ea1SDimitry Andric 
1920fca6ea1SDimitry Andric /* Compute a constant discriminator from the given string.
1930fca6ea1SDimitry Andric 
1940fca6ea1SDimitry Andric    The argument must be a string literal of char character type.  The result
1950fca6ea1SDimitry Andric    has type ptrauth_extra_data_t.
1960fca6ea1SDimitry Andric 
1970fca6ea1SDimitry Andric    The result value is never zero and always within range for both the
1980fca6ea1SDimitry Andric    __ptrauth qualifier and ptrauth_blend_discriminator.
1990fca6ea1SDimitry Andric 
2000fca6ea1SDimitry Andric    This can be used in constant expressions.
2010fca6ea1SDimitry Andric */
2020fca6ea1SDimitry Andric #define ptrauth_string_discriminator(__string)                                 \
2030fca6ea1SDimitry Andric   __builtin_ptrauth_string_discriminator(__string)
2040fca6ea1SDimitry Andric 
205*36b606aeSDimitry Andric /* Compute a constant discriminator from the given type.
206*36b606aeSDimitry Andric 
207*36b606aeSDimitry Andric    The result can be used as the second argument to
208*36b606aeSDimitry Andric    ptrauth_blend_discriminator or the third argument to the
209*36b606aeSDimitry Andric    __ptrauth qualifier.  It has type size_t.
210*36b606aeSDimitry Andric 
211*36b606aeSDimitry Andric    If the type is a C++ member function pointer type, the result is
212*36b606aeSDimitry Andric    the discriminator used to signed member function pointers of that
213*36b606aeSDimitry Andric    type.  If the type is a function, function pointer, or function
214*36b606aeSDimitry Andric    reference type, the result is the discriminator used to sign
215*36b606aeSDimitry Andric    functions of that type.  It is ill-formed to use this macro with any
216*36b606aeSDimitry Andric    other type.
217*36b606aeSDimitry Andric 
218*36b606aeSDimitry Andric    A call to this function is an integer constant expression. */
219*36b606aeSDimitry Andric #define ptrauth_type_discriminator(__type)                                     \
220*36b606aeSDimitry Andric   __builtin_ptrauth_type_discriminator(__type)
221*36b606aeSDimitry Andric 
2220fca6ea1SDimitry Andric /* Compute a signature for the given pair of pointer-sized values.
2230fca6ea1SDimitry Andric    The order of the arguments is significant.
2240fca6ea1SDimitry Andric 
2250fca6ea1SDimitry Andric    Like a pointer signature, the resulting signature depends on
2260fca6ea1SDimitry Andric    private key data and therefore should not be reliably reproducible
2270fca6ea1SDimitry Andric    by attackers.  That means that this can be used to validate the
2280fca6ea1SDimitry Andric    integrity of arbitrary data by storing a signature for that data
2290fca6ea1SDimitry Andric    alongside it, then checking that the signature is still valid later.
2300fca6ea1SDimitry Andric    Data which exceeds two pointers in size can be signed by either
2310fca6ea1SDimitry Andric    computing a tree of generic signatures or just signing an ordinary
2320fca6ea1SDimitry Andric    cryptographic hash of the data.
2330fca6ea1SDimitry Andric 
2340fca6ea1SDimitry Andric    The result has type ptrauth_generic_signature_t.  However, it may
2350fca6ea1SDimitry Andric    not have as many bits of entropy as that type's width would suggest;
2360fca6ea1SDimitry Andric    some implementations are known to compute a compressed signature as
2370fca6ea1SDimitry Andric    if the arguments were a pointer and a discriminator.
2380fca6ea1SDimitry Andric 
2390fca6ea1SDimitry Andric    The arguments must be either pointers or integers; if integers, they
2400fca6ea1SDimitry Andric    will be coerce to uintptr_t. */
2410fca6ea1SDimitry Andric #define ptrauth_sign_generic_data(__value, __data)                             \
2420fca6ea1SDimitry Andric   __builtin_ptrauth_sign_generic_data(__value, __data)
2430fca6ea1SDimitry Andric 
2440fca6ea1SDimitry Andric /* C++ vtable pointer signing class attribute */
2450fca6ea1SDimitry Andric #define ptrauth_cxx_vtable_pointer(key, address_discrimination,                \
2460fca6ea1SDimitry Andric                                    extra_discrimination...)                    \
2470fca6ea1SDimitry Andric   [[clang::ptrauth_vtable_pointer(key, address_discrimination,                 \
2480fca6ea1SDimitry Andric                                   extra_discrimination)]]
2490fca6ea1SDimitry Andric 
2500fca6ea1SDimitry Andric #else
2510fca6ea1SDimitry Andric 
2520fca6ea1SDimitry Andric #define ptrauth_strip(__value, __key)                                          \
2530fca6ea1SDimitry Andric   ({                                                                           \
2540fca6ea1SDimitry Andric     (void)__key;                                                               \
2550fca6ea1SDimitry Andric     __value;                                                                   \
2560fca6ea1SDimitry Andric   })
2570fca6ea1SDimitry Andric 
2580fca6ea1SDimitry Andric #define ptrauth_blend_discriminator(__pointer, __integer)                      \
2590fca6ea1SDimitry Andric   ({                                                                           \
2600fca6ea1SDimitry Andric     (void)__pointer;                                                           \
2610fca6ea1SDimitry Andric     (void)__integer;                                                           \
2620fca6ea1SDimitry Andric     ((ptrauth_extra_data_t)0);                                                 \
2630fca6ea1SDimitry Andric   })
2640fca6ea1SDimitry Andric 
2650fca6ea1SDimitry Andric #define ptrauth_sign_constant(__value, __key, __data)                          \
2660fca6ea1SDimitry Andric   ({                                                                           \
2670fca6ea1SDimitry Andric     (void)__key;                                                               \
2680fca6ea1SDimitry Andric     (void)__data;                                                              \
2690fca6ea1SDimitry Andric     __value;                                                                   \
2700fca6ea1SDimitry Andric   })
2710fca6ea1SDimitry Andric 
2720fca6ea1SDimitry Andric #define ptrauth_sign_unauthenticated(__value, __key, __data)                   \
2730fca6ea1SDimitry Andric   ({                                                                           \
2740fca6ea1SDimitry Andric     (void)__key;                                                               \
2750fca6ea1SDimitry Andric     (void)__data;                                                              \
2760fca6ea1SDimitry Andric     __value;                                                                   \
2770fca6ea1SDimitry Andric   })
2780fca6ea1SDimitry Andric 
2790fca6ea1SDimitry Andric #define ptrauth_auth_and_resign(__value, __old_key, __old_data, __new_key,     \
2800fca6ea1SDimitry Andric                                 __new_data)                                    \
2810fca6ea1SDimitry Andric   ({                                                                           \
2820fca6ea1SDimitry Andric     (void)__old_key;                                                           \
2830fca6ea1SDimitry Andric     (void)__old_data;                                                          \
2840fca6ea1SDimitry Andric     (void)__new_key;                                                           \
2850fca6ea1SDimitry Andric     (void)__new_data;                                                          \
2860fca6ea1SDimitry Andric     __value;                                                                   \
2870fca6ea1SDimitry Andric   })
2880fca6ea1SDimitry Andric 
2890fca6ea1SDimitry Andric #define ptrauth_auth_function(__value, __old_key, __old_data)                  \
2900fca6ea1SDimitry Andric   ({                                                                           \
2910fca6ea1SDimitry Andric     (void)__old_key;                                                           \
2920fca6ea1SDimitry Andric     (void)__old_data;                                                          \
2930fca6ea1SDimitry Andric     __value;                                                                   \
2940fca6ea1SDimitry Andric   })
2950fca6ea1SDimitry Andric 
2960fca6ea1SDimitry Andric #define ptrauth_auth_data(__value, __old_key, __old_data)                      \
2970fca6ea1SDimitry Andric   ({                                                                           \
2980fca6ea1SDimitry Andric     (void)__old_key;                                                           \
2990fca6ea1SDimitry Andric     (void)__old_data;                                                          \
3000fca6ea1SDimitry Andric     __value;                                                                   \
3010fca6ea1SDimitry Andric   })
3020fca6ea1SDimitry Andric 
3030fca6ea1SDimitry Andric #define ptrauth_string_discriminator(__string)                                 \
3040fca6ea1SDimitry Andric   ({                                                                           \
3050fca6ea1SDimitry Andric     (void)__string;                                                            \
3060fca6ea1SDimitry Andric     ((ptrauth_extra_data_t)0);                                                 \
3070fca6ea1SDimitry Andric   })
3080fca6ea1SDimitry Andric 
309*36b606aeSDimitry Andric #define ptrauth_type_discriminator(__type) ((ptrauth_extra_data_t)0)
310*36b606aeSDimitry Andric 
3110fca6ea1SDimitry Andric #define ptrauth_sign_generic_data(__value, __data)                             \
3120fca6ea1SDimitry Andric   ({                                                                           \
3130fca6ea1SDimitry Andric     (void)__value;                                                             \
3140fca6ea1SDimitry Andric     (void)__data;                                                              \
3150fca6ea1SDimitry Andric     ((ptrauth_generic_signature_t)0);                                          \
3160fca6ea1SDimitry Andric   })
3170fca6ea1SDimitry Andric 
3180fca6ea1SDimitry Andric 
3190fca6ea1SDimitry Andric #define ptrauth_cxx_vtable_pointer(key, address_discrimination,                \
3200fca6ea1SDimitry Andric                                    extra_discrimination...)
3210fca6ea1SDimitry Andric 
3220fca6ea1SDimitry Andric #endif /* __has_feature(ptrauth_intrinsics) */
3230fca6ea1SDimitry Andric 
3240fca6ea1SDimitry Andric #endif /* __PTRAUTH_H */
325