From 6d33c0b784e33b344f31217423d97f9c528b9d37 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Fri, 22 May 2020 19:20:44 +0200 Subject: [PATCH] Bring hitag2crack tools in main Makefiles --- Makefile | 13 +- doc/md/Development/Maintainers.md | 4 + tools/hitag2crack/Makefile | 33 +++++ tools/hitag2crack/common/ht2crackutils.h | 5 + tools/hitag2crack/crack2/Makefile | 37 +++--- .../hitag2crack/crack2/ht2crack2buildtable.c | 50 ++++---- tools/hitag2crack/crack2/ht2crack2gentest.c | 4 +- tools/hitag2crack/crack2/ht2crack2search.c | 16 +-- tools/hitag2crack/crack3/.gitignore | 5 +- tools/hitag2crack/crack3/Makefile | 32 ++--- tools/hitag2crack/crack3/README.md | 4 +- tools/hitag2crack/crack3/ht2crack3.c | 12 +- .../crack3/{ht2test.c => ht2crack3test.c} | 2 +- tools/hitag2crack/crack4/Makefile | 30 ++--- tools/hitag2crack/crack4/ht2crack4.c | 57 +++++---- tools/hitag2crack/crack5/Makefile | 29 +++-- tools/hitag2crack/crack5/ht2crack5.c | 10 +- tools/hitag2crack/crack5gpu/Makefile | 42 ++++--- .../crack5gpu/{ht2crack5.c => ht2crack5gpu.c} | 6 +- tools/hitag2crack/hitag2_gen_nRaR.py | 118 ++++++++++++++++++ tools/pm3_tests.sh | 92 +++++++++++++- 21 files changed, 433 insertions(+), 168 deletions(-) create mode 100644 tools/hitag2crack/Makefile rename tools/hitag2crack/crack3/{ht2test.c => ht2crack3test.c} (96%) rename tools/hitag2crack/crack5gpu/{ht2crack5.c => ht2crack5gpu.c} (98%) create mode 100755 tools/hitag2crack/hitag2_gen_nRaR.py diff --git a/Makefile b/Makefile index d111d01fc..f7a434d3b 100644 --- a/Makefile +++ b/Makefile @@ -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 diff --git a/doc/md/Development/Maintainers.md b/doc/md/Development/Maintainers.md index af36dbbe2..09cddede7 100644 --- a/doc/md/Development/Maintainers.md +++ b/doc/md/Development/Maintainers.md @@ -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: diff --git a/tools/hitag2crack/Makefile b/tools/hitag2crack/Makefile new file mode 100644 index 000000000..c36d18b30 --- /dev/null +++ b/tools/hitag2crack/Makefile @@ -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 diff --git a/tools/hitag2crack/common/ht2crackutils.h b/tools/hitag2crack/common/ht2crackutils.h index 41c3a07c2..16f4fab5b 100644 --- a/tools/hitag2crack/common/ht2crackutils.h +++ b/tools/hitag2crack/common/ht2crackutils.h @@ -1,3 +1,6 @@ +#ifndef HT2CRACKUTILS_H +#define HT2CRACKUTILS_H + #include #include #include @@ -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 */ diff --git a/tools/hitag2crack/crack2/Makefile b/tools/hitag2crack/crack2/Makefile index 4794d6ec4..e8dbc4bac 100644 --- a/tools/hitag2crack/crack2/Makefile +++ b/tools/hitag2crack/crack2/Makefile @@ -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) diff --git a/tools/hitag2crack/crack2/ht2crack2buildtable.c b/tools/hitag2crack/crack2/ht2crack2buildtable.c index 8bf67a8ac..c45768998 100644 --- a/tools/hitag2crack/crack2/ht2crack2buildtable.c +++ b/tools/hitag2crack/crack2/ht2crack2buildtable.c @@ -4,7 +4,7 @@ */ #include "ht2crackutils.h" - +#include // 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 diff --git a/tools/hitag2crack/crack2/ht2crack2gentest.c b/tools/hitag2crack/crack2/ht2crack2gentest.c index 0f255a5b6..cc8d1e94e 100644 --- a/tools/hitag2crack/crack2/ht2crack2gentest.c +++ b/tools/hitag2crack/crack2/ht2crack2gentest.c @@ -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); } diff --git a/tools/hitag2crack/crack2/ht2crack2search.c b/tools/hitag2crack/crack2/ht2crack2search.c index 16a2e00b8..d339f878f 100644 --- a/tools/hitag2crack/crack2/ht2crack2search.c +++ b/tools/hitag2crack/crack2/ht2crack2search.c @@ -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); } diff --git a/tools/hitag2crack/crack3/.gitignore b/tools/hitag2crack/crack3/.gitignore index c993f2fe3..adf433d08 100644 --- a/tools/hitag2crack/crack3/.gitignore +++ b/tools/hitag2crack/crack3/.gitignore @@ -1,6 +1,5 @@ ht2crack3 -ht2test +ht2crack3test ht2crack3.exe -ht2test.exe - +ht2crack3test.exe diff --git a/tools/hitag2crack/crack3/Makefile b/tools/hitag2crack/crack3/Makefile index 318b5db78..010b6151c 100644 --- a/tools/hitag2crack/crack3/Makefile +++ b/tools/hitag2crack/crack3/Makefile @@ -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) diff --git a/tools/hitag2crack/crack3/README.md b/tools/hitag2crack/crack3/README.md index 57d5d2aa8..955775a62 100644 --- a/tools/hitag2crack/crack3/README.md +++ b/tools/hitag2crack/crack3/README.md @@ -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 ``` diff --git a/tools/hitag2crack/crack3/ht2crack3.c b/tools/hitag2crack/crack3/ht2crack3.c index 4f481fbf7..b54c7b000 100644 --- a/tools/hitag2crack/crack3/ht2crack3.c +++ b/tools/hitag2crack/crack3/ht2crack3.c @@ -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); } diff --git a/tools/hitag2crack/crack3/ht2test.c b/tools/hitag2crack/crack3/ht2crack3test.c similarity index 96% rename from tools/hitag2crack/crack3/ht2test.c rename to tools/hitag2crack/crack3/ht2crack3test.c index 53d47cfca..8d48cc914 100644 --- a/tools/hitag2crack/crack3/ht2test.c +++ b/tools/hitag2crack/crack3/ht2crack3test.c @@ -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); } diff --git a/tools/hitag2crack/crack4/Makefile b/tools/hitag2crack/crack4/Makefile index b560577bd..1c7298840 100644 --- a/tools/hitag2crack/crack4/Makefile +++ b/tools/hitag2crack/crack4/Makefile @@ -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) diff --git a/tools/hitag2crack/crack4/ht2crack4.c b/tools/hitag2crack/crack4/ht2crack4.c index 4c923737f..e630a956f 100644 --- a/tools/hitag2crack/crack4/ht2crack4.c +++ b/tools/hitag2crack/crack4/ht2crack4.c @@ -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; diff --git a/tools/hitag2crack/crack5/Makefile b/tools/hitag2crack/crack5/Makefile index 9d19b63ee..8fc46e838 100644 --- a/tools/hitag2crack/crack5/Makefile +++ b/tools/hitag2crack/crack5/Makefile @@ -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) diff --git a/tools/hitag2crack/crack5/ht2crack5.c b/tools/hitag2crack/crack5/ht2crack5.c index d07d03b64..a92afc854 100644 --- a/tools/hitag2crack/crack5/ht2crack5.c +++ b/tools/hitag2crack/crack5/ht2crack5.c @@ -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) { diff --git a/tools/hitag2crack/crack5gpu/Makefile b/tools/hitag2crack/crack5gpu/Makefile index b88fa00e8..57e44641f 100644 --- a/tools/hitag2crack/crack5gpu/Makefile +++ b/tools/hitag2crack/crack5gpu/Makefile @@ -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) diff --git a/tools/hitag2crack/crack5gpu/ht2crack5.c b/tools/hitag2crack/crack5gpu/ht2crack5gpu.c similarity index 98% rename from tools/hitag2crack/crack5gpu/ht2crack5.c rename to tools/hitag2crack/crack5gpu/ht2crack5gpu.c index cfacecc98..8cb720540 100644 --- a/tools/hitag2crack/crack5gpu/ht2crack5.c +++ b/tools/hitag2crack/crack5gpu/ht2crack5gpu.c @@ -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]; diff --git a/tools/hitag2crack/hitag2_gen_nRaR.py b/tools/hitag2crack/hitag2_gen_nRaR.py new file mode 100755 index 000000000..14f48a26d --- /dev/null +++ b/tools/hitag2crack/hitag2_gen_nRaR.py @@ -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 " % sys.argv[0]) diff --git a/tools/pm3_tests.sh b/tools/pm3_tests.sh index 8aaf82d58..89850e8bd 100755 --- a/tools/pm3_tests.sh +++ b/tools/pm3_tests.sh @@ -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] <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