1a8e1175bSopenharmony_ci/** 2a8e1175bSopenharmony_ci * \file alignment.h 3a8e1175bSopenharmony_ci * 4a8e1175bSopenharmony_ci * \brief Utility code for dealing with unaligned memory accesses 5a8e1175bSopenharmony_ci */ 6a8e1175bSopenharmony_ci/* 7a8e1175bSopenharmony_ci * Copyright The Mbed TLS Contributors 8a8e1175bSopenharmony_ci * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later 9a8e1175bSopenharmony_ci */ 10a8e1175bSopenharmony_ci 11a8e1175bSopenharmony_ci#ifndef MBEDTLS_LIBRARY_ALIGNMENT_H 12a8e1175bSopenharmony_ci#define MBEDTLS_LIBRARY_ALIGNMENT_H 13a8e1175bSopenharmony_ci 14a8e1175bSopenharmony_ci#include <stdint.h> 15a8e1175bSopenharmony_ci#include <string.h> 16a8e1175bSopenharmony_ci#include <stdlib.h> 17a8e1175bSopenharmony_ci 18a8e1175bSopenharmony_ci/* 19a8e1175bSopenharmony_ci * Define MBEDTLS_EFFICIENT_UNALIGNED_ACCESS for architectures where unaligned memory 20a8e1175bSopenharmony_ci * accesses are known to be efficient. 21a8e1175bSopenharmony_ci * 22a8e1175bSopenharmony_ci * All functions defined here will behave correctly regardless, but might be less 23a8e1175bSopenharmony_ci * efficient when this is not defined. 24a8e1175bSopenharmony_ci */ 25a8e1175bSopenharmony_ci#if defined(__ARM_FEATURE_UNALIGNED) \ 26a8e1175bSopenharmony_ci || defined(MBEDTLS_ARCH_IS_X86) || defined(MBEDTLS_ARCH_IS_X64) \ 27a8e1175bSopenharmony_ci || defined(MBEDTLS_PLATFORM_IS_WINDOWS_ON_ARM64) 28a8e1175bSopenharmony_ci/* 29a8e1175bSopenharmony_ci * __ARM_FEATURE_UNALIGNED is defined where appropriate by armcc, gcc 7, clang 9 30a8e1175bSopenharmony_ci * (and later versions) for Arm v7 and later; all x86 platforms should have 31a8e1175bSopenharmony_ci * efficient unaligned access. 32a8e1175bSopenharmony_ci * 33a8e1175bSopenharmony_ci * https://learn.microsoft.com/en-us/cpp/build/arm64-windows-abi-conventions?view=msvc-170#alignment 34a8e1175bSopenharmony_ci * specifies that on Windows-on-Arm64, unaligned access is safe (except for uncached 35a8e1175bSopenharmony_ci * device memory). 36a8e1175bSopenharmony_ci */ 37a8e1175bSopenharmony_ci#define MBEDTLS_EFFICIENT_UNALIGNED_ACCESS 38a8e1175bSopenharmony_ci#endif 39a8e1175bSopenharmony_ci 40a8e1175bSopenharmony_ci#if defined(__IAR_SYSTEMS_ICC__) && \ 41a8e1175bSopenharmony_ci (defined(MBEDTLS_ARCH_IS_ARM64) || defined(MBEDTLS_ARCH_IS_ARM32) \ 42a8e1175bSopenharmony_ci || defined(__ICCRX__) || defined(__ICCRL78__) || defined(__ICCRISCV__)) 43a8e1175bSopenharmony_ci#pragma language=save 44a8e1175bSopenharmony_ci#pragma language=extended 45a8e1175bSopenharmony_ci#define MBEDTLS_POP_IAR_LANGUAGE_PRAGMA 46a8e1175bSopenharmony_ci/* IAR recommend this technique for accessing unaligned data in 47a8e1175bSopenharmony_ci * https://www.iar.com/knowledge/support/technical-notes/compiler/accessing-unaligned-data 48a8e1175bSopenharmony_ci * This results in a single load / store instruction (if unaligned access is supported). 49a8e1175bSopenharmony_ci * According to that document, this is only supported on certain architectures. 50a8e1175bSopenharmony_ci */ 51a8e1175bSopenharmony_ci #define UINT_UNALIGNED 52a8e1175bSopenharmony_citypedef uint16_t __packed mbedtls_uint16_unaligned_t; 53a8e1175bSopenharmony_citypedef uint32_t __packed mbedtls_uint32_unaligned_t; 54a8e1175bSopenharmony_citypedef uint64_t __packed mbedtls_uint64_unaligned_t; 55a8e1175bSopenharmony_ci#elif defined(MBEDTLS_COMPILER_IS_GCC) && (MBEDTLS_GCC_VERSION >= 40504) && \ 56a8e1175bSopenharmony_ci ((MBEDTLS_GCC_VERSION < 60300) || (!defined(MBEDTLS_EFFICIENT_UNALIGNED_ACCESS))) 57a8e1175bSopenharmony_ci/* 58a8e1175bSopenharmony_ci * gcc may generate a branch to memcpy for calls like `memcpy(dest, src, 4)` rather than 59a8e1175bSopenharmony_ci * generating some LDR or LDRB instructions (similar for stores). 60a8e1175bSopenharmony_ci * 61a8e1175bSopenharmony_ci * This is architecture dependent: x86-64 seems fine even with old gcc; 32-bit Arm 62a8e1175bSopenharmony_ci * is affected. To keep it simple, we enable for all architectures. 63a8e1175bSopenharmony_ci * 64a8e1175bSopenharmony_ci * For versions of gcc < 5.4.0 this issue always happens. 65a8e1175bSopenharmony_ci * For gcc < 6.3.0, this issue happens at -O0 66a8e1175bSopenharmony_ci * For all versions, this issue happens iff unaligned access is not supported. 67a8e1175bSopenharmony_ci * 68a8e1175bSopenharmony_ci * For gcc 4.x, this implementation will generate byte-by-byte loads even if unaligned access is 69a8e1175bSopenharmony_ci * supported, which is correct but not optimal. 70a8e1175bSopenharmony_ci * 71a8e1175bSopenharmony_ci * For performance (and code size, in some cases), we want to avoid the branch and just generate 72a8e1175bSopenharmony_ci * some inline load/store instructions since the access is small and constant-size. 73a8e1175bSopenharmony_ci * 74a8e1175bSopenharmony_ci * The manual states: 75a8e1175bSopenharmony_ci * "The packed attribute specifies that a variable or structure field should have the smallest 76a8e1175bSopenharmony_ci * possible alignment��one byte for a variable" 77a8e1175bSopenharmony_ci * https://gcc.gnu.org/onlinedocs/gcc-4.5.4/gcc/Variable-Attributes.html 78a8e1175bSopenharmony_ci * 79a8e1175bSopenharmony_ci * Previous implementations used __attribute__((__aligned__(1)), but had issues with a gcc bug: 80a8e1175bSopenharmony_ci * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94662 81a8e1175bSopenharmony_ci * 82a8e1175bSopenharmony_ci * Tested with several versions of GCC from 4.5.0 up to 13.2.0 83a8e1175bSopenharmony_ci * We don't enable for older than 4.5.0 as this has not been tested. 84a8e1175bSopenharmony_ci */ 85a8e1175bSopenharmony_ci #define UINT_UNALIGNED_STRUCT 86a8e1175bSopenharmony_citypedef struct { 87a8e1175bSopenharmony_ci uint16_t x; 88a8e1175bSopenharmony_ci} __attribute__((packed)) mbedtls_uint16_unaligned_t; 89a8e1175bSopenharmony_citypedef struct { 90a8e1175bSopenharmony_ci uint32_t x; 91a8e1175bSopenharmony_ci} __attribute__((packed)) mbedtls_uint32_unaligned_t; 92a8e1175bSopenharmony_citypedef struct { 93a8e1175bSopenharmony_ci uint64_t x; 94a8e1175bSopenharmony_ci} __attribute__((packed)) mbedtls_uint64_unaligned_t; 95a8e1175bSopenharmony_ci #endif 96a8e1175bSopenharmony_ci 97a8e1175bSopenharmony_ci/* 98a8e1175bSopenharmony_ci * We try to force mbedtls_(get|put)_unaligned_uintXX to be always inline, because this results 99a8e1175bSopenharmony_ci * in code that is both smaller and faster. IAR and gcc both benefit from this when optimising 100a8e1175bSopenharmony_ci * for size. 101a8e1175bSopenharmony_ci */ 102a8e1175bSopenharmony_ci 103a8e1175bSopenharmony_ci/** 104a8e1175bSopenharmony_ci * Read the unsigned 16 bits integer from the given address, which need not 105a8e1175bSopenharmony_ci * be aligned. 106a8e1175bSopenharmony_ci * 107a8e1175bSopenharmony_ci * \param p pointer to 2 bytes of data 108a8e1175bSopenharmony_ci * \return Data at the given address 109a8e1175bSopenharmony_ci */ 110a8e1175bSopenharmony_ciuint16_t mbedtls_get_unaligned_uint16(const void *p); 111a8e1175bSopenharmony_ci 112a8e1175bSopenharmony_ci/** 113a8e1175bSopenharmony_ci * Write the unsigned 16 bits integer to the given address, which need not 114a8e1175bSopenharmony_ci * be aligned. 115a8e1175bSopenharmony_ci * 116a8e1175bSopenharmony_ci * \param p pointer to 2 bytes of data 117a8e1175bSopenharmony_ci * \param x data to write 118a8e1175bSopenharmony_ci */ 119a8e1175bSopenharmony_civoid mbedtls_put_unaligned_uint16(void *p, uint16_t x); 120a8e1175bSopenharmony_ci 121a8e1175bSopenharmony_ci/** 122a8e1175bSopenharmony_ci * Read the unsigned 32 bits integer from the given address, which need not 123a8e1175bSopenharmony_ci * be aligned. 124a8e1175bSopenharmony_ci * 125a8e1175bSopenharmony_ci * \param p pointer to 4 bytes of data 126a8e1175bSopenharmony_ci * \return Data at the given address 127a8e1175bSopenharmony_ci */ 128a8e1175bSopenharmony_ciuint32_t mbedtls_get_unaligned_uint32(const void *p); 129a8e1175bSopenharmony_ci 130a8e1175bSopenharmony_ci/** 131a8e1175bSopenharmony_ci * Write the unsigned 32 bits integer to the given address, which need not 132a8e1175bSopenharmony_ci * be aligned. 133a8e1175bSopenharmony_ci * 134a8e1175bSopenharmony_ci * \param p pointer to 4 bytes of data 135a8e1175bSopenharmony_ci * \param x data to write 136a8e1175bSopenharmony_ci */ 137a8e1175bSopenharmony_civoid mbedtls_put_unaligned_uint32(void *p, uint32_t x); 138a8e1175bSopenharmony_ci 139a8e1175bSopenharmony_ci/** 140a8e1175bSopenharmony_ci * Read the unsigned 64 bits integer from the given address, which need not 141a8e1175bSopenharmony_ci * be aligned. 142a8e1175bSopenharmony_ci * 143a8e1175bSopenharmony_ci * \param p pointer to 8 bytes of data 144a8e1175bSopenharmony_ci * \return Data at the given address 145a8e1175bSopenharmony_ci */ 146a8e1175bSopenharmony_ciuint64_t mbedtls_get_unaligned_uint64(const void *p); 147a8e1175bSopenharmony_ci 148a8e1175bSopenharmony_ci/** 149a8e1175bSopenharmony_ci * Write the unsigned 64 bits integer to the given address, which need not 150a8e1175bSopenharmony_ci * be aligned. 151a8e1175bSopenharmony_ci * 152a8e1175bSopenharmony_ci * \param p pointer to 8 bytes of data 153a8e1175bSopenharmony_ci * \param x data to write 154a8e1175bSopenharmony_ci */ 155a8e1175bSopenharmony_civoid mbedtls_put_unaligned_uint64(void *p, uint64_t x); 156a8e1175bSopenharmony_ci#if defined(MBEDTLS_POP_IAR_LANGUAGE_PRAGMA) 157a8e1175bSopenharmony_ci#pragma language=restore 158a8e1175bSopenharmony_ci#endif 159a8e1175bSopenharmony_ci 160a8e1175bSopenharmony_ci/** Byte Reading Macros 161a8e1175bSopenharmony_ci * 162a8e1175bSopenharmony_ci * Given a multi-byte integer \p x, MBEDTLS_BYTE_n retrieves the n-th 163a8e1175bSopenharmony_ci * byte from x, where byte 0 is the least significant byte. 164a8e1175bSopenharmony_ci */ 165a8e1175bSopenharmony_ci#define MBEDTLS_BYTE_0(x) ((uint8_t) ((x) & 0xff)) 166a8e1175bSopenharmony_ci#define MBEDTLS_BYTE_1(x) ((uint8_t) (((x) >> 8) & 0xff)) 167a8e1175bSopenharmony_ci#define MBEDTLS_BYTE_2(x) ((uint8_t) (((x) >> 16) & 0xff)) 168a8e1175bSopenharmony_ci#define MBEDTLS_BYTE_3(x) ((uint8_t) (((x) >> 24) & 0xff)) 169a8e1175bSopenharmony_ci#define MBEDTLS_BYTE_4(x) ((uint8_t) (((x) >> 32) & 0xff)) 170a8e1175bSopenharmony_ci#define MBEDTLS_BYTE_5(x) ((uint8_t) (((x) >> 40) & 0xff)) 171a8e1175bSopenharmony_ci#define MBEDTLS_BYTE_6(x) ((uint8_t) (((x) >> 48) & 0xff)) 172a8e1175bSopenharmony_ci#define MBEDTLS_BYTE_7(x) ((uint8_t) (((x) >> 56) & 0xff)) 173a8e1175bSopenharmony_ci 174a8e1175bSopenharmony_ci/* 175a8e1175bSopenharmony_ci * Detect GCC built-in byteswap routines 176a8e1175bSopenharmony_ci */ 177a8e1175bSopenharmony_ci#if defined(__GNUC__) && defined(__GNUC_PREREQ) 178a8e1175bSopenharmony_ci#if __GNUC_PREREQ(4, 8) 179a8e1175bSopenharmony_ci#define MBEDTLS_BSWAP16 __builtin_bswap16 180a8e1175bSopenharmony_ci#endif /* __GNUC_PREREQ(4,8) */ 181a8e1175bSopenharmony_ci#if __GNUC_PREREQ(4, 3) 182a8e1175bSopenharmony_ci#define MBEDTLS_BSWAP32 __builtin_bswap32 183a8e1175bSopenharmony_ci#define MBEDTLS_BSWAP64 __builtin_bswap64 184a8e1175bSopenharmony_ci#endif /* __GNUC_PREREQ(4,3) */ 185a8e1175bSopenharmony_ci#endif /* defined(__GNUC__) && defined(__GNUC_PREREQ) */ 186a8e1175bSopenharmony_ci 187a8e1175bSopenharmony_ci/* 188a8e1175bSopenharmony_ci * Detect Clang built-in byteswap routines 189a8e1175bSopenharmony_ci */ 190a8e1175bSopenharmony_ci#if defined(__clang__) && defined(__has_builtin) 191a8e1175bSopenharmony_ci#if __has_builtin(__builtin_bswap16) && !defined(MBEDTLS_BSWAP16) 192a8e1175bSopenharmony_ci#define MBEDTLS_BSWAP16 __builtin_bswap16 193a8e1175bSopenharmony_ci#endif /* __has_builtin(__builtin_bswap16) */ 194a8e1175bSopenharmony_ci#if __has_builtin(__builtin_bswap32) && !defined(MBEDTLS_BSWAP32) 195a8e1175bSopenharmony_ci#define MBEDTLS_BSWAP32 __builtin_bswap32 196a8e1175bSopenharmony_ci#endif /* __has_builtin(__builtin_bswap32) */ 197a8e1175bSopenharmony_ci#if __has_builtin(__builtin_bswap64) && !defined(MBEDTLS_BSWAP64) 198a8e1175bSopenharmony_ci#define MBEDTLS_BSWAP64 __builtin_bswap64 199a8e1175bSopenharmony_ci#endif /* __has_builtin(__builtin_bswap64) */ 200a8e1175bSopenharmony_ci#endif /* defined(__clang__) && defined(__has_builtin) */ 201a8e1175bSopenharmony_ci 202a8e1175bSopenharmony_ci/* 203a8e1175bSopenharmony_ci * Detect MSVC built-in byteswap routines 204a8e1175bSopenharmony_ci */ 205a8e1175bSopenharmony_ci#if defined(_MSC_VER) 206a8e1175bSopenharmony_ci#if !defined(MBEDTLS_BSWAP16) 207a8e1175bSopenharmony_ci#define MBEDTLS_BSWAP16 _byteswap_ushort 208a8e1175bSopenharmony_ci#endif 209a8e1175bSopenharmony_ci#if !defined(MBEDTLS_BSWAP32) 210a8e1175bSopenharmony_ci#define MBEDTLS_BSWAP32 _byteswap_ulong 211a8e1175bSopenharmony_ci#endif 212a8e1175bSopenharmony_ci#if !defined(MBEDTLS_BSWAP64) 213a8e1175bSopenharmony_ci#define MBEDTLS_BSWAP64 _byteswap_uint64 214a8e1175bSopenharmony_ci#endif 215a8e1175bSopenharmony_ci#endif /* defined(_MSC_VER) */ 216a8e1175bSopenharmony_ci 217a8e1175bSopenharmony_ci/* Detect armcc built-in byteswap routine */ 218a8e1175bSopenharmony_ci#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 410000) && !defined(MBEDTLS_BSWAP32) 219a8e1175bSopenharmony_ci#if defined(__ARM_ACLE) /* ARM Compiler 6 - earlier versions don't need a header */ 220a8e1175bSopenharmony_ci#include <arm_acle.h> 221a8e1175bSopenharmony_ci#endif 222a8e1175bSopenharmony_ci#define MBEDTLS_BSWAP32 __rev 223a8e1175bSopenharmony_ci#endif 224a8e1175bSopenharmony_ci 225a8e1175bSopenharmony_ci/* Detect IAR built-in byteswap routine */ 226a8e1175bSopenharmony_ci#if defined(__IAR_SYSTEMS_ICC__) 227a8e1175bSopenharmony_ci#if defined(__ARM_ACLE) 228a8e1175bSopenharmony_ci#include <arm_acle.h> 229a8e1175bSopenharmony_ci#define MBEDTLS_BSWAP16(x) ((uint16_t) __rev16((uint32_t) (x))) 230a8e1175bSopenharmony_ci#define MBEDTLS_BSWAP32 __rev 231a8e1175bSopenharmony_ci#define MBEDTLS_BSWAP64 __revll 232a8e1175bSopenharmony_ci#endif 233a8e1175bSopenharmony_ci#endif 234a8e1175bSopenharmony_ci 235a8e1175bSopenharmony_ci/* 236a8e1175bSopenharmony_ci * Where compiler built-ins are not present, fall back to C code that the 237a8e1175bSopenharmony_ci * compiler may be able to detect and transform into the relevant bswap or 238a8e1175bSopenharmony_ci * similar instruction. 239a8e1175bSopenharmony_ci */ 240a8e1175bSopenharmony_ci#if !defined(MBEDTLS_BSWAP16) 241a8e1175bSopenharmony_cistatic inline uint16_t mbedtls_bswap16(uint16_t x) 242a8e1175bSopenharmony_ci{ 243a8e1175bSopenharmony_ci return 244a8e1175bSopenharmony_ci (x & 0x00ff) << 8 | 245a8e1175bSopenharmony_ci (x & 0xff00) >> 8; 246a8e1175bSopenharmony_ci} 247a8e1175bSopenharmony_ci#define MBEDTLS_BSWAP16 mbedtls_bswap16 248a8e1175bSopenharmony_ci#endif /* !defined(MBEDTLS_BSWAP16) */ 249a8e1175bSopenharmony_ci 250a8e1175bSopenharmony_ci#if !defined(MBEDTLS_BSWAP32) 251a8e1175bSopenharmony_cistatic inline uint32_t mbedtls_bswap32(uint32_t x) 252a8e1175bSopenharmony_ci{ 253a8e1175bSopenharmony_ci return 254a8e1175bSopenharmony_ci (x & 0x000000ff) << 24 | 255a8e1175bSopenharmony_ci (x & 0x0000ff00) << 8 | 256a8e1175bSopenharmony_ci (x & 0x00ff0000) >> 8 | 257a8e1175bSopenharmony_ci (x & 0xff000000) >> 24; 258a8e1175bSopenharmony_ci} 259a8e1175bSopenharmony_ci#define MBEDTLS_BSWAP32 mbedtls_bswap32 260a8e1175bSopenharmony_ci#endif /* !defined(MBEDTLS_BSWAP32) */ 261a8e1175bSopenharmony_ci 262a8e1175bSopenharmony_ci#if !defined(MBEDTLS_BSWAP64) 263a8e1175bSopenharmony_cistatic inline uint64_t mbedtls_bswap64(uint64_t x) 264a8e1175bSopenharmony_ci{ 265a8e1175bSopenharmony_ci return 266a8e1175bSopenharmony_ci (x & 0x00000000000000ffULL) << 56 | 267a8e1175bSopenharmony_ci (x & 0x000000000000ff00ULL) << 40 | 268a8e1175bSopenharmony_ci (x & 0x0000000000ff0000ULL) << 24 | 269a8e1175bSopenharmony_ci (x & 0x00000000ff000000ULL) << 8 | 270a8e1175bSopenharmony_ci (x & 0x000000ff00000000ULL) >> 8 | 271a8e1175bSopenharmony_ci (x & 0x0000ff0000000000ULL) >> 24 | 272a8e1175bSopenharmony_ci (x & 0x00ff000000000000ULL) >> 40 | 273a8e1175bSopenharmony_ci (x & 0xff00000000000000ULL) >> 56; 274a8e1175bSopenharmony_ci} 275a8e1175bSopenharmony_ci#define MBEDTLS_BSWAP64 mbedtls_bswap64 276a8e1175bSopenharmony_ci#endif /* !defined(MBEDTLS_BSWAP64) */ 277a8e1175bSopenharmony_ci 278a8e1175bSopenharmony_ci#if !defined(__BYTE_ORDER__) 279a8e1175bSopenharmony_ci 280a8e1175bSopenharmony_ci#if defined(__LITTLE_ENDIAN__) 281a8e1175bSopenharmony_ci/* IAR defines __xxx_ENDIAN__, but not __BYTE_ORDER__ */ 282a8e1175bSopenharmony_ci#define MBEDTLS_IS_BIG_ENDIAN 0 283a8e1175bSopenharmony_ci#elif defined(__BIG_ENDIAN__) 284a8e1175bSopenharmony_ci#define MBEDTLS_IS_BIG_ENDIAN 1 285a8e1175bSopenharmony_ci#else 286a8e1175bSopenharmony_cistatic const uint16_t mbedtls_byte_order_detector = { 0x100 }; 287a8e1175bSopenharmony_ci#define MBEDTLS_IS_BIG_ENDIAN (*((unsigned char *) (&mbedtls_byte_order_detector)) == 0x01) 288a8e1175bSopenharmony_ci#endif 289a8e1175bSopenharmony_ci 290a8e1175bSopenharmony_ci#else 291a8e1175bSopenharmony_ci 292a8e1175bSopenharmony_ci#if (__BYTE_ORDER__) == (__ORDER_BIG_ENDIAN__) 293a8e1175bSopenharmony_ci#define MBEDTLS_IS_BIG_ENDIAN 1 294a8e1175bSopenharmony_ci#else 295a8e1175bSopenharmony_ci#define MBEDTLS_IS_BIG_ENDIAN 0 296a8e1175bSopenharmony_ci#endif 297a8e1175bSopenharmony_ci 298a8e1175bSopenharmony_ci#endif /* !defined(__BYTE_ORDER__) */ 299a8e1175bSopenharmony_ci 300a8e1175bSopenharmony_ci/** 301a8e1175bSopenharmony_ci * Get the unsigned 32 bits integer corresponding to four bytes in 302a8e1175bSopenharmony_ci * big-endian order (MSB first). 303a8e1175bSopenharmony_ci * 304a8e1175bSopenharmony_ci * \param data Base address of the memory to get the four bytes from. 305a8e1175bSopenharmony_ci * \param offset Offset from \p data of the first and most significant 306a8e1175bSopenharmony_ci * byte of the four bytes to build the 32 bits unsigned 307a8e1175bSopenharmony_ci * integer from. 308a8e1175bSopenharmony_ci */ 309a8e1175bSopenharmony_ci#define MBEDTLS_GET_UINT32_BE(data, offset) \ 310a8e1175bSopenharmony_ci ((MBEDTLS_IS_BIG_ENDIAN) \ 311a8e1175bSopenharmony_ci ? mbedtls_get_unaligned_uint32((data) + (offset)) \ 312a8e1175bSopenharmony_ci : MBEDTLS_BSWAP32(mbedtls_get_unaligned_uint32((data) + (offset))) \ 313a8e1175bSopenharmony_ci ) 314a8e1175bSopenharmony_ci 315a8e1175bSopenharmony_ci/** 316a8e1175bSopenharmony_ci * Put in memory a 32 bits unsigned integer in big-endian order. 317a8e1175bSopenharmony_ci * 318a8e1175bSopenharmony_ci * \param n 32 bits unsigned integer to put in memory. 319a8e1175bSopenharmony_ci * \param data Base address of the memory where to put the 32 320a8e1175bSopenharmony_ci * bits unsigned integer in. 321a8e1175bSopenharmony_ci * \param offset Offset from \p data where to put the most significant 322a8e1175bSopenharmony_ci * byte of the 32 bits unsigned integer \p n. 323a8e1175bSopenharmony_ci */ 324a8e1175bSopenharmony_ci#define MBEDTLS_PUT_UINT32_BE(n, data, offset) \ 325a8e1175bSopenharmony_ci { \ 326a8e1175bSopenharmony_ci if (MBEDTLS_IS_BIG_ENDIAN) \ 327a8e1175bSopenharmony_ci { \ 328a8e1175bSopenharmony_ci mbedtls_put_unaligned_uint32((data) + (offset), (uint32_t) (n)); \ 329a8e1175bSopenharmony_ci } \ 330a8e1175bSopenharmony_ci else \ 331a8e1175bSopenharmony_ci { \ 332a8e1175bSopenharmony_ci mbedtls_put_unaligned_uint32((data) + (offset), MBEDTLS_BSWAP32((uint32_t) (n))); \ 333a8e1175bSopenharmony_ci } \ 334a8e1175bSopenharmony_ci } 335a8e1175bSopenharmony_ci 336a8e1175bSopenharmony_ci/** 337a8e1175bSopenharmony_ci * Get the unsigned 32 bits integer corresponding to four bytes in 338a8e1175bSopenharmony_ci * little-endian order (LSB first). 339a8e1175bSopenharmony_ci * 340a8e1175bSopenharmony_ci * \param data Base address of the memory to get the four bytes from. 341a8e1175bSopenharmony_ci * \param offset Offset from \p data of the first and least significant 342a8e1175bSopenharmony_ci * byte of the four bytes to build the 32 bits unsigned 343a8e1175bSopenharmony_ci * integer from. 344a8e1175bSopenharmony_ci */ 345a8e1175bSopenharmony_ci#define MBEDTLS_GET_UINT32_LE(data, offset) \ 346a8e1175bSopenharmony_ci ((MBEDTLS_IS_BIG_ENDIAN) \ 347a8e1175bSopenharmony_ci ? MBEDTLS_BSWAP32(mbedtls_get_unaligned_uint32((data) + (offset))) \ 348a8e1175bSopenharmony_ci : mbedtls_get_unaligned_uint32((data) + (offset)) \ 349a8e1175bSopenharmony_ci ) 350a8e1175bSopenharmony_ci 351a8e1175bSopenharmony_ci 352a8e1175bSopenharmony_ci/** 353a8e1175bSopenharmony_ci * Put in memory a 32 bits unsigned integer in little-endian order. 354a8e1175bSopenharmony_ci * 355a8e1175bSopenharmony_ci * \param n 32 bits unsigned integer to put in memory. 356a8e1175bSopenharmony_ci * \param data Base address of the memory where to put the 32 357a8e1175bSopenharmony_ci * bits unsigned integer in. 358a8e1175bSopenharmony_ci * \param offset Offset from \p data where to put the least significant 359a8e1175bSopenharmony_ci * byte of the 32 bits unsigned integer \p n. 360a8e1175bSopenharmony_ci */ 361a8e1175bSopenharmony_ci#define MBEDTLS_PUT_UINT32_LE(n, data, offset) \ 362a8e1175bSopenharmony_ci { \ 363a8e1175bSopenharmony_ci if (MBEDTLS_IS_BIG_ENDIAN) \ 364a8e1175bSopenharmony_ci { \ 365a8e1175bSopenharmony_ci mbedtls_put_unaligned_uint32((data) + (offset), MBEDTLS_BSWAP32((uint32_t) (n))); \ 366a8e1175bSopenharmony_ci } \ 367a8e1175bSopenharmony_ci else \ 368a8e1175bSopenharmony_ci { \ 369a8e1175bSopenharmony_ci mbedtls_put_unaligned_uint32((data) + (offset), ((uint32_t) (n))); \ 370a8e1175bSopenharmony_ci } \ 371a8e1175bSopenharmony_ci } 372a8e1175bSopenharmony_ci 373a8e1175bSopenharmony_ci/** 374a8e1175bSopenharmony_ci * Get the unsigned 16 bits integer corresponding to two bytes in 375a8e1175bSopenharmony_ci * little-endian order (LSB first). 376a8e1175bSopenharmony_ci * 377a8e1175bSopenharmony_ci * \param data Base address of the memory to get the two bytes from. 378a8e1175bSopenharmony_ci * \param offset Offset from \p data of the first and least significant 379a8e1175bSopenharmony_ci * byte of the two bytes to build the 16 bits unsigned 380a8e1175bSopenharmony_ci * integer from. 381a8e1175bSopenharmony_ci */ 382a8e1175bSopenharmony_ci#define MBEDTLS_GET_UINT16_LE(data, offset) \ 383a8e1175bSopenharmony_ci ((MBEDTLS_IS_BIG_ENDIAN) \ 384a8e1175bSopenharmony_ci ? MBEDTLS_BSWAP16(mbedtls_get_unaligned_uint16((data) + (offset))) \ 385a8e1175bSopenharmony_ci : mbedtls_get_unaligned_uint16((data) + (offset)) \ 386a8e1175bSopenharmony_ci ) 387a8e1175bSopenharmony_ci 388a8e1175bSopenharmony_ci/** 389a8e1175bSopenharmony_ci * Put in memory a 16 bits unsigned integer in little-endian order. 390a8e1175bSopenharmony_ci * 391a8e1175bSopenharmony_ci * \param n 16 bits unsigned integer to put in memory. 392a8e1175bSopenharmony_ci * \param data Base address of the memory where to put the 16 393a8e1175bSopenharmony_ci * bits unsigned integer in. 394a8e1175bSopenharmony_ci * \param offset Offset from \p data where to put the least significant 395a8e1175bSopenharmony_ci * byte of the 16 bits unsigned integer \p n. 396a8e1175bSopenharmony_ci */ 397a8e1175bSopenharmony_ci#define MBEDTLS_PUT_UINT16_LE(n, data, offset) \ 398a8e1175bSopenharmony_ci { \ 399a8e1175bSopenharmony_ci if (MBEDTLS_IS_BIG_ENDIAN) \ 400a8e1175bSopenharmony_ci { \ 401a8e1175bSopenharmony_ci mbedtls_put_unaligned_uint16((data) + (offset), MBEDTLS_BSWAP16((uint16_t) (n))); \ 402a8e1175bSopenharmony_ci } \ 403a8e1175bSopenharmony_ci else \ 404a8e1175bSopenharmony_ci { \ 405a8e1175bSopenharmony_ci mbedtls_put_unaligned_uint16((data) + (offset), (uint16_t) (n)); \ 406a8e1175bSopenharmony_ci } \ 407a8e1175bSopenharmony_ci } 408a8e1175bSopenharmony_ci 409a8e1175bSopenharmony_ci/** 410a8e1175bSopenharmony_ci * Get the unsigned 16 bits integer corresponding to two bytes in 411a8e1175bSopenharmony_ci * big-endian order (MSB first). 412a8e1175bSopenharmony_ci * 413a8e1175bSopenharmony_ci * \param data Base address of the memory to get the two bytes from. 414a8e1175bSopenharmony_ci * \param offset Offset from \p data of the first and most significant 415a8e1175bSopenharmony_ci * byte of the two bytes to build the 16 bits unsigned 416a8e1175bSopenharmony_ci * integer from. 417a8e1175bSopenharmony_ci */ 418a8e1175bSopenharmony_ci#define MBEDTLS_GET_UINT16_BE(data, offset) \ 419a8e1175bSopenharmony_ci ((MBEDTLS_IS_BIG_ENDIAN) \ 420a8e1175bSopenharmony_ci ? mbedtls_get_unaligned_uint16((data) + (offset)) \ 421a8e1175bSopenharmony_ci : MBEDTLS_BSWAP16(mbedtls_get_unaligned_uint16((data) + (offset))) \ 422a8e1175bSopenharmony_ci ) 423a8e1175bSopenharmony_ci 424a8e1175bSopenharmony_ci/** 425a8e1175bSopenharmony_ci * Put in memory a 16 bits unsigned integer in big-endian order. 426a8e1175bSopenharmony_ci * 427a8e1175bSopenharmony_ci * \param n 16 bits unsigned integer to put in memory. 428a8e1175bSopenharmony_ci * \param data Base address of the memory where to put the 16 429a8e1175bSopenharmony_ci * bits unsigned integer in. 430a8e1175bSopenharmony_ci * \param offset Offset from \p data where to put the most significant 431a8e1175bSopenharmony_ci * byte of the 16 bits unsigned integer \p n. 432a8e1175bSopenharmony_ci */ 433a8e1175bSopenharmony_ci#define MBEDTLS_PUT_UINT16_BE(n, data, offset) \ 434a8e1175bSopenharmony_ci { \ 435a8e1175bSopenharmony_ci if (MBEDTLS_IS_BIG_ENDIAN) \ 436a8e1175bSopenharmony_ci { \ 437a8e1175bSopenharmony_ci mbedtls_put_unaligned_uint16((data) + (offset), (uint16_t) (n)); \ 438a8e1175bSopenharmony_ci } \ 439a8e1175bSopenharmony_ci else \ 440a8e1175bSopenharmony_ci { \ 441a8e1175bSopenharmony_ci mbedtls_put_unaligned_uint16((data) + (offset), MBEDTLS_BSWAP16((uint16_t) (n))); \ 442a8e1175bSopenharmony_ci } \ 443a8e1175bSopenharmony_ci } 444a8e1175bSopenharmony_ci 445a8e1175bSopenharmony_ci/** 446a8e1175bSopenharmony_ci * Get the unsigned 24 bits integer corresponding to three bytes in 447a8e1175bSopenharmony_ci * big-endian order (MSB first). 448a8e1175bSopenharmony_ci * 449a8e1175bSopenharmony_ci * \param data Base address of the memory to get the three bytes from. 450a8e1175bSopenharmony_ci * \param offset Offset from \p data of the first and most significant 451a8e1175bSopenharmony_ci * byte of the three bytes to build the 24 bits unsigned 452a8e1175bSopenharmony_ci * integer from. 453a8e1175bSopenharmony_ci */ 454a8e1175bSopenharmony_ci#define MBEDTLS_GET_UINT24_BE(data, offset) \ 455a8e1175bSopenharmony_ci ( \ 456a8e1175bSopenharmony_ci ((uint32_t) (data)[(offset)] << 16) \ 457a8e1175bSopenharmony_ci | ((uint32_t) (data)[(offset) + 1] << 8) \ 458a8e1175bSopenharmony_ci | ((uint32_t) (data)[(offset) + 2]) \ 459a8e1175bSopenharmony_ci ) 460a8e1175bSopenharmony_ci 461a8e1175bSopenharmony_ci/** 462a8e1175bSopenharmony_ci * Put in memory a 24 bits unsigned integer in big-endian order. 463a8e1175bSopenharmony_ci * 464a8e1175bSopenharmony_ci * \param n 24 bits unsigned integer to put in memory. 465a8e1175bSopenharmony_ci * \param data Base address of the memory where to put the 24 466a8e1175bSopenharmony_ci * bits unsigned integer in. 467a8e1175bSopenharmony_ci * \param offset Offset from \p data where to put the most significant 468a8e1175bSopenharmony_ci * byte of the 24 bits unsigned integer \p n. 469a8e1175bSopenharmony_ci */ 470a8e1175bSopenharmony_ci#define MBEDTLS_PUT_UINT24_BE(n, data, offset) \ 471a8e1175bSopenharmony_ci { \ 472a8e1175bSopenharmony_ci (data)[(offset)] = MBEDTLS_BYTE_2(n); \ 473a8e1175bSopenharmony_ci (data)[(offset) + 1] = MBEDTLS_BYTE_1(n); \ 474a8e1175bSopenharmony_ci (data)[(offset) + 2] = MBEDTLS_BYTE_0(n); \ 475a8e1175bSopenharmony_ci } 476a8e1175bSopenharmony_ci 477a8e1175bSopenharmony_ci/** 478a8e1175bSopenharmony_ci * Get the unsigned 24 bits integer corresponding to three bytes in 479a8e1175bSopenharmony_ci * little-endian order (LSB first). 480a8e1175bSopenharmony_ci * 481a8e1175bSopenharmony_ci * \param data Base address of the memory to get the three bytes from. 482a8e1175bSopenharmony_ci * \param offset Offset from \p data of the first and least significant 483a8e1175bSopenharmony_ci * byte of the three bytes to build the 24 bits unsigned 484a8e1175bSopenharmony_ci * integer from. 485a8e1175bSopenharmony_ci */ 486a8e1175bSopenharmony_ci#define MBEDTLS_GET_UINT24_LE(data, offset) \ 487a8e1175bSopenharmony_ci ( \ 488a8e1175bSopenharmony_ci ((uint32_t) (data)[(offset)]) \ 489a8e1175bSopenharmony_ci | ((uint32_t) (data)[(offset) + 1] << 8) \ 490a8e1175bSopenharmony_ci | ((uint32_t) (data)[(offset) + 2] << 16) \ 491a8e1175bSopenharmony_ci ) 492a8e1175bSopenharmony_ci 493a8e1175bSopenharmony_ci/** 494a8e1175bSopenharmony_ci * Put in memory a 24 bits unsigned integer in little-endian order. 495a8e1175bSopenharmony_ci * 496a8e1175bSopenharmony_ci * \param n 24 bits unsigned integer to put in memory. 497a8e1175bSopenharmony_ci * \param data Base address of the memory where to put the 24 498a8e1175bSopenharmony_ci * bits unsigned integer in. 499a8e1175bSopenharmony_ci * \param offset Offset from \p data where to put the least significant 500a8e1175bSopenharmony_ci * byte of the 24 bits unsigned integer \p n. 501a8e1175bSopenharmony_ci */ 502a8e1175bSopenharmony_ci#define MBEDTLS_PUT_UINT24_LE(n, data, offset) \ 503a8e1175bSopenharmony_ci { \ 504a8e1175bSopenharmony_ci (data)[(offset)] = MBEDTLS_BYTE_0(n); \ 505a8e1175bSopenharmony_ci (data)[(offset) + 1] = MBEDTLS_BYTE_1(n); \ 506a8e1175bSopenharmony_ci (data)[(offset) + 2] = MBEDTLS_BYTE_2(n); \ 507a8e1175bSopenharmony_ci } 508a8e1175bSopenharmony_ci 509a8e1175bSopenharmony_ci/** 510a8e1175bSopenharmony_ci * Get the unsigned 64 bits integer corresponding to eight bytes in 511a8e1175bSopenharmony_ci * big-endian order (MSB first). 512a8e1175bSopenharmony_ci * 513a8e1175bSopenharmony_ci * \param data Base address of the memory to get the eight bytes from. 514a8e1175bSopenharmony_ci * \param offset Offset from \p data of the first and most significant 515a8e1175bSopenharmony_ci * byte of the eight bytes to build the 64 bits unsigned 516a8e1175bSopenharmony_ci * integer from. 517a8e1175bSopenharmony_ci */ 518a8e1175bSopenharmony_ci#define MBEDTLS_GET_UINT64_BE(data, offset) \ 519a8e1175bSopenharmony_ci ((MBEDTLS_IS_BIG_ENDIAN) \ 520a8e1175bSopenharmony_ci ? mbedtls_get_unaligned_uint64((data) + (offset)) \ 521a8e1175bSopenharmony_ci : MBEDTLS_BSWAP64(mbedtls_get_unaligned_uint64((data) + (offset))) \ 522a8e1175bSopenharmony_ci ) 523a8e1175bSopenharmony_ci 524a8e1175bSopenharmony_ci/** 525a8e1175bSopenharmony_ci * Put in memory a 64 bits unsigned integer in big-endian order. 526a8e1175bSopenharmony_ci * 527a8e1175bSopenharmony_ci * \param n 64 bits unsigned integer to put in memory. 528a8e1175bSopenharmony_ci * \param data Base address of the memory where to put the 64 529a8e1175bSopenharmony_ci * bits unsigned integer in. 530a8e1175bSopenharmony_ci * \param offset Offset from \p data where to put the most significant 531a8e1175bSopenharmony_ci * byte of the 64 bits unsigned integer \p n. 532a8e1175bSopenharmony_ci */ 533a8e1175bSopenharmony_ci#define MBEDTLS_PUT_UINT64_BE(n, data, offset) \ 534a8e1175bSopenharmony_ci { \ 535a8e1175bSopenharmony_ci if (MBEDTLS_IS_BIG_ENDIAN) \ 536a8e1175bSopenharmony_ci { \ 537a8e1175bSopenharmony_ci mbedtls_put_unaligned_uint64((data) + (offset), (uint64_t) (n)); \ 538a8e1175bSopenharmony_ci } \ 539a8e1175bSopenharmony_ci else \ 540a8e1175bSopenharmony_ci { \ 541a8e1175bSopenharmony_ci mbedtls_put_unaligned_uint64((data) + (offset), MBEDTLS_BSWAP64((uint64_t) (n))); \ 542a8e1175bSopenharmony_ci } \ 543a8e1175bSopenharmony_ci } 544a8e1175bSopenharmony_ci 545a8e1175bSopenharmony_ci/** 546a8e1175bSopenharmony_ci * Get the unsigned 64 bits integer corresponding to eight bytes in 547a8e1175bSopenharmony_ci * little-endian order (LSB first). 548a8e1175bSopenharmony_ci * 549a8e1175bSopenharmony_ci * \param data Base address of the memory to get the eight bytes from. 550a8e1175bSopenharmony_ci * \param offset Offset from \p data of the first and least significant 551a8e1175bSopenharmony_ci * byte of the eight bytes to build the 64 bits unsigned 552a8e1175bSopenharmony_ci * integer from. 553a8e1175bSopenharmony_ci */ 554a8e1175bSopenharmony_ci#define MBEDTLS_GET_UINT64_LE(data, offset) \ 555a8e1175bSopenharmony_ci ((MBEDTLS_IS_BIG_ENDIAN) \ 556a8e1175bSopenharmony_ci ? MBEDTLS_BSWAP64(mbedtls_get_unaligned_uint64((data) + (offset))) \ 557a8e1175bSopenharmony_ci : mbedtls_get_unaligned_uint64((data) + (offset)) \ 558a8e1175bSopenharmony_ci ) 559a8e1175bSopenharmony_ci 560a8e1175bSopenharmony_ci/** 561a8e1175bSopenharmony_ci * Put in memory a 64 bits unsigned integer in little-endian order. 562a8e1175bSopenharmony_ci * 563a8e1175bSopenharmony_ci * \param n 64 bits unsigned integer to put in memory. 564a8e1175bSopenharmony_ci * \param data Base address of the memory where to put the 64 565a8e1175bSopenharmony_ci * bits unsigned integer in. 566a8e1175bSopenharmony_ci * \param offset Offset from \p data where to put the least significant 567a8e1175bSopenharmony_ci * byte of the 64 bits unsigned integer \p n. 568a8e1175bSopenharmony_ci */ 569a8e1175bSopenharmony_ci#define MBEDTLS_PUT_UINT64_LE(n, data, offset) \ 570a8e1175bSopenharmony_ci { \ 571a8e1175bSopenharmony_ci if (MBEDTLS_IS_BIG_ENDIAN) \ 572a8e1175bSopenharmony_ci { \ 573a8e1175bSopenharmony_ci mbedtls_put_unaligned_uint64((data) + (offset), MBEDTLS_BSWAP64((uint64_t) (n))); \ 574a8e1175bSopenharmony_ci } \ 575a8e1175bSopenharmony_ci else \ 576a8e1175bSopenharmony_ci { \ 577a8e1175bSopenharmony_ci mbedtls_put_unaligned_uint64((data) + (offset), (uint64_t) (n)); \ 578a8e1175bSopenharmony_ci } \ 579a8e1175bSopenharmony_ci } 580a8e1175bSopenharmony_ci 581a8e1175bSopenharmony_ci#endif /* MBEDTLS_LIBRARY_ALIGNMENT_H */ 582