1 /**
2 * \file common.h
3 *
4 * \brief Utility macros for internal use in the library
5 */
6 /*
7 * Copyright The Mbed TLS Contributors
8 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
9 */
10
11 #ifndef MBEDTLS_LIBRARY_COMMON_H
12 #define MBEDTLS_LIBRARY_COMMON_H
13
14 #include "mbedtls/build_info.h"
15 #include "alignment.h"
16
17 #include <assert.h>
18 #include <stddef.h>
19 #include <stdint.h>
20 #include <stddef.h>
21
22 #if defined(__ARM_NEON)
23 #include <arm_neon.h>
24 #endif /* __ARM_NEON */
25
26 /** Helper to define a function as static except when building invasive tests.
27 *
28 * If a function is only used inside its own source file and should be
29 * declared `static` to allow the compiler to optimize for code size,
30 * but that function has unit tests, define it with
31 * ```
32 * MBEDTLS_STATIC_TESTABLE int mbedtls_foo(...) { ... }
33 * ```
34 * and declare it in a header in the `library/` directory with
35 * ```
36 * #if defined(MBEDTLS_TEST_HOOKS)
37 * int mbedtls_foo(...);
38 * #endif
39 * ```
40 */
41 #if defined(MBEDTLS_TEST_HOOKS)
42 #define MBEDTLS_STATIC_TESTABLE
43 #else
44 #define MBEDTLS_STATIC_TESTABLE static
45 #endif
46
47 #if defined(MBEDTLS_TEST_HOOKS)
48 extern void (*mbedtls_test_hook_test_fail)(const char *test, int line, const char *file);
49 #define MBEDTLS_TEST_HOOK_TEST_ASSERT(TEST) \
50 do { \
51 if ((!(TEST)) && ((*mbedtls_test_hook_test_fail) != NULL)) \
52 { \
53 (*mbedtls_test_hook_test_fail)( #TEST, __LINE__, __FILE__); \
54 } \
55 } while (0)
56 #else
57 #define MBEDTLS_TEST_HOOK_TEST_ASSERT(TEST)
58 #endif /* defined(MBEDTLS_TEST_HOOKS) */
59
60 /** \def ARRAY_LENGTH
61 * Return the number of elements of a static or stack array.
62 *
63 * \param array A value of array (not pointer) type.
64 *
65 * \return The number of elements of the array.
66 */
67 /* A correct implementation of ARRAY_LENGTH, but which silently gives
68 * a nonsensical result if called with a pointer rather than an array. */
69 #define ARRAY_LENGTH_UNSAFE(array) \
70 (sizeof(array) / sizeof(*(array)))
71
72 #if defined(__GNUC__)
73 /* Test if arg and &(arg)[0] have the same type. This is true if arg is
74 * an array but not if it's a pointer. */
75 #define IS_ARRAY_NOT_POINTER(arg) \
76 (!__builtin_types_compatible_p(__typeof__(arg), \
77 __typeof__(&(arg)[0])))
78 /* A compile-time constant with the value 0. If `const_expr` is not a
79 * compile-time constant with a nonzero value, cause a compile-time error. */
80 #define STATIC_ASSERT_EXPR(const_expr) \
81 (0 && sizeof(struct { unsigned int STATIC_ASSERT : 1 - 2 * !(const_expr); }))
82
83 /* Return the scalar value `value` (possibly promoted). This is a compile-time
84 * constant if `value` is. `condition` must be a compile-time constant.
85 * If `condition` is false, arrange to cause a compile-time error. */
86 #define STATIC_ASSERT_THEN_RETURN(condition, value) \
87 (STATIC_ASSERT_EXPR(condition) ? 0 : (value))
88
89 #define ARRAY_LENGTH(array) \
90 (STATIC_ASSERT_THEN_RETURN(IS_ARRAY_NOT_POINTER(array), \
91 ARRAY_LENGTH_UNSAFE(array)))
92
93 #else
94 /* If we aren't sure the compiler supports our non-standard tricks,
95 * fall back to the unsafe implementation. */
96 #define ARRAY_LENGTH(array) ARRAY_LENGTH_UNSAFE(array)
97 #endif
98 /** Allow library to access its structs' private members.
99 *
100 * Although structs defined in header files are publicly available,
101 * their members are private and should not be accessed by the user.
102 */
103 #define MBEDTLS_ALLOW_PRIVATE_ACCESS
104
105 /**
106 * \brief Securely zeroize a buffer then free it.
107 *
108 * Similar to making consecutive calls to
109 * \c mbedtls_platform_zeroize() and \c mbedtls_free(), but has
110 * code size savings, and potential for optimisation in the future.
111 *
112 * Guaranteed to be a no-op if \p buf is \c NULL and \p len is 0.
113 *
114 * \param buf Buffer to be zeroized then freed.
115 * \param len Length of the buffer in bytes
116 */
117 void mbedtls_zeroize_and_free(void *buf, size_t len);
118
119 /** Return an offset into a buffer.
120 *
121 * This is just the addition of an offset to a pointer, except that this
122 * function also accepts an offset of 0 into a buffer whose pointer is null.
123 * (`p + n` has undefined behavior when `p` is null, even when `n == 0`.
124 * A null pointer is a valid buffer pointer when the size is 0, for example
125 * as the result of `malloc(0)` on some platforms.)
126 *
127 * \param p Pointer to a buffer of at least n bytes.
128 * This may be \p NULL if \p n is zero.
129 * \param n An offset in bytes.
130 * \return Pointer to offset \p n in the buffer \p p.
131 * Note that this is only a valid pointer if the size of the
132 * buffer is at least \p n + 1.
133 */
mbedtls_buffer_offset(unsigned char * p,size_t n)134 static inline unsigned char *mbedtls_buffer_offset(
135 unsigned char *p, size_t n)
136 {
137 return p == NULL ? NULL : p + n;
138 }
139
140 /** Return an offset into a read-only buffer.
141 *
142 * Similar to mbedtls_buffer_offset(), but for const pointers.
143 *
144 * \param p Pointer to a buffer of at least n bytes.
145 * This may be \p NULL if \p n is zero.
146 * \param n An offset in bytes.
147 * \return Pointer to offset \p n in the buffer \p p.
148 * Note that this is only a valid pointer if the size of the
149 * buffer is at least \p n + 1.
150 */
mbedtls_buffer_offset_const(const unsigned char * p,size_t n)151 static inline const unsigned char *mbedtls_buffer_offset_const(
152 const unsigned char *p, size_t n)
153 {
154 return p == NULL ? NULL : p + n;
155 }
156
157 /**
158 * Perform a fast block XOR operation, such that
159 * r[i] = a[i] ^ b[i] where 0 <= i < n
160 *
161 * \param r Pointer to result (buffer of at least \p n bytes). \p r
162 * may be equal to either \p a or \p b, but behaviour when
163 * it overlaps in other ways is undefined.
164 * \param a Pointer to input (buffer of at least \p n bytes)
165 * \param b Pointer to input (buffer of at least \p n bytes)
166 * \param n Number of bytes to process.
167 */
mbedtls_xor(unsigned char * r,const unsigned char * a,const unsigned char * b,size_t n)168 inline void mbedtls_xor(unsigned char *r, const unsigned char *a, const unsigned char *b, size_t n)
169 {
170 size_t i = 0;
171 #if defined(MBEDTLS_EFFICIENT_UNALIGNED_ACCESS)
172 #if defined(__ARM_NEON)
173 for (; (i + 16) <= n; i += 16) {
174 uint8x16_t v1 = vld1q_u8(a + i);
175 uint8x16_t v2 = vld1q_u8(b + i);
176 uint8x16_t x = veorq_u8(v1, v2);
177 vst1q_u8(r + i, x);
178 }
179 #elif defined(__amd64__) || defined(__x86_64__) || defined(__aarch64__)
180 /* This codepath probably only makes sense on architectures with 64-bit registers */
181 for (; (i + 8) <= n; i += 8) {
182 uint64_t x = mbedtls_get_unaligned_uint64(a + i) ^ mbedtls_get_unaligned_uint64(b + i);
183 mbedtls_put_unaligned_uint64(r + i, x);
184 }
185 #else
186 for (; (i + 4) <= n; i += 4) {
187 uint32_t x = mbedtls_get_unaligned_uint32(a + i) ^ mbedtls_get_unaligned_uint32(b + i);
188 mbedtls_put_unaligned_uint32(r + i, x);
189 }
190 #endif
191 #endif
192 for (; i < n; i++) {
193 r[i] = a[i] ^ b[i];
194 }
195 }
196
197 /**
198 * Perform a fast block XOR operation, such that
199 * r[i] = a[i] ^ b[i] where 0 <= i < n
200 *
201 * In some situations, this can perform better than mbedtls_xor (e.g., it's about 5%
202 * better in AES-CBC).
203 *
204 * \param r Pointer to result (buffer of at least \p n bytes). \p r
205 * may be equal to either \p a or \p b, but behaviour when
206 * it overlaps in other ways is undefined.
207 * \param a Pointer to input (buffer of at least \p n bytes)
208 * \param b Pointer to input (buffer of at least \p n bytes)
209 * \param n Number of bytes to process.
210 */
mbedtls_xor_no_simd(unsigned char * r,const unsigned char * a,const unsigned char * b,size_t n)211 static inline void mbedtls_xor_no_simd(unsigned char *r,
212 const unsigned char *a,
213 const unsigned char *b,
214 size_t n)
215 {
216 size_t i = 0;
217 #if defined(MBEDTLS_EFFICIENT_UNALIGNED_ACCESS)
218 #if defined(__amd64__) || defined(__x86_64__) || defined(__aarch64__)
219 /* This codepath probably only makes sense on architectures with 64-bit registers */
220 for (; (i + 8) <= n; i += 8) {
221 uint64_t x = mbedtls_get_unaligned_uint64(a + i) ^ mbedtls_get_unaligned_uint64(b + i);
222 mbedtls_put_unaligned_uint64(r + i, x);
223 }
224 #else
225 for (; (i + 4) <= n; i += 4) {
226 uint32_t x = mbedtls_get_unaligned_uint32(a + i) ^ mbedtls_get_unaligned_uint32(b + i);
227 mbedtls_put_unaligned_uint32(r + i, x);
228 }
229 #endif
230 #endif
231 for (; i < n; i++) {
232 r[i] = a[i] ^ b[i];
233 }
234 }
235
236 /* Fix MSVC C99 compatible issue
237 * MSVC support __func__ from visual studio 2015( 1900 )
238 * Use MSVC predefine macro to avoid name check fail.
239 */
240 #if (defined(_MSC_VER) && (_MSC_VER <= 1900))
241 #define /*no-check-names*/ __func__ __FUNCTION__
242 #endif
243
244 /* Define `asm` for compilers which don't define it. */
245 /* *INDENT-OFF* */
246 #ifndef asm
247 #if defined(__IAR_SYSTEMS_ICC__)
248 #define asm __asm
249 #else
250 #define asm __asm__
251 #endif
252 #endif
253 /* *INDENT-ON* */
254
255 /*
256 * Define the constraint used for read-only pointer operands to aarch64 asm.
257 *
258 * This is normally the usual "r", but for aarch64_32 (aka ILP32,
259 * as found in watchos), "p" is required to avoid warnings from clang.
260 *
261 * Note that clang does not recognise '+p' or '=p', and armclang
262 * does not recognise 'p' at all. Therefore, to update a pointer from
263 * aarch64 assembly, it is necessary to use something like:
264 *
265 * uintptr_t uptr = (uintptr_t) ptr;
266 * asm( "ldr x4, [%x0], #8" ... : "+r" (uptr) : : )
267 * ptr = (void*) uptr;
268 *
269 * Note that the "x" in "%x0" is neccessary; writing "%0" will cause warnings.
270 */
271 #if defined(__aarch64__) && defined(MBEDTLS_HAVE_ASM)
272 #if UINTPTR_MAX == 0xfffffffful
273 /* ILP32: Specify the pointer operand slightly differently, as per #7787. */
274 #define MBEDTLS_ASM_AARCH64_PTR_CONSTRAINT "p"
275 #elif UINTPTR_MAX == 0xfffffffffffffffful
276 /* Normal case (64-bit pointers): use "r" as the constraint for pointer operands to asm */
277 #define MBEDTLS_ASM_AARCH64_PTR_CONSTRAINT "r"
278 #else
279 #error "Unrecognised pointer size for aarch64"
280 #endif
281 #endif
282
283 /* Always provide a static assert macro, so it can be used unconditionally.
284 * It will expand to nothing on some systems.
285 * Can be used outside functions (but don't add a trailing ';' in that case:
286 * the semicolon is included here to avoid triggering -Wextra-semi when
287 * MBEDTLS_STATIC_ASSERT() expands to nothing).
288 * Can't use the C11-style `defined(static_assert)` on FreeBSD, since it
289 * defines static_assert even with -std=c99, but then complains about it.
290 */
291 #if defined(static_assert) && !defined(__FreeBSD__)
292 #define MBEDTLS_STATIC_ASSERT(expr, msg) static_assert(expr, msg);
293 #else
294 #define MBEDTLS_STATIC_ASSERT(expr, msg)
295 #endif
296
297 /* Define compiler branch hints */
298 #if defined(__has_builtin)
299 #if __has_builtin(__builtin_expect)
300 #define MBEDTLS_LIKELY(x) __builtin_expect(!!(x), 1)
301 #define MBEDTLS_UNLIKELY(x) __builtin_expect(!!(x), 0)
302 #endif
303 #endif
304 #if !defined(MBEDTLS_LIKELY)
305 #define MBEDTLS_LIKELY(x) x
306 #define MBEDTLS_UNLIKELY(x) x
307 #endif
308
309 #if defined(__GNUC__) && !defined(__ARMCC_VERSION) && !defined(__clang__) \
310 && !defined(__llvm__) && !defined(__INTEL_COMPILER)
311 /* Defined if the compiler really is gcc and not clang, etc */
312 #define MBEDTLS_COMPILER_IS_GCC
313 #endif
314
315 /* For gcc -Os, override with -O2 for a given function.
316 *
317 * This will not affect behaviour for other optimisation settings, e.g. -O0.
318 */
319 #if defined(MBEDTLS_COMPILER_IS_GCC) && defined(__OPTIMIZE_SIZE__)
320 #define MBEDTLS_OPTIMIZE_FOR_PERFORMANCE __attribute__((optimize("-O2")))
321 #else
322 #define MBEDTLS_OPTIMIZE_FOR_PERFORMANCE
323 #endif
324
325 #endif /* MBEDTLS_LIBRARY_COMMON_H */
326