2 * ht2crack2buildtable.c
3 * This builds the 1.2TB table and sorts it.
6 #include "ht2crackutils.h"
9 // DATAMAX is the size of each bucket (bytes). There are 65536 buckets so choose a value such that
10 // DATAMAX * 65536 < RAM available. For ex, if you want to use 12GB of RAM (for a 16GB machine
11 // leaving some RAM free for OS and other stuff), DATAMAX = 12GB / 65536 = 196608. Round this down
12 // to a power of 10; DATAMAX = 196600.
13 #define DATAMAX 196600 // around 192K rounded down to a power of 10
15 // NUM_BUILD_THREADS and NUM_SORT_THREADS are the number of threads to run concurrently. These should
16 // ideally be equal to the number of virtual cores you have available. A quad-core machine will
17 // likely have 8 virtual cores, so set them to 8.
19 // If sorting fails with a 'bus error' then that is likely because your disk I/O can't keep up with
20 // the read/write demands of the multi-threaded sorting. In this case, reduce the number of sorting
21 // threads. This will most likely only be a problem with network disks; SATA should be okay;
22 // USB2/3 should keep up.
24 // These MUST be a power of 2 for the maths to work - you have been warned!
25 // Also, sort threads MUST be <= build threads or a horrible buffer overflow will happen!
26 #define NUM_BUILD_THREADS 8
27 #define NUM_SORT_THREADS 8
29 // DATASIZE is the number of bytes in an entry. This is 10; 4 bytes of keystream (2 are in the filepath) +
30 // 6 bytes of PRNG state.
35 // table entry for a bucket
38 pthread_mutex_t mutex
;
56 static void create_table(struct table
*tt
, int d_1
, int d_2
) {
58 printf("create_table: t is NULL\n");
63 tt
->data
= (unsigned char *)calloc(1, DATAMAX
);
65 printf("create_table: cannot calloc data\n");
69 // set data ptr to start of data table
73 if (pthread_mutex_init(&(tt
->mutex
), NULL
)) {
74 printf("create_table: cannot init mutex\n");
79 // snprintf(tt->path, sizeof(tt->path), "/Volumes/2tb/%02X/%02X.bin", d_1 & 0xff, d_2 & 0xff);
80 snprintf(tt
->path
, sizeof(tt
->path
), "table/%02x/%02x.bin", d_1
& 0xff, d_2
& 0xff);
84 // create all table entries
85 static void create_tables(struct table
*tt
) {
89 printf("create_tables: t is NULL\n");
93 for (i
= 0; i
< 0x100; i
++) {
94 for (j
= 0; j
< 0x100; j
++) {
95 create_table(tt
+ ((i
* 0x100) + j
), i
, j
);
101 // free the table memory
102 static void free_tables(struct table
*tt
) {
104 printf("free_tables: tt is NULL\n");
108 for (int i
= 0; i
< 0x10000; i
++) {
109 struct table
*ttmp
= tt
+ i
;
116 // write (partial) table to file
117 static void writetable(struct table
*t1
) {
120 if (debug
) printf("writetable %s\n", t1
->path
);
122 fd
= open(t1
->path
, O_WRONLY
| O_CREAT
| O_APPEND
, 0644);
124 printf("writetable cannot open file %s for appending\n", t1
->path
);
128 if (debug
) printf("writetable %s opened\n", t1
->path
);
130 if (write(fd
, t1
->data
, t1
->ptr
- t1
->data
) < (t1
->ptr
- t1
->data
)) {
131 printf("writetable cannot write all of the data\n");
135 if (debug
) printf("writetable %s written\n", t1
->path
);
141 // store value in table
142 static void store(unsigned char *data
) {
143 unsigned char d_1
, d_2
;
147 // use the first two bytes as an index
150 offset
= (d_1
* 0x100) + d_2
;
152 if (debug
) printf("store, d1=%02X, d2=%02X, offset = %d\n", d_1
, d_2
, offset
);
154 // get pointer to table entry
157 // wait for a lock on this entry
158 if (pthread_mutex_lock(&(t1
->mutex
))) {
159 printf("store: cannot lock mutex at offset %d\n", offset
);
163 if (debug
) printf("store, offset = %d, got lock\n", offset
);
166 memcpy(t1
->ptr
, data
+ 2, 10);
168 if (debug
) printf("store, offset = %d, copied data\n", offset
);
173 // check if table is full
174 if ((t1
->ptr
- t1
->data
) >= DATAMAX
) {
175 // write the table to disk
181 if (debug
) printf("store, offset = %d, after possible write\n", offset
);
184 if (pthread_mutex_unlock(&(t1
->mutex
))) {
185 printf("store: cannot unlock mutex at offset %d\n", offset
);
189 if (debug
) printf("store, offset = %d, unlocked\n", offset
);
193 // writes the ks (keystream) and s (state)
194 static void write_ks_s(uint32_t ks1
, uint32_t ks2
, uint64_t shiftreg
) {
195 unsigned char buf
[16];
198 writebuf(buf
, ks1
, 3);
199 writebuf(buf
+ 3, ks2
, 3);
200 writebuf(buf
+ 6, shiftreg
, 6);
207 // builds the di table for jumping
208 static void builddi(int steps
, int table
) {
212 uint64_t *thisd
= NULL
;
220 } else if (table
== 2) {
224 printf("builddi: invalid table num\n");
229 for (i
= 0; i
< 48; i
++) {
230 mystate
.shiftreg
= statemask
;
232 hitag2_nstep(&mystate
, steps
);
233 thisd
[i
] = mystate
.shiftreg
;
235 statemask
= statemask
<< 1;
239 // jump function - quickly jumps a load of steps
240 static void jumpnsteps(Hitag_State
*hstate
, int table
) {
244 uint64_t *thisd
= NULL
;
250 } else if (table
== 2) {
253 printf("jumpnsteps: invalid table num\n");
257 // xor all di.si where di is a d state and si is a bit
258 // we do this by multiplying di by si:
259 // if si is 1, di.si = di; if si is 0, di.si = 0
262 for (i
= 0; i
< 48; i
++) {
263 if (hstate
->shiftreg
& bitmask
) {
264 output
= output
^ thisd
[i
];
267 bitmask
= bitmask
<< 1;
270 hstate
->shiftreg
= output
;
275 // thread to build a part of the table
276 static void *buildtable(void *dd
) {
279 unsigned long maxentries
= 1;
280 int index
= (int)(long)dd
;
281 int tnum
= NUM_BUILD_THREADS
;
283 /* set random state */
284 hstate
.shiftreg
= 0x123456789abc;
287 /* jump to offset using jump table 2 (2048) */
288 for (unsigned long i
= 0; i
< index
; i
++) {
289 jumpnsteps(&hstate
, 2);
292 /* set max entries - this is a fraction of 2^37 depending on how many threads we are running.
299 maxentries
= maxentries
<< 37;
300 while (!(tnum
& 0x1)) {
301 maxentries
= maxentries
>> 1;
305 /* make the entries */
306 for (unsigned long i
= 0; i
< maxentries
; i
++) {
308 // copy the current state
309 hstate2
.shiftreg
= hstate
.shiftreg
;
310 hstate2
.lfsr
= hstate
.lfsr
;
312 // get 48 bits of keystream from hstate2
313 // this is split into 2 x 24 bit
314 uint32_t ks1
= hitag2_nstep(&hstate2
, 24);
315 uint32_t ks2
= hitag2_nstep(&hstate2
, 24);
317 write_ks_s(ks1
, ks2
, hstate
.shiftreg
);
319 // jump hstate forward 2048 * NUM_BUILD_THREADS states using di table
320 // this is because we're running NUM_BUILD_THREADS threads at once, from NUM_BUILD_THREADS
321 // different offsets that are 2048 states apart.
322 jumpnsteps(&hstate
, 1);
329 // make 'table/' (unsorted) and 'sorted/' dir structures
330 static void makedirs(void) {
334 if (mkdir("table", 0755)) {
335 printf("cannot make dir table\n");
338 if (mkdir("sorted", 0755)) {
339 printf("cannot make dir sorted\n");
343 for (i
= 0; i
< 0x100; i
++) {
344 snprintf(path
, sizeof(path
), "table/%02x", i
);
345 if (mkdir(path
, 0755)) {
346 printf("cannot make dir %s\n", path
);
349 snprintf(path
, sizeof(path
), "sorted/%02x", i
);
350 if (mkdir(path
, 0755)) {
351 printf("cannot make dir %s\n", path
);
357 static int datacmp(const void *p1
, const void *p2
, void *dummy
) {
358 unsigned char *d_1
= (unsigned char *)p1
;
359 unsigned char *d_2
= (unsigned char *)p2
;
361 return memcmp(d_1
, d_2
, DATASIZE
);
364 static void *sorttable(void *dd
) {
370 unsigned char *data
= NULL
;
371 struct stat filestat
;
372 int index
= (int)(long)dd
;
373 int space
= 0x100 / NUM_SORT_THREADS
;
375 // create table - 50MB should be enough
376 unsigned char *table
= (unsigned char *)calloc(1, 50UL * 1024UL * 1024UL);
378 printf("sorttable: cannot calloc table\n");
382 // loop over our first byte values
383 for (i
= (index
* space
); i
< ((index
+ 1) * space
); i
++) {
384 // loop over all second byte values
385 for (j
= 0; j
< 0x100; j
++) {
387 printf("sorttable: processing bytes 0x%02x/0x%02x\n", i
, j
);
389 // open file, stat it and mmap it
390 snprintf(infile
, sizeof(infile
), "table/%02x/%02x.bin", i
, j
);
392 fdin
= open(infile
, O_RDONLY
);
394 printf("cannot open file %s\n", infile
);
398 if (fstat(fdin
, &filestat
)) {
399 printf("cannot stat file %s\n", infile
);
403 data
= mmap((caddr_t
)0, filestat
.st_size
, PROT_READ
, MAP_PRIVATE
, fdin
, 0);
404 if (data
== MAP_FAILED
) {
405 printf("cannot mmap file %s\n", infile
);
409 // copy data into table
410 memcpy(table
, data
, filestat
.st_size
);
412 uint64_t numentries
= filestat
.st_size
/ DATASIZE
;
414 // unmap file and close it
415 if (munmap(data
, filestat
.st_size
)) {
416 printf("cannot munmap %s\n", infile
);
423 void *dummy
= NULL
; // clang
424 qsort_r(table
, numentries
, DATASIZE
, datacmp
, dummy
);
427 snprintf(outfile
, sizeof(outfile
), "sorted/%02x/%02x.bin", i
, j
);
428 fdout
= open(outfile
, O_WRONLY
| O_CREAT
, 0644);
430 printf("cannot create outfile %s\n", outfile
);
433 if (write(fdout
, table
, numentries
* DATASIZE
) != (numentries
* DATASIZE
)) {
434 printf("writetable cannot write all of the data\n");
440 if (unlink(infile
)) {
441 printf("cannot remove file %s\n", infile
);
450 int main(int argc
, char *argv
[]) {
451 pthread_t threads
[NUM_BUILD_THREADS
];
454 // make the table of tables
455 t
= (struct table
*)calloc(sizeof(struct table
) * 65536, sizeof(uint8_t));
457 printf("calloc failed\n");
464 // create the directories
467 // build the jump table for incremental steps
468 builddi(2048 * NUM_BUILD_THREADS
, 1);
470 // build the jump table for setting the offset
474 for (long i
= 0; i
< NUM_BUILD_THREADS
; i
++) {
475 int ret
= pthread_create(&(threads
[i
]), NULL
, buildtable
, (void *)(i
));
477 printf("cannot start buildtable thread %ld\n", i
);
482 if (debug
) printf("main, started buildtable threads\n");
484 // wait for threads to finish
485 for (long i
= 0; i
< NUM_BUILD_THREADS
; i
++) {
486 int ret
= pthread_join(threads
[i
], &status
);
488 printf("cannot join buildtable thread %ld\n", i
);
491 printf("buildtable thread %ld finished\n", i
);
494 // write all remaining files
495 for (long i
= 0; i
< 0x10000; i
++) {
496 struct table
*t1
= t
+ i
;
497 if (t1
->ptr
> t1
->data
) {
506 // now for the sorting
509 for (long i
= 0; i
< NUM_SORT_THREADS
; i
++) {
510 int ret
= pthread_create(&(threads
[i
]), NULL
, sorttable
, (void *)(i
));
512 printf("cannot start sorttable thread %ld\n", i
);
517 if (debug
) printf("main, started sorttable threads\n");
519 // wait for threads to finish
520 for (long i
= 0; i
< NUM_SORT_THREADS
; i
++) {
521 int ret
= pthread_join(threads
[i
], &status
);
523 printf("cannot join sorttable thread %ld\n", i
);
526 printf("sorttable thread %ld finished\n", i
);