xref: /optee_os/lib/libmbedtls/mbedtls/library/common.h (revision b0563631928755fe864b97785160fb3088e9efdc)
17901324dSJerome Forissier /**
27901324dSJerome Forissier  * \file common.h
37901324dSJerome Forissier  *
47901324dSJerome Forissier  * \brief Utility macros for internal use in the library
57901324dSJerome Forissier  */
67901324dSJerome Forissier /*
77901324dSJerome Forissier  *  Copyright The Mbed TLS Contributors
8*b0563631STom Van Eyck  *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
97901324dSJerome Forissier  */
107901324dSJerome Forissier 
117901324dSJerome Forissier #ifndef MBEDTLS_LIBRARY_COMMON_H
127901324dSJerome Forissier #define MBEDTLS_LIBRARY_COMMON_H
137901324dSJerome Forissier 
1432b31808SJens Wiklander #include "mbedtls/build_info.h"
1532b31808SJens Wiklander #include "alignment.h"
167901324dSJerome Forissier 
1732b31808SJens Wiklander #include <assert.h>
1832b31808SJens Wiklander #include <stddef.h>
19039e02dfSJerome Forissier #include <stdint.h>
2032b31808SJens Wiklander #include <stddef.h>
21039e02dfSJerome Forissier 
22*b0563631STom Van Eyck #if defined(__ARM_NEON)
23*b0563631STom Van Eyck /*
24*b0563631STom Van Eyck  * Undefine and restore __section and __data from compiler.h to prevent
25*b0563631STom Van Eyck  * collision with arm_neon.h
26*b0563631STom Van Eyck  */
27*b0563631STom Van Eyck #pragma push_macro("__section")
28*b0563631STom Van Eyck #pragma push_macro("__data")
29*b0563631STom Van Eyck #undef __section
30*b0563631STom Van Eyck #undef __data
31*b0563631STom Van Eyck #include <arm_neon.h>
32*b0563631STom Van Eyck #pragma pop_macro("__data")
33*b0563631STom Van Eyck #pragma pop_macro("__section")
34*b0563631STom Van Eyck #define MBEDTLS_HAVE_NEON_INTRINSICS
35*b0563631STom Van Eyck #elif defined(MBEDTLS_PLATFORM_IS_WINDOWS_ON_ARM64)
36*b0563631STom Van Eyck #include <arm64_neon.h>
37*b0563631STom Van Eyck #define MBEDTLS_HAVE_NEON_INTRINSICS
38*b0563631STom Van Eyck #endif
39*b0563631STom Van Eyck 
407901324dSJerome Forissier /** Helper to define a function as static except when building invasive tests.
417901324dSJerome Forissier  *
427901324dSJerome Forissier  * If a function is only used inside its own source file and should be
437901324dSJerome Forissier  * declared `static` to allow the compiler to optimize for code size,
447901324dSJerome Forissier  * but that function has unit tests, define it with
457901324dSJerome Forissier  * ```
467901324dSJerome Forissier  * MBEDTLS_STATIC_TESTABLE int mbedtls_foo(...) { ... }
477901324dSJerome Forissier  * ```
487901324dSJerome Forissier  * and declare it in a header in the `library/` directory with
497901324dSJerome Forissier  * ```
507901324dSJerome Forissier  * #if defined(MBEDTLS_TEST_HOOKS)
517901324dSJerome Forissier  * int mbedtls_foo(...);
527901324dSJerome Forissier  * #endif
537901324dSJerome Forissier  * ```
547901324dSJerome Forissier  */
557901324dSJerome Forissier #if defined(MBEDTLS_TEST_HOOKS)
567901324dSJerome Forissier #define MBEDTLS_STATIC_TESTABLE
577901324dSJerome Forissier #else
587901324dSJerome Forissier #define MBEDTLS_STATIC_TESTABLE static
597901324dSJerome Forissier #endif
607901324dSJerome Forissier 
6132b31808SJens Wiklander #if defined(MBEDTLS_TEST_HOOKS)
6232b31808SJens Wiklander extern void (*mbedtls_test_hook_test_fail)(const char *test, int line, const char *file);
6332b31808SJens Wiklander #define MBEDTLS_TEST_HOOK_TEST_ASSERT(TEST) \
6432b31808SJens Wiklander     do { \
6532b31808SJens Wiklander         if ((!(TEST)) && ((*mbedtls_test_hook_test_fail) != NULL)) \
66039e02dfSJerome Forissier         { \
6732b31808SJens Wiklander             (*mbedtls_test_hook_test_fail)( #TEST, __LINE__, __FILE__); \
6832b31808SJens Wiklander         } \
6932b31808SJens Wiklander     } while (0)
7032b31808SJens Wiklander #else
7132b31808SJens Wiklander #define MBEDTLS_TEST_HOOK_TEST_ASSERT(TEST)
7232b31808SJens Wiklander #endif /* defined(MBEDTLS_TEST_HOOKS) */
7332b31808SJens Wiklander 
74*b0563631STom Van Eyck /** \def ARRAY_LENGTH
75*b0563631STom Van Eyck  * Return the number of elements of a static or stack array.
76*b0563631STom Van Eyck  *
77*b0563631STom Van Eyck  * \param array         A value of array (not pointer) type.
78*b0563631STom Van Eyck  *
79*b0563631STom Van Eyck  * \return The number of elements of the array.
80*b0563631STom Van Eyck  */
81*b0563631STom Van Eyck /* A correct implementation of ARRAY_LENGTH, but which silently gives
82*b0563631STom Van Eyck  * a nonsensical result if called with a pointer rather than an array. */
83*b0563631STom Van Eyck #define ARRAY_LENGTH_UNSAFE(array)            \
84*b0563631STom Van Eyck     (sizeof(array) / sizeof(*(array)))
85*b0563631STom Van Eyck 
86*b0563631STom Van Eyck #if defined(__GNUC__)
87*b0563631STom Van Eyck /* Test if arg and &(arg)[0] have the same type. This is true if arg is
88*b0563631STom Van Eyck  * an array but not if it's a pointer. */
89*b0563631STom Van Eyck #define IS_ARRAY_NOT_POINTER(arg)                                     \
90*b0563631STom Van Eyck     (!__builtin_types_compatible_p(__typeof__(arg),                \
91*b0563631STom Van Eyck                                    __typeof__(&(arg)[0])))
92*b0563631STom Van Eyck /* A compile-time constant with the value 0. If `const_expr` is not a
93*b0563631STom Van Eyck  * compile-time constant with a nonzero value, cause a compile-time error. */
94*b0563631STom Van Eyck #define STATIC_ASSERT_EXPR(const_expr)                                \
95*b0563631STom Van Eyck     (0 && sizeof(struct { unsigned int STATIC_ASSERT : 1 - 2 * !(const_expr); }))
96*b0563631STom Van Eyck 
97*b0563631STom Van Eyck /* Return the scalar value `value` (possibly promoted). This is a compile-time
98*b0563631STom Van Eyck  * constant if `value` is. `condition` must be a compile-time constant.
99*b0563631STom Van Eyck  * If `condition` is false, arrange to cause a compile-time error. */
100*b0563631STom Van Eyck #define STATIC_ASSERT_THEN_RETURN(condition, value)   \
101*b0563631STom Van Eyck     (STATIC_ASSERT_EXPR(condition) ? 0 : (value))
102*b0563631STom Van Eyck 
103*b0563631STom Van Eyck #define ARRAY_LENGTH(array)                                           \
104*b0563631STom Van Eyck     (STATIC_ASSERT_THEN_RETURN(IS_ARRAY_NOT_POINTER(array),         \
105*b0563631STom Van Eyck                                ARRAY_LENGTH_UNSAFE(array)))
106*b0563631STom Van Eyck 
107*b0563631STom Van Eyck #else
108*b0563631STom Van Eyck /* If we aren't sure the compiler supports our non-standard tricks,
109*b0563631STom Van Eyck  * fall back to the unsafe implementation. */
110*b0563631STom Van Eyck #define ARRAY_LENGTH(array) ARRAY_LENGTH_UNSAFE(array)
111*b0563631STom Van Eyck #endif
11232b31808SJens Wiklander /** Allow library to access its structs' private members.
11332b31808SJens Wiklander  *
11432b31808SJens Wiklander  * Although structs defined in header files are publicly available,
11532b31808SJens Wiklander  * their members are private and should not be accessed by the user.
11632b31808SJens Wiklander  */
11732b31808SJens Wiklander #define MBEDTLS_ALLOW_PRIVATE_ACCESS
11832b31808SJens Wiklander 
119*b0563631STom Van Eyck /**
120*b0563631STom Van Eyck  * \brief       Securely zeroize a buffer then free it.
121*b0563631STom Van Eyck  *
122*b0563631STom Van Eyck  *              Similar to making consecutive calls to
123*b0563631STom Van Eyck  *              \c mbedtls_platform_zeroize() and \c mbedtls_free(), but has
124*b0563631STom Van Eyck  *              code size savings, and potential for optimisation in the future.
125*b0563631STom Van Eyck  *
126*b0563631STom Van Eyck  *              Guaranteed to be a no-op if \p buf is \c NULL and \p len is 0.
127*b0563631STom Van Eyck  *
128*b0563631STom Van Eyck  * \param buf   Buffer to be zeroized then freed.
129*b0563631STom Van Eyck  * \param len   Length of the buffer in bytes
130*b0563631STom Van Eyck  */
131*b0563631STom Van Eyck void mbedtls_zeroize_and_free(void *buf, size_t len);
132*b0563631STom Van Eyck 
13332b31808SJens Wiklander /** Return an offset into a buffer.
13432b31808SJens Wiklander  *
13532b31808SJens Wiklander  * This is just the addition of an offset to a pointer, except that this
13632b31808SJens Wiklander  * function also accepts an offset of 0 into a buffer whose pointer is null.
13732b31808SJens Wiklander  * (`p + n` has undefined behavior when `p` is null, even when `n == 0`.
13832b31808SJens Wiklander  * A null pointer is a valid buffer pointer when the size is 0, for example
13932b31808SJens Wiklander  * as the result of `malloc(0)` on some platforms.)
14032b31808SJens Wiklander  *
14132b31808SJens Wiklander  * \param p     Pointer to a buffer of at least n bytes.
14232b31808SJens Wiklander  *              This may be \p NULL if \p n is zero.
14332b31808SJens Wiklander  * \param n     An offset in bytes.
14432b31808SJens Wiklander  * \return      Pointer to offset \p n in the buffer \p p.
14532b31808SJens Wiklander  *              Note that this is only a valid pointer if the size of the
14632b31808SJens Wiklander  *              buffer is at least \p n + 1.
14732b31808SJens Wiklander  */
14832b31808SJens Wiklander static inline unsigned char *mbedtls_buffer_offset(
14932b31808SJens Wiklander     unsigned char *p, size_t n)
15032b31808SJens Wiklander {
15132b31808SJens Wiklander     return p == NULL ? NULL : p + n;
15232b31808SJens Wiklander }
15332b31808SJens Wiklander 
15432b31808SJens Wiklander /** Return an offset into a read-only buffer.
15532b31808SJens Wiklander  *
15632b31808SJens Wiklander  * Similar to mbedtls_buffer_offset(), but for const pointers.
15732b31808SJens Wiklander  *
15832b31808SJens Wiklander  * \param p     Pointer to a buffer of at least n bytes.
15932b31808SJens Wiklander  *              This may be \p NULL if \p n is zero.
16032b31808SJens Wiklander  * \param n     An offset in bytes.
16132b31808SJens Wiklander  * \return      Pointer to offset \p n in the buffer \p p.
16232b31808SJens Wiklander  *              Note that this is only a valid pointer if the size of the
16332b31808SJens Wiklander  *              buffer is at least \p n + 1.
16432b31808SJens Wiklander  */
16532b31808SJens Wiklander static inline const unsigned char *mbedtls_buffer_offset_const(
16632b31808SJens Wiklander     const unsigned char *p, size_t n)
16732b31808SJens Wiklander {
16832b31808SJens Wiklander     return p == NULL ? NULL : p + n;
16932b31808SJens Wiklander }
17032b31808SJens Wiklander 
171*b0563631STom Van Eyck /* Always inline mbedtls_xor() for similar reasons as mbedtls_xor_no_simd(). */
172*b0563631STom Van Eyck #if defined(__IAR_SYSTEMS_ICC__)
173*b0563631STom Van Eyck #pragma inline = forced
174*b0563631STom Van Eyck #elif defined(__GNUC__)
175*b0563631STom Van Eyck __attribute__((always_inline))
176*b0563631STom Van Eyck #endif
17732b31808SJens Wiklander /**
17832b31808SJens Wiklander  * Perform a fast block XOR operation, such that
17932b31808SJens Wiklander  * r[i] = a[i] ^ b[i] where 0 <= i < n
18032b31808SJens Wiklander  *
18132b31808SJens Wiklander  * \param   r Pointer to result (buffer of at least \p n bytes). \p r
18232b31808SJens Wiklander  *            may be equal to either \p a or \p b, but behaviour when
18332b31808SJens Wiklander  *            it overlaps in other ways is undefined.
18432b31808SJens Wiklander  * \param   a Pointer to input (buffer of at least \p n bytes)
18532b31808SJens Wiklander  * \param   b Pointer to input (buffer of at least \p n bytes)
18632b31808SJens Wiklander  * \param   n Number of bytes to process.
187*b0563631STom Van Eyck  *
188*b0563631STom Van Eyck  * \note      Depending on the situation, it may be faster to use either mbedtls_xor() or
189*b0563631STom Van Eyck  *            mbedtls_xor_no_simd() (these are functionally equivalent).
190*b0563631STom Van Eyck  *            If the result is used immediately after the xor operation in non-SIMD code (e.g, in
191*b0563631STom Van Eyck  *            AES-CBC), there may be additional latency to transfer the data from SIMD to scalar
192*b0563631STom Van Eyck  *            registers, and in this case, mbedtls_xor_no_simd() may be faster. In other cases where
193*b0563631STom Van Eyck  *            the result is not used immediately (e.g., in AES-CTR), mbedtls_xor() may be faster.
194*b0563631STom Van Eyck  *            For targets without SIMD support, they will behave the same.
19532b31808SJens Wiklander  */
196*b0563631STom Van Eyck static inline void mbedtls_xor(unsigned char *r,
197*b0563631STom Van Eyck                                const unsigned char *a,
198*b0563631STom Van Eyck                                const unsigned char *b,
199*b0563631STom Van Eyck                                size_t n)
20032b31808SJens Wiklander {
20132b31808SJens Wiklander     size_t i = 0;
20232b31808SJens Wiklander #if defined(MBEDTLS_EFFICIENT_UNALIGNED_ACCESS)
203*b0563631STom Van Eyck #if defined(MBEDTLS_HAVE_NEON_INTRINSICS) && \
204*b0563631STom Van Eyck     (!(defined(MBEDTLS_COMPILER_IS_GCC) && MBEDTLS_GCC_VERSION < 70300))
205*b0563631STom Van Eyck     /* Old GCC versions generate a warning here, so disable the NEON path for these compilers */
206*b0563631STom Van Eyck     for (; (i + 16) <= n; i += 16) {
207*b0563631STom Van Eyck         uint8x16_t v1 = vld1q_u8(a + i);
208*b0563631STom Van Eyck         uint8x16_t v2 = vld1q_u8(b + i);
209*b0563631STom Van Eyck         uint8x16_t x = veorq_u8(v1, v2);
210*b0563631STom Van Eyck         vst1q_u8(r + i, x);
211*b0563631STom Van Eyck     }
212*b0563631STom Van Eyck #if defined(__IAR_SYSTEMS_ICC__)
213*b0563631STom Van Eyck     /* This if statement helps some compilers (e.g., IAR) optimise out the byte-by-byte tail case
214*b0563631STom Van Eyck      * where n is a constant multiple of 16.
215*b0563631STom Van Eyck      * For other compilers (e.g. recent gcc and clang) it makes no difference if n is a compile-time
216*b0563631STom Van Eyck      * constant, and is a very small perf regression if n is not a compile-time constant. */
217*b0563631STom Van Eyck     if (n % 16 == 0) {
218*b0563631STom Van Eyck         return;
219*b0563631STom Van Eyck     }
220*b0563631STom Van Eyck #endif
221*b0563631STom Van Eyck #elif defined(MBEDTLS_ARCH_IS_X64) || defined(MBEDTLS_ARCH_IS_ARM64)
222*b0563631STom Van Eyck     /* This codepath probably only makes sense on architectures with 64-bit registers */
223*b0563631STom Van Eyck     for (; (i + 8) <= n; i += 8) {
224*b0563631STom Van Eyck         uint64_t x = mbedtls_get_unaligned_uint64(a + i) ^ mbedtls_get_unaligned_uint64(b + i);
225*b0563631STom Van Eyck         mbedtls_put_unaligned_uint64(r + i, x);
226*b0563631STom Van Eyck     }
227*b0563631STom Van Eyck #if defined(__IAR_SYSTEMS_ICC__)
228*b0563631STom Van Eyck     if (n % 8 == 0) {
229*b0563631STom Van Eyck         return;
230*b0563631STom Van Eyck     }
231*b0563631STom Van Eyck #endif
232*b0563631STom Van Eyck #else
23332b31808SJens Wiklander     for (; (i + 4) <= n; i += 4) {
23432b31808SJens Wiklander         uint32_t x = mbedtls_get_unaligned_uint32(a + i) ^ mbedtls_get_unaligned_uint32(b + i);
23532b31808SJens Wiklander         mbedtls_put_unaligned_uint32(r + i, x);
236039e02dfSJerome Forissier     }
237*b0563631STom Van Eyck #if defined(__IAR_SYSTEMS_ICC__)
238*b0563631STom Van Eyck     if (n % 4 == 0) {
239*b0563631STom Van Eyck         return;
240*b0563631STom Van Eyck     }
241*b0563631STom Van Eyck #endif
242*b0563631STom Van Eyck #endif
243*b0563631STom Van Eyck #endif
244*b0563631STom Van Eyck     for (; i < n; i++) {
245*b0563631STom Van Eyck         r[i] = a[i] ^ b[i];
246*b0563631STom Van Eyck     }
247*b0563631STom Van Eyck }
248*b0563631STom Van Eyck 
249*b0563631STom Van Eyck /* Always inline mbedtls_xor_no_simd() as we see significant perf regressions when it does not get
250*b0563631STom Van Eyck  * inlined (e.g., observed about 3x perf difference in gcm_mult_largetable with gcc 7 - 12) */
251*b0563631STom Van Eyck #if defined(__IAR_SYSTEMS_ICC__)
252*b0563631STom Van Eyck #pragma inline = forced
253*b0563631STom Van Eyck #elif defined(__GNUC__)
254*b0563631STom Van Eyck __attribute__((always_inline))
255*b0563631STom Van Eyck #endif
256*b0563631STom Van Eyck /**
257*b0563631STom Van Eyck  * Perform a fast block XOR operation, such that
258*b0563631STom Van Eyck  * r[i] = a[i] ^ b[i] where 0 <= i < n
259*b0563631STom Van Eyck  *
260*b0563631STom Van Eyck  * In some situations, this can perform better than mbedtls_xor() (e.g., it's about 5%
261*b0563631STom Van Eyck  * better in AES-CBC).
262*b0563631STom Van Eyck  *
263*b0563631STom Van Eyck  * \param   r Pointer to result (buffer of at least \p n bytes). \p r
264*b0563631STom Van Eyck  *            may be equal to either \p a or \p b, but behaviour when
265*b0563631STom Van Eyck  *            it overlaps in other ways is undefined.
266*b0563631STom Van Eyck  * \param   a Pointer to input (buffer of at least \p n bytes)
267*b0563631STom Van Eyck  * \param   b Pointer to input (buffer of at least \p n bytes)
268*b0563631STom Van Eyck  * \param   n Number of bytes to process.
269*b0563631STom Van Eyck  *
270*b0563631STom Van Eyck  * \note      Depending on the situation, it may be faster to use either mbedtls_xor() or
271*b0563631STom Van Eyck  *            mbedtls_xor_no_simd() (these are functionally equivalent).
272*b0563631STom Van Eyck  *            If the result is used immediately after the xor operation in non-SIMD code (e.g, in
273*b0563631STom Van Eyck  *            AES-CBC), there may be additional latency to transfer the data from SIMD to scalar
274*b0563631STom Van Eyck  *            registers, and in this case, mbedtls_xor_no_simd() may be faster. In other cases where
275*b0563631STom Van Eyck  *            the result is not used immediately (e.g., in AES-CTR), mbedtls_xor() may be faster.
276*b0563631STom Van Eyck  *            For targets without SIMD support, they will behave the same.
277*b0563631STom Van Eyck  */
278*b0563631STom Van Eyck static inline void mbedtls_xor_no_simd(unsigned char *r,
279*b0563631STom Van Eyck                                        const unsigned char *a,
280*b0563631STom Van Eyck                                        const unsigned char *b,
281*b0563631STom Van Eyck                                        size_t n)
282*b0563631STom Van Eyck {
283*b0563631STom Van Eyck     size_t i = 0;
284*b0563631STom Van Eyck #if defined(MBEDTLS_EFFICIENT_UNALIGNED_ACCESS)
285*b0563631STom Van Eyck #if defined(MBEDTLS_ARCH_IS_X64) || defined(MBEDTLS_ARCH_IS_ARM64)
286*b0563631STom Van Eyck     /* This codepath probably only makes sense on architectures with 64-bit registers */
287*b0563631STom Van Eyck     for (; (i + 8) <= n; i += 8) {
288*b0563631STom Van Eyck         uint64_t x = mbedtls_get_unaligned_uint64(a + i) ^ mbedtls_get_unaligned_uint64(b + i);
289*b0563631STom Van Eyck         mbedtls_put_unaligned_uint64(r + i, x);
290*b0563631STom Van Eyck     }
291*b0563631STom Van Eyck #if defined(__IAR_SYSTEMS_ICC__)
292*b0563631STom Van Eyck     /* This if statement helps some compilers (e.g., IAR) optimise out the byte-by-byte tail case
293*b0563631STom Van Eyck      * where n is a constant multiple of 8.
294*b0563631STom Van Eyck      * For other compilers (e.g. recent gcc and clang) it makes no difference if n is a compile-time
295*b0563631STom Van Eyck      * constant, and is a very small perf regression if n is not a compile-time constant. */
296*b0563631STom Van Eyck     if (n % 8 == 0) {
297*b0563631STom Van Eyck         return;
298*b0563631STom Van Eyck     }
299*b0563631STom Van Eyck #endif
300*b0563631STom Van Eyck #else
301*b0563631STom Van Eyck     for (; (i + 4) <= n; i += 4) {
302*b0563631STom Van Eyck         uint32_t x = mbedtls_get_unaligned_uint32(a + i) ^ mbedtls_get_unaligned_uint32(b + i);
303*b0563631STom Van Eyck         mbedtls_put_unaligned_uint32(r + i, x);
304*b0563631STom Van Eyck     }
305*b0563631STom Van Eyck #if defined(__IAR_SYSTEMS_ICC__)
306*b0563631STom Van Eyck     if (n % 4 == 0) {
307*b0563631STom Van Eyck         return;
308*b0563631STom Van Eyck     }
309*b0563631STom Van Eyck #endif
310*b0563631STom Van Eyck #endif
311039e02dfSJerome Forissier #endif
31232b31808SJens Wiklander     for (; i < n; i++) {
31332b31808SJens Wiklander         r[i] = a[i] ^ b[i];
314039e02dfSJerome Forissier     }
315039e02dfSJerome Forissier }
31632b31808SJens Wiklander 
31732b31808SJens Wiklander /* Fix MSVC C99 compatible issue
31832b31808SJens Wiklander  *      MSVC support __func__ from visual studio 2015( 1900 )
31932b31808SJens Wiklander  *      Use MSVC predefine macro to avoid name check fail.
32032b31808SJens Wiklander  */
32132b31808SJens Wiklander #if (defined(_MSC_VER) && (_MSC_VER <= 1900))
32232b31808SJens Wiklander #define /*no-check-names*/ __func__ __FUNCTION__
323039e02dfSJerome Forissier #endif
324039e02dfSJerome Forissier 
32532b31808SJens Wiklander /* Define `asm` for compilers which don't define it. */
32632b31808SJens Wiklander /* *INDENT-OFF* */
32732b31808SJens Wiklander #ifndef asm
328*b0563631STom Van Eyck #if defined(__IAR_SYSTEMS_ICC__)
329*b0563631STom Van Eyck #define asm __asm
330*b0563631STom Van Eyck #else
33132b31808SJens Wiklander #define asm __asm__
332039e02dfSJerome Forissier #endif
333*b0563631STom Van Eyck #endif
33432b31808SJens Wiklander /* *INDENT-ON* */
335039e02dfSJerome Forissier 
336*b0563631STom Van Eyck /*
337*b0563631STom Van Eyck  * Define the constraint used for read-only pointer operands to aarch64 asm.
338*b0563631STom Van Eyck  *
339*b0563631STom Van Eyck  * This is normally the usual "r", but for aarch64_32 (aka ILP32,
340*b0563631STom Van Eyck  * as found in watchos), "p" is required to avoid warnings from clang.
341*b0563631STom Van Eyck  *
342*b0563631STom Van Eyck  * Note that clang does not recognise '+p' or '=p', and armclang
343*b0563631STom Van Eyck  * does not recognise 'p' at all. Therefore, to update a pointer from
344*b0563631STom Van Eyck  * aarch64 assembly, it is necessary to use something like:
345*b0563631STom Van Eyck  *
346*b0563631STom Van Eyck  * uintptr_t uptr = (uintptr_t) ptr;
347*b0563631STom Van Eyck  * asm( "ldr x4, [%x0], #8" ... : "+r" (uptr) : : )
348*b0563631STom Van Eyck  * ptr = (void*) uptr;
349*b0563631STom Van Eyck  *
350*b0563631STom Van Eyck  * Note that the "x" in "%x0" is neccessary; writing "%0" will cause warnings.
351*b0563631STom Van Eyck  */
352*b0563631STom Van Eyck #if defined(__aarch64__) && defined(MBEDTLS_HAVE_ASM)
353*b0563631STom Van Eyck #if UINTPTR_MAX == 0xfffffffful
354*b0563631STom Van Eyck /* ILP32: Specify the pointer operand slightly differently, as per #7787. */
355*b0563631STom Van Eyck #define MBEDTLS_ASM_AARCH64_PTR_CONSTRAINT "p"
356*b0563631STom Van Eyck #elif UINTPTR_MAX == 0xfffffffffffffffful
357*b0563631STom Van Eyck /* Normal case (64-bit pointers): use "r" as the constraint for pointer operands to asm */
358*b0563631STom Van Eyck #define MBEDTLS_ASM_AARCH64_PTR_CONSTRAINT "r"
359*b0563631STom Van Eyck #else
360*b0563631STom Van Eyck #error "Unrecognised pointer size for aarch64"
361*b0563631STom Van Eyck #endif
362*b0563631STom Van Eyck #endif
363*b0563631STom Van Eyck 
36432b31808SJens Wiklander /* Always provide a static assert macro, so it can be used unconditionally.
36532b31808SJens Wiklander  * It will expand to nothing on some systems.
36632b31808SJens Wiklander  * Can be used outside functions (but don't add a trailing ';' in that case:
36732b31808SJens Wiklander  * the semicolon is included here to avoid triggering -Wextra-semi when
36832b31808SJens Wiklander  * MBEDTLS_STATIC_ASSERT() expands to nothing).
36932b31808SJens Wiklander  * Can't use the C11-style `defined(static_assert)` on FreeBSD, since it
37032b31808SJens Wiklander  * defines static_assert even with -std=c99, but then complains about it.
371039e02dfSJerome Forissier  */
37232b31808SJens Wiklander #if defined(static_assert) && !defined(__FreeBSD__)
37332b31808SJens Wiklander #define MBEDTLS_STATIC_ASSERT(expr, msg)    static_assert(expr, msg);
37432b31808SJens Wiklander #else
37532b31808SJens Wiklander #define MBEDTLS_STATIC_ASSERT(expr, msg)
376039e02dfSJerome Forissier #endif
377039e02dfSJerome Forissier 
378*b0563631STom Van Eyck #if defined(__has_builtin)
379*b0563631STom Van Eyck #define MBEDTLS_HAS_BUILTIN(x) __has_builtin(x)
380*b0563631STom Van Eyck #else
381*b0563631STom Van Eyck #define MBEDTLS_HAS_BUILTIN(x) 0
382*b0563631STom Van Eyck #endif
383*b0563631STom Van Eyck 
384*b0563631STom Van Eyck /* Define compiler branch hints */
385*b0563631STom Van Eyck #if MBEDTLS_HAS_BUILTIN(__builtin_expect)
386*b0563631STom Van Eyck #define MBEDTLS_LIKELY(x)       __builtin_expect(!!(x), 1)
387*b0563631STom Van Eyck #define MBEDTLS_UNLIKELY(x)     __builtin_expect(!!(x), 0)
388*b0563631STom Van Eyck #else
389*b0563631STom Van Eyck #define MBEDTLS_LIKELY(x)       x
390*b0563631STom Van Eyck #define MBEDTLS_UNLIKELY(x)     x
391*b0563631STom Van Eyck #endif
392*b0563631STom Van Eyck 
393*b0563631STom Van Eyck /* MBEDTLS_ASSUME may be used to provide additional information to the compiler
394*b0563631STom Van Eyck  * which can result in smaller code-size. */
395*b0563631STom Van Eyck #if MBEDTLS_HAS_BUILTIN(__builtin_assume)
396*b0563631STom Van Eyck /* clang provides __builtin_assume */
397*b0563631STom Van Eyck #define MBEDTLS_ASSUME(x)       __builtin_assume(x)
398*b0563631STom Van Eyck #elif MBEDTLS_HAS_BUILTIN(__builtin_unreachable)
399*b0563631STom Van Eyck /* gcc and IAR can use __builtin_unreachable */
400*b0563631STom Van Eyck #define MBEDTLS_ASSUME(x)       do { if (!(x)) __builtin_unreachable(); } while (0)
401*b0563631STom Van Eyck #elif defined(_MSC_VER)
402*b0563631STom Van Eyck /* Supported by MSVC since VS 2005 */
403*b0563631STom Van Eyck #define MBEDTLS_ASSUME(x)       __assume(x)
404*b0563631STom Van Eyck #else
405*b0563631STom Van Eyck #define MBEDTLS_ASSUME(x)       do { } while (0)
406*b0563631STom Van Eyck #endif
407*b0563631STom Van Eyck 
408*b0563631STom Van Eyck /* For gcc -Os, override with -O2 for a given function.
409*b0563631STom Van Eyck  *
410*b0563631STom Van Eyck  * This will not affect behaviour for other optimisation settings, e.g. -O0.
411*b0563631STom Van Eyck  */
412*b0563631STom Van Eyck #if defined(MBEDTLS_COMPILER_IS_GCC) && defined(__OPTIMIZE_SIZE__)
413*b0563631STom Van Eyck #define MBEDTLS_OPTIMIZE_FOR_PERFORMANCE __attribute__((optimize("-O2")))
414*b0563631STom Van Eyck #else
415*b0563631STom Van Eyck #define MBEDTLS_OPTIMIZE_FOR_PERFORMANCE
416*b0563631STom Van Eyck #endif
417*b0563631STom Van Eyck 
418*b0563631STom Van Eyck /* Suppress compiler warnings for unused functions and variables. */
419*b0563631STom Van Eyck #if !defined(MBEDTLS_MAYBE_UNUSED) && defined(__has_attribute)
420*b0563631STom Van Eyck #    if __has_attribute(unused)
421*b0563631STom Van Eyck #        define MBEDTLS_MAYBE_UNUSED __attribute__((unused))
422*b0563631STom Van Eyck #    endif
423*b0563631STom Van Eyck #endif
424*b0563631STom Van Eyck #if !defined(MBEDTLS_MAYBE_UNUSED) && defined(__GNUC__)
425*b0563631STom Van Eyck #    define MBEDTLS_MAYBE_UNUSED __attribute__((unused))
426*b0563631STom Van Eyck #endif
427*b0563631STom Van Eyck #if !defined(MBEDTLS_MAYBE_UNUSED) && defined(__IAR_SYSTEMS_ICC__) && defined(__VER__)
428*b0563631STom Van Eyck /* IAR does support __attribute__((unused)), but only if the -e flag (extended language support)
429*b0563631STom Van Eyck  * is given; the pragma always works.
430*b0563631STom Van Eyck  * Unfortunately the pragma affects the rest of the file where it is used, but this is harmless.
431*b0563631STom Van Eyck  * Check for version 5.2 or later - this pragma may be supported by earlier versions, but I wasn't
432*b0563631STom Van Eyck  * able to find documentation).
433*b0563631STom Van Eyck  */
434*b0563631STom Van Eyck #    if (__VER__ >= 5020000)
435*b0563631STom Van Eyck #        define MBEDTLS_MAYBE_UNUSED _Pragma("diag_suppress=Pe177")
436*b0563631STom Van Eyck #    endif
437*b0563631STom Van Eyck #endif
438*b0563631STom Van Eyck #if !defined(MBEDTLS_MAYBE_UNUSED) && defined(_MSC_VER)
439*b0563631STom Van Eyck #    define MBEDTLS_MAYBE_UNUSED __pragma(warning(suppress:4189))
440*b0563631STom Van Eyck #endif
441*b0563631STom Van Eyck #if !defined(MBEDTLS_MAYBE_UNUSED)
442*b0563631STom Van Eyck #    define MBEDTLS_MAYBE_UNUSED
443*b0563631STom Van Eyck #endif
444*b0563631STom Van Eyck 
4457901324dSJerome Forissier #endif /* MBEDTLS_LIBRARY_COMMON_H */
446