blob: 3f8926e2919100223c4afe19589df305869dab18 [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 Rodgmanfbc23222022-11-24 18:07:37 +000028
Dave Rodgmana616afe2022-11-25 17:11:45 +000029#include "mbedtls/build_info.h"
Dave Rodgman8f6583d2022-11-25 09:16:41 +000030
Dave Rodgman96d61d12022-11-24 19:33:22 +000031/**
Dave Rodgmana360e192022-11-28 14:44:05 +000032 * Read the unsigned 16 bits integer from the given address, which need not
33 * be aligned.
34 *
35 * \param p pointer to 2 bytes of data
36 * \return Data at the given address
37 */
38inline uint16_t mbedtls_get_unaligned_uint16( const void *p )
39{
40 uint16_t r;
41 memcpy( &r, p, sizeof( r ) );
42 return r;
43}
44
45/**
46 * Write the unsigned 16 bits integer to the given address, which need not
47 * be aligned.
48 *
49 * \param p pointer to 2 bytes of data
50 * \param x data to write
51 */
52inline void mbedtls_put_unaligned_uint16( void *p, uint16_t x )
53{
54 memcpy( p, &x, sizeof( x ) );
55}
56
57/**
Dave Rodgman96d61d12022-11-24 19:33:22 +000058 * Read the unsigned 32 bits integer from the given address, which need not
59 * be aligned.
Dave Rodgmanfbc23222022-11-24 18:07:37 +000060 *
Dave Rodgman96d61d12022-11-24 19:33:22 +000061 * \param p pointer to 4 bytes of data
Dave Rodgman875d2382022-11-24 20:43:15 +000062 * \return Data at the given address
Dave Rodgmanfbc23222022-11-24 18:07:37 +000063 */
Dave Rodgman7a910a82022-11-24 21:17:40 +000064inline uint32_t mbedtls_get_unaligned_uint32( const void *p )
Dave Rodgman96d61d12022-11-24 19:33:22 +000065{
66 uint32_t r;
Dave Rodgman7a910a82022-11-24 21:17:40 +000067 memcpy( &r, p, sizeof( r ) );
Dave Rodgman96d61d12022-11-24 19:33:22 +000068 return r;
69}
Dave Rodgmanfbc23222022-11-24 18:07:37 +000070
Dave Rodgman96d61d12022-11-24 19:33:22 +000071/**
72 * Write the unsigned 32 bits integer to the given address, which need not
73 * be aligned.
74 *
75 * \param p pointer to 4 bytes of data
76 * \param x data to write
77 */
Dave Rodgman66433442022-11-24 20:07:39 +000078inline void mbedtls_put_unaligned_uint32( void *p, uint32_t x )
Dave Rodgman96d61d12022-11-24 19:33:22 +000079{
Dave Rodgman7a910a82022-11-24 21:17:40 +000080 memcpy( p, &x, sizeof( x ) );
Dave Rodgman96d61d12022-11-24 19:33:22 +000081}
Dave Rodgmanfbc23222022-11-24 18:07:37 +000082
Dave Rodgmana360e192022-11-28 14:44:05 +000083/**
84 * Read the unsigned 64 bits integer from the given address, which need not
85 * be aligned.
86 *
87 * \param p pointer to 8 bytes of data
88 * \return Data at the given address
89 */
90inline uint64_t mbedtls_get_unaligned_uint64( const void *p )
91{
92 uint64_t r;
93 memcpy( &r, p, sizeof( r ) );
94 return r;
95}
96
97/**
98 * Write the unsigned 64 bits integer to the given address, which need not
99 * be aligned.
100 *
101 * \param p pointer to 8 bytes of data
102 * \param x data to write
103 */
104inline void mbedtls_put_unaligned_uint64( void *p, uint64_t x )
105{
106 memcpy( p, &x, sizeof( x ) );
107}
108
Dave Rodgmanfbc23222022-11-24 18:07:37 +0000109/** Byte Reading Macros
110 *
111 * Given a multi-byte integer \p x, MBEDTLS_BYTE_n retrieves the n-th
112 * byte from x, where byte 0 is the least significant byte.
113 */
114#define MBEDTLS_BYTE_0( x ) ( (uint8_t) ( ( x ) & 0xff ) )
115#define MBEDTLS_BYTE_1( x ) ( (uint8_t) ( ( ( x ) >> 8 ) & 0xff ) )
116#define MBEDTLS_BYTE_2( x ) ( (uint8_t) ( ( ( x ) >> 16 ) & 0xff ) )
117#define MBEDTLS_BYTE_3( x ) ( (uint8_t) ( ( ( x ) >> 24 ) & 0xff ) )
118#define MBEDTLS_BYTE_4( x ) ( (uint8_t) ( ( ( x ) >> 32 ) & 0xff ) )
119#define MBEDTLS_BYTE_5( x ) ( (uint8_t) ( ( ( x ) >> 40 ) & 0xff ) )
120#define MBEDTLS_BYTE_6( x ) ( (uint8_t) ( ( ( x ) >> 48 ) & 0xff ) )
121#define MBEDTLS_BYTE_7( x ) ( (uint8_t) ( ( ( x ) >> 56 ) & 0xff ) )
122
Dave Rodgmane5c42592022-11-28 14:47:46 +0000123#if !defined(__BYTE_ORDER__)
124static const uint16_t mbedtls_byte_order_detector = { 0x100 };
125#define MBEDTLS_IS_BIG_ENDIAN (*((unsigned char *) (&mbedtls_byte_order_detector)) == 0x01)
126#else
127#define MBEDTLS_IS_BIG_ENDIAN ((__BYTE_ORDER__) == (__ORDER_BIG_ENDIAN__))
128#endif /* !defined(__BYTE_ORDER__) */
129
Dave Rodgmanfbc23222022-11-24 18:07:37 +0000130/**
131 * Get the unsigned 32 bits integer corresponding to four bytes in
132 * big-endian order (MSB first).
133 *
134 * \param data Base address of the memory to get the four bytes from.
135 * \param offset Offset from \p data of the first and most significant
136 * byte of the four bytes to build the 32 bits unsigned
137 * integer from.
138 */
139#ifndef MBEDTLS_GET_UINT32_BE
140#define MBEDTLS_GET_UINT32_BE( data , offset ) \
141 ( \
142 ( (uint32_t) ( data )[( offset ) ] << 24 ) \
143 | ( (uint32_t) ( data )[( offset ) + 1] << 16 ) \
144 | ( (uint32_t) ( data )[( offset ) + 2] << 8 ) \
145 | ( (uint32_t) ( data )[( offset ) + 3] ) \
146 )
147#endif
148
149/**
150 * Put in memory a 32 bits unsigned integer in big-endian order.
151 *
152 * \param n 32 bits unsigned integer to put in memory.
153 * \param data Base address of the memory where to put the 32
154 * bits unsigned integer in.
155 * \param offset Offset from \p data where to put the most significant
156 * byte of the 32 bits unsigned integer \p n.
157 */
158#ifndef MBEDTLS_PUT_UINT32_BE
159#define MBEDTLS_PUT_UINT32_BE( n, data, offset ) \
160{ \
161 ( data )[( offset ) ] = MBEDTLS_BYTE_3( n ); \
162 ( data )[( offset ) + 1] = MBEDTLS_BYTE_2( n ); \
163 ( data )[( offset ) + 2] = MBEDTLS_BYTE_1( n ); \
164 ( data )[( offset ) + 3] = MBEDTLS_BYTE_0( n ); \
165}
166#endif
167
168/**
169 * Get the unsigned 32 bits integer corresponding to four bytes in
170 * little-endian order (LSB first).
171 *
172 * \param data Base address of the memory to get the four bytes from.
173 * \param offset Offset from \p data of the first and least significant
174 * byte of the four bytes to build the 32 bits unsigned
175 * integer from.
176 */
177#ifndef MBEDTLS_GET_UINT32_LE
178#define MBEDTLS_GET_UINT32_LE( data, offset ) \
179 ( \
180 ( (uint32_t) ( data )[( offset ) ] ) \
181 | ( (uint32_t) ( data )[( offset ) + 1] << 8 ) \
182 | ( (uint32_t) ( data )[( offset ) + 2] << 16 ) \
183 | ( (uint32_t) ( data )[( offset ) + 3] << 24 ) \
184 )
185#endif
186
187/**
188 * Put in memory a 32 bits unsigned integer in little-endian order.
189 *
190 * \param n 32 bits unsigned integer to put in memory.
191 * \param data Base address of the memory where to put the 32
192 * bits unsigned integer in.
193 * \param offset Offset from \p data where to put the least significant
194 * byte of the 32 bits unsigned integer \p n.
195 */
196#ifndef MBEDTLS_PUT_UINT32_LE
197#define MBEDTLS_PUT_UINT32_LE( n, data, offset ) \
198{ \
199 ( data )[( offset ) ] = MBEDTLS_BYTE_0( n ); \
200 ( data )[( offset ) + 1] = MBEDTLS_BYTE_1( n ); \
201 ( data )[( offset ) + 2] = MBEDTLS_BYTE_2( n ); \
202 ( data )[( offset ) + 3] = MBEDTLS_BYTE_3( n ); \
203}
204#endif
205
206/**
207 * Get the unsigned 16 bits integer corresponding to two bytes in
208 * little-endian order (LSB first).
209 *
210 * \param data Base address of the memory to get the two bytes from.
211 * \param offset Offset from \p data of the first and least significant
212 * byte of the two bytes to build the 16 bits unsigned
213 * integer from.
214 */
215#ifndef MBEDTLS_GET_UINT16_LE
216#define MBEDTLS_GET_UINT16_LE( data, offset ) \
217 ( \
218 ( (uint16_t) ( data )[( offset ) ] ) \
219 | ( (uint16_t) ( data )[( offset ) + 1] << 8 ) \
220 )
221#endif
222
223/**
224 * Put in memory a 16 bits unsigned integer in little-endian order.
225 *
226 * \param n 16 bits unsigned integer to put in memory.
227 * \param data Base address of the memory where to put the 16
228 * bits unsigned integer in.
229 * \param offset Offset from \p data where to put the least significant
230 * byte of the 16 bits unsigned integer \p n.
231 */
232#ifndef MBEDTLS_PUT_UINT16_LE
233#define MBEDTLS_PUT_UINT16_LE( n, data, offset ) \
234{ \
235 ( data )[( offset ) ] = MBEDTLS_BYTE_0( n ); \
236 ( data )[( offset ) + 1] = MBEDTLS_BYTE_1( n ); \
237}
238#endif
239
240/**
241 * Get the unsigned 16 bits integer corresponding to two bytes in
242 * big-endian order (MSB first).
243 *
244 * \param data Base address of the memory to get the two bytes from.
245 * \param offset Offset from \p data of the first and most significant
246 * byte of the two bytes to build the 16 bits unsigned
247 * integer from.
248 */
249#ifndef MBEDTLS_GET_UINT16_BE
250#define MBEDTLS_GET_UINT16_BE( data, offset ) \
251 ( \
252 ( (uint16_t) ( data )[( offset ) ] << 8 ) \
253 | ( (uint16_t) ( data )[( offset ) + 1] ) \
254 )
255#endif
256
257/**
258 * Put in memory a 16 bits unsigned integer in big-endian order.
259 *
260 * \param n 16 bits unsigned integer to put in memory.
261 * \param data Base address of the memory where to put the 16
262 * bits unsigned integer in.
263 * \param offset Offset from \p data where to put the most significant
264 * byte of the 16 bits unsigned integer \p n.
265 */
266#ifndef MBEDTLS_PUT_UINT16_BE
267#define MBEDTLS_PUT_UINT16_BE( n, data, offset ) \
268{ \
269 ( data )[( offset ) ] = MBEDTLS_BYTE_1( n ); \
270 ( data )[( offset ) + 1] = MBEDTLS_BYTE_0( n ); \
271}
272#endif
273
274/**
275 * Get the unsigned 24 bits integer corresponding to three bytes in
276 * big-endian order (MSB first).
277 *
278 * \param data Base address of the memory to get the three bytes from.
279 * \param offset Offset from \p data of the first and most significant
280 * byte of the three bytes to build the 24 bits unsigned
281 * integer from.
282 */
283#ifndef MBEDTLS_GET_UINT24_BE
284#define MBEDTLS_GET_UINT24_BE( data , offset ) \
285 ( \
286 ( (uint32_t) ( data )[( offset ) ] << 16 ) \
287 | ( (uint32_t) ( data )[( offset ) + 1] << 8 ) \
288 | ( (uint32_t) ( data )[( offset ) + 2] ) \
289 )
290#endif
291
292/**
293 * Put in memory a 24 bits unsigned integer in big-endian order.
294 *
295 * \param n 24 bits unsigned integer to put in memory.
296 * \param data Base address of the memory where to put the 24
297 * bits unsigned integer in.
298 * \param offset Offset from \p data where to put the most significant
299 * byte of the 24 bits unsigned integer \p n.
300 */
301#ifndef MBEDTLS_PUT_UINT24_BE
302#define MBEDTLS_PUT_UINT24_BE( n, data, offset ) \
303{ \
304 ( data )[( offset ) ] = MBEDTLS_BYTE_2( n ); \
305 ( data )[( offset ) + 1] = MBEDTLS_BYTE_1( n ); \
306 ( data )[( offset ) + 2] = MBEDTLS_BYTE_0( n ); \
307}
308#endif
309
310/**
311 * Get the unsigned 24 bits integer corresponding to three bytes in
312 * little-endian order (LSB first).
313 *
314 * \param data Base address of the memory to get the three bytes from.
315 * \param offset Offset from \p data of the first and least significant
316 * byte of the three bytes to build the 24 bits unsigned
317 * integer from.
318 */
319#ifndef MBEDTLS_GET_UINT24_LE
320#define MBEDTLS_GET_UINT24_LE( data, offset ) \
321 ( \
322 ( (uint32_t) ( data )[( offset ) ] ) \
323 | ( (uint32_t) ( data )[( offset ) + 1] << 8 ) \
324 | ( (uint32_t) ( data )[( offset ) + 2] << 16 ) \
325 )
326#endif
327
328/**
329 * Put in memory a 24 bits unsigned integer in little-endian order.
330 *
331 * \param n 24 bits unsigned integer to put in memory.
332 * \param data Base address of the memory where to put the 24
333 * bits unsigned integer in.
334 * \param offset Offset from \p data where to put the least significant
335 * byte of the 24 bits unsigned integer \p n.
336 */
337#ifndef MBEDTLS_PUT_UINT24_LE
338#define MBEDTLS_PUT_UINT24_LE( n, data, offset ) \
339{ \
340 ( data )[( offset ) ] = MBEDTLS_BYTE_0( n ); \
341 ( data )[( offset ) + 1] = MBEDTLS_BYTE_1( n ); \
342 ( data )[( offset ) + 2] = MBEDTLS_BYTE_2( n ); \
343}
344#endif
345
346/**
347 * Get the unsigned 64 bits integer corresponding to eight bytes in
348 * big-endian order (MSB first).
349 *
350 * \param data Base address of the memory to get the eight bytes from.
351 * \param offset Offset from \p data of the first and most significant
352 * byte of the eight bytes to build the 64 bits unsigned
353 * integer from.
354 */
355#ifndef MBEDTLS_GET_UINT64_BE
356#define MBEDTLS_GET_UINT64_BE( data, offset ) \
357 ( \
358 ( (uint64_t) ( data )[( offset ) ] << 56 ) \
359 | ( (uint64_t) ( data )[( offset ) + 1] << 48 ) \
360 | ( (uint64_t) ( data )[( offset ) + 2] << 40 ) \
361 | ( (uint64_t) ( data )[( offset ) + 3] << 32 ) \
362 | ( (uint64_t) ( data )[( offset ) + 4] << 24 ) \
363 | ( (uint64_t) ( data )[( offset ) + 5] << 16 ) \
364 | ( (uint64_t) ( data )[( offset ) + 6] << 8 ) \
365 | ( (uint64_t) ( data )[( offset ) + 7] ) \
366 )
367#endif
368
369/**
370 * Put in memory a 64 bits unsigned integer in big-endian order.
371 *
372 * \param n 64 bits unsigned integer to put in memory.
373 * \param data Base address of the memory where to put the 64
374 * bits unsigned integer in.
375 * \param offset Offset from \p data where to put the most significant
376 * byte of the 64 bits unsigned integer \p n.
377 */
378#ifndef MBEDTLS_PUT_UINT64_BE
379#define MBEDTLS_PUT_UINT64_BE( n, data, offset ) \
380{ \
381 ( data )[( offset ) ] = MBEDTLS_BYTE_7( n ); \
382 ( data )[( offset ) + 1] = MBEDTLS_BYTE_6( n ); \
383 ( data )[( offset ) + 2] = MBEDTLS_BYTE_5( n ); \
384 ( data )[( offset ) + 3] = MBEDTLS_BYTE_4( n ); \
385 ( data )[( offset ) + 4] = MBEDTLS_BYTE_3( n ); \
386 ( data )[( offset ) + 5] = MBEDTLS_BYTE_2( n ); \
387 ( data )[( offset ) + 6] = MBEDTLS_BYTE_1( n ); \
388 ( data )[( offset ) + 7] = MBEDTLS_BYTE_0( n ); \
389}
390#endif
391
392/**
393 * Get the unsigned 64 bits integer corresponding to eight bytes in
394 * little-endian order (LSB first).
395 *
396 * \param data Base address of the memory to get the eight bytes from.
397 * \param offset Offset from \p data of the first and least significant
398 * byte of the eight bytes to build the 64 bits unsigned
399 * integer from.
400 */
401#ifndef MBEDTLS_GET_UINT64_LE
402#define MBEDTLS_GET_UINT64_LE( data, offset ) \
403 ( \
404 ( (uint64_t) ( data )[( offset ) + 7] << 56 ) \
405 | ( (uint64_t) ( data )[( offset ) + 6] << 48 ) \
406 | ( (uint64_t) ( data )[( offset ) + 5] << 40 ) \
407 | ( (uint64_t) ( data )[( offset ) + 4] << 32 ) \
408 | ( (uint64_t) ( data )[( offset ) + 3] << 24 ) \
409 | ( (uint64_t) ( data )[( offset ) + 2] << 16 ) \
410 | ( (uint64_t) ( data )[( offset ) + 1] << 8 ) \
411 | ( (uint64_t) ( data )[( offset ) ] ) \
412 )
413#endif
414
415/**
416 * Put in memory a 64 bits unsigned integer in little-endian order.
417 *
418 * \param n 64 bits unsigned integer to put in memory.
419 * \param data Base address of the memory where to put the 64
420 * bits unsigned integer in.
421 * \param offset Offset from \p data where to put the least significant
422 * byte of the 64 bits unsigned integer \p n.
423 */
424#ifndef MBEDTLS_PUT_UINT64_LE
425#define MBEDTLS_PUT_UINT64_LE( n, data, offset ) \
426{ \
427 ( data )[( offset ) ] = MBEDTLS_BYTE_0( n ); \
428 ( data )[( offset ) + 1] = MBEDTLS_BYTE_1( n ); \
429 ( data )[( offset ) + 2] = MBEDTLS_BYTE_2( n ); \
430 ( data )[( offset ) + 3] = MBEDTLS_BYTE_3( n ); \
431 ( data )[( offset ) + 4] = MBEDTLS_BYTE_4( n ); \
432 ( data )[( offset ) + 5] = MBEDTLS_BYTE_5( n ); \
433 ( data )[( offset ) + 6] = MBEDTLS_BYTE_6( n ); \
434 ( data )[( offset ) + 7] = MBEDTLS_BYTE_7( n ); \
435}
436#endif
437
438#endif /* MBEDTLS_LIBRARY_ALIGNMENT_H */