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