blob: 39bccb0c497a1a03ca3008e0ef790ba4f20241a4 [file] [log] [blame]
Dave Rodgmanfb5fedc2022-11-30 15:20:33 +00001/* BEGIN_HEADER */
2#include "../library/alignment.h"
3
4#include <stdint.h>
Dave Rodgman63e6a882022-12-01 10:01:08 +00005
6#pragma clang diagnostic ignored "-Wunreachable-code"
Dave Rodgmanfb5fedc2022-11-30 15:20:33 +00007/* END_HEADER */
8
9/* BEGIN_CASE */
10void mbedtls_unaligned_access( int size, int offset )
11{
12 /* Define 64-bit aligned raw byte array */
13 uint64_t raw[2];
14
15 /* Populate with known data */
16 uint8_t *x = (uint8_t *) raw;
17 for ( size_t i = 0; i < sizeof(raw); i++ )
18 x[i] = (uint8_t)i;
19
20 TEST_ASSERT( size == 16 || size == 32 || size == 64 );
21
22 uint64_t r = 0;
23 switch ( size )
24 {
25 case 16:
26 r = mbedtls_get_unaligned_uint16( x + offset );
27 break;
28 case 32:
29 r = mbedtls_get_unaligned_uint32( x + offset );
30 break;
31 case 64:
32 r = mbedtls_get_unaligned_uint64( x + offset );
33 break;
34 }
35
36 /* Generate expected result */
37 uint64_t expected = 0;
38 for ( uint8_t i = 0; i < 8; i++ )
39 {
40 uint8_t shift;
41 if ( MBEDTLS_IS_BIG_ENDIAN )
42 {
43 /*
44 * Similar to little-endian case described below, but the shift needs
45 * to be inverted
46 */
47 shift = 7 - ( i * 8 );
48 } else {
49 /* example for offset == 1:
50 * expected = (( 1 + 0 ) << (0 * 8)) | (( 1 + 1 ) << (1 * 8)) | (( 1 + 2 ) << (2 * 8)))
51 * = (1 << 0) | (2 << 8) | (3 << 16) ...
52 * = 0x0807060504030201
53 * x = { 0, 1, 2, 3, ... }
54 * ie expected is the value that would be read from x on a LE system, when
55 * byte swapping is not performed
56 */
57 shift = i * 8;
58 }
59 uint64_t b = offset + i;
60 expected |= b << shift;
61 }
62
63 /* Mask out excess bits from expected result */
64 switch ( size )
65 {
66 case 16:
67 expected &= 0xffff;
68 break;
69 case 32:
70 expected &= 0xffffffff;
71 break;
72 }
73
74 TEST_EQUAL( r, expected );
75
76 /* Write sentinel to the part of the array we will testing writing to */
77 for ( size_t i = 0; i < (size_t) ( size / 8 ); i++ )
78 {
79 x[i + offset] = 0xff;
80 }
81 /*
82 * Write back to the array with mbedtls_put_unaligned_uint16 and validate
83 * that the array is unchanged as a result.
84 */
85 switch ( size )
86 {
87 case 16:
88 mbedtls_put_unaligned_uint16( x + offset, r );
89 break;
90 case 32:
91 mbedtls_put_unaligned_uint32( x + offset, r );
92 break;
93 case 64:
94 mbedtls_put_unaligned_uint64( x + offset, r );
95 break;
96 }
97 for ( size_t i = 0; i < sizeof(x); i++ )
98 {
99 TEST_EQUAL( x[i], (uint8_t)i );
100 }
101}
102/* END_CASE */
103
104/* BEGIN_CASE */
105void mbedtls_byteswap( unsigned int input_h, unsigned int input_l, int size,
106 unsigned int expected_h, unsigned int expected_l )
107{
108 uint64_t input = ( ((uint64_t)input_h ) << 32 ) | ( (uint64_t)input_l );
109 uint64_t expected = ( ((uint64_t)expected_h) << 32 ) | ( (uint64_t)expected_l );
110
111 /* Check against expected */
112 uint64_t r;
113 switch ( size )
114 {
115 case 16:
116 r = MBEDTLS_BSWAP16( input );
117 break;
118 case 32:
119 r = MBEDTLS_BSWAP32( input );
120 break;
121 case 64:
122 r = MBEDTLS_BSWAP64( input );
123 break;
124 }
125 TEST_EQUAL( r, expected );
126
127 /*
128 * Check byte by byte by extracting bytes from opposite ends of
129 * input and r.
130 */
131 for ( size_t i = 0; i < (size_t)( size / 8 ); i++ )
132 {
133 size_t s1 = i * 8;
134 size_t s2 = ( ( size / 8 - 1 ) - i ) * 8;
135 uint64_t a = ( input & ( (uint64_t)0xff << s1 ) ) >> s1;
136 uint64_t b = ( r & ( (uint64_t)0xff << s2 ) ) >> s2;
137 TEST_EQUAL( a, b );
138 }
139
140 /* Check BSWAP(BSWAP(x)) == x */
141 switch ( size )
142 {
143 case 16:
144 r = MBEDTLS_BSWAP16( r );
145 TEST_EQUAL( r, input & 0xffff );
146 break;
147 case 32:
148 r = MBEDTLS_BSWAP32( r );
149 TEST_EQUAL( r, input & 0xffffffff );
150 break;
151 case 64:
152 r = MBEDTLS_BSWAP64( r );
153 TEST_EQUAL( r, input );
154 break;
155 }
156}
157/* END_CASE */
158
159/* BEGIN_CASE */
160void get_byte()
161{
162 uint8_t data[16];
163
164 for ( size_t i = 0; i < sizeof(data); i++ )
165 data[i] = (uint8_t) i;
166
167 uint64_t u64 = 0x0706050403020100;
168 for ( size_t b = 0; b < 8 ; b++ )
169 {
170 uint8_t actual;
171 switch ( b )
172 {
173 case 0:
174 actual = MBEDTLS_BYTE_0( u64 );
175 break;
176 case 1:
177 actual = MBEDTLS_BYTE_1( u64 );
178 break;
179 case 2:
180 actual = MBEDTLS_BYTE_2( u64 );
181 break;
182 case 3:
183 actual = MBEDTLS_BYTE_3( u64 );
184 break;
185 case 4:
186 actual = MBEDTLS_BYTE_4( u64 );
187 break;
188 case 5:
189 actual = MBEDTLS_BYTE_5( u64 );
190 break;
191 case 6:
192 actual = MBEDTLS_BYTE_6( u64 );
193 break;
194 case 7:
195 actual = MBEDTLS_BYTE_7( u64 );
196 break;
197 }
198 uint8_t expected = b;
199 TEST_EQUAL( actual, expected );
200 }
201
202 uint32_t u32 = 0x03020100;
203 for ( size_t b = 0; b < 4 ; b++ )
204 {
205 uint8_t actual;
206 switch ( b )
207 {
208 case 0:
209 actual = MBEDTLS_BYTE_0( u32 );
210 break;
211 case 1:
212 actual = MBEDTLS_BYTE_1( u32 );
213 break;
214 case 2:
215 actual = MBEDTLS_BYTE_2( u32 );
216 break;
217 case 3:
218 actual = MBEDTLS_BYTE_3( u32 );
219 break;
220 }
221 uint8_t expected = b;
222 TEST_EQUAL( actual, expected );
223 }
224
225 uint16_t u16 = 0x0100;
226 for ( size_t b = 0; b < 2 ; b++ )
227 {
228 uint8_t actual;
229 switch ( b )
230 {
231 case 0:
232 actual = MBEDTLS_BYTE_0( u16 );
233 break;
234 case 1:
235 actual = MBEDTLS_BYTE_1( u16 );
236 break;
237 }
238 uint8_t expected = b;
239 TEST_EQUAL( actual, expected );
240 }
241
242 uint8_t u8 = 0x01;
243 uint8_t actual = MBEDTLS_BYTE_0( u8 );
244 TEST_EQUAL( actual, u8 );
245}
246/* END_CASE */
247
248/* BEGIN_CASE */
249void unaligned_access_endian_aware(int size, int offset, int big_endian )
250{
251 TEST_ASSERT( size == 16 || size == 24 || size == 32 || size == 64 );
252 TEST_ASSERT( offset >= 0 && offset < 8 );
253
254 /* Define 64-bit aligned raw byte array */
255 uint64_t raw[2];
256 /* Populate with known data: x == { 0, 1, 2, ... } */
257 uint8_t *x = (uint8_t *) raw;
258 for ( size_t i = 0; i < sizeof(raw); i++ )
259 x[i] = (uint8_t) i;
260
261 uint64_t read;
262 if ( big_endian )
263 {
264 switch ( size )
265 {
266 case 16:
267 read = MBEDTLS_GET_UINT16_BE( x, offset );
268 break;
269 case 24:
270 read = MBEDTLS_GET_UINT24_BE( x, offset );
271 break;
272 case 32:
273 read = MBEDTLS_GET_UINT32_BE( x, offset );
274 break;
275 case 64:
276 read = MBEDTLS_GET_UINT64_BE( x, offset );
277 break;
278 }
279 }
280 else
281 {
282 switch ( size )
283 {
284 case 16:
285 read = MBEDTLS_GET_UINT16_LE( x, offset );
286 break;
287 case 24:
288 read = MBEDTLS_GET_UINT24_LE( x, offset );
289 break;
290 case 32:
291 read = MBEDTLS_GET_UINT32_LE( x, offset );
292 break;
293 case 64:
294 read = MBEDTLS_GET_UINT64_LE( x, offset );
295 break;
296 }
297 }
298
299 /* Build up expected value byte by byte, in either big or little endian format */
300 uint64_t expected = 0;
301 for ( size_t i = 0; i < (size_t)(size / 8); i++ )
302 {
303 uint64_t b = x[i + offset];
304 uint8_t shift = (big_endian) ? (8 * ((size / 8 - 1) - i)) : (8 * i);
305 expected |= b << shift;
306 }
307
308 /* Verify read */
309 TEST_EQUAL( read, expected );
310
311 /* Test writing back to memory. First write sentiel */
312 for ( size_t i = 0; i < (size_t)(size / 8); i++ )
313 {
314 x[i + offset] = 0xff;
315 }
316 /* Overwrite sentinel with endian-aware write macro */
317 if ( big_endian )
318 {
319 switch ( size )
320 {
321 case 16:
322 MBEDTLS_PUT_UINT16_BE( read, x, offset );
323 break;
324 case 24:
325 MBEDTLS_PUT_UINT24_BE( read, x, offset );
326 break;
327 case 32:
328 MBEDTLS_PUT_UINT32_BE( read, x, offset );
329 break;
330 case 64:
331 MBEDTLS_PUT_UINT64_BE( read, x, offset );
332 break;
333 }
334 }
335 else
336 {
337 switch ( size )
338 {
339 case 16:
340 MBEDTLS_PUT_UINT16_LE( read, x, offset );
341 break;
342 case 24:
343 MBEDTLS_PUT_UINT24_LE( read, x, offset );
344 break;
345 case 32:
346 MBEDTLS_PUT_UINT32_LE( read, x, offset );
347 break;
348 case 64:
349 MBEDTLS_PUT_UINT64_LE( read, x, offset );
350 break;
351 }
352 }
353
354 /* Verify write - check memory is correct */
355 for ( size_t i = 0; i < sizeof(raw); i++ )
356 TEST_EQUAL( x[i], (uint8_t) i );
357}
358/* END_CASE */
359
360/* BEGIN_CASE */
361void mbedtls_is_big_endian()
362{
363 uint16_t check = 0x1234;
364 uint8_t* p = (uint8_t*) &check;
365
366 if ( MBEDTLS_IS_BIG_ENDIAN )
367 {
368 /* Big-endian: data stored MSB first, i.e. p == { 0x12, 0x34 } */
369 TEST_EQUAL( p[0], 0x12 );
370 TEST_EQUAL( p[1], 0x34 );
371 }
372 else
373 {
374 /* Little-endian: data stored LSB first, i.e. p == { 0x34, 0x12 } */
375 TEST_EQUAL( p[0], 0x34 );
376 TEST_EQUAL( p[1], 0x12 );
377 }
378}
379/* END_CASE */