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