1 /* Copyright (c) 2023, Google Inc. 2 * 3 * Permission to use, copy, modify, and/or distribute this software for any 4 * purpose with or without fee is hereby granted, provided that the above 5 * copyright notice and this permission notice appear in all copies. 6 * 7 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 10 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 12 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 13 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ 14 15 #ifndef OPENSSL_HEADER_ASM_BASE_H 16 #define OPENSSL_HEADER_ASM_BASE_H 17 18 #include <openssl/target.h> 19 20 21 // This header contains symbols and common sections used by assembly files. It 22 // is included as a public header to simplify the build, but is not intended for 23 // external use. 24 // 25 // Every assembly file must include this header. Some linker features require 26 // all object files to be tagged with some section metadata. This header file, 27 // when included in assembly, adds that metadata. It also makes defines like 28 // |OPENSSL_X86_64| available and includes the prefixing macros. 29 // 30 // Including this header in an assembly file imples: 31 // 32 // - The file does not require an executable stack. 33 // 34 // - The file, on aarch64, uses the macros defined below to be compatible with 35 // BTI and PAC. 36 // 37 // - The file, on x86_64, requires the program to be compatible with Intel IBT 38 // and SHSTK 39 40 #if defined(__ASSEMBLER__) 41 42 #if defined(BORINGSSL_PREFIX) 43 #include <boringssl_prefix_symbols_asm.h> 44 #endif 45 46 #if defined(__ELF__) 47 // Every ELF object file, even empty ones, should disable executable stacks. See 48 // https://www.airs.com/blog/archives/518. 49 .pushsection .note.GNU-stack, "", %progbits 50 .popsection 51 #endif 52 53 #if defined(__CET__) && defined(OPENSSL_X86_64) 54 // Clang and GCC define __CET__ and provide <cet.h> when they support Intel's 55 // Indirect Branch Tracking. 56 // https://lpc.events/event/7/contributions/729/attachments/496/903/CET-LPC-2020.pdf 57 // 58 // cet.h defines _CET_ENDBR which is used to mark function entry points for IBT. 59 // and adds the assembly marker. The value of _CET_ENDBR is made dependant on if 60 // '-fcf-protection' is passed to the compiler. _CET_ENDBR is only required when 61 // the function is the target of an indirect jump, but BoringSSL chooses to mark 62 // all assembly entry points because it is easier, and allows BoringSSL's ABI 63 // tester to call the assembly entry points via an indirect jump. 64 #include <cet.h> 65 #else 66 #define _CET_ENDBR 67 #endif 68 69 #if defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64) 70 71 // We require the ARM assembler provide |__ARM_ARCH| from Arm C Language 72 // Extensions (ACLE). This is supported in GCC 4.8+ and Clang 3.2+. MSVC does 73 // not implement ACLE, but we require Clang's assembler on Windows. 74 #if !defined(__ARM_ARCH) 75 #error "ARM assembler must define __ARM_ARCH" 76 #endif 77 78 // Even when building for 32-bit ARM, support for aarch64 crypto instructions 79 // will be included. 80 // 81 // TODO(davidben): Remove this and the corresponding ifdefs? This is only 82 // defined because some OpenSSL assembly files would allow disabling the NEON 83 // code entirely. I think we'd prefer to do that by lifting the dispatch to C 84 // anyway. 85 #define __ARM_MAX_ARCH__ 8 86 87 // Support macros for 88 // - Armv8.3-A Pointer Authentication and 89 // - Armv8.5-A Branch Target Identification 90 // features which require emitting a .note.gnu.property section with the 91 // appropriate architecture-dependent feature bits set. 92 // 93 // |AARCH64_SIGN_LINK_REGISTER| and |AARCH64_VALIDATE_LINK_REGISTER| expand to 94 // PACIxSP and AUTIxSP, respectively. |AARCH64_SIGN_LINK_REGISTER| should be 95 // used immediately before saving the LR register (x30) to the stack. 96 // |AARCH64_VALIDATE_LINK_REGISTER| should be used immediately after restoring 97 // it. Note |AARCH64_SIGN_LINK_REGISTER|'s modifications to LR must be undone 98 // with |AARCH64_VALIDATE_LINK_REGISTER| before RET. The SP register must also 99 // have the same value at the two points. For example: 100 // 101 // .global f 102 // f: 103 // AARCH64_SIGN_LINK_REGISTER 104 // stp x29, x30, [sp, #-96]! 105 // mov x29, sp 106 // ... 107 // ldp x29, x30, [sp], #96 108 // AARCH64_VALIDATE_LINK_REGISTER 109 // ret 110 // 111 // |AARCH64_VALID_CALL_TARGET| expands to BTI 'c'. Either it, or 112 // |AARCH64_SIGN_LINK_REGISTER|, must be used at every point that may be an 113 // indirect call target. In particular, all symbols exported from a file must 114 // begin with one of these macros. For example, a leaf function that does not 115 // save LR can instead use |AARCH64_VALID_CALL_TARGET|: 116 // 117 // .globl return_zero 118 // return_zero: 119 // AARCH64_VALID_CALL_TARGET 120 // mov x0, #0 121 // ret 122 // 123 // A non-leaf function which does not immediately save LR may need both macros 124 // because |AARCH64_SIGN_LINK_REGISTER| appears late. For example, the function 125 // may jump to an alternate implementation before setting up the stack: 126 // 127 // .globl with_early_jump 128 // with_early_jump: 129 // AARCH64_VALID_CALL_TARGET 130 // cmp x0, #128 131 // b.lt .Lwith_early_jump_128 132 // AARCH64_SIGN_LINK_REGISTER 133 // stp x29, x30, [sp, #-96]! 134 // mov x29, sp 135 // ... 136 // ldp x29, x30, [sp], #96 137 // AARCH64_VALIDATE_LINK_REGISTER 138 // ret 139 // 140 // .Lwith_early_jump_128: 141 // ... 142 // ret 143 // 144 // These annotations are only required with indirect calls. Private symbols that 145 // are only the target of direct calls do not require annotations. Also note 146 // that |AARCH64_VALID_CALL_TARGET| is only valid for indirect calls (BLR), not 147 // indirect jumps (BR). Indirect jumps in assembly are currently not supported 148 // and would require a macro for BTI 'j'. 149 // 150 // Although not necessary, it is safe to use these macros in 32-bit ARM 151 // assembly. This may be used to simplify dual 32-bit and 64-bit files. 152 // 153 // References: 154 // - "ELF for the Arm® 64-bit Architecture" 155 // https://github.com/ARM-software/abi-aa/blob/master/aaelf64/aaelf64.rst 156 // - "Providing protection for complex software" 157 // https://developer.arm.com/architectures/learn-the-architecture/providing-protection-for-complex-software 158 159 #if defined(__ARM_FEATURE_BTI_DEFAULT) && __ARM_FEATURE_BTI_DEFAULT == 1 160 #define GNU_PROPERTY_AARCH64_BTI (1 << 0) // Has Branch Target Identification 161 #define AARCH64_VALID_CALL_TARGET hint #34 // BTI 'c' 162 #else 163 #define GNU_PROPERTY_AARCH64_BTI 0 // No Branch Target Identification 164 #define AARCH64_VALID_CALL_TARGET 165 #endif 166 167 #if defined(__ARM_FEATURE_PAC_DEFAULT) && \ 168 (__ARM_FEATURE_PAC_DEFAULT & 1) == 1 // Signed with A-key 169 #define GNU_PROPERTY_AARCH64_POINTER_AUTH \ 170 (1 << 1) // Has Pointer Authentication 171 #define AARCH64_SIGN_LINK_REGISTER hint #25 // PACIASP 172 #define AARCH64_VALIDATE_LINK_REGISTER hint #29 // AUTIASP 173 #elif defined(__ARM_FEATURE_PAC_DEFAULT) && \ 174 (__ARM_FEATURE_PAC_DEFAULT & 2) == 2 // Signed with B-key 175 #define GNU_PROPERTY_AARCH64_POINTER_AUTH \ 176 (1 << 1) // Has Pointer Authentication 177 #define AARCH64_SIGN_LINK_REGISTER hint #27 // PACIBSP 178 #define AARCH64_VALIDATE_LINK_REGISTER hint #31 // AUTIBSP 179 #else 180 #define GNU_PROPERTY_AARCH64_POINTER_AUTH 0 // No Pointer Authentication 181 #if GNU_PROPERTY_AARCH64_BTI != 0 182 #define AARCH64_SIGN_LINK_REGISTER AARCH64_VALID_CALL_TARGET 183 #else 184 #define AARCH64_SIGN_LINK_REGISTER 185 #endif 186 #define AARCH64_VALIDATE_LINK_REGISTER 187 #endif 188 189 #if GNU_PROPERTY_AARCH64_POINTER_AUTH != 0 || GNU_PROPERTY_AARCH64_BTI != 0 190 .pushsection .note.gnu.property, "a"; 191 .balign 8; 192 .long 4; 193 .long 0x10; 194 .long 0x5; 195 .asciz "GNU"; 196 .long 0xc0000000; /* GNU_PROPERTY_AARCH64_FEATURE_1_AND */ 197 .long 4; 198 .long (GNU_PROPERTY_AARCH64_POINTER_AUTH | GNU_PROPERTY_AARCH64_BTI); 199 .long 0; 200 .popsection; 201 #endif 202 #endif // ARM || AARCH64 203 204 #endif // __ASSEMBLER__ 205 206 #endif // OPENSSL_HEADER_ASM_BASE_H 207