c48c4d78 |
1 | //----------------------------------------------------------------------------- |
2 | // Copyright (C) 2015, 2016 by piwi |
3 | // |
4 | // This code is licensed to you under the terms of the GNU GPL, version 2 or, |
5 | // at your option, any later version. See the LICENSE.txt file for the text of |
6 | // the license. |
7 | //----------------------------------------------------------------------------- |
8 | // Implements a card only attack based on crypto text (encrypted nonces |
9 | // received during a nested authentication) only. Unlike other card only |
10 | // attacks this doesn't rely on implementation errors but only on the |
11 | // inherent weaknesses of the crypto1 cypher. Described in |
12 | // Carlo Meijer, Roel Verdult, "Ciphertext-only Cryptanalysis on Hardened |
13 | // Mifare Classic Cards" in Proceedings of the 22nd ACM SIGSAC Conference on |
14 | // Computer and Communications Security, 2015 |
15 | //----------------------------------------------------------------------------- |
16 | // |
17 | // This program calculates tables with possible states for a given |
18 | // bitflip property. |
19 | // |
20 | //----------------------------------------------------------------------------- |
21 | |
22 | #include <inttypes.h> |
23 | #include <stdbool.h> |
24 | #include <stdlib.h> |
25 | #include <string.h> |
26 | #include <stdio.h> |
27 | #include <time.h> |
28 | #include "crapto1/crapto1.h" |
29 | #include "parity.h" |
30 | |
31 | |
32 | #define NUM_PART_SUMS 9 |
33 | #define BITFLIP_2ND_BYTE 0x0200 |
34 | |
35 | typedef enum { |
36 | EVEN_STATE = 0, |
37 | ODD_STATE = 1 |
38 | } odd_even_t; |
39 | |
40 | |
41 | static uint16_t PartialSumProperty(uint32_t state, odd_even_t odd_even) |
42 | { |
43 | uint16_t sum = 0; |
44 | for (uint16_t j = 0; j < 16; j++) { |
45 | uint32_t st = state; |
46 | uint16_t part_sum = 0; |
47 | if (odd_even == ODD_STATE) { |
48 | for (uint16_t i = 0; i < 5; i++) { |
49 | part_sum ^= filter(st); |
50 | st = (st << 1) | ((j >> (3-i)) & 0x01) ; |
51 | } |
52 | part_sum ^= 1; // XOR 1 cancelled out for the other 8 bits |
53 | } else { |
54 | for (uint16_t i = 0; i < 4; i++) { |
55 | st = (st << 1) | ((j >> (3-i)) & 0x01) ; |
56 | part_sum ^= filter(st); |
57 | } |
58 | } |
59 | sum += part_sum; |
60 | } |
61 | return sum; |
62 | } |
63 | |
64 | |
65 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
66 | // bitarray functions |
67 | |
68 | #define malloc_bitarray(x) __builtin_assume_aligned(_aligned_malloc(x, __BIGGEST_ALIGNMENT__), __BIGGEST_ALIGNMENT__) |
69 | #define free_bitarray(x) _aligned_free(x) |
70 | |
71 | static inline void clear_bitarray24(uint32_t *bitarray) |
72 | { |
73 | memset(bitarray, 0x00, sizeof(uint32_t) * (1<<19)); |
74 | } |
75 | |
76 | |
77 | static inline uint32_t test_bit24(uint32_t *bitarray, uint32_t index) |
78 | { |
79 | return bitarray[index>>5] & (0x80000000>>(index&0x0000001f)); |
80 | } |
81 | |
82 | |
83 | static inline void set_bit24(uint32_t *bitarray, uint32_t index) |
84 | { |
85 | bitarray[index>>5] |= 0x80000000>>(index&0x0000001f); |
86 | } |
87 | |
88 | |
89 | static inline uint32_t next_state(uint32_t *bitset, uint32_t state) |
90 | { |
91 | if (++state == 1<<24) return 1<<24; |
92 | uint32_t index = state >> 5; |
93 | uint_fast8_t bit = state & 0x1f; |
94 | uint32_t line = bitset[index] << bit; |
95 | while (bit <= 0x1f) { |
96 | if (line & 0x80000000) return state; |
97 | state++; |
98 | bit++; |
99 | line <<= 1; |
100 | } |
101 | index++; |
102 | while (bitset[index] == 0x00000000 && state < 1<<24) { |
103 | index++; |
104 | state += 0x20; |
105 | } |
106 | if (state >= 1<<24) return 1<<24; |
107 | #if defined __GNUC__ |
108 | return state + __builtin_clz(bitset[index]); |
109 | #else |
110 | bit = 0x00; |
111 | line = bitset[index]; |
112 | while (bit <= 0x1f) { |
113 | if (line & 0x80000000) return state; |
114 | state++; |
115 | bit++; |
116 | line <<= 1; |
117 | } |
118 | return 1<<24; |
119 | #endif |
120 | } |
121 | |
122 | |
123 | static inline uint32_t next_not_state(uint32_t *bitset, uint32_t state) |
124 | { |
125 | if (++state == 1<<24) return 1<<24; |
126 | uint32_t index = state >> 5; |
127 | uint_fast8_t bit = state & 0x1f; |
128 | uint32_t line = bitset[index] << bit; |
129 | while (bit <= 0x1f) { |
130 | if ((line & 0x80000000) == 0) return state; |
131 | state++; |
132 | bit++; |
133 | line <<= 1; |
134 | } |
135 | index++; |
136 | while (bitset[index] == 0xffffffff && state < 1<<24) { |
137 | index++; |
138 | state += 0x20; |
139 | } |
140 | if (state >= 1<<24) return 1<<24; |
141 | #if defined __GNUC__ |
142 | return state + __builtin_clz(~bitset[index]); |
143 | #else |
144 | bit = 0x00; |
145 | line = bitset[index]; |
146 | while (bit <= 0x1f) { |
147 | if ((line & 0x80000000) == 0) return state; |
148 | state++; |
149 | bit++; |
150 | line <<= 1; |
151 | } |
152 | return 1<<24; |
153 | #endif |
154 | } |
155 | |
156 | |
157 | static inline uint32_t bitcount(uint32_t a) |
158 | { |
159 | #if defined __GNUC__ |
160 | return __builtin_popcountl(a); |
161 | #else |
162 | a = a - ((a >> 1) & 0x55555555); |
163 | a = (a & 0x33333333) + ((a >> 2) & 0x33333333); |
164 | return (((a + (a >> 4)) & 0x0f0f0f0f) * 0x01010101) >> 24; |
165 | #endif |
166 | } |
167 | |
168 | |
169 | static inline uint32_t count_states(uint32_t *bitset) |
170 | { |
171 | uint32_t count = 0; |
172 | for (uint32_t i = 0; i < (1<<19); i++) { |
173 | count += bitcount(bitset[i]); |
174 | } |
175 | return count; |
176 | } |
177 | |
178 | |
7f9e4c25 |
179 | static void write_bitflips_file(odd_even_t odd_even, uint16_t bitflip, int sum_a0, uint32_t *bitset, uint32_t count) |
c48c4d78 |
180 | { |
181 | char filename[80]; |
182 | sprintf(filename, "bitflip_%d_%03" PRIx16 "_sum%d_states.bin", odd_even, bitflip, sum_a0); |
183 | FILE *outfile = fopen(filename, "wb"); |
7f9e4c25 |
184 | fwrite(&count, 1, sizeof(count), outfile); |
c48c4d78 |
185 | fwrite(bitset, 1, sizeof(uint32_t)*(1<<19), outfile); |
186 | fclose(outfile); |
187 | } |
188 | |
189 | |
190 | uint32_t *restrict part_sum_a0_bitarrays[2][NUM_PART_SUMS]; |
191 | |
192 | static void init_part_sum_bitarrays(void) |
193 | { |
194 | printf("init_part_sum_bitarrays()..."); |
195 | for (odd_even_t odd_even = EVEN_STATE; odd_even <= ODD_STATE; odd_even++) { |
196 | for (uint16_t part_sum_a0 = 0; part_sum_a0 < NUM_PART_SUMS; part_sum_a0++) { |
197 | part_sum_a0_bitarrays[odd_even][part_sum_a0] = (uint32_t *)malloc_bitarray(sizeof(uint32_t) * (1<<19)); |
198 | if (part_sum_a0_bitarrays[odd_even][part_sum_a0] == NULL) { |
199 | printf("Out of memory error in init_part_suma0_statelists(). Aborting...\n"); |
200 | exit(4); |
201 | } |
202 | clear_bitarray24(part_sum_a0_bitarrays[odd_even][part_sum_a0]); |
203 | } |
204 | } |
205 | for (odd_even_t odd_even = EVEN_STATE; odd_even <= ODD_STATE; odd_even++) { |
206 | //printf("(%d, %" PRIu16 ")...", odd_even, part_sum_a0); |
207 | for (uint32_t state = 0; state < (1<<20); state++) { |
208 | uint16_t part_sum_a0 = PartialSumProperty(state, odd_even) / 2; |
209 | for (uint16_t low_bits = 0; low_bits < 1<<4; low_bits++) { |
210 | set_bit24(part_sum_a0_bitarrays[odd_even][part_sum_a0], state<<4 | low_bits); |
211 | } |
212 | } |
213 | } |
214 | printf("done.\n"); |
215 | } |
216 | |
217 | |
218 | static void free_part_sum_bitarrays(void) |
219 | { |
220 | printf("free_part_sum_bitarrays()..."); |
221 | for (int16_t part_sum_a0 = (NUM_PART_SUMS-1); part_sum_a0 >= 0; part_sum_a0--) { |
222 | free_bitarray(part_sum_a0_bitarrays[ODD_STATE][part_sum_a0]); |
223 | } |
224 | for (int16_t part_sum_a0 = (NUM_PART_SUMS-1); part_sum_a0 >= 0; part_sum_a0--) { |
225 | free_bitarray(part_sum_a0_bitarrays[EVEN_STATE][part_sum_a0]); |
226 | } |
227 | printf("done.\n"); |
228 | } |
229 | |
230 | uint32_t *restrict sum_a0_bitarray[2]; |
231 | |
232 | void init_sum_bitarray(uint16_t sum_a0) |
233 | { |
234 | printf("init_sum_bitarray()...\n"); |
235 | for (odd_even_t odd_even = EVEN_STATE; odd_even <= ODD_STATE; odd_even++) { |
236 | sum_a0_bitarray[odd_even] = (uint32_t *)malloc_bitarray(sizeof(uint32_t) * (1<<19)); |
237 | if (sum_a0_bitarray[odd_even] == NULL) { |
238 | printf("Out of memory error in init_sum_bitarrays(). Aborting...\n"); |
239 | exit(4); |
240 | } |
241 | clear_bitarray24(sum_a0_bitarray[odd_even]); |
242 | } |
243 | for (uint8_t p = 0; p < NUM_PART_SUMS; p++) { |
244 | for (uint8_t q = 0; q < NUM_PART_SUMS; q++) { |
245 | if (sum_a0 == 2*p*(16-2*q) + (16-2*p)*2*q) { |
246 | for (uint32_t i = 0; i < (1<<19); i++) { |
247 | sum_a0_bitarray[EVEN_STATE][i] |= part_sum_a0_bitarrays[EVEN_STATE][q][i]; |
248 | sum_a0_bitarray[ODD_STATE][i] |= part_sum_a0_bitarrays[ODD_STATE][p][i]; |
249 | } |
250 | } |
251 | } |
252 | } |
253 | for (odd_even_t odd_even = EVEN_STATE; odd_even <= ODD_STATE; odd_even++) { |
254 | uint32_t count = count_states(sum_a0_bitarray[odd_even]); |
255 | printf("sum_a0_bitarray[%s] has %d states (%5.2f%%)\n", odd_even==EVEN_STATE?"even":"odd ", count, (float)count/(1<<24)*100.0); |
256 | } |
257 | printf("done.\n"); |
258 | } |
259 | |
260 | |
261 | static void free_sum_bitarray(void) |
262 | { |
263 | printf("free_sum_bitarray()..."); |
264 | free_bitarray(sum_a0_bitarray[ODD_STATE]); |
265 | free_bitarray(sum_a0_bitarray[EVEN_STATE]); |
266 | printf("done.\n"); |
267 | } |
268 | |
269 | |
270 | static void precalculate_bit0_bitflip_bitarrays(uint8_t const bitflip, uint16_t const sum_a0) |
271 | { |
272 | // #define TEST_RUN |
273 | #ifdef TEST_RUN |
274 | #define NUM_TEST_STATES (1<<10) |
275 | #else |
276 | #define NUM_TEST_STATES (1<<23) |
277 | #endif |
278 | |
279 | time_t start_time = time(NULL); |
280 | time_t last_check_time = start_time; |
281 | |
282 | uint32_t *restrict test_bitarray[2]; |
283 | uint32_t *restrict test_not_bitarray[2]; |
284 | |
285 | test_bitarray[EVEN_STATE] = malloc_bitarray(sizeof(uint32_t) * (1<<19)); |
286 | clear_bitarray24(test_bitarray[EVEN_STATE]); |
287 | test_bitarray[ODD_STATE] = malloc_bitarray(sizeof(uint32_t) * (1<<19)); |
288 | clear_bitarray24(test_bitarray[ODD_STATE]); |
289 | |
290 | test_not_bitarray[EVEN_STATE] = malloc_bitarray(sizeof(uint32_t) * (1<<19)); |
291 | clear_bitarray24(test_not_bitarray[EVEN_STATE]); |
292 | test_not_bitarray[ODD_STATE] = malloc_bitarray(sizeof(uint32_t) * (1<<19)); |
293 | clear_bitarray24(test_not_bitarray[ODD_STATE]); |
294 | |
295 | uint32_t count[2]; |
296 | bool all_odd_states_are_possible_for_notbitflip = false; |
297 | |
298 | printf("\n\nStarting search for crypto1 states resulting in bitflip property 0x%03x...\n", bitflip); |
299 | for (uint32_t even_state = next_state(sum_a0_bitarray[EVEN_STATE], -1); even_state < NUM_TEST_STATES; even_state = next_state(sum_a0_bitarray[EVEN_STATE], even_state)) { |
300 | bool even_state_is_possible = false; |
301 | time_t time_now = time(NULL); |
302 | if (difftime(time_now, last_check_time) > 5*60) { // print status every 5 minutes |
303 | float runtime = difftime(time_now, start_time); |
304 | float remaining_time = runtime * ((1<<23) - even_state) / even_state; |
305 | printf("\n%1.1f hours elapsed, expected completion in %1.1f hours (%1.1f days)", runtime/3600, remaining_time/3600, remaining_time/3600/24); |
306 | last_check_time = time_now; |
307 | } |
308 | for (uint32_t odd_state = next_state(sum_a0_bitarray[ODD_STATE], -1); odd_state < (1<<24); odd_state = next_state(test_bitarray[ODD_STATE], odd_state)) { |
309 | if (even_state_is_possible && test_bit24(test_bitarray[ODD_STATE], odd_state)) continue; |
310 | // load crypto1 state |
311 | struct Crypto1State cs; |
312 | cs.odd = odd_state >> 4; |
313 | cs.even = even_state >> 4; |
314 | |
315 | // track flipping bits in state |
316 | struct Crypto1DeltaState { |
317 | uint_fast8_t odd; |
318 | uint_fast8_t even; |
319 | } cs_delta; |
320 | cs_delta.odd = 0; |
321 | cs_delta.even = 0; |
322 | |
323 | uint_fast16_t keystream = 0; |
324 | |
325 | // decrypt 9 bits |
326 | for (int i = 0; i < 9; i++) { |
327 | uint_fast8_t keystream_bit = filter(cs.odd & 0x000fffff) ^ filter((cs.odd & 0x000fffff) ^ cs_delta.odd); |
328 | keystream = keystream << 1 | keystream_bit; |
329 | uint_fast8_t nt_bit = BIT(bitflip, i) ^ keystream_bit; |
330 | uint_fast8_t LSFR_feedback = BIT(cs_delta.odd, 2) ^ BIT(cs_delta.even, 2) ^ BIT(cs_delta.odd, 3); |
331 | |
332 | cs_delta.even = cs_delta.even << 1 | (LSFR_feedback ^ nt_bit); |
333 | uint_fast8_t tmp = cs_delta.odd; |
334 | cs_delta.odd = cs_delta.even; |
335 | cs_delta.even = tmp; |
336 | |
337 | cs.even = cs.odd; |
338 | if (i & 1) { |
339 | cs.odd = odd_state >> (7 - i) / 2; |
340 | } else { |
341 | cs.odd = even_state >> (7 - i) / 2; |
342 | } |
343 | } |
344 | |
345 | if (evenparity32(keystream) == evenparity32(bitflip)) { |
346 | // found valid bitflip state |
347 | even_state_is_possible = true; |
348 | set_bit24(test_bitarray[EVEN_STATE], even_state); |
349 | set_bit24(test_bitarray[EVEN_STATE], 1 << 23 | even_state); |
350 | set_bit24(test_bitarray[ODD_STATE], odd_state); |
351 | } else { |
352 | // found valid !bitflip state |
353 | set_bit24(test_not_bitarray[EVEN_STATE], even_state); |
354 | set_bit24(test_not_bitarray[EVEN_STATE], 1 << 23 | even_state); |
355 | set_bit24(test_not_bitarray[ODD_STATE], odd_state); |
356 | } |
357 | } |
358 | if (!even_state_is_possible) { |
359 | all_odd_states_are_possible_for_notbitflip = true; |
360 | } |
361 | } |
362 | |
363 | printf("\nAnalysis completed. Checking for effective bitflip properties...\n"); |
364 | for (odd_even_t odd_even = EVEN_STATE; odd_even <= ODD_STATE; odd_even++) { |
365 | count[odd_even] = count_states(test_bitarray[odd_even]); |
366 | if (count[odd_even] != 1<<24) { |
367 | printf("Writing %d possible %s states for bitflip property %03x (%d (%1.2f%%) states eliminated)\n", |
368 | count[odd_even], |
369 | odd_even==EVEN_STATE?"even":"odd", |
370 | bitflip, (1<<24) - count[odd_even], |
371 | (float)((1<<24) - count[odd_even]) / (1<<24) * 100.0); |
372 | #ifndef TEST_RUN |
7f9e4c25 |
373 | write_bitflips_file(odd_even, bitflip, sum_a0, test_bitarray[odd_even], count[odd_even]); |
c48c4d78 |
374 | #endif |
375 | } else { |
376 | printf("All %s states for bitflip property %03x are possible. No file written.\n", odd_even==EVEN_STATE?"even":"odd", bitflip); |
377 | } |
378 | } |
379 | uint32_t *restrict test_bitarray_2nd = malloc_bitarray(sizeof(uint32_t) * (1<<19)); |
380 | clear_bitarray24(test_bitarray_2nd); |
381 | for (odd_even_t odd_even = EVEN_STATE; odd_even <= ODD_STATE; odd_even++) { |
382 | if (count[odd_even] != 1<<24) { |
383 | for (uint32_t state = 0; state < (1<<24); state += 1<<4) { |
384 | uint32_t line = test_bitarray[odd_even][state>>5]; |
385 | uint16_t half_line = state&0x000000010 ? line&0x0000ffff : line>>16; |
386 | if (half_line != 0) { |
387 | for (uint32_t low_bits = 0; low_bits < (1<<4); low_bits++) { |
388 | set_bit24(test_bitarray_2nd, low_bits << 20 | state >> 4); |
389 | } |
390 | } |
391 | } |
392 | count[odd_even] = count_states(test_bitarray_2nd); |
393 | if (count[odd_even] != 1<<24) { |
394 | printf("Writing %d possible %s states for bitflip property %03x (%d (%1.2f%%) states eliminated)\n", |
395 | count[odd_even], |
396 | odd_even==EVEN_STATE?"even":"odd", |
397 | bitflip | BITFLIP_2ND_BYTE, (1<<24) - count[odd_even], |
398 | (float)((1<<24) - count[odd_even]) / (1<<24) * 100.0); |
399 | #ifndef TEST_RUN |
7f9e4c25 |
400 | write_bitflips_file(odd_even, bitflip | BITFLIP_2ND_BYTE, sum_a0, test_bitarray_2nd, count[odd_even]); |
c48c4d78 |
401 | #endif |
402 | } else { |
403 | printf("All %s states for bitflip property %03x are possible. No file written.\n", odd_even==EVEN_STATE?"even":"odd", bitflip | BITFLIP_2ND_BYTE); |
404 | } |
405 | } else { |
406 | printf("All %s states for bitflip property %03x are possible. No file written.\n", odd_even==EVEN_STATE?"even":"odd", bitflip | BITFLIP_2ND_BYTE); |
407 | } |
408 | } |
409 | |
410 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
411 | // second run for the remaining "not bitflip" states |
412 | printf("\n\nStarting search for crypto1 states resulting in bitflip property 0x%03x...", bitflip | 0x100); |
413 | start_time = time(NULL); |
414 | last_check_time = start_time; |
415 | for (uint32_t even_state = next_state(sum_a0_bitarray[EVEN_STATE], -1); even_state < NUM_TEST_STATES; even_state = next_state(sum_a0_bitarray[EVEN_STATE], even_state)) { |
416 | bool even_state_is_possible = test_bit24(test_not_bitarray[EVEN_STATE], even_state); |
417 | time_t time_now = time(NULL); |
418 | if (difftime(time_now, last_check_time) > 5*60) { // print status every 5 minutes |
419 | float runtime = difftime(time_now, start_time); |
420 | float remaining_time = runtime * ((1<<23) - even_state) / even_state; |
421 | printf("\n%1.1f hours elapsed, expected completion in %1.1f hours (%1.1f days)", runtime/3600, remaining_time/3600, remaining_time/3600/24); |
422 | last_check_time = time_now; |
423 | } |
424 | for (uint32_t odd_state = next_state(sum_a0_bitarray[ODD_STATE], -1); odd_state < (1<<24); odd_state = next_state(sum_a0_bitarray[ODD_STATE], odd_state)) { |
425 | if (even_state_is_possible) { |
426 | if (all_odd_states_are_possible_for_notbitflip) break; |
427 | if (test_bit24(test_not_bitarray[ODD_STATE], odd_state)) continue; |
428 | } |
429 | // load crypto1 state |
430 | struct Crypto1State cs; |
431 | cs.odd = odd_state >> 4; |
432 | cs.even = even_state >> 4; |
433 | |
434 | // track flipping bits in state |
435 | struct Crypto1DeltaState { |
436 | uint_fast8_t odd; |
437 | uint_fast8_t even; |
438 | } cs_delta; |
439 | cs_delta.odd = 0; |
440 | cs_delta.even = 0; |
441 | |
442 | uint_fast16_t keystream = 0; |
443 | // uint_fast16_t nt = 0; |
444 | |
445 | // decrypt 9 bits |
446 | for (int i = 0; i < 9; i++) { |
447 | uint_fast8_t keystream_bit = filter(cs.odd & 0x000fffff) ^ filter((cs.odd & 0x000fffff) ^ cs_delta.odd); |
448 | keystream = keystream << 1 | keystream_bit; |
449 | uint_fast8_t nt_bit = BIT(bitflip|0x100, i) ^ keystream_bit; |
450 | uint_fast8_t LSFR_feedback = BIT(cs_delta.odd, 2) ^ BIT(cs_delta.even, 2) ^ BIT(cs_delta.odd, 3); |
451 | |
452 | cs_delta.even = cs_delta.even << 1 | (LSFR_feedback ^ nt_bit); |
453 | uint_fast8_t tmp = cs_delta.odd; |
454 | cs_delta.odd = cs_delta.even; |
455 | cs_delta.even = tmp; |
456 | |
457 | cs.even = cs.odd; |
458 | if (i & 1) { |
459 | cs.odd = odd_state >> (7 - i) / 2; |
460 | } else { |
461 | cs.odd = even_state >> (7 - i) / 2; |
462 | } |
463 | } |
464 | |
465 | if (evenparity32(keystream) != evenparity32(bitflip)) { |
466 | // found valid !bitflip state |
467 | even_state_is_possible = true; |
468 | set_bit24(test_not_bitarray[EVEN_STATE], even_state); |
469 | set_bit24(test_not_bitarray[EVEN_STATE], 1 << 23 | even_state); |
470 | set_bit24(test_not_bitarray[ODD_STATE], odd_state); |
471 | } |
472 | } |
473 | } |
474 | |
475 | printf("\nAnalysis completed. Checking for effective !bitflip properties...\n"); |
476 | for (odd_even_t odd_even = EVEN_STATE; odd_even <= ODD_STATE; odd_even++) { |
477 | count[odd_even] = count_states(test_not_bitarray[odd_even]); |
478 | if (count[odd_even] != 1<<24) { |
479 | printf("Writing %d possible %s states for bitflip property %03x (%d (%1.2f%%) states eliminated)\n", |
480 | count[odd_even], |
481 | odd_even==EVEN_STATE?"even":"odd", |
482 | bitflip|0x100, (1<<24) - count[odd_even], |
483 | (float)((1<<24) - count[odd_even]) / (1<<24) * 100.0); |
484 | #ifndef TEST_RUN |
7f9e4c25 |
485 | write_bitflips_file(odd_even, bitflip|0x100, sum_a0, test_not_bitarray[odd_even], count[odd_even]); |
c48c4d78 |
486 | #endif |
487 | } else { |
488 | printf("All %s states for bitflip property %03x are possible. No file written.\n", odd_even==EVEN_STATE?"even":"odd", bitflip|0x100); |
489 | } |
490 | } |
491 | |
492 | clear_bitarray24(test_bitarray_2nd); |
493 | for (odd_even_t odd_even = EVEN_STATE; odd_even <= ODD_STATE; odd_even++) { |
494 | if (count[odd_even] != 1<<24) { |
495 | for (uint32_t state = 0; state < (1<<24); state += 1<<4) { |
496 | uint32_t line = test_not_bitarray[odd_even][state>>5]; |
497 | uint16_t half_line = state&0x000000010 ? line&0x0000ffff : line>>16; |
498 | if (half_line != 0) { |
499 | for (uint32_t low_bits = 0; low_bits < (1<<4); low_bits++) { |
500 | set_bit24(test_bitarray_2nd, low_bits << 20 | state >> 4); |
501 | } |
502 | } |
503 | } |
504 | count[odd_even] = count_states(test_bitarray_2nd); |
505 | if (count[odd_even] != 1<<24) { |
506 | printf("Writing %d possible %s states for bitflip property %03x (%d (%1.2f%%) states eliminated)\n", |
507 | count[odd_even], |
508 | odd_even==EVEN_STATE?"even":"odd", |
509 | bitflip | 0x100| BITFLIP_2ND_BYTE, (1<<24) - count[odd_even], |
510 | (float)((1<<24) - count[odd_even]) / (1<<24) * 100.0); |
511 | #ifndef TEST_RUN |
7f9e4c25 |
512 | write_bitflips_file(odd_even, bitflip | 0x100 | BITFLIP_2ND_BYTE, sum_a0, test_bitarray_2nd, count[odd_even]); |
c48c4d78 |
513 | #endif |
514 | } else { |
515 | printf("All %s states for bitflip property %03x are possible. No file written.\n", odd_even==EVEN_STATE?"even":"odd", bitflip | 0x100 | BITFLIP_2ND_BYTE); |
516 | } |
517 | } else { |
518 | printf("All %s states for bitflip property %03x are possible. No file written.\n", odd_even==EVEN_STATE?"even":"odd", bitflip | 0x100 | BITFLIP_2ND_BYTE); |
519 | } |
520 | } |
521 | |
522 | free_bitarray(test_bitarray_2nd); |
523 | free_bitarray(test_not_bitarray[ODD_STATE]); |
524 | free_bitarray(test_not_bitarray[EVEN_STATE]); |
525 | free_bitarray(test_bitarray[ODD_STATE]); |
526 | free_bitarray(test_bitarray[EVEN_STATE]); |
527 | |
528 | exit(0); |
529 | } |
530 | |
531 | |
532 | int main (int argc, char *argv[]) { |
533 | |
534 | unsigned int bitflip_in; |
535 | int sum_a0; |
536 | |
537 | printf("Create tables required by hardnested attack.\n"); |
538 | printf("Expect a runtime in the range of days or weeks.\n"); |
539 | printf("Single thread only. If you want to use several threads, start it multiple times :-)\n\n"); |
540 | |
541 | if (argc != 2 && argc != 3) { |
542 | printf(" syntax: %s <bitflip property> [<Sum_a0>]\n\n", argv[0]); |
543 | printf(" example: %s 1f\n", argv[0]); |
544 | return 1; |
545 | } |
546 | |
547 | sscanf(argv[1],"%x", &bitflip_in); |
548 | |
549 | if (bitflip_in > 255) { |
550 | printf("Bitflip property must be less than or equal to 0xff\n\n"); |
551 | return 1; |
552 | } |
553 | |
554 | if(argc == 3) { |
555 | sscanf(argv[2], "%d", &sum_a0); |
556 | } |
557 | |
558 | switch (sum_a0) { |
559 | case 0: |
560 | case 32: |
561 | case 56: |
562 | case 64: |
563 | case 80: |
564 | case 96: |
565 | case 104: |
566 | case 112: |
567 | case 120: |
568 | case 128: |
569 | case 136: |
570 | case 144: |
571 | case 152: |
572 | case 160: |
573 | case 176: |
574 | case 192: |
575 | case 200: |
576 | case 224: |
577 | case 256: break; |
578 | default: sum_a0 = -1; |
579 | } |
580 | |
581 | printf("Calculating for bitflip = %02x, sum_a0 = %d\n", bitflip_in, sum_a0); |
582 | |
583 | init_part_sum_bitarrays(); |
584 | init_sum_bitarray(sum_a0); |
585 | |
586 | precalculate_bit0_bitflip_bitarrays(bitflip_in, sum_a0); |
587 | |
588 | free_sum_bitarray(); |
589 | free_part_sum_bitarrays(); |
590 | |
591 | return 0; |
592 | } |