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