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 */ 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 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 */ 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 } 212*98dd4c70SJerome 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 216*98dd4c70SJerome Forissier * constant, and is a very small perf regression if n is not a compile-time constant. 217*98dd4c70SJerome Forissier * GCC 14.2 outputs a warning "array subscript 48 is outside array bounds" if we don't return 218*98dd4c70SJerome 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 */ 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 4497901324dSJerome Forissier #endif /* MBEDTLS_LIBRARY_COMMON_H */ 450