]>
Commit | Line | Data |
---|---|---|
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 | ||
179 | static void write_bitflips_file(odd_even_t odd_even, uint16_t bitflip, int sum_a0, uint32_t *bitset) | |
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"); | |
184 | fwrite(bitset, 1, sizeof(uint32_t)*(1<<19), outfile); | |
185 | fclose(outfile); | |
186 | } | |
187 | ||
188 | ||
189 | uint32_t *restrict part_sum_a0_bitarrays[2][NUM_PART_SUMS]; | |
190 | ||
191 | static void init_part_sum_bitarrays(void) | |
192 | { | |
193 | printf("init_part_sum_bitarrays()..."); | |
194 | for (odd_even_t odd_even = EVEN_STATE; odd_even <= ODD_STATE; odd_even++) { | |
195 | for (uint16_t part_sum_a0 = 0; part_sum_a0 < NUM_PART_SUMS; part_sum_a0++) { | |
196 | part_sum_a0_bitarrays[odd_even][part_sum_a0] = (uint32_t *)malloc_bitarray(sizeof(uint32_t) * (1<<19)); | |
197 | if (part_sum_a0_bitarrays[odd_even][part_sum_a0] == NULL) { | |
198 | printf("Out of memory error in init_part_suma0_statelists(). Aborting...\n"); | |
199 | exit(4); | |
200 | } | |
201 | clear_bitarray24(part_sum_a0_bitarrays[odd_even][part_sum_a0]); | |
202 | } | |
203 | } | |
204 | for (odd_even_t odd_even = EVEN_STATE; odd_even <= ODD_STATE; odd_even++) { | |
205 | //printf("(%d, %" PRIu16 ")...", odd_even, part_sum_a0); | |
206 | for (uint32_t state = 0; state < (1<<20); state++) { | |
207 | uint16_t part_sum_a0 = PartialSumProperty(state, odd_even) / 2; | |
208 | for (uint16_t low_bits = 0; low_bits < 1<<4; low_bits++) { | |
209 | set_bit24(part_sum_a0_bitarrays[odd_even][part_sum_a0], state<<4 | low_bits); | |
210 | } | |
211 | } | |
212 | } | |
213 | printf("done.\n"); | |
214 | } | |
215 | ||
216 | ||
217 | static void free_part_sum_bitarrays(void) | |
218 | { | |
219 | printf("free_part_sum_bitarrays()..."); | |
220 | for (int16_t part_sum_a0 = (NUM_PART_SUMS-1); part_sum_a0 >= 0; part_sum_a0--) { | |
221 | free_bitarray(part_sum_a0_bitarrays[ODD_STATE][part_sum_a0]); | |
222 | } | |
223 | for (int16_t part_sum_a0 = (NUM_PART_SUMS-1); part_sum_a0 >= 0; part_sum_a0--) { | |
224 | free_bitarray(part_sum_a0_bitarrays[EVEN_STATE][part_sum_a0]); | |
225 | } | |
226 | printf("done.\n"); | |
227 | } | |
228 | ||
229 | uint32_t *restrict sum_a0_bitarray[2]; | |
230 | ||
231 | void init_sum_bitarray(uint16_t sum_a0) | |
232 | { | |
233 | printf("init_sum_bitarray()...\n"); | |
234 | for (odd_even_t odd_even = EVEN_STATE; odd_even <= ODD_STATE; odd_even++) { | |
235 | sum_a0_bitarray[odd_even] = (uint32_t *)malloc_bitarray(sizeof(uint32_t) * (1<<19)); | |
236 | if (sum_a0_bitarray[odd_even] == NULL) { | |
237 | printf("Out of memory error in init_sum_bitarrays(). Aborting...\n"); | |
238 | exit(4); | |
239 | } | |
240 | clear_bitarray24(sum_a0_bitarray[odd_even]); | |
241 | } | |
242 | for (uint8_t p = 0; p < NUM_PART_SUMS; p++) { | |
243 | for (uint8_t q = 0; q < NUM_PART_SUMS; q++) { | |
244 | if (sum_a0 == 2*p*(16-2*q) + (16-2*p)*2*q) { | |
245 | for (uint32_t i = 0; i < (1<<19); i++) { | |
246 | sum_a0_bitarray[EVEN_STATE][i] |= part_sum_a0_bitarrays[EVEN_STATE][q][i]; | |
247 | sum_a0_bitarray[ODD_STATE][i] |= part_sum_a0_bitarrays[ODD_STATE][p][i]; | |
248 | } | |
249 | } | |
250 | } | |
251 | } | |
252 | for (odd_even_t odd_even = EVEN_STATE; odd_even <= ODD_STATE; odd_even++) { | |
253 | uint32_t count = count_states(sum_a0_bitarray[odd_even]); | |
254 | printf("sum_a0_bitarray[%s] has %d states (%5.2f%%)\n", odd_even==EVEN_STATE?"even":"odd ", count, (float)count/(1<<24)*100.0); | |
255 | } | |
256 | printf("done.\n"); | |
257 | } | |
258 | ||
259 | ||
260 | static void free_sum_bitarray(void) | |
261 | { | |
262 | printf("free_sum_bitarray()..."); | |
263 | free_bitarray(sum_a0_bitarray[ODD_STATE]); | |
264 | free_bitarray(sum_a0_bitarray[EVEN_STATE]); | |
265 | printf("done.\n"); | |
266 | } | |
267 | ||
268 | ||
269 | static void precalculate_bit0_bitflip_bitarrays(uint8_t const bitflip, uint16_t const sum_a0) | |
270 | { | |
271 | // #define TEST_RUN | |
272 | #ifdef TEST_RUN | |
273 | #define NUM_TEST_STATES (1<<10) | |
274 | #else | |
275 | #define NUM_TEST_STATES (1<<23) | |
276 | #endif | |
277 | ||
278 | time_t start_time = time(NULL); | |
279 | time_t last_check_time = start_time; | |
280 | ||
281 | uint32_t *restrict test_bitarray[2]; | |
282 | uint32_t *restrict test_not_bitarray[2]; | |
283 | ||
284 | test_bitarray[EVEN_STATE] = malloc_bitarray(sizeof(uint32_t) * (1<<19)); | |
285 | clear_bitarray24(test_bitarray[EVEN_STATE]); | |
286 | test_bitarray[ODD_STATE] = malloc_bitarray(sizeof(uint32_t) * (1<<19)); | |
287 | clear_bitarray24(test_bitarray[ODD_STATE]); | |
288 | ||
289 | test_not_bitarray[EVEN_STATE] = malloc_bitarray(sizeof(uint32_t) * (1<<19)); | |
290 | clear_bitarray24(test_not_bitarray[EVEN_STATE]); | |
291 | test_not_bitarray[ODD_STATE] = malloc_bitarray(sizeof(uint32_t) * (1<<19)); | |
292 | clear_bitarray24(test_not_bitarray[ODD_STATE]); | |
293 | ||
294 | uint32_t count[2]; | |
295 | bool all_odd_states_are_possible_for_notbitflip = false; | |
296 | ||
297 | printf("\n\nStarting search for crypto1 states resulting in bitflip property 0x%03x...\n", bitflip); | |
298 | 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)) { | |
299 | bool even_state_is_possible = false; | |
300 | time_t time_now = time(NULL); | |
301 | if (difftime(time_now, last_check_time) > 5*60) { // print status every 5 minutes | |
302 | float runtime = difftime(time_now, start_time); | |
303 | float remaining_time = runtime * ((1<<23) - even_state) / even_state; | |
304 | printf("\n%1.1f hours elapsed, expected completion in %1.1f hours (%1.1f days)", runtime/3600, remaining_time/3600, remaining_time/3600/24); | |
305 | last_check_time = time_now; | |
306 | } | |
307 | 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)) { | |
308 | if (even_state_is_possible && test_bit24(test_bitarray[ODD_STATE], odd_state)) continue; | |
309 | // load crypto1 state | |
310 | struct Crypto1State cs; | |
311 | cs.odd = odd_state >> 4; | |
312 | cs.even = even_state >> 4; | |
313 | ||
314 | // track flipping bits in state | |
315 | struct Crypto1DeltaState { | |
316 | uint_fast8_t odd; | |
317 | uint_fast8_t even; | |
318 | } cs_delta; | |
319 | cs_delta.odd = 0; | |
320 | cs_delta.even = 0; | |
321 | ||
322 | uint_fast16_t keystream = 0; | |
323 | ||
324 | // decrypt 9 bits | |
325 | for (int i = 0; i < 9; i++) { | |
326 | uint_fast8_t keystream_bit = filter(cs.odd & 0x000fffff) ^ filter((cs.odd & 0x000fffff) ^ cs_delta.odd); | |
327 | keystream = keystream << 1 | keystream_bit; | |
328 | uint_fast8_t nt_bit = BIT(bitflip, i) ^ keystream_bit; | |
329 | uint_fast8_t LSFR_feedback = BIT(cs_delta.odd, 2) ^ BIT(cs_delta.even, 2) ^ BIT(cs_delta.odd, 3); | |
330 | ||
331 | cs_delta.even = cs_delta.even << 1 | (LSFR_feedback ^ nt_bit); | |
332 | uint_fast8_t tmp = cs_delta.odd; | |
333 | cs_delta.odd = cs_delta.even; | |
334 | cs_delta.even = tmp; | |
335 | ||
336 | cs.even = cs.odd; | |
337 | if (i & 1) { | |
338 | cs.odd = odd_state >> (7 - i) / 2; | |
339 | } else { | |
340 | cs.odd = even_state >> (7 - i) / 2; | |
341 | } | |
342 | } | |
343 | ||
344 | if (evenparity32(keystream) == evenparity32(bitflip)) { | |
345 | // found valid bitflip state | |
346 | even_state_is_possible = true; | |
347 | set_bit24(test_bitarray[EVEN_STATE], even_state); | |
348 | set_bit24(test_bitarray[EVEN_STATE], 1 << 23 | even_state); | |
349 | set_bit24(test_bitarray[ODD_STATE], odd_state); | |
350 | } else { | |
351 | // found valid !bitflip state | |
352 | set_bit24(test_not_bitarray[EVEN_STATE], even_state); | |
353 | set_bit24(test_not_bitarray[EVEN_STATE], 1 << 23 | even_state); | |
354 | set_bit24(test_not_bitarray[ODD_STATE], odd_state); | |
355 | } | |
356 | } | |
357 | if (!even_state_is_possible) { | |
358 | all_odd_states_are_possible_for_notbitflip = true; | |
359 | } | |
360 | } | |
361 | ||
362 | printf("\nAnalysis completed. Checking for effective bitflip properties...\n"); | |
363 | for (odd_even_t odd_even = EVEN_STATE; odd_even <= ODD_STATE; odd_even++) { | |
364 | count[odd_even] = count_states(test_bitarray[odd_even]); | |
365 | if (count[odd_even] != 1<<24) { | |
366 | printf("Writing %d possible %s states for bitflip property %03x (%d (%1.2f%%) states eliminated)\n", | |
367 | count[odd_even], | |
368 | odd_even==EVEN_STATE?"even":"odd", | |
369 | bitflip, (1<<24) - count[odd_even], | |
370 | (float)((1<<24) - count[odd_even]) / (1<<24) * 100.0); | |
371 | #ifndef TEST_RUN | |
372 | write_bitflips_file(odd_even, bitflip, sum_a0, test_bitarray[odd_even]); | |
373 | #endif | |
374 | } else { | |
375 | printf("All %s states for bitflip property %03x are possible. No file written.\n", odd_even==EVEN_STATE?"even":"odd", bitflip); | |
376 | } | |
377 | } | |
378 | uint32_t *restrict test_bitarray_2nd = malloc_bitarray(sizeof(uint32_t) * (1<<19)); | |
379 | clear_bitarray24(test_bitarray_2nd); | |
380 | for (odd_even_t odd_even = EVEN_STATE; odd_even <= ODD_STATE; odd_even++) { | |
381 | if (count[odd_even] != 1<<24) { | |
382 | for (uint32_t state = 0; state < (1<<24); state += 1<<4) { | |
383 | uint32_t line = test_bitarray[odd_even][state>>5]; | |
384 | uint16_t half_line = state&0x000000010 ? line&0x0000ffff : line>>16; | |
385 | if (half_line != 0) { | |
386 | for (uint32_t low_bits = 0; low_bits < (1<<4); low_bits++) { | |
387 | set_bit24(test_bitarray_2nd, low_bits << 20 | state >> 4); | |
388 | } | |
389 | } | |
390 | } | |
391 | count[odd_even] = count_states(test_bitarray_2nd); | |
392 | if (count[odd_even] != 1<<24) { | |
393 | printf("Writing %d possible %s states for bitflip property %03x (%d (%1.2f%%) states eliminated)\n", | |
394 | count[odd_even], | |
395 | odd_even==EVEN_STATE?"even":"odd", | |
396 | bitflip | BITFLIP_2ND_BYTE, (1<<24) - count[odd_even], | |
397 | (float)((1<<24) - count[odd_even]) / (1<<24) * 100.0); | |
398 | #ifndef TEST_RUN | |
399 | write_bitflips_file(odd_even, bitflip | BITFLIP_2ND_BYTE, sum_a0, test_bitarray_2nd); | |
400 | #endif | |
401 | } else { | |
402 | printf("All %s states for bitflip property %03x are possible. No file written.\n", odd_even==EVEN_STATE?"even":"odd", bitflip | BITFLIP_2ND_BYTE); | |
403 | } | |
404 | } else { | |
405 | printf("All %s states for bitflip property %03x are possible. No file written.\n", odd_even==EVEN_STATE?"even":"odd", bitflip | BITFLIP_2ND_BYTE); | |
406 | } | |
407 | } | |
408 | ||
409 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |
410 | // second run for the remaining "not bitflip" states | |
411 | printf("\n\nStarting search for crypto1 states resulting in bitflip property 0x%03x...", bitflip | 0x100); | |
412 | start_time = time(NULL); | |
413 | last_check_time = start_time; | |
414 | 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)) { | |
415 | bool even_state_is_possible = test_bit24(test_not_bitarray[EVEN_STATE], even_state); | |
416 | time_t time_now = time(NULL); | |
417 | if (difftime(time_now, last_check_time) > 5*60) { // print status every 5 minutes | |
418 | float runtime = difftime(time_now, start_time); | |
419 | float remaining_time = runtime * ((1<<23) - even_state) / even_state; | |
420 | printf("\n%1.1f hours elapsed, expected completion in %1.1f hours (%1.1f days)", runtime/3600, remaining_time/3600, remaining_time/3600/24); | |
421 | last_check_time = time_now; | |
422 | } | |
423 | 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)) { | |
424 | if (even_state_is_possible) { | |
425 | if (all_odd_states_are_possible_for_notbitflip) break; | |
426 | if (test_bit24(test_not_bitarray[ODD_STATE], odd_state)) continue; | |
427 | } | |
428 | // load crypto1 state | |
429 | struct Crypto1State cs; | |
430 | cs.odd = odd_state >> 4; | |
431 | cs.even = even_state >> 4; | |
432 | ||
433 | // track flipping bits in state | |
434 | struct Crypto1DeltaState { | |
435 | uint_fast8_t odd; | |
436 | uint_fast8_t even; | |
437 | } cs_delta; | |
438 | cs_delta.odd = 0; | |
439 | cs_delta.even = 0; | |
440 | ||
441 | uint_fast16_t keystream = 0; | |
442 | // uint_fast16_t nt = 0; | |
443 | ||
444 | // decrypt 9 bits | |
445 | for (int i = 0; i < 9; i++) { | |
446 | uint_fast8_t keystream_bit = filter(cs.odd & 0x000fffff) ^ filter((cs.odd & 0x000fffff) ^ cs_delta.odd); | |
447 | keystream = keystream << 1 | keystream_bit; | |
448 | uint_fast8_t nt_bit = BIT(bitflip|0x100, i) ^ keystream_bit; | |
449 | uint_fast8_t LSFR_feedback = BIT(cs_delta.odd, 2) ^ BIT(cs_delta.even, 2) ^ BIT(cs_delta.odd, 3); | |
450 | ||
451 | cs_delta.even = cs_delta.even << 1 | (LSFR_feedback ^ nt_bit); | |
452 | uint_fast8_t tmp = cs_delta.odd; | |
453 | cs_delta.odd = cs_delta.even; | |
454 | cs_delta.even = tmp; | |
455 | ||
456 | cs.even = cs.odd; | |
457 | if (i & 1) { | |
458 | cs.odd = odd_state >> (7 - i) / 2; | |
459 | } else { | |
460 | cs.odd = even_state >> (7 - i) / 2; | |
461 | } | |
462 | } | |
463 | ||
464 | if (evenparity32(keystream) != evenparity32(bitflip)) { | |
465 | // found valid !bitflip state | |
466 | even_state_is_possible = true; | |
467 | set_bit24(test_not_bitarray[EVEN_STATE], even_state); | |
468 | set_bit24(test_not_bitarray[EVEN_STATE], 1 << 23 | even_state); | |
469 | set_bit24(test_not_bitarray[ODD_STATE], odd_state); | |
470 | } | |
471 | } | |
472 | } | |
473 | ||
474 | printf("\nAnalysis completed. Checking for effective !bitflip properties...\n"); | |
475 | for (odd_even_t odd_even = EVEN_STATE; odd_even <= ODD_STATE; odd_even++) { | |
476 | count[odd_even] = count_states(test_not_bitarray[odd_even]); | |
477 | if (count[odd_even] != 1<<24) { | |
478 | printf("Writing %d possible %s states for bitflip property %03x (%d (%1.2f%%) states eliminated)\n", | |
479 | count[odd_even], | |
480 | odd_even==EVEN_STATE?"even":"odd", | |
481 | bitflip|0x100, (1<<24) - count[odd_even], | |
482 | (float)((1<<24) - count[odd_even]) / (1<<24) * 100.0); | |
483 | #ifndef TEST_RUN | |
484 | write_bitflips_file(odd_even, bitflip|0x100, sum_a0, test_not_bitarray[odd_even]); | |
485 | #endif | |
486 | } else { | |
487 | printf("All %s states for bitflip property %03x are possible. No file written.\n", odd_even==EVEN_STATE?"even":"odd", bitflip|0x100); | |
488 | } | |
489 | } | |
490 | ||
491 | clear_bitarray24(test_bitarray_2nd); | |
492 | for (odd_even_t odd_even = EVEN_STATE; odd_even <= ODD_STATE; odd_even++) { | |
493 | if (count[odd_even] != 1<<24) { | |
494 | for (uint32_t state = 0; state < (1<<24); state += 1<<4) { | |
495 | uint32_t line = test_not_bitarray[odd_even][state>>5]; | |
496 | uint16_t half_line = state&0x000000010 ? line&0x0000ffff : line>>16; | |
497 | if (half_line != 0) { | |
498 | for (uint32_t low_bits = 0; low_bits < (1<<4); low_bits++) { | |
499 | set_bit24(test_bitarray_2nd, low_bits << 20 | state >> 4); | |
500 | } | |
501 | } | |
502 | } | |
503 | count[odd_even] = count_states(test_bitarray_2nd); | |
504 | if (count[odd_even] != 1<<24) { | |
505 | printf("Writing %d possible %s states for bitflip property %03x (%d (%1.2f%%) states eliminated)\n", | |
506 | count[odd_even], | |
507 | odd_even==EVEN_STATE?"even":"odd", | |
508 | bitflip | 0x100| BITFLIP_2ND_BYTE, (1<<24) - count[odd_even], | |
509 | (float)((1<<24) - count[odd_even]) / (1<<24) * 100.0); | |
510 | #ifndef TEST_RUN | |
511 | write_bitflips_file(odd_even, bitflip | 0x100 | BITFLIP_2ND_BYTE, sum_a0, test_bitarray_2nd); | |
512 | #endif | |
513 | } else { | |
514 | 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); | |
515 | } | |
516 | } else { | |
517 | 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); | |
518 | } | |
519 | } | |
520 | ||
521 | free_bitarray(test_bitarray_2nd); | |
522 | free_bitarray(test_not_bitarray[ODD_STATE]); | |
523 | free_bitarray(test_not_bitarray[EVEN_STATE]); | |
524 | free_bitarray(test_bitarray[ODD_STATE]); | |
525 | free_bitarray(test_bitarray[EVEN_STATE]); | |
526 | ||
527 | exit(0); | |
528 | } | |
529 | ||
530 | ||
531 | int main (int argc, char *argv[]) { | |
532 | ||
533 | unsigned int bitflip_in; | |
534 | int sum_a0; | |
535 | ||
536 | printf("Create tables required by hardnested attack.\n"); | |
537 | printf("Expect a runtime in the range of days or weeks.\n"); | |
538 | printf("Single thread only. If you want to use several threads, start it multiple times :-)\n\n"); | |
539 | ||
540 | if (argc != 2 && argc != 3) { | |
541 | printf(" syntax: %s <bitflip property> [<Sum_a0>]\n\n", argv[0]); | |
542 | printf(" example: %s 1f\n", argv[0]); | |
543 | return 1; | |
544 | } | |
545 | ||
546 | sscanf(argv[1],"%x", &bitflip_in); | |
547 | ||
548 | if (bitflip_in > 255) { | |
549 | printf("Bitflip property must be less than or equal to 0xff\n\n"); | |
550 | return 1; | |
551 | } | |
552 | ||
553 | if(argc == 3) { | |
554 | sscanf(argv[2], "%d", &sum_a0); | |
555 | } | |
556 | ||
557 | switch (sum_a0) { | |
558 | case 0: | |
559 | case 32: | |
560 | case 56: | |
561 | case 64: | |
562 | case 80: | |
563 | case 96: | |
564 | case 104: | |
565 | case 112: | |
566 | case 120: | |
567 | case 128: | |
568 | case 136: | |
569 | case 144: | |
570 | case 152: | |
571 | case 160: | |
572 | case 176: | |
573 | case 192: | |
574 | case 200: | |
575 | case 224: | |
576 | case 256: break; | |
577 | default: sum_a0 = -1; | |
578 | } | |
579 | ||
580 | printf("Calculating for bitflip = %02x, sum_a0 = %d\n", bitflip_in, sum_a0); | |
581 | ||
582 | init_part_sum_bitarrays(); | |
583 | init_sum_bitarray(sum_a0); | |
584 | ||
585 | precalculate_bit0_bitflip_bitarrays(bitflip_in, sum_a0); | |
586 | ||
587 | free_sum_bitarray(); | |
588 | free_part_sum_bitarrays(); | |
589 | ||
590 | return 0; | |
591 | } |