1/* 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 *) ✓ 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 */ 361