Bring hitag2crack tools in main Makefiles

This commit is contained in:
Philippe Teuwen 2020-05-22 19:20:44 +02:00
commit 6d33c0b784
21 changed files with 433 additions and 168 deletions

View file

@ -15,6 +15,8 @@ ifneq (,$(DESTDIR))
endif
all clean install uninstall check: %: client/% bootrom/% armsrc/% recovery/% mfkey/% nonce2key/% mf_nonce_brute/% fpga_compress/%
# hitag2crack toolsuite is not yet integrated in "all", it must be called explicitly: "make hitag2crack"
#all clean install uninstall check: %: hitag2crack/%
INSTALLTOOLS=pm3_eml2lower.sh pm3_eml2upper.sh pm3_mfdread.py pm3_mfd2eml.py pm3_eml2mfd.py findbits.py rfidtest.pl xorcheck.py
INSTALLSIMFW=sim011.bin sim011.sha512.txt
@ -103,6 +105,9 @@ client/check: FORCE
recovery/check: FORCE
$(info [*] CHECK $(patsubst %/check,%,$@))
$(Q)$(BASH) tools/pm3_tests.sh $(CHECKARGS) $(patsubst %/check,%,$@)
hitag2crack/check: FORCE
$(info [*] CHECK $(patsubst %/check,%,$@))
$(Q)$(BASH) tools/pm3_tests.sh $(CHECKARGS) $(patsubst %/check,%,$@)
common/check: FORCE
$(info [*] CHECK $(patsubst %/check,%,$@))
$(Q)$(BASH) tools/pm3_tests.sh $(CHECKARGS) $(patsubst %/check,%,$@)
@ -135,9 +140,12 @@ recovery/install: bootrom/all armsrc/all
recovery/%: FORCE cleanifplatformchanged
$(info [*] MAKE $@)
$(Q)$(MAKE) --no-print-directory -C recovery $(patsubst recovery/%,%,$@) DESTDIR=$(MYDESTDIR)
hitag2crack/%: FORCE
$(info [*] MAKE $@)
$(Q)$(MAKE) --no-print-directory -C tools/hitag2crack $(patsubst hitag2crack/%,%,$@) DESTDIR=$(MYDESTDIR)
FORCE: # Dummy target to force remake in the subdirectories, even if files exist (this Makefile doesn't know about the prerequisites)
.PHONY: all clean install uninstall help _test bootrom fullimage recovery client mfkey nonce2key mf_nonce_brute style miscchecks release FORCE udev accessrights cleanifplatformchanged
.PHONY: all clean install uninstall help _test bootrom fullimage recovery client mfkey nonce2key mf_nonce_brute hitag2crack style miscchecks release FORCE udev accessrights cleanifplatformchanged
help:
@echo "Multi-OS Makefile"
@ -157,6 +165,7 @@ help:
@echo "+ mfkey - Make tools/mfkey"
@echo "+ nonce2key - Make tools/nonce2key"
@echo "+ mf_nonce_brute - Make tools/mf_nonce_brute"
@echo "+ hitag2crack - Make tools/hitag2crack"
@echo "+ fpga_compress - Make tools/fpga_compress"
@echo
@echo "+ style - Apply some automated source code formatting rules"
@ -193,6 +202,8 @@ mf_nonce_brute: mf_nonce_brute/all
fpga_compress: fpga_compress/all
hitag2crack: hitag2crack/all
newtarbin:
$(RM) proxmark3-$(platform)-bin.tar proxmark3-$(platform)-bin.tar.gz
@touch proxmark3-$(platform)-bin.tar

View file

@ -72,6 +72,10 @@ On some architectures, pthread library is not present:
* `make client SKIPPTHREAD=1` to skip `-lpthread` at linker stage.
One tool requires a CUDA compilation environment, it can be skipped as well:
* `make hitag2crack SKIPGPU=1` to skip ht2crack5gpu tool when compiling the hitag2crack toolsuite.
Some unittests are available via `make check`, which is actually triggering individual targets as for `make install`.
`make install` is actually triggering the following individual targets which can be accessed individually:

View file

@ -0,0 +1,33 @@
# Must be called before any Makefile include
ROOT_DIR:=$(dir $(realpath $(lastword $(MAKEFILE_LIST))))
include ../../Makefile.defs
all clean install uninstall check: %: crack2/% crack3/% crack4/% crack5/%
ifneq ($(SKIPGPU),1)
all clean install uninstall check: %: crack5gpu/%
endif
crack2/%: FORCE
$(info [*] MAKE $@)
$(Q)$(MAKE) --no-print-directory -C crack2 $(patsubst crack2/%,%,$@) DESTDIR=$(MYDESTDIR)
crack3/%: FORCE
$(info [*] MAKE $@)
$(Q)$(MAKE) --no-print-directory -C crack3 $(patsubst crack3/%,%,$@) DESTDIR=$(MYDESTDIR)
crack4/%: FORCE
$(info [*] MAKE $@)
$(Q)$(MAKE) --no-print-directory -C crack4 $(patsubst crack4/%,%,$@) DESTDIR=$(MYDESTDIR)
crack5/%: FORCE
$(info [*] MAKE $@)
$(Q)$(MAKE) --no-print-directory -C crack5 $(patsubst crack5/%,%,$@) DESTDIR=$(MYDESTDIR)
crack5gpu/%: FORCE
$(info [*] MAKE $@)
$(Q)$(MAKE) --no-print-directory -C crack5gpu $(patsubst crack5gpu/%,%,$@) DESTDIR=$(MYDESTDIR)
FORCE: # Dummy target to force remake in the subdirectories, even if files exist (this Makefile doesn't know about the prerequisites)
.phony: crack2 crack3 crack4 crack5 crack5gpu FORCE

View file

@ -1,3 +1,6 @@
#ifndef HT2CRACKUTILS_H
#define HT2CRACKUTILS_H
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
@ -41,3 +44,5 @@ void buildlfsr(Hitag_State *hstate);
#define rev64(X) (rev32(X) + (rev32(X >> 32) << 32))
unsigned long hexreversetoulong(char *hex);
unsigned long long hexreversetoulonglong(char *hex);
#endif /* HT2CRACKUTILS_H */

View file

