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