7 #include "hitagcrypto.h"
8 #include "ht2crackutils.h"
10 // max number of NrAr pairs to load - you only need 136 good pairs, but this
15 // table entry for Tkleft
22 // table entry for nR aR pair
28 // struct to hold data for thread
37 // macros to pick out 4 bits in various patterns of 1s & 2s & make a new number
38 // these and the following hitag2_crypt function taken from Rfidler
39 #define pickbits2_2(S, A, B) ( ((S >> A) & 3) | ((S >> (B - 2)) & 0xC) )
40 #define pickbits1x4(S, A, B, C, D) ( ((S >> A) & 1) | ((S >> (B - 1)) & 2) | \
41 ((S >> (C - 2)) & 4) | ((S >> (D - 3)) & 8) )
42 #define pickbits1_1_2(S, A, B, C) ( ((S >> A) & 1) | ((S >> (B - 1)) & 2) | \
43 ((S >> (C - 2)) & 0xC) )
44 #define pickbits2_1_1(S, A, B, C) ( ((S >> A) & 3) | ((S >> (B - 2)) & 4) | \
45 ((S >> (C - 3)) & 8) )
46 #define pickbits1_2_1(S, A, B, C) ( ((S >> A) & 1) | ((S >> (B - 1)) & 6) | \
47 ((S >> (C - 3)) & 8) )
50 static uint32_t hitag2_crypt(uint64_t s
) {
51 const uint32_t ht2_function4a
= 0x2C79; // 0010 1100 0111 1001
52 const uint32_t ht2_function4b
= 0x6671; // 0110 0110 0111 0001
53 const uint32_t ht2_function5c
= 0x7907287B; // 0111 1001 0000 0111 0010 1000 0111 1011
56 bitindex
= (ht2_function4a
>> pickbits2_2(s
, 1, 4)) & 1;
57 bitindex
|= ((ht2_function4b
<< 1) >> pickbits1_1_2(s
, 7, 11, 13)) & 0x02;
58 bitindex
|= ((ht2_function4b
<< 2) >> pickbits1x4(s
, 16, 20, 22, 25)) & 0x04;
59 bitindex
|= ((ht2_function4b
<< 3) >> pickbits2_1_1(s
, 27, 30, 32)) & 0x08;
60 bitindex
|= ((ht2_function4a
<< 4) >> pickbits1_2_1(s
, 33, 42, 45)) & 0x10;
62 return (ht2_function5c
>> bitindex
) & 1;
66 // this function is a modification of the filter function f, based heavily
67 // on the hitag2_crypt function in Rfidler
68 static int fnP(uint64_t klowery
) {
69 const uint32_t ht2_function4a
= 0x2C79; // 0010 1100 0111 1001
70 const uint32_t ht2_function4b
= 0x6671; // 0110 0110 0111 0001
71 const uint32_t ht2_function4p
= 0xAE83; // 1010 1110 1000 0011
74 i
= (ht2_function4a
>> pickbits2_2(klowery
, 2, 5)) & 1;
75 i
|= ((ht2_function4b
<< 1) >> pickbits1_1_2(klowery
, 8, 12, 14)) & 0x02;
76 i
|= ((ht2_function4b
<< 2) >> pickbits1x4(klowery
, 17, 21, 23, 26)) & 0x04;
77 i
|= ((ht2_function4b
<< 3) >> pickbits2_1_1(klowery
, 28, 31, 33)) & 0x08;
79 // modified to use reference implementation approach
80 // orig fc table is 0x7907287B = 0111 1001 0000 0111 0010 1000 0111 1011
81 // we ignore the top bit (bit 4) of the parameter, so therefore create a new
82 // table that indicates which bit positions are the same if the top bit is 1 or 0
83 return (ht2_function4p
>> i
) & 1;
86 // comparison function for sorting/searching Tklower entries
87 static int Tk_cmp(const void *v1
, const void *v2
) {
88 const struct Tklower
*Tk1
= (struct Tklower
*)v1
;
89 const struct Tklower
*Tk2
= (struct Tklower
*)v2
;
91 if (Tk1
->yxorb
< Tk2
->yxorb
) {
93 } else if (Tk1
->yxorb
> Tk2
->yxorb
) {
100 // test for bad guesses of kmiddle
101 static int is_kmiddle_badguess(uint64_t z
, struct Tklower
*Tk
, int max
, int aR0
) {
103 struct Tklower
*result
, target
;
105 // "If there is an entry in Tklower for which y ^ b = z but !b32 != aR[0]
106 // then the attacker learns that kmiddle is a bad guess... otherwise, if
107 // !b32 == aR[0] then kmiddle is still a viable guess."
111 result
= (struct Tklower
*)bsearch(&target
, Tk
, max
, sizeof(struct Tklower
), Tk_cmp
);
114 if (result
->notb32
!= aR0
) {
124 // function to test if a partial key is valid
125 static int testkey(uint64_t *out
, uint64_t uid
, uint64_t pkey
, uint64_t nR
, uint64_t aR
) {
135 normaR
= ((revaR
>> 24) | ((revaR
>> 8) & 0xff00) | ((revaR
<< 8) & 0xff0000) | (revaR
<< 24));
137 // search for remaining 14 bits
138 for (kupper
= 0; kupper
< 0x3fff; kupper
++) {
139 key
= (kupper
<< 34) | pkey
;
140 hitag2_init(&hstate
, key
, uid
, nR
);
141 b
= hitag2_nstep(&hstate
, 32);
142 if ((normaR
^ b
) == 0xffffffff) {
150 // some notes on how I think this attack should work.
151 // due to the way fc works, in a number of cases, it doesn't matter what
152 // the most significant bits are doing for it to produce the same result.
153 // These are the most sig 14 bits to be clear. Looking at fc it is poss
154 // to see cases where the most sig bit of the input to fc (which is made
155 // from fa on 4 of the most sig bits from bit 34 onwards) does not affect
156 // whether it gives a 0 or 1 as the input 0b0ABCD gives the same bit value
158 // The PRNG is initialised by setting the lower 32 bits to the UID, with
159 // the upper 16 bits set to the lower 16 bits of the key. Next the 32
160 // upper bits of the key are XORed with the private nonce and these are
161 // shifted in, with the PRNG outputting bits b0 to b31. These bits are
162 // used to encrypt (XOR with) the nonce to produce nR, which is sent to
164 // (The card should init the PRNG with the same UID and lower 16 bits of
165 // the key, receive the nR, then shift it in bit by bit while xoring each
166 // bit with its output, and the key - this essentially decrypts the nR to
167 // the nonce XOR the upper 32 bits of the key, while shifting it in.
168 // The card's PRNG will then be in the same state as the RWD.)
169 // By knowing the UID and guessing the lower 16 bits of the key, and
170 // focusing on nR values that don't affect the upper bits of fc, we can
171 // limit our guesses to a smaller set than a full brute force and
172 // effectively work out candidates for the lower 34 bits of the key.
174 static void *crack(void *d
) {
175 struct threaddata
*data
= (struct threaddata
*)d
;
178 unsigned int numnrar
;
183 uint64_t klower
, kmiddle
, klowery
;
184 uint64_t y
, b
, z
, bit
;
187 uint64_t foundkey
, revkey
;
190 unsigned int badguess
;
191 struct Tklower
*Tk
= NULL
;
194 printf("Thread data is NULL\n");
200 numnrar
= data
->numnrar
;
202 // create space for tables
203 Tk
= (struct Tklower
*)malloc(sizeof(struct Tklower
) * 0x40000);
205 printf("Failed to allocate memory (Tk)\n");
210 for (klower
= data
->klowerstart
; klower
< (data
->klowerstart
+ data
->klowerrange
); klower
++) {
211 printf("trying klower = 0x%05"PRIx64
"\n", klower
);
214 for (y
= 0; y
< 0x40000; y
++) {
216 klowery
= (y
<< 16) | klower
;
217 // check for cases where right most bit of fc doesn't matter
221 Tk
[count
].klowery
= klowery
;
222 // build the initial prng state
223 hstate
.shiftreg
= (klower
<< 32) | uid
;
224 // zero the lfsr so only 0s are inserted
226 // insert y into shiftreg and extract keystream, reversed order
229 for (j
= 0; j
< 2; j
++) {
230 hstate
.shiftreg
= hstate
.shiftreg
| ((ytmp
& 0xffff) << 48);
231 for (i
= 0; i
< 16; i
++) {
232 hstate
.shiftreg
= hstate
.shiftreg
>> 1;
233 bit
= hitag2_crypt(hstate
.shiftreg
);
234 b
= (b
>> 1) | (bit
<< 31);
239 // store the xor of y and b0-17
240 Tk
[count
].yxorb
= y
^ (b
& 0x3ffff);
242 // get and store inverse of next bit from prng
243 // don't need to worry about shifting in the new bit because
244 // it doesn't affect the filter function anyway
245 hstate
.shiftreg
= hstate
.shiftreg
>> 1;
246 Tk
[count
].notb32
= hitag2_crypt(hstate
.shiftreg
) ^ 0x1;
253 qsort(Tk
, count
, sizeof(struct Tklower
), Tk_cmp
);
256 for (kmiddle
= 0; kmiddle
< 0x40000; kmiddle
++) {
257 // loop over nRaR pairs
260 for (i
= 0; (i
< numnrar
) && (!badguess
); i
++) {
261 z
= kmiddle
^ (TnRaR
[i
].nR
& 0x3ffff);
262 ret
= is_kmiddle_badguess(z
, Tk
, count
, TnRaR
[i
].aR
& 0x1);
265 } else if (ret
== 0) {
270 if ((found
) && (!badguess
)) {
272 printf("possible partial key found: 0x%012"PRIx64
"\n", ((uint64_t)kmiddle
<< 16) | klower
);
274 if (testkey(&foundkey
, uid
, (kmiddle
<< 16 | klower
), TnRaR
[0].nR
, TnRaR
[0].aR
) &&
275 testkey(&foundkey
, uid
, (kmiddle
<< 16 | klower
), TnRaR
[1].nR
, TnRaR
[1].aR
)) {
276 // normalise foundkey
277 revkey
= rev64(foundkey
);
278 foundkey
= ((revkey
>> 40) & 0xff) | ((revkey
>> 24) & 0xff00) | ((revkey
>> 8) & 0xff0000) | ((revkey
<< 8) & 0xff000000) | ((revkey
<< 24) & 0xff00000000) | ((revkey
<< 40) & 0xff0000000000);
279 printf("\n\nSuccess - key = %012"PRIx64
"\n", foundkey
);
282 return (void *)foundkey
;
293 int main(int argc
, char *argv
[]) {
296 pthread_t threads
[NUM_THREADS
];
300 uint64_t klowerstart
;
301 unsigned int numnrar
= 0;
307 struct nRaR
*TnRaR
= NULL
;
308 struct threaddata
*tdata
= NULL
;
311 printf("%s uid nRaRfile\n", argv
[0]);
315 // read the UID into internal format
316 if (!strncmp(argv
[1], "0x", 2)) {
317 uid
= rev32(hexreversetoulong(argv
[1] + 2));
319 uid
= rev32(hexreversetoulong(argv
[1]));
322 // create table of nR aR pairs
323 TnRaR
= (struct nRaR
*)malloc(sizeof(struct nRaR
) * NUM_NRAR
);
326 fp
= fopen(argv
[2], "r");
328 printf("cannot open nRaRfile\n");
332 // set klowerstart (for debugging)
334 klowerstart
= strtol(argv
[3], NULL
, 0);
339 // read in nR aR pairs
341 buf
= (char *)malloc(lenbuf
);
343 printf("cannot malloc buf\n");
347 while (getline(&buf
, &lenbuf
, fp
) > 0) {
348 buft1
= strchr(buf
, ' ');
350 printf("invalid file input on line %u\n", numnrar
+ 1);
355 buft2
= strchr(buft1
, '\n');
357 printf("no CR on line %u\n", numnrar
+ 1);
361 if (!strncmp(buf
, "0x", 2)) {
362 TnRaR
[numnrar
].nR
= rev32(hexreversetoulong(buf
+ 2));
363 TnRaR
[numnrar
].aR
= rev32(hexreversetoulong(buft1
+ 2));
365 TnRaR
[numnrar
].nR
= rev32(hexreversetoulong(buf
));
366 TnRaR
[numnrar
].aR
= rev32(hexreversetoulong(buft1
));
374 printf("Loaded %u NrAr pairs\n", numnrar
);
376 // create table of thread data
377 tdata
= (struct threaddata
*)malloc(sizeof(struct threaddata
) * NUM_THREADS
);
379 printf("cannot malloc threaddata\n");
383 for (i
= 0; i
< NUM_THREADS
; i
++) {
385 tdata
[i
].TnRaR
= TnRaR
;
386 tdata
[i
].numnrar
= numnrar
;
387 tdata
[i
].klowerrange
= 0x10000 / NUM_THREADS
;
388 tdata
[i
].klowerstart
= i
* tdata
[i
].klowerrange
;
392 // debug mode only runs one thread from klowerstart
393 tdata
[0].klowerstart
= klowerstart
;
396 // run full threaded mode
397 for (i
= 0; i
< NUM_THREADS
; i
++) {
398 if (pthread_create(&(threads
[i
]), NULL
, crack
, (void *)(tdata
+ i
))) {
399 printf("cannot start thread %d\n", i
);
405 // wait for threads to finish
406 for (i
= 0; i
< NUM_THREADS
; i
++) {
407 if (pthread_join(threads
[i
], &status
)) {
408 printf("cannot join thread %d\n", i
);
411 printf("thread %i finished\n", i
);
413 printf("Key = %012"PRIx64
"\n", (uint64_t)status
);
418 printf("Did not find key :(\n");