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