blob: a5b71d306f88c8f5d7a021f385b1e88289a81865 [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 Rodgman96d61d12022-11-24 19:33:22 +000029/**
30 * Read the unsigned 32 bits integer from the given address, which need not
31 * be aligned.
Dave Rodgmanfbc23222022-11-24 18:07:37 +000032 *
Dave Rodgman96d61d12022-11-24 19:33:22 +000033 * \param p pointer to 4 bytes of data
Dave Rodgmanfbc23222022-11-24 18:07:37 +000034 */
Dave Rodgman96d61d12022-11-24 19:33:22 +000035static inline uint32_t mbedtls_get_unaligned_uint32( void const *p )
36{
37 uint32_t r;
38 memcpy( &r, p, 4 );
39 return r;
40}
Dave Rodgmanfbc23222022-11-24 18:07:37 +000041
Dave Rodgman96d61d12022-11-24 19:33:22 +000042/**
43 * Write the unsigned 32 bits integer to the given address, which need not
44 * be aligned.
45 *
46 * \param p pointer to 4 bytes of data
47 * \param x data to write
48 */
49static inline void mbedtls_put_unaligned_uint32( void *p, uint32_t x )
50{
Dave Rodgman4b910c12022-11-24 19:44:52 +000051 memcpy( p, &x, 4 );
Dave Rodgman96d61d12022-11-24 19:33:22 +000052}
Dave Rodgmanfbc23222022-11-24 18:07:37 +000053
54/** Byte Reading Macros
55 *
56 * Given a multi-byte integer \p x, MBEDTLS_BYTE_n retrieves the n-th
57 * byte from x, where byte 0 is the least significant byte.
58 */
59#define MBEDTLS_BYTE_0( x ) ( (uint8_t) ( ( x ) & 0xff ) )
60#define MBEDTLS_BYTE_1( x ) ( (uint8_t) ( ( ( x ) >> 8 ) & 0xff ) )
61#define MBEDTLS_BYTE_2( x ) ( (uint8_t) ( ( ( x ) >> 16 ) & 0xff ) )
62#define MBEDTLS_BYTE_3( x ) ( (uint8_t) ( ( ( x ) >> 24 ) & 0xff ) )
63#define MBEDTLS_BYTE_4( x ) ( (uint8_t) ( ( ( x ) >> 32 ) & 0xff ) )
64#define MBEDTLS_BYTE_5( x ) ( (uint8_t) ( ( ( x ) >> 40 ) & 0xff ) )
65#define MBEDTLS_BYTE_6( x ) ( (uint8_t) ( ( ( x ) >> 48 ) & 0xff ) )
66#define MBEDTLS_BYTE_7( x ) ( (uint8_t) ( ( ( x ) >> 56 ) & 0xff ) )
67
68/**
69 * Get the unsigned 32 bits integer corresponding to four bytes in
70 * big-endian order (MSB first).
71 *
72 * \param data Base address of the memory to get the four bytes from.
73 * \param offset Offset from \p data of the first and most significant
74 * byte of the four bytes to build the 32 bits unsigned
75 * integer from.
76 */
77#ifndef MBEDTLS_GET_UINT32_BE
78#define MBEDTLS_GET_UINT32_BE( data , offset ) \
79 ( \
80 ( (uint32_t) ( data )[( offset ) ] << 24 ) \
81 | ( (uint32_t) ( data )[( offset ) + 1] << 16 ) \
82 | ( (uint32_t) ( data )[( offset ) + 2] << 8 ) \
83 | ( (uint32_t) ( data )[( offset ) + 3] ) \
84 )
85#endif
86
87/**
88 * Put in memory a 32 bits unsigned integer in big-endian order.
89 *
90 * \param n 32 bits unsigned integer to put in memory.
91 * \param data Base address of the memory where to put the 32
92 * bits unsigned integer in.
93 * \param offset Offset from \p data where to put the most significant
94 * byte of the 32 bits unsigned integer \p n.
95 */
96#ifndef MBEDTLS_PUT_UINT32_BE
97#define MBEDTLS_PUT_UINT32_BE( n, data, offset ) \
98{ \
99 ( data )[( offset ) ] = MBEDTLS_BYTE_3( n ); \
100 ( data )[( offset ) + 1] = MBEDTLS_BYTE_2( n ); \
101 ( data )[( offset ) + 2] = MBEDTLS_BYTE_1( n ); \
102 ( data )[( offset ) + 3] = MBEDTLS_BYTE_0( n ); \
103}
104#endif
105
106/**
107 * Get the unsigned 32 bits integer corresponding to four bytes in
108 * little-endian order (LSB first).
109 *
110 * \param data Base address of the memory to get the four bytes from.
111 * \param offset Offset from \p data of the first and least significant
112 * byte of the four bytes to build the 32 bits unsigned
113 * integer from.
114 */
115#ifndef MBEDTLS_GET_UINT32_LE
116#define MBEDTLS_GET_UINT32_LE( data, offset ) \
117 ( \
118 ( (uint32_t) ( data )[( offset ) ] ) \
119 | ( (uint32_t) ( data )[( offset ) + 1] << 8 ) \
120 | ( (uint32_t) ( data )[( offset ) + 2] << 16 ) \
121 | ( (uint32_t) ( data )[( offset ) + 3] << 24 ) \
122 )
123#endif
124
125/**
126 * Put in memory a 32 bits unsigned integer in little-endian order.
127 *
128 * \param n 32 bits unsigned integer to put in memory.
129 * \param data Base address of the memory where to put the 32
130 * bits unsigned integer in.
131 * \param offset Offset from \p data where to put the least significant
132 * byte of the 32 bits unsigned integer \p n.
133 */
134#ifndef MBEDTLS_PUT_UINT32_LE
135#define MBEDTLS_PUT_UINT32_LE( n, data, offset ) \
136{ \
137 ( data )[( offset ) ] = MBEDTLS_BYTE_0( n ); \
138 ( data )[( offset ) + 1] = MBEDTLS_BYTE_1( n ); \
139 ( data )[( offset ) + 2] = MBEDTLS_BYTE_2( n ); \
140 ( data )[( offset ) + 3] = MBEDTLS_BYTE_3( n ); \
141}
142#endif
143
144/**
145 * Get the unsigned 16 bits integer corresponding to two bytes in
146 * little-endian order (LSB first).
147 *
148 * \param data Base address of the memory to get the two bytes from.
149 * \param offset Offset from \p data of the first and least significant
150 * byte of the two bytes to build the 16 bits unsigned
151 * integer from.
152 */
153#ifndef MBEDTLS_GET_UINT16_LE
154#define MBEDTLS_GET_UINT16_LE( data, offset ) \
155 ( \
156 ( (uint16_t) ( data )[( offset ) ] ) \
157 | ( (uint16_t) ( data )[( offset ) + 1] << 8 ) \
158 )
159#endif
160
161/**
162 * Put in memory a 16 bits unsigned integer in little-endian order.
163 *
164 * \param n 16 bits unsigned integer to put in memory.
165 * \param data Base address of the memory where to put the 16
166 * bits unsigned integer in.
167 * \param offset Offset from \p data where to put the least significant
168 * byte of the 16 bits unsigned integer \p n.
169 */
170#ifndef MBEDTLS_PUT_UINT16_LE
171#define MBEDTLS_PUT_UINT16_LE( n, data, offset ) \
172{ \
173 ( data )[( offset ) ] = MBEDTLS_BYTE_0( n ); \
174 ( data )[( offset ) + 1] = MBEDTLS_BYTE_1( n ); \
175}
176#endif
177
178/**
179 * Get the unsigned 16 bits integer corresponding to two bytes in
180 * big-endian order (MSB first).
181 *
182 * \param data Base address of the memory to get the two bytes from.
183 * \param offset Offset from \p data of the first and most significant
184 * byte of the two bytes to build the 16 bits unsigned
185 * integer from.
186 */
187#ifndef MBEDTLS_GET_UINT16_BE
188#define MBEDTLS_GET_UINT16_BE( data, offset ) \
189 ( \
190 ( (uint16_t) ( data )[( offset ) ] << 8 ) \
191 | ( (uint16_t) ( data )[( offset ) + 1] ) \
192 )
193#endif
194
195/**
196 * Put in memory a 16 bits unsigned integer in big-endian order.
197 *
198 * \param n 16 bits unsigned integer to put in memory.
199 * \param data Base address of the memory where to put the 16
200 * bits unsigned integer in.
201 * \param offset Offset from \p data where to put the most significant
202 * byte of the 16 bits unsigned integer \p n.
203 */
204#ifndef MBEDTLS_PUT_UINT16_BE
205#define MBEDTLS_PUT_UINT16_BE( n, data, offset ) \
206{ \
207 ( data )[( offset ) ] = MBEDTLS_BYTE_1( n ); \
208 ( data )[( offset ) + 1] = MBEDTLS_BYTE_0( n ); \
209}
210#endif
211
212/**
213 * Get the unsigned 24 bits integer corresponding to three bytes in
214 * big-endian order (MSB first).
215 *
216 * \param data Base address of the memory to get the three bytes from.
217 * \param offset Offset from \p data of the first and most significant
218 * byte of the three bytes to build the 24 bits unsigned
219 * integer from.
220 */
221#ifndef MBEDTLS_GET_UINT24_BE
222#define MBEDTLS_GET_UINT24_BE( data , offset ) \
223 ( \
224 ( (uint32_t) ( data )[( offset ) ] << 16 ) \
225 | ( (uint32_t) ( data )[( offset ) + 1] << 8 ) \
226 | ( (uint32_t) ( data )[( offset ) + 2] ) \
227 )
228#endif
229
230/**
231 * Put in memory a 24 bits unsigned integer in big-endian order.
232 *
233 * \param n 24 bits unsigned integer to put in memory.
234 * \param data Base address of the memory where to put the 24
235 * bits unsigned integer in.
236 * \param offset Offset from \p data where to put the most significant
237 * byte of the 24 bits unsigned integer \p n.
238 */
239#ifndef MBEDTLS_PUT_UINT24_BE
240#define MBEDTLS_PUT_UINT24_BE( n, data, offset ) \
241{ \
242 ( data )[( offset ) ] = MBEDTLS_BYTE_2( n ); \
243 ( data )[( offset ) + 1] = MBEDTLS_BYTE_1( n ); \
244 ( data )[( offset ) + 2] = MBEDTLS_BYTE_0( n ); \
245}
246#endif
247
248/**
249 * Get the unsigned 24 bits integer corresponding to three bytes in
250 * little-endian order (LSB first).
251 *
252 * \param data Base address of the memory to get the three bytes from.
253 * \param offset Offset from \p data of the first and least significant
254 * byte of the three bytes to build the 24 bits unsigned
255 * integer from.
256 */
257#ifndef MBEDTLS_GET_UINT24_LE
258#define MBEDTLS_GET_UINT24_LE( data, offset ) \
259 ( \
260 ( (uint32_t) ( data )[( offset ) ] ) \
261 | ( (uint32_t) ( data )[( offset ) + 1] << 8 ) \
262 | ( (uint32_t) ( data )[( offset ) + 2] << 16 ) \
263 )
264#endif
265
266/**
267 * Put in memory a 24 bits unsigned integer in little-endian order.
268 *
269 * \param n 24 bits unsigned integer to put in memory.
270 * \param data Base address of the memory where to put the 24
271 * bits unsigned integer in.
272 * \param offset Offset from \p data where to put the least significant
273 * byte of the 24 bits unsigned integer \p n.
274 */
275#ifndef MBEDTLS_PUT_UINT24_LE
276#define MBEDTLS_PUT_UINT24_LE( n, data, offset ) \
277{ \
278 ( data )[( offset ) ] = MBEDTLS_BYTE_0( n ); \
279 ( data )[( offset ) + 1] = MBEDTLS_BYTE_1( n ); \
280 ( data )[( offset ) + 2] = MBEDTLS_BYTE_2( n ); \
281}
282#endif
283
284/**
285 * Get the unsigned 64 bits integer corresponding to eight bytes in
286 * big-endian order (MSB first).
287 *
288 * \param data Base address of the memory to get the eight bytes from.
289 * \param offset Offset from \p data of the first and most significant
290 * byte of the eight bytes to build the 64 bits unsigned
291 * integer from.
292 */
293#ifndef MBEDTLS_GET_UINT64_BE
294#define MBEDTLS_GET_UINT64_BE( data, offset ) \
295 ( \
296 ( (uint64_t) ( data )[( offset ) ] << 56 ) \
297 | ( (uint64_t) ( data )[( offset ) + 1] << 48 ) \
298 | ( (uint64_t) ( data )[( offset ) + 2] << 40 ) \
299 | ( (uint64_t) ( data )[( offset ) + 3] << 32 ) \
300 | ( (uint64_t) ( data )[( offset ) + 4] << 24 ) \
301 | ( (uint64_t) ( data )[( offset ) + 5] << 16 ) \
302 | ( (uint64_t) ( data )[( offset ) + 6] << 8 ) \
303 | ( (uint64_t) ( data )[( offset ) + 7] ) \
304 )
305#endif
306
307/**
308 * Put in memory a 64 bits unsigned integer in big-endian order.
309 *
310 * \param n 64 bits unsigned integer to put in memory.
311 * \param data Base address of the memory where to put the 64
312 * bits unsigned integer in.
313 * \param offset Offset from \p data where to put the most significant
314 * byte of the 64 bits unsigned integer \p n.
315 */
316#ifndef MBEDTLS_PUT_UINT64_BE
317#define MBEDTLS_PUT_UINT64_BE( n, data, offset ) \
318{ \
319 ( data )[( offset ) ] = MBEDTLS_BYTE_7( n ); \
320 ( data )[( offset ) + 1] = MBEDTLS_BYTE_6( n ); \
321 ( data )[( offset ) + 2] = MBEDTLS_BYTE_5( n ); \
322 ( data )[( offset ) + 3] = MBEDTLS_BYTE_4( n ); \
323 ( data )[( offset ) + 4] = MBEDTLS_BYTE_3( n ); \
324 ( data )[( offset ) + 5] = MBEDTLS_BYTE_2( n ); \
325 ( data )[( offset ) + 6] = MBEDTLS_BYTE_1( n ); \
326 ( data )[( offset ) + 7] = MBEDTLS_BYTE_0( n ); \
327}
328#endif
329
330/**
331 * Get the unsigned 64 bits integer corresponding to eight bytes in
332 * little-endian order (LSB first).
333 *
334 * \param data Base address of the memory to get the eight bytes from.
335 * \param offset Offset from \p data of the first and least significant
336 * byte of the eight bytes to build the 64 bits unsigned
337 * integer from.
338 */
339#ifndef MBEDTLS_GET_UINT64_LE
340#define MBEDTLS_GET_UINT64_LE( data, offset ) \
341 ( \
342 ( (uint64_t) ( data )[( offset ) + 7] << 56 ) \
343 | ( (uint64_t) ( data )[( offset ) + 6] << 48 ) \
344 | ( (uint64_t) ( data )[( offset ) + 5] << 40 ) \
345 | ( (uint64_t) ( data )[( offset ) + 4] << 32 ) \
346 | ( (uint64_t) ( data )[( offset ) + 3] << 24 ) \
347 | ( (uint64_t) ( data )[( offset ) + 2] << 16 ) \
348 | ( (uint64_t) ( data )[( offset ) + 1] << 8 ) \
349 | ( (uint64_t) ( data )[( offset ) ] ) \
350 )
351#endif
352
353/**
354 * Put in memory a 64 bits unsigned integer in little-endian order.
355 *
356 * \param n 64 bits unsigned integer to put in memory.
357 * \param data Base address of the memory where to put the 64
358 * bits unsigned integer in.
359 * \param offset Offset from \p data where to put the least significant
360 * byte of the 64 bits unsigned integer \p n.
361 */
362#ifndef MBEDTLS_PUT_UINT64_LE
363#define MBEDTLS_PUT_UINT64_LE( n, data, offset ) \
364{ \
365 ( data )[( offset ) ] = MBEDTLS_BYTE_0( n ); \
366 ( data )[( offset ) + 1] = MBEDTLS_BYTE_1( n ); \
367 ( data )[( offset ) + 2] = MBEDTLS_BYTE_2( n ); \
368 ( data )[( offset ) + 3] = MBEDTLS_BYTE_3( n ); \
369 ( data )[( offset ) + 4] = MBEDTLS_BYTE_4( n ); \
370 ( data )[( offset ) + 5] = MBEDTLS_BYTE_5( n ); \
371 ( data )[( offset ) + 6] = MBEDTLS_BYTE_6( n ); \
372 ( data )[( offset ) + 7] = MBEDTLS_BYTE_7( n ); \
373}
374#endif
375
376#endif /* MBEDTLS_LIBRARY_ALIGNMENT_H */