xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/AArch64/AArch64PointerAuth.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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