15f757f3fSDimitry Andric //===-- AArch64PointerAuth.h -- Harden code using PAuth ---------*- C++ -*-===// 25f757f3fSDimitry Andric // 35f757f3fSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 45f757f3fSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 55f757f3fSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 65f757f3fSDimitry Andric // 75f757f3fSDimitry Andric //===----------------------------------------------------------------------===// 85f757f3fSDimitry Andric 95f757f3fSDimitry Andric #ifndef LLVM_LIB_TARGET_AARCH64_AARCH64POINTERAUTH_H 105f757f3fSDimitry Andric #define LLVM_LIB_TARGET_AARCH64_AARCH64POINTERAUTH_H 115f757f3fSDimitry Andric 125f757f3fSDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h" 135f757f3fSDimitry Andric #include "llvm/CodeGen/Register.h" 145f757f3fSDimitry Andric 155f757f3fSDimitry Andric namespace llvm { 165f757f3fSDimitry Andric namespace AArch64PAuth { 175f757f3fSDimitry Andric 185f757f3fSDimitry Andric /// Variants of check performed on an authenticated pointer. 195f757f3fSDimitry Andric /// 205f757f3fSDimitry Andric /// In cases such as authenticating the LR value when performing a tail call 215f757f3fSDimitry Andric /// or when re-signing a signed pointer with a different signing schema, 225f757f3fSDimitry Andric /// a failed authentication may not generate an exception on its own and may 235f757f3fSDimitry Andric /// create an authentication or signing oracle if not checked explicitly. 245f757f3fSDimitry Andric /// 255f757f3fSDimitry Andric /// A number of check methods modify control flow in a similar way by 265f757f3fSDimitry Andric /// rewriting the code 275f757f3fSDimitry Andric /// 285f757f3fSDimitry Andric /// ``` 295f757f3fSDimitry Andric /// <authenticate LR> 305f757f3fSDimitry Andric /// <more instructions> 315f757f3fSDimitry Andric /// ``` 325f757f3fSDimitry Andric /// 335f757f3fSDimitry Andric /// as follows: 345f757f3fSDimitry Andric /// 355f757f3fSDimitry Andric /// ``` 365f757f3fSDimitry Andric /// <authenticate LR> 375f757f3fSDimitry Andric /// <method-specific checker> 385f757f3fSDimitry Andric /// ret_block: 395f757f3fSDimitry Andric /// <more instructions> 405f757f3fSDimitry Andric /// ... 415f757f3fSDimitry Andric /// 425f757f3fSDimitry Andric /// break_block: 435f757f3fSDimitry Andric /// brk <code> 445f757f3fSDimitry Andric /// ``` 455f757f3fSDimitry Andric enum class AuthCheckMethod { 465f757f3fSDimitry Andric /// Do not check the value at all 475f757f3fSDimitry Andric None, 485f757f3fSDimitry Andric /// Perform a load to a temporary register 495f757f3fSDimitry Andric DummyLoad, 505f757f3fSDimitry Andric /// Check by comparing bits 62 and 61 of the authenticated address. 515f757f3fSDimitry Andric /// 525f757f3fSDimitry Andric /// This method modifies control flow and inserts the following checker: 535f757f3fSDimitry Andric /// 545f757f3fSDimitry Andric /// ``` 555f757f3fSDimitry Andric /// eor Xtmp, Xn, Xn, lsl #1 565f757f3fSDimitry Andric /// tbnz Xtmp, #62, break_block 575f757f3fSDimitry Andric /// ``` 585f757f3fSDimitry Andric HighBitsNoTBI, 595f757f3fSDimitry Andric /// Check by comparing the authenticated value with an XPAC-ed one without 605f757f3fSDimitry Andric /// using PAuth instructions not encoded as HINT. Can only be applied to LR. 615f757f3fSDimitry Andric /// 625f757f3fSDimitry Andric /// This method modifies control flow and inserts the following checker: 635f757f3fSDimitry Andric /// 645f757f3fSDimitry Andric /// ``` 655f757f3fSDimitry Andric /// mov Xtmp, LR 665f757f3fSDimitry Andric /// xpaclri ; encoded as "hint #7" 675f757f3fSDimitry Andric /// ; Note: at this point, the LR register contains the address as if 685f757f3fSDimitry Andric /// ; the authentication succeeded and the temporary register contains the 695f757f3fSDimitry Andric /// ; *real* result of authentication. 705f757f3fSDimitry Andric /// cmp Xtmp, LR 715f757f3fSDimitry Andric /// b.ne break_block 725f757f3fSDimitry Andric /// ``` 735f757f3fSDimitry Andric XPACHint, 745f757f3fSDimitry Andric }; 755f757f3fSDimitry Andric 765f757f3fSDimitry Andric #define AUTH_CHECK_METHOD_CL_VALUES_COMMON \ 775f757f3fSDimitry Andric clEnumValN(AArch64PAuth::AuthCheckMethod::None, "none", \ 785f757f3fSDimitry Andric "Do not check authenticated address"), \ 795f757f3fSDimitry Andric clEnumValN(AArch64PAuth::AuthCheckMethod::DummyLoad, "load", \ 805f757f3fSDimitry Andric "Perform dummy load from authenticated address"), \ 815f757f3fSDimitry Andric clEnumValN(AArch64PAuth::AuthCheckMethod::HighBitsNoTBI, \ 825f757f3fSDimitry Andric "high-bits-notbi", \ 835f757f3fSDimitry Andric "Compare bits 62 and 61 of address (TBI should be disabled)") 845f757f3fSDimitry Andric 855f757f3fSDimitry Andric #define AUTH_CHECK_METHOD_CL_VALUES_LR \ 865f757f3fSDimitry Andric AUTH_CHECK_METHOD_CL_VALUES_COMMON, \ 875f757f3fSDimitry Andric clEnumValN(AArch64PAuth::AuthCheckMethod::XPACHint, "xpac-hint", \ 885f757f3fSDimitry Andric "Compare with the result of XPACLRI") 895f757f3fSDimitry Andric 905f757f3fSDimitry Andric /// Explicitly checks that pointer authentication succeeded. 915f757f3fSDimitry Andric /// 925f757f3fSDimitry Andric /// Assuming AuthenticatedReg contains a value returned by one of the AUT* 935f757f3fSDimitry Andric /// instructions, check the value using Method just before the instruction 945f757f3fSDimitry Andric /// pointed to by MBBI. If the check succeeds, execution proceeds to the 955f757f3fSDimitry Andric /// instruction pointed to by MBBI, otherwise a CPU exception is generated. 965f757f3fSDimitry Andric /// 975f757f3fSDimitry Andric /// Some of the methods may need to know if the pointer was authenticated 985f757f3fSDimitry Andric /// using an I-key or D-key and which register can be used as temporary. 995f757f3fSDimitry Andric /// If an explicit BRK instruction is used to generate an exception, BrkImm 1005f757f3fSDimitry Andric /// specifies its immediate operand. 101*0fca6ea1SDimitry Andric void checkAuthenticatedRegister(MachineBasicBlock::iterator MBBI, 1025f757f3fSDimitry Andric AuthCheckMethod Method, 103*0fca6ea1SDimitry Andric Register AuthenticatedReg, Register TmpReg, 104*0fca6ea1SDimitry Andric bool UseIKey, unsigned BrkImm); 1055f757f3fSDimitry Andric 1065f757f3fSDimitry Andric /// Returns the number of bytes added by checkAuthenticatedRegister. 1075f757f3fSDimitry Andric unsigned getCheckerSizeInBytes(AuthCheckMethod Method); 1085f757f3fSDimitry Andric 1095f757f3fSDimitry Andric } // end namespace AArch64PAuth 1105f757f3fSDimitry Andric } // end namespace llvm 1115f757f3fSDimitry Andric 1125f757f3fSDimitry Andric #endif 113