@ -1,23 +1,22 @@
CFLAGS?=-Wall -Werror -O3
# Linux libs
LIBS=-pthread -D_GNU_SOURCE
# Mac libs
# LIBS=
VPATH=../common
INC=-I ../common
MYSRCPATHS = ../common
MYSRCS = ht2crackutils.c hitagcrypto.c
MYINCLUDES =-I ../common
MYCFLAGS = -D_GNU_SOURCE
MYDEFS =
MYLDLIBS = -lpthread
all: ht2crack2buildtable.c ht2crack2search.c ht2crack2gentest.c hitagcrypto.o ht2crackutils.o
$(CC) $(CFLAGS) $(INC) -o ht2crack2buildtable ht2crack2buildtable.c hitagcrypto.o ht2crackutils.o $(LIBS)
$(CC) $(CFLAGS) $(INC) -o ht2crack2search ht2crack2search.c hitagcrypto.o ht2crackutils.o $(LIBS)
$(CC) $(CFLAGS) $(INC) -o ht2crack2gentest ht2crack2gentest.c hitagcrypto.o ht2crackutils.o $(LIBS)
BINS = ht2crack2buildtable ht2crack2search ht2crack2gentest
INSTALLTOOLS = $(BINS)
ht2crackutils.o: ht2crackutils.c ht2crackutils.h
$(CC) $(CFLAGS) -c $<
include ../../../Makefile.host
hitagcrypto.o: hitagcrypto.c hitagcrypto.h
$(CC) $(CFLAGS) -c $<
# checking platform can be done only after Makefile.host
ifneq (,$(findstring MINGW,$(platform)))
# Mingw uses by default Microsoft printf, we want the GNU printf (e.g. for %z)
# and setting _ISOC99_SOURCE sets internally __USE_MINGW_ANSI_STDIO=1
CFLAGS += -D_ISOC99_SOURCE
endif
clean:
rm -rf *.o ht2crack2buildtable ht2crack2search ht2crack2gentest
fresh: clean all
ht2crack2buildtable : $(OBJDIR)/ht2crack2buildtable.o $(MYOBJS)
ht2crack2search : $(OBJDIR)/ht2crack2search.o $(MYOBJS)
ht2crack2gentest : $(OBJDIR)/ht2crack2gentest.o $(MYOBJS)

View file

