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