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