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