xref: /freebsd/contrib/llvm-project/llvm/lib/Target/AArch64/AArch64PointerAuth.h (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
1*5f757f3fSDimitry Andric //===-- AArch64PointerAuth.h -- Harden code using PAuth ---------*- C++ -*-===//
2*5f757f3fSDimitry Andric //
3*5f757f3fSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*5f757f3fSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*5f757f3fSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*5f757f3fSDimitry Andric //
7*5f757f3fSDimitry Andric //===----------------------------------------------------------------------===//
8*5f757f3fSDimitry Andric 
9*5f757f3fSDimitry Andric #ifndef LLVM_LIB_TARGET_AARCH64_AARCH64POINTERAUTH_H
10*5f757f3fSDimitry Andric #define LLVM_LIB_TARGET_AARCH64_AARCH64POINTERAUTH_H
11*5f757f3fSDimitry Andric 
12*5f757f3fSDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h"
13*5f757f3fSDimitry Andric #include "llvm/CodeGen/Register.h"
14*5f757f3fSDimitry Andric 
15*5f757f3fSDimitry Andric namespace llvm {
16*5f757f3fSDimitry Andric namespace AArch64PAuth {
17*5f757f3fSDimitry Andric 
18*5f757f3fSDimitry Andric /// Variants of check performed on an authenticated pointer.
19*5f757f3fSDimitry Andric ///
20*5f757f3fSDimitry Andric /// In cases such as authenticating the LR value when performing a tail call
21*5f757f3fSDimitry Andric /// or when re-signing a signed pointer with a different signing schema,
22*5f757f3fSDimitry Andric /// a failed authentication may not generate an exception on its own and may
23*5f757f3fSDimitry Andric /// create an authentication or signing oracle if not checked explicitly.
24*5f757f3fSDimitry Andric ///
25*5f757f3fSDimitry Andric /// A number of check methods modify control flow in a similar way by
26*5f757f3fSDimitry Andric /// rewriting the code
27*5f757f3fSDimitry Andric ///
28*5f757f3fSDimitry Andric /// ```
29*5f757f3fSDimitry Andric ///   <authenticate LR>
30*5f757f3fSDimitry Andric ///   <more instructions>
31*5f757f3fSDimitry Andric /// ```
32*5f757f3fSDimitry Andric ///
33*5f757f3fSDimitry Andric /// as follows:
34*5f757f3fSDimitry Andric ///
35*5f757f3fSDimitry Andric /// ```
36*5f757f3fSDimitry Andric ///   <authenticate LR>
37*5f757f3fSDimitry Andric ///   <method-specific checker>
38*5f757f3fSDimitry Andric /// ret_block:
39*5f757f3fSDimitry Andric ///   <more instructions>
40*5f757f3fSDimitry Andric ///   ...
41*5f757f3fSDimitry Andric ///
42*5f757f3fSDimitry Andric /// break_block:
43*5f757f3fSDimitry Andric ///   brk <code>
44*5f757f3fSDimitry Andric /// ```
45*5f757f3fSDimitry Andric enum class AuthCheckMethod {
46*5f757f3fSDimitry Andric   /// Do not check the value at all
47*5f757f3fSDimitry Andric   None,
48*5f757f3fSDimitry Andric   /// Perform a load to a temporary register
49*5f757f3fSDimitry Andric   DummyLoad,
50*5f757f3fSDimitry Andric   /// Check by comparing bits 62 and 61 of the authenticated address.
51*5f757f3fSDimitry Andric   ///
52*5f757f3fSDimitry Andric   /// This method modifies control flow and inserts the following checker:
53*5f757f3fSDimitry Andric   ///
54*5f757f3fSDimitry Andric   /// ```
55*5f757f3fSDimitry Andric   ///   eor Xtmp, Xn, Xn, lsl #1
56*5f757f3fSDimitry Andric   ///   tbnz Xtmp, #62, break_block
57*5f757f3fSDimitry Andric   /// ```
58*5f757f3fSDimitry Andric   HighBitsNoTBI,
59*5f757f3fSDimitry Andric   /// Check by comparing the authenticated value with an XPAC-ed one without
60*5f757f3fSDimitry Andric   /// using PAuth instructions not encoded as HINT. Can only be applied to LR.
61*5f757f3fSDimitry Andric   ///
62*5f757f3fSDimitry Andric   /// This method modifies control flow and inserts the following checker:
63*5f757f3fSDimitry Andric   ///
64*5f757f3fSDimitry Andric   /// ```
65*5f757f3fSDimitry Andric   ///   mov Xtmp, LR
66*5f757f3fSDimitry Andric   ///   xpaclri           ; encoded as "hint #7"
67*5f757f3fSDimitry Andric   ///   ; Note: at this point, the LR register contains the address as if
68*5f757f3fSDimitry Andric   ///   ; the authentication succeeded and the temporary register contains the
69*5f757f3fSDimitry Andric   ///   ; *real* result of authentication.
70*5f757f3fSDimitry Andric   ///   cmp Xtmp, LR
71*5f757f3fSDimitry Andric   ///   b.ne break_block
72*5f757f3fSDimitry Andric   /// ```
73*5f757f3fSDimitry Andric   XPACHint,
74*5f757f3fSDimitry Andric };
75*5f757f3fSDimitry Andric 
76*5f757f3fSDimitry Andric #define AUTH_CHECK_METHOD_CL_VALUES_COMMON                                     \
77*5f757f3fSDimitry Andric       clEnumValN(AArch64PAuth::AuthCheckMethod::None, "none",                  \
78*5f757f3fSDimitry Andric                  "Do not check authenticated address"),                        \
79*5f757f3fSDimitry Andric       clEnumValN(AArch64PAuth::AuthCheckMethod::DummyLoad, "load",             \
80*5f757f3fSDimitry Andric                  "Perform dummy load from authenticated address"),             \
81*5f757f3fSDimitry Andric       clEnumValN(AArch64PAuth::AuthCheckMethod::HighBitsNoTBI,                 \
82*5f757f3fSDimitry Andric                  "high-bits-notbi",                                            \
83*5f757f3fSDimitry Andric                  "Compare bits 62 and 61 of address (TBI should be disabled)")
84*5f757f3fSDimitry Andric 
85*5f757f3fSDimitry Andric #define AUTH_CHECK_METHOD_CL_VALUES_LR                                         \
86*5f757f3fSDimitry Andric       AUTH_CHECK_METHOD_CL_VALUES_COMMON,                                      \
87*5f757f3fSDimitry Andric       clEnumValN(AArch64PAuth::AuthCheckMethod::XPACHint, "xpac-hint",         \
88*5f757f3fSDimitry Andric                  "Compare with the result of XPACLRI")
89*5f757f3fSDimitry Andric 
90*5f757f3fSDimitry Andric /// Explicitly checks that pointer authentication succeeded.
91*5f757f3fSDimitry Andric ///
92*5f757f3fSDimitry Andric /// Assuming AuthenticatedReg contains a value returned by one of the AUT*
93*5f757f3fSDimitry Andric /// instructions, check the value using Method just before the instruction
94*5f757f3fSDimitry Andric /// pointed to by MBBI. If the check succeeds, execution proceeds to the
95*5f757f3fSDimitry Andric /// instruction pointed to by MBBI, otherwise a CPU exception is generated.
96*5f757f3fSDimitry Andric ///
97*5f757f3fSDimitry Andric /// Some of the methods may need to know if the pointer was authenticated
98*5f757f3fSDimitry Andric /// using an I-key or D-key and which register can be used as temporary.
99*5f757f3fSDimitry Andric /// If an explicit BRK instruction is used to generate an exception, BrkImm
100*5f757f3fSDimitry Andric /// specifies its immediate operand.
101*5f757f3fSDimitry Andric ///
102*5f757f3fSDimitry Andric /// \returns The machine basic block containing the code that is executed
103*5f757f3fSDimitry Andric ///          after the check succeeds.
104*5f757f3fSDimitry Andric MachineBasicBlock &checkAuthenticatedRegister(MachineBasicBlock::iterator MBBI,
105*5f757f3fSDimitry Andric                                               AuthCheckMethod Method,
106*5f757f3fSDimitry Andric                                               Register AuthenticatedReg,
107*5f757f3fSDimitry Andric                                               Register TmpReg, bool UseIKey,
108*5f757f3fSDimitry Andric                                               unsigned BrkImm);
109*5f757f3fSDimitry Andric 
110*5f757f3fSDimitry Andric /// Returns the number of bytes added by checkAuthenticatedRegister.
111*5f757f3fSDimitry Andric unsigned getCheckerSizeInBytes(AuthCheckMethod Method);
112*5f757f3fSDimitry Andric 
113*5f757f3fSDimitry Andric } // end namespace AArch64PAuth
114*5f757f3fSDimitry Andric } // end namespace llvm
115*5f757f3fSDimitry Andric 
116*5f757f3fSDimitry Andric #endif
117