alignment.h 26 KB

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