blob: 41823485ad733060178dcabfec4fe52dc04b5a3c [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)
Dave Rodgman2dae4b32022-11-30 12:07:36 +0000184#define MBEDTLS_BSWAP32 __rev
185#endif
186
Dave Rodgmanf7f1f742022-11-28 14:52:45 +0000187/*
188 * Where compiler built-ins are not present, fall back to C code that the
189 * compiler may be able to detect and transform into the relevant bswap or
190 * similar instruction.
191 */
192#if !defined(MBEDTLS_BSWAP16)
Gilles Peskine449bd832023-01-11 14:50:10 +0100193static inline uint16_t mbedtls_bswap16(uint16_t x)
194{
Dave Rodgman6298b242022-11-28 14:51:49 +0000195 return
Gilles Peskine449bd832023-01-11 14:50:10 +0100196 (x & 0x00ff) << 8 |
197 (x & 0xff00) >> 8;
Dave Rodgman6298b242022-11-28 14:51:49 +0000198}
199#define MBEDTLS_BSWAP16 mbedtls_bswap16
Dave Rodgmanf7f1f742022-11-28 14:52:45 +0000200#endif /* !defined(MBEDTLS_BSWAP16) */
Dave Rodgman6298b242022-11-28 14:51:49 +0000201
Dave Rodgmanf7f1f742022-11-28 14:52:45 +0000202#if !defined(MBEDTLS_BSWAP32)
Gilles Peskine449bd832023-01-11 14:50:10 +0100203static inline uint32_t mbedtls_bswap32(uint32_t x)
204{
Dave Rodgman6298b242022-11-28 14:51:49 +0000205 return
Gilles Peskine449bd832023-01-11 14:50:10 +0100206 (x & 0x000000ff) << 24 |
207 (x & 0x0000ff00) << 8 |
208 (x & 0x00ff0000) >> 8 |
209 (x & 0xff000000) >> 24;
Dave Rodgman6298b242022-11-28 14:51:49 +0000210}
211#define MBEDTLS_BSWAP32 mbedtls_bswap32
Dave Rodgmanf7f1f742022-11-28 14:52:45 +0000212#endif /* !defined(MBEDTLS_BSWAP32) */
Dave Rodgman6298b242022-11-28 14:51:49 +0000213
Dave Rodgmanf7f1f742022-11-28 14:52:45 +0000214#if !defined(MBEDTLS_BSWAP64)
Gilles Peskine449bd832023-01-11 14:50:10 +0100215static inline uint64_t mbedtls_bswap64(uint64_t x)
216{
Dave Rodgman6298b242022-11-28 14:51:49 +0000217 return
Tom Cosgrovebbe166e2023-03-08 13:23:24 +0000218 (x & 0x00000000000000ffULL) << 56 |
219 (x & 0x000000000000ff00ULL) << 40 |
220 (x & 0x0000000000ff0000ULL) << 24 |
221 (x & 0x00000000ff000000ULL) << 8 |
222 (x & 0x000000ff00000000ULL) >> 8 |
223 (x & 0x0000ff0000000000ULL) >> 24 |
224 (x & 0x00ff000000000000ULL) >> 40 |
225 (x & 0xff00000000000000ULL) >> 56;
Dave Rodgman6298b242022-11-28 14:51:49 +0000226}
227#define MBEDTLS_BSWAP64 mbedtls_bswap64
Dave Rodgmanf7f1f742022-11-28 14:52:45 +0000228#endif /* !defined(MBEDTLS_BSWAP64) */
Dave Rodgman6298b242022-11-28 14:51:49 +0000229
Dave Rodgmane5c42592022-11-28 14:47:46 +0000230#if !defined(__BYTE_ORDER__)
231static const uint16_t mbedtls_byte_order_detector = { 0x100 };
232#define MBEDTLS_IS_BIG_ENDIAN (*((unsigned char *) (&mbedtls_byte_order_detector)) == 0x01)
233#else
234#define MBEDTLS_IS_BIG_ENDIAN ((__BYTE_ORDER__) == (__ORDER_BIG_ENDIAN__))
235#endif /* !defined(__BYTE_ORDER__) */
236
Dave Rodgmanfbc23222022-11-24 18:07:37 +0000237/**
238 * Get the unsigned 32 bits integer corresponding to four bytes in
239 * big-endian order (MSB first).
240 *
241 * \param data Base address of the memory to get the four bytes from.
242 * \param offset Offset from \p data of the first and most significant
243 * byte of the four bytes to build the 32 bits unsigned
244 * integer from.
245 */
Dave Rodgman914c6322023-03-01 09:30:14 +0000246#define MBEDTLS_GET_UINT32_BE(data, offset) \
247 ((MBEDTLS_IS_BIG_ENDIAN) \
Dave Rodgmana5110b02022-11-28 14:48:45 +0000248 ? mbedtls_get_unaligned_uint32((data) + (offset)) \
249 : MBEDTLS_BSWAP32(mbedtls_get_unaligned_uint32((data) + (offset))) \
Dave Rodgmanfbc23222022-11-24 18:07:37 +0000250 )
Dave Rodgmanfbc23222022-11-24 18:07:37 +0000251
252/**
253 * Put in memory a 32 bits unsigned integer in big-endian order.
254 *
255 * \param n 32 bits unsigned integer to put in memory.
256 * \param data Base address of the memory where to put the 32
257 * bits unsigned integer in.
258 * \param offset Offset from \p data where to put the most significant
259 * byte of the 32 bits unsigned integer \p n.
260 */
Dave Rodgman914c6322023-03-01 09:30:14 +0000261#define MBEDTLS_PUT_UINT32_BE(n, data, offset) \
Gilles Peskine449bd832023-01-11 14:50:10 +0100262 { \
Dave Rodgman914c6322023-03-01 09:30:14 +0000263 if (MBEDTLS_IS_BIG_ENDIAN) \
Gilles Peskine449bd832023-01-11 14:50:10 +0100264 { \
Dave Rodgman914c6322023-03-01 09:30:14 +0000265 mbedtls_put_unaligned_uint32((data) + (offset), (uint32_t) (n)); \
Gilles Peskine449bd832023-01-11 14:50:10 +0100266 } \
267 else \
268 { \
269 mbedtls_put_unaligned_uint32((data) + (offset), MBEDTLS_BSWAP32((uint32_t) (n))); \
270 } \
271 }
Dave Rodgmanfbc23222022-11-24 18:07:37 +0000272
273/**
274 * Get the unsigned 32 bits integer corresponding to four bytes in
275 * little-endian order (LSB first).
276 *
277 * \param data Base address of the memory to get the four bytes from.
278 * \param offset Offset from \p data of the first and least significant
279 * byte of the four bytes to build the 32 bits unsigned
280 * integer from.
281 */
Dave Rodgman914c6322023-03-01 09:30:14 +0000282#define MBEDTLS_GET_UINT32_LE(data, offset) \
283 ((MBEDTLS_IS_BIG_ENDIAN) \
Dave Rodgmana5110b02022-11-28 14:48:45 +0000284 ? MBEDTLS_BSWAP32(mbedtls_get_unaligned_uint32((data) + (offset))) \
285 : mbedtls_get_unaligned_uint32((data) + (offset)) \
Dave Rodgmanfbc23222022-11-24 18:07:37 +0000286 )
Dave Rodgmana5110b02022-11-28 14:48:45 +0000287
Dave Rodgmanfbc23222022-11-24 18:07:37 +0000288
289/**
290 * Put in memory a 32 bits unsigned integer in little-endian order.
291 *
292 * \param n 32 bits unsigned integer to put in memory.
293 * \param data Base address of the memory where to put the 32
294 * bits unsigned integer in.
295 * \param offset Offset from \p data where to put the least significant
296 * byte of the 32 bits unsigned integer \p n.
297 */
Dave Rodgman914c6322023-03-01 09:30:14 +0000298#define MBEDTLS_PUT_UINT32_LE(n, data, offset) \
Gilles Peskine449bd832023-01-11 14:50:10 +0100299 { \
Dave Rodgman914c6322023-03-01 09:30:14 +0000300 if (MBEDTLS_IS_BIG_ENDIAN) \
Gilles Peskine449bd832023-01-11 14:50:10 +0100301 { \
302 mbedtls_put_unaligned_uint32((data) + (offset), MBEDTLS_BSWAP32((uint32_t) (n))); \
303 } \
304 else \
305 { \
Dave Rodgman914c6322023-03-01 09:30:14 +0000306 mbedtls_put_unaligned_uint32((data) + (offset), ((uint32_t) (n))); \
Gilles Peskine449bd832023-01-11 14:50:10 +0100307 } \
308 }
Dave Rodgmanfbc23222022-11-24 18:07:37 +0000309
310/**
311 * Get the unsigned 16 bits integer corresponding to two bytes in
312 * little-endian order (LSB first).
313 *
314 * \param data Base address of the memory to get the two bytes from.
315 * \param offset Offset from \p data of the first and least significant
316 * byte of the two bytes to build the 16 bits unsigned
317 * integer from.
318 */
Dave Rodgman914c6322023-03-01 09:30:14 +0000319#define MBEDTLS_GET_UINT16_LE(data, offset) \
320 ((MBEDTLS_IS_BIG_ENDIAN) \
Dave Rodgmana5110b02022-11-28 14:48:45 +0000321 ? MBEDTLS_BSWAP16(mbedtls_get_unaligned_uint16((data) + (offset))) \
322 : mbedtls_get_unaligned_uint16((data) + (offset)) \
Dave Rodgmanfbc23222022-11-24 18:07:37 +0000323 )
Dave Rodgmanfbc23222022-11-24 18:07:37 +0000324
325/**
326 * Put in memory a 16 bits unsigned integer in little-endian order.
327 *
328 * \param n 16 bits unsigned integer to put in memory.
329 * \param data Base address of the memory where to put the 16
330 * bits unsigned integer in.
331 * \param offset Offset from \p data where to put the least significant
332 * byte of the 16 bits unsigned integer \p n.
333 */
Dave Rodgman914c6322023-03-01 09:30:14 +0000334#define MBEDTLS_PUT_UINT16_LE(n, data, offset) \
Gilles Peskine449bd832023-01-11 14:50:10 +0100335 { \
Dave Rodgman914c6322023-03-01 09:30:14 +0000336 if (MBEDTLS_IS_BIG_ENDIAN) \
Gilles Peskine449bd832023-01-11 14:50:10 +0100337 { \
338 mbedtls_put_unaligned_uint16((data) + (offset), MBEDTLS_BSWAP16((uint16_t) (n))); \
339 } \
340 else \
341 { \
Dave Rodgman914c6322023-03-01 09:30:14 +0000342 mbedtls_put_unaligned_uint16((data) + (offset), (uint16_t) (n)); \
Gilles Peskine449bd832023-01-11 14:50:10 +0100343 } \
344 }
Dave Rodgmanfbc23222022-11-24 18:07:37 +0000345
346/**
347 * Get the unsigned 16 bits integer corresponding to two bytes in
348 * big-endian order (MSB first).
349 *
350 * \param data Base address of the memory to get the two bytes from.
351 * \param offset Offset from \p data of the first and most significant
352 * byte of the two bytes to build the 16 bits unsigned
353 * integer from.
354 */
Dave Rodgman914c6322023-03-01 09:30:14 +0000355#define MBEDTLS_GET_UINT16_BE(data, offset) \
356 ((MBEDTLS_IS_BIG_ENDIAN) \
Dave Rodgmana5110b02022-11-28 14:48:45 +0000357 ? mbedtls_get_unaligned_uint16((data) + (offset)) \
358 : MBEDTLS_BSWAP16(mbedtls_get_unaligned_uint16((data) + (offset))) \
Dave Rodgmanfbc23222022-11-24 18:07:37 +0000359 )
Dave Rodgmanfbc23222022-11-24 18:07:37 +0000360
361/**
362 * Put in memory a 16 bits unsigned integer in big-endian order.
363 *
364 * \param n 16 bits unsigned integer to put in memory.
365 * \param data Base address of the memory where to put the 16
366 * bits unsigned integer in.
367 * \param offset Offset from \p data where to put the most significant
368 * byte of the 16 bits unsigned integer \p n.
369 */
Dave Rodgman914c6322023-03-01 09:30:14 +0000370#define MBEDTLS_PUT_UINT16_BE(n, data, offset) \
Gilles Peskine449bd832023-01-11 14:50:10 +0100371 { \
Dave Rodgman914c6322023-03-01 09:30:14 +0000372 if (MBEDTLS_IS_BIG_ENDIAN) \
Gilles Peskine449bd832023-01-11 14:50:10 +0100373 { \
Dave Rodgman914c6322023-03-01 09:30:14 +0000374 mbedtls_put_unaligned_uint16((data) + (offset), (uint16_t) (n)); \
Gilles Peskine449bd832023-01-11 14:50:10 +0100375 } \
376 else \
377 { \
378 mbedtls_put_unaligned_uint16((data) + (offset), MBEDTLS_BSWAP16((uint16_t) (n))); \
379 } \
380 }
Dave Rodgmanfbc23222022-11-24 18:07:37 +0000381
382/**
383 * Get the unsigned 24 bits integer corresponding to three bytes in
384 * big-endian order (MSB first).
385 *
386 * \param data Base address of the memory to get the three bytes from.
387 * \param offset Offset from \p data of the first and most significant
388 * byte of the three bytes to build the 24 bits unsigned
389 * integer from.
390 */
Dave Rodgman914c6322023-03-01 09:30:14 +0000391#define MBEDTLS_GET_UINT24_BE(data, offset) \
392 ( \
393 ((uint32_t) (data)[(offset)] << 16) \
394 | ((uint32_t) (data)[(offset) + 1] << 8) \
395 | ((uint32_t) (data)[(offset) + 2]) \
Dave Rodgmanfbc23222022-11-24 18:07:37 +0000396 )
Dave Rodgmanfbc23222022-11-24 18:07:37 +0000397
398/**
399 * Put in memory a 24 bits unsigned integer in big-endian order.
400 *
401 * \param n 24 bits unsigned integer to put in memory.
402 * \param data Base address of the memory where to put the 24
403 * bits unsigned integer in.
404 * \param offset Offset from \p data where to put the most significant
405 * byte of the 24 bits unsigned integer \p n.
406 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100407#define MBEDTLS_PUT_UINT24_BE(n, data, offset) \
Dave Rodgman914c6322023-03-01 09:30:14 +0000408 { \
409 (data)[(offset)] = MBEDTLS_BYTE_2(n); \
Gilles Peskine449bd832023-01-11 14:50:10 +0100410 (data)[(offset) + 1] = MBEDTLS_BYTE_1(n); \
411 (data)[(offset) + 2] = MBEDTLS_BYTE_0(n); \
412 }
Dave Rodgmanfbc23222022-11-24 18:07:37 +0000413
414/**
415 * Get the unsigned 24 bits integer corresponding to three bytes in
416 * little-endian order (LSB first).
417 *
418 * \param data Base address of the memory to get the three bytes from.
419 * \param offset Offset from \p data of the first and least significant
420 * byte of the three bytes to build the 24 bits unsigned
421 * integer from.
422 */
Dave Rodgman914c6322023-03-01 09:30:14 +0000423#define MBEDTLS_GET_UINT24_LE(data, offset) \
424 ( \
425 ((uint32_t) (data)[(offset)]) \
Gilles Peskine449bd832023-01-11 14:50:10 +0100426 | ((uint32_t) (data)[(offset) + 1] << 8) \
427 | ((uint32_t) (data)[(offset) + 2] << 16) \
Dave Rodgmanfbc23222022-11-24 18:07:37 +0000428 )
Dave Rodgmanfbc23222022-11-24 18:07:37 +0000429
430/**
431 * Put in memory a 24 bits unsigned integer in little-endian order.
432 *
433 * \param n 24 bits unsigned integer to put in memory.
434 * \param data Base address of the memory where to put the 24
435 * bits unsigned integer in.
436 * \param offset Offset from \p data where to put the least significant
437 * byte of the 24 bits unsigned integer \p n.
438 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100439#define MBEDTLS_PUT_UINT24_LE(n, data, offset) \
Dave Rodgman914c6322023-03-01 09:30:14 +0000440 { \
441 (data)[(offset)] = MBEDTLS_BYTE_0(n); \
Gilles Peskine449bd832023-01-11 14:50:10 +0100442 (data)[(offset) + 1] = MBEDTLS_BYTE_1(n); \
443 (data)[(offset) + 2] = MBEDTLS_BYTE_2(n); \
444 }
Dave Rodgmanfbc23222022-11-24 18:07:37 +0000445
446/**
447 * Get the unsigned 64 bits integer corresponding to eight bytes in
448 * big-endian order (MSB first).
449 *
450 * \param data Base address of the memory to get the eight bytes from.
451 * \param offset Offset from \p data of the first and most significant
452 * byte of the eight bytes to build the 64 bits unsigned
453 * integer from.
454 */
Dave Rodgman914c6322023-03-01 09:30:14 +0000455#define MBEDTLS_GET_UINT64_BE(data, offset) \
456 ((MBEDTLS_IS_BIG_ENDIAN) \
Dave Rodgmana5110b02022-11-28 14:48:45 +0000457 ? mbedtls_get_unaligned_uint64((data) + (offset)) \
458 : MBEDTLS_BSWAP64(mbedtls_get_unaligned_uint64((data) + (offset))) \
Dave Rodgmanfbc23222022-11-24 18:07:37 +0000459 )
Dave Rodgmanfbc23222022-11-24 18:07:37 +0000460
461/**
462 * Put in memory a 64 bits unsigned integer in big-endian order.
463 *
464 * \param n 64 bits unsigned integer to put in memory.
465 * \param data Base address of the memory where to put the 64
466 * bits unsigned integer in.
467 * \param offset Offset from \p data where to put the most significant
468 * byte of the 64 bits unsigned integer \p n.
469 */
Dave Rodgman914c6322023-03-01 09:30:14 +0000470#define MBEDTLS_PUT_UINT64_BE(n, data, offset) \
Gilles Peskine449bd832023-01-11 14:50:10 +0100471 { \
Dave Rodgman914c6322023-03-01 09:30:14 +0000472 if (MBEDTLS_IS_BIG_ENDIAN) \
Gilles Peskine449bd832023-01-11 14:50:10 +0100473 { \
Dave Rodgman914c6322023-03-01 09:30:14 +0000474 mbedtls_put_unaligned_uint64((data) + (offset), (uint64_t) (n)); \
Gilles Peskine449bd832023-01-11 14:50:10 +0100475 } \
476 else \
477 { \
478 mbedtls_put_unaligned_uint64((data) + (offset), MBEDTLS_BSWAP64((uint64_t) (n))); \
479 } \
480 }
Dave Rodgmanfbc23222022-11-24 18:07:37 +0000481
482/**
483 * Get the unsigned 64 bits integer corresponding to eight bytes in
484 * little-endian order (LSB first).
485 *
486 * \param data Base address of the memory to get the eight bytes from.
487 * \param offset Offset from \p data of the first and least significant
488 * byte of the eight bytes to build the 64 bits unsigned
489 * integer from.
490 */
Dave Rodgman914c6322023-03-01 09:30:14 +0000491#define MBEDTLS_GET_UINT64_LE(data, offset) \
492 ((MBEDTLS_IS_BIG_ENDIAN) \
Dave Rodgmana5110b02022-11-28 14:48:45 +0000493 ? MBEDTLS_BSWAP64(mbedtls_get_unaligned_uint64((data) + (offset))) \
494 : mbedtls_get_unaligned_uint64((data) + (offset)) \
Dave Rodgmanfbc23222022-11-24 18:07:37 +0000495 )
Dave Rodgmanfbc23222022-11-24 18:07:37 +0000496
497/**
498 * Put in memory a 64 bits unsigned integer in little-endian order.
499 *
500 * \param n 64 bits unsigned integer to put in memory.
501 * \param data Base address of the memory where to put the 64
502 * bits unsigned integer in.
503 * \param offset Offset from \p data where to put the least significant
504 * byte of the 64 bits unsigned integer \p n.
505 */
Dave Rodgman914c6322023-03-01 09:30:14 +0000506#define MBEDTLS_PUT_UINT64_LE(n, data, offset) \
Gilles Peskine449bd832023-01-11 14:50:10 +0100507 { \
Dave Rodgman914c6322023-03-01 09:30:14 +0000508 if (MBEDTLS_IS_BIG_ENDIAN) \
Gilles Peskine449bd832023-01-11 14:50:10 +0100509 { \
510 mbedtls_put_unaligned_uint64((data) + (offset), MBEDTLS_BSWAP64((uint64_t) (n))); \
511 } \
512 else \
513 { \
Dave Rodgman914c6322023-03-01 09:30:14 +0000514 mbedtls_put_unaligned_uint64((data) + (offset), (uint64_t) (n)); \
Gilles Peskine449bd832023-01-11 14:50:10 +0100515 } \
516 }
Dave Rodgmanfbc23222022-11-24 18:07:37 +0000517
518#endif /* MBEDTLS_LIBRARY_ALIGNMENT_H */