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 *) ✓ 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