@ -4,7 +4,7 @@
*/
#include "ht2crackutils.h"
#include <stdlib.h>
// DATAMAX is the size of each bucket (bytes). There are 65536 buckets so choose a value such that
// DATAMAX * 65536 < RAM available. For ex, if you want to use 12GB of RAM (for a 16GB machine
@ -53,63 +53,63 @@ uint64_t d2[48];
int nsteps2;
// create table entry
void create_table(struct table *t, int d1, int d2) {
if (!t) {
static void create_table(struct table *tt, int d_1, int d_2) {
if (!tt) {
printf("create_table: t is NULL\n");
exit(1);
}
// create some space
t->data = (unsigned char *)malloc(DATAMAX);
if (!(t->data)) {
tt->data = (unsigned char *)malloc(DATAMAX);
if (!(tt->data)) {
printf("create_table: cannot malloc data\n");
exit(1);
}
// set data ptr to start of data table
t->ptr = t->data;
tt->ptr = tt->data;
// init the mutex
if (pthread_mutex_init(&(t->mutex), NULL)) {
if (pthread_mutex_init(&(tt->mutex), NULL)) {
printf("create_table: cannot init mutex\n");
exit(1);
}
// create the path
// sprintf(t->path, "/Volumes/2tb/%02X/%02X.bin", d1 & 0xff, d2 & 0xff);
sprintf(t->path, "table/%02x/%02x.bin", d1 & 0xff, d2 & 0xff);
// sprintf(tt->path, "/Volumes/2tb/%02X/%02X.bin", d_1 & 0xff, d_2 & 0xff);
sprintf(tt->path, "table/%02x/%02x.bin", d_1 & 0xff, d_2 & 0xff);
}
// create all table entries
void create_tables(struct table *t) {
static void create_tables(struct table *tt) {
int i, j;
if (!t) {
if (!tt) {
printf("create_tables: t is NULL\n");
exit(1);
}
for (i = 0; i < 0x100; i++) {
for (j = 0; j < 0x100; j++) {
create_table(t + ((i * 0x100) + j), i, j);
create_table(tt + ((i * 0x100) + j), i, j);
}
}
}
// free the table memory
void free_tables(struct table *t) {
static void free_tables(struct table *tt) {
int i;
struct table *ttmp;
if (!t) {
if (!tt) {
printf("free_tables: t is NULL\n");
exit(1);
}
for (i = 0; i < 0x10000; i++) {
ttmp = t + i;
ttmp = tt + i;
free(ttmp->data);
}
}
@ -117,7 +117,7 @@ void free_tables(struct table *t) {
// write (partial) table to file
void writetable(struct table *t1) {
static void writetable(struct table *t1) {
int fd;
if (debug) printf("writetable %s\n", t1->path);
@ -142,7 +142,7 @@ void writetable(struct table *t1) {
// store value in table
void store(unsigned char *data) {
static void store(unsigned char *data) {
unsigned char d_1, d_2;
int offset;
struct table *t1;
@ -194,7 +194,7 @@ void store(unsigned char *data) {
}
// writes the ks (keystream) and s (state)
void write_ks_s(uint32_t ks1, uint32_t ks2, uint64_t shiftreg) {
static void write_ks_s(uint32_t ks1, uint32_t ks2, uint64_t shiftreg) {
unsigned char buf[16];
// create buffer
@ -209,7 +209,7 @@ void write_ks_s(uint32_t ks1, uint32_t ks2, uint64_t shiftreg) {
// builds the di table for jumping
void builddi(int steps, int table) {
static void builddi(int steps, int table) {
uint64_t statemask;
int i;
Hitag_State mystate;
@ -241,7 +241,7 @@ void builddi(int steps, int table) {
}
// jump function - quickly jumps a load of steps
void jumpnsteps(Hitag_State *hstate, int table) {
static void jumpnsteps(Hitag_State *hstate, int table) {
uint64_t output = 0;
uint64_t bitmask;
int i;
@ -277,14 +277,14 @@ void jumpnsteps(Hitag_State *hstate, int table) {
// thread to build a part of the table
void *buildtable(void *d) {
static void *buildtable(void *dd) {
Hitag_State hstate;
Hitag_State hstate2;
unsigned long i;
unsigned long maxentries = 1;
uint32_t ks1;
uint32_t ks2;
int index = (int)(long)d;
int index = (int)(long)dd;
int tnum = NUM_BUILD_THREADS;
/* set random state */
@ -334,7 +334,7 @@ void *buildtable(void *d) {
// make 'table/' (unsorted) and 'sorted/' dir structures
void makedirs() {
static void makedirs(void) {
char path[32];
int i;
@ -368,7 +368,7 @@ static int datacmp(const void *p1, const void *p2, void *dummy) {
return memcmp(d_1, d_2, DATASIZE);
}
void *sorttable(void *d) {
static void *sorttable(void *dd) {
int i, j;
int fdin;
int fdout;
@ -378,7 +378,7 @@ void *sorttable(void *d) {
struct stat filestat;
unsigned char *table = NULL;
uint64_t numentries = 0;
int index = (int)(long)d;
int index = (int)(long)dd;
int space = 0x100 / NUM_SORT_THREADS;
// create table - 50MB should be enough

View file

@ -5,7 +5,7 @@
#include "ht2crackutils.h"
int makerandom(char *hex, unsigned int len, int fd) {
static int makerandom(char *hex, unsigned int len, int fd) {
unsigned char raw[32];
int i;
@ -43,7 +43,7 @@ int main(int argc, char *argv[]) {
int urandomfd;
if (argc < 2) {
printf("ht2crack2gentest number\n");
printf("%s number\n", argv[0]);
exit(1);
}

View file

@ -23,7 +23,7 @@ static int datacmp(const void *p1, const void *p2) {
return memcmp(d1, d2, DATASIZE - 6);
}
int loadrngdata(struct rngdata *r, char *file) {
static int loadrngdata(struct rngdata *r, char *file) {
int fd;
int i, j;
int nibble;
@ -90,7 +90,7 @@ int loadrngdata(struct rngdata *r, char *file) {
return 1;
}
int makecand(unsigned char *c, struct rngdata *r, int bitoffset) {
static int makecand(unsigned char *c, struct rngdata *r, int bitoffset) {
int bytenum;
int bitnum;
int i;
@ -116,7 +116,7 @@ int makecand(unsigned char *c, struct rngdata *r, int bitoffset) {
// test the candidate against the next or previous rng data
int testcand(unsigned char *f, unsigned char *rt, int fwd) {
static int testcand(unsigned char *f, unsigned char *rt, int fwd) {
Hitag_State hstate;
int i;
uint32_t ks1;
@ -154,7 +154,7 @@ int testcand(unsigned char *f, unsigned char *rt, int fwd) {
}
}
int searchcand(unsigned char *c, unsigned char *rt, int fwd, unsigned char *m, unsigned char *s) {
static int searchcand(unsigned char *c, unsigned char *rt, int fwd, unsigned char *m, unsigned char *s) {
int fd;
struct stat filestat;
char file[64];
@ -222,7 +222,7 @@ int searchcand(unsigned char *c, unsigned char *rt, int fwd, unsigned char *m, u
}
int findmatch(struct rngdata *r, unsigned char *outmatch, unsigned char *outstate, int *bitoffset) {
static int findmatch(struct rngdata *r, unsigned char *outmatch, unsigned char *outstate, int *bitoffset) {
int i;
int bitlen;
unsigned char cand[6];
@ -276,7 +276,7 @@ int findmatch(struct rngdata *r, unsigned char *outmatch, unsigned char *outstat
void rollbackrng(Hitag_State *hstate, unsigned char *s, int offset) {
static void rollbackrng(Hitag_State *hstate, unsigned char *s, int offset) {
int i;
if (!s) {
@ -305,7 +305,7 @@ void rollbackrng(Hitag_State *hstate, unsigned char *s, int offset) {
}
uint64_t recoverkey(Hitag_State *hstate, char *uidstr, char *nRstr) {
static uint64_t recoverkey(Hitag_State *hstate, char *uidstr, char *nRstr) {
uint64_t key;
uint64_t keyupper;
uint32_t uid;
@ -368,7 +368,7 @@ int main(int argc, char *argv[]) {
int i;
if (argc < 4) {
printf("ht2crack2search rngdatafile UID nR\n");
printf("%s rngdatafile UID nR\n", argv[0]);
exit(1);
}

View file

@ -1,6 +1,5 @@
ht2crack3
ht2test
ht2crack3test
ht2crack3.exe
ht2test.exe
ht2crack3test.exe

View file

@ -1,19 +1,21 @@
CFLAGS?=-Wall -Werror -O3
LIBS=
VPATH=../common
INC=-I ../common
MYSRCPATHS = ../common
MYSRCS = ht2crackutils.c hitagcrypto.c
MYINCLUDES =-I ../common
MYCFLAGS = -D_GNU_SOURCE
MYDEFS =
MYLDLIBS = -lpthread
all: ht2crack3.c ht2test.c hitagcrypto.o ht2crackutils.o
$(CC) $(CFLAGS) $(INC) -o ht2crack3 $< hitagcrypto.o ht2crackutils.o -lpthread $(LIBS)
$(CC) $(CFLAGS) $(INC) -o ht2test ht2test.c hitagcrypto.o ht2crackutils.o $(LIBS)
BINS = ht2crack3 ht2crack3test
INSTALLTOOLS = $(BINS)
ht2crackutils.o: ht2crackutils.c ht2crackutils.h
$(CC) $(CFLAGS) -c $<
include ../../../Makefile.host
hitagcrypto.o: hitagcrypto.c hitagcrypto.h
$(CC) $(CFLAGS) -c $<
# checking platform can be done only after Makefile.host
ifneq (,$(findstring MINGW,$(platform)))
# Mingw uses by default Microsoft printf, we want the GNU printf (e.g. for %z)
# and setting _ISOC99_SOURCE sets internally __USE_MINGW_ANSI_STDIO=1
CFLAGS += -D_ISOC99_SOURCE
endif
clean:
rm -rf *.o ht2crack3 ht2test
fresh: clean all
ht2crack3 : $(OBJDIR)/ht2crack3.o $(MYOBJS)
ht2crack3test : $(OBJDIR)/ht2crack3test.o $(MYOBJS)

View file

@ -31,9 +31,9 @@ Tests
If you happen to know the key and want to check that all your nR aR values
are valid (for high-powered demonstrations only, really) then you can use
the ht2test program to check them. It's otherwise massively pointless and a
the ht2crack3test program to check them. It's otherwise massively pointless and a
complete waste of space.
```
./ht2test NRARFILE KEY UID
./ht2crack3test NRARFILE KEY UID
```

View file

@ -65,7 +65,7 @@ static uint32_t hitag2_crypt(uint64_t s) {
// this function is a modification of the filter function f, based heavily
// on the hitag2_crypt function in Rfidler
int fnP(uint64_t klowery) {
static int fnP(uint64_t klowery) {
const uint32_t ht2_function4a = 0x2C79; // 0010 1100 0111 1001
const uint32_t ht2_function4b = 0x6671; // 0110 0110 0111 0001
const uint32_t ht2_function4p = 0xAE83; // 1010 1110 1000 0011
@ -84,7 +84,7 @@ int fnP(uint64_t klowery) {
}
// comparison function for sorting/searching Tklower entries
int Tk_cmp(const void *v1, const void *v2) {
static int Tk_cmp(const void *v1, const void *v2) {
const struct Tklower *Tk1 = (struct Tklower *)v1;
const struct Tklower *Tk2 = (struct Tklower *)v2;
@ -98,7 +98,7 @@ int Tk_cmp(const void *v1, const void *v2) {
}
// test for bad guesses of kmiddle
int is_kmiddle_badguess(uint64_t z, struct Tklower *Tk, int max, int aR0) {
static int is_kmiddle_badguess(uint64_t z, struct Tklower *Tk, int max, int aR0) {
struct Tklower *result, target;
@ -122,7 +122,7 @@ int is_kmiddle_badguess(uint64_t z, struct Tklower *Tk, int max, int aR0) {
}
// function to test if a partial key is valid
int testkey(uint64_t *out, uint64_t uid, uint64_t pkey, uint64_t nR, uint64_t aR) {
static int testkey(uint64_t *out, uint64_t uid, uint64_t pkey, uint64_t nR, uint64_t aR) {
uint64_t kupper;
uint64_t key;
Hitag_State hstate;
@ -178,7 +178,7 @@ int testkey(uint64_t *out, uint64_t uid, uint64_t pkey, uint64_t nR, uint64_t aR
// effectively work out candidates for the lower 34 bits of the key.
void *crack(void *d) {
static void *crack(void *d) {
struct threaddata *data = (struct threaddata *)d;
uint64_t uid;
struct nRaR *TnRaR;
@ -321,7 +321,7 @@ int main(int argc, char *argv[]) {
struct threaddata *tdata = NULL;
if (argc < 3) {
printf("ht2crack3 uid nRaRfile\n");
printf("%s uid nRaRfile\n", argv[0]);
exit(1);
}

View file

@ -19,7 +19,7 @@ int main(int argc, char *argv[]) {
char *uid;
if (argc < 4) {
printf("ht2test nRaRfile KEY UID\n");
printf("%s nRaRfile KEY UID\n", argv[0]);
exit(1);
}

View file

@ -1,18 +1,20 @@
CFLAGS?=-Wall -Werror -O3
LIBS=-lpthread
VPATH=../common
INC=-I ../common
MYSRCPATHS = ../common
MYSRCS = ht2crackutils.c hitagcrypto.c
MYINCLUDES =-I ../common
MYCFLAGS = -D_GNU_SOURCE
MYDEFS =
MYLDLIBS = -lpthread
all: ht2crack4.c hitagcrypto.o ht2crackutils.o
$(CC) $(CFLAGS) $(INC) -o ht2crack4 $< hitagcrypto.o ht2crackutils.o $(LIBS)
BINS = ht2crack4
INSTALLTOOLS = $(BINS)
hitagcrypto.o: hitagcrypto.c hitagcrypto.h
$(CC) $(CFLAGS) -c $<
include ../../../Makefile.host
ht2crackutils.o: ht2crackutils.c ht2crackutils.h
$(CC) $(CFLAGS) -c $<
# checking platform can be done only after Makefile.host
ifneq (,$(findstring MINGW,$(platform)))
# Mingw uses by default Microsoft printf, we want the GNU printf (e.g. for %z)
# and setting _ISOC99_SOURCE sets internally __USE_MINGW_ANSI_STDIO=1
CFLAGS += -D_ISOC99_SOURCE
endif
clean:
rm -rf *.o ht2crack4
fresh: clean all
ht2crack4 : $(OBJDIR)/ht2crack4.o $(MYOBJS)

View file

@ -93,7 +93,7 @@ uint64_t uid;
int maxtablesize = 800000;
uint64_t supplied_testkey = 0;
void usage() {
static void usage(void) {
printf("ht2crack4 - K Sheldrake, based on the work of Garcia et al\n\n");
printf("Cracks a HiTag2 key using a small number (4 to 16) of encrypted\n");
printf("nonce and challenge response pairs, using a fast correlation\n");
@ -147,6 +147,7 @@ double pfnc[][16] = {
/* hitag2_crypt works on the post-shifted form of the lfsr; this is the ref in rfidler code */
/*
static uint32_t hitag2_crypt(uint64_t s) {
uint32_t bitindex;
@ -158,9 +159,10 @@ static uint32_t hitag2_crypt(uint64_t s) {
return (ht2_function5c >> bitindex) & 1;
}
*/
/* ht2crypt works on the pre-shifted form of the lfsr; this is the ref in the paper */
uint64_t ht2crypt(uint64_t s) {
static uint64_t ht2crypt(uint64_t s) {
uint64_t bitindex;
bitindex = (ht2_function4a >> pickbits2_2(s, 2, 5)) & 1;
@ -174,12 +176,13 @@ uint64_t ht2crypt(uint64_t s) {
/* fnL is the feedback function for the reference code */
uint64_t fnL(uint64_t x) {
/*
static uint64_t fnL(uint64_t x) {
return (bitn(x, 0) ^ bitn(x, 2) ^ bitn(x, 3) ^ bitn(x, 6) ^ bitn(x, 7) ^ bitn(x, 8) ^
bitn(x, 16) ^ bitn(x, 22) ^ bitn(x, 23) ^ bitn(x, 26) ^ bitn(x, 30) ^ bitn(x, 41) ^
bitn(x, 42) ^ bitn(x, 43) ^ bitn(x, 46) ^ bitn(x, 47));
}
*/
/* packed_size is an array that maps the number of confirmed bits in a state to
* the number of relevant bits.
@ -193,7 +196,7 @@ unsigned int packed_size[] = { 0, 0, 0, 1, 2, 2, 3, 4, 4, 5, 5, 5, 5
/* f20 is the same as hitag2_crypt except it works on the packed version
* of the state where all 20 relevant bits are squashed together */
uint64_t f20(uint64_t y) {
static uint64_t f20(uint64_t y) {
uint64_t bitindex;
bitindex = (ht2_function4a >> (y & 0xf)) & 1;
@ -207,7 +210,7 @@ uint64_t f20(uint64_t y) {
/* packstate packs the relevant bits from LFSR state into 20 bits for pre-shifted lfsr */
uint64_t packstate(uint64_t s) {
static uint64_t packstate(uint64_t s) {
uint64_t packed;
packed = pickbits2_2(s, 2, 5);
@ -221,7 +224,7 @@ uint64_t packstate(uint64_t s) {
/* create_guess_table mallocs the tables */
void create_guess_table() {
static void create_guess_table(void) {
guesses = (struct guess *)malloc(sizeof(struct guess) * maxtablesize);
if (!guesses) {
printf("cannot malloc guess table\n");
@ -232,7 +235,7 @@ void create_guess_table() {
/* init the guess table by reading in the encrypted nR,aR values and
* setting the first 2^16 key guesses */
void init_guess_table(char *filename, char *uidstr) {
static void init_guess_table(char *filename, char *uidstr) {
unsigned int i, j;
FILE *fp;
char *buf = NULL;
@ -313,7 +316,7 @@ void init_guess_table(char *filename, char *uidstr) {
/* bit_score calculates the ratio of partial states that could generate
* the resulting bit b to all possible states
* size is the number of confirmed bits in the state */
double bit_score(uint64_t s, uint64_t size, uint64_t b) {
static double bit_score(uint64_t s, uint64_t size, uint64_t b) {
uint64_t packed;
uint64_t chopped;
unsigned int n;
@ -396,7 +399,7 @@ double bit_score(uint64_t s, uint64_t size, uint64_t b) {
* bit_scores together until no bits remain. bit_scores are
* multiplied by the number of relevant bits in the scored state
* to give weight to more complete states. */
double score(uint64_t s, unsigned int size, uint64_t ks, unsigned int kssize) {
static double score(uint64_t s, unsigned int size, uint64_t ks, unsigned int kssize) {
double sc, sc2;
if ((size == 1) || (kssize == 1)) {
@ -427,7 +430,7 @@ double score(uint64_t s, unsigned int size, uint64_t ks, unsigned int kssize) {
/* score_traces runs score for each encrypted nonce */
void score_traces(struct guess *g, unsigned int size) {
static void score_traces(struct guess *g, unsigned int size) {
uint64_t lfsr;
unsigned int i;
double sc;
@ -481,7 +484,7 @@ void score_all_traces(unsigned int size)
*/
/* score_some_traces runs score_traces for every key guess in a section of the table */
void *score_some_traces(void *data) {
static void *score_some_traces(void *data) {
unsigned int i;
struct thread_data *tdata = (struct thread_data *)data;
@ -494,7 +497,7 @@ void *score_some_traces(void *data) {
/* score_all_traces runs score_traces for every key guess in the table */
void score_all_traces(unsigned int size) {
static void score_all_traces(unsigned int size) {
pthread_t threads[NUM_THREADS];
void *status;
struct thread_data tdata[NUM_THREADS];
@ -535,7 +538,7 @@ void score_all_traces(unsigned int size) {
/* cmp_guess is the comparison function for qsorting the guess table */
int cmp_guess(const void *a, const void *b) {
static int cmp_guess(const void *a, const void *b) {
struct guess *a1 = (struct guess *)a;
struct guess *b1 = (struct guess *)b;
@ -552,7 +555,7 @@ int cmp_guess(const void *a, const void *b) {
/* expand all guesses in first half of (sorted) table by
* copying them into the second half and extending the copied
* ones with an extra 1, leaving the first half with an extra 0 */
void expand_guesses(unsigned int halfsize, unsigned int size) {
static void expand_guesses(unsigned int halfsize, unsigned int size) {
unsigned int i, j;
for (i = 0; i < halfsize; i++) {
@ -567,7 +570,7 @@ void expand_guesses(unsigned int halfsize, unsigned int size) {
/* checks if the supplied test key is still in the table, which
* is useful when testing different scoring methods */
void check_supplied_testkey(unsigned int size) {
static void check_supplied_testkey(unsigned int size) {
uint64_t partkey;
unsigned int i;
@ -586,7 +589,7 @@ void check_supplied_testkey(unsigned int size) {
/* execute_round scores the guesses, sorts them and expands the good half */
void execute_round(unsigned int size) {
static void execute_round(unsigned int size) {
unsigned int halfsize;
// score all the current guesses
@ -614,7 +617,7 @@ void execute_round(unsigned int size) {
/* crack is the main cracking algo; it executes the rounds */
void crack() {
static void crack(void) {
unsigned int i;
uint64_t revkey;
uint64_t foundkey;
@ -630,9 +633,9 @@ void crack() {
}
}
/* test function to make sure I know how the LFSR works */
void testkey(uint64_t key) {
/*
static void testkey(uint64_t key) {
uint64_t i;
uint64_t b0to31 = 0;
uint64_t ks = 0;
@ -689,10 +692,11 @@ void testkey(uint64_t key) {
printbin2(lfsr, 48);
printf("\n\n");
}
*/
/* test function to generate test data */
void gen_bitstreams_testks(struct guess *g, uint64_t key) {
/*
static void gen_bitstreams_testks(struct guess *g, uint64_t key) {
unsigned int i, j;
uint64_t nRxorkey, lfsr, ks;
@ -730,10 +734,11 @@ void gen_bitstreams_testks(struct guess *g, uint64_t key) {
}
}
}
*/
/* test function */
void test() {
/*
static void test(void) {
uint64_t lfsr;
uint64_t packed;
@ -751,10 +756,10 @@ void test() {
printf("test done\n");
}
*/
/* check_key tests the potential key against an encrypted nonce, ks pair */
int check_key(uint64_t key, uint64_t enc_nR, uint64_t ks) {
static int check_key(uint64_t key, uint64_t enc_nR, uint64_t ks) {
Hitag_State hstate;
uint64_t bits;
int i;

View file

@ -1,17 +1,20 @@
CFLAGS?=-Wall -Werror -O3
LIBS=-lpthread
VPATH=../common
INC=-I ../common
MYSRCPATHS = ../common
MYSRCS = ht2crackutils.c hitagcrypto.c
MYINCLUDES =-I ../common
MYCFLAGS =
MYDEFS =
MYLDLIBS = -lpthread
all: ht2crack5.c ht2crackutils.o hitagcrypto.o
$(CC) $(CFLAGS) $(INC) -O3 $< -o ht2crack5 ht2crackutils.o hitagcrypto.o $(LIBS)
BINS = ht2crack5
INSTALLTOOLS = $(BINS)
hitagcrypto.o: hitagcrypto.c hitagcrypto.h
$(CC) $(CFLAGS) -c $<
include ../../../Makefile.host
ht2crackutils.o: ht2crackutils.c ht2crackutils.h
$(CC) $(CFLAGS) -c $<
# checking platform can be done only after Makefile.host
ifneq (,$(findstring MINGW,$(platform)))
# Mingw uses by default Microsoft printf, we want the GNU printf (e.g. for %z)
# and setting _ISOC99_SOURCE sets internally __USE_MINGW_ANSI_STDIO=1
CFLAGS += -D_ISOC99_SOURCE
endif
clean:
rm -f *.o ht2crack5
fresh: clean all
ht2crack5 : $(OBJDIR)/ht2crack5.o $(MYOBJS)

View file

@ -55,7 +55,7 @@ bitslice_t bs_zeroes, bs_ones;
#define get_bit(n, word) ((word >> (n)) & 1)
#define get_vector_bit(slice, value) get_bit(slice&0x3f, value.bytes64[slice>>6])
const uint64_t expand(uint64_t mask, uint64_t value) {
static uint64_t expand(uint64_t mask, uint64_t value) {
uint64_t fill = 0;
for (uint64_t bit_index = 0; bit_index < 48; bit_index++) {
if (mask & 1) {
@ -67,7 +67,7 @@ const uint64_t expand(uint64_t mask, uint64_t value) {
return fill;
}
void bitslice(const uint64_t value, bitslice_t *restrict bitsliced_value, const size_t bit_len, bool reverse) {
static void bitslice(const uint64_t value, bitslice_t *restrict bitsliced_value, const size_t bit_len, bool reverse) {
size_t bit_idx;
for (bit_idx = 0; bit_idx < bit_len; bit_idx++) {
bool bit;
@ -84,7 +84,7 @@ void bitslice(const uint64_t value, bitslice_t *restrict bitsliced_value, const
}
}
const uint64_t unbitslice(const bitslice_t *restrict b, const uint8_t s, const uint8_t n) {
static uint64_t unbitslice(const bitslice_t *restrict b, const uint8_t s, const uint8_t n) {
uint64_t result = 0;
for (uint8_t i = 0; i < n; ++i) {
result <<= 1;
@ -118,7 +118,7 @@ bitslice_t initial_bitslices[48];
size_t filter_pos[20] = {4, 7, 9, 13, 16, 18, 22, 24, 27, 30, 32, 35, 45, 47 };
size_t thread_count = 8;
uint64_t layer_0_found;
void *find_state(void *thread_d);
static void *find_state(void *thread_d);
static void try_state(uint64_t s);
int main(int argc, char *argv[]) {
@ -201,7 +201,7 @@ int main(int argc, char *argv[]) {
exit(1);
}
void *find_state(void *thread_d) {
static void *find_state(void *thread_d) {
uint64_t thread = (uint64_t)thread_d;
for (uint64_t index = thread; index < layer_0_found; index += thread_count) {

View file

@ -1,23 +1,27 @@
CFLAGS?=-Wall
#INCLUDE=-I/usr/local/cuda-7.5/include
INCLUDE=-I/opt/nvidia/cuda/include
#Linux
#LIBS=-L/usr/local/cuda-7.5/lib64 -lOpenCL
LIBS=-L/opt/nvidia/cuda/lib64 -lOpenCL
#Mac
#LIBS=-framework OpenCL
VPATH=../common
INC=-I ../common
MYSRCPATHS = ../common
MYSRCS = ht2crackutils.c hitagcrypto.c
MYCFLAGS =
MYDEFS =
ifeq ($(platform),Darwin)
MYLDLIBS ?= -framework OpenCL
else
#MYINCLUDES ?=-I/usr/local/cuda-7.5/include
#MYINCLUDES ?=-I/opt/nvidia/cuda/include
#MYLDLIBS ?= -L/usr/local/cuda-7.5/lib64 -lOpenCL
MYLDLIBS ?= -L/opt/nvidia/cuda/lib64 -lOpenCL
endif
MYINCLUDES +=-I ../common
all: ht2crack5.c ht2crackutils.o hitagcrypto.o
$(CC) $(CFLAGS) $(INC) -o ht2crack5gpu $< ht2crackutils.o hitagcrypto.o $(LIBS) -lpthread
BINS = ht2crack5gpu
INSTALLTOOLS = $(BINS)
hitagcrypto.o: hitagcrypto.c hitagcrypto.h
$(CC) $(CFLAGS) $(INCLUDE) -c $<
include ../../../Makefile.host
ht2crackutils.o: ht2crackutils.c ht2crackutils.h
$(CC) $(CFLAGS) $(INCLUDE) -c $<
# checking platform can be done only after Makefile.host
ifneq (,$(findstring MINGW,$(platform)))
# Mingw uses by default Microsoft printf, we want the GNU printf (e.g. for %z)
# and setting _ISOC99_SOURCE sets internally __USE_MINGW_ANSI_STDIO=1
CFLAGS += -D_ISOC99_SOURCE
endif
clean:
rm -f *.o ht2crack5gpu
fresh: clean all
ht2crack5gpu : $(OBJDIR)/ht2crack5gpu.o $(MYOBJS)

View file

@ -65,7 +65,7 @@ bitslice_t bs_zeroes, bs_ones;
state[-2+i+42].value ^ state[-2+i+43].value ^ state[-2+i+46].value ^ state[-2+i+47].value);
#define get_bit(n, word) ((word >> (n)) & 1)
const uint64_t expand(uint64_t mask, uint64_t value) {
static uint64_t expand(uint64_t mask, uint64_t value) {
uint64_t fill = 0;
for (uint64_t bit_index = 0; bit_index < 48; bit_index++) {
if (mask & 1) {
@ -77,7 +77,7 @@ const uint64_t expand(uint64_t mask, uint64_t value) {
return fill;
}
void bitslice(const uint64_t value, bitslice_t *restrict bitsliced_value, const size_t bit_len, bool reverse) {
static void bitslice(const uint64_t value, bitslice_t *restrict bitsliced_value, const size_t bit_len, bool reverse) {
size_t bit_idx;
for (bit_idx = 0; bit_idx < bit_len; bit_idx++) {
bool bit;
@ -123,7 +123,7 @@ struct context {
};
void runKernel(struct context *ctx, uint32_t cand_base, uint64_t *matches, uint32_t *matches_found) {
static void runKernel(struct context *ctx, uint32_t cand_base, uint64_t *matches, uint32_t *matches_found) {
int err;
size_t global[2];

View file

@ -0,0 +1,118 @@
#!/usr/bin/env python3
"""
HITAG2 cipher
Implemented by Aram Verstegen
"""
import random
def i4(x, a, b, c, d):
return (((x >> a) & 1)*8)+((x >> b) & 1)*4+((x >> c) & 1)*2+((x >> d) & 1)
def f20_4(state):
return ((0x3c65 >> i4(state,34,43,44,46)) & 1)
def f20_3(state):
return (( 0xee5 >> i4(state,28,29,31,33)) & 1)
def f20_2(state):
return (( 0xee5 >> i4(state,17,21,23,26)) & 1)
def f20_1(state):
return (( 0xee5 >> i4(state, 8,12,14,15)) & 1)
def f20_0(state):
return ((0x3c65 >> i4(state, 2, 3, 5, 6)) & 1)
def f20_last(s0,s1,s2,s3,s4):
return (0xdd3929b >> ((s0 * 16)
+ (s1 * 8)
+ (s2 * 4)
+ (s3 * 2)
+ (s4 * 1))) & 1
def f20(state):
return f20_last(f20_0(state), f20_1(state), f20_2(state), f20_3(state), f20_4(state))
def lfsr_bs(state, i):
return (state[i+ 0] ^ state[i+ 2] ^ state[i+ 3] ^ state[i+ 6] ^
state[i+ 7] ^ state[i+ 8] ^ state[i+16] ^ state[i+22] ^
state[i+23] ^ state[i+26] ^ state[i+30] ^ state[i+41] ^
state[i+42] ^ state[i+43] ^ state[i+46] ^ state[i+47])
def f20a_bs(a,b,c,d):
return (~(((a|b)&c)^(a|d)^b)) # 6 ops
def f20b_bs(a,b,c,d):
return (~(((d|c)&(a^b))^(d|a|b))) # 7 ops
def f20c_bs(a,b,c,d,e):
return (~((((((c^e)|d)&a)^b)&(c^b))^(((d^e)|a)&((d^b)|c)))) # 13 ops
def filter_bs(state, i):
return (f20c_bs( f20a_bs(state[i+ 2],state[i+ 3],state[i+ 5],state[i+ 6]),
f20b_bs(state[i+ 8],state[i+12],state[i+14],state[i+15]),
f20b_bs(state[i+17],state[i+21],state[i+23],state[i+26]),
f20b_bs(state[i+28],state[i+29],state[i+31],state[i+33]),
f20a_bs(state[i+34],state[i+43],state[i+44],state[i+46])))
def unbitslice(s, n):
return int(''.join(map(str,map(int,map(bool,s[n:n+48])))[::-1]),2)
def hitag2_init(key, uid, nonce):
state = 0
for i in range(32, 48):
state = (state << 1) | ((key >> i) & 1)
for i in range(0, 32):
state = (state << 1) | ((uid >> i) & 1)
#print '%012x' % state
#print '%012x' % (int("{0:048b}".format(state)[::-1],2))
for i in range(0, 32):
nonce_bit = (f20(state) ^ ((nonce >> (31-i)) & 1))
#print nonce_bit
state = (state >> 1) | (((nonce_bit ^ (key >> (31-i))) & 1) << 47)
#print '%012x' % state
#print '%012x' % (int("{0:048b}".format(state)[::-1],2))
return state
def lfsr_feedback(state):
return (((state >> 0) ^ (state >> 2) ^ (state >> 3)
^ (state >> 6) ^ (state >> 7) ^ (state >> 8)
^ (state >> 16) ^ (state >> 22) ^ (state >> 23)
^ (state >> 26) ^ (state >> 30) ^ (state >> 41)
^ (state >> 42) ^ (state >> 43) ^ (state >> 46)
^ (state >> 47)) & 1)
def lfsr(state):
return (state >> 1) + (lfsr_feedback(state) << 47)
def lfsr_feedback_inv(state):
return (((state >> 47) ^ (state >> 1) ^ (state >> 2)
^ (state >> 5) ^ (state >> 6) ^ (state >> 7)
^ (state >> 15) ^ (state >> 21) ^ (state >> 22)
^ (state >> 25) ^ (state >> 29) ^ (state >> 40)
^ (state >> 41) ^ (state >> 42) ^ (state >> 45)
^ (state >> 46)) & 1)
def lfsr_inv(state):
return ((state << 1) + (lfsr_feedback_inv(state))) & ((1<<48)-1)
def hitag2(state, length=48):
c = 0
for i in range(0, length):
c = (c << 1) | f20(state)
#print '%012x' % state
#print '%012x' % (int("{0:048b}".format(state)[::-1],2))
state = lfsr(state)
return c
if __name__ == "__main__":
import sys
if len(sys.argv) == 4:
key = int(sys.argv[1], 16)
uid = int(sys.argv[2], 16)
n = int(sys.argv[3])
for i in range(n):
nonce = random.randrange(2**32)
state = hitag2_init(key, uid, nonce)
print('%08X %08X' % (nonce, hitag2(state, 32)^0xffffffff))
else:
print("Usage: python %s <key> <uid> <nr of nRaR to generate>" % sys.argv[0])

View file

@ -4,10 +4,12 @@ PM3PATH="$(dirname "$0")/.."
cd "$PM3PATH" || exit 1
SLOWTESTS=false
GPUTESTS=false
TESTALL=true
TESTMFKEY=false
TESTNONCE2KEY=false
TESTMFNONCEBRUTE=false
TESTHITAG2CRACK=false
TESTFPGACOMPRESS=false
TESTBOOTROM=false
TESTARMSRC=false
@ -32,6 +34,10 @@ Usage: $0 [--long] [--clientbin /path/to/proxmark3] [mfkey|nonce2key|mf_nonce_br
SLOWTESTS=true
shift
;;
--gpu)
GPUTESTS=true
shift
;;
--clientbin)
if [ -n "$2" ] && [ ${2:0:1} != "-" ]; then
CLIENTBIN=$2
@ -61,6 +67,11 @@ Usage: $0 [--long] [--clientbin /path/to/proxmark3] [mfkey|nonce2key|mf_nonce_br
TESTFPGACOMPRESS=true
shift
;;
hitag2crack)
TESTALL=false
TESTHITAG2CRACK=true
shift
;;
bootrom)
TESTALL=false
TESTBOOTROM=true
@ -122,24 +133,45 @@ function CheckFileExist() {
return 1
}
# title, command line, check result, repeat several times if failed, ignore if fail
# [slow] [gpu] [retry] [ignore] <title> <command_line> <check_result_regex>
# slow: test takes more than ~5s
# gpu: test requires GPU presence
# retry: test repeated up to 3 times in case of failure
# ignore: test failure is not fatal
function CheckExecute() {
if [ "$1" == "slow" ]; then
SLOWTEST=true
local SLOWTEST=true
shift
else
SLOWTEST=false
local SLOWTEST=false
fi
if [ "$4" ]; then
if [ "$1" == "gpu" ]; then
local GPUTEST=true
shift
else
local GPUTEST=false
fi
if [ "$1" == "retry" ]; then
local RETRY="1 2 3 e"
shift
else
local RETRY="e"
fi
if [ "$1" == "ignore" ]; then
local IGNOREFAILURE=true
shift
else
local IGNOREFAILURE=false
fi
if $SLOWTEST && ! $SLOWTESTS; then
echo -e "$1 ${C_YELLOW}[SKIPPED]${C_NC} (slow)\n"
return 0
fi
if $GPUTEST && ! $GPUTESTS; then
echo -e "$1 ${C_YELLOW}[SKIPPED]${C_NC} (gpu)\n"
return 0
fi
for I in $RETRY
do
@ -151,7 +183,7 @@ function CheckExecute() {
if [ ! $I == "e" ]; then echo "retry $I"; fi
done
if [ "$5" ]; then
if $IGNOREFAILURE; then
echo -e "$1 ${C_YELLOW}[Ignored]${C_NC}"
return 0
fi
@ -227,6 +259,54 @@ while true; do
if ! CheckFileExist "mf_nonce_brute exists" "$MFNONCEBRUTEBIN"; then break; fi
if ! CheckExecute slow "mf_nonce_brute test" "$MFNONCEBRUTEBIN 9c599b32 5a920d85 1011 98d76b77 d6c6e870 0000 ca7e0b63 0111 3e709c8a" "Key.*: \[ffffffffffff\]"; then break; fi
fi
# hitag2crack not yet part of "all"
# if $TESTALL || $TESTHITAG2CRACK; then
if $TESTHITAG2CRACK; then
echo -e "\n${C_BLUE}Testing ht2crack2:${C_NC} ${HT2CRACK2PATH:=./tools/hitag2crack/crack2/}"
if ! CheckFileExist "ht2crack2buildtable exists" "$HT2CRACK2PATH/ht2crack2buildtable"; then break; fi
if ! CheckFileExist "ht2crack2gentest exists" "$HT2CRACK2PATH/ht2crack2gentest"; then break; fi
if ! CheckFileExist "ht2crack2search exists" "$HT2CRACK2PATH/ht2crack2search"; then break; fi
# 1.5Tb tables are supposed to be absent, so it's just a fast check without real cracking
if ! CheckExecute "ht2crack2 quick test" "cd $HT2CRACK2PATH; ./ht2crack2gentest 1 && ./runalltests.sh; rm keystream*" "searching on bit"; then break; fi
echo -e "\n${C_BLUE}Testing ht2crack3:${C_NC} ${HT2CRACK3PATH:=./tools/hitag2crack/crack3/}"
if ! CheckFileExist "ht2crack3 exists" "$HT2CRACK3PATH/ht2crack3"; then break; fi
if ! CheckFileExist "ht2crack3test exists" "$HT2CRACK3PATH/ht2crack3test"; then break; fi
HT2CRACK3UID=AABBCCDD
# Test fast only for HT2CRACK3KEY in begin of keyspace!
HT2CRACK3KEY=000102030405
HT2CRACK3N=32
HT2CRACK3NRAR=hitag2_${HT2CRACK3UID}_nrar_${HT2CRACK3N}emul.txt
if ! CheckExecute "ht2crack3 gen testfile" "cd $HT2CRACK3PATH; python3 ../hitag2_gen_nRaR.py $HT2CRACK3KEY $HT2CRACK3UID $HT2CRACK3N > $HT2CRACK3NRAR && echo SUCCESS" "SUCCESS"; then break; fi
if ! CheckExecute "ht2crack3test test" "cd $HT2CRACK3PATH; ./ht2crack3test $HT2CRACK3NRAR $HT2CRACK3KEY $HT2CRACK3UID|grep -v SUCCESS||echo SUCCESS" "SUCCESS"; then break; fi
if ! CheckExecute "ht2crack3 test" "cd $HT2CRACK3PATH; ./ht2crack3 $HT2CRACK3UID $HT2CRACK3NRAR |egrep -v '(trying|partial)'" "key = $HT2CRACK3KEY"; then break; fi
if ! CheckExecute "ht2crack3 rm testfile" "cd $HT2CRACK3PATH; rm $HT2CRACK3NRAR && echo SUCCESS" "SUCCESS"; then break; fi
echo -e "\n${C_BLUE}Testing ht2crack4:${C_NC} ${HT2CRACK4PATH:=./tools/hitag2crack/crack4/}"
if ! CheckFileExist "ht2crack4 exists" "$HT2CRACK4PATH/ht2crack4"; then break; fi
HT2CRACK4UID=12345678
HT2CRACK4KEY=AABBCCDDEEFF
HT2CRACK4N=32
HT2CRACK4NRAR=hitag2_${HT2CRACK4UID}_nrar_${HT2CRACK4N}emul.txt
# The success is probabilistic: a fresh random nRaR file is required for each run
# Order of magnitude to crack it: ~15s -> tagged as "slow"
if ! CheckExecute slow retry ignore "ht2crack4 test" "cd $HT2CRACK4PATH; \
python3 ../hitag2_gen_nRaR.py $HT2CRACK4KEY $HT2CRACK4UID $HT2CRACK4N > $HT2CRACK4NRAR; \
./ht2crack4 -u $HT2CRACK4UID -n $HT2CRACK4NRAR -N 16 -t 500000 2>&1; \
rm $HT2CRACK4NRAR" "key = $HT2CRACK4KEY"; then break; fi
echo -e "\n${C_BLUE}Testing ht2crack5:${C_NC} ${HT2CRACK5PATH:=./tools/hitag2crack/crack5/}"
if ! CheckFileExist "ht2crack5 exists" "$HT2CRACK5PATH/ht2crack5"; then break; fi
echo -e "\n${C_BLUE}Testing ht2crack5gpu:${C_NC} ${HT2CRACK5GPUPATH:=./tools/hitag2crack/crack5gpu/}"
if ! CheckFileExist "ht2crack5gpu exists" "$HT2CRACK5GPUPATH/ht2crack5gpu"; then break; fi
HT2CRACK5GPUUID=12345678
HT2CRACK5GPUKEY=AABBCCDDEEFF
# The speed depends on the nRaR so we'll use two pairs known to work fast
HT2CRACK5GPUNRAR="B438220C 944FFD74 942C59E3 3D450B34"
# Order of magnitude to crack it: ~15s -> tagged as "slow"
if ! CheckExecute slow gpu "ht2crack5gpu test" "cd $HT2CRACK5GPUPATH; ./ht2crack5gpu $HT2CRACK5GPUUID $HT2CRACK5GPUNRAR" "Key: $HT2CRACK5GPUKEY"; then break; fi
fi
if $TESTALL || $TESTCLIENT; then
echo -e "\n${C_BLUE}Testing client:${C_NC} ${CLIENTBIN:=./client/proxmark3}"
if ! CheckFileExist "proxmark3 exists" "$CLIENTBIN"; then break; fi
@ -261,7 +341,7 @@ while true; do
echo -e "\n${C_BLUE}Testing HF:${C_NC}"
if ! CheckExecute "hf mf offline text" "$CLIENTBIN -c 'hf mf'" "at_enc"; then break; fi
if ! CheckExecute slow "hf mf hardnested long test" "$CLIENTBIN -c 'hf mf hardnested t 1 000000000000'" "found:" "repeat" "ignore"; then break; fi
if ! CheckExecute slow retry ignore "hf mf hardnested long test" "$CLIENTBIN -c 'hf mf hardnested t 1 000000000000'" "found:"; then break; fi
if ! CheckExecute slow "hf iclass long test" "$CLIENTBIN -c 'hf iclass loclass t l'" "verified ok"; then break; fi
if ! CheckExecute slow "emv long test" "$CLIENTBIN -c 'emv test -l'" "Test(s) \[ OK"; then break; fi
if ! $SLOWTESTS; then