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
8b0563631STom 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
22b0563631STom Van Eyck #if defined(__ARM_NEON)
23b0563631STom Van Eyck /*
24b0563631STom Van Eyck * Undefine and restore __section and __data from compiler.h to prevent
25b0563631STom Van Eyck * collision with arm_neon.h
26b0563631STom Van Eyck */
27b0563631STom Van Eyck #pragma push_macro("__section")
28b0563631STom Van Eyck #pragma push_macro("__data")
29b0563631STom Van Eyck #undef __section
30b0563631STom Van Eyck #undef __data
31b0563631STom Van Eyck #include <arm_neon.h>
32b0563631STom Van Eyck #pragma pop_macro("__data")
33b0563631STom Van Eyck #pragma pop_macro("__section")
34b0563631STom Van Eyck #define MBEDTLS_HAVE_NEON_INTRINSICS
35b0563631STom Van Eyck #elif defined(MBEDTLS_PLATFORM_IS_WINDOWS_ON_ARM64)
36b0563631STom Van Eyck #include <arm64_neon.h>
37b0563631STom Van Eyck #define MBEDTLS_HAVE_NEON_INTRINSICS
38b0563631STom Van Eyck #endif
39b0563631STom 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
74b0563631STom Van Eyck /** \def ARRAY_LENGTH
75b0563631STom Van Eyck * Return the number of elements of a static or stack array.
76b0563631STom Van Eyck *
77b0563631STom Van Eyck * \param array A value of array (not pointer) type.
78b0563631STom Van Eyck *
79b0563631STom Van Eyck * \return The number of elements of the array.
80b0563631STom Van Eyck */
81b0563631STom Van Eyck /* A correct implementation of ARRAY_LENGTH, but which silently gives
82b0563631STom Van Eyck * a nonsensical result if called with a pointer rather than an array. */
83b0563631STom Van Eyck #define ARRAY_LENGTH_UNSAFE(array) \
84b0563631STom Van Eyck (sizeof(array) / sizeof(*(array)))
85b0563631STom Van Eyck
86b0563631STom Van Eyck #if defined(__GNUC__)
87b0563631STom Van Eyck /* Test if arg and &(arg)[0] have the same type. This is true if arg is
88b0563631STom Van Eyck * an array but not if it's a pointer. */
89b0563631STom Van Eyck #define IS_ARRAY_NOT_POINTER(arg) \
90b0563631STom Van Eyck (!__builtin_types_compatible_p(__typeof__(arg), \
91b0563631STom Van Eyck __typeof__(&(arg)[0])))
92b0563631STom Van Eyck /* A compile-time constant with the value 0. If `const_expr` is not a
93b0563631STom Van Eyck * compile-time constant with a nonzero value, cause a compile-time error. */
94b0563631STom Van Eyck #define STATIC_ASSERT_EXPR(const_expr) \
95b0563631STom Van Eyck (0 && sizeof(struct { unsigned int STATIC_ASSERT : 1 - 2 * !(const_expr); }))
96b0563631STom Van Eyck
97b0563631STom Van Eyck /* Return the scalar value `value` (possibly promoted). This is a compile-time
98b0563631STom Van Eyck * constant if `value` is. `condition` must be a compile-time constant.
99b0563631STom Van Eyck * If `condition` is false, arrange to cause a compile-time error. */
100b0563631STom Van Eyck #define STATIC_ASSERT_THEN_RETURN(condition, value) \
101b0563631STom Van Eyck (STATIC_ASSERT_EXPR(condition) ? 0 : (value))
102b0563631STom Van Eyck
103b0563631STom Van Eyck #define ARRAY_LENGTH(array) \
104b0563631STom Van Eyck (STATIC_ASSERT_THEN_RETURN(IS_ARRAY_NOT_POINTER(array), \
105b0563631STom Van Eyck ARRAY_LENGTH_UNSAFE(array)))
106b0563631STom Van Eyck
107b0563631STom Van Eyck #else
108b0563631STom Van Eyck /* If we aren't sure the compiler supports our non-standard tricks,
109b0563631STom Van Eyck * fall back to the unsafe implementation. */
110b0563631STom Van Eyck #define ARRAY_LENGTH(array) ARRAY_LENGTH_UNSAFE(array)
111b0563631STom 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
119b0563631STom Van Eyck /**
120b0563631STom Van Eyck * \brief Securely zeroize a buffer then free it.
121b0563631STom Van Eyck *
122b0563631STom Van Eyck * Similar to making consecutive calls to
123b0563631STom Van Eyck * \c mbedtls_platform_zeroize() and \c mbedtls_free(), but has
124b0563631STom Van Eyck * code size savings, and potential for optimisation in the future.
125b0563631STom Van Eyck *
126b0563631STom Van Eyck * Guaranteed to be a no-op if \p buf is \c NULL and \p len is 0.
127b0563631STom Van Eyck *
128b0563631STom Van Eyck * \param buf Buffer to be zeroized then freed.
129b0563631STom Van Eyck * \param len Length of the buffer in bytes
130b0563631STom Van Eyck */
131b0563631STom Van Eyck void mbedtls_zeroize_and_free(void *buf, size_t len);
132b0563631STom 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 */
mbedtls_buffer_offset(unsigned char * p,size_t n)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 */
mbedtls_buffer_offset_const(const unsigned char * p,size_t n)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
171b0563631STom Van Eyck /* Always inline mbedtls_xor() for similar reasons as mbedtls_xor_no_simd(). */
172b0563631STom Van Eyck #if defined(__IAR_SYSTEMS_ICC__)
173b0563631STom Van Eyck #pragma inline = forced
174b0563631STom Van Eyck #elif defined(__GNUC__)
175b0563631STom Van Eyck __attribute__((always_inline))
176b0563631STom 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.
187b0563631STom Van Eyck *
188b0563631STom Van Eyck * \note Depending on the situation, it may be faster to use either mbedtls_xor() or
189b0563631STom Van Eyck * mbedtls_xor_no_simd() (these are functionally equivalent).
190b0563631STom Van Eyck * If the result is used immediately after the xor operation in non-SIMD code (e.g, in
191b0563631STom Van Eyck * AES-CBC), there may be additional latency to transfer the data from SIMD to scalar
192b0563631STom Van Eyck * registers, and in this case, mbedtls_xor_no_simd() may be faster. In other cases where
193b0563631STom Van Eyck * the result is not used immediately (e.g., in AES-CTR), mbedtls_xor() may be faster.
194b0563631STom Van Eyck * For targets without SIMD support, they will behave the same.
19532b31808SJens Wiklander */
mbedtls_xor(unsigned char * r,const unsigned char * a,const unsigned char * b,size_t n)196b0563631STom Van Eyck static inline void mbedtls_xor(unsigned char *r,
197b0563631STom Van Eyck const unsigned char *a,
198b0563631STom Van Eyck const unsigned char *b,
199b0563631STom Van Eyck size_t n)
20032b31808SJens Wiklander {
20132b31808SJens Wiklander size_t i = 0;
20232b31808SJens Wiklander #if defined(MBEDTLS_EFFICIENT_UNALIGNED_ACCESS)
203b0563631STom Van Eyck #if defined(MBEDTLS_HAVE_NEON_INTRINSICS) && \
204b0563631STom Van Eyck (!(defined(MBEDTLS_COMPILER_IS_GCC) && MBEDTLS_GCC_VERSION < 70300))
205b0563631STom Van Eyck /* Old GCC versions generate a warning here, so disable the NEON path for these compilers */
206b0563631STom Van Eyck for (; (i + 16) <= n; i += 16) {
207b0563631STom Van Eyck uint8x16_t v1 = vld1q_u8(a + i);
208b0563631STom Van Eyck uint8x16_t v2 = vld1q_u8(b + i);
209b0563631STom Van Eyck uint8x16_t x = veorq_u8(v1, v2);
210b0563631STom Van Eyck vst1q_u8(r + i, x);
211b0563631STom Van Eyck }
21298dd4c70SJerome Forissier #if defined(__IAR_SYSTEMS_ICC__) || defined(MBEDTLS_COMPILER_IS_GCC)
213b0563631STom Van Eyck /* This if statement helps some compilers (e.g., IAR) optimise out the byte-by-byte tail case
214b0563631STom Van Eyck * where n is a constant multiple of 16.
215b0563631STom Van Eyck * For other compilers (e.g. recent gcc and clang) it makes no difference if n is a compile-time
21698dd4c70SJerome Forissier * constant, and is a very small perf regression if n is not a compile-time constant.
21798dd4c70SJerome Forissier * GCC 14.2 outputs a warning "array subscript 48 is outside array bounds" if we don't return
21898dd4c70SJerome Forissier * early. */
219b0563631STom Van Eyck if (n % 16 == 0) {
220b0563631STom Van Eyck return;
221b0563631STom Van Eyck }
222b0563631STom Van Eyck #endif
223b0563631STom Van Eyck #elif defined(MBEDTLS_ARCH_IS_X64) || defined(MBEDTLS_ARCH_IS_ARM64)
224b0563631STom Van Eyck /* This codepath probably only makes sense on architectures with 64-bit registers */
225b0563631STom Van Eyck for (; (i + 8) <= n; i += 8) {
226b0563631STom Van Eyck uint64_t x = mbedtls_get_unaligned_uint64(a + i) ^ mbedtls_get_unaligned_uint64(b + i);
227b0563631STom Van Eyck mbedtls_put_unaligned_uint64(r + i, x);
228b0563631STom Van Eyck }
229b0563631STom Van Eyck #if defined(__IAR_SYSTEMS_ICC__)
230b0563631STom Van Eyck if (n % 8 == 0) {
231b0563631STom Van Eyck return;
232b0563631STom Van Eyck }
233b0563631STom Van Eyck #endif
234b0563631STom Van Eyck #else
23532b31808SJens Wiklander for (; (i + 4) <= n; i += 4) {
23632b31808SJens Wiklander uint32_t x = mbedtls_get_unaligned_uint32(a + i) ^ mbedtls_get_unaligned_uint32(b + i);
23732b31808SJens Wiklander mbedtls_put_unaligned_uint32(r + i, x);
238039e02dfSJerome Forissier }
239b0563631STom Van Eyck #if defined(__IAR_SYSTEMS_ICC__)
240b0563631STom Van Eyck if (n % 4 == 0) {
241b0563631STom Van Eyck return;
242b0563631STom Van Eyck }
243b0563631STom Van Eyck #endif
244b0563631STom Van Eyck #endif
245b0563631STom Van Eyck #endif
246b0563631STom Van Eyck for (; i < n; i++) {
247b0563631STom Van Eyck r[i] = a[i] ^ b[i];
248b0563631STom Van Eyck }
249b0563631STom Van Eyck }
250b0563631STom Van Eyck
251b0563631STom Van Eyck /* Always inline mbedtls_xor_no_simd() as we see significant perf regressions when it does not get
252b0563631STom Van Eyck * inlined (e.g., observed about 3x perf difference in gcm_mult_largetable with gcc 7 - 12) */
253b0563631STom Van Eyck #if defined(__IAR_SYSTEMS_ICC__)
254b0563631STom Van Eyck #pragma inline = forced
255b0563631STom Van Eyck #elif defined(__GNUC__)
256b0563631STom Van Eyck __attribute__((always_inline))
257b0563631STom Van Eyck #endif
258b0563631STom Van Eyck /**
259b0563631STom Van Eyck * Perform a fast block XOR operation, such that
260b0563631STom Van Eyck * r[i] = a[i] ^ b[i] where 0 <= i < n
261b0563631STom Van Eyck *
262b0563631STom Van Eyck * In some situations, this can perform better than mbedtls_xor() (e.g., it's about 5%
263b0563631STom Van Eyck * better in AES-CBC).
264b0563631STom Van Eyck *
265b0563631STom Van Eyck * \param r Pointer to result (buffer of at least \p n bytes). \p r
266b0563631STom Van Eyck * may be equal to either \p a or \p b, but behaviour when
267b0563631STom Van Eyck * it overlaps in other ways is undefined.
268b0563631STom Van Eyck * \param a Pointer to input (buffer of at least \p n bytes)
269b0563631STom Van Eyck * \param b Pointer to input (buffer of at least \p n bytes)
270b0563631STom Van Eyck * \param n Number of bytes to process.
271b0563631STom Van Eyck *
272b0563631STom Van Eyck * \note Depending on the situation, it may be faster to use either mbedtls_xor() or
273b0563631STom Van Eyck * mbedtls_xor_no_simd() (these are functionally equivalent).
274b0563631STom Van Eyck * If the result is used immediately after the xor operation in non-SIMD code (e.g, in
275b0563631STom Van Eyck * AES-CBC), there may be additional latency to transfer the data from SIMD to scalar
276b0563631STom Van Eyck * registers, and in this case, mbedtls_xor_no_simd() may be faster. In other cases where
277b0563631STom Van Eyck * the result is not used immediately (e.g., in AES-CTR), mbedtls_xor() may be faster.
278b0563631STom Van Eyck * For targets without SIMD support, they will behave the same.
279b0563631STom Van Eyck */
mbedtls_xor_no_simd(unsigned char * r,const unsigned char * a,const unsigned char * b,size_t n)280b0563631STom Van Eyck static inline void mbedtls_xor_no_simd(unsigned char *r,
281b0563631STom Van Eyck const unsigned char *a,
282b0563631STom Van Eyck const unsigned char *b,
283b0563631STom Van Eyck size_t n)
284b0563631STom Van Eyck {
285b0563631STom Van Eyck size_t i = 0;
286b0563631STom Van Eyck #if defined(MBEDTLS_EFFICIENT_UNALIGNED_ACCESS)
287b0563631STom Van Eyck #if defined(MBEDTLS_ARCH_IS_X64) || defined(MBEDTLS_ARCH_IS_ARM64)
288b0563631STom Van Eyck /* This codepath probably only makes sense on architectures with 64-bit registers */
289b0563631STom Van Eyck for (; (i + 8) <= n; i += 8) {
290b0563631STom Van Eyck uint64_t x = mbedtls_get_unaligned_uint64(a + i) ^ mbedtls_get_unaligned_uint64(b + i);
291b0563631STom Van Eyck mbedtls_put_unaligned_uint64(r + i, x);
292b0563631STom Van Eyck }
293b0563631STom Van Eyck #if defined(__IAR_SYSTEMS_ICC__)
294b0563631STom Van Eyck /* This if statement helps some compilers (e.g., IAR) optimise out the byte-by-byte tail case
295b0563631STom Van Eyck * where n is a constant multiple of 8.
296b0563631STom Van Eyck * For other compilers (e.g. recent gcc and clang) it makes no difference if n is a compile-time
297b0563631STom Van Eyck * constant, and is a very small perf regression if n is not a compile-time constant. */
298b0563631STom Van Eyck if (n % 8 == 0) {
299b0563631STom Van Eyck return;
300b0563631STom Van Eyck }
301b0563631STom Van Eyck #endif
302b0563631STom Van Eyck #else
303b0563631STom Van Eyck for (; (i + 4) <= n; i += 4) {
304b0563631STom Van Eyck uint32_t x = mbedtls_get_unaligned_uint32(a + i) ^ mbedtls_get_unaligned_uint32(b + i);
305b0563631STom Van Eyck mbedtls_put_unaligned_uint32(r + i, x);
306b0563631STom Van Eyck }
307b0563631STom Van Eyck #if defined(__IAR_SYSTEMS_ICC__)
308b0563631STom Van Eyck if (n % 4 == 0) {
309b0563631STom Van Eyck return;
310b0563631STom Van Eyck }
311b0563631STom Van Eyck #endif
312b0563631STom Van Eyck #endif
313039e02dfSJerome Forissier #endif
31432b31808SJens Wiklander for (; i < n; i++) {
31532b31808SJens Wiklander r[i] = a[i] ^ b[i];
316039e02dfSJerome Forissier }
317039e02dfSJerome Forissier }
31832b31808SJens Wiklander
31932b31808SJens Wiklander /* Fix MSVC C99 compatible issue
32032b31808SJens Wiklander * MSVC support __func__ from visual studio 2015( 1900 )
32132b31808SJens Wiklander * Use MSVC predefine macro to avoid name check fail.
32232b31808SJens Wiklander */
32332b31808SJens Wiklander #if (defined(_MSC_VER) && (_MSC_VER <= 1900))
32432b31808SJens Wiklander #define /*no-check-names*/ __func__ __FUNCTION__
325039e02dfSJerome Forissier #endif
326039e02dfSJerome Forissier
32732b31808SJens Wiklander /* Define `asm` for compilers which don't define it. */
32832b31808SJens Wiklander /* *INDENT-OFF* */
32932b31808SJens Wiklander #ifndef asm
330b0563631STom Van Eyck #if defined(__IAR_SYSTEMS_ICC__)
331b0563631STom Van Eyck #define asm __asm
332b0563631STom Van Eyck #else
33332b31808SJens Wiklander #define asm __asm__
334039e02dfSJerome Forissier #endif
335b0563631STom Van Eyck #endif
33632b31808SJens Wiklander /* *INDENT-ON* */
337039e02dfSJerome Forissier
338b0563631STom Van Eyck /*
339b0563631STom Van Eyck * Define the constraint used for read-only pointer operands to aarch64 asm.
340b0563631STom Van Eyck *
341b0563631STom Van Eyck * This is normally the usual "r", but for aarch64_32 (aka ILP32,
342b0563631STom Van Eyck * as found in watchos), "p" is required to avoid warnings from clang.
343b0563631STom Van Eyck *
344b0563631STom Van Eyck * Note that clang does not recognise '+p' or '=p', and armclang
345b0563631STom Van Eyck * does not recognise 'p' at all. Therefore, to update a pointer from
346b0563631STom Van Eyck * aarch64 assembly, it is necessary to use something like:
347b0563631STom Van Eyck *
348b0563631STom Van Eyck * uintptr_t uptr = (uintptr_t) ptr;
349b0563631STom Van Eyck * asm( "ldr x4, [%x0], #8" ... : "+r" (uptr) : : )
350b0563631STom Van Eyck * ptr = (void*) uptr;
351b0563631STom Van Eyck *
352b0563631STom Van Eyck * Note that the "x" in "%x0" is neccessary; writing "%0" will cause warnings.
353b0563631STom Van Eyck */
354b0563631STom Van Eyck #if defined(__aarch64__) && defined(MBEDTLS_HAVE_ASM)
355b0563631STom Van Eyck #if UINTPTR_MAX == 0xfffffffful
356b0563631STom Van Eyck /* ILP32: Specify the pointer operand slightly differently, as per #7787. */
357b0563631STom Van Eyck #define MBEDTLS_ASM_AARCH64_PTR_CONSTRAINT "p"
358b0563631STom Van Eyck #elif UINTPTR_MAX == 0xfffffffffffffffful
359b0563631STom Van Eyck /* Normal case (64-bit pointers): use "r" as the constraint for pointer operands to asm */
360b0563631STom Van Eyck #define MBEDTLS_ASM_AARCH64_PTR_CONSTRAINT "r"
361b0563631STom Van Eyck #else
362b0563631STom Van Eyck #error "Unrecognised pointer size for aarch64"
363b0563631STom Van Eyck #endif
364b0563631STom Van Eyck #endif
365b0563631STom Van Eyck
36632b31808SJens Wiklander /* Always provide a static assert macro, so it can be used unconditionally.
367cb034002SJerome Forissier * It does nothing on systems where we don't know how to define a static assert.
368cb034002SJerome Forissier */
369cb034002SJerome Forissier /* 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__)
373cb034002SJerome Forissier #define MBEDTLS_STATIC_ASSERT(expr, msg) static_assert(expr, msg)
37432b31808SJens Wiklander #else
375cb034002SJerome Forissier /* Make sure `MBEDTLS_STATIC_ASSERT(expr, msg);` is valid both inside and
376cb034002SJerome Forissier * outside a function. We choose a struct declaration, which can be repeated
377cb034002SJerome Forissier * any number of times and does not need a matching definition. */
378cb034002SJerome Forissier #define MBEDTLS_STATIC_ASSERT(expr, msg) \
379cb034002SJerome Forissier struct ISO_C_does_not_allow_extra_semicolon_outside_of_a_function
380039e02dfSJerome Forissier #endif
381039e02dfSJerome Forissier
382b0563631STom Van Eyck #if defined(__has_builtin)
383b0563631STom Van Eyck #define MBEDTLS_HAS_BUILTIN(x) __has_builtin(x)
384b0563631STom Van Eyck #else
385b0563631STom Van Eyck #define MBEDTLS_HAS_BUILTIN(x) 0
386b0563631STom Van Eyck #endif
387b0563631STom Van Eyck
388b0563631STom Van Eyck /* Define compiler branch hints */
389b0563631STom Van Eyck #if MBEDTLS_HAS_BUILTIN(__builtin_expect)
390b0563631STom Van Eyck #define MBEDTLS_LIKELY(x) __builtin_expect(!!(x), 1)
391b0563631STom Van Eyck #define MBEDTLS_UNLIKELY(x) __builtin_expect(!!(x), 0)
392b0563631STom Van Eyck #else
393b0563631STom Van Eyck #define MBEDTLS_LIKELY(x) x
394b0563631STom Van Eyck #define MBEDTLS_UNLIKELY(x) x
395b0563631STom Van Eyck #endif
396b0563631STom Van Eyck
397b0563631STom Van Eyck /* MBEDTLS_ASSUME may be used to provide additional information to the compiler
398b0563631STom Van Eyck * which can result in smaller code-size. */
399b0563631STom Van Eyck #if MBEDTLS_HAS_BUILTIN(__builtin_assume)
400b0563631STom Van Eyck /* clang provides __builtin_assume */
401b0563631STom Van Eyck #define MBEDTLS_ASSUME(x) __builtin_assume(x)
402b0563631STom Van Eyck #elif MBEDTLS_HAS_BUILTIN(__builtin_unreachable)
403b0563631STom Van Eyck /* gcc and IAR can use __builtin_unreachable */
404b0563631STom Van Eyck #define MBEDTLS_ASSUME(x) do { if (!(x)) __builtin_unreachable(); } while (0)
405b0563631STom Van Eyck #elif defined(_MSC_VER)
406b0563631STom Van Eyck /* Supported by MSVC since VS 2005 */
407b0563631STom Van Eyck #define MBEDTLS_ASSUME(x) __assume(x)
408b0563631STom Van Eyck #else
409b0563631STom Van Eyck #define MBEDTLS_ASSUME(x) do { } while (0)
410b0563631STom Van Eyck #endif
411b0563631STom Van Eyck
412b0563631STom Van Eyck /* For gcc -Os, override with -O2 for a given function.
413b0563631STom Van Eyck *
414b0563631STom Van Eyck * This will not affect behaviour for other optimisation settings, e.g. -O0.
415b0563631STom Van Eyck */
416b0563631STom Van Eyck #if defined(MBEDTLS_COMPILER_IS_GCC) && defined(__OPTIMIZE_SIZE__)
417b0563631STom Van Eyck #define MBEDTLS_OPTIMIZE_FOR_PERFORMANCE __attribute__((optimize("-O2")))
418b0563631STom Van Eyck #else
419b0563631STom Van Eyck #define MBEDTLS_OPTIMIZE_FOR_PERFORMANCE
420b0563631STom Van Eyck #endif
421b0563631STom Van Eyck
422b0563631STom Van Eyck /* Suppress compiler warnings for unused functions and variables. */
423b0563631STom Van Eyck #if !defined(MBEDTLS_MAYBE_UNUSED) && defined(__has_attribute)
424b0563631STom Van Eyck # if __has_attribute(unused)
425b0563631STom Van Eyck # define MBEDTLS_MAYBE_UNUSED __attribute__((unused))
426b0563631STom Van Eyck # endif
427b0563631STom Van Eyck #endif
428b0563631STom Van Eyck #if !defined(MBEDTLS_MAYBE_UNUSED) && defined(__GNUC__)
429b0563631STom Van Eyck # define MBEDTLS_MAYBE_UNUSED __attribute__((unused))
430b0563631STom Van Eyck #endif
431b0563631STom Van Eyck #if !defined(MBEDTLS_MAYBE_UNUSED) && defined(__IAR_SYSTEMS_ICC__) && defined(__VER__)
432b0563631STom Van Eyck /* IAR does support __attribute__((unused)), but only if the -e flag (extended language support)
433b0563631STom Van Eyck * is given; the pragma always works.
434b0563631STom Van Eyck * Unfortunately the pragma affects the rest of the file where it is used, but this is harmless.
435b0563631STom Van Eyck * Check for version 5.2 or later - this pragma may be supported by earlier versions, but I wasn't
436b0563631STom Van Eyck * able to find documentation).
437b0563631STom Van Eyck */
438b0563631STom Van Eyck # if (__VER__ >= 5020000)
439b0563631STom Van Eyck # define MBEDTLS_MAYBE_UNUSED _Pragma("diag_suppress=Pe177")
440b0563631STom Van Eyck # endif
441b0563631STom Van Eyck #endif
442b0563631STom Van Eyck #if !defined(MBEDTLS_MAYBE_UNUSED) && defined(_MSC_VER)
443b0563631STom Van Eyck # define MBEDTLS_MAYBE_UNUSED __pragma(warning(suppress:4189))
444b0563631STom Van Eyck #endif
445b0563631STom Van Eyck #if !defined(MBEDTLS_MAYBE_UNUSED)
446b0563631STom Van Eyck # define MBEDTLS_MAYBE_UNUSED
447b0563631STom Van Eyck #endif
448b0563631STom Van Eyck
449*273a583eSThomas Bourgoin /* GCC >= 15 has a warning 'unterminated-string-initialization' which complains if you initialize
450*273a583eSThomas Bourgoin * a string into an array without space for a terminating NULL character. In some places in the
451*273a583eSThomas Bourgoin * codebase this behaviour is intended, so we add the macro MBEDTLS_ATTRIBUTE_UNTERMINATED_STRING
452*273a583eSThomas Bourgoin * to suppress the warning in these places.
453*273a583eSThomas Bourgoin */
454*273a583eSThomas Bourgoin #if defined(__has_attribute)
455*273a583eSThomas Bourgoin #if __has_attribute(nonstring)
456*273a583eSThomas Bourgoin #define MBEDTLS_HAS_ATTRIBUTE_NONSTRING
457*273a583eSThomas Bourgoin #endif /* __has_attribute(nonstring) */
458*273a583eSThomas Bourgoin #endif /* __has_attribute */
459*273a583eSThomas Bourgoin #if defined(MBEDTLS_HAS_ATTRIBUTE_NONSTRING)
460*273a583eSThomas Bourgoin #define MBEDTLS_ATTRIBUTE_UNTERMINATED_STRING __attribute__((nonstring))
461*273a583eSThomas Bourgoin #else
462*273a583eSThomas Bourgoin #define MBEDTLS_ATTRIBUTE_UNTERMINATED_STRING
463*273a583eSThomas Bourgoin #endif /* MBEDTLS_HAS_ATTRIBUTE_NONSTRING */
464*273a583eSThomas Bourgoin
4657901324dSJerome Forissier #endif /* MBEDTLS_LIBRARY_COMMON_H */
466