blob: ab15986e5176a224f929893b5d0a32da10aeb544 [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
8 * SPDX-License-Identifier: Apache-2.0
9 *
10 * Licensed under the Apache License, Version 2.0 (the "License"); you may
11 * not use this file except in compliance with the License.
12 * You may obtain a copy of the License at
13 *
14 * http://www.apache.org/licenses/LICENSE-2.0
15 *
16 * Unless required by applicable law or agreed to in writing, software
17 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
18 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19 * See the License for the specific language governing permissions and
20 * limitations under the License.
21 */
22
23#ifndef MBEDTLS_LIBRARY_ALIGNMENT_H
24#define MBEDTLS_LIBRARY_ALIGNMENT_H
25
26#include <stdint.h>
Dave Rodgman96d61d12022-11-24 19:33:22 +000027#include <string.h>
Dave Rodgmanf7f1f742022-11-28 14:52:45 +000028#include <stdlib.h>
Dave Rodgmanfbc23222022-11-24 18:07:37 +000029
Dave Rodgmanb9cd19b2022-12-30 21:32:03 +000030/*
31 * Define MBEDTLS_EFFICIENT_UNALIGNED_ACCESS for architectures where unaligned memory
Dave Rodgman7f376fa2023-01-05 12:25:15 +000032 * accesses are known to be efficient.
33 *
34 * All functions defined here will behave correctly regardless, but might be less
35 * efficient when this is not defined.
Dave Rodgmanb9cd19b2022-12-30 21:32:03 +000036 */
37#if defined(__ARM_FEATURE_UNALIGNED) \
38 || defined(__i386__) || defined(__amd64__) || defined(__x86_64__)
39/*
40 * __ARM_FEATURE_UNALIGNED is defined where appropriate by armcc, gcc 7, clang 9
Dave Rodgman7f376fa2023-01-05 12:25:15 +000041 * (and later versions) for Arm v7 and later; all x86 platforms should have
42 * efficient unaligned access.
Dave Rodgmanb9cd19b2022-12-30 21:32:03 +000043 */
44#define MBEDTLS_EFFICIENT_UNALIGNED_ACCESS
45#endif
46
Dave Rodgman96d61d12022-11-24 19:33:22 +000047/**
Dave Rodgmana360e192022-11-28 14:44:05 +000048 * Read the unsigned 16 bits integer from the given address, which need not
49 * be aligned.
50 *
51 * \param p pointer to 2 bytes of data
52 * \return Data at the given address
53 */
Gilles Peskine449bd832023-01-11 14:50:10 +010054inline uint16_t mbedtls_get_unaligned_uint16(const void *p)
Dave Rodgmana360e192022-11-28 14:44:05 +000055{
56 uint16_t r;
Gilles Peskine449bd832023-01-11 14:50:10 +010057 memcpy(&r, p, sizeof(r));
Dave Rodgmana360e192022-11-28 14:44:05 +000058 return r;
59}
60
61/**
62 * Write the unsigned 16 bits integer to the given address, which need not
63 * be aligned.
64 *
65 * \param p pointer to 2 bytes of data
66 * \param x data to write
67 */
Gilles Peskine449bd832023-01-11 14:50:10 +010068inline void mbedtls_put_unaligned_uint16(void *p, uint16_t x)
Dave Rodgmana360e192022-11-28 14:44:05 +000069{
Gilles Peskine449bd832023-01-11 14:50:10 +010070 memcpy(p, &x, sizeof(x));
Dave Rodgmana360e192022-11-28 14:44:05 +000071}
72
73/**
Dave Rodgman96d61d12022-11-24 19:33:22 +000074 * Read the unsigned 32 bits integer from the given address, which need not
75 * be aligned.
Dave Rodgmanfbc23222022-11-24 18:07:37 +000076 *
Dave Rodgman96d61d12022-11-24 19:33:22 +000077 * \param p pointer to 4 bytes of data
Dave Rodgman875d2382022-11-24 20:43:15 +000078 * \return Data at the given address
Dave Rodgmanfbc23222022-11-24 18:07:37 +000079 */
Gilles Peskine449bd832023-01-11 14:50:10 +010080inline uint32_t mbedtls_get_unaligned_uint32(const void *p)
Dave Rodgman96d61d12022-11-24 19:33:22 +000081{
82 uint32_t r;
Gilles Peskine449bd832023-01-11 14:50:10 +010083 memcpy(&r, p, sizeof(r));
Dave Rodgman96d61d12022-11-24 19:33:22 +000084 return r;
85}
Dave Rodgmanfbc23222022-11-24 18:07:37 +000086
Dave Rodgman96d61d12022-11-24 19:33:22 +000087/**
88 * Write the unsigned 32 bits integer to the given address, which need not
89 * be aligned.
90 *
91 * \param p pointer to 4 bytes of data
92 * \param x data to write
93 */
Gilles Peskine449bd832023-01-11 14:50:10 +010094inline void mbedtls_put_unaligned_uint32(void *p, uint32_t x)
Dave Rodgman96d61d12022-11-24 19:33:22 +000095{
Gilles Peskine449bd832023-01-11 14:50:10 +010096 memcpy(p, &x, sizeof(x));
Dave Rodgman96d61d12022-11-24 19:33:22 +000097}
Dave Rodgmanfbc23222022-11-24 18:07:37 +000098
Dave Rodgmana360e192022-11-28 14:44:05 +000099/**
100 * Read the unsigned 64 bits integer from the given address, which need not
101 * be aligned.
102 *
103 * \param p pointer to 8 bytes of data
104 * \return Data at the given address
105 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100106inline uint64_t mbedtls_get_unaligned_uint64(const void *p)
Dave Rodgmana360e192022-11-28 14:44:05 +0000107{
108 uint64_t r;
Gilles Peskine449bd832023-01-11 14:50:10 +0100109 memcpy(&r, p, sizeof(r));
Dave Rodgmana360e192022-11-28 14:44:05 +0000110 return r;
111}
112
113/**
114 * Write the unsigned 64 bits integer to the given address, which need not
115 * be aligned.
116 *
117 * \param p pointer to 8 bytes of data
118 * \param x data to write
119 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100120inline void mbedtls_put_unaligned_uint64(void *p, uint64_t x)
Dave Rodgmana360e192022-11-28 14:44:05 +0000121{
Gilles Peskine449bd832023-01-11 14:50:10 +0100122 memcpy(p, &x, sizeof(x));
Dave Rodgmana360e192022-11-28 14:44:05 +0000123}
124
Dave Rodgmanfbc23222022-11-24 18:07:37 +0000125/** Byte Reading Macros
126 *
127 * Given a multi-byte integer \p x, MBEDTLS_BYTE_n retrieves the n-th
128 * byte from x, where byte 0 is the least significant byte.
129 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100130#define MBEDTLS_BYTE_0(x) ((uint8_t) ((x) & 0xff))
Dave Rodgman914c6322023-03-01 09:30:14 +0000131#define MBEDTLS_BYTE_1(x) ((uint8_t) (((x) >> 8) & 0xff))
Gilles Peskine449bd832023-01-11 14:50:10 +0100132#define MBEDTLS_BYTE_2(x) ((uint8_t) (((x) >> 16) & 0xff))
133#define MBEDTLS_BYTE_3(x) ((uint8_t) (((x) >> 24) & 0xff))
134#define MBEDTLS_BYTE_4(x) ((uint8_t) (((x) >> 32) & 0xff))
135#define MBEDTLS_BYTE_5(x) ((uint8_t) (((x) >> 40) & 0xff))
136#define MBEDTLS_BYTE_6(x) ((uint8_t) (((x) >> 48) & 0xff))
137#define MBEDTLS_BYTE_7(x) ((uint8_t) (((x) >> 56) & 0xff))
Dave Rodgmanfbc23222022-11-24 18:07:37 +0000138
Dave Rodgmanf7f1f742022-11-28 14:52:45 +0000139/*
140 * Detect GCC built-in byteswap routines
141 */
142#if defined(__GNUC__) && defined(__GNUC_PREREQ)
Gilles Peskine449bd832023-01-11 14:50:10 +0100143#if __GNUC_PREREQ(4, 8)
Dave Rodgmanf7f1f742022-11-28 14:52:45 +0000144#define MBEDTLS_BSWAP16 __builtin_bswap16
145#endif /* __GNUC_PREREQ(4,8) */
Gilles Peskine449bd832023-01-11 14:50:10 +0100146#if __GNUC_PREREQ(4, 3)
Dave Rodgmanf7f1f742022-11-28 14:52:45 +0000147#define MBEDTLS_BSWAP32 __builtin_bswap32
148#define MBEDTLS_BSWAP64 __builtin_bswap64
149#endif /* __GNUC_PREREQ(4,3) */
150#endif /* defined(__GNUC__) && defined(__GNUC_PREREQ) */
151
152/*
153 * Detect Clang built-in byteswap routines
154 */
155#if defined(__clang__) && defined(__has_builtin)
Dave Rodgmane47899d2023-02-28 17:39:03 +0000156#if __has_builtin(__builtin_bswap16) && !defined(MBEDTLS_BSWAP16)
Dave Rodgmanf7f1f742022-11-28 14:52:45 +0000157#define MBEDTLS_BSWAP16 __builtin_bswap16
158#endif /* __has_builtin(__builtin_bswap16) */
Dave Rodgmane47899d2023-02-28 17:39:03 +0000159#if __has_builtin(__builtin_bswap32) && !defined(MBEDTLS_BSWAP32)
Dave Rodgmanf7f1f742022-11-28 14:52:45 +0000160#define MBEDTLS_BSWAP32 __builtin_bswap32
161#endif /* __has_builtin(__builtin_bswap32) */
Dave Rodgmane47899d2023-02-28 17:39:03 +0000162#if __has_builtin(__builtin_bswap64) && !defined(MBEDTLS_BSWAP64)
Dave Rodgmanf7f1f742022-11-28 14:52:45 +0000163#define MBEDTLS_BSWAP64 __builtin_bswap64
164#endif /* __has_builtin(__builtin_bswap64) */
165#endif /* defined(__clang__) && defined(__has_builtin) */
166
167/*
168 * Detect MSVC built-in byteswap routines
169 */
170#if defined(_MSC_VER)
Dave Rodgmane47899d2023-02-28 17:39:03 +0000171#if !defined(MBEDTLS_BSWAP16)
Dave Rodgmanf7f1f742022-11-28 14:52:45 +0000172#define MBEDTLS_BSWAP16 _byteswap_ushort
Dave Rodgmane47899d2023-02-28 17:39:03 +0000173#endif
174#if !defined(MBEDTLS_BSWAP32)
Dave Rodgmanf7f1f742022-11-28 14:52:45 +0000175#define MBEDTLS_BSWAP32 _byteswap_ulong
Dave Rodgmane47899d2023-02-28 17:39:03 +0000176#endif
177#if !defined(MBEDTLS_BSWAP64)
Dave Rodgmanf7f1f742022-11-28 14:52:45 +0000178#define MBEDTLS_BSWAP64 _byteswap_uint64
Dave Rodgmane47899d2023-02-28 17:39:03 +0000179#endif
Dave Rodgmanf7f1f742022-11-28 14:52:45 +0000180#endif /* defined(_MSC_VER) */
181
Dave Rodgman2dae4b32022-11-30 12:07:36 +0000182/* Detect armcc built-in byteswap routine */
Dave Rodgmane47899d2023-02-28 17:39:03 +0000183#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 410000) && !defined(MBEDTLS_BSWAP32)
Tom Cosgrovef2b5a132023-04-26 17:00:12 +0100184#if defined(__ARM_ACLE) /* ARM Compiler 6 - earlier versions don't need a header */
185#include <arm_acle.h>
186#endif
Dave Rodgman2dae4b32022-11-30 12:07:36 +0000187#define MBEDTLS_BSWAP32 __rev
188#endif
189
Dave Rodgmanf7f1f742022-11-28 14:52:45 +0000190/*
191 * Where compiler built-ins are not present, fall back to C code that the
192 * compiler may be able to detect and transform into the relevant bswap or
193 * similar instruction.
194 */
195#if !defined(MBEDTLS_BSWAP16)
Gilles Peskine449bd832023-01-11 14:50:10 +0100196static inline uint16_t mbedtls_bswap16(uint16_t x)
197{
Dave Rodgman6298b242022-11-28 14:51:49 +0000198 return
Gilles Peskine449bd832023-01-11 14:50:10 +0100199 (x & 0x00ff) << 8 |
200 (x & 0xff00) >> 8;
Dave Rodgman6298b242022-11-28 14:51:49 +0000201}
202#define MBEDTLS_BSWAP16 mbedtls_bswap16
Dave Rodgmanf7f1f742022-11-28 14:52:45 +0000203#endif /* !defined(MBEDTLS_BSWAP16) */
Dave Rodgman6298b242022-11-28 14:51:49 +0000204
Dave Rodgmanf7f1f742022-11-28 14:52:45 +0000205#if !defined(MBEDTLS_BSWAP32)
Gilles Peskine449bd832023-01-11 14:50:10 +0100206static inline uint32_t mbedtls_bswap32(uint32_t x)
207{
Dave Rodgman6298b242022-11-28 14:51:49 +0000208 return
Gilles Peskine449bd832023-01-11 14:50:10 +0100209 (x & 0x000000ff) << 24 |
210 (x & 0x0000ff00) << 8 |
211 (x & 0x00ff0000) >> 8 |
212 (x & 0xff000000) >> 24;
Dave Rodgman6298b242022-11-28 14:51:49 +0000213}
214#define MBEDTLS_BSWAP32 mbedtls_bswap32
Dave Rodgmanf7f1f742022-11-28 14:52:45 +0000215#endif /* !defined(MBEDTLS_BSWAP32) */
Dave Rodgman6298b242022-11-28 14:51:49 +0000216
Dave Rodgmanf7f1f742022-11-28 14:52:45 +0000217#if !defined(MBEDTLS_BSWAP64)
Gilles Peskine449bd832023-01-11 14:50:10 +0100218static inline uint64_t mbedtls_bswap64(uint64_t x)
219{
Dave Rodgman6298b242022-11-28 14:51:49 +0000220 return
Tom Cosgrovebbe166e2023-03-08 13:23:24 +0000221 (x & 0x00000000000000ffULL) << 56 |
222 (x & 0x000000000000ff00ULL) << 40 |
223 (x & 0x0000000000ff0000ULL) << 24 |
224 (x & 0x00000000ff000000ULL) << 8 |
225 (x & 0x000000ff00000000ULL) >> 8 |
226 (x & 0x0000ff0000000000ULL) >> 24 |
227 (x & 0x00ff000000000000ULL) >> 40 |
228 (x & 0xff00000000000000ULL) >> 56;
Dave Rodgman6298b242022-11-28 14:51:49 +0000229}
230#define MBEDTLS_BSWAP64 mbedtls_bswap64
Dave Rodgmanf7f1f742022-11-28 14:52:45 +0000231#endif /* !defined(MBEDTLS_BSWAP64) */
Dave Rodgman6298b242022-11-28 14:51:49 +0000232
Dave Rodgmane5c42592022-11-28 14:47:46 +0000233#if !defined(__BYTE_ORDER__)
234static const uint16_t mbedtls_byte_order_detector = { 0x100 };
235#define MBEDTLS_IS_BIG_ENDIAN (*((unsigned char *) (&mbedtls_byte_order_detector)) == 0x01)
236#else
237#define MBEDTLS_IS_BIG_ENDIAN ((__BYTE_ORDER__) == (__ORDER_BIG_ENDIAN__))
238#endif /* !defined(__BYTE_ORDER__) */
239
Dave Rodgmanfbc23222022-11-24 18:07:37 +0000240/**
241 * Get the unsigned 32 bits integer corresponding to four bytes in
242 * big-endian order (MSB first).
243 *
244 * \param data Base address of the memory to get the four bytes from.
245 * \param offset Offset from \p data of the first and most significant
246 * byte of the four bytes to build the 32 bits unsigned
247 * integer from.
248 */
Dave Rodgman914c6322023-03-01 09:30:14 +0000249#define MBEDTLS_GET_UINT32_BE(data, offset) \
250 ((MBEDTLS_IS_BIG_ENDIAN) \
Dave Rodgmana5110b02022-11-28 14:48:45 +0000251 ? mbedtls_get_unaligned_uint32((data) + (offset)) \
252 : MBEDTLS_BSWAP32(mbedtls_get_unaligned_uint32((data) + (offset))) \
Dave Rodgmanfbc23222022-11-24 18:07:37 +0000253 )
Dave Rodgmanfbc23222022-11-24 18:07:37 +0000254
255/**
256 * Put in memory a 32 bits unsigned integer in big-endian order.
257 *
258 * \param n 32 bits unsigned integer to put in memory.
259 * \param data Base address of the memory where to put the 32
260 * bits unsigned integer in.
261 * \param offset Offset from \p data where to put the most significant
262 * byte of the 32 bits unsigned integer \p n.
263 */
Dave Rodgman914c6322023-03-01 09:30:14 +0000264#define MBEDTLS_PUT_UINT32_BE(n, data, offset) \
Gilles Peskine449bd832023-01-11 14:50:10 +0100265 { \
Dave Rodgman914c6322023-03-01 09:30:14 +0000266 if (MBEDTLS_IS_BIG_ENDIAN) \
Gilles Peskine449bd832023-01-11 14:50:10 +0100267 { \
Dave Rodgman914c6322023-03-01 09:30:14 +0000268 mbedtls_put_unaligned_uint32((data) + (offset), (uint32_t) (n)); \
Gilles Peskine449bd832023-01-11 14:50:10 +0100269 } \
270 else \
271 { \
272 mbedtls_put_unaligned_uint32((data) + (offset), MBEDTLS_BSWAP32((uint32_t) (n))); \
273 } \
274 }
Dave Rodgmanfbc23222022-11-24 18:07:37 +0000275
276/**
277 * Get the unsigned 32 bits integer corresponding to four bytes in
278 * little-endian order (LSB first).
279 *
280 * \param data Base address of the memory to get the four bytes from.
281 * \param offset Offset from \p data of the first and least significant
282 * byte of the four bytes to build the 32 bits unsigned
283 * integer from.
284 */
Dave Rodgman914c6322023-03-01 09:30:14 +0000285#define MBEDTLS_GET_UINT32_LE(data, offset) \
286 ((MBEDTLS_IS_BIG_ENDIAN) \
Dave Rodgmana5110b02022-11-28 14:48:45 +0000287 ? MBEDTLS_BSWAP32(mbedtls_get_unaligned_uint32((data) + (offset))) \
288 : mbedtls_get_unaligned_uint32((data) + (offset)) \
Dave Rodgmanfbc23222022-11-24 18:07:37 +0000289 )
Dave Rodgmana5110b02022-11-28 14:48:45 +0000290
Dave Rodgmanfbc23222022-11-24 18:07:37 +0000291
292/**
293 * Put in memory a 32 bits unsigned integer in little-endian order.
294 *
295 * \param n 32 bits unsigned integer to put in memory.
296 * \param data Base address of the memory where to put the 32
297 * bits unsigned integer in.
298 * \param offset Offset from \p data where to put the least significant
299 * byte of the 32 bits unsigned integer \p n.
300 */
Dave Rodgman914c6322023-03-01 09:30:14 +0000301#define MBEDTLS_PUT_UINT32_LE(n, data, offset) \
Gilles Peskine449bd832023-01-11 14:50:10 +0100302 { \
Dave Rodgman914c6322023-03-01 09:30:14 +0000303 if (MBEDTLS_IS_BIG_ENDIAN) \
Gilles Peskine449bd832023-01-11 14:50:10 +0100304 { \
305 mbedtls_put_unaligned_uint32((data) + (offset), MBEDTLS_BSWAP32((uint32_t) (n))); \
306 } \
307 else \
308 { \
Dave Rodgman914c6322023-03-01 09:30:14 +0000309 mbedtls_put_unaligned_uint32((data) + (offset), ((uint32_t) (n))); \
Gilles Peskine449bd832023-01-11 14:50:10 +0100310 } \
311 }
Dave Rodgmanfbc23222022-11-24 18:07:37 +0000312
313/**
314 * Get the unsigned 16 bits integer corresponding to two bytes in
315 * little-endian order (LSB first).
316 *
317 * \param data Base address of the memory to get the two bytes from.
318 * \param offset Offset from \p data of the first and least significant
319 * byte of the two bytes to build the 16 bits unsigned
320 * integer from.
321 */
Dave Rodgman914c6322023-03-01 09:30:14 +0000322#define MBEDTLS_GET_UINT16_LE(data, offset) \
323 ((MBEDTLS_IS_BIG_ENDIAN) \
Dave Rodgmana5110b02022-11-28 14:48:45 +0000324 ? MBEDTLS_BSWAP16(mbedtls_get_unaligned_uint16((data) + (offset))) \
325 : mbedtls_get_unaligned_uint16((data) + (offset)) \
Dave Rodgmanfbc23222022-11-24 18:07:37 +0000326 )
Dave Rodgmanfbc23222022-11-24 18:07:37 +0000327
328/**
329 * Put in memory a 16 bits unsigned integer in little-endian order.
330 *
331 * \param n 16 bits unsigned integer to put in memory.
332 * \param data Base address of the memory where to put the 16
333 * bits unsigned integer in.
334 * \param offset Offset from \p data where to put the least significant
335 * byte of the 16 bits unsigned integer \p n.
336 */
Dave Rodgman914c6322023-03-01 09:30:14 +0000337#define MBEDTLS_PUT_UINT16_LE(n, data, offset) \
Gilles Peskine449bd832023-01-11 14:50:10 +0100338 { \
Dave Rodgman914c6322023-03-01 09:30:14 +0000339 if (MBEDTLS_IS_BIG_ENDIAN) \
Gilles Peskine449bd832023-01-11 14:50:10 +0100340 { \
341 mbedtls_put_unaligned_uint16((data) + (offset), MBEDTLS_BSWAP16((uint16_t) (n))); \
342 } \
343 else \
344 { \
Dave Rodgman914c6322023-03-01 09:30:14 +0000345 mbedtls_put_unaligned_uint16((data) + (offset), (uint16_t) (n)); \
Gilles Peskine449bd832023-01-11 14:50:10 +0100346 } \
347 }
Dave Rodgmanfbc23222022-11-24 18:07:37 +0000348
349/**
350 * Get the unsigned 16 bits integer corresponding to two bytes in
351 * big-endian order (MSB first).
352 *
353 * \param data Base address of the memory to get the two bytes from.
354 * \param offset Offset from \p data of the first and most significant
355 * byte of the two bytes to build the 16 bits unsigned
356 * integer from.
357 */
Dave Rodgman914c6322023-03-01 09:30:14 +0000358#define MBEDTLS_GET_UINT16_BE(data, offset) \
359 ((MBEDTLS_IS_BIG_ENDIAN) \
Dave Rodgmana5110b02022-11-28 14:48:45 +0000360 ? mbedtls_get_unaligned_uint16((data) + (offset)) \
361 : MBEDTLS_BSWAP16(mbedtls_get_unaligned_uint16((data) + (offset))) \
Dave Rodgmanfbc23222022-11-24 18:07:37 +0000362 )
Dave Rodgmanfbc23222022-11-24 18:07:37 +0000363
364/**
365 * Put in memory a 16 bits unsigned integer in big-endian order.
366 *
367 * \param n 16 bits unsigned integer to put in memory.
368 * \param data Base address of the memory where to put the 16
369 * bits unsigned integer in.
370 * \param offset Offset from \p data where to put the most significant
371 * byte of the 16 bits unsigned integer \p n.
372 */
Dave Rodgman914c6322023-03-01 09:30:14 +0000373#define MBEDTLS_PUT_UINT16_BE(n, data, offset) \
Gilles Peskine449bd832023-01-11 14:50:10 +0100374 { \
Dave Rodgman914c6322023-03-01 09:30:14 +0000375 if (MBEDTLS_IS_BIG_ENDIAN) \
Gilles Peskine449bd832023-01-11 14:50:10 +0100376 { \
Dave Rodgman914c6322023-03-01 09:30:14 +0000377 mbedtls_put_unaligned_uint16((data) + (offset), (uint16_t) (n)); \
Gilles Peskine449bd832023-01-11 14:50:10 +0100378 } \
379 else \
380 { \
381 mbedtls_put_unaligned_uint16((data) + (offset), MBEDTLS_BSWAP16((uint16_t) (n))); \
382 } \
383 }
Dave Rodgmanfbc23222022-11-24 18:07:37 +0000384
385/**
386 * Get the unsigned 24 bits integer corresponding to three bytes in
387 * big-endian order (MSB first).
388 *
389 * \param data Base address of the memory to get the three bytes from.
390 * \param offset Offset from \p data of the first and most significant
391 * byte of the three bytes to build the 24 bits unsigned
392 * integer from.
393 */
Dave Rodgman914c6322023-03-01 09:30:14 +0000394#define MBEDTLS_GET_UINT24_BE(data, offset) \
395 ( \
396 ((uint32_t) (data)[(offset)] << 16) \
397 | ((uint32_t) (data)[(offset) + 1] << 8) \
398 | ((uint32_t) (data)[(offset) + 2]) \
Dave Rodgmanfbc23222022-11-24 18:07:37 +0000399 )
Dave Rodgmanfbc23222022-11-24 18:07:37 +0000400
401/**
402 * Put in memory a 24 bits unsigned integer in big-endian order.
403 *
404 * \param n 24 bits unsigned integer to put in memory.
405 * \param data Base address of the memory where to put the 24
406 * bits unsigned integer in.
407 * \param offset Offset from \p data where to put the most significant
408 * byte of the 24 bits unsigned integer \p n.
409 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100410#define MBEDTLS_PUT_UINT24_BE(n, data, offset) \
Dave Rodgman914c6322023-03-01 09:30:14 +0000411 { \
412 (data)[(offset)] = MBEDTLS_BYTE_2(n); \
Gilles Peskine449bd832023-01-11 14:50:10 +0100413 (data)[(offset) + 1] = MBEDTLS_BYTE_1(n); \
414 (data)[(offset) + 2] = MBEDTLS_BYTE_0(n); \
415 }
Dave Rodgmanfbc23222022-11-24 18:07:37 +0000416
417/**
418 * Get the unsigned 24 bits integer corresponding to three bytes in
419 * little-endian order (LSB first).
420 *
421 * \param data Base address of the memory to get the three bytes from.
422 * \param offset Offset from \p data of the first and least significant
423 * byte of the three bytes to build the 24 bits unsigned
424 * integer from.
425 */
Dave Rodgman914c6322023-03-01 09:30:14 +0000426#define MBEDTLS_GET_UINT24_LE(data, offset) \
427 ( \
428 ((uint32_t) (data)[(offset)]) \
Gilles Peskine449bd832023-01-11 14:50:10 +0100429 | ((uint32_t) (data)[(offset) + 1] << 8) \
430 | ((uint32_t) (data)[(offset) + 2] << 16) \
Dave Rodgmanfbc23222022-11-24 18:07:37 +0000431 )
Dave Rodgmanfbc23222022-11-24 18:07:37 +0000432
433/**
434 * Put in memory a 24 bits unsigned integer in little-endian order.
435 *
436 * \param n 24 bits unsigned integer to put in memory.
437 * \param data Base address of the memory where to put the 24
438 * bits unsigned integer in.
439 * \param offset Offset from \p data where to put the least significant
440 * byte of the 24 bits unsigned integer \p n.
441 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100442#define MBEDTLS_PUT_UINT24_LE(n, data, offset) \
Dave Rodgman914c6322023-03-01 09:30:14 +0000443 { \
444 (data)[(offset)] = MBEDTLS_BYTE_0(n); \
Gilles Peskine449bd832023-01-11 14:50:10 +0100445 (data)[(offset) + 1] = MBEDTLS_BYTE_1(n); \
446 (data)[(offset) + 2] = MBEDTLS_BYTE_2(n); \
447 }
Dave Rodgmanfbc23222022-11-24 18:07:37 +0000448
449/**
450 * Get the unsigned 64 bits integer corresponding to eight bytes in
451 * big-endian order (MSB first).
452 *
453 * \param data Base address of the memory to get the eight bytes from.
454 * \param offset Offset from \p data of the first and most significant
455 * byte of the eight bytes to build the 64 bits unsigned
456 * integer from.
457 */
Dave Rodgman914c6322023-03-01 09:30:14 +0000458#define MBEDTLS_GET_UINT64_BE(data, offset) \
459 ((MBEDTLS_IS_BIG_ENDIAN) \
Dave Rodgmana5110b02022-11-28 14:48:45 +0000460 ? mbedtls_get_unaligned_uint64((data) + (offset)) \
461 : MBEDTLS_BSWAP64(mbedtls_get_unaligned_uint64((data) + (offset))) \
Dave Rodgmanfbc23222022-11-24 18:07:37 +0000462 )
Dave Rodgmanfbc23222022-11-24 18:07:37 +0000463
464/**
465 * Put in memory a 64 bits unsigned integer in big-endian order.
466 *
467 * \param n 64 bits unsigned integer to put in memory.
468 * \param data Base address of the memory where to put the 64
469 * bits unsigned integer in.
470 * \param offset Offset from \p data where to put the most significant
471 * byte of the 64 bits unsigned integer \p n.
472 */
Dave Rodgman914c6322023-03-01 09:30:14 +0000473#define MBEDTLS_PUT_UINT64_BE(n, data, offset) \
Gilles Peskine449bd832023-01-11 14:50:10 +0100474 { \
Dave Rodgman914c6322023-03-01 09:30:14 +0000475 if (MBEDTLS_IS_BIG_ENDIAN) \
Gilles Peskine449bd832023-01-11 14:50:10 +0100476 { \
Dave Rodgman914c6322023-03-01 09:30:14 +0000477 mbedtls_put_unaligned_uint64((data) + (offset), (uint64_t) (n)); \
Gilles Peskine449bd832023-01-11 14:50:10 +0100478 } \
479 else \
480 { \
481 mbedtls_put_unaligned_uint64((data) + (offset), MBEDTLS_BSWAP64((uint64_t) (n))); \
482 } \
483 }
Dave Rodgmanfbc23222022-11-24 18:07:37 +0000484
485/**
486 * Get the unsigned 64 bits integer corresponding to eight bytes in
487 * little-endian order (LSB first).
488 *
489 * \param data Base address of the memory to get the eight bytes from.
490 * \param offset Offset from \p data of the first and least significant
491 * byte of the eight bytes to build the 64 bits unsigned
492 * integer from.
493 */
Dave Rodgman914c6322023-03-01 09:30:14 +0000494#define MBEDTLS_GET_UINT64_LE(data, offset) \
495 ((MBEDTLS_IS_BIG_ENDIAN) \
Dave Rodgmana5110b02022-11-28 14:48:45 +0000496 ? MBEDTLS_BSWAP64(mbedtls_get_unaligned_uint64((data) + (offset))) \
497 : mbedtls_get_unaligned_uint64((data) + (offset)) \
Dave Rodgmanfbc23222022-11-24 18:07:37 +0000498 )
Dave Rodgmanfbc23222022-11-24 18:07:37 +0000499
500/**
501 * Put in memory a 64 bits unsigned integer in little-endian order.
502 *
503 * \param n 64 bits unsigned integer to put in memory.
504 * \param data Base address of the memory where to put the 64
505 * bits unsigned integer in.
506 * \param offset Offset from \p data where to put the least significant
507 * byte of the 64 bits unsigned integer \p n.
508 */
Dave Rodgman914c6322023-03-01 09:30:14 +0000509#define MBEDTLS_PUT_UINT64_LE(n, data, offset) \
Gilles Peskine449bd832023-01-11 14:50:10 +0100510 { \
Dave Rodgman914c6322023-03-01 09:30:14 +0000511 if (MBEDTLS_IS_BIG_ENDIAN) \
Gilles Peskine449bd832023-01-11 14:50:10 +0100512 { \
513 mbedtls_put_unaligned_uint64((data) + (offset), MBEDTLS_BSWAP64((uint64_t) (n))); \
514 } \
515 else \
516 { \
Dave Rodgman914c6322023-03-01 09:30:14 +0000517 mbedtls_put_unaligned_uint64((data) + (offset), (uint64_t) (n)); \
Gilles Peskine449bd832023-01-11 14:50:10 +0100518 } \
519 }
Dave Rodgmanfbc23222022-11-24 18:07:37 +0000520
521#endif /* MBEDTLS_LIBRARY_ALIGNMENT_H */