blob: e6b95dfa6bc611fbeaadba48036f86b4d767e611 [file] [log] [blame]
David Benjamina905bbb2023-06-12 18:11:13 -04001/* 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.
Bob Beck9fc1c332023-06-08 10:43:31 -060036//
Bob Beck51ed32f2023-07-10 14:15:42 -060037// - The file, on x86_64, requires the program to be compatible with Intel IBT
Bob Beck9fc1c332023-06-08 10:43:31 -060038// and SHSTK
David Benjamina905bbb2023-06-12 18:11:13 -040039
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
Bob Beck9fc1c332023-06-08 10:43:31 -060053#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
David Benjamina905bbb2023-06-12 18:11:13 -040069#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
David Benjamina905bbb2023-06-12 18:11:13 -040078// Even when building for 32-bit ARM, support for aarch64 crypto instructions
79// will be included.
David Benjamin8313e132023-10-11 12:51:36 -040080//
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.
David Benjamina905bbb2023-06-12 18:11:13 -040085#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