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