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