xref: /freebsd/contrib/llvm-project/clang/lib/Headers/ptrauth.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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