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 <ring-core/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 #include <ring_core_generated/prefix_symbols_asm.h> 43 44 #if defined(__ELF__) 45 // Every ELF object file, even empty ones, should disable executable stacks. See 46 // https://www.airs.com/blog/archives/518. 47 .pushsection .note.GNU-stack, "", %progbits 48 .popsection 49 #endif 50 51 #if defined(__CET__) && defined(OPENSSL_X86_64) 52 // Clang and GCC define __CET__ and provide <cet.h> when they support Intel's 53 // Indirect Branch Tracking. 54 // https://lpc.events/event/7/contributions/729/attachments/496/903/CET-LPC-2020.pdf 55 // 56 // cet.h defines _CET_ENDBR which is used to mark function entry points for IBT. 57 // and adds the assembly marker. The value of _CET_ENDBR is made dependant on if 58 // '-fcf-protection' is passed to the compiler. _CET_ENDBR is only required when 59 // the function is the target of an indirect jump, but BoringSSL chooses to mark 60 // all assembly entry points because it is easier, and allows BoringSSL's ABI 61 // tester to call the assembly entry points via an indirect jump. 62 #include <cet.h> 63 #else 64 #define _CET_ENDBR 65 #endif 66 67 #if defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64) 68 69 // We require the ARM assembler provide |__ARM_ARCH| from Arm C Language 70 // Extensions (ACLE). This is supported in GCC 4.8+ and Clang 3.2+. MSVC does 71 // not implement ACLE, but we require Clang's assembler on Windows. 72 #if !defined(__ARM_ARCH) 73 #error "ARM assembler must define __ARM_ARCH" 74 #endif 75 76 // __ARM_ARCH__ is used by OpenSSL assembly to determine the minimum target ARM 77 // version. 78 // 79 // TODO(davidben): Switch the assembly to use |__ARM_ARCH| directly. 80 #define __ARM_ARCH__ __ARM_ARCH 81 82 // Even when building for 32-bit ARM, support for aarch64 crypto instructions 83 // will be included. 84 #define __ARM_MAX_ARCH__ 8 85 86 // Support macros for 87 // - Armv8.3-A Pointer Authentication and 88 // - Armv8.5-A Branch Target Identification 89 // features which require emitting a .note.gnu.property section with the 90 // appropriate architecture-dependent feature bits set. 91 // 92 // |AARCH64_SIGN_LINK_REGISTER| and |AARCH64_VALIDATE_LINK_REGISTER| expand to 93 // PACIxSP and AUTIxSP, respectively. |AARCH64_SIGN_LINK_REGISTER| should be 94 // used immediately before saving the LR register (x30) to the stack. 95 // |AARCH64_VALIDATE_LINK_REGISTER| should be used immediately after restoring 96 // it. Note |AARCH64_SIGN_LINK_REGISTER|'s modifications to LR must be undone 97 // with |AARCH64_VALIDATE_LINK_REGISTER| before RET. The SP register must also 98 // have the same value at the two points. For example: 99 // 100 // .global f 101 // f: 102 // AARCH64_SIGN_LINK_REGISTER 103 // stp x29, x30, [sp, #-96]! 104 // mov x29, sp 105 // ... 106 // ldp x29, x30, [sp], #96 107 // AARCH64_VALIDATE_LINK_REGISTER 108 // ret 109 // 110 // |AARCH64_VALID_CALL_TARGET| expands to BTI 'c'. Either it, or 111 // |AARCH64_SIGN_LINK_REGISTER|, must be used at every point that may be an 112 // indirect call target. In particular, all symbols exported from a file must 113 // begin with one of these macros. For example, a leaf function that does not 114 // save LR can instead use |AARCH64_VALID_CALL_TARGET|: 115 // 116 // .globl return_zero 117 // return_zero: 118 // AARCH64_VALID_CALL_TARGET 119 // mov x0, #0 120 // ret 121 // 122 // A non-leaf function which does not immediately save LR may need both macros 123 // because |AARCH64_SIGN_LINK_REGISTER| appears late. For example, the function 124 // may jump to an alternate implementation before setting up the stack: 125 // 126 // .globl with_early_jump 127 // with_early_jump: 128 // AARCH64_VALID_CALL_TARGET 129 // cmp x0, #128 130 // b.lt .Lwith_early_jump_128 131 // AARCH64_SIGN_LINK_REGISTER 132 // stp x29, x30, [sp, #-96]! 133 // mov x29, sp 134 // ... 135 // ldp x29, x30, [sp], #96 136 // AARCH64_VALIDATE_LINK_REGISTER 137 // ret 138 // 139 // .Lwith_early_jump_128: 140 // ... 141 // ret 142 // 143 // These annotations are only required with indirect calls. Private symbols that 144 // are only the target of direct calls do not require annotations. Also note 145 // that |AARCH64_VALID_CALL_TARGET| is only valid for indirect calls (BLR), not 146 // indirect jumps (BR). Indirect jumps in assembly are currently not supported 147 // and would require a macro for BTI 'j'. 148 // 149 // Although not necessary, it is safe to use these macros in 32-bit ARM 150 // assembly. This may be used to simplify dual 32-bit and 64-bit files. 151 // 152 // References: 153 // - "ELF for the Arm® 64-bit Architecture" 154 // https://github.com/ARM-software/abi-aa/blob/master/aaelf64/aaelf64.rst 155 // - "Providing protection for complex software" 156 // https://developer.arm.com/architectures/learn-the-architecture/providing-protection-for-complex-software 157 158 #if defined(__ARM_FEATURE_BTI_DEFAULT) && __ARM_FEATURE_BTI_DEFAULT == 1 159 #define GNU_PROPERTY_AARCH64_BTI (1 << 0) // Has Branch Target Identification 160 #define AARCH64_VALID_CALL_TARGET hint #34 // BTI 'c' 161 #else 162 #define GNU_PROPERTY_AARCH64_BTI 0 // No Branch Target Identification 163 #define AARCH64_VALID_CALL_TARGET 164 #endif 165 166 #if defined(__ARM_FEATURE_PAC_DEFAULT) && \ 167 (__ARM_FEATURE_PAC_DEFAULT & 1) == 1 // Signed with A-key 168 #define GNU_PROPERTY_AARCH64_POINTER_AUTH \ 169 (1 << 1) // Has Pointer Authentication 170 #define AARCH64_SIGN_LINK_REGISTER hint #25 // PACIASP 171 #define AARCH64_VALIDATE_LINK_REGISTER hint #29 // AUTIASP 172 #elif defined(__ARM_FEATURE_PAC_DEFAULT) && \ 173 (__ARM_FEATURE_PAC_DEFAULT & 2) == 2 // Signed with B-key 174 #define GNU_PROPERTY_AARCH64_POINTER_AUTH \ 175 (1 << 1) // Has Pointer Authentication 176 #define AARCH64_SIGN_LINK_REGISTER hint #27 // PACIBSP 177 #define AARCH64_VALIDATE_LINK_REGISTER hint #31 // AUTIBSP 178 #else 179 #define GNU_PROPERTY_AARCH64_POINTER_AUTH 0 // No Pointer Authentication 180 #if GNU_PROPERTY_AARCH64_BTI != 0 181 #define AARCH64_SIGN_LINK_REGISTER AARCH64_VALID_CALL_TARGET 182 #else 183 #define AARCH64_SIGN_LINK_REGISTER 184 #endif 185 #define AARCH64_VALIDATE_LINK_REGISTER 186 #endif 187 188 #if GNU_PROPERTY_AARCH64_POINTER_AUTH != 0 || GNU_PROPERTY_AARCH64_BTI != 0 189 .pushsection .note.gnu.property, "a"; 190 .balign 8; 191 .long 4; 192 .long 0x10; 193 .long 0x5; 194 .asciz "GNU"; 195 .long 0xc0000000; /* GNU_PROPERTY_AARCH64_FEATURE_1_AND */ 196 .long 4; 197 .long (GNU_PROPERTY_AARCH64_POINTER_AUTH | GNU_PROPERTY_AARCH64_BTI); 198 .long 0; 199 .popsection; 200 #endif 201 #endif // ARM || AARCH64 202 203 #endif // __ASSEMBLER__ 204 205 #endif // OPENSSL_HEADER_ASM_BASE_H 206