blob: 9e1e044ec634c7eded0ca8fa8b31fd6e67acf11e [file] [log] [blame]
Dave Rodgmanfbc23222022-11-24 18:07:37 +00001/**
2 * \file alignment.h
3 *
4 * \brief Utility code for dealing with unaligned memory accesses
5 */
6/*
7 * Copyright The Mbed TLS Contributors
Dave Rodgman16799db2023-11-02 19:47:20 +00008 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
Dave Rodgmanfbc23222022-11-24 18:07:37 +00009 */
10
11#ifndef MBEDTLS_LIBRARY_ALIGNMENT_H
12#define MBEDTLS_LIBRARY_ALIGNMENT_H
13
14#include <stdint.h>
Dave Rodgman96d61d12022-11-24 19:33:22 +000015#include <string.h>
Dave Rodgmanf7f1f742022-11-28 14:52:45 +000016#include <stdlib.h>
Dave Rodgmanfbc23222022-11-24 18:07:37 +000017
Dave Rodgmanb9cd19b2022-12-30 21:32:03 +000018/*
19 * Define MBEDTLS_EFFICIENT_UNALIGNED_ACCESS for architectures where unaligned memory
Dave Rodgman7f376fa2023-01-05 12:25:15 +000020 * accesses are known to be efficient.
21 *
22 * All functions defined here will behave correctly regardless, but might be less
23 * efficient when this is not defined.
Dave Rodgmanb9cd19b2022-12-30 21:32:03 +000024 */
25#if defined(__ARM_FEATURE_UNALIGNED) \
Dave Rodgmanc5cc7272023-09-15 11:41:17 +010026 || defined(MBEDTLS_ARCH_IS_X86) || defined(MBEDTLS_ARCH_IS_X64) \
Dave Rodgman0a487172023-09-15 11:52:06 +010027 || defined(MBEDTLS_PLATFORM_IS_WINDOWS_ON_ARM64)
Dave Rodgmanb9cd19b2022-12-30 21:32:03 +000028/*
29 * __ARM_FEATURE_UNALIGNED is defined where appropriate by armcc, gcc 7, clang 9
Dave Rodgman7f376fa2023-01-05 12:25:15 +000030 * (and later versions) for Arm v7 and later; all x86 platforms should have
31 * efficient unaligned access.
Dave Rodgman78fc0bd2023-08-08 10:36:15 +010032 *
33 * https://learn.microsoft.com/en-us/cpp/build/arm64-windows-abi-conventions?view=msvc-170#alignment
34 * specifies that on Windows-on-Arm64, unaligned access is safe (except for uncached
35 * device memory).
Dave Rodgmanb9cd19b2022-12-30 21:32:03 +000036 */
37#define MBEDTLS_EFFICIENT_UNALIGNED_ACCESS
38#endif
39
Dave Rodgman96d61d12022-11-24 19:33:22 +000040/**
Dave Rodgmana360e192022-11-28 14:44:05 +000041 * Read the unsigned 16 bits integer from the given address, which need not
42 * be aligned.
43 *
44 * \param p pointer to 2 bytes of data
45 * \return Data at the given address
46 */
Gilles Peskine449bd832023-01-11 14:50:10 +010047inline uint16_t mbedtls_get_unaligned_uint16(const void *p)
Dave Rodgmana360e192022-11-28 14:44:05 +000048{
49 uint16_t r;
Gilles Peskine449bd832023-01-11 14:50:10 +010050 memcpy(&r, p, sizeof(r));
Dave Rodgmana360e192022-11-28 14:44:05 +000051 return r;
52}
53
54/**
55 * Write the unsigned 16 bits integer to the given address, which need not
56 * be aligned.
57 *
58 * \param p pointer to 2 bytes of data
59 * \param x data to write
60 */
Gilles Peskine449bd832023-01-11 14:50:10 +010061inline void mbedtls_put_unaligned_uint16(void *p, uint16_t x)
Dave Rodgmana360e192022-11-28 14:44:05 +000062{
Gilles Peskine449bd832023-01-11 14:50:10 +010063 memcpy(p, &x, sizeof(x));
Dave Rodgmana360e192022-11-28 14:44:05 +000064}
65
66/**
Dave Rodgman96d61d12022-11-24 19:33:22 +000067 * Read the unsigned 32 bits integer from the given address, which need not
68 * be aligned.
Dave Rodgmanfbc23222022-11-24 18:07:37 +000069 *
Dave Rodgman96d61d12022-11-24 19:33:22 +000070 * \param p pointer to 4 bytes of data
Dave Rodgman875d2382022-11-24 20:43:15 +000071 * \return Data at the given address
Dave Rodgmanfbc23222022-11-24 18:07:37 +000072 */
Gilles Peskine449bd832023-01-11 14:50:10 +010073inline uint32_t mbedtls_get_unaligned_uint32(const void *p)
Dave Rodgman96d61d12022-11-24 19:33:22 +000074{
75 uint32_t r;
Gilles Peskine449bd832023-01-11 14:50:10 +010076 memcpy(&r, p, sizeof(r));
Dave Rodgman96d61d12022-11-24 19:33:22 +000077 return r;
78}
Dave Rodgmanfbc23222022-11-24 18:07:37 +000079
Dave Rodgman96d61d12022-11-24 19:33:22 +000080/**
81 * Write the unsigned 32 bits integer to the given address, which need not
82 * be aligned.
83 *
84 * \param p pointer to 4 bytes of data
85 * \param x data to write
86 */
Gilles Peskine449bd832023-01-11 14:50:10 +010087inline void mbedtls_put_unaligned_uint32(void *p, uint32_t x)
Dave Rodgman96d61d12022-11-24 19:33:22 +000088{
Gilles Peskine449bd832023-01-11 14:50:10 +010089 memcpy(p, &x, sizeof(x));
Dave Rodgman96d61d12022-11-24 19:33:22 +000090}
Dave Rodgmanfbc23222022-11-24 18:07:37 +000091
Dave Rodgmana360e192022-11-28 14:44:05 +000092/**
93 * Read the unsigned 64 bits integer from the given address, which need not
94 * be aligned.
95 *
96 * \param p pointer to 8 bytes of data
97 * \return Data at the given address
98 */
Gilles Peskine449bd832023-01-11 14:50:10 +010099inline uint64_t mbedtls_get_unaligned_uint64(const void *p)
Dave Rodgmana360e192022-11-28 14:44:05 +0000100{
101 uint64_t r;
Gilles Peskine449bd832023-01-11 14:50:10 +0100102 memcpy(&r, p, sizeof(r));
Dave Rodgmana360e192022-11-28 14:44:05 +0000103 return r;
104}
105
106/**
107 * Write the unsigned 64 bits integer to the given address, which need not
108 * be aligned.
109 *
110 * \param p pointer to 8 bytes of data
111 * \param x data to write
112 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100113inline void mbedtls_put_unaligned_uint64(void *p, uint64_t x)
Dave Rodgmana360e192022-11-28 14:44:05 +0000114{
Gilles Peskine449bd832023-01-11 14:50:10 +0100115 memcpy(p, &x, sizeof(x));
Dave Rodgmana360e192022-11-28 14:44:05 +0000116}
117
Dave Rodgmanfbc23222022-11-24 18:07:37 +0000118/** Byte Reading Macros
119 *
120 * Given a multi-byte integer \p x, MBEDTLS_BYTE_n retrieves the n-th
121 * byte from x, where byte 0 is the least significant byte.
122 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100123#define MBEDTLS_BYTE_0(x) ((uint8_t) ((x) & 0xff))
Dave Rodgman914c6322023-03-01 09:30:14 +0000124#define MBEDTLS_BYTE_1(x) ((uint8_t) (((x) >> 8) & 0xff))
Gilles Peskine449bd832023-01-11 14:50:10 +0100125#define MBEDTLS_BYTE_2(x) ((uint8_t) (((x) >> 16) & 0xff))
126#define MBEDTLS_BYTE_3(x) ((uint8_t) (((x) >> 24) & 0xff))
127#define MBEDTLS_BYTE_4(x) ((uint8_t) (((x) >> 32) & 0xff))
128#define MBEDTLS_BYTE_5(x) ((uint8_t) (((x) >> 40) & 0xff))
129#define MBEDTLS_BYTE_6(x) ((uint8_t) (((x) >> 48) & 0xff))
130#define MBEDTLS_BYTE_7(x) ((uint8_t) (((x) >> 56) & 0xff))
Dave Rodgmanfbc23222022-11-24 18:07:37 +0000131
Dave Rodgmanf7f1f742022-11-28 14:52:45 +0000132/*
133 * Detect GCC built-in byteswap routines
134 */
135#if defined(__GNUC__) && defined(__GNUC_PREREQ)
Gilles Peskine449bd832023-01-11 14:50:10 +0100136#if __GNUC_PREREQ(4, 8)
Dave Rodgmanf7f1f742022-11-28 14:52:45 +0000137#define MBEDTLS_BSWAP16 __builtin_bswap16
138#endif /* __GNUC_PREREQ(4,8) */
Gilles Peskine449bd832023-01-11 14:50:10 +0100139#if __GNUC_PREREQ(4, 3)
Dave Rodgmanf7f1f742022-11-28 14:52:45 +0000140#define MBEDTLS_BSWAP32 __builtin_bswap32
141#define MBEDTLS_BSWAP64 __builtin_bswap64
142#endif /* __GNUC_PREREQ(4,3) */
143#endif /* defined(__GNUC__) && defined(__GNUC_PREREQ) */
144
145/*
146 * Detect Clang built-in byteswap routines
147 */
148#if defined(__clang__) && defined(__has_builtin)
Dave Rodgmane47899d2023-02-28 17:39:03 +0000149#if __has_builtin(__builtin_bswap16) && !defined(MBEDTLS_BSWAP16)
Dave Rodgmanf7f1f742022-11-28 14:52:45 +0000150#define MBEDTLS_BSWAP16 __builtin_bswap16
151#endif /* __has_builtin(__builtin_bswap16) */
Dave Rodgmane47899d2023-02-28 17:39:03 +0000152#if __has_builtin(__builtin_bswap32) && !defined(MBEDTLS_BSWAP32)
Dave Rodgmanf7f1f742022-11-28 14:52:45 +0000153#define MBEDTLS_BSWAP32 __builtin_bswap32
154#endif /* __has_builtin(__builtin_bswap32) */
Dave Rodgmane47899d2023-02-28 17:39:03 +0000155#if __has_builtin(__builtin_bswap64) && !defined(MBEDTLS_BSWAP64)
Dave Rodgmanf7f1f742022-11-28 14:52:45 +0000156#define MBEDTLS_BSWAP64 __builtin_bswap64
157#endif /* __has_builtin(__builtin_bswap64) */
158#endif /* defined(__clang__) && defined(__has_builtin) */
159
160/*
161 * Detect MSVC built-in byteswap routines
162 */
163#if defined(_MSC_VER)
Dave Rodgmane47899d2023-02-28 17:39:03 +0000164#if !defined(MBEDTLS_BSWAP16)
Dave Rodgmanf7f1f742022-11-28 14:52:45 +0000165#define MBEDTLS_BSWAP16 _byteswap_ushort
Dave Rodgmane47899d2023-02-28 17:39:03 +0000166#endif
167#if !defined(MBEDTLS_BSWAP32)
Dave Rodgmanf7f1f742022-11-28 14:52:45 +0000168#define MBEDTLS_BSWAP32 _byteswap_ulong
Dave Rodgmane47899d2023-02-28 17:39:03 +0000169#endif
170#if !defined(MBEDTLS_BSWAP64)
Dave Rodgmanf7f1f742022-11-28 14:52:45 +0000171#define MBEDTLS_BSWAP64 _byteswap_uint64
Dave Rodgmane47899d2023-02-28 17:39:03 +0000172#endif
Dave Rodgmanf7f1f742022-11-28 14:52:45 +0000173#endif /* defined(_MSC_VER) */
174
Dave Rodgman2dae4b32022-11-30 12:07:36 +0000175/* Detect armcc built-in byteswap routine */
Dave Rodgmane47899d2023-02-28 17:39:03 +0000176#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 410000) && !defined(MBEDTLS_BSWAP32)
Tom Cosgrovef2b5a132023-04-26 17:00:12 +0100177#if defined(__ARM_ACLE) /* ARM Compiler 6 - earlier versions don't need a header */
178#include <arm_acle.h>
179#endif
Dave Rodgman2dae4b32022-11-30 12:07:36 +0000180#define MBEDTLS_BSWAP32 __rev
181#endif
182
Dave Rodgman650674b2023-12-05 12:16:48 +0000183/* Detect IAR built-in byteswap routine */
184#if defined(__IAR_SYSTEMS_ICC__)
185#if defined(__ARM_ACLE)
186#include <arm_acle.h>
187#define MBEDTLS_BSWAP16(x) ((uint16_t) __rev16((uint32_t) (x)))
188#define MBEDTLS_BSWAP32 __rev
189#define MBEDTLS_BSWAP64 __revll
190#endif
191#endif
192
Dave Rodgmanf7f1f742022-11-28 14:52:45 +0000193/*
194 * Where compiler built-ins are not present, fall back to C code that the
195 * compiler may be able to detect and transform into the relevant bswap or
196 * similar instruction.
197 */
198#if !defined(MBEDTLS_BSWAP16)
Gilles Peskine449bd832023-01-11 14:50:10 +0100199static inline uint16_t mbedtls_bswap16(uint16_t x)
200{
Dave Rodgman6298b242022-11-28 14:51:49 +0000201 return
Gilles Peskine449bd832023-01-11 14:50:10 +0100202 (x & 0x00ff) << 8 |
203 (x & 0xff00) >> 8;
Dave Rodgman6298b242022-11-28 14:51:49 +0000204}
205#define MBEDTLS_BSWAP16 mbedtls_bswap16
Dave Rodgmanf7f1f742022-11-28 14:52:45 +0000206#endif /* !defined(MBEDTLS_BSWAP16) */
Dave Rodgman6298b242022-11-28 14:51:49 +0000207
Dave Rodgmanf7f1f742022-11-28 14:52:45 +0000208#if !defined(MBEDTLS_BSWAP32)
Gilles Peskine449bd832023-01-11 14:50:10 +0100209static inline uint32_t mbedtls_bswap32(uint32_t x)
210{
Dave Rodgman6298b242022-11-28 14:51:49 +0000211 return
Gilles Peskine449bd832023-01-11 14:50:10 +0100212 (x & 0x000000ff) << 24 |
213 (x & 0x0000ff00) << 8 |
214 (x & 0x00ff0000) >> 8 |
215 (x & 0xff000000) >> 24;
Dave Rodgman6298b242022-11-28 14:51:49 +0000216}
217#define MBEDTLS_BSWAP32 mbedtls_bswap32
Dave Rodgmanf7f1f742022-11-28 14:52:45 +0000218#endif /* !defined(MBEDTLS_BSWAP32) */
Dave Rodgman6298b242022-11-28 14:51:49 +0000219
Dave Rodgmanf7f1f742022-11-28 14:52:45 +0000220#if !defined(MBEDTLS_BSWAP64)
Gilles Peskine449bd832023-01-11 14:50:10 +0100221static inline uint64_t mbedtls_bswap64(uint64_t x)
222{
Dave Rodgman6298b242022-11-28 14:51:49 +0000223 return
Tom Cosgrovebbe166e2023-03-08 13:23:24 +0000224 (x & 0x00000000000000ffULL) << 56 |
225 (x & 0x000000000000ff00ULL) << 40 |
226 (x & 0x0000000000ff0000ULL) << 24 |
227 (x & 0x00000000ff000000ULL) << 8 |
228 (x & 0x000000ff00000000ULL) >> 8 |
229 (x & 0x0000ff0000000000ULL) >> 24 |
230 (x & 0x00ff000000000000ULL) >> 40 |
231 (x & 0xff00000000000000ULL) >> 56;
Dave Rodgman6298b242022-11-28 14:51:49 +0000232}
233#define MBEDTLS_BSWAP64 mbedtls_bswap64
Dave Rodgmanf7f1f742022-11-28 14:52:45 +0000234#endif /* !defined(MBEDTLS_BSWAP64) */
Dave Rodgman6298b242022-11-28 14:51:49 +0000235
Dave Rodgmane5c42592022-11-28 14:47:46 +0000236#if !defined(__BYTE_ORDER__)
Dave Rodgmanf3c04f32023-12-05 12:06:11 +0000237
238#if defined(__LITTLE_ENDIAN__)
239/* IAR defines __xxx_ENDIAN__, but not __BYTE_ORDER__ */
240#define MBEDTLS_IS_BIG_ENDIAN 0
241#elif defined(__BIG_ENDIAN__)
242#define MBEDTLS_IS_BIG_ENDIAN 1
243#else
Dave Rodgmane5c42592022-11-28 14:47:46 +0000244static const uint16_t mbedtls_byte_order_detector = { 0x100 };
245#define MBEDTLS_IS_BIG_ENDIAN (*((unsigned char *) (&mbedtls_byte_order_detector)) == 0x01)
Dave Rodgmanf3c04f32023-12-05 12:06:11 +0000246#endif
247
Dave Rodgmane5c42592022-11-28 14:47:46 +0000248#else
Dave Rodgmanf3c04f32023-12-05 12:06:11 +0000249
250#if (__BYTE_ORDER__) == (__ORDER_BIG_ENDIAN__)
251#define MBEDTLS_IS_BIG_ENDIAN 1
252#else
253#define MBEDTLS_IS_BIG_ENDIAN 0
254#endif
255
Dave Rodgmane5c42592022-11-28 14:47:46 +0000256#endif /* !defined(__BYTE_ORDER__) */
257
Dave Rodgmanfbc23222022-11-24 18:07:37 +0000258/**
259 * Get the unsigned 32 bits integer corresponding to four bytes in
260 * big-endian order (MSB first).
261 *
262 * \param data Base address of the memory to get the four bytes from.
263 * \param offset Offset from \p data of the first and most significant
264 * byte of the four bytes to build the 32 bits unsigned
265 * integer from.
266 */
Dave Rodgman914c6322023-03-01 09:30:14 +0000267#define MBEDTLS_GET_UINT32_BE(data, offset) \
268 ((MBEDTLS_IS_BIG_ENDIAN) \
Dave Rodgmana5110b02022-11-28 14:48:45 +0000269 ? mbedtls_get_unaligned_uint32((data) + (offset)) \
270 : MBEDTLS_BSWAP32(mbedtls_get_unaligned_uint32((data) + (offset))) \
Dave Rodgmanfbc23222022-11-24 18:07:37 +0000271 )
Dave Rodgmanfbc23222022-11-24 18:07:37 +0000272
273/**
274 * Put in memory a 32 bits unsigned integer in big-endian order.
275 *
276 * \param n 32 bits unsigned integer to put in memory.
277 * \param data Base address of the memory where to put the 32
278 * bits unsigned integer in.
279 * \param offset Offset from \p data where to put the most significant
280 * byte of the 32 bits unsigned integer \p n.
281 */
Dave Rodgman914c6322023-03-01 09:30:14 +0000282#define MBEDTLS_PUT_UINT32_BE(n, data, offset) \
Gilles Peskine449bd832023-01-11 14:50:10 +0100283 { \
Dave Rodgman914c6322023-03-01 09:30:14 +0000284 if (MBEDTLS_IS_BIG_ENDIAN) \
Gilles Peskine449bd832023-01-11 14:50:10 +0100285 { \
Dave Rodgman914c6322023-03-01 09:30:14 +0000286 mbedtls_put_unaligned_uint32((data) + (offset), (uint32_t) (n)); \
Gilles Peskine449bd832023-01-11 14:50:10 +0100287 } \
288 else \
289 { \
290 mbedtls_put_unaligned_uint32((data) + (offset), MBEDTLS_BSWAP32((uint32_t) (n))); \
291 } \
292 }
Dave Rodgmanfbc23222022-11-24 18:07:37 +0000293
294/**
295 * Get the unsigned 32 bits integer corresponding to four bytes in
296 * little-endian order (LSB first).
297 *
298 * \param data Base address of the memory to get the four bytes from.
299 * \param offset Offset from \p data of the first and least significant
300 * byte of the four bytes to build the 32 bits unsigned
301 * integer from.
302 */
Dave Rodgman914c6322023-03-01 09:30:14 +0000303#define MBEDTLS_GET_UINT32_LE(data, offset) \
304 ((MBEDTLS_IS_BIG_ENDIAN) \
Dave Rodgmana5110b02022-11-28 14:48:45 +0000305 ? MBEDTLS_BSWAP32(mbedtls_get_unaligned_uint32((data) + (offset))) \
306 : mbedtls_get_unaligned_uint32((data) + (offset)) \
Dave Rodgmanfbc23222022-11-24 18:07:37 +0000307 )
Dave Rodgmana5110b02022-11-28 14:48:45 +0000308
Dave Rodgmanfbc23222022-11-24 18:07:37 +0000309
310/**
311 * Put in memory a 32 bits unsigned integer in little-endian order.
312 *
313 * \param n 32 bits unsigned integer to put in memory.
314 * \param data Base address of the memory where to put the 32
315 * bits unsigned integer in.
316 * \param offset Offset from \p data where to put the least significant
317 * byte of the 32 bits unsigned integer \p n.
318 */
Dave Rodgman914c6322023-03-01 09:30:14 +0000319#define MBEDTLS_PUT_UINT32_LE(n, data, offset) \
Gilles Peskine449bd832023-01-11 14:50:10 +0100320 { \
Dave Rodgman914c6322023-03-01 09:30:14 +0000321 if (MBEDTLS_IS_BIG_ENDIAN) \
Gilles Peskine449bd832023-01-11 14:50:10 +0100322 { \
323 mbedtls_put_unaligned_uint32((data) + (offset), MBEDTLS_BSWAP32((uint32_t) (n))); \
324 } \
325 else \
326 { \
Dave Rodgman914c6322023-03-01 09:30:14 +0000327 mbedtls_put_unaligned_uint32((data) + (offset), ((uint32_t) (n))); \
Gilles Peskine449bd832023-01-11 14:50:10 +0100328 } \
329 }
Dave Rodgmanfbc23222022-11-24 18:07:37 +0000330
331/**
332 * Get the unsigned 16 bits integer corresponding to two bytes in
333 * little-endian order (LSB first).
334 *
335 * \param data Base address of the memory to get the two bytes from.
336 * \param offset Offset from \p data of the first and least significant
337 * byte of the two bytes to build the 16 bits unsigned
338 * integer from.
339 */
Dave Rodgman914c6322023-03-01 09:30:14 +0000340#define MBEDTLS_GET_UINT16_LE(data, offset) \
341 ((MBEDTLS_IS_BIG_ENDIAN) \
Dave Rodgmana5110b02022-11-28 14:48:45 +0000342 ? MBEDTLS_BSWAP16(mbedtls_get_unaligned_uint16((data) + (offset))) \
343 : mbedtls_get_unaligned_uint16((data) + (offset)) \
Dave Rodgmanfbc23222022-11-24 18:07:37 +0000344 )
Dave Rodgmanfbc23222022-11-24 18:07:37 +0000345
346/**
347 * Put in memory a 16 bits unsigned integer in little-endian order.
348 *
349 * \param n 16 bits unsigned integer to put in memory.
350 * \param data Base address of the memory where to put the 16
351 * bits unsigned integer in.
352 * \param offset Offset from \p data where to put the least significant
353 * byte of the 16 bits unsigned integer \p n.
354 */
Dave Rodgman914c6322023-03-01 09:30:14 +0000355#define MBEDTLS_PUT_UINT16_LE(n, data, offset) \
Gilles Peskine449bd832023-01-11 14:50:10 +0100356 { \
Dave Rodgman914c6322023-03-01 09:30:14 +0000357 if (MBEDTLS_IS_BIG_ENDIAN) \
Gilles Peskine449bd832023-01-11 14:50:10 +0100358 { \
359 mbedtls_put_unaligned_uint16((data) + (offset), MBEDTLS_BSWAP16((uint16_t) (n))); \
360 } \
361 else \
362 { \
Dave Rodgman914c6322023-03-01 09:30:14 +0000363 mbedtls_put_unaligned_uint16((data) + (offset), (uint16_t) (n)); \
Gilles Peskine449bd832023-01-11 14:50:10 +0100364 } \
365 }
Dave Rodgmanfbc23222022-11-24 18:07:37 +0000366
367/**
368 * Get the unsigned 16 bits integer corresponding to two bytes in
369 * big-endian order (MSB first).
370 *
371 * \param data Base address of the memory to get the two bytes from.
372 * \param offset Offset from \p data of the first and most significant
373 * byte of the two bytes to build the 16 bits unsigned
374 * integer from.
375 */
Dave Rodgman914c6322023-03-01 09:30:14 +0000376#define MBEDTLS_GET_UINT16_BE(data, offset) \
377 ((MBEDTLS_IS_BIG_ENDIAN) \
Dave Rodgmana5110b02022-11-28 14:48:45 +0000378 ? mbedtls_get_unaligned_uint16((data) + (offset)) \
379 : MBEDTLS_BSWAP16(mbedtls_get_unaligned_uint16((data) + (offset))) \
Dave Rodgmanfbc23222022-11-24 18:07:37 +0000380 )
Dave Rodgmanfbc23222022-11-24 18:07:37 +0000381
382/**
383 * Put in memory a 16 bits unsigned integer in big-endian order.
384 *
385 * \param n 16 bits unsigned integer to put in memory.
386 * \param data Base address of the memory where to put the 16
387 * bits unsigned integer in.
388 * \param offset Offset from \p data where to put the most significant
389 * byte of the 16 bits unsigned integer \p n.
390 */
Dave Rodgman914c6322023-03-01 09:30:14 +0000391#define MBEDTLS_PUT_UINT16_BE(n, data, offset) \
Gilles Peskine449bd832023-01-11 14:50:10 +0100392 { \
Dave Rodgman914c6322023-03-01 09:30:14 +0000393 if (MBEDTLS_IS_BIG_ENDIAN) \
Gilles Peskine449bd832023-01-11 14:50:10 +0100394 { \
Dave Rodgman914c6322023-03-01 09:30:14 +0000395 mbedtls_put_unaligned_uint16((data) + (offset), (uint16_t) (n)); \
Gilles Peskine449bd832023-01-11 14:50:10 +0100396 } \
397 else \
398 { \
399 mbedtls_put_unaligned_uint16((data) + (offset), MBEDTLS_BSWAP16((uint16_t) (n))); \
400 } \
401 }
Dave Rodgmanfbc23222022-11-24 18:07:37 +0000402
403/**
404 * Get the unsigned 24 bits integer corresponding to three bytes in
405 * big-endian order (MSB first).
406 *
407 * \param data Base address of the memory to get the three bytes from.
408 * \param offset Offset from \p data of the first and most significant
409 * byte of the three bytes to build the 24 bits unsigned
410 * integer from.
411 */
Dave Rodgman914c6322023-03-01 09:30:14 +0000412#define MBEDTLS_GET_UINT24_BE(data, offset) \
413 ( \
414 ((uint32_t) (data)[(offset)] << 16) \
415 | ((uint32_t) (data)[(offset) + 1] << 8) \
416 | ((uint32_t) (data)[(offset) + 2]) \
Dave Rodgmanfbc23222022-11-24 18:07:37 +0000417 )
Dave Rodgmanfbc23222022-11-24 18:07:37 +0000418
419/**
420 * Put in memory a 24 bits unsigned integer in big-endian order.
421 *
422 * \param n 24 bits unsigned integer to put in memory.
423 * \param data Base address of the memory where to put the 24
424 * bits unsigned integer in.
425 * \param offset Offset from \p data where to put the most significant
426 * byte of the 24 bits unsigned integer \p n.
427 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100428#define MBEDTLS_PUT_UINT24_BE(n, data, offset) \
Dave Rodgman914c6322023-03-01 09:30:14 +0000429 { \
430 (data)[(offset)] = MBEDTLS_BYTE_2(n); \
Gilles Peskine449bd832023-01-11 14:50:10 +0100431 (data)[(offset) + 1] = MBEDTLS_BYTE_1(n); \
432 (data)[(offset) + 2] = MBEDTLS_BYTE_0(n); \
433 }
Dave Rodgmanfbc23222022-11-24 18:07:37 +0000434
435/**
436 * Get the unsigned 24 bits integer corresponding to three bytes in
437 * little-endian order (LSB first).
438 *
439 * \param data Base address of the memory to get the three bytes from.
440 * \param offset Offset from \p data of the first and least significant
441 * byte of the three bytes to build the 24 bits unsigned
442 * integer from.
443 */
Dave Rodgman914c6322023-03-01 09:30:14 +0000444#define MBEDTLS_GET_UINT24_LE(data, offset) \
445 ( \
446 ((uint32_t) (data)[(offset)]) \
Gilles Peskine449bd832023-01-11 14:50:10 +0100447 | ((uint32_t) (data)[(offset) + 1] << 8) \
448 | ((uint32_t) (data)[(offset) + 2] << 16) \
Dave Rodgmanfbc23222022-11-24 18:07:37 +0000449 )
Dave Rodgmanfbc23222022-11-24 18:07:37 +0000450
451/**
452 * Put in memory a 24 bits unsigned integer in little-endian order.
453 *
454 * \param n 24 bits unsigned integer to put in memory.
455 * \param data Base address of the memory where to put the 24
456 * bits unsigned integer in.
457 * \param offset Offset from \p data where to put the least significant
458 * byte of the 24 bits unsigned integer \p n.
459 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100460#define MBEDTLS_PUT_UINT24_LE(n, data, offset) \
Dave Rodgman914c6322023-03-01 09:30:14 +0000461 { \
462 (data)[(offset)] = MBEDTLS_BYTE_0(n); \
Gilles Peskine449bd832023-01-11 14:50:10 +0100463 (data)[(offset) + 1] = MBEDTLS_BYTE_1(n); \
464 (data)[(offset) + 2] = MBEDTLS_BYTE_2(n); \
465 }
Dave Rodgmanfbc23222022-11-24 18:07:37 +0000466
467/**
468 * Get the unsigned 64 bits integer corresponding to eight bytes in
469 * big-endian order (MSB first).
470 *
471 * \param data Base address of the memory to get the eight bytes from.
472 * \param offset Offset from \p data of the first and most significant
473 * byte of the eight bytes to build the 64 bits unsigned
474 * integer from.
475 */
Dave Rodgman914c6322023-03-01 09:30:14 +0000476#define MBEDTLS_GET_UINT64_BE(data, offset) \
477 ((MBEDTLS_IS_BIG_ENDIAN) \
Dave Rodgmana5110b02022-11-28 14:48:45 +0000478 ? mbedtls_get_unaligned_uint64((data) + (offset)) \
479 : MBEDTLS_BSWAP64(mbedtls_get_unaligned_uint64((data) + (offset))) \
Dave Rodgmanfbc23222022-11-24 18:07:37 +0000480 )
Dave Rodgmanfbc23222022-11-24 18:07:37 +0000481
482/**
483 * Put in memory a 64 bits unsigned integer in big-endian order.
484 *
485 * \param n 64 bits unsigned integer to put in memory.
486 * \param data Base address of the memory where to put the 64
487 * bits unsigned integer in.
488 * \param offset Offset from \p data where to put the most significant
489 * byte of the 64 bits unsigned integer \p n.
490 */
Dave Rodgman914c6322023-03-01 09:30:14 +0000491#define MBEDTLS_PUT_UINT64_BE(n, data, offset) \
Gilles Peskine449bd832023-01-11 14:50:10 +0100492 { \
Dave Rodgman914c6322023-03-01 09:30:14 +0000493 if (MBEDTLS_IS_BIG_ENDIAN) \
Gilles Peskine449bd832023-01-11 14:50:10 +0100494 { \
Dave Rodgman914c6322023-03-01 09:30:14 +0000495 mbedtls_put_unaligned_uint64((data) + (offset), (uint64_t) (n)); \
Gilles Peskine449bd832023-01-11 14:50:10 +0100496 } \
497 else \
498 { \
499 mbedtls_put_unaligned_uint64((data) + (offset), MBEDTLS_BSWAP64((uint64_t) (n))); \
500 } \
501 }
Dave Rodgmanfbc23222022-11-24 18:07:37 +0000502
503/**
504 * Get the unsigned 64 bits integer corresponding to eight bytes in
505 * little-endian order (LSB first).
506 *
507 * \param data Base address of the memory to get the eight bytes from.
508 * \param offset Offset from \p data of the first and least significant
509 * byte of the eight bytes to build the 64 bits unsigned
510 * integer from.
511 */
Dave Rodgman914c6322023-03-01 09:30:14 +0000512#define MBEDTLS_GET_UINT64_LE(data, offset) \
513 ((MBEDTLS_IS_BIG_ENDIAN) \
Dave Rodgmana5110b02022-11-28 14:48:45 +0000514 ? MBEDTLS_BSWAP64(mbedtls_get_unaligned_uint64((data) + (offset))) \
515 : mbedtls_get_unaligned_uint64((data) + (offset)) \
Dave Rodgmanfbc23222022-11-24 18:07:37 +0000516 )
Dave Rodgmanfbc23222022-11-24 18:07:37 +0000517
518/**
519 * Put in memory a 64 bits unsigned integer in little-endian order.
520 *
521 * \param n 64 bits unsigned integer to put in memory.
522 * \param data Base address of the memory where to put the 64
523 * bits unsigned integer in.
524 * \param offset Offset from \p data where to put the least significant
525 * byte of the 64 bits unsigned integer \p n.
526 */
Dave Rodgman914c6322023-03-01 09:30:14 +0000527#define MBEDTLS_PUT_UINT64_LE(n, data, offset) \
Gilles Peskine449bd832023-01-11 14:50:10 +0100528 { \
Dave Rodgman914c6322023-03-01 09:30:14 +0000529 if (MBEDTLS_IS_BIG_ENDIAN) \
Gilles Peskine449bd832023-01-11 14:50:10 +0100530 { \
531 mbedtls_put_unaligned_uint64((data) + (offset), MBEDTLS_BSWAP64((uint64_t) (n))); \
532 } \
533 else \
534 { \
Dave Rodgman914c6322023-03-01 09:30:14 +0000535 mbedtls_put_unaligned_uint64((data) + (offset), (uint64_t) (n)); \
Gilles Peskine449bd832023-01-11 14:50:10 +0100536 } \
537 }
Dave Rodgmanfbc23222022-11-24 18:07:37 +0000538
539#endif /* MBEDTLS_LIBRARY_ALIGNMENT_H */