Merge remote-tracking branch 'upstream/master' into git-attribute

This commit is contained in:
vratiskol 2019-03-27 23:30:36 +01:00
commit 14e4364734
221 changed files with 3391 additions and 3523 deletions

1
.gitignore vendored
View file

@ -2,6 +2,7 @@
# don't push these files to the repository # don't push these files to the repository
.history .history
.bash_history
*.log *.log
*.eml *.eml
*.o *.o

View file

@ -3,6 +3,47 @@ All notable changes to this project will be documented in this file.
This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log...
## [unreleased][unreleased] ## [unreleased][unreleased]
- Add - dictionary key file for MFU. (not in use at the moment) (@mazodude)
- Change 'lf fdx demod - better biphase maxerrors. (@MalteHillmann)
- Change 'hf mf sim' - now works better against android (@mceloff)
- Fix 'lf t55xx brute' - now works after aquiredata adaptations (@iceman)
- Fix 'lf t55xx chk' - now works after aquiredata adaptations (@iceman)
- Fix 'lf t55xx recoverpwd' - now works after aquiredata adaptations (@iceman)
- Fix 'data detect p' - reverted bad clock detection (@iceman)
- Change 'data detect a' - better clock detection (@iceman)
- Add 'hf 14a info' - now detects some magic card Gen2 (@iceman)
- Removed 'LCD' code in armsrc compilation (@iceman)
- Change - Generic fixes of codestyle (@doegox) (@iceman)
- Change 'lf indala demod' - refactoring (@iceman)
- Change - handling fault bit markers (7) and partial nibbles in hex printing (@doegox)
- Change - printing of fault bit markers (7) using a dot (@doegox)
- Change 'sc upgrade' - firmware file integrity check (@piwi)
- Fix 'data rawdemod am' - last bit was missing (@doegox)
- Fix 'hf 15 dump f' - also selects tag first (@iceman)
- Fix 'hf iclass clone' - missing fileclose (@iceman)
- Add 'trace list hitag' - old hitag annotations now use the new trace (@iceman)
- Change 'lf hitag sim' - loads bin/eml/json (@iceman)
- Change 'lf hitag reader 21' - saves in bin/eml/json (@iceman)
- Change 'lf hitag' - refactoring (@iceman)
- Change 'lf hitag' - refactoring (@piwi)
- Fix 'lf hitag' - generic fix for missing clock init (@piwi)
- Fix fsk sim operations on deviceside - avoid division by zero (@doegox)
- Fix 'hf mf fchk' - condition always false (@doegox)
- Fix 'lf t55xx recoverpw' - shift as u32 (@doegox)
- Fix 'lf ti demod' - shift as u32 (@doegox)
- Fix 'lf ti read' - shift as u32 (@doegox)
- Fix 'lf t55xx chk' - condition always false (@doegox)
- Change 'lf sim' - ledcontrol refactoring (@doegox)
- Fix 'hf mf nack' - signedness bug (@doegox)
- Fix 'hf epa cnonce' - check return value (@doegox)
- Fix 'lf hitag write' - condition always true (@doegox)
- Fix 'mem write' - added extra check (@doegox)
- Fix 'iso15693' - bad string cpy (@doegox)
- Fix 'make style' - EOF LF support (@doegox)
- Add 'hf 14b raw' - added -t for timeout (@iceman)
- Rename 'lf hitag snoop' - renamed to 'lf hitag sniff' (@iceman)
- Rename 'lf snoop' - renamed to 'lf sniff' (@iceman)
- Rename 'hf snoop' - renamed to 'hf sniff' (@iceman)
- Fix 'hf mfp wrbl' - more blocks available (@merlokk) - Fix 'hf mfp wrbl' - more blocks available (@merlokk)
- Add 'make platform' - compile for non-rdv4 devices made simpler (@doegox) - Add 'make platform' - compile for non-rdv4 devices made simpler (@doegox)
- Change Makefiles optimizations when recompiling (@doegox) - Change Makefiles optimizations when recompiling (@doegox)

View file

@ -6,33 +6,21 @@ so we don't have clear guidelines on how to place new code just yet. However,
please don't make things worse. please don't make things worse.
However, we have established a set of coding style guidelines in order to However, we have established a set of coding style guidelines in order to
clean up the code consistently and keep it consistent in the future. Use common clean up the code consistently and keep it consistent in the future.
sense and good taste. If breaking a rule leads to cleaner code, you can do so, Look around and respect the same style.
but laziness is not an excuse. Helper script to get some uniformity in the style:
$ make style
It makes use of "astyle" so be sure to install it first.
=== INDENTATION === === INDENTATION ===
Use tabs for indentation, but use spaces for alignment: Don't use tabs, editors are messing them up too easily.
Increment unit is four spaces.
if (foo(this, that, there) If you use "make style", this will be done for you.
&& bar == baz)
{
dostuff();
}
Notice it's like this (T___ for tab, S for space, for a 4-char tab setting):
T___if (foo(this, that, there)
T___SSSS&& bar == baz)
Another example:
#define THIS 0x10
#define THAT_THING 0x20
#define SOMETHING_ELSE 0x80
These should look good no matter what your editor's tab setting is, so go nuts
and pick whatever you like best.
=== WIDTH === === WIDTH ===
@ -65,7 +53,7 @@ use microsoft-style DWORD and the like, we're getting rid of those. Avoid char
for buffers, uint8_t is more obvious when you're not working with strings. Use for buffers, uint8_t is more obvious when you're not working with strings. Use
'const' where things are const. Try to use size_t for sizes. 'const' where things are const. Try to use size_t for sizes.
Pointers are: Pointers and reference operators are attached to the variable name:
void *ptr; void *ptr;
not: not:
void* ptr; void* ptr;
@ -73,12 +61,16 @@ otherwise you're tempted to write:
void* in, out; void* in, out;
and you'll fail. and you'll fail.
"make style" will take care of pointers & reference operators.
=== EXPRESSIONS === === EXPRESSIONS ===
In general, use whitespace around binary operators - no unspaced blobs of an In general, use whitespace around binary operators - no unspaced blobs of an
expression. This rule may be broken if it makes things clearer. For example, expression. "make style" will take care of whitespaces around operators.
if (5*a < b && some_bool_var) For example,
if (5 * a < b && some_bool_var)
but not but not
@ -90,24 +82,14 @@ anyway.
=== IF / FOR / WHILE / etc. === === IF / FOR / WHILE / etc. ===
Put the opening brace on the same line, with a space before it. Exception: if Put the opening brace on the same line, with a space before it.
the if/for/while condition/whatever are split over several lines, it might be
more appealing to put the opening brace on its own line, so use your own
judgement there:
if (foo(this, that, there)
&& bar == baz)
{
dostuff();
}
If you do split the condition, put the binary operators that join the lines at
the beginning of the following lines (as above), not at the end of the prior
lines.
There should be a space between the construct name (if/for/whatever) and the There should be a space between the construct name (if/for/whatever) and the
opening parenthesis, and there should be a space between the closing parenthesis opening parenthesis, and there should be a space between the closing parenthesis
and the opening brace. and the opening brace, and no space between parenthesis and expression.
"make style" will take care of all that.
If you do split the condition, put the binary operators that join the lines at
the beginning of the following lines, not at the end of the prior lines.
For generic for() iterator variables, declare them in-line: For generic for() iterator variables, declare them in-line:
@ -127,33 +109,25 @@ if/else should be laid out as follows:
... ...
} }
or You can skip braces around 1 line statements but don't mix braces vs. no braces.
if (foo)
...
else if (bar)
...
else
...
Don't mix braces vs. no braces. If any of your bodies are > 1 line, put braces
around them all.
=== FUNCTIONS === === FUNCTIONS ===
Functions with no arguments are declared as f(void), not f(). Put the return Put the return type on the same line.
type on the same line. Use static for functions that aren't exported, and put Put a space after a comma in argument lists.
exported functions in a header file (one header file per source file with Open the brace after the declaration (after a space).
exported functions usually, no huge headers with all functions). Put a space "make style" will take care of all that.
after a comma in argument lists.
void foo(int a_thing, int something_else) void foo(int a_thing, int something_else) {
{
... ...
} }
void baz(void) Functions with no arguments are declared as f(void), not f().
{ Use static for functions that aren't exported, and put exported functions
in a header file (one header file per source file with exported functions
usually, no huge headers with all functions).
void baz(void) {
foo(bluh, blah); foo(bluh, blah);
} }
@ -161,11 +135,10 @@ Function names should be separated_with_underscores(), except for standard
functions (memcpy, etc.). It may make sense to break this rule for very common, functions (memcpy, etc.). It may make sense to break this rule for very common,
generic functions that look like library functions (e.g. dprintf()). generic functions that look like library functions (e.g. dprintf()).
Don't use single-character arguments. Exception: very short functions with one Don't use single-character arguments.
argument that's really obvious: Exception: very short functions with one argument that's really obvious:
static int ascii(char c) static int ascii(char c) {
{
if (c < 0x20 || c >= 0x7f) if (c < 0x20 || c >= 0x7f)
return '.'; return '.';
else else
@ -174,8 +147,7 @@ static int ascii(char c)
vs. vs.
static void hexdump(void *buf, size_t len) static void hexdump(void *buf, size_t len) {
{
... ...
} }
@ -207,8 +179,10 @@ switch(bar) {
break; break;
} }
If you fall through into another case, add an explicit comment; otherwise, it "make style" will take care of the indentation.
can look confusing.
If you fall through into another case, add an explicit comment;
otherwise, it can look confusing.
If your switch() is too long or has too many cases, it should be cleaned up. If your switch() is too long or has too many cases, it should be cleaned up.
Split off the cases into functions, break the switch() into parent and children Split off the cases into functions, break the switch() into parent and children
@ -219,7 +193,7 @@ If you need local scope variables for a case, you can add braces:
switch(bar) { switch(bar) {
case OPTION_A: { case OPTION_A: {
int baz = 5*bar; int baz = 5 * bar;
do_stuff(baz); do_stuff(baz);
break; break;
} }
@ -266,7 +240,7 @@ License/description header first:
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
If you modify a file in any non-trivial way (add code, etc.), add your copyright If you modify a file in any non-trivial way (add code, etc.), add your copyright
to the top. to the top with the current year.
=== HEADER FILES === === HEADER FILES ===
@ -284,8 +258,7 @@ you shouldn't use it (same for _FOOBAR_H).
=== WHITESPACE === === WHITESPACE ===
Avoid trailing whitespace (no line should end in tab or space). People forget Avoid trailing whitespace (no line should end in tab or space).
this all the time if their editor doesn't handle it, but don't be surprised if
you see someone fixing it from time to time.
Keep a newline (blank line) at the end of each file. Keep a newline (blank line) at the end of each file.
"make style" will take care of both.

View file

@ -56,22 +56,40 @@ recovery/%: FORCE
$(MAKE) -C recovery $(patsubst recovery/%,%,$@) $(MAKE) -C recovery $(patsubst recovery/%,%,$@)
FORCE: # Dummy target to force remake in the subdirectories, even if files exist (this Makefile doesn't know about the prerequisites) FORCE: # Dummy target to force remake in the subdirectories, even if files exist (this Makefile doesn't know about the prerequisites)
.PHONY: all clean help _test flash-bootrom flash-os flash-all style FORCE .PHONY: all clean help _test bootrom flash-bootrom os flash-os flash-all recovery client mfkey nounce2key style FORCE
help: help:
@echo Multi-OS Makefile, you are running on $(DETECTED_OS) @echo "Multi-OS Makefile"
@echo Possible targets: @echo
@echo + all - Make bootrom, armsrc and the OS-specific host directory @echo "Possible targets:"
@echo + client - Make only the OS-specific host directory @echo "+ all - Make all targets: bootrom, armsrc and OS-specific host tools"
@echo + flash-bootrom - Make bootrom and flash it @echo "+ clean - Clean in all targets"
@echo + flash-os - Make armsrc and flash os \(includes fpga\) @echo
@echo + flash-all - Make bootrom and armsrc and flash bootrom and os image @echo "+ bootrom - Make bootrom"
@echo + mfkey - Make tools/mfkey @echo "+ os - Make armsrc \(includes fpga\)"
@echo + nounce2key - Make tools/nounce2key @echo "+ flash-bootrom - Make bootrom and flash it"
@echo + clean - Clean in bootrom, armsrc and the OS-specific host directory @echo "+ flash-os - Make armsrc and flash os image \(includes fpga\)"
@echo "+ flash-all - Make bootrom and armsrc and flash bootrom and os image"
@echo "+ recovery - Make bootrom and armsrc images for JTAG flashing"
@echo
@echo "+ client - Make only the OS-specific host client"
@echo "+ mfkey - Make tools/mfkey"
@echo "+ nounce2key - Make tools/nounce2key"
@echo
@echo "Possible platforms: try \"make PLATFORM=\" for more info, default is PM3RDV4"
client: client/all client: client/all
bootrom: bootrom/all
os: armsrc/all
recovery: recovery/all
mfkey: mfkey/all
nonce2key: nonce2key/all
flash-bootrom: bootrom/obj/bootrom.elf $(FLASH_TOOL) flash-bootrom: bootrom/obj/bootrom.elf $(FLASH_TOOL)
$(FLASH_TOOL) $(FLASH_PORT) -b $(subst /,$(PATHSEP),$<) $(FLASH_TOOL) $(FLASH_PORT) -b $(subst /,$(PATHSEP),$<)
@ -106,8 +124,14 @@ endif
print-%: ; @echo $* = $($*) print-%: ; @echo $* = $($*)
style: style:
# Make sure astyle is installed
@which astyle >/dev/null || ( echo "Please install 'astyle' package first" ; exit 1 ) @which astyle >/dev/null || ( echo "Please install 'astyle' package first" ; exit 1 )
find . \( -name "*.[ch]" -or -name "*.cpp" -or -name "*.lua" -or -name "Makefile" \) -exec perl -pi -e 's/[ \t\r]+$$//' {} \; # Remove spaces & tabs at EOL, add LF at EOF if needed on *.c, *.h, *.cpp. *.lua, *.py, *.pl, Makefile
find . \( -name "*.[ch]" -or -name "*.cpp" -or -name "*.lua" -or -name "*.py" -or -name "*.pl" -or -name "Makefile" \) \
-exec perl -pi -e 's/[ \t\r]+$$//' {} \; \
-exec sh -c "tail -c1 {} | xxd -p | tail -1 | grep -q -v 0a$$" \; \
-exec sh -c "echo >> {}" \;
# Apply astyle on *.c, *.h, *.cpp
find . \( -name "*.[ch]" -or -name "*.cpp" \) -exec astyle --formatted --mode=c --suffix=none \ find . \( -name "*.[ch]" -or -name "*.cpp" \) -exec astyle --formatted --mode=c --suffix=none \
--indent=spaces=4 --indent-switches --indent-preprocessor \ --indent=spaces=4 --indent-switches --indent-preprocessor \
--keep-one-line-blocks --max-instatement-indent=60 \ --keep-one-line-blocks --max-instatement-indent=60 \

View file

@ -286,7 +286,7 @@ You will need to run these commands to make sure your rdv4 is prepared
### Verify sim module firmware version ### Verify sim module firmware version
To make sure you got the latest sim module firmware. To make sure you got the latest sim module firmware.
_Lastest version is v3.10_ _Lastest version is v3.11_
pm3 --> hw status pm3 --> hw status
@ -298,7 +298,7 @@ Find version in the long output, look for these two lines
This version is obselete. The following command upgrades your device sim module firmware. This version is obselete. The following command upgrades your device sim module firmware.
Don't not turn of your device during the execution of this command. Don't not turn of your device during the execution of this command.
pm3 --> sc upgrade f ../tools/simmodule/SIM010.BIN pm3 --> sc upgrade f ../tools/simmodule/SIM011.BIN
You get the following output, this is a successful execution. You get the following output, this is a successful execution.

View file

@ -195,47 +195,6 @@ bool RAMFUNC LogTrace(const uint8_t *btBytes, uint16_t iLen, uint32_t timestamp_
return true; return true;
} }
int LogTraceHitag(const uint8_t *btBytes, int iBits, int iSamples, uint32_t dwParity, int readerToTag) {
/**
Todo, rewrite the logger to use the generic functionality instead. It should be noted, however,
that this logger takes number of bits as argument, not number of bytes.
**/
if (!tracing) return false;
uint8_t *trace = BigBuf_get_addr();
uint32_t iLen = nbytes(iBits);
// Return when trace is full
if (traceLen + sizeof(rsamples) + sizeof(dwParity) + sizeof(iBits) + iLen > BigBuf_max_traceLen()) return false;
//Hitag traces appear to use this traceformat:
// 32 bits timestamp (little endian,Highest Bit used as readerToTag flag)
// 32 bits parity
// 8 bits size (number of bits in the trace entry, not number of bytes)
// y Bytes data
rsamples += iSamples;
trace[traceLen++] = ((rsamples >> 0) & 0xff);
trace[traceLen++] = ((rsamples >> 8) & 0xff);
trace[traceLen++] = ((rsamples >> 16) & 0xff);
trace[traceLen++] = ((rsamples >> 24) & 0xff);
if (!readerToTag) {
trace[traceLen - 1] |= 0x80;
}
trace[traceLen++] = ((dwParity >> 0) & 0xff);
trace[traceLen++] = ((dwParity >> 8) & 0xff);
trace[traceLen++] = ((dwParity >> 16) & 0xff);
trace[traceLen++] = ((dwParity >> 24) & 0xff);
trace[traceLen++] = iBits;
memcpy(trace + traceLen, btBytes, iLen);
traceLen += iLen;
return true;
}
// Emulator memory // Emulator memory
uint8_t emlSet(uint8_t *data, uint32_t offset, uint32_t length) { uint8_t emlSet(uint8_t *data, uint32_t offset, uint32_t length) {
uint8_t *mem = BigBuf_get_EM_addr(); uint8_t *mem = BigBuf_get_EM_addr();

View file

@ -42,6 +42,5 @@ extern void set_tracing(bool enable);
extern void set_tracelen(uint32_t value); extern void set_tracelen(uint32_t value);
extern bool get_tracing(void); extern bool get_tracing(void);
extern bool RAMFUNC LogTrace(const uint8_t *btBytes, uint16_t iLen, uint32_t timestamp_start, uint32_t timestamp_end, uint8_t *parity, bool readerToTag); extern bool RAMFUNC LogTrace(const uint8_t *btBytes, uint16_t iLen, uint32_t timestamp_start, uint32_t timestamp_end, uint8_t *parity, bool readerToTag);
extern int LogTraceHitag(const uint8_t *btBytes, int iBits, int iSamples, uint32_t dwParity, int bReader);
extern uint8_t emlSet(uint8_t *data, uint32_t offset, uint32_t length); extern uint8_t emlSet(uint8_t *data, uint32_t offset, uint32_t length);
#endif /* __BIGBUF_H */ #endif /* __BIGBUF_H */

View file

@ -38,7 +38,7 @@ APP_CFLAGS = $(PLATFORM_DEFS) \
-DWITH_ISO14443a \ -DWITH_ISO14443a \
-DWITH_ICLASS \ -DWITH_ICLASS \
-DWITH_FELICA \ -DWITH_FELICA \
-DWITH_HFSNOOP \ -DWITH_HFSNIFF \
-DWITH_LF_SAMYRUN \ -DWITH_LF_SAMYRUN \
-fno-strict-aliasing -ffunction-sections -fdata-sections -fno-strict-aliasing -ffunction-sections -fdata-sections
@ -58,9 +58,7 @@ APP_CFLAGS = $(PLATFORM_DEFS) \
# -DWITH_HF_COLIN # -DWITH_HF_COLIN
# -DWITH_HF_BOG # -DWITH_HF_BOG
SRC_LF = lfops.c hitag2_crypto.c hitag2.c hitagS.c lfsampling.c pcf7931.c lfdemod.c
SRC_LCD = fonts.c LCD.c
SRC_LF = lfops.c hitag2.c hitagS.c lfsampling.c pcf7931.c lfdemod.c
SRC_ISO15693 = iso15693.c iso15693tools.c SRC_ISO15693 = iso15693.c iso15693tools.c
#SRC_ISO14443a = iso14443a.c mifareutil.c mifarecmd.c epa.c mifaresim.c #SRC_ISO14443a = iso14443a.c mifareutil.c mifarecmd.c epa.c mifaresim.c
SRC_ISO14443a = iso14443a.c mifareutil.c mifarecmd.c epa.c SRC_ISO14443a = iso14443a.c mifareutil.c mifarecmd.c epa.c
@ -91,6 +89,12 @@ else
SRC_FPC = SRC_FPC =
endif endif
ifneq (,$(findstring WITH_LCD,$(APP_CLAGS)))
SRC_LCD = fonts.c LCD.c
else
SRC_LCD =
endif
# Generic standalone Mode injection of source code # Generic standalone Mode injection of source code
SRC_STANDALONE = SRC_STANDALONE =
# WITH_LF_ICERUN # WITH_LF_ICERUN

View file

@ -207,7 +207,7 @@ void RunMod() {
cjcuid = 0; cjcuid = 0;
uint8_t sectorsCnt = (MF1KSZ / MF1KSZSIZE); uint8_t sectorsCnt = (MF1KSZ / MF1KSZSIZE);
uint64_t key64; // Defines current key uint64_t key64; // Defines current key
uint8_t *keyBlock = NULL; // Where the keys will be held in memory. uint8_t *keyBlock; // Where the keys will be held in memory.
/* VIGIK EXPIRED DUMP FOR STUDY /* VIGIK EXPIRED DUMP FOR STUDY
Sector 0 Sector 0
@ -807,8 +807,8 @@ void e_MifareECardLoad(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *dat
struct Crypto1State *pcs; struct Crypto1State *pcs;
pcs = &mpcs; pcs = &mpcs;
byte_t dataoutbuf[16]; uint8_t dataoutbuf[16];
byte_t dataoutbuf2[16]; uint8_t dataoutbuf2[16];
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
@ -1006,7 +1006,7 @@ int saMifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *data
uint8_t wipeC[] = {0x41}; uint8_t wipeC[] = {0x41};
// variables // variables
byte_t isOK = 0; uint8_t isOK = 0;
uint8_t d_block[18] = {0x00}; uint8_t d_block[18] = {0x00};
uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE]; uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];

View file

@ -59,7 +59,7 @@ static int saMifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_
uint8_t wipeC[] = {0x41}; uint8_t wipeC[] = {0x41};
// variables // variables
byte_t isOK = 0; uint8_t isOK = 0;
uint8_t d_block[18] = {0x00}; uint8_t d_block[18] = {0x00};
uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE]; uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];
@ -191,7 +191,6 @@ static int saMifareChkKeys(uint8_t blockNo, uint8_t keyType, bool clearTrace, ui
return -1; return -1;
} }
void RunMod() { void RunMod() {
StandAloneMode(); StandAloneMode();
Dbprintf(">> Matty mifare chk/dump/sim a.k.a MattyRun Started <<"); Dbprintf(">> Matty mifare chk/dump/sim a.k.a MattyRun Started <<");
@ -230,7 +229,7 @@ void RunMod() {
uint8_t sectorsCnt = (mifare_size / sectorSize); uint8_t sectorsCnt = (mifare_size / sectorSize);
uint8_t keyType = 2; // Keytype buffer uint8_t keyType = 2; // Keytype buffer
uint64_t key64; // Defines current key uint64_t key64; // Defines current key
uint8_t *keyBlock = NULL; // Where the keys will be held in memory. uint8_t *keyBlock; // Where the keys will be held in memory.
uint8_t stKeyBlock = 20; // Set the quantity of keys in the block. uint8_t stKeyBlock = 20; // Set the quantity of keys in the block.
uint8_t filled = 0; // Used to check if the memory was filled with success. uint8_t filled = 0; // Used to check if the memory was filled with success.
bool keyFound = false; bool keyFound = false;

View file

@ -164,7 +164,7 @@ void RunMod() {
Dbprintf("[=] Proxbrute - starting decrementing card number"); Dbprintf("[=] Proxbrute - starting decrementing card number");
while (cardnum >= 0) { while (cardnum > 0) {
// Needed for exiting from proxbrute when button is pressed // Needed for exiting from proxbrute when button is pressed
if (BUTTON_PRESS()) { if (BUTTON_PRESS()) {

View file

@ -23,6 +23,7 @@
#include "lfsampling.h" #include "lfsampling.h"
#include "BigBuf.h" #include "BigBuf.h"
#include "mifareutil.h" #include "mifareutil.h"
#include "hitag.h"
#define DEBUG 1 #define DEBUG 1
@ -650,8 +651,8 @@ void UsbPacketReceived(uint8_t *packet, int len) {
case CMD_MOD_THEN_ACQUIRE_RAW_ADC_SAMPLES_125K: case CMD_MOD_THEN_ACQUIRE_RAW_ADC_SAMPLES_125K:
ModThenAcquireRawAdcSamples125k(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); ModThenAcquireRawAdcSamples125k(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes);
break; break;
case CMD_LF_SNOOP_RAW_ADC_SAMPLES: { case CMD_LF_SNIFF_RAW_ADC_SAMPLES: {
uint32_t bits = SnoopLF(); uint32_t bits = SniffLF();
cmd_send(CMD_ACK, bits, 0, 0, 0, 0); cmd_send(CMD_ACK, bits, 0, 0, 0, 0);
break; break;
} }
@ -664,13 +665,13 @@ void UsbPacketReceived(uint8_t *packet, int len) {
CmdHIDsimTAG(c->arg[0], c->arg[1], 1); CmdHIDsimTAG(c->arg[0], c->arg[1], 1);
break; break;
case CMD_FSK_SIM_TAG: case CMD_FSK_SIM_TAG:
CmdFSKsimTAG(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); CmdFSKsimTAG(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes, 1);
break; break;
case CMD_ASK_SIM_TAG: case CMD_ASK_SIM_TAG:
CmdASKsimTag(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); CmdASKsimTag(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes, 1);
break; break;
case CMD_PSK_SIM_TAG: case CMD_PSK_SIM_TAG:
CmdPSKsimTag(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); CmdPSKsimTag(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes, 1);
break; break;
case CMD_HID_CLONE_TAG: case CMD_HID_CLONE_TAG:
CopyHIDtoT55x7(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes[0]); CopyHIDtoT55x7(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes[0]);
@ -707,7 +708,7 @@ void UsbPacketReceived(uint8_t *packet, int len) {
SimulateTagLowFrequencyBidir(c->arg[0], c->arg[1]); SimulateTagLowFrequencyBidir(c->arg[0], c->arg[1]);
break; break;
case CMD_INDALA_CLONE_TAG: case CMD_INDALA_CLONE_TAG:
CopyIndala64toT55x7(c->arg[0], c->arg[1]); CopyIndala64toT55x7(c->d.asDwords[0], c->d.asDwords[1]);
break; break;
case CMD_INDALA_CLONE_TAG_L: case CMD_INDALA_CLONE_TAG_L:
CopyIndala224toT55x7( CopyIndala224toT55x7(
@ -765,20 +766,20 @@ void UsbPacketReceived(uint8_t *packet, int len) {
#endif #endif
#ifdef WITH_HITAG #ifdef WITH_HITAG
case CMD_SNOOP_HITAG: // Eavesdrop Hitag tag, args = type case CMD_SNIFF_HITAG: // Eavesdrop Hitag tag, args = type
SnoopHitag(c->arg[0]); SniffHitag(c->arg[0]);
break; break;
case CMD_SIMULATE_HITAG: // Simulate Hitag tag, args = memory content case CMD_SIMULATE_HITAG: // Simulate Hitag tag, args = memory content
SimulateHitagTag((bool)c->arg[0], (byte_t *)c->d.asBytes); SimulateHitagTag((bool)c->arg[0], c->d.asBytes);
break; break;
case CMD_READER_HITAG: // Reader for Hitag tags, args = type and function case CMD_READER_HITAG: // Reader for Hitag tags, args = type and function
ReaderHitag((hitag_function)c->arg[0], (hitag_data *)c->d.asBytes); ReaderHitag((hitag_function)c->arg[0], (hitag_data *)c->d.asBytes);
break; break;
case CMD_SIMULATE_HITAG_S:// Simulate Hitag s tag, args = memory content case CMD_SIMULATE_HITAG_S:// Simulate Hitag s tag, args = memory content
SimulateHitagSTag((bool)c->arg[0], (byte_t *)c->d.asBytes); SimulateHitagSTag((bool)c->arg[0], c->d.asBytes);
break; break;
case CMD_TEST_HITAGS_TRACES:// Tests every challenge within the given file case CMD_TEST_HITAGS_TRACES:// Tests every challenge within the given file
check_challenges((bool)c->arg[0], (byte_t *)c->d.asBytes); check_challenges((bool)c->arg[0], c->d.asBytes);
break; break;
case CMD_READ_HITAG_S: //Reader for only Hitag S tags, args = key or challenge case CMD_READ_HITAG_S: //Reader for only Hitag S tags, args = key or challenge
ReadHitagS((hitag_function)c->arg[0], (hitag_data *)c->d.asBytes); ReadHitagS((hitag_function)c->arg[0], (hitag_data *)c->d.asBytes);
@ -786,7 +787,7 @@ void UsbPacketReceived(uint8_t *packet, int len) {
case CMD_WR_HITAG_S: //writer for Hitag tags args=data to write,page and key or challenge case CMD_WR_HITAG_S: //writer for Hitag tags args=data to write,page and key or challenge
if ((hitag_function)c->arg[0] < 10) { if ((hitag_function)c->arg[0] < 10) {
WritePageHitagS((hitag_function)c->arg[0], (hitag_data *)c->d.asBytes, c->arg[2]); WritePageHitagS((hitag_function)c->arg[0], (hitag_data *)c->d.asBytes, c->arg[2]);
} else if ((hitag_function)c->arg[0] >= 10) { } else {
WriterHitag((hitag_function)c->arg[0], (hitag_data *)c->d.asBytes, c->arg[2]); WriterHitag((hitag_function)c->arg[0], (hitag_data *)c->d.asBytes, c->arg[2]);
} }
break; break;
@ -843,7 +844,7 @@ void UsbPacketReceived(uint8_t *packet, int len) {
case CMD_READ_SRI_TAG: case CMD_READ_SRI_TAG:
ReadSTMemoryIso14443b(c->arg[0]); ReadSTMemoryIso14443b(c->arg[0]);
break; break;
case CMD_SNOOP_ISO_14443B: case CMD_SNIFF_ISO_14443B:
SniffIso14443b(); SniffIso14443b();
break; break;
case CMD_SIMULATE_TAG_ISO_14443B: case CMD_SIMULATE_TAG_ISO_14443B:
@ -862,7 +863,7 @@ void UsbPacketReceived(uint8_t *packet, int len) {
case CMD_FELICA_LITE_SIM: case CMD_FELICA_LITE_SIM:
felica_sim_lite(c->arg[0]); felica_sim_lite(c->arg[0]);
break; break;
case CMD_FELICA_SNOOP: case CMD_FELICA_SNIFF:
felica_sniff(c->arg[0], c->arg[1]); felica_sniff(c->arg[0], c->arg[1]);
break; break;
case CMD_FELICA_LITE_DUMP: case CMD_FELICA_LITE_DUMP:
@ -871,7 +872,7 @@ void UsbPacketReceived(uint8_t *packet, int len) {
#endif #endif
#ifdef WITH_ISO14443a #ifdef WITH_ISO14443a
case CMD_SNOOP_ISO_14443a: case CMD_SNIFF_ISO_14443a:
SniffIso14443a(c->arg[0]); SniffIso14443a(c->arg[0]);
break; break;
case CMD_READER_ISO_14443a: case CMD_READER_ISO_14443a:
@ -1003,7 +1004,7 @@ void UsbPacketReceived(uint8_t *packet, int len) {
#ifdef WITH_ICLASS #ifdef WITH_ICLASS
// Makes use of ISO14443a FPGA Firmware // Makes use of ISO14443a FPGA Firmware
case CMD_SNOOP_ICLASS: case CMD_SNIFF_ICLASS:
SniffIClass(); SniffIClass();
break; break;
case CMD_SIMULATE_TAG_ICLASS: case CMD_SIMULATE_TAG_ICLASS:
@ -1043,9 +1044,9 @@ void UsbPacketReceived(uint8_t *packet, int len) {
break; break;
#endif #endif
#ifdef WITH_HFSNOOP #ifdef WITH_HFSNIFF
case CMD_HF_SNIFFER: case CMD_HF_SNIFFER:
HfSnoop(c->arg[0], c->arg[1]); HfSniff(c->arg[0], c->arg[1]);
break; break;
#endif #endif
@ -1322,10 +1323,12 @@ void UsbPacketReceived(uint8_t *packet, int len) {
// first mem page // first mem page
res = Flash_WriteDataCont(startidx, data, first_len); res = Flash_WriteDataCont(startidx, data, first_len);
isok = (res == first_len) ? 1 : 0;
// second mem page // second mem page
res = Flash_WriteDataCont(startidx + first_len, data + first_len, len - first_len); res = Flash_WriteDataCont(startidx + first_len, data + first_len, len - first_len);
isok = (res == (len - first_len)) ? 1 : 0; isok &= (res == (len - first_len)) ? 1 : 0;
} else { } else {
res = Flash_WriteDataCont(startidx, data, len); res = Flash_WriteDataCont(startidx, data, len);
@ -1389,6 +1392,7 @@ void UsbPacketReceived(uint8_t *packet, int len) {
FlashStop(); FlashStop();
cmd_send(CMD_ACK, 1, 0, 0, 0, 0); cmd_send(CMD_ACK, 1, 0, 0, 0, 0);
BigBuf_free();
LED_B_OFF(); LED_B_OFF();
break; break;
} }

View file

@ -85,9 +85,9 @@ void SimulateTagLowFrequency(int period, int gap, int ledcontrol);
void SimulateTagLowFrequencyBidir(int divisor, int max_bitlen); void SimulateTagLowFrequencyBidir(int divisor, int max_bitlen);
void CmdHIDsimTAGEx(uint32_t hi, uint32_t lo, int ledcontrol, int numcycles); void CmdHIDsimTAGEx(uint32_t hi, uint32_t lo, int ledcontrol, int numcycles);
void CmdHIDsimTAG(uint32_t hi, uint32_t lo, int ledcontrol); void CmdHIDsimTAG(uint32_t hi, uint32_t lo, int ledcontrol);
void CmdFSKsimTAG(uint16_t arg1, uint16_t arg2, size_t size, uint8_t *BitStream); void CmdFSKsimTAG(uint16_t arg1, uint16_t arg2, size_t size, uint8_t *BitStream, int ledcontrol);
void CmdASKsimTag(uint16_t arg1, uint16_t arg2, size_t size, uint8_t *BitStream); void CmdASKsimTag(uint16_t arg1, uint16_t arg2, size_t size, uint8_t *BitStream, int ledcontrol);
void CmdPSKsimTag(uint16_t arg1, uint16_t arg2, size_t size, uint8_t *BitStream); void CmdPSKsimTag(uint16_t arg1, uint16_t arg2, size_t size, uint8_t *BitStream, int ledcontrol);
void CmdHIDdemodFSK(int findone, uint32_t *high, uint32_t *low, int ledcontrol); void CmdHIDdemodFSK(int findone, uint32_t *high, uint32_t *low, int ledcontrol);
void CmdAWIDdemodFSK(int findone, uint32_t *high, uint32_t *low, int ledcontrol); // Realtime demodulation mode for AWID26 void CmdAWIDdemodFSK(int findone, uint32_t *high, uint32_t *low, int ledcontrol); // Realtime demodulation mode for AWID26
void CmdEM410xdemod(int findone, uint32_t *high, uint64_t *low, int ledcontrol); void CmdEM410xdemod(int findone, uint32_t *high, uint64_t *low, int ledcontrol);
@ -222,28 +222,16 @@ void iClass_Dump(uint8_t blockno, uint8_t numblks);
void iClass_Clone(uint8_t startblock, uint8_t endblock, uint8_t *data); void iClass_Clone(uint8_t startblock, uint8_t endblock, uint8_t *data);
void iClass_ReadCheck(uint8_t blockNo, uint8_t keyType); void iClass_ReadCheck(uint8_t blockNo, uint8_t keyType);
// hitag2.h
void SnoopHitag(uint32_t type);
void SimulateHitagTag(bool tag_mem_supplied, byte_t *data);
void ReaderHitag(hitag_function htf, hitag_data *htd);
void WriterHitag(hitag_function htf, hitag_data *htd, int page);
//hitagS.h
void SimulateHitagSTag(bool tag_mem_supplied, byte_t *data);
void ReadHitagS(hitag_function htf, hitag_data *htd);
void WritePageHitagS(hitag_function htf, hitag_data *htd, int page);
void check_challenges(bool file_given, byte_t *data);
// cmd.h // cmd.h
uint8_t cmd_receive(UsbCommand *cmd); uint8_t cmd_receive(UsbCommand *cmd);
uint8_t cmd_send(uint64_t cmd, uint64_t arg0, uint64_t arg1, uint64_t arg2, void *data, size_t len); uint8_t cmd_send(uint64_t cmd, uint64_t arg0, uint64_t arg1, uint64_t arg2, void *data, size_t len);
// util.h // util.h
void HfSnoop(int, int); void HfSniff(int, int);
//felica.c //felica.c
extern void felica_sendraw(UsbCommand *c); extern void felica_sendraw(UsbCommand *c);
extern void felica_sniff(uint32_t samples, uint32_t triggers); extern void felica_sniff(uint32_t samplesToSkip, uint32_t triggersToSkip);
extern void felica_sim_lite(uint64_t uid); extern void felica_sim_lite(uint64_t uid);
extern void felica_dump_lite_s(); extern void felica_dump_lite_s();

View file

@ -313,7 +313,7 @@ void *mifare_cryto_postprocess_data(desfiretag_t tag, void *data, size_t *nbytes
case AS_LEGACY: case AS_LEGACY:
if (communication_settings & MAC_VERIFY) { if (communication_settings & MAC_VERIFY) {
*nbytes -= key_macing_length(key); *nbytes -= key_macing_length(key);
if (*nbytes <= 0) { if (*nbytes == 0) {
*nbytes = -1; *nbytes = -1;
res = NULL; res = NULL;
#ifdef WITH_DEBUG #ifdef WITH_DEBUG

View file

@ -305,6 +305,11 @@ void EPA_PACE_Collect_Nonce(UsbCommand *c) {
// initiate the PACE protocol // initiate the PACE protocol
// use the CAN for the password since that doesn't change // use the CAN for the password since that doesn't change
func_return = EPA_PACE_MSE_Set_AT(pace_version_info, 2); func_return = EPA_PACE_MSE_Set_AT(pace_version_info, 2);
// check if the command succeeded
if (func_return != 0) {
EPA_PACE_Collect_Nonce_Abort(4, func_return);
return;
}
// now get the nonce // now get the nonce
uint8_t nonce[256] = {0}; uint8_t nonce[256] = {0};
@ -312,7 +317,7 @@ void EPA_PACE_Collect_Nonce(UsbCommand *c) {
func_return = EPA_PACE_Get_Nonce(requested_size, nonce); func_return = EPA_PACE_Get_Nonce(requested_size, nonce);
// check if the command succeeded // check if the command succeeded
if (func_return < 0) { if (func_return < 0) {
EPA_PACE_Collect_Nonce_Abort(4, func_return); EPA_PACE_Collect_Nonce_Abort(5, func_return);
return; return;
} }

View file

@ -544,7 +544,7 @@ void felica_sniff(uint32_t samplesToSkip, uint32_t triggersToSkip) {
int remFrames = (samplesToSkip) ? samplesToSkip : 0; int remFrames = (samplesToSkip) ? samplesToSkip : 0;
Dbprintf("Snoop FelicaLiteS: Getting first %d frames, Skipping %d triggers.\n", samplesToSkip, triggersToSkip); Dbprintf("Sniff FelicaLiteS: Getting first %d frames, Skipping %d triggers.\n", samplesToSkip, triggersToSkip);
iso18092_setup(FPGA_HF_ISO18092_FLAG_NOMOD); iso18092_setup(FPGA_HF_ISO18092_FLAG_NOMOD);
@ -611,13 +611,13 @@ void felica_sniff(uint32_t samplesToSkip, uint32_t triggersToSkip) {
#define R_READBLK_LEN 0x21 #define R_READBLK_LEN 0x21
//simulate NFC Tag3 card - for now only poll response works //simulate NFC Tag3 card - for now only poll response works
// second half (4 bytes) of NDEF2 goes into nfcid2_0, first into nfcid2_1 // second half (4 bytes) of NDEF2 goes into nfcid2_0, first into nfcid2_1
void felica_sim_lite(uint64_t nfcid) { void felica_sim_lite(uint64_t uid) {
int i, curlen = 0; int i, curlen = 0;
uint8_t *curresp = 0; uint8_t *curresp = 0;
uint8_t ndef[8]; uint8_t ndef[8];
num_to_bytes(nfcid, 8, ndef); num_to_bytes(uid, 8, ndef);
//prepare our 3 responses... //prepare our 3 responses...
uint8_t resp_poll0[R_POLL0_LEN] = { 0xb2, 0x4d, 0x12, FELICA_POLL_ACK, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf1, 0x00, 0x00, 0x00, 0x01, 0x43, 0x00, 0xb3, 0x7f}; uint8_t resp_poll0[R_POLL0_LEN] = { 0xb2, 0x4d, 0x12, FELICA_POLL_ACK, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf1, 0x00, 0x00, 0x00, 0x01, 0x43, 0x00, 0xb3, 0x7f};

View file

@ -4,9 +4,9 @@
#include "util.h" #include "util.h"
#include "usb_cdc.h" // for usb_poll_validate_length #include "usb_cdc.h" // for usb_poll_validate_length
static void RAMFUNC optimizedSnoop(void); static void RAMFUNC optimizedSniff(void);
static void RAMFUNC optimizedSnoop(void) { static void RAMFUNC optimizedSniff(void) {
int n = BigBuf_max_traceLen() / sizeof(uint16_t); // take all memory int n = BigBuf_max_traceLen() / sizeof(uint16_t); // take all memory
uint16_t *dest = (uint16_t *)BigBuf_get_addr(); uint16_t *dest = (uint16_t *)BigBuf_get_addr();
@ -23,7 +23,7 @@ static void RAMFUNC optimizedSnoop(void) {
set_tracelen(BigBuf_max_traceLen()); set_tracelen(BigBuf_max_traceLen());
} }
void HfSnoop(int samplesToSkip, int triggersToSkip) { void HfSniff(int samplesToSkip, int triggersToSkip) {
BigBuf_free(); BigBuf_free();
BigBuf_Clear(); BigBuf_Clear();
@ -66,14 +66,14 @@ void HfSnoop(int samplesToSkip, int triggersToSkip) {
if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY))
waitcount--; waitcount--;
} }
optimizedSnoop(); optimizedSniff();
Dbprintf("Trigger kicked! Value: %d, Dumping Samples Hispeed now.", r); Dbprintf("Trigger kicked! Value: %d, Dumping Samples Hispeed now.", r);
} }
//Resetting Frame mode (First set in fpgaloader.c) //Resetting Frame mode (First set in fpgaloader.c)
AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(8) | AT91C_SSC_MSBF | SSC_FRAME_MODE_WORDS_PER_TRANSFER(0); AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(8) | AT91C_SSC_MSBF | SSC_FRAME_MODE_WORDS_PER_TRANSFER(0);
DbpString("HF Snoop end"); DbpString("HF Sniffing end");
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LED_D_OFF(); LED_D_OFF();
} }

View file

@ -3,46 +3,35 @@
// at your option, any later version. See the LICENSE.txt file for the text of // at your option, any later version. See the LICENSE.txt file for the text of
// the license. // the license.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Hitag2 emulation (preliminary test version) // Hitag2 emulation
// //
// (c) 2009 Henryk Plötz <henryk@ploetzli.ch> // (c) 2009 Henryk Plötz <henryk@ploetzli.ch>
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Hitag2 complete rewrite of the code // Hitag2 complete rewrite of the code
// - Fixed modulation/encoding issues // - Fixed modulation/encoding issues
// - Rewrote code for transponder emulation // - Rewrote code for transponder emulation
// - Added snooping of transponder communication // - Added sniffing of transponder communication
// - Added reader functionality // - Added reader functionality
// //
// (c) 2012 Roel Verdult // (c) 2012 Roel Verdult
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Piwi, 2019
// Iceman, 2019
#include "hitag2.h"
#include "hitag2_crypto.h"
#include "hitag.h"
#include "proxmark3.h" #include "proxmark3.h"
#include "apps.h" #include "apps.h"
#include "util.h" #include "util.h"
#include "hitag2.h"
#include "string.h" #include "string.h"
#include "BigBuf.h" #include "BigBuf.h"
static bool bQuiet;
static bool bCrypto; static bool bCrypto;
static bool bAuthenticating; static bool bAuthenticating;
static bool bPwd; static bool bPwd;
static bool bSuccessful; static bool bSuccessful;
struct hitag2_tag {
uint32_t uid;
enum {
TAG_STATE_RESET = 0x01, // Just powered up, awaiting GetSnr
TAG_STATE_ACTIVATING = 0x02, // In activation phase (password mode), sent UID, awaiting reader password
TAG_STATE_ACTIVATED = 0x03, // Activation complete, awaiting read/write commands
TAG_STATE_WRITING = 0x04, // In write command, awaiting sector contents to be written
} state;
unsigned int active_sector;
uint8_t crypto_active;
uint64_t cs;
uint8_t sectors[12][4];
};
static struct hitag2_tag tag = { static struct hitag2_tag tag = {
.state = TAG_STATE_RESET, .state = TAG_STATE_RESET,
.sectors = { // Password mode: | Crypto mode: .sectors = { // Password mode: | Crypto mode:
@ -81,87 +70,6 @@ static uint8_t key[8];
static uint8_t writedata[4]; static uint8_t writedata[4];
static uint64_t cipher_state; static uint64_t cipher_state;
/* Following is a modified version of cryptolib.com/ciphers/hitag2/ */
// Software optimized 48-bit Philips/NXP Mifare Hitag2 PCF7936/46/47/52 stream cipher algorithm by I.C. Wiener 2006-2007.
// For educational purposes only.
// No warranties or guarantees of any kind.
// This code is released into the public domain by its author.
// Basic macros:
#define u8 uint8_t
#define u32 uint32_t
#define u64 uint64_t
#define rev8(x) ((((x)>>7)&1)+((((x)>>6)&1)<<1)+((((x)>>5)&1)<<2)+((((x)>>4)&1)<<3)+((((x)>>3)&1)<<4)+((((x)>>2)&1)<<5)+((((x)>>1)&1)<<6)+(((x)&1)<<7))
#define rev16(x) (rev8 (x)+(rev8 (x>> 8)<< 8))
#define rev32(x) (rev16(x)+(rev16(x>>16)<<16))
#define rev64(x) (rev32(x)+(rev32(x>>32)<<32))
#define bit(x,n) (((x)>>(n))&1)
#define bit32(x,n) ((((x)[(n)>>5])>>((n)))&1)
#define inv32(x,i,n) ((x)[(i)>>5]^=((u32)(n))<<((i)&31))
#define rotl64(x, n) ((((u64)(x))<<((n)&63))+(((u64)(x))>>((0-(n))&63)))
// Single bit Hitag2 functions:
#define i4(x,a,b,c,d) ((u32)((((x)>>(a))&1)+(((x)>>(b))&1)*2+(((x)>>(c))&1)*4+(((x)>>(d))&1)*8))
static const u32 ht2_f4a = 0x2C79; // 0010 1100 0111 1001
static const u32 ht2_f4b = 0x6671; // 0110 0110 0111 0001
static const u32 ht2_f5c = 0x7907287B; // 0111 1001 0000 0111 0010 1000 0111 1011
static u32 _f20(const u64 x) {
u32 i5;
i5 = ((ht2_f4a >> i4(x, 1, 2, 4, 5)) & 1) * 1
+ ((ht2_f4b >> i4(x, 7, 11, 13, 14)) & 1) * 2
+ ((ht2_f4b >> i4(x, 16, 20, 22, 25)) & 1) * 4
+ ((ht2_f4b >> i4(x, 27, 28, 30, 32)) & 1) * 8
+ ((ht2_f4a >> i4(x, 33, 42, 43, 45)) & 1) * 16;
return (ht2_f5c >> i5) & 1;
}
static u64 _hitag2_init(const u64 key, const u32 serial, const u32 IV) {
u32 i;
u64 x = ((key & 0xFFFF) << 32) + serial;
for (i = 0; i < 32; i++) {
x >>= 1;
x += (u64)(_f20(x) ^ (((IV >> i) ^ (key >> (i + 16))) & 1)) << 47;
}
return x;
}
static u64 _hitag2_round(u64 *state) {
u64 x = *state;
x = (x >> 1) +
((((x >> 0) ^ (x >> 2) ^ (x >> 3) ^ (x >> 6)
^ (x >> 7) ^ (x >> 8) ^ (x >> 16) ^ (x >> 22)
^ (x >> 23) ^ (x >> 26) ^ (x >> 30) ^ (x >> 41)
^ (x >> 42) ^ (x >> 43) ^ (x >> 46) ^ (x >> 47)) & 1) << 47);
*state = x;
return _f20(x);
}
// "MIKRON" = O N M I K R
// Key = 4F 4E 4D 49 4B 52 - Secret 48-bit key
// Serial = 49 43 57 69 - Serial number of the tag, transmitted in clear
// Random = 65 6E 45 72 - Random IV, transmitted in clear
//~28~DC~80~31 = D7 23 7F CE - Authenticator value = inverted first 4 bytes of the keystream
// The code below must print out "D7 23 7F CE 8C D0 37 A9 57 49 C1 E6 48 00 8A B6".
// The inverse of the first 4 bytes is sent to the tag to authenticate.
// The rest is encrypted by XORing it with the subsequent keystream.
static u32 _hitag2_byte(u64 *x) {
u32 i, c;
for (i = 0, c = 0; i < 8; i++) {
c += (u32) _hitag2_round(x) << (i ^ 7);
}
return c;
}
static int hitag2_reset(void) { static int hitag2_reset(void) {
tag.state = TAG_STATE_RESET; tag.state = TAG_STATE_RESET;
tag.crypto_active = 0; tag.crypto_active = 0;
@ -173,48 +81,13 @@ static int hitag2_init(void) {
return 0; return 0;
} }
static void hitag2_cipher_reset(struct hitag2_tag *tag, const uint8_t *iv) {
uint64_t key = ((uint64_t)tag->sectors[2][2]) |
((uint64_t)tag->sectors[2][3] << 8) |
((uint64_t)tag->sectors[1][0] << 16) |
((uint64_t)tag->sectors[1][1] << 24) |
((uint64_t)tag->sectors[1][2] << 32) |
((uint64_t)tag->sectors[1][3] << 40);
uint32_t uid = ((uint32_t)tag->sectors[0][0]) |
((uint32_t)tag->sectors[0][1] << 8) |
((uint32_t)tag->sectors[0][2] << 16) |
((uint32_t)tag->sectors[0][3] << 24);
uint32_t iv_ = (((uint32_t)(iv[0]))) |
(((uint32_t)(iv[1])) << 8) |
(((uint32_t)(iv[2])) << 16) |
(((uint32_t)(iv[3])) << 24);
tag->cs = _hitag2_init(rev64(key), rev32(uid), rev32(iv_));
}
static int hitag2_cipher_authenticate(uint64_t *cs, const uint8_t *authenticator_is) {
uint8_t authenticator_should[4];
authenticator_should[0] = ~_hitag2_byte(cs);
authenticator_should[1] = ~_hitag2_byte(cs);
authenticator_should[2] = ~_hitag2_byte(cs);
authenticator_should[3] = ~_hitag2_byte(cs);
return (memcmp(authenticator_should, authenticator_is, 4) == 0);
}
static int hitag2_cipher_transcrypt(uint64_t *cs, uint8_t *data, unsigned int bytes, unsigned int bits) {
int i;
for (i = 0; i < bytes; i++) data[i] ^= _hitag2_byte(cs);
for (i = 0; i < bits; i++) data[bytes] ^= _hitag2_round(cs) << (7 - i);
return 0;
}
// Sam7s has several timers, we will use the source TIMER_CLOCK1 (aka AT91C_TC_CLKS_TIMER_DIV1_CLOCK) // Sam7s has several timers, we will use the source TIMER_CLOCK1 (aka AT91C_TC_CLKS_TIMER_DIV1_CLOCK)
// TIMER_CLOCK1 = MCK/2, MCK is running at 48 MHz, Timer is running at 48/2 = 24 MHz // TIMER_CLOCK1 = MCK/2, MCK is running at 48 MHz, Timer is running at 48/2 = 24 MHz
// Hitag units (T0) have duration of 8 microseconds (us), which is 1/125000 per second (carrier) // Hitag units (T0) have duration of 8 microseconds (us), which is 1/125000 per second (carrier)
// T0 = TIMER_CLOCK1 / 125000 = 192 // T0 = TIMER_CLOCK1 / 125000 = 192
#ifndef T0
#define T0 192 #define T0 192
#endif
#define SHORT_COIL() LOW(GPIO_SSC_DOUT)
#define OPEN_COIL() HIGH(GPIO_SSC_DOUT)
#define HITAG_FRAME_LEN 20 #define HITAG_FRAME_LEN 20
#define HITAG_T_STOP 36 /* T_EOF should be > 36 */ #define HITAG_T_STOP 36 /* T_EOF should be > 36 */
@ -241,7 +114,6 @@ static int hitag2_cipher_transcrypt(uint64_t *cs, uint8_t *data, unsigned int by
#define HITAG_T_TAG_CAPTURE_THREE_HALF 41 #define HITAG_T_TAG_CAPTURE_THREE_HALF 41
#define HITAG_T_TAG_CAPTURE_FOUR_HALF 57 #define HITAG_T_TAG_CAPTURE_FOUR_HALF 57
static void hitag_send_bit(int bit) { static void hitag_send_bit(int bit) {
LED_A_ON(); LED_A_ON();
// Reset clock for the next bit // Reset clock for the next bit
@ -265,10 +137,12 @@ static void hitag_send_bit(int bit) {
} }
static void hitag_send_frame(const uint8_t *frame, size_t frame_len) { static void hitag_send_frame(const uint8_t *frame, size_t frame_len) {
// Send start of frame // SOF - send start of frame
for (size_t i = 0; i < 5; i++) { hitag_send_bit(1);
hitag_send_bit(1);
hitag_send_bit(1);
hitag_send_bit(1);
hitag_send_bit(1); hitag_send_bit(1);
}
// Send the content of the frame // Send the content of the frame
for (size_t i = 0; i < frame_len; i++) { for (size_t i = 0; i < frame_len; i++) {
@ -279,7 +153,7 @@ static void hitag_send_frame(const uint8_t *frame, size_t frame_len) {
LOW(GPIO_SSC_DOUT); LOW(GPIO_SSC_DOUT);
} }
// sim
static void hitag2_handle_reader_command(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t *txlen) { static void hitag2_handle_reader_command(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t *txlen) {
uint8_t rx_air[HITAG_FRAME_LEN]; uint8_t rx_air[HITAG_FRAME_LEN];
@ -398,14 +272,15 @@ static void hitag2_handle_reader_command(uint8_t *rx, const size_t rxlen, uint8_
break; break;
} }
// LogTraceHitag(rx,rxlen,0,0,false); // LogTrace(rx, nbytes(rxlen), 0, 0, NULL, false);
// LogTraceHitag(tx,*txlen,0,0,true); // LogTrace(tx, nbytes(txlen), 0, 0, NULL, true);
if (tag.crypto_active) { if (tag.crypto_active) {
hitag2_cipher_transcrypt(&(tag.cs), tx, *txlen / 8, *txlen % 8); hitag2_cipher_transcrypt(&(tag.cs), tx, *txlen / 8, *txlen % 8);
} }
} }
// sim
static void hitag_reader_send_bit(int bit) { static void hitag_reader_send_bit(int bit) {
LED_A_ON(); LED_A_ON();
// Reset clock for the next bit // Reset clock for the next bit
@ -418,8 +293,7 @@ static void hitag_reader_send_bit(int bit) {
HIGH(GPIO_SSC_DOUT); HIGH(GPIO_SSC_DOUT);
// Wait for 4-10 times the carrier period // Wait for 4-10 times the carrier period
while (AT91C_BASE_TC0->TC_CV < T0 * 6); while (AT91C_BASE_TC0->TC_CV < T0 * 6) {};
// SpinDelayUs(8*8);
// Disable modulation, just activates the field again // Disable modulation, just activates the field again
LOW(GPIO_SSC_DOUT); LOW(GPIO_SSC_DOUT);
@ -435,7 +309,7 @@ static void hitag_reader_send_bit(int bit) {
LED_A_OFF(); LED_A_OFF();
} }
// sim
static void hitag_reader_send_frame(const uint8_t *frame, size_t frame_len) { static void hitag_reader_send_frame(const uint8_t *frame, size_t frame_len) {
// Send the content of the frame // Send the content of the frame
for (size_t i = 0; i < frame_len; i++) { for (size_t i = 0; i < frame_len; i++) {
@ -446,13 +320,17 @@ static void hitag_reader_send_frame(const uint8_t *frame, size_t frame_len) {
// Enable modulation, which means, drop the field // Enable modulation, which means, drop the field
HIGH(GPIO_SSC_DOUT); HIGH(GPIO_SSC_DOUT);
// Wait for 4-10 times the carrier period // Wait for 4-10 times the carrier period
while (AT91C_BASE_TC0->TC_CV < T0 * 6); while (AT91C_BASE_TC0->TC_CV < T0 * 6) {};
// Disable modulation, just activates the field again // Disable modulation, just activates the field again
LOW(GPIO_SSC_DOUT); LOW(GPIO_SSC_DOUT);
} }
size_t blocknr; size_t blocknr;
//-----------------------------------------------------------------------------
// Hitag2 operations
//-----------------------------------------------------------------------------
static bool hitag2_password(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t *txlen) { static bool hitag2_password(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t *txlen) {
// Reset the transmission frame length // Reset the transmission frame length
*txlen = 0; *txlen = 0;
@ -467,7 +345,7 @@ static bool hitag2_password(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t
return false; return false;
} }
*txlen = 5; *txlen = 5;
memcpy(tx, "\xc0", nbytes(*txlen)); memcpy(tx, "\xC0", nbytes(*txlen));
} }
break; break;
@ -495,7 +373,7 @@ static bool hitag2_password(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t
return false; return false;
} }
*txlen = 10; *txlen = 10;
tx[0] = 0xc0 | (blocknr << 3) | ((blocknr ^ 7) >> 2); tx[0] = 0xC0 | (blocknr << 3) | ((blocknr ^ 7) >> 2);
tx[1] = ((blocknr ^ 7) << 6); tx[1] = ((blocknr ^ 7) << 6);
} }
} }
@ -521,9 +399,10 @@ static bool hitag2_write_page(uint8_t *rx, const size_t rxlen, uint8_t *tx, size
break; break;
case WRITE_STATE_PAGENUM_WRITTEN: case WRITE_STATE_PAGENUM_WRITTEN:
// Check if page number was received correctly // Check if page number was received correctly
if ((rxlen == 10) && if ( (rxlen == 10)
(rx[0] == (0x82 | (blocknr << 3) | ((blocknr ^ 7) >> 2))) && && (rx[0] == (0x82 | (blocknr << 3) | ((blocknr ^ 7) >> 2)))
(rx[1] == (((blocknr & 0x3) ^ 0x3) << 6))) { && (rx[1] == (((blocknr & 0x3) ^ 0x3) << 6))) {
*txlen = 32; *txlen = 32;
memset(tx, 0, HITAG_FRAME_LEN); memset(tx, 0, HITAG_FRAME_LEN);
memcpy(tx, writedata, 4); memcpy(tx, writedata, 4);
@ -605,8 +484,8 @@ static bool hitag2_crypto(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t *
if (!bCrypto) { if (!bCrypto) {
uint64_t ui64key = key[0] | ((uint64_t)key[1]) << 8 | ((uint64_t)key[2]) << 16 | ((uint64_t)key[3]) << 24 | ((uint64_t)key[4]) << 32 | ((uint64_t)key[5]) << 40; uint64_t ui64key = key[0] | ((uint64_t)key[1]) << 8 | ((uint64_t)key[2]) << 16 | ((uint64_t)key[3]) << 24 | ((uint64_t)key[4]) << 32 | ((uint64_t)key[5]) << 40;
uint32_t ui32uid = rx[0] | ((uint32_t)rx[1]) << 8 | ((uint32_t)rx[2]) << 16 | ((uint32_t)rx[3]) << 24; uint32_t ui32uid = rx[0] | ((uint32_t)rx[1]) << 8 | ((uint32_t)rx[2]) << 16 | ((uint32_t)rx[3]) << 24;
Dbprintf("hitag2_crypto: key=0x%x%x uid=0x%x", (uint32_t)((rev64(ui64key)) >> 32), (uint32_t)((rev64(ui64key)) & 0xffffffff), rev32(ui32uid)); Dbprintf("hitag2_crypto: key=0x%x%x uid=0x%x", (uint32_t)((REV64(ui64key)) >> 32), (uint32_t)((REV64(ui64key)) & 0xffffffff), REV32(ui32uid));
cipher_state = _hitag2_init(rev64(ui64key), rev32(ui32uid), 0); cipher_state = _hitag2_init(REV64(ui64key), REV32(ui32uid), 0);
memset(tx, 0x00, 4); memset(tx, 0x00, 4);
memset(tx + 4, 0xff, 4); memset(tx + 4, 0xff, 4);
hitag2_cipher_transcrypt(&cipher_state, tx + 4, 4, 0); hitag2_cipher_transcrypt(&cipher_state, tx + 4, 4, 0);
@ -674,7 +553,7 @@ static bool hitag2_authenticate(uint8_t *rx, const size_t rxlen, uint8_t *tx, si
return false; return false;
} }
*txlen = 5; *txlen = 5;
memcpy(tx, "\xc0", nbytes(*txlen)); memcpy(tx, "\xC0", nbytes(*txlen));
} }
break; break;
@ -801,7 +680,11 @@ static bool hitag2_read_uid(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t
return true; return true;
} }
void SnoopHitag(uint32_t type) { // Hitag2 Sniffing
void SniffHitag(uint32_t type) {
StopTicks();
int frame_count; int frame_count;
int response; int response;
int overflow; int overflow;
@ -814,12 +697,8 @@ void SnoopHitag(uint32_t type) {
size_t rxlen = 0; size_t rxlen = 0;
FpgaDownloadAndGo(FPGA_BITSTREAM_LF); FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
// free eventually allocated BigBuf memory
BigBuf_free(); BigBuf_free();
BigBuf_Clear_ext(false); BigBuf_Clear_ext(false);
// Clean up trace and prepare it for storing frames
clear_trace(); clear_trace();
set_tracing(true); set_tracing(true);
@ -829,19 +708,18 @@ void SnoopHitag(uint32_t type) {
auth_table = (uint8_t *)BigBuf_malloc(AUTH_TABLE_LENGTH); auth_table = (uint8_t *)BigBuf_malloc(AUTH_TABLE_LENGTH);
memset(auth_table, 0x00, AUTH_TABLE_LENGTH); memset(auth_table, 0x00, AUTH_TABLE_LENGTH);
DbpString("Starting Hitag2 snoop"); DbpString("Starting Hitag2 sniffing");
LED_D_ON(); LED_D_ON();
// Set up eavesdropping mode, frequency divisor which will drive the FPGA // Set up eavesdropping mode, frequency divisor which will drive the FPGA
// and analog mux selection. // and analog mux selection.
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_TOGGLE_MODE); FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_TOGGLE_MODE);
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95);
SetAdcMuxFor(GPIO_MUXSEL_LOPKD); SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
RELAY_OFF();
// Configure output pin that is connected to the FPGA (for modulating) // Configure output pin that is connected to the FPGA (for modulating)
AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT; AT91C_BASE_PIOA->PIO_OER |= GPIO_SSC_DOUT;
AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT; AT91C_BASE_PIOA->PIO_PER |= GPIO_SSC_DOUT;
// Disable modulation, we are going to eavesdrop, not modulate ;) // Disable modulation, we are going to eavesdrop, not modulate ;)
LOW(GPIO_SSC_DOUT); LOW(GPIO_SSC_DOUT);
@ -853,14 +731,16 @@ void SnoopHitag(uint32_t type) {
// Disable timer during configuration // Disable timer during configuration
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
// Capture mode, defaul timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger, // TC1: Capture mode, default timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger,
// external trigger rising edge, load RA on rising edge of TIOA. // external trigger rising edge, load RA on rising edge of TIOA.
uint32_t t1_channel_mode = AT91C_TC_CLKS_TIMER_DIV1_CLOCK | AT91C_TC_ETRGEDG_BOTH | AT91C_TC_ABETRG | AT91C_TC_LDRA_BOTH; AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK | AT91C_TC_ETRGEDG_BOTH | AT91C_TC_ABETRG | AT91C_TC_LDRA_BOTH;
AT91C_BASE_TC1->TC_CMR = t1_channel_mode;
// Enable and reset counter // Enable and reset counter
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
// synchronized startup procedure
while (AT91C_BASE_TC0->TC_CV > 0) {}; // wait until TC0 returned to zero
// Reset the received frame, frame count and timing info // Reset the received frame, frame count and timing info
memset(rx, 0x00, sizeof(rx)); memset(rx, 0x00, sizeof(rx));
frame_count = 0; frame_count = 0;
@ -971,10 +851,7 @@ void SnoopHitag(uint32_t type) {
// Check if frame was captured // Check if frame was captured
if (rxlen > 0) { if (rxlen > 0) {
frame_count++; frame_count++;
if (!LogTraceHitag(rx, rxlen, response, 0, reader_frame)) { LogTrace(rx, nbytes(rxlen), response, 0, NULL, reader_frame);
DbpString("Trace full");
break;
}
// Check if we recognize a valid authentication attempt // Check if we recognize a valid authentication attempt
if (nbytes(rxlen) == 8) { if (nbytes(rxlen) == 8) {
@ -1005,49 +882,47 @@ void SnoopHitag(uint32_t type) {
// Reset the timer to restart while-loop that receives frames // Reset the timer to restart while-loop that receives frames
AT91C_BASE_TC1->TC_CCR = AT91C_TC_SWTRG; AT91C_BASE_TC1->TC_CCR = AT91C_TC_SWTRG;
} }
LED_A_ON(); LEDsoff();
LED_B_OFF(); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LED_C_OFF(); set_tracing(false);
LED_D_OFF();
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS;
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LED_A_OFF(); // release allocated memory from BigBuff.
set_tracing(false); BigBuf_free();
// Dbprintf("frame received: %d",frame_count); StartTicks();
// Dbprintf("Authentication Attempts: %d",(auth_table_len/8));
// DbpString("All done"); DbpString("Hitag2 sniffing end, use `lf hitag list` for annotations");
} }
// Hitag2 simulation
void SimulateHitagTag(bool tag_mem_supplied, uint8_t *data) { void SimulateHitagTag(bool tag_mem_supplied, uint8_t *data) {
int frame_count;
int response; StopTicks();
int overflow;
int frame_count = 0, response = 0, overflow = 0;
uint8_t rx[HITAG_FRAME_LEN]; uint8_t rx[HITAG_FRAME_LEN];
size_t rxlen = 0; size_t rxlen = 0;
uint8_t tx[HITAG_FRAME_LEN]; uint8_t tx[HITAG_FRAME_LEN];
size_t txlen = 0; size_t txlen = 0;
bool bQuitTraceFull = false;
bQuiet = false;
FpgaDownloadAndGo(FPGA_BITSTREAM_LF); FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
// free eventually allocated BigBuf memory
BigBuf_free(); BigBuf_free();
BigBuf_Clear_ext(false); BigBuf_Clear_ext(false);
// Clean up trace and prepare it for storing frames
clear_trace(); clear_trace();
set_tracing(true); set_tracing(true);
auth_table_len = 0; auth_table_len = 0;
auth_table_pos = 0; auth_table_pos = 0;
uint8_t *auth_table; uint8_t *auth_table = BigBuf_malloc(AUTH_TABLE_LENGTH);
auth_table = (uint8_t *)BigBuf_malloc(AUTH_TABLE_LENGTH);
memset(auth_table, 0x00, AUTH_TABLE_LENGTH); memset(auth_table, 0x00, AUTH_TABLE_LENGTH);
// Reset the received frame, frame count and timing info
memset(rx, 0x00, sizeof(rx));
DbpString("Starting Hitag2 simulation"); DbpString("Starting Hitag2 simulation");
LED_D_ON(); LED_D_ON();
hitag2_init(); hitag2_init();
@ -1068,41 +943,41 @@ void SimulateHitagTag(bool tag_mem_supplied, uint8_t *data) {
// Set up simulator mode, frequency divisor which will drive the FPGA // Set up simulator mode, frequency divisor which will drive the FPGA
// and analog mux selection. // and analog mux selection.
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT); FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT);
SpinDelay(50);
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
SetAdcMuxFor(GPIO_MUXSEL_LOPKD); SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
RELAY_OFF();
// Configure output pin that is connected to the FPGA (for modulating) // Configure output pin that is connected to the FPGA (for modulating)
AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT; AT91C_BASE_PIOA->PIO_OER |= GPIO_SSC_DOUT;
AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT; AT91C_BASE_PIOA->PIO_PER |= GPIO_SSC_DOUT;
// Disable modulation at default, which means release resistance // Disable modulation at default, which means release resistance
LOW(GPIO_SSC_DOUT); LOW(GPIO_SSC_DOUT);
// Enable Peripheral Clock for TIMER_CLOCK0, used to measure exact timing before answering // Enable Peripheral Clock for
AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC0); // TIMER_CLOCK0, used to measure exact timing before answering
// TIMER_CLOCK1, used to capture edges of the tag frames
AT91C_BASE_PMC->PMC_PCER |= (1 << AT91C_ID_TC0) | (1 << AT91C_ID_TC1);
// Enable Peripheral Clock for TIMER_CLOCK1, used to capture edges of the reader frames
AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC1);
AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME; AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME;
// Disable timer during configuration // Disable timer during configuration
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS;
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
// Capture mode, default timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger, // TC0: Capture mode, default timer source = MCK/2 (TIMER_CLOCK1), no triggers
AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK;
// TC1: Capture mode, default timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger,
// external trigger rising edge, load RA on rising edge of TIOA. // external trigger rising edge, load RA on rising edge of TIOA.
AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK | AT91C_TC_ETRGEDG_RISING | AT91C_TC_ABETRG | AT91C_TC_LDRA_RISING; AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK | AT91C_TC_ETRGEDG_RISING | AT91C_TC_ABETRG | AT91C_TC_LDRA_RISING;
// Reset the received frame, frame count and timing info
memset(rx, 0x00, sizeof(rx));
frame_count = 0;
response = 0;
overflow = 0;
// Enable and reset counter // Enable and reset counter
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
// synchronized startup procedure
while (AT91C_BASE_TC0->TC_CV > 0) {}; // wait until TC0 returned to zero
while (!BUTTON_PRESS() && !usb_poll_validate_length()) { while (!BUTTON_PRESS() && !usb_poll_validate_length()) {
// Watchdog hit // Watchdog hit
WDT_HIT(); WDT_HIT();
@ -1144,16 +1019,7 @@ void SimulateHitagTag(bool tag_mem_supplied, uint8_t *data) {
// Check if frame was captured // Check if frame was captured
if (rxlen > 4) { if (rxlen > 4) {
frame_count++; frame_count++;
if (!bQuiet) { LogTrace(rx, nbytes(rxlen), response, response, NULL, true);
if (!LogTraceHitag(rx, rxlen, response, 0, true)) {
DbpString("Trace full");
if (bQuitTraceFull) {
break;
} else {
bQuiet = true;
}
}
}
// Disable timer 1 with external trigger to avoid triggers during our own modulation // Disable timer 1 with external trigger to avoid triggers during our own modulation
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
@ -1170,19 +1036,8 @@ void SimulateHitagTag(bool tag_mem_supplied, uint8_t *data) {
// Send and store the tag answer (if there is any) // Send and store the tag answer (if there is any)
if (txlen) { if (txlen) {
// Transmit the tag frame
hitag_send_frame(tx, txlen); hitag_send_frame(tx, txlen);
// Store the frame in the trace LogTrace(tx, nbytes(txlen), 0, 0, NULL, false);
if (!bQuiet) {
if (!LogTraceHitag(tx, txlen, 0, 0, false)) {
DbpString("Trace full");
if (bQuitTraceFull) {
break;
} else {
bQuiet = true;
}
}
}
} }
// Reset the received frame and response timing info // Reset the received frame and response timing info
@ -1200,17 +1055,25 @@ void SimulateHitagTag(bool tag_mem_supplied, uint8_t *data) {
// Reset the timer to restart while-loop that receives frames // Reset the timer to restart while-loop that receives frames
AT91C_BASE_TC1->TC_CCR = AT91C_TC_SWTRG; AT91C_BASE_TC1->TC_CCR = AT91C_TC_SWTRG;
} }
LED_B_OFF();
LED_D_OFF(); LEDsoff();
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
set_tracing(false);
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS;
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
// release allocated memory from BigBuff.
BigBuf_free();
StartTicks();
DbpString("Sim Stopped"); DbpString("Sim Stopped");
set_tracing(false);
} }
void ReaderHitag(hitag_function htf, hitag_data *htd) { void ReaderHitag(hitag_function htf, hitag_data *htd) {
StopTicks();
int frame_count = 0; int frame_count = 0;
int response = 0; int response = 0;
uint8_t rx[HITAG_FRAME_LEN]; uint8_t rx[HITAG_FRAME_LEN];
@ -1233,7 +1096,6 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) {
Dbprintf("List identifier in password mode"); Dbprintf("List identifier in password mode");
memcpy(password, htd->pwd.password, 4); memcpy(password, htd->pwd.password, 4);
blocknr = 0; blocknr = 0;
bQuiet = false;
bPwd = false; bPwd = false;
break; break;
} }
@ -1241,7 +1103,6 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) {
DbpString("Authenticating using nr,ar pair:"); DbpString("Authenticating using nr,ar pair:");
memcpy(NrAr, htd->auth.NrAr, 8); memcpy(NrAr, htd->auth.NrAr, 8);
Dbhexdump(8, NrAr, false); Dbhexdump(8, NrAr, false);
bQuiet = false;
bCrypto = false; bCrypto = false;
bAuthenticating = false; bAuthenticating = false;
break; break;
@ -1251,7 +1112,6 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) {
memcpy(key, htd->crypto.key, 6); //HACK; 4 or 6?? I read both in the code. memcpy(key, htd->crypto.key, 6); //HACK; 4 or 6?? I read both in the code.
Dbhexdump(6, key, false); Dbhexdump(6, key, false);
blocknr = 0; blocknr = 0;
bQuiet = false;
bCrypto = false; bCrypto = false;
bAuthenticating = false; bAuthenticating = false;
break; break;
@ -1260,13 +1120,11 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) {
Dbprintf("Testing %d authentication attempts", (auth_table_len / 8)); Dbprintf("Testing %d authentication attempts", (auth_table_len / 8));
auth_table_pos = 0; auth_table_pos = 0;
memcpy(NrAr, auth_table, 8); memcpy(NrAr, auth_table, 8);
bQuiet = false;
bCrypto = false; bCrypto = false;
break; break;
} }
case RHT2F_UID_ONLY: { case RHT2F_UID_ONLY: {
blocknr = 0; blocknr = 0;
bQuiet = false;
bCrypto = false; bCrypto = false;
bAuthenticating = false; bAuthenticating = false;
break; break;
@ -1274,6 +1132,7 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) {
default: { default: {
Dbprintf("Error, unknown function: %d", htf); Dbprintf("Error, unknown function: %d", htf);
set_tracing(false); set_tracing(false);
StartTicks();
return; return;
} }
} }
@ -1286,33 +1145,35 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) {
LED_D_ON(); LED_D_ON();
hitag2_init(); hitag2_init();
// Configure output and enable pin that is connected to the FPGA (for modulating)
AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT;
AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT;
// Set fpga in edge detect with reader field, we can modulate as reader now // Set fpga in edge detect with reader field, we can modulate as reader now
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_READER_FIELD); FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_READER_FIELD);
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
SetAdcMuxFor(GPIO_MUXSEL_LOPKD); SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
// RELAY_OFF();
// Configure output and enable pin that is connected to the FPGA (for modulating)
AT91C_BASE_PIOA->PIO_OER |= GPIO_SSC_DOUT;
AT91C_BASE_PIOA->PIO_PER |= GPIO_SSC_DOUT;
// Disable modulation at default, which means enable the field // Disable modulation at default, which means enable the field
LOW(GPIO_SSC_DOUT); LOW(GPIO_SSC_DOUT);
// Give it a bit of time for the resonant antenna to settle. // Enable Peripheral Clock for
SpinDelay(30); // TIMER_CLOCK0, used to measure exact timing before answering
// TIMER_CLOCK1, used to capture edges of the tag frames
AT91C_BASE_PMC->PMC_PCER |= (1 << AT91C_ID_TC0) | (1 << AT91C_ID_TC1);
// Enable Peripheral Clock for TIMER_CLOCK0, used to measure exact timing before answering // PIO_A - BSR
AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC0);
// Enable Peripheral Clock for TIMER_CLOCK1, used to capture edges of the tag frames
AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC1);
AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME; AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME;
// Disable timer during configuration // Disable timer during configuration
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS;
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
// Capture mode, defaul timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger, // TC0: Capture mode, default timer source = MCK/2 (TIMER_CLOCK1), no triggers
AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK;
// TC1: Capture mode, default timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger,
// external trigger rising edge, load RA on falling edge of TIOA. // external trigger rising edge, load RA on falling edge of TIOA.
AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK | AT91C_TC_ETRGEDG_FALLING | AT91C_TC_ABETRG | AT91C_TC_LDRA_FALLING; AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK | AT91C_TC_ETRGEDG_FALLING | AT91C_TC_ABETRG | AT91C_TC_LDRA_FALLING;
@ -1320,36 +1181,36 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) {
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
// synchronized startup procedure
while (AT91C_BASE_TC0->TC_CV > 0) {}; // wait until TC0 returned to zero
// Tag specific configuration settings (sof, timings, etc.) // Tag specific configuration settings (sof, timings, etc.)
if (htf < 10) { if (htf < 10) {
// hitagS settings // hitagS settings
reset_sof = 1; reset_sof = 1;
t_wait = 200; t_wait = 200;
// DbpString("Configured for hitagS reader");
} else if (htf < 20) { } else if (htf < 20) {
// hitag1 settings // hitag1 settings
reset_sof = 1; reset_sof = 1;
t_wait = 200; t_wait = 200;
// DbpString("Configured for hitag1 reader");
} else if (htf < 30) { } else if (htf < 30) {
// hitag2 settings // hitag2 settings
reset_sof = 4; reset_sof = 4;
t_wait = HITAG_T_WAIT_2; t_wait = HITAG_T_WAIT_2;
// DbpString("Configured for hitag2 reader");
} else { } else {
Dbprintf("Error, unknown hitag reader type: %d", htf); Dbprintf("Error, unknown hitag reader type: %d", htf);
goto out; goto out;
} }
uint8_t attempt_count = 0; uint8_t attempt_count = 0;
while (!bStop && !BUTTON_PRESS() && !usb_poll_validate_length() ) { while (!bStop && !BUTTON_PRESS() && !usb_poll_validate_length()) {
WDT_HIT(); WDT_HIT();
// Check if frame was captured and store it // Check if frame was captured and store it
if (rxlen > 0) { if (rxlen > 0) {
frame_count++; frame_count++;
LogTraceHitag(rx, rxlen, response, 0, false); LogTrace(rx, nbytes(rxlen), response, response, NULL, false);
} }
// By default reset the transmission buffer // By default reset the transmission buffer
@ -1405,7 +1266,7 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) {
// Add transmitted frame to total count // Add transmitted frame to total count
if (txlen > 0) { if (txlen > 0) {
frame_count++; frame_count++;
LogTraceHitag(tx, txlen, HITAG_T_WAIT_2, 0, true); LogTrace(tx, nbytes(txlen), HITAG_T_WAIT_2, HITAG_T_WAIT_2, NULL, true);
} }
// Reset values for receiving frames // Reset values for receiving frames
@ -1419,6 +1280,7 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) {
// Receive frame, watch for at most T0*EOF periods // Receive frame, watch for at most T0*EOF periods
while (AT91C_BASE_TC1->TC_CV < T0 * HITAG_T_WAIT_MAX) { while (AT91C_BASE_TC1->TC_CV < T0 * HITAG_T_WAIT_MAX) {
// Check if falling edge in tag modulation is detected // Check if falling edge in tag modulation is detected
if (AT91C_BASE_TC1->TC_SR & AT91C_TC_LDRAS) { if (AT91C_BASE_TC1->TC_SR & AT91C_TC_LDRAS) {
// Retrieve the new timing values // Retrieve the new timing values
@ -1477,11 +1339,16 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) {
out: out:
LEDsoff(); LEDsoff();
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS;
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
set_tracing(false); set_tracing(false);
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS;
// release allocated memory from BigBuff.
BigBuf_free();
StartTicks();
if (bSuccessful) if (bSuccessful)
cmd_send(CMD_ACK, bSuccessful, 0, 0, (uint8_t *)tag.sectors, 48); cmd_send(CMD_ACK, bSuccessful, 0, 0, (uint8_t *)tag.sectors, 48);
else else
@ -1489,8 +1356,10 @@ out:
} }
void WriterHitag(hitag_function htf, hitag_data *htd, int page) { void WriterHitag(hitag_function htf, hitag_data *htd, int page) {
int frame_count;
int response; StopTicks();
int frame_count = 0, response = 0;
uint8_t rx[HITAG_FRAME_LEN]; uint8_t rx[HITAG_FRAME_LEN];
size_t rxlen = 0; size_t rxlen = 0;
uint8_t txbuf[HITAG_FRAME_LEN]; uint8_t txbuf[HITAG_FRAME_LEN];
@ -1502,17 +1371,13 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) {
int tag_sof; int tag_sof;
int t_wait = HITAG_T_WAIT_MAX; int t_wait = HITAG_T_WAIT_MAX;
bool bStop; bool bStop;
bool bQuitTraceFull = false;
FpgaDownloadAndGo(FPGA_BITSTREAM_LF); FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
// Reset the return status
bSuccessful = false;
// Clean up trace and prepare it for storing frames
set_tracing(true); set_tracing(true);
clear_trace(); clear_trace();
// DbpString("Starting Hitag reader family"); // Reset the return status
bSuccessful = false;
// Check configuration // Check configuration
switch (htf) { switch (htf) {
@ -1522,15 +1387,14 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) {
memcpy(writedata, htd->crypto.data, 4); memcpy(writedata, htd->crypto.data, 4);
Dbhexdump(6, key, false); Dbhexdump(6, key, false);
blocknr = page; blocknr = page;
bQuiet = false;
bCrypto = false; bCrypto = false;
bAuthenticating = false; bAuthenticating = false;
bQuitTraceFull = true;
writestate = WRITE_STATE_START; writestate = WRITE_STATE_START;
} }
break; break;
default: { default: {
Dbprintf("Error, unknown function: %d", htf); Dbprintf("Error, unknown function: %d", htf);
StartTicks();
return; return;
} }
break; break;
@ -1540,44 +1404,45 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) {
hitag2_init(); hitag2_init();
// Configure output and enable pin that is connected to the FPGA (for modulating) // Configure output and enable pin that is connected to the FPGA (for modulating)
AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT; AT91C_BASE_PIOA->PIO_OER |= GPIO_SSC_DOUT;
AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT; AT91C_BASE_PIOA->PIO_PER |= GPIO_SSC_DOUT;
// Set fpga in edge detect with reader field, we can modulate as reader now // Set fpga in edge detect with reader field, we can modulate as reader now
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_READER_FIELD); FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_READER_FIELD);
// Set Frequency divisor which will drive the FPGA and analog mux selection
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
SetAdcMuxFor(GPIO_MUXSEL_LOPKD); SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
RELAY_OFF();
// Disable modulation at default, which means enable the field // Disable modulation at default, which means enable the field
LOW(GPIO_SSC_DOUT); LOW(GPIO_SSC_DOUT);
// Give it a bit of time for the resonant antenna to settle. // Enable Peripheral Clock for
SpinDelay(30); // TIMER_CLOCK0, used to measure exact timing before answering
// TIMER_CLOCK1, used to capture edges of the tag frames
AT91C_BASE_PMC->PMC_PCER |= (1 << AT91C_ID_TC0) | (1 << AT91C_ID_TC1);
// Enable Peripheral Clock for TIMER_CLOCK0, used to measure exact timing before answering
AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC0);
// Enable Peripheral Clock for TIMER_CLOCK1, used to capture edges of the tag frames
AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC1);
AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME; AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME;
// Disable timer during configuration // Disable timer during configuration
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS;
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
// Capture mode, defaul timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger, // TC0: Capture mode, default timer source = MCK/2 (TIMER_CLOCK1), no triggers
AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK;
// TC1: Capture mode, defaul timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger,
// external trigger rising edge, load RA on falling edge of TIOA. // external trigger rising edge, load RA on falling edge of TIOA.
AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK | AT91C_TC_ETRGEDG_FALLING | AT91C_TC_ABETRG | AT91C_TC_LDRA_FALLING; AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK
| AT91C_TC_ETRGEDG_FALLING
| AT91C_TC_ABETRG
| AT91C_TC_LDRA_FALLING;
// Enable and reset counters // Enable and reset counters
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
while (AT91C_BASE_TC0->TC_CV > 0) {};
// Reset the received frame, frame count and timing info // Reset the received frame, frame count and timing info
frame_count = 0;
response = 0;
lastbit = 1; lastbit = 1;
bStop = false; bStop = false;
@ -1586,38 +1451,27 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) {
// hitagS settings // hitagS settings
reset_sof = 1; reset_sof = 1;
t_wait = 200; t_wait = 200;
// DbpString("Configured for hitagS reader");
} else if (htf < 20) { } else if (htf < 20) {
// hitag1 settings // hitag1 settings
reset_sof = 1; reset_sof = 1;
t_wait = 200; t_wait = 200;
// DbpString("Configured for hitag1 reader");
} else if (htf < 30) { } else if (htf < 30) {
// hitag2 settings // hitag2 settings
reset_sof = 4; reset_sof = 4;
t_wait = HITAG_T_WAIT_2; t_wait = HITAG_T_WAIT_2;
// DbpString("Configured for hitag2 reader");
} else { } else {
Dbprintf("Error, unknown hitag reader type: %d", htf); Dbprintf("Error, unknown hitag reader type: %d", htf);
return; return;
} }
while (!bStop && !BUTTON_PRESS()) {
// Watchdog hit while (!bStop && !BUTTON_PRESS() && !usb_poll_validate_length()) {
WDT_HIT(); WDT_HIT();
// Check if frame was captured and store it // Check if frame was captured and store it
if (rxlen > 0) { if (rxlen > 0) {
frame_count++; frame_count++;
if (!bQuiet) { LogTrace(rx, nbytes(rxlen), response, response, NULL, false);
if (!LogTraceHitag(rx, rxlen, response, 0, false)) {
DbpString("Trace full");
if (bQuitTraceFull) {
break;
} else {
bQuiet = true;
}
}
}
} }
// By default reset the transmission buffer // By default reset the transmission buffer
@ -1643,9 +1497,7 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) {
// falling edge occured halfway the period. with respect to this falling edge, // falling edge occured halfway the period. with respect to this falling edge,
// we need to wait (T_Wait2 + half_tag_period) when the last was a 'one'. // we need to wait (T_Wait2 + half_tag_period) when the last was a 'one'.
// All timer values are in terms of T0 units // All timer values are in terms of T0 units
while (AT91C_BASE_TC0->TC_CV < T0 * (t_wait + (HITAG_T_TAG_HALF_PERIOD * lastbit))); while (AT91C_BASE_TC0->TC_CV < T0 * (t_wait + (HITAG_T_TAG_HALF_PERIOD * lastbit))) {};
// Dbprintf("DEBUG: Sending reader frame");
// Transmit the reader frame // Transmit the reader frame
hitag_reader_send_frame(tx, txlen); hitag_reader_send_frame(tx, txlen);
@ -1656,16 +1508,7 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) {
// Add transmitted frame to total count // Add transmitted frame to total count
if (txlen > 0) { if (txlen > 0) {
frame_count++; frame_count++;
if (!bQuiet) { LogTrace(tx, nbytes(txlen), HITAG_T_WAIT_2, HITAG_T_WAIT_2, NULL, true);
// Store the frame in the trace
if (!LogTraceHitag(tx, txlen, HITAG_T_WAIT_2, 0, true)) {
if (bQuitTraceFull) {
break;
} else {
bQuiet = true;
}
}
}
} }
// Reset values for receiving frames // Reset values for receiving frames
@ -1675,7 +1518,6 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) {
bSkip = true; bSkip = true;
tag_sof = reset_sof; tag_sof = reset_sof;
response = 0; response = 0;
// Dbprintf("DEBUG: Waiting to receive frame");
uint32_t errorCount = 0; uint32_t errorCount = 0;
// Receive frame, watch for at most T0*EOF periods // Receive frame, watch for at most T0*EOF periods
@ -1748,6 +1590,7 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) {
} }
// if we saw over 100 wierd values break it probably isn't hitag... // if we saw over 100 wierd values break it probably isn't hitag...
if (errorCount > 100) break; if (errorCount > 100) break;
// We can break this loop if we received the last bit from a frame // We can break this loop if we received the last bit from a frame
if (AT91C_BASE_TC1->TC_CV > T0 * HITAG_T_EOF) { if (AT91C_BASE_TC1->TC_CV > T0 * HITAG_T_EOF) {
if (rxlen > 0) break; if (rxlen > 0) break;
@ -1760,14 +1603,15 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) {
while (AT91C_BASE_TC0->TC_CV < T0 * (HITAG_T_PROG - HITAG_T_WAIT_MAX)); while (AT91C_BASE_TC0->TC_CV < T0 * (HITAG_T_PROG - HITAG_T_WAIT_MAX));
} }
} }
// Dbprintf("DEBUG: Done waiting for frame");
LED_B_OFF(); LEDsoff();
LED_D_OFF(); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
set_tracing(false);
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS;
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
// Dbprintf("frame received: %d",frame_count); StartTicks();
// DbpString("All done");
cmd_send(CMD_ACK, bSuccessful, 0, 0, (uint8_t *)tag.sectors, 48); cmd_send(CMD_ACK, bSuccessful, 0, 0, (uint8_t *)tag.sectors, 48);
} }

23
armsrc/hitag2.h Normal file
View file

@ -0,0 +1,23 @@
//-----------------------------------------------------------------------------
// (c) 2012 Roel Verdult
//
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
// at your option, any later version. See the LICENSE.txt file for the text of
// the license.
//-----------------------------------------------------------------------------
// Hitag2 type prototyping
//-----------------------------------------------------------------------------
#ifndef _HITAG2_H_
#define _HITAG2_H_
#include <stdint.h>
#include <stdbool.h>
#include "hitag.h"
void SniffHitag(uint32_t type);
void SimulateHitagTag(bool tag_mem_supplied, uint8_t *data);
void ReaderHitag(hitag_function htf, hitag_data *htd);
void WriterHitag(hitag_function htf, hitag_data *htd, int page);
#endif

116
armsrc/hitag2_crypto.c Normal file
View file

@ -0,0 +1,116 @@
//-----------------------------------------------------------------------------
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
// at your option, any later version. See the LICENSE.txt file for the text of
// the license.
//-----------------------------------------------------------------------------
// Hitag2 Crypto
//
// (c) 2009 Henryk Plötz <henryk@ploetzli.ch>
// (c) 2012 Roel Verdult
// (c) 2019 Iceman
//-----------------------------------------------------------------------------
#include "hitag2_crypto.h"
/* Following is a modified version of cryptolib.com/ciphers/hitag2/ */
// Software optimized 48-bit Philips/NXP Mifare Hitag2 PCF7936/46/47/52 stream cipher algorithm by I.C. Wiener 2006-2007.
// For educational purposes only.
// No warranties or guarantees of any kind.
// This code is released into the public domain by its author.
// Single bit Hitag2 functions:
#ifndef i4
#define i4(x,a,b,c,d) ((uint32_t)((((x)>>(a))&1)+(((x)>>(b))&1)*2+(((x)>>(c))&1)*4+(((x)>>(d))&1)*8))
#endif
static const uint32_t ht2_f4a = 0x2C79; // 0010 1100 0111 1001
static const uint32_t ht2_f4b = 0x6671; // 0110 0110 0111 0001
static const uint32_t ht2_f5c = 0x7907287B; // 0111 1001 0000 0111 0010 1000 0111 1011
uint32_t _f20(const uint64_t x) {
uint32_t i5;
i5 = ((ht2_f4a >> i4(x, 1, 2, 4, 5)) & 1) * 1
+ ((ht2_f4b >> i4(x, 7, 11, 13, 14)) & 1) * 2
+ ((ht2_f4b >> i4(x, 16, 20, 22, 25)) & 1) * 4
+ ((ht2_f4b >> i4(x, 27, 28, 30, 32)) & 1) * 8
+ ((ht2_f4a >> i4(x, 33, 42, 43, 45)) & 1) * 16;
return (ht2_f5c >> i5) & 1;
}
uint64_t _hitag2_init(const uint64_t key, const uint32_t serial, const uint32_t IV) {
uint32_t i;
uint64_t x = ((key & 0xFFFF) << 32) + serial;
for (i = 0; i < 32; i++) {
x >>= 1;
x += (uint64_t)(_f20(x) ^ (((IV >> i) ^ (key >> (i + 16))) & 1)) << 47;
}
return x;
}
uint64_t _hitag2_round(uint64_t *state) {
uint64_t x = *state;
x = (x >> 1) +
((((x >> 0) ^ (x >> 2) ^ (x >> 3) ^ (x >> 6)
^ (x >> 7) ^ (x >> 8) ^ (x >> 16) ^ (x >> 22)
^ (x >> 23) ^ (x >> 26) ^ (x >> 30) ^ (x >> 41)
^ (x >> 42) ^ (x >> 43) ^ (x >> 46) ^ (x >> 47)) & 1) << 47);
*state = x;
return _f20(x);
}
// "MIKRON" = O N M I K R
// Key = 4F 4E 4D 49 4B 52 - Secret 48-bit key
// Serial = 49 43 57 69 - Serial number of the tag, transmitted in clear
// Random = 65 6E 45 72 - Random IV, transmitted in clear
//~28~DC~80~31 = D7 23 7F CE - Authenticator value = inverted first 4 bytes of the keystream
// The code below must print out "D7 23 7F CE 8C D0 37 A9 57 49 C1 E6 48 00 8A B6".
// The inverse of the first 4 bytes is sent to the tag to authenticate.
// The rest is encrypted by XORing it with the subsequent keystream.
uint32_t _hitag2_byte(uint64_t *x) {
uint32_t i, c;
for (i = 0, c = 0; i < 8; i++) {
c += (uint32_t) _hitag2_round(x) << (i ^ 7);
}
return c;
}
void hitag2_cipher_reset(struct hitag2_tag *tag, const uint8_t *iv) {
uint64_t key = ((uint64_t)tag->sectors[2][2]) |
((uint64_t)tag->sectors[2][3] << 8) |
((uint64_t)tag->sectors[1][0] << 16) |
((uint64_t)tag->sectors[1][1] << 24) |
((uint64_t)tag->sectors[1][2] << 32) |
((uint64_t)tag->sectors[1][3] << 40);
uint32_t uid = ((uint32_t)tag->sectors[0][0]) |
((uint32_t)tag->sectors[0][1] << 8) |
((uint32_t)tag->sectors[0][2] << 16) |
((uint32_t)tag->sectors[0][3] << 24);
uint32_t iv_ = (((uint32_t)(iv[0]))) |
(((uint32_t)(iv[1])) << 8) |
(((uint32_t)(iv[2])) << 16) |
(((uint32_t)(iv[3])) << 24);
tag->cs = _hitag2_init(REV64(key), REV32(uid), REV32(iv_));
}
int hitag2_cipher_authenticate(uint64_t *cs, const uint8_t *authenticator_is) {
uint8_t authenticator_should[4];
authenticator_should[0] = ~_hitag2_byte(cs);
authenticator_should[1] = ~_hitag2_byte(cs);
authenticator_should[2] = ~_hitag2_byte(cs);
authenticator_should[3] = ~_hitag2_byte(cs);
return (memcmp(authenticator_should, authenticator_is, 4) == 0);
}
int hitag2_cipher_transcrypt(uint64_t *cs, uint8_t *data, uint16_t bytes, uint16_t bits) {
int i;
for (i = 0; i < bytes; i++) data[i] ^= _hitag2_byte(cs);
for (i = 0; i < bits; i++) data[bytes] ^= _hitag2_round(cs) << (7 - i);
return 0;
}

36
armsrc/hitag2_crypto.h Normal file
View file

@ -0,0 +1,36 @@
#ifndef __HITAG2_CRYPTO_H
#define __HITAG2_CRYPTO_H
#ifdef __cplusplus
extern "C" {
#endif
#include "string.h"
#include "util.h"
struct hitag2_tag {
uint32_t uid;
enum {
TAG_STATE_RESET = 0x01, // Just powered up, awaiting GetSnr
TAG_STATE_ACTIVATING = 0x02, // In activation phase (password mode), sent UID, awaiting reader password
TAG_STATE_ACTIVATED = 0x03, // Activation complete, awaiting read/write commands
TAG_STATE_WRITING = 0x04, // In write command, awaiting sector contents to be written
} state;
uint16_t active_sector;
uint8_t crypto_active;
uint64_t cs;
uint8_t sectors[12][4];
};
extern uint32_t _f20(const uint64_t x);
extern uint64_t _hitag2_init(const uint64_t key, const uint32_t serial, const uint32_t IV);
extern uint64_t _hitag2_round(uint64_t *state);
extern uint32_t _hitag2_byte(uint64_t *x);
extern void hitag2_cipher_reset(struct hitag2_tag *tag, const uint8_t *iv);
extern int hitag2_cipher_authenticate(uint64_t *cs, const uint8_t *authenticator_is);
extern int hitag2_cipher_transcrypt(uint64_t *cs, uint8_t *data, uint16_t bytes, uint16_t bits) ;
#ifdef __cplusplus
}
#endif
#endif

File diff suppressed because it is too large Load diff

31
armsrc/hitagS.h Normal file
View file

@ -0,0 +1,31 @@
//-----------------------------------------------------------------------------
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
// at your option, any later version. See the LICENSE.txt file for the text of
// the license.
//-----------------------------------------------------------------------------
// HitagS emulation (preliminary test version)
//
// (c) 2016 Oguzhan Cicek, Hendrik Schwartke, Ralf Spenneberg
// <info@os-s.de>
//-----------------------------------------------------------------------------
#ifndef _HITAGS_H_
#define _HITAGS_H_
#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
#include "hitag2_crypto.h"
#include "hitag.h"
#include "proxmark3.h"
#include "apps.h"
#include "util.h"
#include "string.h"
#include "BigBuf.h"
void SimulateHitagSTag(bool tag_mem_supplied, uint8_t *data);
void ReadHitagS(hitag_function htf, hitag_data *htd);
void WritePageHitagS(hitag_function htf, hitag_data *htd, int page);
void check_challenges(bool file_given, uint8_t *data);
#endif

View file

@ -18,7 +18,7 @@
// //
// FIX: // FIX:
// ==== // ====
// We still have sometimes a demodulation error when snooping iClass communication. // We still have sometimes a demodulation error when sniffing iClass communication.
// The resulting trace of a read-block-03 command may look something like this: // The resulting trace of a read-block-03 command may look something like this:
// //
// + 22279: : 0c 03 e8 01 // + 22279: : 0c 03 e8 01

View file

@ -1138,8 +1138,7 @@ void SimulateIso14443aTag(int tagType, int flags, uint8_t *data) {
uint8_t index = receivedCmd[1]; uint8_t index = receivedCmd[1];
if (index > 2) { if (index > 2) {
// send NACK 0x0 == invalid argument // send NACK 0x0 == invalid argument
uint8_t nack[] = {0x00}; EmSend4bit(0x00);
EmSendCmd(nack, sizeof(nack));
} else { } else {
uint8_t cmd[] = {0x00, 0x00, 0x00, 0x14, 0xa5}; uint8_t cmd[] = {0x00, 0x00, 0x00, 0x14, 0xa5};
num_to_bytes(counters[index], 3, cmd); num_to_bytes(counters[index], 3, cmd);
@ -1151,8 +1150,7 @@ void SimulateIso14443aTag(int tagType, int flags, uint8_t *data) {
uint8_t index = receivedCmd[1]; uint8_t index = receivedCmd[1];
if (index > 2) { if (index > 2) {
// send NACK 0x0 == invalid argument // send NACK 0x0 == invalid argument
uint8_t nack[] = {0x00}; EmSend4bit(0x00);
EmSendCmd(nack, sizeof(nack));
} else { } else {
uint32_t val = bytes_to_num(receivedCmd + 2, 4); uint32_t val = bytes_to_num(receivedCmd + 2, 4);
@ -1160,13 +1158,11 @@ void SimulateIso14443aTag(int tagType, int flags, uint8_t *data) {
// if new value + old value is bigger 24bits, fail // if new value + old value is bigger 24bits, fail
if (val + counters[index] > 0xFFFFFF) { if (val + counters[index] > 0xFFFFFF) {
// send NACK 0x4 == counter overflow // send NACK 0x4 == counter overflow
uint8_t nack[] = {0x04}; EmSend4bit(CARD_NACK_NA);
EmSendCmd(nack, sizeof(nack));
} else { } else {
counters[index] = val; counters[index] = val;
// send ACK // send ACK
uint8_t ack[] = {0x0a}; EmSend4bit(CARD_ACK);
EmSendCmd(ack, sizeof(ack));
} }
} }
p_response = NULL; p_response = NULL;
@ -1176,8 +1172,7 @@ void SimulateIso14443aTag(int tagType, int flags, uint8_t *data) {
uint8_t index = receivedCmd[1]; uint8_t index = receivedCmd[1];
if (index > 2) { if (index > 2) {
// send NACK 0x0 == invalid argument // send NACK 0x0 == invalid argument
uint8_t nack[] = {0x00}; EmSend4bit(0x00);
EmSendCmd(nack, sizeof(nack));
} else { } else {
emlGetMemBt(emdata, 10 + index, 1); emlGetMemBt(emdata, 10 + index, 1);
AddCrc14A(emdata, sizeof(emdata) - 2); AddCrc14A(emdata, sizeof(emdata) - 2);
@ -1983,7 +1978,7 @@ static int GetATQA(uint8_t *resp, uint8_t *resp_par) {
// if anticollision is false, then the UID must be provided in uid_ptr[] // if anticollision is false, then the UID must be provided in uid_ptr[]
// and num_cascades must be set (1: 4 Byte UID, 2: 7 Byte UID, 3: 10 Byte UID) // and num_cascades must be set (1: 4 Byte UID, 2: 7 Byte UID, 3: 10 Byte UID)
// requests ATS unless no_rats is true // requests ATS unless no_rats is true
int iso14443a_select_card(byte_t *uid_ptr, iso14a_card_select_t *p_card, uint32_t *cuid_ptr, bool anticollision, uint8_t num_cascades, bool no_rats) { int iso14443a_select_card(uint8_t *uid_ptr, iso14a_card_select_t *p_card, uint32_t *cuid_ptr, bool anticollision, uint8_t num_cascades, bool no_rats) {
uint8_t sel_all[] = { ISO14443A_CMD_ANTICOLL_OR_SELECT, 0x20 }; uint8_t sel_all[] = { ISO14443A_CMD_ANTICOLL_OR_SELECT, 0x20 };
uint8_t sel_uid[] = { ISO14443A_CMD_ANTICOLL_OR_SELECT, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; uint8_t sel_uid[] = { ISO14443A_CMD_ANTICOLL_OR_SELECT, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
@ -2747,7 +2742,7 @@ void DetectNACKbug() {
bool received_nack; bool received_nack;
// Mifare Classic's random generator repeats every 2^16 cycles (and so do the nonces). // Mifare Classic's random generator repeats every 2^16 cycles (and so do the nonces).
uint32_t sync_cycles = PRNG_SEQUENCE_LENGTH; int32_t sync_cycles = PRNG_SEQUENCE_LENGTH;
BigBuf_free(); BigBuf_free();
BigBuf_Clear_ext(false); BigBuf_Clear_ext(false);
@ -3334,9 +3329,18 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t *
break; break;
} }
/*
ans = prng_successor(nonce, 96) ^ crypto1_word(pcs, 0, 0); ans = prng_successor(nonce, 96) ^ crypto1_word(pcs, 0, 0);
num_to_bytes(ans, 4, rAUTH_AT); num_to_bytes(ans, 4, rAUTH_AT);
EmSendCmd(rAUTH_AT, sizeof(rAUTH_AT)); EmSendCmd(rAUTH_AT, sizeof(rAUTH_AT));
*/
ans = prng_successor(nonce, 96);
num_to_bytes(ans, 4, response);
mf_crypto1_encrypt(pcs, response, 4, response_par);
EmSendCmdPar(response, 4, response_par);
LED_C_ON(); LED_C_ON();
if (MF_DBGLEVEL >= 3) { if (MF_DBGLEVEL >= 3) {

View file

@ -1413,7 +1413,7 @@ static void iso1444b_setup_sniff(void) {
FpgaDownloadAndGo(FPGA_BITSTREAM_HF); FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
BigBuf_free(); BigBuf_free();
BigBuf_Clear_ext(false); BigBuf_Clear_ext(false);
clear_trace();//setup snoop clear_trace();
set_tracing(true); set_tracing(true);
// Initialize Demod and Uart structs // Initialize Demod and Uart structs
@ -1570,6 +1570,7 @@ void iso14b_set_trigger(bool enable) {
void SendRawCommand14443B_Ex(UsbCommand *c) { void SendRawCommand14443B_Ex(UsbCommand *c) {
iso14b_command_t param = c->arg[0]; iso14b_command_t param = c->arg[0];
size_t len = c->arg[1] & 0xffff; size_t len = c->arg[1] & 0xffff;
uint32_t timeout = c->arg[2];
uint8_t *cmd = c->d.asBytes; uint8_t *cmd = c->d.asBytes;
uint8_t status = 0; uint8_t status = 0;
uint32_t sendlen = sizeof(iso14b_card_select_t); uint32_t sendlen = sizeof(iso14b_card_select_t);
@ -1586,6 +1587,9 @@ void SendRawCommand14443B_Ex(UsbCommand *c) {
clear_trace(); clear_trace();
} }
if ((param & ISO14B_SET_TIMEOUT))
iso14b_set_timeout(timeout);
set_tracing(true); set_tracing(true);
if ((param & ISO14B_SELECT_STD) == ISO14B_SELECT_STD) { if ((param & ISO14B_SELECT_STD) == ISO14B_SELECT_STD) {

View file

@ -621,8 +621,8 @@ void Iso15693InitReader(void) {
// Encode (into the ToSend buffers) an identify request, which is the first // Encode (into the ToSend buffers) an identify request, which is the first
// thing that you must send to a tag to get a response. // thing that you must send to a tag to get a response.
// It expects "out" to be at least CMD_ID_RESP large
static void BuildIdentifyRequest(uint8_t *out) { static void BuildIdentifyRequest(uint8_t *out) {
uint8_t cmd[CMD_ID_RESP] = {0, ISO15_CMD_INVENTORY, 0, 0, 0}; uint8_t cmd[CMD_ID_RESP] = {0, ISO15_CMD_INVENTORY, 0, 0, 0};
// flags // flags
cmd[0] = ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH | ISO15_REQ_INVENTORY | ISO15_REQINV_SLOT1; cmd[0] = ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH | ISO15_REQ_INVENTORY | ISO15_REQINV_SLOT1;
@ -665,6 +665,7 @@ static void BuildReadBlockRequest(uint8_t **out, uint8_t *uid, uint8_t blockNumb
*/ */
// Now the VICC>VCD responses when we are simulating a tag // Now the VICC>VCD responses when we are simulating a tag
// It expects "out" to be at least CMD_INV_RESP large
static void BuildInventoryResponse(uint8_t *out, uint8_t *uid) { static void BuildInventoryResponse(uint8_t *out, uint8_t *uid) {
uint8_t cmd[CMD_INV_RESP] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; uint8_t cmd[CMD_INV_RESP] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
@ -686,7 +687,7 @@ static void BuildInventoryResponse(uint8_t *out, uint8_t *uid) {
// CRC // CRC
AddCrc(cmd, 10); AddCrc(cmd, 10);
CodeIso15693AsReader(cmd, CMD_INV_RESP); CodeIso15693AsReader(cmd, CMD_INV_RESP);
memcpy(out, cmd, CMD_ID_RESP); memcpy(out, cmd, CMD_INV_RESP);
} }
// Universal Method for sending to and recv bytes from a tag // Universal Method for sending to and recv bytes from a tag
@ -739,50 +740,50 @@ void DbdecodeIso15693Answer(int len, uint8_t *d) {
if (len > 3) { if (len > 3) {
if (d[0] & (1 << 3)) if (d[0] & (1 << 3))
strncat(status, "ProtExt ", DBD15STATLEN); strncat(status, "ProtExt ", DBD15STATLEN - strlen(status));
if (d[0] & 1) { if (d[0] & 1) {
// error // error
strncat(status, "Error ", DBD15STATLEN); strncat(status, "Error ", DBD15STATLEN - strlen(status));
switch (d[1]) { switch (d[1]) {
case 0x01: case 0x01:
strncat(status, "01: not supported", DBD15STATLEN); strncat(status, "01: not supported", DBD15STATLEN - strlen(status));
break; break;
case 0x02: case 0x02:
strncat(status, "02: not recognized", DBD15STATLEN); strncat(status, "02: not recognized", DBD15STATLEN - strlen(status));
break; break;
case 0x03: case 0x03:
strncat(status, "03: opt not supported", DBD15STATLEN); strncat(status, "03: opt not supported", DBD15STATLEN - strlen(status));
break; break;
case 0x0f: case 0x0f:
strncat(status, "0F: no info", DBD15STATLEN); strncat(status, "0F: no info", DBD15STATLEN - strlen(status));
break; break;
case 0x10: case 0x10:
strncat(status, "10: dont exist", DBD15STATLEN); strncat(status, "10: dont exist", DBD15STATLEN - strlen(status));
break; break;
case 0x11: case 0x11:
strncat(status, "11: lock again", DBD15STATLEN); strncat(status, "11: lock again", DBD15STATLEN - strlen(status));
break; break;
case 0x12: case 0x12:
strncat(status, "12: locked", DBD15STATLEN); strncat(status, "12: locked", DBD15STATLEN - strlen(status));
break; break;
case 0x13: case 0x13:
strncat(status, "13: program error", DBD15STATLEN); strncat(status, "13: program error", DBD15STATLEN - strlen(status));
break; break;
case 0x14: case 0x14:
strncat(status, "14: lock error", DBD15STATLEN); strncat(status, "14: lock error", DBD15STATLEN - strlen(status));
break; break;
default: default:
strncat(status, "unknown error", DBD15STATLEN); strncat(status, "unknown error", DBD15STATLEN - strlen(status));
} }
strncat(status, " ", DBD15STATLEN); strncat(status, " ", DBD15STATLEN - strlen(status));
} else { } else {
strncat(status, "No error ", DBD15STATLEN); strncat(status, "No error ", DBD15STATLEN - strlen(status));
} }
if (CheckCrc(d, len)) if (CheckCrc(d, len))
strncat(status, "[+] crc OK", DBD15STATLEN); strncat(status, "[+] crc OK", DBD15STATLEN - strlen(status));
else else
strncat(status, "[!] crc fail", DBD15STATLEN); strncat(status, "[!] crc fail", DBD15STATLEN - strlen(status));
if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("%s", status); if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("%s", status);
} }

View file

@ -21,13 +21,6 @@
#include "common.h" #include "common.h"
#include "flashmem.h" // persistence on mem #include "flashmem.h" // persistence on mem
#ifndef SHORT_COIL
# define SHORT_COIL() LOW(GPIO_SSC_DOUT)
#endif
#ifndef OPEN_COIL
# define OPEN_COIL() HIGH(GPIO_SSC_DOUT)
#endif
//#define START_GAP 31*8 // was 250 // SPEC: 1*8 to 50*8 - typ 15*8 (15fc) //#define START_GAP 31*8 // was 250 // SPEC: 1*8 to 50*8 - typ 15*8 (15fc)
//#define WRITE_GAP 8*8 // 17*8 // was 160 // SPEC: 1*8 to 20*8 - typ 10*8 (10fc) //#define WRITE_GAP 8*8 // 17*8 // was 160 // SPEC: 1*8 to 20*8 - typ 10*8 (10fc)
//#define WRITE_0 15*8 // 18*8 // was 144 // SPEC: 16*8 to 32*8 - typ 24*8 (24fc) //#define WRITE_0 15*8 // 18*8 // was 144 // SPEC: 16*8 to 32*8 - typ 24*8 (24fc)
@ -317,7 +310,7 @@ void ReadTItag(void) {
// expected for either the low or high frequency // expected for either the low or high frequency
if ((samples > (sampleslo - threshold)) && (samples < (sampleslo + threshold))) { if ((samples > (sampleslo - threshold)) && (samples < (sampleslo + threshold))) {
// low frequency represents a 1 // low frequency represents a 1
shift3 |= (1 << 31); shift3 |= (1u << 31);
} else if ((samples > (sampleshi - threshold)) && (samples < (sampleshi + threshold))) { } else if ((samples > (sampleshi - threshold)) && (samples < (sampleshi + threshold))) {
// high frequency represents a 0 // high frequency represents a 0
} else { } else {
@ -481,7 +474,7 @@ void AcquireTiType(void) {
// unpack buffer // unpack buffer
for (i = TIBUFLEN - 1; i >= 0; i--) { for (i = TIBUFLEN - 1; i >= 0; i--) {
for (j = 0; j < 32; j++) { for (j = 0; j < 32; j++) {
if (buf[i] & (1 << j)) { if (buf[i] & (1u << j)) {
dest[--n] = 1; dest[--n] = 1;
} else { } else {
dest[--n] = -1; dest[--n] = -1;
@ -730,8 +723,6 @@ static void fcAll(uint8_t fc, int *n, uint8_t clock, uint16_t *modCnt) {
uint8_t halfFC = fc >> 1; uint8_t halfFC = fc >> 1;
uint8_t wavesPerClock = clock / fc; uint8_t wavesPerClock = clock / fc;
uint8_t mod = clock % fc; //modifier uint8_t mod = clock % fc; //modifier
uint8_t modAdj = fc / mod; //how often to apply modifier
bool modAdjOk = !(fc % mod); //if (fc % mod==0) modAdjOk = true;
// loop through clock - step field clock // loop through clock - step field clock
for (uint8_t idx = 0; idx < wavesPerClock; idx++) { for (uint8_t idx = 0; idx < wavesPerClock; idx++) {
@ -740,20 +731,24 @@ static void fcAll(uint8_t fc, int *n, uint8_t clock, uint16_t *modCnt) {
memset(dest + (*n) + (fc - halfFC), 1, halfFC); memset(dest + (*n) + (fc - halfFC), 1, halfFC);
*n += fc; *n += fc;
} }
if (mod > 0)(*modCnt)++; if (mod > 0) {
uint8_t modAdj = fc / mod; //how often to apply modifier
bool modAdjOk = !(fc % mod); //if (fc % mod==0) modAdjOk = true;
(*modCnt)++;
if ((mod > 0) && modAdjOk) { //fsk2 if (modAdjOk) { //fsk2
if ((*modCnt % modAdj) == 0) { //if 4th 8 length wave in a rf/50 add extra 8 length wave if ((*modCnt % modAdj) == 0) { //if 4th 8 length wave in a rf/50 add extra 8 length wave
memset(dest + (*n), 0, fc - halfFC); memset(dest + (*n), 0, fc - halfFC);
memset(dest + (*n) + (fc - halfFC), 1, halfFC); memset(dest + (*n) + (fc - halfFC), 1, halfFC);
*n += fc; *n += fc;
} }
} }
if (mod > 0 && !modAdjOk) { //fsk1 if (!modAdjOk) { //fsk1
memset(dest + (*n), 0, mod - (mod >> 1)); memset(dest + (*n), 0, mod - (mod >> 1));
memset(dest + (*n) + (mod - (mod >> 1)), 1, mod >> 1); memset(dest + (*n) + (mod - (mod >> 1)), 1, mod >> 1);
*n += mod; *n += mod;
} }
}
} }
// prepare a waveform pattern in the buffer based on the ID given then // prepare a waveform pattern in the buffer based on the ID given then
@ -829,7 +824,7 @@ void CmdHIDsimTAG(uint32_t hi, uint32_t lo, int ledcontrol) {
// prepare a waveform pattern in the buffer based on the ID given then // prepare a waveform pattern in the buffer based on the ID given then
// simulate a FSK tag until the button is pressed // simulate a FSK tag until the button is pressed
// arg1 contains fcHigh and fcLow, arg2 contains STT marker and clock // arg1 contains fcHigh and fcLow, arg2 contains STT marker and clock
void CmdFSKsimTAG(uint16_t arg1, uint16_t arg2, size_t size, uint8_t *bits) { void CmdFSKsimTAG(uint16_t arg1, uint16_t arg2, size_t size, uint8_t *bits, int ledcontrol) {
FpgaDownloadAndGo(FPGA_BITSTREAM_LF); FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
// free eventually allocated BigBuf memory // free eventually allocated BigBuf memory
@ -838,7 +833,7 @@ void CmdFSKsimTAG(uint16_t arg1, uint16_t arg2, size_t size, uint8_t *bits) {
clear_trace(); clear_trace();
set_tracing(false); set_tracing(false);
int ledcontrol = 1, n = 0, i = 0; int n = 0, i = 0;
uint8_t fcHigh = arg1 >> 8; uint8_t fcHigh = arg1 >> 8;
uint8_t fcLow = arg1 & 0xFF; uint8_t fcLow = arg1 & 0xFF;
uint16_t modCnt = 0; uint16_t modCnt = 0;
@ -906,11 +901,11 @@ static void stAskSimBit(int *n, uint8_t clock) {
} }
// args clock, ask/man or askraw, invert, transmission separator // args clock, ask/man or askraw, invert, transmission separator
void CmdASKsimTag(uint16_t arg1, uint16_t arg2, size_t size, uint8_t *BitStream) { void CmdASKsimTag(uint16_t arg1, uint16_t arg2, size_t size, uint8_t *BitStream, int ledcontrol) {
FpgaDownloadAndGo(FPGA_BITSTREAM_LF); FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
set_tracing(false); set_tracing(false);
int ledcontrol = 1, n = 0, i = 0; int n = 0, i = 0;
uint8_t clk = (arg1 >> 8) & 0xFF; uint8_t clk = (arg1 >> 8) & 0xFF;
uint8_t encoding = arg1 & 0xFF; uint8_t encoding = arg1 & 0xFF;
uint8_t separator = arg2 & 1; uint8_t separator = arg2 & 1;
@ -973,11 +968,11 @@ static void pskSimBit(uint8_t waveLen, int *n, uint8_t clk, uint8_t *curPhase, b
} }
// args clock, carrier, invert, // args clock, carrier, invert,
void CmdPSKsimTag(uint16_t arg1, uint16_t arg2, size_t size, uint8_t *BitStream) { void CmdPSKsimTag(uint16_t arg1, uint16_t arg2, size_t size, uint8_t *BitStream, int ledcontrol) {
FpgaDownloadAndGo(FPGA_BITSTREAM_LF); FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
set_tracing(false); set_tracing(false);
int ledcontrol = 1, n = 0, i = 0; int n = 0, i = 0;
uint8_t clk = arg1 >> 8; uint8_t clk = arg1 >> 8;
uint8_t carrier = arg1 & 0xFF; uint8_t carrier = arg1 & 0xFF;
uint8_t invert = arg2 & 0xFF; uint8_t invert = arg2 & 0xFF;
@ -1066,13 +1061,9 @@ void CmdHIDdemodFSK(int findone, uint32_t *high, uint32_t *low, int ledcontrol)
} }
} else { //if bit 38 is not set then 37 bit format is used } else { //if bit 38 is not set then 37 bit format is used
bitlen = 37; bitlen = 37;
fc = 0;
cardnum = 0;
if (bitlen == 37) {
cardnum = (lo >> 1) & 0x7FFFF; cardnum = (lo >> 1) & 0x7FFFF;
fc = ((hi & 0xF) << 12) | (lo >> 20); fc = ((hi & 0xF) << 12) | (lo >> 20);
} }
}
Dbprintf("TAG ID: %x%08x (%d) - Format Len: %dbit - FC: %d - Card: %d", Dbprintf("TAG ID: %x%08x (%d) - Format Len: %dbit - FC: %d - Card: %d",
hi, hi,
lo, lo,
@ -1382,8 +1373,6 @@ void T55xxResetRead(void) {
//clear buffer now so it does not interfere with timing later //clear buffer now so it does not interfere with timing later
BigBuf_Clear_keep_EM(); BigBuf_Clear_keep_EM();
StartTicks();
// Set up FPGA, 125kHz // Set up FPGA, 125kHz
LFSetupFPGAForADC(95, true); LFSetupFPGAForADC(95, true);
// make sure tag is fully powered up... // make sure tag is fully powered up...
@ -1416,8 +1405,6 @@ void T55xxWriteBlockExt(uint32_t Data, uint8_t Block, uint32_t Pwd, uint8_t arg)
bool testMode = arg & 0x4; bool testMode = arg & 0x4;
uint32_t i = 0; uint32_t i = 0;
StartTicks();
// Set up FPGA, 125kHz // Set up FPGA, 125kHz
LFSetupFPGAForADC(95, true); LFSetupFPGAForADC(95, true);
@ -1513,8 +1500,6 @@ void T55xxReadBlock(uint16_t arg0, uint8_t Block, uint32_t Pwd) {
//make sure block is at max 7 //make sure block is at max 7
Block &= 0x7; Block &= 0x7;
StartTicks();
// Set up FPGA, 125kHz to power up the tag // Set up FPGA, 125kHz to power up the tag
LFSetupFPGAForADC(95, true); LFSetupFPGAForADC(95, true);
// make sure tag is fully powered up... // make sure tag is fully powered up...
@ -1591,8 +1576,6 @@ void T55xx_ChkPwds() {
uint32_t candidate = 0; uint32_t candidate = 0;
#ifdef WITH_FLASH #ifdef WITH_FLASH
bool use_flashmem = true;
if (use_flashmem) {
BigBuf_Clear_EM(); BigBuf_Clear_EM();
uint16_t isok = 0; uint16_t isok = 0;
uint8_t counter[2] = {0x00, 0x00}; uint8_t counter[2] = {0x00, 0x00};
@ -1602,7 +1585,7 @@ void T55xx_ChkPwds() {
pwdCount = counter[1] << 8 | counter[0]; pwdCount = counter[1] << 8 | counter[0];
if (pwdCount == 0 && pwdCount == 0xFFFF) if (pwdCount == 0 || pwdCount == 0xFFFF)
goto OUT; goto OUT;
isok = Flash_ReadData(DEFAULT_T55XX_KEYS_OFFSET + 2, pwds, pwdCount * 4); isok = Flash_ReadData(DEFAULT_T55XX_KEYS_OFFSET + 2, pwds, pwdCount * 4);
@ -1610,7 +1593,6 @@ void T55xx_ChkPwds() {
goto OUT; goto OUT;
Dbprintf("[=] Password dictionary count %d ", pwdCount); Dbprintf("[=] Password dictionary count %d ", pwdCount);
}
#endif #endif
uint32_t pwd = 0, curr = 0, prev = 0; uint32_t pwd = 0, curr = 0, prev = 0;
@ -1661,8 +1643,6 @@ void T55xxWakeUp(uint32_t Pwd) {
LED_B_ON(); LED_B_ON();
uint32_t i = 0; uint32_t i = 0;
StartTicks();
// Set up FPGA, 125kHz // Set up FPGA, 125kHz
LFSetupFPGAForADC(95, true); LFSetupFPGAForADC(95, true);
// make sure tag is fully powered up... // make sure tag is fully powered up...

View file

@ -29,7 +29,7 @@ void printConfig() {
/** /**
* Called from the USB-handler to set the sampling configuration * Called from the USB-handler to set the sampling configuration
* The sampling config is used for std reading and snooping. * The sampling config is used for std reading and sniffing.
* *
* Other functions may read samples and ignore the sampling config, * Other functions may read samples and ignore the sampling config,
* such as functions to read the UID from a prox tag or similar. * such as functions to read the UID from a prox tag or similar.
@ -253,10 +253,10 @@ uint32_t SampleLF(bool printCfg, int sample_size) {
return ReadLF(true, printCfg, sample_size); return ReadLF(true, printCfg, sample_size);
} }
/** /**
* Initializes the FPGA for snoop-mode (field off), and acquires the samples. * Initializes the FPGA for sniffer-mode (field off), and acquires the samples.
* @return number of bits sampled * @return number of bits sampled
**/ **/
uint32_t SnoopLF() { uint32_t SniffLF() {
BigBuf_Clear_ext(false); BigBuf_Clear_ext(false);
return ReadLF(false, true, 0); return ReadLF(false, true, 0);
} }
@ -427,12 +427,10 @@ uint32_t doCotagAcquisitionManchester() {
if (sample > COTAG_ONE_THRESHOLD) { if (sample > COTAG_ONE_THRESHOLD) {
prev = curr; prev = curr;
curr = 1; curr = 1;
} } else if (sample < COTAG_ZERO_THRESHOLD) {
else if ( sample < COTAG_ZERO_THRESHOLD) {
prev = curr; prev = curr;
curr = 0; curr = 0;
} } else {
else {
curr = prev; curr = prev;
} }

View file

@ -30,10 +30,10 @@ void doT55x7Acquisition(size_t sample_size);
uint32_t SampleLF(bool silent, int sample_size); uint32_t SampleLF(bool silent, int sample_size);
/** /**
* Initializes the FPGA for snoop-mode (field off), and acquires the samples. * Initializes the FPGA for sniff-mode (field off), and acquires the samples.
* @return number of bits sampled * @return number of bits sampled
**/ **/
uint32_t SnoopLF(); uint32_t SniffLF();
// adds sample size to default options // adds sample size to default options
uint32_t DoPartialAcquisition(int trigger_threshold, bool silent, int sample_size, uint32_t cancel_after); uint32_t DoPartialAcquisition(int trigger_threshold, bool silent, int sample_size, uint32_t cancel_after);
@ -67,7 +67,7 @@ void LFSetupFPGAForADC(int divisor, bool lf_field);
/** /**
* Called from the USB-handler to set the sampling configuration * Called from the USB-handler to set the sampling configuration
* The sampling config is used for std reading and snooping. * The sampling config is used for std reading and sniffing.
* *
* Other functions may read samples and ignore the sampling config, * Other functions may read samples and ignore the sampling config,
* such as functions to read the UID from a prox tag or similar. * such as functions to read the UID from a prox tag or similar.

View file

@ -46,8 +46,8 @@ void MifareReadBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
ui64Key = bytes_to_num(datain, 6); ui64Key = bytes_to_num(datain, 6);
// variables // variables
byte_t isOK = 0; uint8_t isOK = 0;
byte_t dataoutbuf[16] = {0x00}; uint8_t dataoutbuf[16] = {0x00};
uint8_t uid[10] = {0x00}; uint8_t uid[10] = {0x00};
uint32_t cuid = 0; uint32_t cuid = 0;
struct Crypto1State mpcs = {0, 0}; struct Crypto1State mpcs = {0, 0};
@ -137,7 +137,7 @@ void MifareUC_Auth(uint8_t arg0, uint8_t *keybytes) {
// datain = PWD bytes, // datain = PWD bytes,
void MifareUReadBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain) { void MifareUReadBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain) {
uint8_t blockNo = arg0; uint8_t blockNo = arg0;
byte_t dataout[16] = {0x00}; uint8_t dataout[16] = {0x00};
bool useKey = (arg1 == 1); //UL_C bool useKey = (arg1 == 1); //UL_C
bool usePwd = (arg1 == 2); //UL_EV1/NTAG bool usePwd = (arg1 == 2); //UL_EV1/NTAG
@ -206,8 +206,8 @@ void MifareReadSector(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
ui64Key = bytes_to_num(datain, 6); ui64Key = bytes_to_num(datain, 6);
// variables // variables
byte_t isOK = 0; uint8_t isOK = 0;
byte_t dataoutbuf[16 * 16]; uint8_t dataoutbuf[16 * 16];
uint8_t uid[10] = {0x00}; uint8_t uid[10] = {0x00};
uint32_t cuid = 0; uint32_t cuid = 0;
struct Crypto1State mpcs = {0, 0}; struct Crypto1State mpcs = {0, 0};
@ -368,13 +368,13 @@ void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
uint8_t blockNo = arg0; uint8_t blockNo = arg0;
uint8_t keyType = arg1; uint8_t keyType = arg1;
uint64_t ui64Key = 0; uint64_t ui64Key = 0;
byte_t blockdata[16] = {0x00}; uint8_t blockdata[16] = {0x00};
ui64Key = bytes_to_num(datain, 6); ui64Key = bytes_to_num(datain, 6);
memcpy(blockdata, datain + 10, 16); memcpy(blockdata, datain + 10, 16);
// variables // variables
byte_t isOK = 0; uint8_t isOK = 0;
uint8_t uid[10] = {0x00}; uint8_t uid[10] = {0x00};
uint32_t cuid = 0; uint32_t cuid = 0;
struct Crypto1State mpcs = {0, 0}; struct Crypto1State mpcs = {0, 0};
@ -430,7 +430,7 @@ void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
void MifareUWriteBlockCompat(uint8_t arg0, uint8_t *datain) void MifareUWriteBlockCompat(uint8_t arg0, uint8_t *datain)
{ {
uint8_t blockNo = arg0; uint8_t blockNo = arg0;
byte_t blockdata[16] = {0x00}; uint8_t blockdata[16] = {0x00};
memcpy(blockdata, datain, 16); memcpy(blockdata, datain, 16);
@ -477,7 +477,7 @@ void MifareUWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain) {
uint8_t blockNo = arg0; uint8_t blockNo = arg0;
bool useKey = (arg1 == 1); //UL_C bool useKey = (arg1 == 1); //UL_C
bool usePwd = (arg1 == 2); //UL_EV1/NTAG bool usePwd = (arg1 == 2); //UL_EV1/NTAG
byte_t blockdata[4] = {0x00}; uint8_t blockdata[4] = {0x00};
memcpy(blockdata, datain, 4); memcpy(blockdata, datain, 4);
@ -539,7 +539,7 @@ void MifareUWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain) {
void MifareUSetPwd(uint8_t arg0, uint8_t *datain) { void MifareUSetPwd(uint8_t arg0, uint8_t *datain) {
uint8_t pwd[16] = {0x00}; uint8_t pwd[16] = {0x00};
byte_t blockdata[4] = {0x00}; uint8_t blockdata[4] = {0x00};
memcpy(pwd, datain, 16); memcpy(pwd, datain, 16);
@ -1247,7 +1247,7 @@ void MifareChkKeys_fast(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *da
keyCount = size[1] << 8 | size[0]; keyCount = size[1] << 8 | size[0];
if (keyCount == 0 && keyCount == 0xFFFF) if (keyCount == 0 || keyCount == 0xFFFF)
goto OUT; goto OUT;
datain = BigBuf_malloc(keyCount * 6); datain = BigBuf_malloc(keyCount * 6);
@ -1630,7 +1630,7 @@ void MifareEMemSet(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain)
void MifareEMemGet(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain) { void MifareEMemGet(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain) {
FpgaDownloadAndGo(FPGA_BITSTREAM_HF); FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
byte_t buf[USB_CMD_DATA_SIZE] = {0x00}; uint8_t buf[USB_CMD_DATA_SIZE] = {0x00};
emlGetMem(buf, arg0, arg1); // data, block num, blocks count (max 4) emlGetMem(buf, arg0, arg1); // data, block num, blocks count (max 4)
LED_B_ON(); LED_B_ON();
@ -1652,8 +1652,8 @@ void MifareECardLoad(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai
pcs = &mpcs; pcs = &mpcs;
// variables // variables
byte_t dataoutbuf[16] = {0x00}; uint8_t dataoutbuf[16] = {0x00};
byte_t dataoutbuf2[16] = {0x00}; uint8_t dataoutbuf2[16] = {0x00};
uint8_t uid[10] = {0x00}; uint8_t uid[10] = {0x00};
LED_A_ON(); LED_A_ON();
@ -1933,6 +1933,11 @@ void MifareCIdent() {
uint8_t isGen = 0; uint8_t isGen = 0;
uint8_t rec[1] = {0x00}; uint8_t rec[1] = {0x00};
uint8_t recpar[1] = {0x00}; uint8_t recpar[1] = {0x00};
uint8_t rats[4] = { ISO14443A_CMD_RATS, 0x80, 0x31, 0x73 };
uint8_t *par = BigBuf_malloc(MAX_PARITY_SIZE);
uint8_t *buf = BigBuf_malloc(USB_CMD_DATA_SIZE);
uint8_t *uid = BigBuf_malloc(10);
uint32_t cuid = 0;
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
@ -1951,32 +1956,29 @@ void MifareCIdent() {
goto OUT; goto OUT;
TEST2: TEST2:
; // reset card
/* FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
// Generation 2 test SpinDelay(100);
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
// halt previous. int res = iso14443a_select_card(uid, NULL, &cuid, true, 0, true);
mifare_classic_halt(NULL, 0); if ( res == 2 ) {
ReaderTransmit(rats, sizeof(rats), NULL);
//select res = ReaderReceive(buf, par);
if (!iso14443a_select_card(NULL, NULL, NULL, true, 0, true)) { if (memcmp(buf, "\x09\x78\x00\x91\x02\xDA\xBC\x19\x10\xF0\x05", 11) == 0) {
goto OUT;
};
// MIFARE_CLASSIC_WRITEBLOCK 0xA0
// ACK 0x0a
uint16_t len = mifare_sendcmd_short(null, 1, 0xA0, 0, rec, recpar, NULL);
if ((len != 1) || (rec[0] != 0x0A)) {
isGen = GEN_2; isGen = GEN_2;
goto OUT;
}
if (memcmp(buf, "\x0D\x78\x00\x71\x02\x88\x49\xA1\x30\x20\x15\x06\x08\x56\x3D", 15) == 0) {
isGen = GEN_2;
}
}; };
*/
OUT: OUT:
;
// removed the if, since some magic tags misbehavies and send an answer to it.
mifare_classic_halt_ex(NULL);
cmd_send(CMD_ACK, isGen, 0, 0, 0, 0); cmd_send(CMD_ACK, isGen, 0, 0, 0, 0);
// turns off // turns off
OnSuccessMagic(); OnSuccessMagic();
BigBuf_free();
} }
void OnSuccessMagic() { void OnSuccessMagic() {
@ -2051,7 +2053,7 @@ void MifareSetMod(uint8_t mod, uint8_t *key) {
// DESFIRE // DESFIRE
// //
void Mifare_DES_Auth1(uint8_t arg0, uint8_t *datain) { void Mifare_DES_Auth1(uint8_t arg0, uint8_t *datain) {
byte_t dataout[12] = {0x00}; uint8_t dataout[12] = {0x00};
uint8_t uid[10] = {0x00}; uint8_t uid[10] = {0x00};
uint32_t cuid = 0; uint32_t cuid = 0;
@ -2079,8 +2081,8 @@ void Mifare_DES_Auth1(uint8_t arg0, uint8_t *datain) {
void Mifare_DES_Auth2(uint32_t arg0, uint8_t *datain) { void Mifare_DES_Auth2(uint32_t arg0, uint8_t *datain) {
uint32_t cuid = arg0; uint32_t cuid = arg0;
uint8_t key[16] = {0x00}; uint8_t key[16] = {0x00};
byte_t dataout[12] = {0x00}; uint8_t dataout[12] = {0x00};
byte_t isOK = 0; uint8_t isOK = 0;
memcpy(key, datain, 16); memcpy(key, datain, 16);

View file

@ -384,7 +384,7 @@ int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t bl
uint16_t len = 0; uint16_t len = 0;
uint32_t pos = 0; uint32_t pos = 0;
uint8_t par[3] = {0x00, 0x00, 0x00}; // enough for 18 Bytes to send uint8_t par[3] = {0x00, 0x00, 0x00}; // enough for 18 Bytes to send
byte_t res = 0; uint8_t res = 0;
uint8_t d_block[18], d_block_enc[18]; uint8_t d_block[18], d_block_enc[18];
uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0x00}; uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0x00};

View file

@ -12,25 +12,19 @@ size_t DemodPCF7931(uint8_t **outBlocks) {
if (GraphTraceLen > 18000) if (GraphTraceLen > 18000)
GraphTraceLen = 18000; GraphTraceLen = 18000;
int i, j, lastval, bitidx, half_switch; int i = 2, j, lastval, bitidx, half_switch;
int clock = 64; int clock = 64;
int tolerance = clock / 8; int tolerance = clock / 8;
int pmc, block_done; int pmc, block_done;
int lc, warnings = 0; int lc, warnings = 0;
size_t num_blocks = 0; size_t num_blocks = 0;
int lmin = 128, lmax = 128; int lmin = 64, lmax = 192;
uint8_t dir; uint8_t dir;
//clear read buffer
BigBuf_Clear_keep_EM();
BigBuf_Clear_keep_EM();
LFSetupFPGAForADC(95, true); LFSetupFPGAForADC(95, true);
DoAcquisition_default(0, true); DoAcquisition_default(0, true);
lmin = 64;
lmax = 192;
i = 2;
/* Find first local max/min */ /* Find first local max/min */
if (dest[1] > dest[0]) { if (dest[1] > dest[0]) {
while (i < GraphTraceLen) { while (i < GraphTraceLen) {
@ -142,10 +136,16 @@ bool IsBlock0PCF7931(uint8_t *block) {
bool IsBlock1PCF7931(uint8_t *block) { bool IsBlock1PCF7931(uint8_t *block) {
// assuming all RFU bits are set to 0 // assuming all RFU bits are set to 0
if (block[10] == 0 && block[11] == 0 && block[12] == 0 && block[13] == 0) if (block[10] == 0
if ((block[14] & 0x7f) <= 9 && block[15] <= 9) && block[11] == 0
return true; && block[12] == 0
&& block[13] == 0) {
if ( (block[14] & 0x7f) <= 9
&& block[15] <= 9) {
return true;
}
}
return false; return false;
} }
@ -153,7 +153,6 @@ void ReadPCF7931() {
int found_blocks = 0; // successfully read blocks int found_blocks = 0; // successfully read blocks
int max_blocks = 8; // readable blocks int max_blocks = 8; // readable blocks
uint8_t memory_blocks[8][17]; // PCF content uint8_t memory_blocks[8][17]; // PCF content
uint8_t single_blocks[8][17]; // PFC blocks with unknown position uint8_t single_blocks[8][17]; // PFC blocks with unknown position
int single_blocks_cnt = 0; int single_blocks_cnt = 0;

View file

@ -16,7 +16,7 @@
#include "string.h" #include "string.h"
int kvsprintf(const char *format, void *arg, int radix, va_list ap) __attribute__((format(printf, 1, 0))); int kvsprintf(const char *format, void *arg, int radix, va_list ap) __attribute__((format(printf, 1, 0)));
int vsprintf(char *str, const char *format, va_list ap) __attribute__((format(printf, 2, 0))); int vsprintf(char *dest, const char *fmt, va_list ap) __attribute__((format(printf, 2, 0)));
int sprintf(char *str, const char *format, ...) __attribute__((format(printf, 2, 3))); int sprintf(char *dest, const char *fmt, ...) __attribute__((format(printf, 2, 3)));
#endif #endif

View file

@ -17,7 +17,18 @@
#include "BigBuf.h" #include "BigBuf.h"
#include "ticks.h" #include "ticks.h"
// Basic macros
#ifndef SHORT_COIL
#define SHORT_COIL() LOW(GPIO_SSC_DOUT)
#endif
#ifndef OPEN_COIL
#define OPEN_COIL() HIGH(GPIO_SSC_DOUT)
#endif
#ifndef BYTEx
#define BYTEx(x, n) (((x) >> (n * 8)) & 0xff ) #define BYTEx(x, n) (((x) >> (n * 8)) & 0xff )
#endif
#define LED_RED 1 #define LED_RED 1
#define LED_ORANGE 2 #define LED_ORANGE 2
@ -43,6 +54,34 @@
# define NTIME(n) for (int _index = 0; _index < n; _index++) # define NTIME(n) for (int _index = 0; _index < n; _index++)
#endif #endif
#ifndef REV8
#define REV8(x) ((((x)>>7)&1)+((((x)>>6)&1)<<1)+((((x)>>5)&1)<<2)+((((x)>>4)&1)<<3)+((((x)>>3)&1)<<4)+((((x)>>2)&1)<<5)+((((x)>>1)&1)<<6)+(((x)&1)<<7))
#endif
#ifndef REV16
#define REV16(x) (REV8(x) + (REV8 (x >> 8) << 8))
#endif
#ifndef REV32
#define REV32(x) (REV16(x) + (REV16(x >> 16) << 16))
#endif
#ifndef REV64
#define REV64(x) (REV32(x) + (REV32(x >> 32) << 32))
#endif
#ifndef BIT32
#define BIT32(x,n) ((((x)[(n)>>5])>>((n)))&1)
#endif
#ifndef INV32
#define INV32(x,i,n) ((x)[(i)>>5]^=((uint32_t)(n))<<((i)&31))
#endif
#ifndef ROTL64
#define ROTL64(x, n) ((((uint64_t)(x))<<((n)&63))+(((uint64_t)(x))>>((0-(n))&63)))
#endif
size_t nbytes(size_t nbits); size_t nbytes(size_t nbits);
extern uint32_t reflect(uint32_t v, int b); // used in crc.c ... extern uint32_t reflect(uint32_t v, int b); // used in crc.c ...

View file

@ -16,11 +16,11 @@ extern char _bootrom_start, _bootrom_end, _flash_start, _flash_end;
extern uint32_t _osimage_entry; extern uint32_t _osimage_entry;
void DbpString(char *str) { void DbpString(char *str) {
byte_t len = 0; uint8_t len = 0;
while (str[len] != 0x00) while (str[len] != 0x00)
len++; len++;
cmd_send(CMD_DEBUG_PRINT_STRING, len, 0, 0, (byte_t *)str, len); cmd_send(CMD_DEBUG_PRINT_STRING, len, 0, 0, (uint8_t *)str, len);
} }
static void ConfigClocks(void) { static void ConfigClocks(void) {

View file

@ -347,28 +347,28 @@ cbor_build:
print-%: ; @echo $* = $($*) print-%: ; @echo $* = $($*)
$(OBJDIR)/%_NOSIMD.o : %.c $(OBJDIR)/%_NOSIMD.d $(OBJDIR)/%_NOSIMD.o : %.c $(OBJDIR)/%_NOSIMD.d
$(CC) $(DEPFLAGS) $(CFLAGS) $(HARD_SWITCH_NOSIMD) -c -o $@ $< $(CC) $(DEPFLAGS:%.Td=%_NOSIMD.Td) $(CFLAGS) $(HARD_SWITCH_NOSIMD) -c -o $@ $<
$(POSTCOMPILE:%.d=%_NOSIMD.d) $(MV) -f $(OBJDIR)/$*_NOSIMD.Td $(OBJDIR)/$*_NOSIMD.d
$(OBJDIR)/%_MMX.o : %.c $(OBJDIR)/%_MMX.d $(OBJDIR)/%_MMX.o : %.c $(OBJDIR)/%_MMX.d
$(CC) $(DEPFLAGS) $(CFLAGS) $(HARD_SWITCH_MMX) -c -o $@ $< $(CC) $(DEPFLAGS:%.Td=%_MMX.Td) $(CFLAGS) $(HARD_SWITCH_MMX) -c -o $@ $<
$(POSTCOMPILE:%.d=%_MMX.d) $(MV) -f $(OBJDIR)/$*_MMX.Td $(OBJDIR)/$*_MMX.d
$(OBJDIR)/%_SSE2.o : %.c $(OBJDIR)/%_SSE2.d $(OBJDIR)/%_SSE2.o : %.c $(OBJDIR)/%_SSE2.d
$(CC) $(DEPFLAGS) $(CFLAGS) $(HARD_SWITCH_SSE2) -c -o $@ $< $(CC) $(DEPFLAGS:%.Td=%_SSE2.Td) $(CFLAGS) $(HARD_SWITCH_SSE2) -c -o $@ $<
$(POSTCOMPILE:%.d=%_SSE2.d) $(MV) -f $(OBJDIR)/$*_SSE2.Td $(OBJDIR)/$*_SSE2.d
$(OBJDIR)/%_AVX.o : %.c $(OBJDIR)/%_AVX.d $(OBJDIR)/%_AVX.o : %.c $(OBJDIR)/%_AVX.d
$(CC) $(DEPFLAGS) $(CFLAGS) $(HARD_SWITCH_AVX) -c -o $@ $< $(CC) $(DEPFLAGS:%.Td=%_AVX.Td) $(CFLAGS) $(HARD_SWITCH_AVX) -c -o $@ $<
$(POSTCOMPILE:%.d=%_AVX.d) $(MV) -f $(OBJDIR)/$*_AVX.Td $(OBJDIR)/$*_AVX.d
$(OBJDIR)/%_AVX2.o : %.c $(OBJDIR)/%_AVX2.d $(OBJDIR)/%_AVX2.o : %.c $(OBJDIR)/%_AVX2.d
$(CC) $(DEPFLAGS) $(CFLAGS) $(HARD_SWITCH_AVX2) -c -o $@ $< $(CC) $(DEPFLAGS:%.Td=%_AVX2.Td) $(CFLAGS) $(HARD_SWITCH_AVX2) -c -o $@ $<
$(POSTCOMPILE:%.d=%_AVX2.d) $(MV) -f $(OBJDIR)/$*_AVX2.Td $(OBJDIR)/$*_AVX2.d
$(OBJDIR)/%_AVX512.o : %.c $(OBJDIR)/%_AVX512.d $(OBJDIR)/%_AVX512.o : %.c $(OBJDIR)/%_AVX512.d
$(CC) $(DEPFLAGS) $(CFLAGS) $(HARD_SWITCH_AVX512) -c -o $@ $< $(CC) $(DEPFLAGS:%.Td=%_AVX512.Td) $(CFLAGS) $(HARD_SWITCH_AVX512) -c -o $@ $<
$(POSTCOMPILE:%.d=%_AVX512.d) $(MV) -f $(OBJDIR)/$*_AVX512.Td $(OBJDIR)/$*_AVX512.d
%.o: %.c %.o: %.c
$(OBJDIR)/%.o : %.c $(OBJDIR)/%.d $(OBJDIR)/%.o : %.c $(OBJDIR)/%.d

View file

@ -8,7 +8,7 @@
#include <amiibo.h> #include <amiibo.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include "../loclass/fileutil.h" #include "../loclass/fileutils.h"
#define NTAG215_SIZE 540 #define NTAG215_SIZE 540

View file

@ -21,7 +21,7 @@ int main(int argc, char **argv) {
if (argc != 3 && argc != 4) { if (argc != 3 && argc != 4) {
printf("\n\tusage: cli <command 1> <command 2> [logfile (default cli.log)]\n"); printf("\n\tusage: cli <command 1> <command 2> [logfile (default cli.log)]\n");
printf("\n"); printf("\n");
printf("\texample: cli hi14asnoop hi14alist h14a.log\n"); printf("\texample: cli hf 14a sniff hf 14a list h14a.log\n");
printf("\n"); printf("\n");
return -1; return -1;
} }

View file

@ -876,15 +876,19 @@ int CmdAnalyseNuid(const char *Cmd) {
/* selftest1 UID 040D681AB52281 -> NUID 8F430FEF */ /* selftest1 UID 040D681AB52281 -> NUID 8F430FEF */
/* selftest2 UID 04183F09321B85 -> NUID 4F505D7D */ /* selftest2 UID 04183F09321B85 -> NUID 4F505D7D */
if (cmdp == 't') { if (cmdp == 't') {
memcpy(uid, "\x04\x0d\x68\x1a\xb5\x22\x81", 7); uint8_t uid_test1[] = {0x04, 0x0d, 0x68, 0x1a, 0xb5, 0x22, 0x81};
uint8_t nuid_test1[] = {0x8f, 0x43, 0x0f, 0xef};
uint8_t uid_test2[] = {0x04, 0x18, 0x3f, 0x09, 0x32, 0x1b, 0x85};
uint8_t nuid_test2[] = {0x4f, 0x50, 0x5d, 0x7d};
memcpy(uid, uid_test1, sizeof(uid));
generate4bNUID(uid, nuid); generate4bNUID(uid, nuid);
bool test1 = (0 == memcmp(nuid, "\x8f\x43\x0f\xef", 4)); bool test1 = (0 == memcmp(nuid, nuid_test1, sizeof(nuid)));
PrintAndLogEx(SUCCESS, "Selftest1 %s\n", test1 ? _GREEN_("OK") : _RED_("Fail")); PrintAndLogEx(SUCCESS, "Selftest1 %s\n", test1 ? _GREEN_("OK") : _RED_("Fail"));
memcpy(uid, "\x04\x18\x3f\x09\x32\x1b\x85", 7); memcpy(uid, uid_test2, sizeof(uid));
generate4bNUID(uid, nuid); generate4bNUID(uid, nuid);
bool test2 = (0 == memcmp(nuid, "\x4f\x50\x5d\x7d", 4)); bool test2 = (0 == memcmp(nuid, nuid_test2, sizeof(nuid)));
PrintAndLogEx(SUCCESS, "Selftest2 %s\n", test2 ? _GREEN_("OK") : _RED_("Fail")); PrintAndLogEx(SUCCESS, "Selftest2 %s\n", test2 ? _GREEN_("OK") : _RED_("Fail"));
return 0; return 0;
} }

View file

@ -93,10 +93,12 @@ int GetModels(char *Models[], int *count, uint8_t *width) {
PrintAndLogEx(WARNING, "out of memory?"); PrintAndLogEx(WARNING, "out of memory?");
return 0; return 0;
} }
if ( model.name != NULL ) {
memcpy(tmp, model.name, size); memcpy(tmp, model.name, size);
Models[mode] = tmp; Models[mode] = tmp;
width[mode] = plen(model.spoly); width[mode] = plen(model.spoly);
} }
}
mfree(&model); mfree(&model);
} else { //reveng -s } else { //reveng -s
@ -401,7 +403,7 @@ char *SwapEndianStr(const char *inStr, const size_t len, const uint8_t blockSize
// takes hex string in and searches for a matching result (hex string must include checksum) // takes hex string in and searches for a matching result (hex string must include checksum)
int CmdrevengSearch(const char *Cmd) { int CmdrevengSearch(const char *Cmd) {
#define NMODELS 105 #define NMODELS 106
char inHexStr[100] = {0x00}; char inHexStr[100] = {0x00};
int dataLen = param_getstr(Cmd, 0, inHexStr, sizeof(inHexStr)); int dataLen = param_getstr(Cmd, 0, inHexStr, sizeof(inHexStr));

View file

@ -366,7 +366,8 @@ int CmdSetDebugMode(const char *Cmd) {
} }
//by marshmellow //by marshmellow
// max output to 512 bits if we have more - should be plenty // max output to 512 bits if we have more
// doesn't take inconsideration where the demod offset or bitlen found.
void printDemodBuff(void) { void printDemodBuff(void) {
int len = DemodBufferLen; int len = DemodBufferLen;
if (len < 1) { if (len < 1) {
@ -375,7 +376,7 @@ void printDemodBuff(void) {
} }
if (len > 512) len = 512; if (len > 512) len = 512;
PrintAndLogEx(NORMAL, "%s", sprint_bin_break(DemodBuffer, len, 16)); PrintAndLogEx(NORMAL, "%s", sprint_bin_break(DemodBuffer, len, 32));
} }
int CmdPrintDemodBuff(const char *Cmd) { int CmdPrintDemodBuff(const char *Cmd) {
@ -417,18 +418,16 @@ int CmdPrintDemodBuff(const char *Cmd) {
return 0; return 0;
} }
length = (length > (DemodBufferLen - offset)) ? DemodBufferLen - offset : length; length = (length > (DemodBufferLen - offset)) ? DemodBufferLen - offset : length;
int numBits = (length) & 0x00FFC; //make sure we don't exceed our string
if (hexMode) { if (hexMode) {
char *buf = (char *)(DemodBuffer + offset); char *buf = (char *)(DemodBuffer + offset);
numBits = (numBits > sizeof(hex)) ? sizeof(hex) : numBits; int numBits = binarraytohex(hex, sizeof(hex), buf, length);
numBits = binarraytohex(hex, buf, numBits);
if (numBits == 0) { if (numBits == 0) {
return 0; return 0;
} }
PrintAndLogEx(NORMAL, "DemodBuffer: %s", hex); PrintAndLogEx(NORMAL, "DemodBuffer: %s", hex);
} else { } else {
PrintAndLogEx(NORMAL, "DemodBuffer:\n%s", sprint_bin_break(DemodBuffer + offset, numBits, 16)); PrintAndLogEx(NORMAL, "DemodBuffer:\n%s", sprint_bin_break(DemodBuffer + offset, length, 32));
} }
return 1; return 1;
} }
@ -475,29 +474,35 @@ int ASKDemod_ext(const char *Cmd, bool verbose, bool emSearch, uint8_t askType,
size_t BitLen = getFromGraphBuf(bits); size_t BitLen = getFromGraphBuf(bits);
PrintAndLogEx(DEBUG, "DEBUG: (ASKDemod_ext) Bitlen from grphbuff: %d", BitLen); PrintAndLogEx(DEBUG, "DEBUG: (ASKDemod_ext) #samples from graphbuff: %d", BitLen);
if (BitLen < 255) return 0; if (BitLen < 255) return 0;
if (maxLen < BitLen && maxLen != 0) BitLen = maxLen; if (maxLen < BitLen && maxLen != 0) BitLen = maxLen;
int foundclk = 0; int foundclk = 0;
//amp before ST check
if (amp == 'a')
askAmp(bits, BitLen);
bool st = false; //amplify signal before ST check
if (amp == 'a') {
askAmp(bits, BitLen);
}
size_t ststart = 0, stend = 0; size_t ststart = 0, stend = 0;
if (*stCheck) // if (*stCheck)
st = DetectST(bits, &BitLen, &foundclk, &ststart, &stend); bool st = DetectST(bits, &BitLen, &foundclk, &ststart, &stend);
if ( clk == 0 ) {
if ( foundclk == 32 || foundclk == 64 ) {
clk = foundclk;
}
}
if (st) { if (st) {
*stCheck = st; *stCheck = st;
clk = (clk == 0) ? foundclk : clk;
CursorCPos = ststart; CursorCPos = ststart;
CursorDPos = stend; CursorDPos = stend;
if (verbose || g_debugMode) if (verbose)
PrintAndLogEx(NORMAL, "Found Sequence Terminator - First one is shown by orange and blue graph markers"); PrintAndLogEx(DEBUG, "Found Sequence Terminator - First one is shown by orange / blue graph markers");
} }
int startIdx = 0; int startIdx = 0;
@ -513,20 +518,20 @@ int ASKDemod_ext(const char *Cmd, bool verbose, bool emSearch, uint8_t askType,
return 0; return 0;
} }
if (verbose || g_debugMode) PrintAndLogEx(DEBUG, "DEBUG: (ASKDemod_ext) Using clock:%d, invert:%d, bits found:%d", clk, invert, BitLen); if (verbose) PrintAndLogEx(DEBUG, "DEBUG: (ASKDemod_ext) Using clock:%d, invert:%d, bits found:%d", clk, invert, BitLen);
//output //output
setDemodBuf(bits, BitLen, 0); setDemodBuf(bits, BitLen, 0);
setClockGrid(clk, startIdx); setClockGrid(clk, startIdx);
if (verbose || g_debugMode) { if (verbose) {
if (errCnt > 0) if (errCnt > 0)
PrintAndLogEx(NORMAL, "# Errors during Demoding (shown as 7 in bit stream): %d", errCnt); PrintAndLogEx(DEBUG, "# Errors during Demoding (shown as 7 in bit stream): %d", errCnt);
if (askType) if (askType)
PrintAndLogEx(NORMAL, "ASK/Manchester - Clock: %d - Decoded bitstream:", clk); PrintAndLogEx(DEBUG, "ASK/Manchester - Clock: %d - Decoded bitstream:", clk);
else else
PrintAndLogEx(NORMAL, "ASK/Raw - Clock: %d - Decoded bitstream:", clk); PrintAndLogEx(DEBUG, "ASK/Raw - Clock: %d - Decoded bitstream:", clk);
// Now output the bitstream to the scrollback by line of 16 bits
printDemodBuff(); printDemodBuff();
} }
uint64_t lo = 0; uint64_t lo = 0;
@ -595,7 +600,7 @@ int Cmdmandecoderaw(const char *Cmd) {
} }
PrintAndLogEx(NORMAL, "Manchester Decoded - # errors:%d - data:", errCnt); PrintAndLogEx(NORMAL, "Manchester Decoded - # errors:%d - data:", errCnt);
PrintAndLogEx(NORMAL, "%s", sprint_bin_break(bits, size, 16)); PrintAndLogEx(NORMAL, "%s", sprint_bin_break(bits, size, 32));
if (errCnt == 0) { if (errCnt == 0) {
uint64_t id = 0; uint64_t id = 0;
@ -610,21 +615,24 @@ int Cmdmandecoderaw(const char *Cmd) {
return 1; return 1;
} }
//by marshmellow /*
//biphase decode * @author marshmellow
//take 01 or 10 = 0 and 11 or 00 = 1 * biphase decode
//takes 2 arguments "offset" default = 0 if 1 it will shift the decode by one bit * decodes 01 or 10 -> ZERO
// and "invert" default = 0 if 1 it will invert output * 11 or 00 -> ONE
// the argument offset allows us to manually shift if the output is incorrect - [EDIT: now auto detects] * param offset adjust start position
* param invert invert output
* param masxErr maximum tolerated errors
*/
int CmdBiphaseDecodeRaw(const char *Cmd) { int CmdBiphaseDecodeRaw(const char *Cmd) {
size_t size = 0; size_t size = 0;
int offset = 0, invert = 0, maxErr = 20, errCnt = 0; int offset = 0, invert = 0, maxErr = 20, errCnt = 0;
char cmdp = tolower(param_getchar(Cmd, 0)); char cmdp = tolower(param_getchar(Cmd, 0));
if (strlen(Cmd) > 3 || cmdp == 'h') return usage_data_biphaserawdecode(); if (strlen(Cmd) > 5 || cmdp == 'h') return usage_data_biphaserawdecode();
sscanf(Cmd, "%i %i %i", &offset, &invert, &maxErr); sscanf(Cmd, "%i %i %i", &offset, &invert, &maxErr);
if (DemodBufferLen == 0) { if (DemodBufferLen == 0) {
PrintAndLogEx(NORMAL, "DemodBuffer Empty - run 'data rawdemod ar' first"); PrintAndLogEx(WARNING, "DemodBuffer Empty - run " _YELLOW_("'data rawdemod ar'")" first");
return 0; return 0;
} }
@ -643,10 +651,10 @@ int CmdBiphaseDecodeRaw(const char *Cmd) {
} }
if (errCnt > 0) if (errCnt > 0)
PrintAndLogEx(WARNING, "# Errors found during Demod (shown as 7 in bit stream): %d", errCnt); PrintAndLogEx(WARNING, "# Errors found during Demod (shown as " _YELLOW_("7")" in bit stream): %d", errCnt);
PrintAndLogEx(NORMAL, "Biphase Decoded using offset: %d - # invert:%d - data:", offset, invert); PrintAndLogEx(NORMAL, "Biphase Decoded using offset: %d - # invert:%d - data:", offset, invert);
PrintAndLogEx(NORMAL, "%s", sprint_bin_break(bits, size, 16)); PrintAndLogEx(NORMAL, "%s", sprint_bin_break(bits, size, 32));
//remove first bit from raw demod //remove first bit from raw demod
if (offset) if (offset)
@ -660,7 +668,7 @@ int CmdBiphaseDecodeRaw(const char *Cmd) {
// - ASK Demod then Biphase decode GraphBuffer samples // - ASK Demod then Biphase decode GraphBuffer samples
int ASKbiphaseDemod(const char *Cmd, bool verbose) { int ASKbiphaseDemod(const char *Cmd, bool verbose) {
//ask raw demod GraphBuffer first //ask raw demod GraphBuffer first
int offset = 0, clk = 0, invert = 0, maxErr = 0; int offset = 0, clk = 0, invert = 0, maxErr = 100;
sscanf(Cmd, "%i %i %i %i", &offset, &clk, &invert, &maxErr); sscanf(Cmd, "%i %i %i %i", &offset, &clk, &invert, &maxErr);
uint8_t BitStream[MAX_DEMOD_BUF_LEN]; uint8_t BitStream[MAX_DEMOD_BUF_LEN];
@ -716,7 +724,7 @@ int AutoCorrelate(const int *in, int *out, size_t len, int window, bool SaveGrph
// sanity check // sanity check
if (window > len) window = len; if (window > len) window = len;
if (verbose) PrintAndLogEx(INFO, "performing %d correlations", GraphTraceLen - window); if (verbose) PrintAndLogEx(INFO, "performing " _YELLOW_("%d")" correlations", GraphTraceLen - window);
//test //test
double autocv = 0.0; // Autocovariance value double autocv = 0.0; // Autocovariance value
@ -769,10 +777,11 @@ int AutoCorrelate(const int *in, int *out, size_t len, int window, bool SaveGrph
} }
int foo = ABS(hi - hi_1); int foo = ABS(hi - hi_1);
int bar = (int)((int)((hi + hi_1) / 2) * 0.03); int bar = (int)((int)((hi + hi_1) / 2) * 0.04);
if (verbose && foo < bar) { if (verbose && foo < bar) {
distance = idx_1 - idx; distance = idx_1 - idx;
PrintAndLogEx(SUCCESS, "possible 3% visible correlation %4d samples", distance); PrintAndLogEx(SUCCESS, "possible 4% visible correlation %4d samples", distance);
} else if (verbose && (correlation > 1)) { } else if (verbose && (correlation > 1)) {
PrintAndLogEx(SUCCESS, "possible correlation %4d samples", correlation); PrintAndLogEx(SUCCESS, "possible correlation %4d samples", correlation);
} else { } else {
@ -1069,7 +1078,7 @@ int FSKrawDemod(const char *Cmd, bool verbose) {
} }
return 1; return 1;
} else { } else {
if (g_debugMode) PrintAndLogEx(NORMAL, "no FSK data found"); PrintAndLogEx(DEBUG, "no FSK data found");
} }
return 0; return 0;
} }
@ -1089,7 +1098,9 @@ int CmdFSKrawdemod(const char *Cmd) {
//attempt to psk1 demod graph buffer //attempt to psk1 demod graph buffer
int PSKDemod(const char *Cmd, bool verbose) { int PSKDemod(const char *Cmd, bool verbose) {
int invert = 0, clk = 0, maxErr = 100; int invert = 0, clk = 0, maxErr = 100;
sscanf(Cmd, "%i %i %i", &clk, &invert, &maxErr); sscanf(Cmd, "%i %i %i", &clk, &invert, &maxErr);
if (clk == 1) { if (clk == 1) {
invert = 1; invert = 1;
clk = 0; clk = 0;
@ -1102,33 +1113,34 @@ int PSKDemod(const char *Cmd, bool verbose) {
if (getSignalProperties()->isnoise) if (getSignalProperties()->isnoise)
return 0; return 0;
uint8_t BitStream[MAX_GRAPH_TRACE_LEN] = {0}; uint8_t bits[MAX_GRAPH_TRACE_LEN] = {0};
size_t BitLen = getFromGraphBuf(BitStream); size_t bitlen = getFromGraphBuf(bits);
if (BitLen == 0) return 0; if (bitlen == 0)
int errCnt = 0; return 0;
int startIdx = 0; int startIdx = 0;
errCnt = pskRawDemod_ext(BitStream, &BitLen, &clk, &invert, &startIdx); int errCnt = pskRawDemod_ext(bits, &bitlen, &clk, &invert, &startIdx);
if (errCnt > maxErr) { if (errCnt > maxErr) {
if (g_debugMode || verbose) PrintAndLogEx(DEBUG, "DEBUG: (PSKdemod) Too many errors found, clk: %d, invert: %d, numbits: %d, errCnt: %d", clk, invert, BitLen, errCnt); if (g_debugMode || verbose) PrintAndLogEx(DEBUG, "DEBUG: (PSKdemod) Too many errors found, clk: %d, invert: %d, numbits: %d, errCnt: %d", clk, invert, bitlen, errCnt);
return 0; return 0;
} }
if (errCnt < 0 || BitLen < 16) { //throw away static - allow 1 and -1 (in case of threshold command first) if (errCnt < 0 || bitlen < 16) { //throw away static - allow 1 and -1 (in case of threshold command first)
if (g_debugMode || verbose) PrintAndLogEx(DEBUG, "DEBUG: (PSKdemod) no data found, clk: %d, invert: %d, numbits: %d, errCnt: %d", clk, invert, BitLen, errCnt); if (g_debugMode || verbose) PrintAndLogEx(DEBUG, "DEBUG: (PSKdemod) no data found, clk: %d, invert: %d, numbits: %d, errCnt: %d", clk, invert, bitlen, errCnt);
return 0; return 0;
} }
if (verbose || g_debugMode) { if (verbose || g_debugMode) {
PrintAndLogEx(DEBUG, "DEBUG: (PSKdemod) Using Clock:%d, invert:%d, Bits Found:%d", clk, invert, BitLen); PrintAndLogEx(DEBUG, "DEBUG: (PSKdemod) Using Clock:%d, invert:%d, Bits Found:%d", clk, invert, bitlen);
if (errCnt > 0) { if (errCnt > 0) {
PrintAndLogEx(DEBUG, "DEBUG: (PSKdemod) errors during Demoding (shown as 7 in bit stream): %d", errCnt); PrintAndLogEx(DEBUG, "DEBUG: (PSKdemod) errors during Demoding (shown as 7 in bit stream): %d", errCnt);
} }
} }
//prime demod buffer for output //prime demod buffer for output
setDemodBuf(BitStream, BitLen, 0); setDemodBuf(bits, bitlen, 0);
setClockGrid(clk, startIdx); setClockGrid(clk, startIdx);
return 1; return 1;
} }
int CmdPSKIdteck(const char *Cmd) { int CmdIdteckDemod(const char *Cmd) {
if (!PSKDemod("", false)) { if (!PSKDemod("", false)) {
PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck PSKDemod failed"); PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck PSKDemod failed");
@ -1308,6 +1320,9 @@ int CmdRawDemod(const char *Cmd) {
void setClockGrid(int clk, int offset) { void setClockGrid(int clk, int offset) {
g_DemodStartIdx = offset; g_DemodStartIdx = offset;
g_DemodClock = clk; g_DemodClock = clk;
if ( clk == 0 && offset == 0)
PrintAndLogEx(DEBUG, "DEBUG: (setClockGrid) clear settings");
else
PrintAndLogEx(DEBUG, "DEBUG: (setClockGrid) demodoffset %d, clk %d", offset, clk); PrintAndLogEx(DEBUG, "DEBUG: (setClockGrid) demodoffset %d, clk %d", offset, clk);
if (offset > clk) offset %= clk; if (offset > clk) offset %= clk;
@ -1607,7 +1622,6 @@ int CmdLoad(const char *Cmd) {
break; break;
} }
if (f)
fclose(f); fclose(f);
PrintAndLogEx(SUCCESS, "loaded %d samples", GraphTraceLen); PrintAndLogEx(SUCCESS, "loaded %d samples", GraphTraceLen);
@ -1865,11 +1879,9 @@ int Cmdhex2bin(const char *Cmd) {
else else
continue; continue;
//Uses printf instead of PrintAndLog since the latter //Uses printf instead of PrintAndLog since the latter adds linebreaks to each printout
// adds linebreaks to each printout - this way was more convenient since we don't have to
// allocate a string and write to that first...
for (int i = 0 ; i < 4 ; ++i) for (int i = 0 ; i < 4 ; ++i)
PrintAndLogEx(NORMAL, "%d", (x >> (3 - i)) & 1); printf("%d", (x >> (3 - i)) & 1);
} }
PrintAndLogEx(NORMAL, "\n"); PrintAndLogEx(NORMAL, "\n");
return 0; return 0;

View file

@ -54,7 +54,7 @@ int CmdDetectClockRate(const char *Cmd);
int CmdFSKrawdemod(const char *Cmd); int CmdFSKrawdemod(const char *Cmd);
int CmdPSK1rawDemod(const char *Cmd); int CmdPSK1rawDemod(const char *Cmd);
int CmdPSK2rawDemod(const char *Cmd); int CmdPSK2rawDemod(const char *Cmd);
int CmdPSKIdteck(const char *Cmd); int CmdIdteckDemod(const char *Cmd);
int CmdGrid(const char *Cmd); int CmdGrid(const char *Cmd);
int CmdGetBitStream(const char *Cmd); int CmdGetBitStream(const char *Cmd);
int CmdHexsamples(const char *Cmd); int CmdHexsamples(const char *Cmd);

View file

@ -245,7 +245,7 @@ int CmdFlashMemLoad(const char *Cmd) {
break; break;
default: default:
res = loadFile(filename, "bin", data, &datalen); res = loadFile(filename, "bin", data, FLASH_MEM_MAX_SIZE, &datalen);
//int res = loadFileEML( filename, "eml", data, &datalen); //int res = loadFileEML( filename, "eml", data, &datalen);
if (res) { if (res) {
free(data); free(data);
@ -260,7 +260,13 @@ int CmdFlashMemLoad(const char *Cmd) {
break; break;
} }
data = realloc(data, datalen); uint8_t *newdata = realloc(data, datalen);
if (newdata == NULL) {
free(data);
return 1;
} else {
data = newdata;
}
//Send to device //Send to device
uint32_t bytes_sent = 0; uint32_t bytes_sent = 0;

View file

@ -35,9 +35,9 @@ typedef enum {
extern int CmdFlashMem(const char *Cmd); extern int CmdFlashMem(const char *Cmd);
extern int CmdFlashMemRead(const char *cmd); extern int CmdFlashMemRead(const char *Cmd);
extern int CmdFlashMemLoad(const char *cmd); extern int CmdFlashMemLoad(const char *Cmd);
extern int CmdFlashMemSave(const char *cmd); extern int CmdFlashMemSave(const char *Cmd);
extern int CmdFlashMemWipe(const char *Cmd); extern int CmdFlashMemWipe(const char *Cmd);
extern int CmdFlashMemInfo(const char *Cmd); extern int CmdFlashMemInfo(const char *Cmd);
#endif #endif

View file

@ -21,7 +21,7 @@ int usage_hf_search() {
return 0; return 0;
} }
int usage_hf_sniff() { int usage_hf_sniff() {
PrintAndLogEx(NORMAL, "The high frequence snoop will assign all available memory on device for sniffed data"); PrintAndLogEx(NORMAL, "The high frequence sniffer will assign all available memory on device for sniffed data");
PrintAndLogEx(NORMAL, "Use " _YELLOW_("'data samples'")" command to download from device, and " _YELLOW_("'data plot'")" to look at it"); PrintAndLogEx(NORMAL, "Use " _YELLOW_("'data samples'")" command to download from device, and " _YELLOW_("'data plot'")" to look at it");
PrintAndLogEx(NORMAL, "Press button to quit the sniffing.\n"); PrintAndLogEx(NORMAL, "Press button to quit the sniffing.\n");
PrintAndLogEx(NORMAL, "Usage: hf sniff <skip pairs> <skip triggers>"); PrintAndLogEx(NORMAL, "Usage: hf sniff <skip pairs> <skip triggers>");

View file

@ -524,7 +524,7 @@ int CmdHF14AInfo(const char *Cmd) {
(tb1 ? "" : " NOT"), (tb1 ? "" : " NOT"),
(tc1 ? "" : " NOT"), (tc1 ? "" : " NOT"),
fsci, fsci,
fsci < sizeof(atsFSC) ? atsFSC[fsci] : -1 fsci < sizeof(atsFSC)/sizeof(atsFSC[0]) ? atsFSC[fsci] : -1
); );
} }
pos = 2; pos = 2;
@ -541,7 +541,11 @@ int CmdHF14AInfo(const char *Cmd) {
if (strlen(dr) != 0) dr[strlen(dr) - 2] = '\0'; if (strlen(dr) != 0) dr[strlen(dr) - 2] = '\0';
PrintAndLogEx(NORMAL, " - TA1 : different divisors are%s supported, " PrintAndLogEx(NORMAL, " - TA1 : different divisors are%s supported, "
"DR: [%s], DS: [%s]", "DR: [%s], DS: [%s]",
(card.ats[pos] & 0x80 ? " NOT" : ""), dr, ds); ((card.ats[pos] & 0x80) ? " NOT" : ""),
dr,
ds
);
pos++; pos++;
} }
if (tb1) { if (tb1) {
@ -803,19 +807,19 @@ int CmdHF14ASniff(const char *Cmd) {
if (ctmp == 'c') param |= 0x01; if (ctmp == 'c') param |= 0x01;
if (ctmp == 'r') param |= 0x02; if (ctmp == 'r') param |= 0x02;
} }
UsbCommand c = {CMD_SNOOP_ISO_14443a, {param, 0, 0}}; UsbCommand c = {CMD_SNIFF_ISO_14443a, {param, 0, 0}};
clearCommandBuffer(); clearCommandBuffer();
SendCommand(&c); SendCommand(&c);
return 0; return 0;
} }
int ExchangeRAW14a(uint8_t *datain, int datainlen, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen) { int ExchangeRAW14a(uint8_t *datain, int datainlen, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen) {
static bool responseNum = false; static uint8_t responseNum = 0;
uint16_t cmdc = 0; uint16_t cmdc = 0;
*dataoutlen = 0; *dataoutlen = 0;
if (activateField) { if (activateField) {
responseNum = false; responseNum = 1;
UsbCommand resp; UsbCommand resp;
// Anticollision + SELECT card // Anticollision + SELECT card
@ -848,7 +852,7 @@ int ExchangeRAW14a(uint8_t *datain, int datainlen, bool activateField, bool leav
return 1; return 1;
} }
if (resp.arg[0] <= 0) { // ats_len if (resp.arg[0] == 0) { // ats_len
PrintAndLogEx(ERR, "Can't get ATS."); PrintAndLogEx(ERR, "Can't get ATS.");
return 1; return 1;
} }
@ -859,7 +863,7 @@ int ExchangeRAW14a(uint8_t *datain, int datainlen, bool activateField, bool leav
cmdc |= ISO14A_NO_DISCONNECT; cmdc |= ISO14A_NO_DISCONNECT;
UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_RAW | ISO14A_APPEND_CRC | cmdc, (datainlen & 0xFFFF) + 2, 0}}; UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_RAW | ISO14A_APPEND_CRC | cmdc, (datainlen & 0xFFFF) + 2, 0}};
uint8_t header[] = {0x0a | responseNum, 0x00}; uint8_t header[] = { 0x0a | responseNum, 0x00};
responseNum ^= 1; responseNum ^= 1;
memcpy(c.d.asBytes, header, 2); memcpy(c.d.asBytes, header, 2);
memcpy(&c.d.asBytes[2], datain, datainlen); memcpy(&c.d.asBytes[2], datain, datainlen);
@ -899,7 +903,6 @@ int ExchangeRAW14a(uint8_t *datain, int datainlen, bool activateField, bool leav
return 3; return 3;
} }
} else { } else {
PrintAndLogEx(ERR, "Reply timeout."); PrintAndLogEx(ERR, "Reply timeout.");
return 4; return 4;
@ -948,7 +951,7 @@ int SelectCard14443_4(bool disconnect, iso14a_card_select_t *card) {
return 1; return 1;
} }
if (resp.arg[0] <= 0) { // ats_len if (resp.arg[0] == 0) { // ats_len
PrintAndLogEx(ERR, "Can't get ATS."); PrintAndLogEx(ERR, "Can't get ATS.");
return 1; return 1;
} }
@ -956,7 +959,7 @@ int SelectCard14443_4(bool disconnect, iso14a_card_select_t *card) {
// get frame length from ATS in data field // get frame length from ATS in data field
if (resp.arg[0] > 1) { if (resp.arg[0] > 1) {
uint8_t fsci = resp.d.asBytes[1] & 0x0f; uint8_t fsci = resp.d.asBytes[1] & 0x0f;
if (fsci < sizeof(atsFSC)) if (fsci < sizeof(atsFSC)/sizeof(atsFSC[0]))
frameLength = atsFSC[fsci]; frameLength = atsFSC[fsci];
} }
} else { } else {
@ -964,7 +967,7 @@ int SelectCard14443_4(bool disconnect, iso14a_card_select_t *card) {
iso14a_card_select_t *vcard = (iso14a_card_select_t *) resp.d.asBytes; iso14a_card_select_t *vcard = (iso14a_card_select_t *) resp.d.asBytes;
if (vcard->ats_len > 1) { if (vcard->ats_len > 1) {
uint8_t fsci = vcard->ats[1] & 0x0f; uint8_t fsci = vcard->ats[1] & 0x0f;
if (fsci < sizeof(atsFSC)) if (fsci < sizeof(atsFSC)/sizeof(atsFSC[0]))
frameLength = atsFSC[fsci]; frameLength = atsFSC[fsci];
} }
@ -997,7 +1000,10 @@ int CmdExchangeAPDU(bool chainingin, uint8_t *datain, int datainlen, bool activa
// here length USB_CMD_DATA_SIZE=512 // here length USB_CMD_DATA_SIZE=512
// timeout must be authomatically set by "get ATS" // timeout must be authomatically set by "get ATS"
UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_APDU | ISO14A_NO_DISCONNECT | cmdc, (datainlen & 0xFFFF), 0}}; UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_APDU | ISO14A_NO_DISCONNECT | cmdc, (datainlen & 0xFFFF), 0}};
if ( datain )
memcpy(c.d.asBytes, datain, datainlen); memcpy(c.d.asBytes, datain, datainlen);
SendCommand(&c); SendCommand(&c);
uint8_t *recv; uint8_t *recv;
@ -1132,7 +1138,7 @@ int ExchangeAPDU14a(uint8_t *datain, int datainlen, bool activateField, bool lea
} }
// ISO14443-4. 7. Half-duplex block transmission protocol // ISO14443-4. 7. Half-duplex block transmission protocol
int CmdHF14AAPDU(const char *cmd) { int CmdHF14AAPDU(const char *Cmd) {
uint8_t data[USB_CMD_DATA_SIZE]; uint8_t data[USB_CMD_DATA_SIZE];
int datalen = 0; int datalen = 0;
bool activateField = false; bool activateField = false;
@ -1151,7 +1157,7 @@ int CmdHF14AAPDU(const char *cmd) {
arg_strx1(NULL, NULL, "<APDU (hex)>", NULL), arg_strx1(NULL, NULL, "<APDU (hex)>", NULL),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(cmd, argtable, false); CLIExecWithReturn(Cmd, argtable, false);
activateField = arg_get_lit(1); activateField = arg_get_lit(1);
leaveSignalON = arg_get_lit(2); leaveSignalON = arg_get_lit(2);
@ -1179,7 +1185,7 @@ int CmdHF14AAPDU(const char *cmd) {
return 0; return 0;
} }
int CmdHF14ACmdRaw(const char *cmd) { int CmdHF14ACmdRaw(const char *Cmd) {
UsbCommand c = {CMD_READER_ISO_14443a, {0, 0, 0}}; UsbCommand c = {CMD_READER_ISO_14443a, {0, 0, 0}};
bool reply = 1; bool reply = 1;
bool crc = false; bool crc = false;
@ -1197,15 +1203,15 @@ int CmdHF14ACmdRaw(const char *cmd) {
uint16_t datalen = 0; uint16_t datalen = 0;
uint32_t temp; uint32_t temp;
if (strlen(cmd) < 2) return usage_hf_14a_raw(); if (strlen(Cmd) < 2) return usage_hf_14a_raw();
// strip // strip
while (*cmd == ' ' || *cmd == '\t') cmd++; while (*Cmd == ' ' || *Cmd == '\t') Cmd++;
while (cmd[i] != '\0') { while (Cmd[i] != '\0') {
if (cmd[i] == ' ' || cmd[i] == '\t') { i++; continue; } if (Cmd[i] == ' ' || Cmd[i] == '\t') { i++; continue; }
if (cmd[i] == '-') { if (Cmd[i] == '-') {
switch (cmd[i + 1]) { switch (Cmd[i + 1]) {
case 'H': case 'H':
case 'h': case 'h':
return usage_hf_14a_raw(); return usage_hf_14a_raw();
@ -1225,18 +1231,18 @@ int CmdHF14ACmdRaw(const char *cmd) {
active_select = true; active_select = true;
break; break;
case 'b': case 'b':
sscanf(cmd + i + 2, "%d", &temp); sscanf(Cmd + i + 2, "%d", &temp);
numbits = temp & 0xFFFF; numbits = temp & 0xFFFF;
i += 3; i += 3;
while (cmd[i] != ' ' && cmd[i] != '\0') { i++; } while (Cmd[i] != ' ' && Cmd[i] != '\0') { i++; }
i -= 2; i -= 2;
break; break;
case 't': case 't':
bTimeout = true; bTimeout = true;
sscanf(cmd + i + 2, "%d", &temp); sscanf(Cmd + i + 2, "%d", &temp);
timeout = temp; timeout = temp;
i += 3; i += 3;
while (cmd[i] != ' ' && cmd[i] != '\0') { i++; } while (Cmd[i] != ' ' && Cmd[i] != '\0') { i++; }
i -= 2; i -= 2;
break; break;
case 'T': case 'T':
@ -1251,11 +1257,11 @@ int CmdHF14ACmdRaw(const char *cmd) {
i += 2; i += 2;
continue; continue;
} }
if ((cmd[i] >= '0' && cmd[i] <= '9') || if ((Cmd[i] >= '0' && Cmd[i] <= '9') ||
(cmd[i] >= 'a' && cmd[i] <= 'f') || (Cmd[i] >= 'a' && Cmd[i] <= 'f') ||
(cmd[i] >= 'A' && cmd[i] <= 'F')) { (Cmd[i] >= 'A' && Cmd[i] <= 'F')) {
buf[strlen(buf) + 1] = 0; buf[strlen(buf) + 1] = 0;
buf[strlen(buf)] = cmd[i]; buf[strlen(buf)] = Cmd[i];
i++; i++;
if (strlen(buf) >= 2) { if (strlen(buf) >= 2) {
@ -1363,7 +1369,7 @@ static int waitCmd(uint8_t iSelect) {
return 0; return 0;
} }
int CmdHF14AAntiFuzz(const char *cmd) { int CmdHF14AAntiFuzz(const char *Cmd) {
CLIParserInit("hf 14a antifuzz", CLIParserInit("hf 14a antifuzz",
"Tries to fuzz the ISO14443a anticollision phase", "Tries to fuzz the ISO14443a anticollision phase",
@ -1377,7 +1383,7 @@ int CmdHF14AAntiFuzz(const char *cmd) {
arg_lit0(NULL, "10", "10 byte uid"), arg_lit0(NULL, "10", "10 byte uid"),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(cmd, argtable, false); CLIExecWithReturn(Cmd, argtable, false);
uint8_t arg0 = FLAG_4B_UID_IN_DATA; uint8_t arg0 = FLAG_4B_UID_IN_DATA;
if (arg_get_lit(2)) if (arg_get_lit(2))
@ -1392,7 +1398,7 @@ int CmdHF14AAntiFuzz(const char *cmd) {
return 0; return 0;
} }
int CmdHF14AChaining(const char *cmd) { int CmdHF14AChaining(const char *Cmd) {
CLIParserInit("hf 14a chaining", CLIParserInit("hf 14a chaining",
"Enable/Disable ISO14443a input chaining. Maximum input length goes from ATS.", "Enable/Disable ISO14443a input chaining. Maximum input length goes from ATS.",
@ -1405,7 +1411,7 @@ int CmdHF14AChaining(const char *cmd) {
arg_str0(NULL, NULL, "<enable/disable or 0/1>", NULL), arg_str0(NULL, NULL, "<enable/disable or 0/1>", NULL),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(cmd, argtable, true); CLIExecWithReturn(Cmd, argtable, true);
struct arg_str *str = arg_get_str(1); struct arg_str *str = arg_get_str(1);
int len = arg_get_str_len(1); int len = arg_get_str_len(1);

View file

@ -47,7 +47,7 @@ extern int CmdHF14ASim(const char *Cmd);
extern int CmdHF14ASniff(const char *Cmd); extern int CmdHF14ASniff(const char *Cmd);
extern int CmdHF14ACmdRaw(const char *Cmd); extern int CmdHF14ACmdRaw(const char *Cmd);
extern int CmdHF14ACUIDs(const char *Cmd); extern int CmdHF14ACUIDs(const char *Cmd);
extern int CmdHF14AAntiFuzz(const char *cmd); extern int CmdHF14AAntiFuzz(const char *Cmd);
extern char *getTagInfo(uint8_t uid); extern char *getTagInfo(uint8_t uid);
extern int Hf14443_4aGetCardData(iso14a_card_select_t *card); extern int Hf14443_4aGetCardData(iso14a_card_select_t *card);

View file

@ -33,7 +33,7 @@ int usage_hf_14b_reader(void) {
return 0; return 0;
} }
int usage_hf_14b_raw(void) { int usage_hf_14b_raw(void) {
PrintAndLogEx(NORMAL, "Usage: hf 14b raw [-h] [-r] [-c] [-p] [-s || -ss] <0A 0B 0C ... hex>"); PrintAndLogEx(NORMAL, "Usage: hf 14b raw [-h] [-r] [-c] [-p] [-s / -ss] [-t] <0A 0B 0C ... hex>");
PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " -h this help"); PrintAndLogEx(NORMAL, " -h this help");
PrintAndLogEx(NORMAL, " -r do not read response"); PrintAndLogEx(NORMAL, " -r do not read response");
@ -41,6 +41,7 @@ int usage_hf_14b_raw(void) {
PrintAndLogEx(NORMAL, " -p leave the field on after receive"); PrintAndLogEx(NORMAL, " -p leave the field on after receive");
PrintAndLogEx(NORMAL, " -s active signal field ON with select"); PrintAndLogEx(NORMAL, " -s active signal field ON with select");
PrintAndLogEx(NORMAL, " -ss active signal field ON with select for SRx ST Microelectronics tags"); PrintAndLogEx(NORMAL, " -ss active signal field ON with select for SRx ST Microelectronics tags");
PrintAndLogEx(NORMAL, " -t timeout in ms");
PrintAndLogEx(NORMAL, "Example:"); PrintAndLogEx(NORMAL, "Example:");
PrintAndLogEx(NORMAL, " hf 14b raw -s -c -p 0200a40400"); PrintAndLogEx(NORMAL, " hf 14b raw -s -c -p 0200a40400");
return 0; return 0;
@ -145,20 +146,20 @@ int CmdHF14BSniff(const char *Cmd) {
char cmdp = tolower(param_getchar(Cmd, 0)); char cmdp = tolower(param_getchar(Cmd, 0));
if (cmdp == 'h') return usage_hf_14b_sniff(); if (cmdp == 'h') return usage_hf_14b_sniff();
UsbCommand c = {CMD_SNOOP_ISO_14443B, {0, 0, 0}}; UsbCommand c = {CMD_SNIFF_ISO_14443B, {0, 0, 0}};
clearCommandBuffer(); clearCommandBuffer();
SendCommand(&c); SendCommand(&c);
return 0; return 0;
} }
int CmdHF14BCmdRaw(const char *Cmd) { int CmdHF14BCmdRaw(const char *Cmd) {
bool reply = true, power = false, select = false; bool reply = true, power = false, select = false, hasTimeout = false;
char buf[5] = ""; char buf[5] = "";
int i = 0; int i = 0;
uint8_t data[USB_CMD_DATA_SIZE] = {0x00}; uint8_t data[USB_CMD_DATA_SIZE] = {0x00};
uint16_t datalen = 0; uint16_t datalen = 0;
uint32_t flags = ISO14B_CONNECT; uint32_t flags = ISO14B_CONNECT;
uint32_t temp = 0; uint32_t temp = 0, user_timeout = 0, time_wait = 0;
if (strlen(Cmd) < 3) return usage_hf_14b_raw(); if (strlen(Cmd) < 3) return usage_hf_14b_raw();
@ -189,6 +190,13 @@ int CmdHF14BCmdRaw(const char *Cmd) {
flags |= ISO14B_SELECT_STD; flags |= ISO14B_SELECT_STD;
} }
break; break;
case 't':
hasTimeout = true;
sscanf(Cmd + i + 2, "%d", &user_timeout);
i += 3;
while (Cmd[i] != ' ' && Cmd[i] != '\0') { i++; }
i -= 2;
break;
default: default:
return usage_hf_14b_raw(); return usage_hf_14b_raw();
} }
@ -214,7 +222,17 @@ int CmdHF14BCmdRaw(const char *Cmd) {
return 0; return 0;
} }
if (!power) if (hasTimeout) {
#define MAX_TIMEOUT 40542464 // = (2^32-1) * (8*16) / 13560000Hz * 1000ms/s
flags |= ISO14B_SET_TIMEOUT;
if (user_timeout > MAX_TIMEOUT) {
user_timeout = MAX_TIMEOUT;
PrintAndLogEx(NORMAL, "Set timeout to 40542 seconds (11.26 hours). The max we can wait for response");
}
time_wait = 13560000 / 1000 / (8 * 16) * user_timeout; // timeout in ETUs (time to transfer 1 bit, approx. 9.4 us)
}
if (power == 0)
flags |= ISO14B_DISCONNECT; flags |= ISO14B_DISCONNECT;
if (datalen > 0) if (datalen > 0)
@ -223,7 +241,7 @@ int CmdHF14BCmdRaw(const char *Cmd) {
// Max buffer is USB_CMD_DATA_SIZE // Max buffer is USB_CMD_DATA_SIZE
datalen = (datalen > USB_CMD_DATA_SIZE) ? USB_CMD_DATA_SIZE : datalen; datalen = (datalen > USB_CMD_DATA_SIZE) ? USB_CMD_DATA_SIZE : datalen;
UsbCommand c = {CMD_ISO_14443B_COMMAND, {flags, datalen, 0}}; UsbCommand c = {CMD_ISO_14443B_COMMAND, {flags, datalen, time_wait}};
memcpy(c.d.asBytes, data, datalen); memcpy(c.d.asBytes, data, datalen);
clearCommandBuffer(); clearCommandBuffer();
SendCommand(&c); SendCommand(&c);

View file

@ -233,7 +233,7 @@ static char *getTagInfo_15(uint8_t *uid) {
int i = 0, best = -1; int i = 0, best = -1;
memcpy(&myuid, uid, sizeof(uint64_t)); memcpy(&myuid, uid, sizeof(uint64_t));
while (uidmapping[i].mask > 0) { while (uidmapping[i].mask > 0) {
mask = (~0LL) << (64 - uidmapping[i].mask); mask = (~0ULL) << (64 - uidmapping[i].mask);
if ((myuid & mask) == uidmapping[i].uid) { if ((myuid & mask) == uidmapping[i].uid) {
if (best == -1) { if (best == -1) {
best = i; best = i;
@ -684,15 +684,15 @@ int CmdHF15Dump(const char *Cmd) {
//Validations //Validations
if (errors) return usage_15_dump(); if (errors) return usage_15_dump();
if (fileNameLen < 1) {
PrintAndLogEx(INFO, "Using UID as filename");
if (!getUID(uid)) { if (!getUID(uid)) {
PrintAndLogEx(WARNING, "No tag found."); PrintAndLogEx(WARNING, "No tag found.");
return 1; return 1;
} }
if (fileNameLen < 1) {
PrintAndLogEx(INFO, "Using UID as filename");
fptr += sprintf(fptr, "hf-15-"); fptr += sprintf(fptr, "hf-15-");
FillFileNameByUID(fptr, uid, "-dump", sizeof(uid)); FillFileNameByUID(fptr, uid, "-dump", sizeof(uid));
} }
@ -796,7 +796,7 @@ int CmdHF15Restore(const char *Cmd) {
case '2': case '2':
case 'o': case 'o':
strncpy(newCmdPrefix, " ", sizeof(newCmdPrefix) - 1); strncpy(newCmdPrefix, " ", sizeof(newCmdPrefix) - 1);
strncat(newCmdPrefix, param, sizeof(newCmdPrefix) - 1); strncat(newCmdPrefix, param, sizeof(newCmdPrefix) - strlen(newCmdPrefix) - 1);
break; break;
default: default:
PrintAndLogEx(WARNING, "Unknown parameter '%s'", param); PrintAndLogEx(WARNING, "Unknown parameter '%s'", param);

View file

@ -218,7 +218,7 @@ int CmdHFFelicaSniff(const char *Cmd) {
//Validations //Validations
if (errors || cmdp == 0) return usage_hf_felica_sniff(); if (errors || cmdp == 0) return usage_hf_felica_sniff();
UsbCommand c = {CMD_FELICA_SNOOP, {samples2skip, triggers2skip, 0}}; UsbCommand c = {CMD_FELICA_SNIFF, {samples2skip, triggers2skip, 0}};
clearCommandBuffer(); clearCommandBuffer();
SendCommand(&c); SendCommand(&c);
return 0; return 0;
@ -425,15 +425,15 @@ int CmdHFFelicaDumpLite(const char *Cmd) {
} }
uint64_t tracelen = resp.arg[1]; uint64_t tracelen = resp.arg[1];
if (tracelen == 0)
return 1;
uint8_t *trace = calloc(tracelen, sizeof(uint8_t)); uint8_t *trace = calloc(tracelen, sizeof(uint8_t));
if (trace == NULL) { if (trace == NULL) {
PrintAndLogEx(WARNING, "Cannot allocate memory for trace"); PrintAndLogEx(WARNING, "Cannot allocate memory for trace");
return 1; return 1;
} }
// only download data if there is any.
if (tracelen > 0) {
if (!GetFromDevice(BIG_BUF, trace, tracelen, 0, NULL, 2500, false)) { if (!GetFromDevice(BIG_BUF, trace, tracelen, 0, NULL, 2500, false)) {
PrintAndLogEx(WARNING, "command execution time out"); PrintAndLogEx(WARNING, "command execution time out");
free(trace); free(trace);
@ -443,20 +443,19 @@ int CmdHFFelicaDumpLite(const char *Cmd) {
PrintAndLogEx(SUCCESS, "Recorded Activity (trace len = %d bytes)", tracelen); PrintAndLogEx(SUCCESS, "Recorded Activity (trace len = %d bytes)", tracelen);
print_hex_break(trace, tracelen, 32); print_hex_break(trace, tracelen, 32);
printSep(); printSep();
uint16_t tracepos = 0; uint16_t tracepos = 0;
while (tracepos < tracelen) while (tracepos < tracelen)
tracepos = PrintFliteBlock(tracepos, trace, tracelen); tracepos = PrintFliteBlock(tracepos, trace, tracelen);
printSep(); printSep();
}
free(trace); free(trace);
return 0; return 0;
} }
int CmdHFFelicaCmdRaw(const char *cmd) { int CmdHFFelicaCmdRaw(const char *Cmd) {
UsbCommand c = {CMD_FELICA_COMMAND, {0, 0, 0}}; UsbCommand c = {CMD_FELICA_COMMAND, {0, 0, 0}};
bool reply = 1; bool reply = 1;
bool crc = false; bool crc = false;
@ -470,15 +469,15 @@ int CmdHFFelicaCmdRaw(const char *cmd) {
uint16_t datalen = 0; uint16_t datalen = 0;
uint32_t temp; uint32_t temp;
if (strlen(cmd) < 2) return usage_hf_felica_raw(); if (strlen(Cmd) < 2) return usage_hf_felica_raw();
// strip // strip
while (*cmd == ' ' || *cmd == '\t') cmd++; while (*Cmd == ' ' || *Cmd == '\t') Cmd++;
while (cmd[i] != '\0') { while (Cmd[i] != '\0') {
if (cmd[i] == ' ' || cmd[i] == '\t') { i++; continue; } if (Cmd[i] == ' ' || Cmd[i] == '\t') { i++; continue; }
if (cmd[i] == '-') { if (Cmd[i] == '-') {
switch (cmd[i + 1]) { switch (Cmd[i + 1]) {
case 'H': case 'H':
case 'h': case 'h':
return usage_hf_felica_raw(); return usage_hf_felica_raw();
@ -498,10 +497,10 @@ int CmdHFFelicaCmdRaw(const char *cmd) {
active_select = true; active_select = true;
break; break;
case 'b': case 'b':
sscanf(cmd + i + 2, "%d", &temp); sscanf(Cmd + i + 2, "%d", &temp);
numbits = temp & 0xFFFF; numbits = temp & 0xFFFF;
i += 3; i += 3;
while (cmd[i] != ' ' && cmd[i] != '\0') { i++; } while (Cmd[i] != ' ' && Cmd[i] != '\0') { i++; }
i -= 2; i -= 2;
break; break;
default: default:
@ -510,11 +509,11 @@ int CmdHFFelicaCmdRaw(const char *cmd) {
i += 2; i += 2;
continue; continue;
} }
if ((cmd[i] >= '0' && cmd[i] <= '9') || if ((Cmd[i] >= '0' && Cmd[i] <= '9') ||
(cmd[i] >= 'a' && cmd[i] <= 'f') || (Cmd[i] >= 'a' && Cmd[i] <= 'f') ||
(cmd[i] >= 'A' && cmd[i] <= 'F')) { (Cmd[i] >= 'A' && Cmd[i] <= 'F')) {
buf[strlen(buf) + 1] = 0; buf[strlen(buf) + 1] = 0;
buf[strlen(buf)] = cmd[i]; buf[strlen(buf)] = Cmd[i];
i++; i++;
if (strlen(buf) >= 2) { if (strlen(buf) >= 2) {

View file

@ -215,7 +215,7 @@ int CmdHFFidoRegister(const char *cmd) {
if (paramsPlain) { if (paramsPlain) {
memset(cdata, 0x00, 32); memset(cdata, 0x00, 32);
CLIGetStrWithReturn(6, cdata, &chlen); CLIGetStrWithReturn(6, cdata, &chlen);
if (chlen && chlen > 16) { if (chlen > 16) {
PrintAndLog("ERROR: challenge parameter length in ASCII mode must be less than 16 chars instead of: %d", chlen); PrintAndLog("ERROR: challenge parameter length in ASCII mode must be less than 16 chars instead of: %d", chlen);
return 1; return 1;
} }
@ -233,7 +233,7 @@ int CmdHFFidoRegister(const char *cmd) {
if (paramsPlain) { if (paramsPlain) {
memset(adata, 0x00, 32); memset(adata, 0x00, 32);
CLIGetStrWithReturn(7, adata, &applen); CLIGetStrWithReturn(7, adata, &applen);
if (applen && applen > 16) { if (applen > 16) {
PrintAndLog("ERROR: application parameter length in ASCII mode must be less than 16 chars instead of: %d", applen); PrintAndLog("ERROR: application parameter length in ASCII mode must be less than 16 chars instead of: %d", applen);
return 1; return 1;
} }
@ -479,7 +479,7 @@ int CmdHFFidoAuthenticate(const char *cmd) {
if (paramsPlain) { if (paramsPlain) {
memset(hdata, 0x00, 32); memset(hdata, 0x00, 32);
CLIGetStrWithReturn(9, hdata, &hdatalen); CLIGetStrWithReturn(9, hdata, &hdatalen);
if (hdatalen && hdatalen > 16) { if (hdatalen > 16) {
PrintAndLog("ERROR: challenge parameter length in ASCII mode must be less than 16 chars instead of: %d", hdatalen); PrintAndLog("ERROR: challenge parameter length in ASCII mode must be less than 16 chars instead of: %d", hdatalen);
return 1; return 1;
} }
@ -496,7 +496,7 @@ int CmdHFFidoAuthenticate(const char *cmd) {
if (paramsPlain) { if (paramsPlain) {
memset(hdata, 0x00, 32); memset(hdata, 0x00, 32);
CLIGetStrWithReturn(11, hdata, &hdatalen); CLIGetStrWithReturn(11, hdata, &hdatalen);
if (hdatalen && hdatalen > 16) { if (hdatalen > 16) {
PrintAndLog("ERROR: application parameter length in ASCII mode must be less than 16 chars instead of: %d", hdatalen); PrintAndLog("ERROR: application parameter length in ASCII mode must be less than 16 chars instead of: %d", hdatalen);
return 1; return 1;
} }

View file

@ -279,7 +279,7 @@ int CmdHFiClassList(const char *Cmd) {
int CmdHFiClassSniff(const char *Cmd) { int CmdHFiClassSniff(const char *Cmd) {
char cmdp = tolower(param_getchar(Cmd, 0)); char cmdp = tolower(param_getchar(Cmd, 0));
if (cmdp == 'h') return usage_hf_iclass_sniff(); if (cmdp == 'h') return usage_hf_iclass_sniff();
UsbCommand c = {CMD_SNOOP_ICLASS}; UsbCommand c = {CMD_SNIFF_ICLASS};
SendCommand(&c); SendCommand(&c);
return 0; return 0;
} }
@ -784,8 +784,8 @@ int CmdHFiClassDecrypt(const char *Cmd) {
} }
saveFile(outfilename, "bin", decrypted, fsize); saveFile(outfilename, "bin", decrypted, fsize);
free(decrypted);
printIclassDumpContents(decrypted, 1, (fsize / 8), fsize); printIclassDumpContents(decrypted, 1, (fsize / 8), fsize);
free(decrypted);
return 0; return 0;
} }
@ -1375,11 +1375,14 @@ int CmdHFiClassCloneTag(const char *Cmd) {
return 2; return 2;
} }
fclose(f);
uint8_t MAC[4] = {0x00, 0x00, 0x00, 0x00}; uint8_t MAC[4] = {0x00, 0x00, 0x00, 0x00};
uint8_t div_key[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; uint8_t div_key[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
if (!select_and_auth(KEY, MAC, div_key, use_credit_key, elite, rawkey, verbose)) if (!select_and_auth(KEY, MAC, div_key, use_credit_key, elite, rawkey, verbose)) {
return 0; return 0;
}
UsbCommand w = {CMD_ICLASS_CLONE, {startblock, endblock}}; UsbCommand w = {CMD_ICLASS_CLONE, {startblock, endblock}};
uint8_t *ptr; uint8_t *ptr;
@ -1401,6 +1404,7 @@ int CmdHFiClassCloneTag(const char *Cmd) {
PrintAndLogEx(NORMAL, " %02x%02x%02x%02x%02x%02x%02x%02x |", p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]); PrintAndLogEx(NORMAL, " %02x%02x%02x%02x%02x%02x%02x%02x |", p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
PrintAndLogEx(NORMAL, " MAC |%02x%02x%02x%02x|\n", p[8], p[9], p[10], p[11]); PrintAndLogEx(NORMAL, " MAC |%02x%02x%02x%02x|\n", p[8], p[9], p[10], p[11]);
} }
UsbCommand resp; UsbCommand resp;
clearCommandBuffer(); clearCommandBuffer();
SendCommand(&w); SendCommand(&w);

View file

@ -230,21 +230,21 @@ int CmdLegicInfo(const char *Cmd) {
int fl = 0; int fl = 0;
if (data[6] == 0xec) { if (data[6] == 0xec) {
strncpy(token_type, "XAM", sizeof(token_type)); strncpy(token_type, "XAM", sizeof(token_type) - 1);
fl = 1; fl = 1;
stamp_len = 0x0c - (data[5] >> 4); stamp_len = 0x0c - (data[5] >> 4);
} else { } else {
switch (data[5] & 0x7f) { switch (data[5] & 0x7f) {
case 0x00 ... 0x2f: case 0x00 ... 0x2f:
strncpy(token_type, "IAM", sizeof(token_type)); strncpy(token_type, "IAM", sizeof(token_type) - 1);
fl = (0x2f - (data[5] & 0x7f)) + 1; fl = (0x2f - (data[5] & 0x7f)) + 1;
break; break;
case 0x30 ... 0x6f: case 0x30 ... 0x6f:
strncpy(token_type, "SAM", sizeof(token_type)); strncpy(token_type, "SAM", sizeof(token_type) - 1);
fl = (0x6f - (data[5] & 0x7f)) + 1; fl = (0x6f - (data[5] & 0x7f)) + 1;
break; break;
case 0x70 ... 0x7f: case 0x70 ... 0x7f:
strncpy(token_type, "GAM", sizeof(token_type)); strncpy(token_type, "GAM", sizeof(token_type) - 1);
fl = (0x7f - (data[5] & 0x7f)) + 1; fl = (0x7f - (data[5] & 0x7f)) + 1;
break; break;
} }
@ -266,9 +266,9 @@ int CmdLegicInfo(const char *Cmd) {
if (data[7] == 0x9F && data[8] == 0xFF) { if (data[7] == 0x9F && data[8] == 0xFF) {
bIsSegmented = 1; bIsSegmented = 1;
strncpy(token_type, "IM-S", sizeof(token_type)); strncpy(token_type, "IM-S", sizeof(token_type) - 1);
} else { } else {
strncpy(token_type, "IM", sizeof(token_type)); strncpy(token_type, "IM", sizeof(token_type) - 1);
} }
PrintAndLogEx(NORMAL, "DCF: %d (%02x %02x), Token Type=%s (OLE=%01u)", PrintAndLogEx(NORMAL, "DCF: %d (%02x %02x), Token Type=%s (OLE=%01u)",
@ -614,8 +614,7 @@ int CmdLegicRfWrite(const char *Cmd) {
PrintAndLogEx(NORMAL, "############# DANGER ################"); PrintAndLogEx(NORMAL, "############# DANGER ################");
PrintAndLogEx(NORMAL, "# changing the DCF is irreversible #"); PrintAndLogEx(NORMAL, "# changing the DCF is irreversible #");
PrintAndLogEx(NORMAL, "#####################################"); PrintAndLogEx(NORMAL, "#####################################");
char *answer = NULL; char *answer = readline("do you really want to continue? y(es) n(o) : ");
answer = readline("do you really want to continue? y(es) n(o) : ");
bool overwrite = (answer[0] == 'y' || answer[0] == 'Y'); bool overwrite = (answer[0] == 'y' || answer[0] == 'Y');
if (!overwrite) { if (!overwrite) {
PrintAndLogEx(NORMAL, "command cancelled"); PrintAndLogEx(NORMAL, "command cancelled");
@ -1283,6 +1282,7 @@ int CmdLegicWipe(const char *Cmd) {
} }
} }
PrintAndLogEx(SUCCESS, "ok\n"); PrintAndLogEx(SUCCESS, "ok\n");
free(data);
return 0; return 0;
} }

View file

@ -44,7 +44,7 @@ void ClearAuthData() {
uint8_t iso14443A_CRC_check(bool isResponse, uint8_t *d, uint8_t n) { uint8_t iso14443A_CRC_check(bool isResponse, uint8_t *d, uint8_t n) {
if (n < 3) return 2; if (n < 3) return 2;
if (isResponse & (n < 6)) return 2; if (isResponse && (n < 6)) return 2;
return check_crc(CRC_14443_A, d, n); return check_crc(CRC_14443_A, d, n);
} }
@ -216,7 +216,7 @@ int applyIso14443a(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize) {
break; break;
case MIFARE_ULEV1_AUTH: case MIFARE_ULEV1_AUTH:
if (cmdsize == 7) if (cmdsize == 7)
snprintf(exp, size, "PWD-AUTH KEY: 0x%02x%02x%02x%02x", cmd[1], cmd[2], cmd[3], cmd[4]); snprintf(exp, size, "PWD-AUTH KEY: " _YELLOW_("0x%02x%02x%02x%02x"), cmd[1], cmd[2], cmd[3], cmd[4]);
else else
snprintf(exp, size, "PWD-AUTH"); snprintf(exp, size, "PWD-AUTH");
break; break;

View file

@ -53,7 +53,7 @@ typedef struct {
} TAuthData; } TAuthData;
extern void ClearAuthData(); extern void ClearAuthData();
extern uint8_t iso14443A_CRC_check(bool isResponse, uint8_t *data, uint8_t len); extern uint8_t iso14443A_CRC_check(bool isResponse, uint8_t *d, uint8_t n);
extern uint8_t iso14443B_CRC_check(uint8_t *d, uint8_t n); extern uint8_t iso14443B_CRC_check(uint8_t *d, uint8_t n);
extern uint8_t mifare_CRC_check(bool isResponse, uint8_t *data, uint8_t len); extern uint8_t mifare_CRC_check(bool isResponse, uint8_t *data, uint8_t len);
extern uint8_t iso15693_CRC_check(uint8_t *d, uint8_t n); extern uint8_t iso15693_CRC_check(uint8_t *d, uint8_t n);

View file

@ -1321,8 +1321,6 @@ int CmdHF14AMfNested(const char *Cmd) {
} }
free(e_sector); free(e_sector);
} }
free(e_sector);
return 0; return 0;
} }
@ -1350,7 +1348,7 @@ int CmdHF14AMfNestedHard(const char *Cmd) {
case 'r': case 'r':
fptr = GenerateFilename("hf-mf-", "-nonces.bin"); fptr = GenerateFilename("hf-mf-", "-nonces.bin");
if (fptr == NULL) if (fptr == NULL)
strncpy(filename, "nonces.bin", FILE_PATH_SIZE); strncpy(filename, "nonces.bin", FILE_PATH_SIZE - 1);
else else
strncpy(filename, fptr, FILE_PATH_SIZE - 1); strncpy(filename, fptr, FILE_PATH_SIZE - 1);
@ -1538,7 +1536,7 @@ int CmdHF14AMfChk_fast(const char *Cmd) {
char buf[13]; char buf[13];
char *fptr; char *fptr;
uint8_t tempkey[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; uint8_t tempkey[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
uint8_t *keyBlock = NULL, *p; uint8_t *keyBlock, *p;
uint8_t sectorsCnt = 1; uint8_t sectorsCnt = 1;
int i, keycnt = 0; int i, keycnt = 0;
int clen = 0; int clen = 0;
@ -1786,7 +1784,7 @@ int CmdHF14AMfChk(const char *Cmd) {
FILE *f; FILE *f;
char filename[FILE_PATH_SIZE] = {0}; char filename[FILE_PATH_SIZE] = {0};
char buf[13]; char buf[13];
uint8_t *keyBlock = NULL, *p; uint8_t *keyBlock, *p;
sector_t *e_sector = NULL; sector_t *e_sector = NULL;
uint8_t blockNo = 0; uint8_t blockNo = 0;
@ -2541,7 +2539,7 @@ int CmdHF14AMfELoad(const char *Cmd) {
uint8_t *data = calloc(4096, sizeof(uint8_t)); uint8_t *data = calloc(4096, sizeof(uint8_t));
size_t datalen = 0; size_t datalen = 0;
//int res = loadFile(filename, "bin", data, &datalen); //int res = loadFile(filename, "bin", data, maxdatalen, &datalen);
int res = loadFileEML(filename, "eml", data, &datalen); int res = loadFileEML(filename, "eml", data, &datalen);
if (res) { if (res) {
free(data); free(data);
@ -2827,7 +2825,7 @@ int CmdHF14AMfCLoad(const char *Cmd) {
size_t datalen = 0; size_t datalen = 0;
int res = 0; int res = 0;
if (fillFromBin) { if (fillFromBin) {
res = loadFile(fileName, "bin", data, &datalen); res = loadFile(fileName, "bin", data, maxdatalen, &datalen);
} else { } else {
if (fillFromJson) { if (fillFromJson) {
res = loadFileJSON(fileName, "json", data, maxdatalen, &datalen); res = loadFileJSON(fileName, "json", data, maxdatalen, &datalen);
@ -3297,7 +3295,7 @@ int CmdHF14AMfAuth4(const char *Cmd) {
} }
// https://www.nxp.com/docs/en/application-note/AN10787.pdf // https://www.nxp.com/docs/en/application-note/AN10787.pdf
int CmdHF14AMfMAD(const char *cmd) { int CmdHF14AMfMAD(const char *Cmd) {
CLIParserInit("hf mf mad", CLIParserInit("hf mf mad",
"Checks and prints Mifare Application Directory (MAD)", "Checks and prints Mifare Application Directory (MAD)",
@ -3312,7 +3310,7 @@ int CmdHF14AMfMAD(const char *cmd) {
arg_lit0("bB", "keyb", "use key B for access printing sectors (by default: key A)"), arg_lit0("bB", "keyb", "use key B for access printing sectors (by default: key A)"),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(cmd, argtable, true); CLIExecWithReturn(Cmd, argtable, true);
bool verbose = arg_get_lit(1); bool verbose = arg_get_lit(1);
uint8_t aid[2] = {0}; uint8_t aid[2] = {0};
int aidlen; int aidlen;
@ -3387,7 +3385,7 @@ int CmdHF14AMfMAD(const char *cmd) {
return 0; return 0;
} }
int CmdHFMFNDEF(const char *cmd) { int CmdHFMFNDEF(const char *Cmd) {
CLIParserInit("hf mf ndef", CLIParserInit("hf mf ndef",
"Prints NFC Data Exchange Format (NDEF)", "Prints NFC Data Exchange Format (NDEF)",
@ -3402,7 +3400,7 @@ int CmdHFMFNDEF(const char *cmd) {
arg_lit0("bB", "keyb", "use key B for access sectors (by default: key A)"), arg_lit0("bB", "keyb", "use key B for access sectors (by default: key A)"),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(cmd, argtable, true); CLIExecWithReturn(Cmd, argtable, true);
bool verbose = arg_get_lit(1); bool verbose = arg_get_lit(1);
bool verbose2 = arg_get_lit(1) > 1; bool verbose2 = arg_get_lit(1) > 1;
@ -3506,7 +3504,7 @@ static command_t CommandTable[] = {
{"nack", CmdHf14AMfNack, 0, "Test for Mifare NACK bug"}, {"nack", CmdHf14AMfNack, 0, "Test for Mifare NACK bug"},
{"chk", CmdHF14AMfChk, 0, "Check keys"}, {"chk", CmdHF14AMfChk, 0, "Check keys"},
{"fchk", CmdHF14AMfChk_fast, 0, "Check keys fast, targets all keys on card"}, {"fchk", CmdHF14AMfChk_fast, 0, "Check keys fast, targets all keys on card"},
{"decrypt", CmdHf14AMfDecryptBytes, 1, "[nt] [ar_enc] [at_enc] [data] - to decrypt snoop or trace"}, {"decrypt", CmdHf14AMfDecryptBytes, 1, "[nt] [ar_enc] [at_enc] [data] - to decrypt sniff or trace"},
{"-----------", CmdHelp, 1, ""}, {"-----------", CmdHelp, 1, ""},
{"dbg", CmdHF14AMfDbg, 0, "Set default debug mode"}, {"dbg", CmdHF14AMfDbg, 0, "Set default debug mode"},
{"rdbl", CmdHF14AMfRdBl, 0, "Read MIFARE classic block"}, {"rdbl", CmdHF14AMfRdBl, 0, "Read MIFARE classic block"},

View file

@ -36,35 +36,35 @@
extern int CmdHFMF(const char *Cmd); extern int CmdHFMF(const char *Cmd);
extern int CmdHF14AMfList(const char *Cmd); extern int CmdHF14AMfList(const char *Cmd);
extern int CmdHF14AMfDbg(const char *cmd); extern int CmdHF14AMfDbg(const char *Cmd);
extern int CmdHF14AMfRdBl(const char *cmd); extern int CmdHF14AMfRdBl(const char *Cmd);
extern int CmdHF14AMfURdBl(const char *cmd); extern int CmdHF14AMfURdBl(const char *Cmd);
extern int CmdHF14AMfRdSc(const char *cmd); extern int CmdHF14AMfRdSc(const char *Cmd);
extern int CmdHF14SMfURdCard(const char *cmd); extern int CmdHF14SMfURdCard(const char *Cmd);
extern int CmdHF14AMfDump(const char *cmd); extern int CmdHF14AMfDump(const char *Cmd);
extern int CmdHF14AMfRestore(const char *cmd); extern int CmdHF14AMfRestore(const char *Cmd);
extern int CmdHF14AMfWrBl(const char *cmd); extern int CmdHF14AMfWrBl(const char *Cmd);
extern int CmdHF14AMfUWrBl(const char *cmd); extern int CmdHF14AMfUWrBl(const char *Cmd);
extern int CmdHF14AMfChk(const char *cmd); extern int CmdHF14AMfChk(const char *Cmd);
extern int CmdHF14AMfDarkside(const char *cmd); extern int CmdHF14AMfDarkside(const char *Cmd);
extern int CmdHF14AMfNested(const char *cmd); extern int CmdHF14AMfNested(const char *Cmd);
extern int CmdHF14AMfNestedHard(const char *Cmd); extern int CmdHF14AMfNestedHard(const char *Cmd);
//extern int CmdHF14AMfSniff(const char* cmd); //extern int CmdHF14AMfSniff(const char* Cmd);
extern int CmdHF14AMf1kSim(const char *cmd); extern int CmdHF14AMf1kSim(const char *Cmd);
extern int CmdHF14AMfKeyBrute(const char *Cmd); extern int CmdHF14AMfKeyBrute(const char *Cmd);
extern int CmdHF14AMfEClear(const char *cmd); extern int CmdHF14AMfEClear(const char *Cmd);
extern int CmdHF14AMfEGet(const char *cmd); extern int CmdHF14AMfEGet(const char *Cmd);
extern int CmdHF14AMfESet(const char *cmd); extern int CmdHF14AMfESet(const char *Cmd);
extern int CmdHF14AMfELoad(const char *cmd); extern int CmdHF14AMfELoad(const char *Cmd);
extern int CmdHF14AMfESave(const char *cmd); extern int CmdHF14AMfESave(const char *Cmd);
extern int CmdHF14AMfECFill(const char *cmd); extern int CmdHF14AMfECFill(const char *Cmd);
extern int CmdHF14AMfEKeyPrn(const char *cmd); extern int CmdHF14AMfEKeyPrn(const char *Cmd);
extern int CmdHF14AMfCSetUID(const char *cmd); extern int CmdHF14AMfCSetUID(const char *Cmd);
extern int CmdHF14AMfCSetBlk(const char *cmd); extern int CmdHF14AMfCSetBlk(const char *Cmd);
extern int CmdHF14AMfCGetBlk(const char *cmd); extern int CmdHF14AMfCGetBlk(const char *Cmd);
extern int CmdHF14AMfCGetSc(const char *cmd); extern int CmdHF14AMfCGetSc(const char *Cmd);
extern int CmdHF14AMfCLoad(const char *cmd); extern int CmdHF14AMfCLoad(const char *Cmd);
extern int CmdHF14AMfCSave(const char *cmd); extern int CmdHF14AMfCSave(const char *Cmd);
extern int CmdHf14MfDecryptBytes(const char *Cmd); extern int CmdHf14MfDecryptBytes(const char *Cmd);
extern int CmdHf14AMfSetMod(const char *Cmd); extern int CmdHf14AMfSetMod(const char *Cmd);
extern int CmdHf14AMfNack(const char *Cmd); extern int CmdHf14AMfNack(const char *Cmd);

View file

@ -1013,7 +1013,8 @@ static bool shrink_key_space(float *brute_forces) {
//iceman 2018 //iceman 2018
return ((hardnested_stage & CHECK_2ND_BYTES) && return ((hardnested_stage & CHECK_2ND_BYTES) &&
reduction_rate >= 0.0 && reduction_rate >= 0.0 &&
(reduction_rate < brute_force_per_second * (float)sample_period / 1000.0 || *brute_forces < 0x1F00000000)); (reduction_rate < brute_force_per_second * (float)sample_period / 1000.0 || *brute_forces < 0xF00000));
} }
@ -1073,7 +1074,7 @@ static int read_nonce_file(char *filename) {
fclose(fnonces); fclose(fnonces);
char progress_string[80]; char progress_string[80];
sprintf(progress_string, "Read %d nonces from file. cuid=%08x", num_acquired_nonces, cuid); sprintf(progress_string, "Read %u nonces from file. cuid = %08x", num_acquired_nonces, cuid);
hardnested_print_progress(num_acquired_nonces, progress_string, (float)(1LL << 47), 0); hardnested_print_progress(num_acquired_nonces, progress_string, (float)(1LL << 47), 0);
sprintf(progress_string, "Target Block=%d, Keytype=%c", trgBlockNo, trgKeyType == 0 ? 'A' : 'B'); sprintf(progress_string, "Target Block=%d, Keytype=%c", trgBlockNo, trgKeyType == 0 ? 'A' : 'B');
hardnested_print_progress(num_acquired_nonces, progress_string, (float)(1LL << 47), 0); hardnested_print_progress(num_acquired_nonces, progress_string, (float)(1LL << 47), 0);
@ -1353,7 +1354,7 @@ static void simulate_acquire_nonces() {
// difftime(end_time, time1)!=0.0?(float)total_num_nonces*60.0/difftime(end_time, time1):INFINITY // difftime(end_time, time1)!=0.0?(float)total_num_nonces*60.0/difftime(end_time, time1):INFINITY
// ); // );
fprintf(fstats, "%" PRId32 ";%" PRId32 ";%1.0f;", total_num_nonces, num_acquired_nonces, difftime(end_time, time1)); fprintf(fstats, "%" PRIu32 ";%" PRIu32 ";%1.0f;", total_num_nonces, num_acquired_nonces, difftime(end_time, time1));
} }

View file

@ -84,10 +84,15 @@ void transform_D(uint8_t *ru) {
uint32_t v1 = ((ru[3] << 24) | (ru[2] << 16) | (ru[1] << 8) | ru[0]) + c_D[p++]; uint32_t v1 = ((ru[3] << 24) | (ru[2] << 16) | (ru[1] << 8) | ru[0]) + c_D[p++];
uint32_t v2 = ((ru[7] << 24) | (ru[6] << 16) | (ru[5] << 8) | ru[4]) + c_D[p++]; uint32_t v2 = ((ru[7] << 24) | (ru[6] << 16) | (ru[5] << 8) | ru[4]) + c_D[p++];
for (i = 0; i < 12; i += 2) { for (i = 0; i < 12; i += 2) {
uint32_t t1 = ROTL(v1 ^ v2, v2 & 0x1F) + c_D[p++];
uint32_t t2 = ROTL(v2 ^ t1, t1 & 0x1F) + c_D[p++]; uint32_t xor1 = v1 ^ v2;
v1 = ROTL(t1 ^ t2, t2 & 0x1F) + c_D[p++]; uint32_t t1 = ROTL(xor1, v2 & 0x1F) + c_D[p++];
v2 = ROTL(t2 ^ v1, v1 & 0x1F) + c_D[p++]; uint32_t xor2 = v2 ^ t1;
uint32_t t2 = ROTL(xor2, t1 & 0x1F) + c_D[p++];
uint32_t xor3 = t1 ^ t2;
uint32_t xor4 = t2 ^ v1;
v1 = ROTL(xor3, t2 & 0x1F) + c_D[p++];
v2 = ROTL(xor4, v1 & 0x1F) + c_D[p++];
} }
//Re-use ru //Re-use ru
@ -317,6 +322,9 @@ static int ul_read(uint8_t page, uint8_t *response, uint16_t responseLength) {
static int ul_comp_write(uint8_t page, uint8_t *data, uint8_t datalen) { static int ul_comp_write(uint8_t page, uint8_t *data, uint8_t datalen) {
if (data == NULL)
return -1;
uint8_t cmd[18]; uint8_t cmd[18];
memset(cmd, 0x00, sizeof(cmd)); memset(cmd, 0x00, sizeof(cmd));
datalen = (datalen > 16) ? 16 : datalen; datalen = (datalen > 16) ? 16 : datalen;
@ -325,7 +333,7 @@ static int ul_comp_write(uint8_t page, uint8_t *data, uint8_t datalen) {
cmd[1] = page; cmd[1] = page;
memcpy(cmd + 2, data, datalen); memcpy(cmd + 2, data, datalen);
uint8_t response[1] = {0xff}; uint8_t response[1] = {0xFF};
ul_send_cmd_raw(cmd, 2 + datalen, response, sizeof(response)); ul_send_cmd_raw(cmd, 2 + datalen, response, sizeof(response));
// ACK // ACK
if (response[0] == 0x0a) return 0; if (response[0] == 0x0a) return 0;
@ -943,7 +951,7 @@ int CmdHF14AMfUInfo(const char *Cmd) {
uint8_t pwd[4] = {0, 0, 0, 0}; uint8_t pwd[4] = {0, 0, 0, 0};
uint8_t *key = pwd; uint8_t *key = pwd;
uint8_t pack[4] = {0, 0, 0, 0}; uint8_t pack[4] = {0, 0, 0, 0};
int len = 0; int len;
char tempStr[50]; char tempStr[50];
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {

View file

@ -70,8 +70,8 @@ int usage_lf_config(void) {
PrintAndLogEx(NORMAL, " a resolution of 4 bits per sample."); PrintAndLogEx(NORMAL, " a resolution of 4 bits per sample.");
PrintAndLogEx(NORMAL, " lf read"); PrintAndLogEx(NORMAL, " lf read");
PrintAndLogEx(NORMAL, " Performs a read (active field)"); PrintAndLogEx(NORMAL, " Performs a read (active field)");
PrintAndLogEx(NORMAL, " lf snoop"); PrintAndLogEx(NORMAL, " lf sniff");
PrintAndLogEx(NORMAL, " Performs a snoop (no active field)"); PrintAndLogEx(NORMAL, " Performs a sniff (no active field)");
return 0; return 0;
} }
int usage_lf_simfsk(void) { int usage_lf_simfsk(void) {
@ -389,7 +389,7 @@ int CmdLFSniff(const char *Cmd) {
uint8_t cmdp = tolower(param_getchar(Cmd, 0)); uint8_t cmdp = tolower(param_getchar(Cmd, 0));
if (cmdp == 'h') return usage_lf_sniff(); if (cmdp == 'h') return usage_lf_sniff();
UsbCommand c = {CMD_LF_SNOOP_RAW_ADC_SAMPLES, {0, 0, 0}}; UsbCommand c = {CMD_LF_SNIFF_RAW_ADC_SAMPLES, {0, 0, 0}};
clearCommandBuffer(); clearCommandBuffer();
SendCommand(&c); SendCommand(&c);
WaitForResponse(CMD_ACK, NULL); WaitForResponse(CMD_ACK, NULL);
@ -471,7 +471,7 @@ int CmdLFfskSim(const char *Cmd) {
cmdp += 2; cmdp += 2;
break; break;
case 's': case 's':
separator = 1; separator = true;
cmdp++; cmdp++;
break; break;
case 'd': case 'd':
@ -519,7 +519,7 @@ int CmdLFfskSim(const char *Cmd) {
uint16_t arg1, arg2; uint16_t arg1, arg2;
arg1 = fcHigh << 8 | fcLow; arg1 = fcHigh << 8 | fcLow;
arg2 = separator << 8 | clk; arg2 = (separator << 8) | clk;
size_t size = DemodBufferLen; size_t size = DemodBufferLen;
if (size > USB_CMD_DATA_SIZE) { if (size > USB_CMD_DATA_SIZE) {
PrintAndLogEx(NORMAL, "DemodBuffer too long for current implementation - length: %d - max: %d", size, USB_CMD_DATA_SIZE); PrintAndLogEx(NORMAL, "DemodBuffer too long for current implementation - length: %d - max: %d", size, USB_CMD_DATA_SIZE);
@ -707,7 +707,7 @@ int CmdLFpskSim(const char *Cmd) {
setDemodBuf(data, dataLen, 0); setDemodBuf(data, dataLen, 0);
} }
if (clk <= 0) clk = 32; if (clk == 0) clk = 32;
if (carrier != 2 && carrier != 4 && carrier != 8) if (carrier != 2 && carrier != 4 && carrier != 8)
carrier = 2; carrier = 2;
@ -884,24 +884,24 @@ int CmdLFfind(const char *Cmd) {
// The improved noise detection will find Cotag. // The improved noise detection will find Cotag.
if (getSignalProperties()->isnoise) { if (getSignalProperties()->isnoise) {
PrintAndLogEx(INFO, "Signal looks just like noise. Looking for Hitag signal now.");
// 26 === RHT2F_UID_ONLY
if (CmdLFHitagReader("26") == 0) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Hitag") " found!"); return 1;} if (CmdLFHitagReader("26") == 0) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Hitag") " found!"); return 1;}
if (CmdCOTAGRead("") > 0) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("COTAG ID") " found!"); return 1;} if (CmdCOTAGRead("") > 0) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("COTAG ID") " found!"); return 1;}
PrintAndLogEx(FAILED, "\nNo data found! - maybe not an LF tag?"); PrintAndLogEx(FAILED, "\n" _YELLOW_("No data found!") " - Signal looks like noise. Maybe not an LF tag?");
return 0; return 0;
} }
} }
if (EM4x50Read("", false)) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("EM4x50 ID") " found!"); return 1;} if (EM4x50Read("", false)) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("EM4x50 ID") " found!"); return 1;}
if (CmdHIDDemod("")) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("HID Prox ID") " found!"); goto out;}
if (CmdAWIDDemod("")) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("AWID ID") " found!"); goto out;} if (CmdAWIDDemod("")) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("AWID ID") " found!"); goto out;}
if (CmdParadoxDemod("")) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Paradox ID") " found!"); goto out;}
if (CmdEM410xDemod("")) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("EM410x ID") " found!"); goto out;} if (CmdEM410xDemod("")) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("EM410x ID") " found!"); goto out;}
if (CmdFdxDemod("")) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("FDX-B ID") " found!"); goto out;} if (CmdFdxDemod("")) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("FDX-B ID") " found!"); goto out;}
if (CmdGuardDemod("")) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Guardall G-Prox II ID") " found!"); goto out; } if (CmdGuardDemod("")) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Guardall G-Prox II ID") " found!"); goto out; }
if (CmdHIDDemod("")) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("HID Prox ID") " found!"); goto out;} if (CmdIdteckDemod("")) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Idteck ID") " found!"); goto out;}
if (CmdPSKIdteck("")) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Idteck ID") " found!"); goto out;}
if (CmdIndalaDemod("")) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Indala ID") " found!"); goto out;} if (CmdIndalaDemod("")) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Indala ID") " found!"); goto out;}
if (CmdIOProxDemod("")) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("IO Prox ID") " found!"); goto out;} if (CmdIOProxDemod("")) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("IO Prox ID") " found!"); goto out;}
if (CmdJablotronDemod("")) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Jablotron ID") " found!"); goto out;} if (CmdJablotronDemod("")) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Jablotron ID") " found!"); goto out;}
@ -910,7 +910,7 @@ int CmdLFfind(const char *Cmd) {
if (CmdNoralsyDemod("")) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Noralsy ID") " found!"); goto out;} if (CmdNoralsyDemod("")) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Noralsy ID") " found!"); goto out;}
if (CmdKeriDemod("")) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("KERI ID") " found!"); goto out;} if (CmdKeriDemod("")) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("KERI ID") " found!"); goto out;}
if (CmdPacDemod("")) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("PAC/Stanley ID") " found!"); goto out;} if (CmdPacDemod("")) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("PAC/Stanley ID") " found!"); goto out;}
if (CmdParadoxDemod("")) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Paradox ID") " found!"); goto out;}
if (CmdPrescoDemod("")) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Presco ID") " found!"); goto out;} if (CmdPrescoDemod("")) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Presco ID") " found!"); goto out;}
if (CmdPyramidDemod("")) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Pyramid ID") " found!"); goto out;} if (CmdPyramidDemod("")) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Pyramid ID") " found!"); goto out;}
if (CmdSecurakeyDemod("")) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Securakey ID") " found!"); goto out;} if (CmdSecurakeyDemod("")) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Securakey ID") " found!"); goto out;}
@ -945,19 +945,19 @@ int CmdLFfind(const char *Cmd) {
bool st = true; bool st = true;
if (ASKDemod_ext("0 0 0", true, false, 1, &st)) { if (ASKDemod_ext("0 0 0", true, false, 1, &st)) {
PrintAndLogEx(NORMAL, "\nUnknown ASK Modulated and Manchester encoded Tag found!"); PrintAndLogEx(NORMAL, "\nUnknown ASK Modulated and Manchester encoded Tag found!");
PrintAndLogEx(NORMAL, "if it does not look right it could instead be ASK/Biphase - try " _YELLOW_("'data rawdemod ab'") ); PrintAndLogEx(NORMAL, "if it does not look right it could instead be ASK/Biphase - try " _YELLOW_("'data rawdemod ab'"));
goto out; goto out;
} }
if (CmdPSK1rawDemod("")) { if (CmdPSK1rawDemod("")) {
PrintAndLogEx(NORMAL, "Possible unknown PSK1 Modulated Tag found above!"); PrintAndLogEx(NORMAL, "Possible unknown PSK1 Modulated Tag found above!");
PrintAndLogEx(NORMAL, " Could also be PSK2 - try " _YELLOW_("'data rawdemod p2'") ); PrintAndLogEx(NORMAL, " Could also be PSK2 - try " _YELLOW_("'data rawdemod p2'"));
PrintAndLogEx(NORMAL, " Could also be PSK3 - [currently not supported]"); PrintAndLogEx(NORMAL, " Could also be PSK3 - [currently not supported]");
PrintAndLogEx(NORMAL, " Could also be NRZ - try " _YELLOW_("'data rawdemod nr") ); PrintAndLogEx(NORMAL, " Could also be NRZ - try " _YELLOW_("'data rawdemod nr"));
goto out; goto out;
} }
PrintAndLogEx(FAILED, _RED_("\nNo data found!") ); PrintAndLogEx(FAILED, _RED_("\nNo data found!"));
} }
out: out:
// identify chipset // identify chipset

View file

@ -808,21 +808,21 @@ int EM4x50Read(const char *Cmd, bool verbose) {
low = sp->low; low = sp->low;
// get to first full low to prime loop and skip incomplete first pulse // get to first full low to prime loop and skip incomplete first pulse
while ((bits[i] < high) && (i < size)) while ((i < size) && (bits[i] < high))
++i; ++i;
while ((bits[i] > low) && (i < size)) while ((i < size) && (bits[i] > low))
++i; ++i;
skip = i; skip = i;
// populate tmpbuff buffer with pulse lengths // populate tmpbuff buffer with pulse lengths
while (i < size) { while (i < size) {
// measure from low to low // measure from low to low
while ((bits[i] > low) && (i < size)) while ((i < size) && (bits[i] > low))
++i; ++i;
start = i; start = i;
while ((bits[i] < high) && (i < size)) while ((i < size) && (bits[i] < high))
++i; ++i;
while ((bits[i] > low) && (i < size)) while ((i < size) && (bits[i] > low))
++i; ++i;
if (j >= (MAX_GRAPH_TRACE_LEN / 64)) { if (j >= (MAX_GRAPH_TRACE_LEN / 64)) {
break; break;
@ -1244,7 +1244,7 @@ int CmdEM4x05Write(const char *Cmd) {
PrintAndLogEx(NORMAL, "Writing address %d data %08X using password %08X", addr, data, pwd); PrintAndLogEx(NORMAL, "Writing address %d data %08X using password %08X", addr, data, pwd);
} }
uint16_t flag = (addr << 8) | usePwd; uint16_t flag = (addr << 8) | (usePwd);
UsbCommand c = {CMD_EM4X_WRITE_WORD, {flag, data, pwd}}; UsbCommand c = {CMD_EM4X_WRITE_WORD, {flag, data, pwd}};
clearCommandBuffer(); clearCommandBuffer();
@ -1486,8 +1486,8 @@ int CmdEM4x05Info(const char *Cmd) {
static command_t CommandTable[] = { static command_t CommandTable[] = {
{"help", CmdHelp, 1, "This help"}, {"help", CmdHelp, 1, "This help"},
//{"410x_demod", CmdEMdemodASK, 0, "Extract ID from EM410x tag on antenna)"}, //{"410x_demod", CmdEMdemodASK, 0, "Extract ID from EM410x tag on antenna)"},
{"410x_demod", CmdEM410xDemod, 0, "demodulate a EM410x tag from the GraphBuffer"}, {"410x_demod", CmdEM410xDemod, 1, "demodulate a EM410x tag from the GraphBuffer"},
{"410x_read", CmdEM410xRead, 1, "attempt to read and extract tag data"}, {"410x_read", CmdEM410xRead, 0, "attempt to read and extract tag data"},
{"410x_sim", CmdEM410xSim, 0, "simulate EM410x tag"}, {"410x_sim", CmdEM410xSim, 0, "simulate EM410x tag"},
{"410x_brute", CmdEM410xBrute, 0, "reader bruteforce attack by simulating EM410x tags"}, {"410x_brute", CmdEM410xBrute, 0, "reader bruteforce attack by simulating EM410x tags"},
{"410x_watch", CmdEM410xWatch, 0, "watches for EM410x 125/134 kHz tags (option 'h' for 134)"}, {"410x_watch", CmdEM410xWatch, 0, "watches for EM410x 125/134 kHz tags (option 'h' for 134)"},

View file

@ -160,7 +160,7 @@ int getFDXBits(uint64_t national_id, uint16_t country, uint8_t isanimal, uint8_t
int CmdFDXBdemodBI(const char *Cmd) { int CmdFDXBdemodBI(const char *Cmd) {
int clk = 32; int clk = 32;
int invert = 1, errCnt = 0, offset = 0, maxErr = 0; int invert = 1, errCnt = 0, offset = 0, maxErr = 100;
uint8_t bs[MAX_DEMOD_BUF_LEN]; uint8_t bs[MAX_DEMOD_BUF_LEN];
size_t size = getFromGraphBuf(bs); size_t size = getFromGraphBuf(bs);
@ -236,7 +236,7 @@ int CmdFdxDemod(const char *Cmd) {
//Differential Biphase / di-phase (inverted biphase) //Differential Biphase / di-phase (inverted biphase)
//get binary from ask wave //get binary from ask wave
if (!ASKbiphaseDemod("0 32 1 0", false)) { if (!ASKbiphaseDemod("0 32 1 100", false)) {
PrintAndLogEx(DEBUG, "DEBUG: Error - FDX-B ASKbiphaseDemod failed"); PrintAndLogEx(DEBUG, "DEBUG: Error - FDX-B ASKbiphaseDemod failed");
return 0; return 0;
} }

View file

@ -297,6 +297,8 @@ int CmdHIDClone(const char *Cmd) {
SendCommand(&c); SendCommand(&c);
return 0; return 0;
} }
/*
// struct to handle wiegand // struct to handle wiegand
typedef struct { typedef struct {
uint8_t FormatLen; uint8_t FormatLen;
@ -306,6 +308,7 @@ typedef struct {
uint8_t *Wiegand; uint8_t *Wiegand;
size_t Wiegand_n; size_t Wiegand_n;
} wiegand_t; } wiegand_t;
*/
static void addHIDMarker(uint8_t fmtlen, uint8_t *out) { static void addHIDMarker(uint8_t fmtlen, uint8_t *out) {
// temp array // temp array

View file

@ -17,20 +17,65 @@
#include "common.h" #include "common.h"
#include "util.h" #include "util.h"
#include "parity.h" #include "parity.h"
#include "hitag2.h" #include "hitag.h"
#include "hitagS.h"
#include "util_posix.h" #include "util_posix.h"
#include "comms.h" #include "comms.h"
#include "cmddata.h" #include "cmddata.h"
#include "loclass/fileutils.h" // savefile
static int CmdHelp(const char *Cmd); static int CmdHelp(const char *Cmd);
size_t nbytes(size_t nbits) { size_t nbytes(size_t nbits) {
return (nbits / 8) + ((nbits % 8) > 0); return (nbits / 8) + ((nbits % 8) > 0);
} }
int usage_hitag_sniff(void) {
int usage_hitag_reader(void) PrintAndLogEx(NORMAL, "Sniff traffic between Hitag reader and tag. Use " _YELLOW_("`lf hitag list`")" to view collected data.");
{ PrintAndLogEx(NORMAL, "Usage: lf hitag sniff [h] ");
PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h This help");
// PrintAndLogEx(NORMAL, " p <pwd> Password");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, " lf hitag sniff");
return 0;
}
int usage_hitag_sim(void) {
PrintAndLogEx(NORMAL, "Simulate " _YELLOW_("Hitag2 / HitagS")" transponder");
PrintAndLogEx(NORMAL, "Usage: lf hitag sim [h] [2|s] e|j|b <filename w/o extension>");
PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h This help");
PrintAndLogEx(NORMAL, " [2|s] 2 = hitag2, s = hitagS");
PrintAndLogEx(NORMAL, " e <filename> Load data from EML file");
PrintAndLogEx(NORMAL, " j <filename> Load data from JSON file");
PrintAndLogEx(NORMAL, " b <filename> Load data from BIN file");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, " lf hitag sim 2 b lf-hitag-dump");
return 0;
}
int usage_hitag_info(void) {
PrintAndLogEx(NORMAL, "Usage: lf hitag info [h] p <pwd>");
PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h This help");
PrintAndLogEx(NORMAL, " p <pwd> password");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, " lf hitag info");
return 0;
}
int usage_hitag_dump(void) {
PrintAndLogEx(NORMAL, "Usage: lf hitag dump [h] p <pwd> f <name>");
PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h This help");
// PrintAndLogEx(NORMAL, " p <pwd> password");
// PrintAndLogEx(NORMAL, " f <name> data filename, if no <name> given, UID will be used as filename");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, " lf hitag dump f mydump");
PrintAndLogEx(NORMAL, " lf hitag dump p 4D494B52 f mydump");
return 0;
}
int usage_hitag_reader(void) {
PrintAndLogEx(NORMAL, "Hitag reader functions");
PrintAndLogEx(NORMAL, "Usage: lf hitag reader [h] <reader function #>"); PrintAndLogEx(NORMAL, "Usage: lf hitag reader [h] <reader function #>");
PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h This help"); PrintAndLogEx(NORMAL, " h This help");
@ -46,8 +91,38 @@ int usage_hitag_reader(void)
PrintAndLogEx(NORMAL, " 26 Just read UID"); PrintAndLogEx(NORMAL, " 26 Just read UID");
return 0; return 0;
} }
int usage_hitag_writer(void) {
PrintAndLogEx(NORMAL, "Hitag writer functions");
PrintAndLogEx(NORMAL, "Usage: lf hitag write [h] <reader function #>");
PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h This help");
PrintAndLogEx(NORMAL, " HitagS (0*)");
PrintAndLogEx(NORMAL, " 03 <nr,ar> (Challenge) <page> <byte0...byte3> write page on a Hitag S tag");
PrintAndLogEx(NORMAL, " 04 <key> (set to 0 if no authentication is needed) <page> <byte0...byte3> write page on a Hitag S tag");
PrintAndLogEx(NORMAL, " Hitag1 (1*)");
PrintAndLogEx(NORMAL, " Hitag2 (2*)");
PrintAndLogEx(NORMAL, " 24 <key> (set to 0 if no authentication is needed) <page> <byte0...byte3> write page on a Hitag2 tag");
return 0;
}
int usage_hitag_checkchallenges(void) {
PrintAndLogEx(NORMAL, "Check challenges, load a file with save hitag crypto challenges and test them all.");
PrintAndLogEx(NORMAL, "The file should be 8 * 60 bytes long, the file extension defaults to " _YELLOW_("`.cc`"));
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Usage: lf hitag cc [h] f <filename w/o extension>");
PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h This help");
PrintAndLogEx(NORMAL, " f <filename> Load data from BIN file");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, " lf hitag cc f lf-hitag-challenges");
return 0;
}
int CmdLFHitagList(const char *Cmd) { int CmdLFHitagList(const char *Cmd) {
CmdTraceList("hitag");
return 0;
/*
uint8_t *got = calloc(USB_CMD_DATA_SIZE, sizeof(uint8_t)); uint8_t *got = calloc(USB_CMD_DATA_SIZE, sizeof(uint8_t));
if (!got) { if (!got) {
PrintAndLogEx(WARNING, "Cannot allocate memory for trace"); PrintAndLogEx(WARNING, "Cannot allocate memory for trace");
@ -172,10 +247,15 @@ int CmdLFHitagList(const char *Cmd) {
free(got); free(got);
return 0; return 0;
*/
} }
int CmdLFHitagSnoop(const char *Cmd) { int CmdLFHitagSniff(const char *Cmd) {
UsbCommand c = {CMD_SNOOP_HITAG};
char ctmp = tolower(param_getchar(Cmd, 0));
if (ctmp == 'h') return usage_hitag_sniff();
UsbCommand c = {CMD_SNIFF_HITAG, {0, 0, 0}};
clearCommandBuffer(); clearCommandBuffer();
SendCommand(&c); SendCommand(&c);
return 0; return 0;
@ -183,40 +263,249 @@ int CmdLFHitagSnoop(const char *Cmd) {
int CmdLFHitagSim(const char *Cmd) { int CmdLFHitagSim(const char *Cmd) {
UsbCommand c = {CMD_SIMULATE_HITAG}; bool errors = false;
bool tag_mem_supplied = false;
uint8_t cmdp = 0;
size_t maxdatalen = 48;
uint8_t *data = calloc(4 * 64, sizeof(uint8_t));
size_t datalen = 0;
int res = 0;
char filename[FILE_PATH_SIZE] = { 0x00 }; char filename[FILE_PATH_SIZE] = { 0x00 };
FILE *f;
bool tag_mem_supplied;
int len = strlen(Cmd); UsbCommand c = {CMD_SIMULATE_HITAG, {0, 0, 0}};
if (len > FILE_PATH_SIZE) len = FILE_PATH_SIZE;
memcpy(filename, Cmd, len);
if (strlen(filename) > 0) { while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
f = fopen(filename, "rb+"); switch (tolower(param_getchar(Cmd, cmdp))) {
if (!f) { case 'h':
PrintAndLogEx(WARNING, "Error: Could not open file [%s]", filename); free(data);
return 1; return usage_hitag_sim();
case '2':
maxdatalen = 48;
cmdp++;
break;
case 's':
c.cmd = CMD_SIMULATE_HITAG_S;
maxdatalen = 4 * 64;
cmdp++;
break;
case 'e':
param_getstr(Cmd, cmdp + 1, filename, sizeof(filename));
res = loadFileEML(filename, "eml", data, &datalen);
if (res > 0 || datalen != maxdatalen) {
PrintAndLogDevice(FAILED, "error, bytes read mismatch file size");
errors = true;
break;
} }
tag_mem_supplied = true; tag_mem_supplied = true;
size_t bytes_read = fread(c.d.asBytes, 1, 48, f); cmdp += 2;
if (bytes_read == 48) { break;
PrintAndLogEx(WARNING, "Error: File reading error"); case 'j':
fclose(f); param_getstr(Cmd, cmdp + 1, filename, sizeof(filename));
return 1; res = loadFileJSON(filename, "json", data, maxdatalen, &datalen);
if (res > 0) {
errors = true;
break;
}
tag_mem_supplied = true;
cmdp += 2;
break;
case 'b':
param_getstr(Cmd, cmdp + 1, filename, sizeof(filename));
res = loadFile(filename, "bin", data, maxdatalen, &datalen);
if (res > 0) {
errors = true;
break;
}
tag_mem_supplied = true;
cmdp += 2;
break;
default:
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
errors = true;
break;
} }
fclose(f);
} else {
tag_mem_supplied = false;
} }
// Does the tag comes with memory //Validations
if (errors || cmdp == 0) {
free(data);
return usage_hitag_sim();
}
c.arg[0] = (uint32_t)tag_mem_supplied; c.arg[0] = (uint32_t)tag_mem_supplied;
if (tag_mem_supplied) {
memcpy(c.d.asBytes, data, datalen);
}
clearCommandBuffer(); clearCommandBuffer();
SendCommand(&c); SendCommand(&c);
free(data);
return 0; return 0;
} }
static void printHitagConfiguration(uint8_t config) {
char msg[100];
memset(msg, 0, sizeof(msg));
char bits[9];
char *bs = bits;
for (uint8_t i = 0 ; i < 8 ; i++) {
snprintf(bs, sizeof(bits) - i, "%1d", (config >> (7 - i)) & 1);
bs++;
}
PrintAndLogEx(INFO, "\n\nHitag2 tag information ");
PrintAndLogEx(INFO, "------------------------------------");
//configuration byte
PrintAndLogEx(SUCCESS, "Config byte : 0x%02X [ %s ]", config, bits);
// encoding
strcat(msg, "Encoding : ");
if (config & 0x1) {
strcat(msg + strlen(msg), _YELLOW_("Biphase"));
} else {
strcat(msg + strlen(msg), _YELLOW_("Manchester"));
}
PrintAndLogEx(SUCCESS, "%s", msg);
memset(msg, 0, sizeof(msg));
// version
strcat(msg, "Coding in HITAG 2 operation: %s");
uint8_t foo = (config & 0x6) >> 1;
switch (foo) {
case 0:
PrintAndLogEx(SUCCESS, "Version : public mode B, Coding: biphase");
PrintAndLogEx(SUCCESS, msg, (config & 0x1) ? "biphase" : "manchester");
break;
case 1:
PrintAndLogEx(SUCCESS, "Version : public mode A, Coding: manchester");
PrintAndLogEx(SUCCESS, msg, (config & 0x1) ? "biphase" : "manchester");
break;
case 2:
PrintAndLogEx(SUCCESS, "Version : public mode C, Coding: biphase");
PrintAndLogEx(SUCCESS, msg, (config & 0x1) ? "biphase" : "manchester");
break;
case 3:
PrintAndLogEx(SUCCESS, "Version : Hitag2");
PrintAndLogEx(SUCCESS, msg, (config & 0x1) ? "biphase" : "manchester");
break;
}
memset(msg, 0, sizeof(msg));
// mode
strcat(msg, "Tag is in : ");
if (config & 0x8) {
strcat(msg + strlen(msg), _YELLOW_("Crypto mode"));
} else {
strcat(msg + strlen(msg), _YELLOW_("Password mode"));
}
PrintAndLogEx(SUCCESS, "%s", msg);
memset(msg, 0, sizeof(msg));
// page access
strcat(msg, "Page 6,7 : ");
if (config & 0x10) {
strcat(msg + strlen(msg), "read only");
} else {
strcat(msg + strlen(msg), _GREEN_("read write"));
}
PrintAndLogEx(SUCCESS, "%s", msg);
memset(msg, 0, sizeof(msg));
// page access
strcat(msg, "Page 4,5 : ");
if (config & 0x20) {
strcat(msg + strlen(msg), "read only");
} else {
strcat(msg + strlen(msg), _GREEN_("read write"));
}
PrintAndLogEx(SUCCESS, "%s", msg);
memset(msg, 0, sizeof(msg));
// OTP
strcat(msg, "Page 3 : ");
if (config & 0x40) {
strcat(msg + strlen(msg), "read only. Configuration byte and password tag " _RED_("FIXED / IRREVERSIBLE"));
} else {
strcat(msg + strlen(msg), _GREEN_("read write"));
}
PrintAndLogEx(SUCCESS, "%s", msg);
memset(msg, 0, sizeof(msg));
// OTP
if (config & 0x80) {
strcat(msg, "Page 1 : " _RED_("locked") "\n");
strcat(msg + strlen(msg), "Page 2 : ");
if (config & 0x8) {
strcat(msg + strlen(msg), _RED_("locked"));
} else {
strcat(msg + strlen(msg), "read only");
}
} else {
strcat(msg, "Page 1,2 : " _GREEN_("read write"));
}
PrintAndLogEx(SUCCESS, "%s", msg);
PrintAndLogEx(INFO, "------------------------------------");
}
static bool getHitagUid(uint32_t *uid) {
UsbCommand c = {CMD_READER_HITAG, {RHT2F_UID_ONLY, 0, 0} };
clearCommandBuffer();
SendCommand(&c);
UsbCommand resp;
if (!WaitForResponseTimeout(CMD_ACK, &resp, 2500)) {
PrintAndLogEx(WARNING, "timeout while waiting for reply.");
return false;
}
if (resp.arg[0] == false) {
PrintAndLogEx(DEBUG, "DEBUG: Error - failed getting UID");
return false;
}
if ( uid )
*uid = bytes_to_num(resp.d.asBytes, 4);
return true;
}
int CmdLFHitagInfo(const char *Cmd) {
PrintAndLogEx(INFO, "Hitag2 tag information ");
PrintAndLogEx(INFO, "To be done!");
PrintAndLogEx(INFO, "------------------------------------");
char ctmp = tolower(param_getchar(Cmd, 0));
if (ctmp == 'h') return usage_hitag_info();
// pwd or key
// read UID
uint32_t uid = 0;
if ( getHitagUid( &uid ) == false )
return 1;
PrintAndLogEx(SUCCESS, "UID: %08X", uid);
// how to detemine Hitag types?
// read block3, get configuration byte.
// common configurations.
printHitagConfiguration(0x06);
//printHitagConfiguration( 0x0E );
//printHitagConfiguration( 0x02 );
//printHitagConfiguration( 0x00 );
//printHitagConfiguration( 0x04 );
return 0;
}
// TODO: iceman
// Hitag2 reader, problem is that this command mixes up stuff. So 26 give uid. 21 etc will also give you a memory dump !?
//
int CmdLFHitagReader(const char *Cmd) { int CmdLFHitagReader(const char *Cmd) {
UsbCommand c = {CMD_READER_HITAG, {0, 0, 0} }; UsbCommand c = {CMD_READER_HITAG, {0, 0, 0} };
@ -257,7 +546,6 @@ int CmdLFHitagReader(const char *Cmd) {
break; break;
} }
default: { default: {
PrintAndLogEx(NORMAL, "\nError: unkown reader function %d", htf);
return usage_hitag_reader(); return usage_hitag_reader();
} }
} }
@ -278,150 +566,136 @@ int CmdLFHitagReader(const char *Cmd) {
uint32_t id = bytes_to_num(resp.d.asBytes, 4); uint32_t id = bytes_to_num(resp.d.asBytes, 4);
if (htf == RHT2F_UID_ONLY) { PrintAndLogEx(SUCCESS, "Valid Hitag2 tag found - UID: %08x", id);
PrintAndLogEx(NORMAL, "Valid Hitag2 tag found - UID: %08x", id); if (htf != RHT2F_UID_ONLY) {
} else {
PrintAndLogEx(SUCCESS, "Dumping tag memory..." );
uint8_t *data = resp.d.asBytes;
char filename[FILE_PATH_SIZE]; char filename[FILE_PATH_SIZE];
FILE *f = NULL; char *fnameptr = filename;
sprintf(filename, "%08x_%04x.ht2", id, (rand() & 0xffff)); fnameptr += sprintf(fnameptr, "lf-hitag-");
f = fopen(filename, "wb"); FillFileNameByUID(fnameptr, data, "-dump", 4);
if (!f) {
PrintAndLogEx(WARNING, "Error: Could not open file [%s]", filename);
return 1;
}
// Write the 48 tag memory bytes to file and finalize saveFile(filename, "bin", data, 48);
fwrite(resp.d.asBytes, 1, 48, f); saveFileEML(filename, "eml", data, 48, 4);
fclose(f); saveFileJSON(filename, "json", jsfHitag, data, 48);
PrintAndLogEx(NORMAL, "Succesfully saved tag memory to [%s]", filename);
}
return 0;
}
int CmdLFHitagSimS(const char *Cmd) { // block3, 1 byte
UsbCommand c = { CMD_SIMULATE_HITAG_S }; printHitagConfiguration(data[4*3] );
char filename[FILE_PATH_SIZE] = { 0x00 };
FILE *f;
bool tag_mem_supplied;
int len = strlen(Cmd);
if (len > FILE_PATH_SIZE)
len = FILE_PATH_SIZE;
memcpy(filename, Cmd, len);
if (strlen(filename) > 0) {
f = fopen(filename, "rb+");
if (!f) {
PrintAndLogEx(WARNING, "Error: Could not open file [%s]", filename);
return 1;
} }
tag_mem_supplied = true;
size_t bytes_read = fread(c.d.asBytes, 1, 4 * 64, f);
if (bytes_read == 4 * 64) {
PrintAndLogEx(WARNING, "Error: File reading error");
fclose(f);
return 1;
}
fclose(f);
} else {
tag_mem_supplied = false;
}
// Does the tag comes with memory
c.arg[0] = (uint32_t) tag_mem_supplied;
clearCommandBuffer();
SendCommand(&c);
return 0; return 0;
} }
int CmdLFHitagCheckChallenges(const char *Cmd) { int CmdLFHitagCheckChallenges(const char *Cmd) {
UsbCommand c = { CMD_TEST_HITAGS_TRACES };
char filename[FILE_PATH_SIZE] = { 0x00 };
FILE *f;
bool file_given;
int len = strlen(Cmd);
if (len > FILE_PATH_SIZE)
len = FILE_PATH_SIZE;
memcpy(filename, Cmd, len);
if (strlen(filename) > 0) { UsbCommand c = { CMD_TEST_HITAGS_TRACES, {0, 0, 0}};
f = fopen(filename, "rb+"); char filename[FILE_PATH_SIZE] = { 0x00 };
if (!f) { size_t datalen = 0;
PrintAndLogEx(WARNING, "Error: Could not open file [%s]", filename); int res = 0;
return 1; bool file_given = false;
bool errors = false;
uint8_t cmdp = 0;
uint8_t *data = calloc(8 * 60, sizeof(uint8_t));
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
switch (tolower(param_getchar(Cmd, cmdp))) {
case 'h':
free(data);
return usage_hitag_checkchallenges();
case 'f':
param_getstr(Cmd, cmdp + 1, filename, sizeof(filename));
res = loadFile(filename, "cc", data, 8 * 60, &datalen);
if (res > 0) {
errors = true;
break;
} }
memcpy(c.d.asBytes, data, datalen);
file_given = true; file_given = true;
size_t bytes_read = fread(c.d.asBytes, 1, 8 * 60, f); cmdp += 2;
if (bytes_read == 8 * 60) { break;
PrintAndLogEx(WARNING, "Error: File reading error"); default:
fclose(f); PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
return 1; errors = true;
break;
} }
fclose(f); }
} else {
file_given = false; //Validations
if (errors) {
free(data);
return usage_hitag_checkchallenges();
} }
//file with all the challenges to try //file with all the challenges to try
c.arg[0] = (uint32_t)file_given; c.arg[0] = (uint32_t)file_given;
clearCommandBuffer(); clearCommandBuffer();
SendCommand(&c); SendCommand(&c);
free(data);
return 0; return 0;
} }
int CmdLFHitagWP(const char *Cmd) { int CmdLFHitagWriter(const char *Cmd) {
UsbCommand c = { CMD_WR_HITAG_S }; UsbCommand c = { CMD_WR_HITAG_S, {0, 0, 0}};
hitag_data *htd = (hitag_data *)c.d.asBytes; hitag_data *htd = (hitag_data *)c.d.asBytes;
hitag_function htf = param_get32ex(Cmd, 0, 0, 10); hitag_function htf = param_get32ex(Cmd, 0, 0, 10);
switch (htf) { switch (htf) {
case 03: { //WHTSF_CHALLENGE case WHTSF_CHALLENGE: {
num_to_bytes(param_get64ex(Cmd, 1, 0, 16), 8, htd->auth.NrAr); num_to_bytes(param_get64ex(Cmd, 1, 0, 16), 8, htd->auth.NrAr);
c.arg[2] = param_get32ex(Cmd, 2, 0, 10); c.arg[2] = param_get32ex(Cmd, 2, 0, 10);
num_to_bytes(param_get32ex(Cmd, 3, 0, 16), 4, htd->auth.data); num_to_bytes(param_get32ex(Cmd, 3, 0, 16), 4, htd->auth.data);
}
break; break;
case 04: }
case 24: { case WHTSF_KEY:
//WHTSF_KEY case WHT2F_CRYPTO: {
num_to_bytes(param_get64ex(Cmd, 1, 0, 16), 6, htd->crypto.key); num_to_bytes(param_get64ex(Cmd, 1, 0, 16), 6, htd->crypto.key);
c.arg[2] = param_get32ex(Cmd, 2, 0, 10); c.arg[2] = param_get32ex(Cmd, 2, 0, 10);
num_to_bytes(param_get32ex(Cmd, 3, 0, 16), 4, htd->crypto.data); num_to_bytes(param_get32ex(Cmd, 3, 0, 16), 4, htd->crypto.data);
}
break; break;
}
default: { default: {
PrintAndLogEx(WARNING, "Error: unkown writer function %d", htf); return usage_hitag_writer();
PrintAndLogEx(NORMAL, "Hitag writer functions");
PrintAndLogEx(NORMAL, " HitagS (0*)");
PrintAndLogEx(NORMAL, " 03 <nr,ar> (Challenge) <page> <byte0...byte3> write page on a Hitag S tag");
PrintAndLogEx(NORMAL, " 04 <key> (set to 0 if no authentication is needed) <page> <byte0...byte3> write page on a Hitag S tag");
PrintAndLogEx(NORMAL, " Hitag1 (1*)");
PrintAndLogEx(NORMAL, " Hitag2 (2*)");
return 1;
} }
break;
} }
// Copy the hitag function into the first argument
c.arg[0] = htf; c.arg[0] = htf;
clearCommandBuffer(); clearCommandBuffer();
SendCommand(&c); SendCommand(&c);
UsbCommand resp; UsbCommand resp;
WaitForResponse(CMD_ACK, &resp); if (!WaitForResponseTimeout(CMD_ACK, &resp, 4000)) {
PrintAndLogEx(WARNING, "timeout while waiting for reply.");
return 1;
}
// Check the return status, stored in the first argument if (resp.arg[0] == false) {
if (resp.arg[0] == false) return 1; PrintAndLogEx(DEBUG, "DEBUG: Error - hitag write failed");
return 1;
}
return 0;
}
int CmdLFHitagDump(const char *Cmd) {
PrintAndLogEx(INFO, "Dumping of tag memory");
PrintAndLogEx(INFO, "To be done!");
char ctmp = tolower(param_getchar(Cmd, 0));
if (ctmp == 'h') return usage_hitag_dump();
return 0; return 0;
} }
static command_t CommandTable[] = { static command_t CommandTable[] = {
{"help", CmdHelp, 1, "This help"}, {"help", CmdHelp, 1, "This help" },
{"list", CmdLFHitagList, 1, "<outfile> List Hitag trace history"}, {"list", CmdLFHitagList, 0, "List Hitag trace history" },
{"reader", CmdLFHitagReader, 1, "Act like a Hitag Reader"}, {"info", CmdLFHitagInfo, 1, "Tag information" },
{"sim", CmdLFHitagSim, 1, "<infile> Simulate Hitag transponder"}, {"reader", CmdLFHitagReader, 1, "Act like a Hitag Reader" },
{"simS", CmdLFHitagSimS, 1, "<hitagS.hts> Simulate HitagS transponder" }, {"sim", CmdLFHitagSim, 1, "Simulate Hitag transponder" },
{"snoop", CmdLFHitagSnoop, 1, "Eavesdrop Hitag communication"}, {"sniff", CmdLFHitagSniff, 1, "Eavesdrop Hitag communication" },
{"writer", CmdLFHitagWP, 1, "Act like a Hitag Writer" }, {"writer", CmdLFHitagWriter, 1, "Act like a Hitag Writer" },
{"check_challenges", CmdLFHitagCheckChallenges, 1, "<challenges.cc> test all challenges" }, {"cc", CmdLFHitagCheckChallenges, 1, "Test all challenges" },
{ NULL, NULL, 0, NULL } { NULL, NULL, 0, NULL }
}; };

View file

@ -14,11 +14,12 @@
extern int CmdLFHitag(const char *Cmd); extern int CmdLFHitag(const char *Cmd);
extern int CmdLFHitagList(const char *Cmd); extern int CmdLFHitagList(const char *Cmd);
extern int CmdLFHitagReader(const char *Cmd); extern int CmdLFHitagSniff(const char *Cmd);
extern int CmdLFHitagSim(const char *Cmd); extern int CmdLFHitagSim(const char *Cmd);
extern int CmdLFHitagSimS(const char *Cmd); extern int CmdLFHitagInfo(const char *Cmd);
extern int CmdLFHitagSnoop(const char *Cmd); extern int CmdLFHitagReader(const char *Cmd);
extern int CmdLFHitagWP(const char *Cmd);
extern int CmdLFHitagCheckChallenges(const char *Cmd); extern int CmdLFHitagCheckChallenges(const char *Cmd);
extern int CmdLFHitagWriter(const char *Cmd);
extern int CmdLFHitagDump(const char *cmd);
#endif #endif

View file

@ -12,6 +12,12 @@
static int CmdHelp(const char *Cmd); static int CmdHelp(const char *Cmd);
//large 224 bit indala formats (different preamble too...)
static uint8_t preamble224[] = {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1};
// standard 64 bit indala formats including 26 bit 40134 format
static uint8_t preamble64[] = {1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1};
int usage_lf_indala_demod(void) { int usage_lf_indala_demod(void) {
PrintAndLogEx(NORMAL, "Enables Indala compatible reader mode printing details of scanned tags."); PrintAndLogEx(NORMAL, "Enables Indala compatible reader mode printing details of scanned tags.");
PrintAndLogEx(NORMAL, "By default, values are printed and logged until the button is pressed or another USB command is issued."); PrintAndLogEx(NORMAL, "By default, values are printed and logged until the button is pressed or another USB command is issued.");
@ -40,69 +46,129 @@ int usage_lf_indala_sim(void) {
} }
int usage_lf_indala_clone(void) { int usage_lf_indala_clone(void) {
PrintAndLogEx(NORMAL, "Enables cloning of Indala card with specified uid onto T55x7.");
PrintAndLogEx(NORMAL, "The T55x7 must be on the antenna when issuing this command. T55x7 blocks are calculated and printed in the process.");
PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Usage: lf indala clone [h] <uid> [Q5]"); PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Usage: lf indala clone [h]<l> <uid> [Q5]");
PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h : This help"); PrintAndLogEx(NORMAL, " h : This help");
PrintAndLogEx(NORMAL, " <uid> : 64/224 UID"); PrintAndLogEx(NORMAL, " l : long uid 64/224");
PrintAndLogEx(NORMAL, " <uid> : UID");
PrintAndLogEx(NORMAL, " Q5 : optional - clone to Q5 (T5555) instead of T55x7 chip"); PrintAndLogEx(NORMAL, " Q5 : optional - clone to Q5 (T5555) instead of T55x7 chip");
PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, " lf indala clone 112233"); PrintAndLogEx(NORMAL, " lf indala clone 112233 -- 64");
PrintAndLogEx(NORMAL, " lf indala clone l 112233 -- long 224");
return 0; return 0;
} }
// redesigned by marshmellow adjusted from existing decode functions // redesigned by marshmellow adjusted from existing decode functions
// indala id decoding // indala id decoding
int indala64decode(uint8_t *dest, size_t *size, uint8_t *invert) { int detectIndala(uint8_t *dest, size_t *size, uint8_t *invert) {
//standard 64 bit indala formats including 26 bit 40134 format
uint8_t preamble64[] = {1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1};
uint8_t preamble64_i[] = {0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0}; uint8_t preamble64_i[] = {0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0};
size_t idx = 0;
size_t found_size = *size;
if (!preambleSearch(dest, preamble64, sizeof(preamble64), &found_size, &idx)) {
// if didn't find preamble try again inverting
if (!preambleSearch(dest, preamble64_i, sizeof(preamble64_i), &found_size, &idx)) return -1;
*invert ^= 1;
}
if (found_size != 64) return -2;
if (*invert == 1)
for (size_t i = idx; i < found_size + idx; i++)
dest[i] ^= 1;
// note: don't change *size until we are sure we got it...
*size = found_size;
return (int) idx;
}
int indala224decode(uint8_t *dest, size_t *size, uint8_t *invert) {
//large 224 bit indala formats (different preamble too...)
uint8_t preamble224[] = {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1};
uint8_t preamble224_i[] = {0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0}; uint8_t preamble224_i[] = {0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0};
size_t idx = 0; size_t idx = 0;
size_t found_size = *size; size_t found_size = *size;
if (!preambleSearch(dest, preamble224, sizeof(preamble224), &found_size, &idx)) {
// if didn't find preamble try again inverting
if (!preambleSearch(dest, preamble224_i, sizeof(preamble224_i), &found_size, &idx)) return -1;
*invert ^= 1;
}
if (found_size != 224) return -2;
if (*invert == 1 && idx > 0) // PSK1
for (size_t i = idx - 1; i < found_size + idx + 2; i++) bool res = preambleSearch(dest, preamble64, sizeof(preamble64), &found_size, &idx);
if ( res ) {
PrintAndLogEx(DEBUG, "DEBUG: detectindala PSK1 found 64");
goto out;
}
idx = 0;
found_size = *size;
res = preambleSearch(dest, preamble64_i, sizeof(preamble64_i), &found_size, &idx);
if ( res ) {
PrintAndLogEx(DEBUG, "DEBUG: detectindala PSK1 found 64 inverted preamble");
goto inv;
}
/*
idx = 0;
found_size = *size;
res = preambleSearch(dest, preamble224, sizeof(preamble224), &found_size, &idx);
if ( res ) {
PrintAndLogEx(DEBUG, "DEBUG: detectindala PSK1 found 224");
goto out;
}
idx = 0;
found_size = *size;
res = preambleSearch(dest, preamble224_i, sizeof(preamble224_i), &found_size, &idx);
if ( res ) {
PrintAndLogEx(DEBUG, "DEBUG: detectindala PSK1 found 224 inverted preamble");
goto inv;
}
*/
// PSK2
psk1TOpsk2(dest, *size);
PrintAndLogEx(DEBUG, "DEBUG: detectindala Converting PSK1 -> PSK2");
idx = 0;
found_size = *size;
res = preambleSearch(dest, preamble64, sizeof(preamble64), &found_size, &idx);
if ( res ) {
PrintAndLogEx(DEBUG, "DEBUG: detectindala PSK2 found 64 preamble");
goto out;
}
idx = 0;
found_size = *size;
res = preambleSearch(dest, preamble224, sizeof(preamble224), &found_size, &idx);
if ( res ) {
PrintAndLogEx(DEBUG, "DEBUG: detectindala PSK2 found 224 preamble");
goto out;
}
idx = 0;
found_size = *size;
res = preambleSearch(dest, preamble64_i, sizeof(preamble64_i), &found_size, &idx);
if ( res ) {
PrintAndLogEx(DEBUG, "DEBUG: detectindala PSK2 found 64 inverted preamble");
goto inv;
}
idx = 0;
found_size = *size;
res = preambleSearch(dest, preamble224_i, sizeof(preamble224_i), &found_size, &idx);
if ( res ) {
PrintAndLogEx(DEBUG, "DEBUG: detectindala PSK2 found 224 inverted preamble");
goto inv;
}
inv:
if ( res == 0 ) {
return -4;
}
*invert ^= 1;
if (*invert && idx > 0) {
for (size_t i = idx - 1; i < found_size + idx + 2; i++) {
dest[i] ^= 1; dest[i] ^= 1;
}
}
PrintAndLogEx(DEBUG, "DEBUG: Warning - Indala had to invert bits");
out:
*size = found_size;
//PrintAndLogEx(INFO, "DEBUG: detectindala RES = %d | %d | %d", res, found_size, idx);
if (found_size != 224 && found_size != 64) {
PrintAndLogEx(INFO, "DEBUG: detectindala | %d", found_size);
return -5;
}
// 224 formats are typically PSK2 (afaik 2017 Marshmellow) // 224 formats are typically PSK2 (afaik 2017 Marshmellow)
// note loses 1 bit at beginning of transformation... // note loses 1 bit at beginning of transformation...
// don't need to verify array is big enough as to get here there has to be a full preamble after all of our data
psk1TOpsk2(dest + (idx - 1), found_size + 2);
idx++;
*size = found_size;
return (int) idx; return (int) idx;
} }
// this read is the "normal" read, which download lf signal and tries to demod here. // this read is the "normal" read, which download lf signal and tries to demod here.
@ -117,9 +183,9 @@ int CmdIndalaRead(const char *Cmd) {
int CmdIndalaDemod(const char *Cmd) { int CmdIndalaDemod(const char *Cmd) {
int ans; int ans;
if (strlen(Cmd) > 0) if (strlen(Cmd) > 0)
ans = PSKDemod(Cmd, 0); ans = PSKDemod(Cmd, true);
else //default to RF/32 else
ans = PSKDemod("32", 0); ans = PSKDemod("32", true);
if (!ans) { if (!ans) {
PrintAndLogEx(DEBUG, "DEBUG: Error - Indala can't demod signal: %d", ans); PrintAndLogEx(DEBUG, "DEBUG: Error - Indala can't demod signal: %d", ans);
@ -128,47 +194,91 @@ int CmdIndalaDemod(const char *Cmd) {
uint8_t invert = 0; uint8_t invert = 0;
size_t size = DemodBufferLen; size_t size = DemodBufferLen;
int idx = indala64decode(DemodBuffer, &size, &invert); int idx = detectIndala(DemodBuffer, &size, &invert);
if (idx < 0 || size != 64) { if (idx < 0) {
// try 224 indala if (idx == -1)
invert = 0; PrintAndLogEx(DEBUG, "DEBUG: Error - Indala: not enough samples");
size = DemodBufferLen; else if (idx == -2)
idx = indala224decode(DemodBuffer, &size, &invert); PrintAndLogEx(DEBUG, "DEBUG: Error - Indala: only noise found");
if (idx < 0 || size != 224) { else if (idx == -4)
PrintAndLogEx(DEBUG, "DEBUG: Error - Indala wrong size, expected [64|224] got: %d (startindex %i)", size, idx); PrintAndLogEx(DEBUG, "DEBUG: Error - Indala: preamble not found");
else if (idx == -5)
PrintAndLogEx(DEBUG, "DEBUG: Error - Indala: size not correct: %d", size);
else
PrintAndLogEx(DEBUG, "DEBUG: Error - Indala: error demoding psk idx: %d", idx);
return 0; return 0;
} }
} setDemodBuf(DemodBuffer, size, idx);
setDemodBuf(DemodBuffer, size, (size_t)idx);
setClockGrid(g_DemodClock, g_DemodStartIdx + (idx * g_DemodClock)); setClockGrid(g_DemodClock, g_DemodStartIdx + (idx * g_DemodClock));
if (invert) {
PrintAndLogEx(DEBUG, "DEBUG: Error - Indala had to invert bits");
for (size_t i = 0; i < size; i++)
DemodBuffer[i] ^= 1;
}
//convert UID to HEX //convert UID to HEX
uint32_t uid1, uid2, uid3, uid4, uid5, uid6, uid7; uint32_t uid1, uid2, uid3, uid4, uid5, uid6, uid7;
uid1 = bytebits_to_byte(DemodBuffer, 32); uid1 = bytebits_to_byte(DemodBuffer, 32);
uid2 = bytebits_to_byte(DemodBuffer + 32, 32); uid2 = bytebits_to_byte(DemodBuffer + 32, 32);
uint64_t foo = (((uint64_t)uid1 << 32) & 0x1FFFFFFF ) | (uid2 & 0x7FFFFFFF );
if (DemodBufferLen == 64) { if (DemodBufferLen == 64) {
PrintAndLogEx(SUCCESS, "Indala Found - bitlength %d, UID = (0x%x%08x)\n%s", PrintAndLogEx(
DemodBufferLen, uid1, uid2, sprint_bin_break(DemodBuffer, DemodBufferLen, 32) SUCCESS
, "Indala Found - bitlength %d, Raw %x%08x"
, DemodBufferLen
, uid1
, uid2
); );
uint16_t p1 = 0;
p1 |= DemodBuffer[32+ 3] << 8;
p1 |= DemodBuffer[32+ 6] << 5;
p1 |= DemodBuffer[32+ 8] << 4;
p1 |= DemodBuffer[32+ 9] << 3;
p1 |= DemodBuffer[32+11] << 1;
p1 |= DemodBuffer[32+16] << 6;
p1 |= DemodBuffer[32+19] << 7;
p1 |= DemodBuffer[32+20] << 10;
p1 |= DemodBuffer[32+21] << 2;
p1 |= DemodBuffer[32+22] << 0;
p1 |= DemodBuffer[32+24] << 9;
/*
uint16_t fc = 0;
fc |= DemodBuffer[32+ 1] << 0;
fc |= DemodBuffer[32+ 2] << 1;
fc |= DemodBuffer[32+ 4] << 2;
fc |= DemodBuffer[32+ 5] << 3;
fc |= DemodBuffer[32+ 7] << 4;
fc |= DemodBuffer[32+10] << 5;
fc |= DemodBuffer[32+14] << 6;
fc |= DemodBuffer[32+15] << 7;
fc |= DemodBuffer[32+17] << 8;
*/
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(SUCCESS, "Possible de-scramble patterns");
PrintAndLogEx(SUCCESS, "\tPrinted | __%04d__ [0x%X]", p1, p1);
//PrintAndLogEx(SUCCESS, "\tPrinted | __%04d__ [0x%X]", fc, fc);
PrintAndLogEx(SUCCESS, "\tInternal ID | %" PRIu64 , foo);
} else { } else {
uid3 = bytebits_to_byte(DemodBuffer + 64, 32); uid3 = bytebits_to_byte(DemodBuffer + 64, 32);
uid4 = bytebits_to_byte(DemodBuffer + 96, 32); uid4 = bytebits_to_byte(DemodBuffer + 96, 32);
uid5 = bytebits_to_byte(DemodBuffer + 128, 32); uid5 = bytebits_to_byte(DemodBuffer + 128, 32);
uid6 = bytebits_to_byte(DemodBuffer + 160, 32); uid6 = bytebits_to_byte(DemodBuffer + 160, 32);
uid7 = bytebits_to_byte(DemodBuffer + 192, 32); uid7 = bytebits_to_byte(DemodBuffer + 192, 32);
PrintAndLogEx(SUCCESS, "Indala Found - bitlength %d, UID = (0x%x%08x%08x%08x%08x%08x%08x)\n%s", PrintAndLogEx(SUCCESS, "Indala Found - bitlength %d, UID = 0x%x%08x%08x%08x%08x%08x%08x"
DemodBufferLen, , DemodBufferLen
uid1, uid2, uid3, uid4, uid5, uid6, uid7, sprint_bin_break(DemodBuffer, DemodBufferLen, 32) , uid1
, uid2
, uid3
, uid4
, uid5
, uid6
, uid7
); );
} }
if (g_debugMode) { if (g_debugMode) {
PrintAndLogEx(DEBUG, "DEBUG: Indala - printing demodbuffer:"); PrintAndLogEx(DEBUG, "DEBUG: Indala - printing demodbuffer");
printDemodBuff(); printDemodBuff();
} }
return 1; return 1;
@ -420,41 +530,48 @@ int CmdIndalaSim(const char *Cmd) {
// iceman - needs refactoring // iceman - needs refactoring
int CmdIndalaClone(const char *Cmd) { int CmdIndalaClone(const char *Cmd) {
UsbCommand c = {0};
uint32_t uid1, uid2, uid3, uid4, uid5, uid6, uid7;
uid1 = uid2 = uid3 = uid4 = uid5 = uid6 = uid7 = 0;
uint32_t n = 0, i = 0;
if (strchr(Cmd, 'l') != 0) { bool isLongUid = false;
uint8_t data[7*4];
int datalen = 0;
while (sscanf(&Cmd[i++], "%1x", &n) == 1) { CLIParserInit("lf indala clone",
uid1 = (uid1 << 4) | (uid2 >> 28); "Enables cloning of Indala card with specified uid onto T55x7\n"
uid2 = (uid2 << 4) | (uid3 >> 28); "defaults to 64.\n",
uid3 = (uid3 << 4) | (uid4 >> 28); "\n"
uid4 = (uid4 << 4) | (uid5 >> 28); "Samples:\n"
uid5 = (uid5 << 4) | (uid6 >> 28); "\tlf indala clone a0000000a0002021\n"
uid6 = (uid6 << 4) | (uid7 >> 28); "\tlf indala clone -l 80000001b23523a6c2e31eba3cbee4afb3c6ad1fcf649393928c14e5");
uid7 = (uid7 << 4) | (n & 0xf);
}
PrintAndLogEx(INFO, "Preparing to clone Indala 224bit tag with UID %x%08x%08x%08x%08x%08x%08x", uid1, uid2, uid3, uid4, uid5, uid6, uid7); void *argtable[] = {
arg_param_begin,
arg_lit0("lL", "long", "long UID 224 bits"),
arg_strx1(NULL, NULL, "<uid (hex)>", NULL),
arg_param_end
};
CLIExecWithReturn(Cmd, argtable, false);
isLongUid = arg_get_lit(1);
CLIGetHexWithReturn(2, data, &datalen);
CLIParserFree();
UsbCommand c = {0, {0,0,0}};
if (isLongUid) {
PrintAndLogEx(INFO, "Preparing to clone Indala 224bit tag with UID %s", sprint_hex(data, datalen));
c.cmd = CMD_INDALA_CLONE_TAG_L; c.cmd = CMD_INDALA_CLONE_TAG_L;
c.d.asDwords[0] = uid1; c.d.asDwords[0] = bytes_to_num(data, 4);
c.d.asDwords[1] = uid2; c.d.asDwords[1] = bytes_to_num(data + 4, 4);
c.d.asDwords[2] = uid3; c.d.asDwords[2] = bytes_to_num(data + 8, 4);
c.d.asDwords[3] = uid4; c.d.asDwords[3] = bytes_to_num(data + 12, 4);
c.d.asDwords[4] = uid5; c.d.asDwords[4] = bytes_to_num(data + 16, 4);
c.d.asDwords[5] = uid6; c.d.asDwords[5] = bytes_to_num(data + 20, 4);
c.d.asDwords[6] = uid7; c.d.asDwords[6] = bytes_to_num(data + 24, 4);
} else { } else {
while (sscanf(&Cmd[i++], "%1x", &n) == 1) { PrintAndLogEx(INFO, "Preparing to clone Indala 64bit tag with UID %s", sprint_hex(data, datalen));
uid1 = (uid1 << 4) | (uid2 >> 28);
uid2 = (uid2 << 4) | (n & 0xf);
}
PrintAndLogEx(INFO, "Preparing to clone Indala 64bit tag with UID %x%08x", uid1, uid2);
c.cmd = CMD_INDALA_CLONE_TAG; c.cmd = CMD_INDALA_CLONE_TAG;
c.arg[0] = uid1; c.d.asDwords[0] = bytes_to_num(data, 4);
c.arg[1] = uid2; c.d.asDwords[1] = bytes_to_num(data + 4, 4);
} }
clearCommandBuffer(); clearCommandBuffer();

View file

@ -32,8 +32,8 @@ extern int CmdIndalaClone(const char *Cmd);
extern int CmdIndalaSim(const char *Cmd); extern int CmdIndalaSim(const char *Cmd);
extern int detectIndala26(uint8_t *bitStream, size_t *size, uint8_t *invert); extern int detectIndala26(uint8_t *bitStream, size_t *size, uint8_t *invert);
extern int indala64decode(uint8_t *bitStream, size_t *size, uint8_t *invert); extern int detectIndala64(uint8_t *bitStream, size_t *size, uint8_t *invert);
extern int indala224decode(uint8_t *bitStream, size_t *size, uint8_t *invert); extern int detectIndala224(uint8_t *bitStream, size_t *size, uint8_t *invert);
extern int usage_lf_indala_demod(void); extern int usage_lf_indala_demod(void);
extern int usage_lf_indala_clone(void); extern int usage_lf_indala_clone(void);

View file

@ -257,7 +257,7 @@ int CmdIOProxSim(const char *Cmd) {
fc = param_get8(Cmd, 1); fc = param_get8(Cmd, 1);
cn = param_get32ex(Cmd, 2, 0, 10); cn = param_get32ex(Cmd, 2, 0, 10);
if (!version | !fc || !cn) return usage_lf_io_sim(); if (!version || !fc || !cn) return usage_lf_io_sim();
if ((cn & 0xFFFF) != cn) { if ((cn & 0xFFFF) != cn) {
cn &= 0xFFFF; cn &= 0xFFFF;
@ -303,7 +303,7 @@ int CmdIOProxClone(const char *Cmd) {
fc = param_get8(Cmd, 1); fc = param_get8(Cmd, 1);
cn = param_get32ex(Cmd, 2, 0, 10); cn = param_get32ex(Cmd, 2, 0, 10);
if (!version | !fc || !cn) return usage_lf_io_clone(); if (!version || !fc || !cn) return usage_lf_io_clone();
if ((cn & 0xFFFF) != cn) { if ((cn & 0xFFFF) != cn) {
cn &= 0xFFFF; cn &= 0xFFFF;

View file

@ -41,8 +41,8 @@ int usage_lf_keri_sim(void) {
// find KERI preamble in already demoded data // find KERI preamble in already demoded data
int detectKeri(uint8_t *dest, size_t *size, bool *invert) { int detectKeri(uint8_t *dest, size_t *size, bool *invert) {
uint8_t preamble[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}; uint8_t preamble[] = {1,1,1,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1};
uint8_t preamble_i[] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0}; uint8_t preamble_i[] = {0,0,0,1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0};
// sanity check. // sanity check.
if (*size < sizeof(preamble) + 100) return -1; if (*size < sizeof(preamble) + 100) return -1;
@ -157,18 +157,16 @@ int CmdKeriClone(const char *Cmd) {
2 << T5555_MAXBLOCK_SHIFT; 2 << T5555_MAXBLOCK_SHIFT;
} }
// MSB is ONE // MSB is ONE
internalid |= 0x80000000; internalid |= 0x80000000;
// 3 LSB is ONE // 3 LSB is ONE
uint64_t data = ((uint64_t)internalid << 3) + 7; uint64_t data = ((uint64_t)internalid << 3) + 7;
PrintAndLogEx(INFO, "Preparing to clone KERI to T55x7 with Internal Id: %" PRIx64, internalid );
// //
blocks[1] = data >> 32; blocks[1] = data >> 32;
blocks[2] = data & 0xFFFFFFFF; blocks[2] = data & 0xFFFFFFFF;
PrintAndLogEx(INFO, "Preparing to clone KERI to T55x7 with Internal Id: %u", internalid);
print_blocks(blocks, 3); print_blocks(blocks, 3);

View file

@ -147,8 +147,8 @@ int CmdParadoxRead(const char *Cmd) {
int CmdParadoxSim(const char *Cmd) { int CmdParadoxSim(const char *Cmd) {
char cmdp = param_getchar(Cmd, 0); char cmdp = tolower(param_getchar(Cmd, 0));
if (strlen(Cmd) == 0 || cmdp == 'h' || cmdp == 'H') return usage_lf_paradox_sim(); if (strlen(Cmd) == 0 || cmdp == 'h') return usage_lf_paradox_sim();
uint32_t facilitycode = 0, cardnumber = 0, fc = 0, cn = 0; uint32_t facilitycode = 0, cardnumber = 0, fc = 0, cn = 0;

View file

@ -55,7 +55,7 @@ int detectPyramid(uint8_t *dest, size_t *size, int *waveStartIdx) {
if (getSignalProperties()->isnoise) return -2; if (getSignalProperties()->isnoise) return -2;
// FSK demodulator RF/50 FSK 10,8 // FSK demodulator RF/50 FSK 10,8
*size = fskdemod(dest, *size, 50, 0, 10, 8, waveStartIdx); // pyramid fsk2 *size = fskdemod(dest, *size, 50, 1, 10, 8, waveStartIdx); // pyramid fsk2
//did we get a good demod? //did we get a good demod?
if (*size < 128) return -3; if (*size < 128) return -3;
@ -235,10 +235,12 @@ int CmdPyramidDemod(const char *Cmd) {
PrintAndLogEx(SUCCESS, "Pyramid ID Found - BitLength: %d -unknown BitLength- (%d), Raw: %08x%08x%08x%08x", fmtLen, cardnum, rawHi3, rawHi2, rawHi, rawLo); PrintAndLogEx(SUCCESS, "Pyramid ID Found - BitLength: %d -unknown BitLength- (%d), Raw: %08x%08x%08x%08x", fmtLen, cardnum, rawHi3, rawHi2, rawHi, rawLo);
} }
} }
if (checksum == checkCS)
PrintAndLogEx(SUCCESS, "Checksum %02x passed", checksum); PrintAndLogEx(DEBUG, "DEBUG: Pyramid: checksum : 0x%02X - %02X - %s"
else , checksum
PrintAndLogEx(FAILED, "Checksum %02x failed - should have been %02x", checksum, checkCS); , checkCS
, (checksum == checkCS) ? _GREEN_("Passed") : _RED_("Failed")
);
PrintAndLogEx(DEBUG, "DEBUG: Pyramid: idx: %d, Len: %d, Printing Demod Buffer:", idx, 128); PrintAndLogEx(DEBUG, "DEBUG: Pyramid: idx: %d, Len: %d, Printing Demod Buffer:", idx, 128);
if (g_debugMode) if (g_debugMode)

View file

@ -143,22 +143,26 @@ int usage_t55xx_wakup() {
} }
int usage_t55xx_chk() { int usage_t55xx_chk() {
PrintAndLogEx(NORMAL, "This command uses a dictionary attack"); PrintAndLogEx(NORMAL, "This command uses a dictionary attack");
PrintAndLogEx(NORMAL, "press 'enter' to cancel the command"); PrintAndLogEx(NORMAL, "press " _YELLOW_("'enter'") " to cancel the command");
PrintAndLogEx(NORMAL, "Usage: lf t55xx bruteforce [h] <m> [i <*.dic>]"); PrintAndLogEx(NORMAL, "WARNING: this may brick non-password protected chips!");
PrintAndLogEx(NORMAL, "Try to reading block 7 before\n");
PrintAndLogEx(NORMAL, "Usage: lf t55xx chk [h] <m> [i <*.dic>]");
PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h - this help"); PrintAndLogEx(NORMAL, " h - this help");
PrintAndLogEx(NORMAL, " m - use dictionary from flashmemory\n"); PrintAndLogEx(NORMAL, " m - use dictionary from flashmemory\n");
PrintAndLogEx(NORMAL, " i <*.dic> - loads a default keys dictionary file <*.dic>"); PrintAndLogEx(NORMAL, " i <*.dic> - loads a default keys dictionary file <*.dic>");
PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, " lf t55xx bruteforce m"); PrintAndLogEx(NORMAL, " lf t55xx chk m");
PrintAndLogEx(NORMAL, " lf t55xx bruteforce i default_pwd.dic"); PrintAndLogEx(NORMAL, " lf t55xx chk i default_pwd.dic");
PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "");
return 0; return 0;
} }
int usage_t55xx_bruteforce() { int usage_t55xx_bruteforce() {
PrintAndLogEx(NORMAL, "This command uses bruteforce to scan a number range"); PrintAndLogEx(NORMAL, "This command uses bruteforce to scan a number range");
PrintAndLogEx(NORMAL, "press 'enter' to cancel the command"); PrintAndLogEx(NORMAL, "press " _YELLOW_("'enter'") " to cancel the command");
PrintAndLogEx(NORMAL, "WARNING: this may brick non-password protected chips!");
PrintAndLogEx(NORMAL, "Try to reading block 7 before\n");
PrintAndLogEx(NORMAL, "Usage: lf t55xx bruteforce [h] <start password> <end password>"); PrintAndLogEx(NORMAL, "Usage: lf t55xx bruteforce [h] <start password> <end password>");
PrintAndLogEx(NORMAL, " password must be 4 bytes (8 hex symbols)"); PrintAndLogEx(NORMAL, " password must be 4 bytes (8 hex symbols)");
PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, "Options:");
@ -167,14 +171,15 @@ int usage_t55xx_bruteforce() {
PrintAndLogEx(NORMAL, " <end_pwd> - 4 byte hex value to end pwd search at"); PrintAndLogEx(NORMAL, " <end_pwd> - 4 byte hex value to end pwd search at");
PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, " lf t55xx bruteforce aaaaaaaa bbbbbbbb"); PrintAndLogEx(NORMAL, " lf t55xx bruteforce aaaaaa77 aaaaaa99");
PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "");
return 0; return 0;
} }
int usage_t55xx_recoverpw() { int usage_t55xx_recoverpw() {
PrintAndLogEx(NORMAL, "This command uses a few tricks to try to recover mangled password"); PrintAndLogEx(NORMAL, "This command uses a few tricks to try to recover mangled password");
PrintAndLogEx(NORMAL, "press 'enter' to cancel the command"); PrintAndLogEx(NORMAL, "press " _YELLOW_("'enter'") " to cancel the command");
PrintAndLogEx(NORMAL, "WARNING: this may brick non-password protected chips!"); PrintAndLogEx(NORMAL, "WARNING: this may brick non-password protected chips!");
PrintAndLogEx(NORMAL, "Try to reading block 7 before\n");
PrintAndLogEx(NORMAL, "Usage: lf t55xx recoverpw [password]"); PrintAndLogEx(NORMAL, "Usage: lf t55xx recoverpw [password]");
PrintAndLogEx(NORMAL, " password must be 4 bytes (8 hex symbols)"); PrintAndLogEx(NORMAL, " password must be 4 bytes (8 hex symbols)");
PrintAndLogEx(NORMAL, " default password is 51243648, used by many cloners"); PrintAndLogEx(NORMAL, " default password is 51243648, used by many cloners");
@ -1053,6 +1058,7 @@ int CmdT55xxWriteBlock(const char *Cmd) {
c.arg[2] = password; c.arg[2] = password;
c.d.asBytes[0] |= 0x1; c.d.asBytes[0] |= 0x1;
} }
clearCommandBuffer(); clearCommandBuffer();
SendCommand(&c); SendCommand(&c);
if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
@ -1363,7 +1369,7 @@ bool AquireData(uint8_t page, uint8_t block, bool pwdmode, uint32_t password) {
// bit1 = page to read from // bit1 = page to read from
// arg1: which block to read // arg1: which block to read
// arg2: password // arg2: password
uint8_t arg0 = (page << 1) | pwdmode; uint8_t arg0 = ( page << 1 | (pwdmode) );
UsbCommand c = {CMD_T55XX_READ_BLOCK, {arg0, block, password}}; UsbCommand c = {CMD_T55XX_READ_BLOCK, {arg0, block, password}};
clearCommandBuffer(); clearCommandBuffer();
SendCommand(&c); SendCommand(&c);
@ -1382,35 +1388,35 @@ char *GetBitRateStr(uint32_t id, bool xmode) {
char *retStr = buf; char *retStr = buf;
if (xmode) { //xmode bitrate calc is same as em4x05 calc if (xmode) { //xmode bitrate calc is same as em4x05 calc
snprintf(retStr, sizeof(buf), "%d - RF/%d", id, EM4x05_GET_BITRATE(id)); snprintf(retStr, sizeof(buf), "%u - RF/%d", id, EM4x05_GET_BITRATE(id));
} else { } else {
switch (id) { switch (id) {
case 0: case 0:
snprintf(retStr, sizeof(buf), "%d - RF/8", id); snprintf(retStr, sizeof(buf), "%u - RF/8", id);
break; break;
case 1: case 1:
snprintf(retStr, sizeof(buf), "%d - RF/16", id); snprintf(retStr, sizeof(buf), "%u - RF/16", id);
break; break;
case 2: case 2:
snprintf(retStr, sizeof(buf), "%d - RF/32", id); snprintf(retStr, sizeof(buf), "%u - RF/32", id);
break; break;
case 3: case 3:
snprintf(retStr, sizeof(buf), "%d - RF/40", id); snprintf(retStr, sizeof(buf), "%u - RF/40", id);
break; break;
case 4: case 4:
snprintf(retStr, sizeof(buf), "%d - RF/50", id); snprintf(retStr, sizeof(buf), "%u - RF/50", id);
break; break;
case 5: case 5:
snprintf(retStr, sizeof(buf), "%d - RF/64", id); snprintf(retStr, sizeof(buf), "%u - RF/64", id);
break; break;
case 6: case 6:
snprintf(retStr, sizeof(buf), "%d - RF/100", id); snprintf(retStr, sizeof(buf), "%u - RF/100", id);
break; break;
case 7: case 7:
snprintf(retStr, sizeof(buf), "%d - RF/128", id); snprintf(retStr, sizeof(buf), "%u - RF/128", id);
break; break;
default: default:
snprintf(retStr, sizeof(buf), "%d - (Unknown)", id); snprintf(retStr, sizeof(buf), "%u - (Unknown)", id);
break; break;
} }
} }
@ -1421,12 +1427,12 @@ char *GetSaferStr(uint32_t id) {
static char buf[40]; static char buf[40];
char *retStr = buf; char *retStr = buf;
snprintf(retStr, sizeof(buf), "%d", id); snprintf(retStr, sizeof(buf), "%u", id);
if (id == 6) { if (id == 6) {
snprintf(retStr, sizeof(buf), "%d - passwd", id); snprintf(retStr, sizeof(buf), "%u - " _YELLOW_("passwd"), id);
} }
if (id == 9) { if (id == 9) {
snprintf(retStr, sizeof(buf), "%d - testmode", id); snprintf(retStr, sizeof(buf), "%u - " _YELLOW_("testmode"), id);
} }
return buf; return buf;
@ -1438,40 +1444,40 @@ char *GetModulationStr(uint32_t id) {
switch (id) { switch (id) {
case 0: case 0:
snprintf(retStr, sizeof(buf), "%d - DIRECT (ASK/NRZ)", id); snprintf(retStr, sizeof(buf), "%u - DIRECT (ASK/NRZ)", id);
break; break;
case 1: case 1:
snprintf(retStr, sizeof(buf), "%d - PSK 1 phase change when input changes", id); snprintf(retStr, sizeof(buf), "%u - PSK 1 phase change when input changes", id);
break; break;
case 2: case 2:
snprintf(retStr, sizeof(buf), "%d - PSK 2 phase change on bitclk if input high", id); snprintf(retStr, sizeof(buf), "%u - PSK 2 phase change on bitclk if input high", id);
break; break;
case 3: case 3:
snprintf(retStr, sizeof(buf), "%d - PSK 3 phase change on rising edge of input", id); snprintf(retStr, sizeof(buf), "%u - PSK 3 phase change on rising edge of input", id);
break; break;
case 4: case 4:
snprintf(retStr, sizeof(buf), "%d - FSK 1 RF/8 RF/5", id); snprintf(retStr, sizeof(buf), "%u - FSK 1 RF/8 RF/5", id);
break; break;
case 5: case 5:
snprintf(retStr, sizeof(buf), "%d - FSK 2 RF/8 RF/10", id); snprintf(retStr, sizeof(buf), "%u - FSK 2 RF/8 RF/10", id);
break; break;
case 6: case 6:
snprintf(retStr, sizeof(buf), "%d - FSK 1a RF/5 RF/8", id); snprintf(retStr, sizeof(buf), "%u - FSK 1a RF/5 RF/8", id);
break; break;
case 7: case 7:
snprintf(retStr, sizeof(buf), "%d - FSK 2a RF/10 RF/8", id); snprintf(retStr, sizeof(buf), "%u - FSK 2a RF/10 RF/8", id);
break; break;
case 8: case 8:
snprintf(retStr, sizeof(buf), "%d - Manchester", id); snprintf(retStr, sizeof(buf), "%u - Manchester", id);
break; break;
case 16: case 16:
snprintf(retStr, sizeof(buf), "%d - Biphase", id); snprintf(retStr, sizeof(buf), "%u - Biphase", id);
break; break;
case 0x18: case 0x18:
snprintf(retStr, sizeof(buf), "%d - Biphase a - AKA Conditional Dephase Encoding(CDP)", id); snprintf(retStr, sizeof(buf), "%u - Biphase a - AKA Conditional Dephase Encoding(CDP)", id);
break; break;
case 17: case 17:
snprintf(retStr, sizeof(buf), "%d - Reserved", id); snprintf(retStr, sizeof(buf), "%u - Reserved", id);
break; break;
default: default:
snprintf(retStr, sizeof(buf), "0x%02X (Unknown)", id); snprintf(retStr, sizeof(buf), "0x%02X (Unknown)", id);
@ -1624,23 +1630,20 @@ bool IsCancelled(void) {
return false; return false;
} }
// load a default pwd file.
int CmdT55xxChkPwds(const char *Cmd) { int CmdT55xxChkPwds(const char *Cmd) {
// load a default pwd file.
char line[9];
char filename[FILE_PATH_SIZE] = {0}; char filename[FILE_PATH_SIZE] = {0};
int keycnt = 0;
uint8_t stKeyBlock = 20;
uint8_t *keyBlock = NULL, *p = NULL;
bool found = false; bool found = false;
uint8_t timeout = 0; uint8_t timeout = 0;
uint8_t *keyBlock = NULL;
memset(line, 0, sizeof(line));
char cmdp = tolower(param_getchar(Cmd, 0)); char cmdp = tolower(param_getchar(Cmd, 0));
if (strlen(Cmd) == 0 || cmdp == 'h') return usage_t55xx_chk(); if (strlen(Cmd) == 0 || cmdp == 'h') return usage_t55xx_chk();
/* /*
if ( T55xxReadBlock(7, 0, 0, 0, 0) ) { // block 7, page1 = false, usepwd = false, override = false, pwd = 00000000
if ( T55xxReadBlock(7, false, false, false, 0x00000000) ) {
// now try to validate it.. // now try to validate it..
PrintAndLogEx(WARNING, "\n Block 7 was readable"); PrintAndLogEx(WARNING, "\n Block 7 was readable");
@ -1667,93 +1670,49 @@ int CmdT55xxChkPwds(const char *Cmd) {
} }
if (resp.arg[0]) { if (resp.arg[0]) {
PrintAndLogEx(SUCCESS, "\nFound a candidate [ %08X ]. Trying to validate", resp.arg[1]); PrintAndLogEx(SUCCESS, "\nFound a candidate [ " _YELLOW_("%08X") " ]. Trying to validate", resp.arg[1]);
if (!AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, true, resp.arg[1])) { AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, true, resp.arg[1]);
PrintAndLogEx(INFO, "Aquireing data from device failed. Quitting");
return 2;
}
found = tryDetectModulation(); found = tryDetectModulation();
if (found) { if (found) {
PrintAndLogEx(SUCCESS, "Found valid password: [ %08X ]", resp.arg[1]); PrintAndLogEx(SUCCESS, "Found valid password: [ " _GREEN_("%08") " ]", resp.arg[1]);
} else { } else {
PrintAndLogEx(WARNING, "Password NOT found."); PrintAndLogEx(WARNING, "Check pwd failed");
} }
} else { } else {
PrintAndLogEx(WARNING, "Password NOT found."); PrintAndLogEx(WARNING, "Check pwd failed");
} }
goto out; goto out;
} }
keyBlock = calloc(stKeyBlock, 4);
if (keyBlock == NULL) return 1;
if (cmdp == 'i') { if (cmdp == 'i') {
int len = strlen(Cmd + 2); int len = strlen(Cmd + 2);
if (len > FILE_PATH_SIZE) len = FILE_PATH_SIZE; if (len > FILE_PATH_SIZE) len = FILE_PATH_SIZE;
memcpy(filename, Cmd + 2, len); memcpy(filename, Cmd + 2, len);
FILE *f = fopen(filename, "r"); uint16_t keycount = 0;
if (!f) { size_t datalen = 0;
PrintAndLogEx(FAILED, "File: " _YELLOW_("%s") ": not found or locked.", filename);
free(keyBlock); // TODO, a way of reallocating memory if file was larger
keyBlock = calloc(4*200, sizeof(uint8_t));
if ( keyBlock == NULL ) {
PrintAndLogDevice(WARNING, "error, cannot allocate memory ");
return 1; return 1;
} }
while (fgets(line, sizeof(line), f)) { int res = loadFileDICTIONARY(filename, "dic", keyBlock, &datalen, 4, &keycount );
if (strlen(line) < 8 || line[7] == '\n') continue; if (res || keycount == 0) {
//goto next line
while (fgetc(f) != '\n' && !feof(f)) ;
//The line start with # is comment, skip
if (line[0] == '#') continue;
if (!isxdigit(line[0])) {
PrintAndLogEx(WARNING, "File content error. '%s' must include 8 HEX symbols", line);
continue;
}
line[8] = 0;
// realloc keyblock array size.
if (stKeyBlock - keycnt < 2) {
p = realloc(keyBlock, 4 * (stKeyBlock += 10));
if (!p) {
PrintAndLogEx(WARNING, "Cannot allocate memory for defaultKeys");
free(keyBlock);
if (f)
fclose(f);
return 2;
}
keyBlock = p;
}
// clear mem
memset(keyBlock + 4 * keycnt, 0, 4);
num_to_bytes(strtoll(line, NULL, 16), 4, keyBlock + 4 * keycnt);
// PrintAndLogEx(NORMAL, "chk custom pwd[%2d] %08X", keycnt, bytes_to_num(keyBlock + 4 * keycnt, 4) );
keycnt++;
memset(line, 0, sizeof(line));
}
if (f)
fclose(f);
if (keycnt == 0) {
PrintAndLogEx(WARNING, "No keys found in file"); PrintAndLogEx(WARNING, "No keys found in file");
free(keyBlock); free(keyBlock);
return 1; return 1;
} }
PrintAndLogEx(SUCCESS, "Loaded %d keys", keycnt);
// loop // loop
uint64_t testpwd = 0x00; uint64_t curr_password = 0x00;
for (uint16_t c = 0; c < keycnt; ++c) { for (uint16_t c = 0; c < keycount; ++c) {
if (IsOffline()) { if (IsOffline()) {
PrintAndLogEx(WARNING, "Device offline\n"); PrintAndLogEx(WARNING, "Device offline\n");
@ -1766,35 +1725,33 @@ int CmdT55xxChkPwds(const char *Cmd) {
return 0; return 0;
} }
testpwd = bytes_to_num(keyBlock + 4 * c, 4); curr_password = bytes_to_num(keyBlock + 4 * c, 4);
PrintAndLogEx(INFO, "Testing %08X", testpwd); PrintAndLogEx(INFO, "Testing %08X", curr_password);
if (!AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, true, testpwd)) { if (!AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, true, curr_password)) {
PrintAndLogEx(INFO, "Aquireing data from device failed. Quitting"); continue;
free(keyBlock);
return 0;
} }
found = tryDetectModulation(); found = tryDetectModulation();
if (found) if (found)
break; break;
} }
if (found) if (found)
PrintAndLogEx(SUCCESS, "Found valid password: [ %08X ]", testpwd); PrintAndLogEx(SUCCESS, "Found valid password: [ " _GREEN_("%08X") " ]", curr_password);
else else
PrintAndLogEx(WARNING, "Password NOT found."); PrintAndLogEx(WARNING, "Check pwd failed");
} }
free(keyBlock); free(keyBlock);
out: out:
t1 = msclock() - t1; t1 = msclock() - t1;
PrintAndLogEx(SUCCESS, "\nTime in bruteforce: %.0f seconds\n", (float)t1 / 1000.0); PrintAndLogEx(SUCCESS, "\nTime in check pwd: %.0f seconds\n", (float)t1 / 1000.0);
return 0; return 0;
} }
// Bruteforce - incremental password range search
int CmdT55xxBruteForce(const char *Cmd) { int CmdT55xxBruteForce(const char *Cmd) {
uint32_t start_password = 0x00000000; //start password uint32_t start_password = 0x00000000; //start password
@ -1802,15 +1759,11 @@ int CmdT55xxBruteForce(const char *Cmd) {
uint32_t curr = 0; uint32_t curr = 0;
bool found = false; bool found = false;
char cmdp = tolower(param_getchar(Cmd, 0)); char cmdp = tolower(param_getchar(Cmd, 0));
if (cmdp == 'h') return usage_t55xx_bruteforce(); if (cmdp == 'h') return usage_t55xx_bruteforce();
uint64_t t1 = msclock(); uint64_t t1 = msclock();
// Try to read Block 7, first :)
// incremental pwd range search
start_password = param_get32ex(Cmd, 0, 0, 16); start_password = param_get32ex(Cmd, 0, 0, 16);
end_password = param_get32ex(Cmd, 1, 0, 16); end_password = param_get32ex(Cmd, 1, 0, 16);
@ -1831,24 +1784,20 @@ int CmdT55xxBruteForce(const char *Cmd) {
return 0; return 0;
} }
if (!AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, true, curr)) { found = tryOnePassword(curr);
PrintAndLogEx(WARNING, "Aquiring data from device failed. Quitting");
return 0;
}
found = tryDetectModulation();
if (curr == end_password) if (curr == end_password)
break; break;
curr++; curr++;
} }
PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "");
if (found) if (found)
PrintAndLogEx(SUCCESS, "Found valid password: [ %08X ]", curr); PrintAndLogEx(SUCCESS, "Found valid password: [ " _GREEN_("%08X") " ]", curr);
else else
PrintAndLogEx(WARNING, "Password NOT found. Last tried: [ %08X ]", --curr); PrintAndLogEx(WARNING, "Bruteforce failed, last tried: [ " _YELLOW_("%08X") " ]", --curr);
t1 = msclock() - t1; t1 = msclock() - t1;
PrintAndLogEx(SUCCESS, "\nTime in bruteforce: %.0f seconds\n", (float)t1 / 1000.0); PrintAndLogEx(SUCCESS, "\nTime in bruteforce: %.0f seconds\n", (float)t1 / 1000.0);
@ -1856,11 +1805,12 @@ int CmdT55xxBruteForce(const char *Cmd) {
} }
int tryOnePassword(uint32_t password) { int tryOnePassword(uint32_t password) {
PrintAndLogEx(INFO, "Trying password %08x", password); PrintAndLogEx(INFO, "Trying password %08X", password);
if (!AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, true, password)) {
PrintAndLogEx(NORMAL, "Acquire data from device failed. Quitting"); AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, true, password);
return -1;
} if (getSignalProperties()->isnoise == false)
return 0;
if (tryDetectModulation()) if (tryDetectModulation())
return 1; return 1;
@ -1882,12 +1832,15 @@ int CmdT55xxRecoverPW(const char *Cmd) {
// first try fliping each bit in the expected password // first try fliping each bit in the expected password
while (bit < 32) { while (bit < 32) {
curr_password = orig_password ^ (1 << bit); curr_password = orig_password ^ (1u << bit);
found = tryOnePassword(curr_password); found = tryOnePassword(curr_password);
if (found == -1) return 0; if ( found == 1)
goto out;
bit++; bit++;
if (IsCancelled()) return 0; if (IsCancelled())
return 0;
} }
// now try to use partial original password, since block 7 should have been completely // now try to use partial original password, since block 7 should have been completely
@ -1897,26 +1850,30 @@ int CmdT55xxRecoverPW(const char *Cmd) {
// from low bit to high bit // from low bit to high bit
bit = 0; bit = 0;
while (bit < 32) { while (bit < 32) {
mask += (1 << bit); mask += (1u << bit);
curr_password = orig_password & mask; curr_password = orig_password & mask;
// if updated mask didn't change the password, don't try it again // if updated mask didn't change the password, don't try it again
if (prev_password == curr_password) { if (prev_password == curr_password) {
bit++; bit++;
continue; continue;
} }
found = tryOnePassword(curr_password); found = tryOnePassword(curr_password);
if (found == -1) return 0; if ( found == 1 )
goto out;
bit++; bit++;
prev_password = curr_password; prev_password = curr_password;
if (IsCancelled()) return 0; if (IsCancelled())
return 0;
} }
// from high bit to low // from high bit to low
bit = 0; bit = 0;
mask = 0xffffffff; mask = 0xffffffff;
while (bit < 32) { while (bit < 32) {
mask -= (1 << bit); mask -= (1u << bit);
curr_password = orig_password & mask; curr_password = orig_password & mask;
// if updated mask didn't change the password, don't try it again // if updated mask didn't change the password, don't try it again
if (prev_password == curr_password) { if (prev_password == curr_password) {
@ -1924,20 +1881,24 @@ int CmdT55xxRecoverPW(const char *Cmd) {
continue; continue;
} }
found = tryOnePassword(curr_password); found = tryOnePassword(curr_password);
if (found == -1) if ( found == 1 )
return 0; goto out;
bit++; bit++;
prev_password = curr_password; prev_password = curr_password;
if (IsCancelled()) return 0; if (IsCancelled())
return 0;
} }
out:
PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "");
if (found == 1) if (found == 1)
PrintAndLogEx(SUCCESS, "Found valid password: [%08x]", curr_password); PrintAndLogEx(SUCCESS, "Found valid password: [ " _GREEN_("%08X") " ]", curr_password);
else else
PrintAndLogEx(WARNING, "Password NOT found."); PrintAndLogEx(WARNING, "Recover pwd failed");
return 0; return 0;
} }

View file

@ -24,7 +24,8 @@
#include "cmdlf.h" #include "cmdlf.h"
#include "util.h" #include "util.h"
#include "lfdemod.h" #include "lfdemod.h"
#include "cmdhf14a.h" //for getTagInfo #include "cmdhf14a.h" // for getTagInfo
#include "loclass/fileutils.h" // loadDictionary
#define T55x7_CONFIGURATION_BLOCK 0x00 #define T55x7_CONFIGURATION_BLOCK 0x00
@ -37,6 +38,7 @@
#define T55X7_DEFAULT_CONFIG_BLOCK 0x000880E8 // ASK, compat mode, data rate 32, manchester, STT, 7 data blocks #define T55X7_DEFAULT_CONFIG_BLOCK 0x000880E8 // ASK, compat mode, data rate 32, manchester, STT, 7 data blocks
#define T55X7_RAW_CONFIG_BLOCK 0x000880E0 // ASK, compat mode, data rate 32, manchester, 7 data blocks #define T55X7_RAW_CONFIG_BLOCK 0x000880E0 // ASK, compat mode, data rate 32, manchester, 7 data blocks
#define T55X7_EM_UNIQUE_CONFIG_BLOCK 0x00148040 // ASK, emulate em4x02/unique - compat mode, manchester, data rate 64, 2 data blocks #define T55X7_EM_UNIQUE_CONFIG_BLOCK 0x00148040 // ASK, emulate em4x02/unique - compat mode, manchester, data rate 64, 2 data blocks
#define T55X7_EM_PAXTON_CONFIG_BLOCK 0x00148040 // ASK, emulate em4x02/paxton - compat mode, manchester, data rate 64, 2 data blocks
// FDXB requires data inversion and BiPhase 57 is simply BiPhase 50 inverted, so we can either do it using the modulation scheme or the inversion flag // FDXB requires data inversion and BiPhase 57 is simply BiPhase 50 inverted, so we can either do it using the modulation scheme or the inversion flag
// we've done both below to prove that it works either way, and the modulation value for BiPhase 50 in the Atmel data sheet of binary "10001" (17) is a typo, // we've done both below to prove that it works either way, and the modulation value for BiPhase 50 in the Atmel data sheet of binary "10001" (17) is a typo,
// and it should actually be "10000" (16) // and it should actually be "10000" (16)
@ -53,6 +55,7 @@
#define T55X7_PRESCO_CONFIG_BLOCK 0x00088088 // ASK, data rate 32, Manchester, 5 data blocks, STT #define T55X7_PRESCO_CONFIG_BLOCK 0x00088088 // ASK, data rate 32, Manchester, 5 data blocks, STT
#define T55X7_NEDAP_64_CONFIG_BLOCK 0x907f0042 // BiPhase, data rate 64, 3 data blocks #define T55X7_NEDAP_64_CONFIG_BLOCK 0x907f0042 // BiPhase, data rate 64, 3 data blocks
#define T55X7_NEDAP_128_CONFIG_BLOCK 0x907f0082 // BiPhase, data rate 64, 5 data blocks #define T55X7_NEDAP_128_CONFIG_BLOCK 0x907f0082 // BiPhase, data rate 64, 5 data blocks
#define T55X7_bin 0b0010 #define T55X7_bin 0b0010
#define T5555_DEFAULT_CONFIG_BLOCK 0x6001F004 // data rate 64 , ask, manchester, 2 data blocks? #define T5555_DEFAULT_CONFIG_BLOCK 0x6001F004 // data rate 64 , ask, manchester, 2 data blocks?
@ -161,9 +164,8 @@ extern bool tryDetectP1(bool getData);
bool test(uint8_t mode, uint8_t *offset, int *fndBitRate, uint8_t clk, bool *Q5); bool test(uint8_t mode, uint8_t *offset, int *fndBitRate, uint8_t clk, bool *Q5);
int special(const char *Cmd); int special(const char *Cmd);
bool AquireData(uint8_t page, uint8_t block, bool pwdmode, uint32_t password); bool AquireData(uint8_t page, uint8_t block, bool pwdmode, uint32_t password);
bool AquireDataEx(uint8_t page, uint8_t block, bool pwdmode, uint32_t password, uint32_t timing) ;
bool detectPassword(int password); int tryOnePassword(uint32_t password);
void printT55x7Trace(t55x7_tracedata_t data, uint8_t repeat); void printT55x7Trace(t55x7_tracedata_t data, uint8_t repeat);
void printT5555Trace(t5555_tracedata_t data, uint8_t repeat); void printT5555Trace(t5555_tracedata_t data, uint8_t repeat);

View file

@ -191,7 +191,7 @@ int CmdTIDemod(const char *Cmd) {
bits[i] = '1'; bits[i] = '1';
maxPos += highLen; maxPos += highLen;
// bitstream arrives lsb first so shift right // bitstream arrives lsb first so shift right
shift3 |= (1 << 31); shift3 |= (1u << 31);
} else { } else {
bits[i] = '.'; bits[i] = '.';
maxPos += lowLen; maxPos += lowLen;
@ -254,7 +254,7 @@ int CmdTIDemod(const char *Cmd) {
//crc = crc16_ccitt(message, sizeof(message); //crc = crc16_ccitt(message, sizeof(message);
char *crcStr = (crc == (shift2 & 0xFFFF)) ? "Passed" : "Failed"; char *crcStr = (crc == (shift2 & 0xFFFF)) ? _GREEN_("Passed") : _RED_("Failed");
PrintAndLogEx(INFO, "Tag data = %08X%08X [Crc %04X %s]", shift1, shift0, crc, crcStr); PrintAndLogEx(INFO, "Tag data = %08X%08X [Crc %04X %s]", shift1, shift0, crc, crcStr);

View file

@ -49,13 +49,13 @@ int usage_sm_info(void) {
return 0; return 0;
} }
int usage_sm_upgrade(void) { int usage_sm_upgrade(void) {
PrintAndLogEx(NORMAL, "Upgrade firmware"); PrintAndLogEx(NORMAL, "Upgrade RDV4.0 Sim module firmware");
PrintAndLogEx(NORMAL, "Usage: sc upgrade f <file name>"); PrintAndLogEx(NORMAL, "Usage: sc upgrade f <file name>");
PrintAndLogEx(NORMAL, " h : this help"); PrintAndLogEx(NORMAL, " h : this help");
PrintAndLogEx(NORMAL, " f <filename> : firmware file name"); PrintAndLogEx(NORMAL, " f <filename> : firmware file name");
PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, " sc upgrade f myfile"); PrintAndLogEx(NORMAL, " sc upgrade f ../tools/simmodule/SIM011.BIN");
return 0; return 0;
} }
int usage_sm_setclock(void) { int usage_sm_setclock(void) {
@ -116,7 +116,7 @@ uint8_t GetATRTA1(uint8_t *atr, size_t atrlen) {
return atr[2]; return atr[2];
} }
return 0x11; // default value is 0x11, corresponding to fmax=5 MHz, Fi=372, Di=1. return 0x11; // default value is 0x11, corresponding to fmax=5 MHz, Fi=372, Di=1.
} }
int DiArray[] = { int DiArray[] = {
@ -196,6 +196,8 @@ static int PrintATR(uint8_t *atr, size_t atrlen) {
uint8_t T0 = atr[1]; uint8_t T0 = atr[1];
uint8_t K = T0 & 0x0F; uint8_t K = T0 & 0x0F;
uint8_t TD1 = 0, T1len = 0, TD1len = 0, TDilen = 0; uint8_t TD1 = 0, T1len = 0, TD1len = 0, TDilen = 0;
bool protocol_T0_present = true;
bool protocol_T15_present = false;
if (T0 & 0x10) { if (T0 & 0x10) {
PrintAndLog("\t- TA1 (Maximum clock frequency, proposed bit duration) [ 0x%02x ]", atr[2 + T1len]); PrintAndLog("\t- TA1 (Maximum clock frequency, proposed bit duration) [ 0x%02x ]", atr[2 + T1len]);
@ -215,6 +217,14 @@ static int PrintATR(uint8_t *atr, size_t atrlen) {
if (T0 & 0x80) { if (T0 & 0x80) {
TD1 = atr[2 + T1len]; TD1 = atr[2 + T1len];
PrintAndLog("\t- TD1 (First offered transmission protocol, presence of TA2..TD2) [ 0x%02x ] Protocol T%d", TD1, TD1 & 0x0f); PrintAndLog("\t- TD1 (First offered transmission protocol, presence of TA2..TD2) [ 0x%02x ] Protocol T%d", TD1, TD1 & 0x0f);
protocol_T0_present = false;
if ((TD1 & 0x0f) == 0) {
protocol_T0_present = true;
}
if ((TD1 & 0x0f) == 15) {
protocol_T15_present = true;
}
T1len++; T1len++;
if (TD1 & 0x10) { if (TD1 & 0x10) {
@ -232,6 +242,12 @@ static int PrintATR(uint8_t *atr, size_t atrlen) {
if (TD1 & 0x80) { if (TD1 & 0x80) {
uint8_t TDi = atr[2 + T1len + TD1len]; uint8_t TDi = atr[2 + T1len + TD1len];
PrintAndLog("\t- TD2 (A supported protocol or more global parameters, presence of TA3..TD3) [ 0x%02x ] Protocol T%d", TDi, TDi & 0x0f); PrintAndLog("\t- TD2 (A supported protocol or more global parameters, presence of TA3..TD3) [ 0x%02x ] Protocol T%d", TDi, TDi & 0x0f);
if ((TDi & 0x0f) == 0) {
protocol_T0_present = true;
}
if ((TDi & 0x0f) == 15) {
protocol_T15_present = true;
}
TD1len++; TD1len++;
bool nextCycle = true; bool nextCycle = true;
@ -262,19 +278,20 @@ static int PrintATR(uint8_t *atr, size_t atrlen) {
} }
} }
if (!protocol_T0_present || protocol_T15_present) { // there is CRC Check Byte TCK
uint8_t vxor = 0; uint8_t vxor = 0;
for (int i = 1; i < atrlen; i++) for (int i = 1; i < atrlen; i++)
vxor ^= atr[i]; vxor ^= atr[i];
if (vxor) if (vxor)
PrintAndLogEx(WARNING, "Check summ error. Must be 0 got 0x%02X", vxor); PrintAndLogEx(WARNING, "Check sum error. Must be 0 got 0x%02X", vxor);
else else
PrintAndLogEx(INFO, "Check summ OK."); PrintAndLogEx(INFO, "Check sum OK.");
}
if (atr[0] != 0x3b) if (atr[0] != 0x3b)
PrintAndLogEx(WARNING, "Not a direct convention [ 0x%02x ]", atr[0]); PrintAndLogEx(WARNING, "Not a direct convention [ 0x%02x ]", atr[0]);
uint8_t calen = 2 + T1len + TD1len + TDilen + K; uint8_t calen = 2 + T1len + TD1len + TDilen + K;
if (atrlen != calen && atrlen != calen + 1) // may be CRC if (atrlen != calen && atrlen != calen + 1) // may be CRC
@ -561,8 +578,9 @@ int ExchangeAPDUSC(uint8_t *datain, int datainlen, bool activateCard, bool leave
int CmdSmartUpgrade(const char *Cmd) { int CmdSmartUpgrade(const char *Cmd) {
PrintAndLogEx(WARNING, "WARNING - Smartcard socket firmware upgrade."); PrintAndLogEx(WARNING, "WARNING - Sim module firmware upgrade.");
PrintAndLogEx(WARNING, "A dangerous command, do wrong and you will brick the smart card socket"); PrintAndLogEx(WARNING, "A dangerous command, do wrong and you could brick the sim module");
PrintAndLogEx(NORMAL, "");
FILE *f; FILE *f;
char filename[FILE_PATH_SIZE] = {0}; char filename[FILE_PATH_SIZE] = {0};
@ -592,10 +610,33 @@ int CmdSmartUpgrade(const char *Cmd) {
//Validations //Validations
if (errors || cmdp == 0) return usage_sm_upgrade(); if (errors || cmdp == 0) return usage_sm_upgrade();
// load file
char sha512filename[FILE_PATH_SIZE] = {'\0'};
char *bin_extension = filename;
char *dot_position = NULL;
while ((dot_position = strchr(bin_extension, '.')) != NULL) {
bin_extension = dot_position + 1;
}
if (!strcmp(bin_extension, "BIN")
#ifdef _WIN32
|| !strcmp(bin_extension, "bin")
#endif
) {
memcpy(sha512filename, filename, strlen(filename) - strlen("bin"));
strcat(sha512filename, "sha512.txt");
} else {
PrintAndLogEx(FAILED, "Filename extension of firmware upgrade file must be .BIN");
return 1;
}
PrintAndLogEx(INFO, "firmware file : " _YELLOW_("%s"), filename);
PrintAndLogEx(INFO, "Checking integrity : " _YELLOW_("%s"), sha512filename);
// load firmware file
f = fopen(filename, "rb"); f = fopen(filename, "rb");
if (!f) { if (!f) {
PrintAndLogEx(FAILED, "File: " _YELLOW_("%s") ": not found or locked.", filename); PrintAndLogEx(FAILED, "Firmware file " _YELLOW_("%s") " not found or locked.", filename);
return 1; return 1;
} }
@ -605,27 +646,83 @@ int CmdSmartUpgrade(const char *Cmd) {
fseek(f, 0, SEEK_SET); fseek(f, 0, SEEK_SET);
if (fsize < 0) { if (fsize < 0) {
PrintAndLogDevice(WARNING, "error, when getting filesize"); PrintAndLogEx(WARNING, "error, when getting filesize");
fclose(f); fclose(f);
return 1; return 1;
} }
uint8_t *dump = calloc(fsize, sizeof(uint8_t)); uint8_t *dump = calloc(fsize, sizeof(uint8_t));
if (!dump) { if (!dump) {
PrintAndLogDevice(WARNING, "error, cannot allocate memory "); PrintAndLogEx(WARNING, "error, cannot allocate memory ");
fclose(f); fclose(f);
return 1; return 1;
} }
size_t bytes_read = fread(dump, 1, fsize, f); size_t firmware_size = fread(dump, 1, fsize, f);
if (f) {
fclose(f);
}
// load sha512 file
f = fopen(sha512filename, "rb");
if (!f) {
PrintAndLogEx(FAILED, "SHA-512 file not found or locked.");
free(dump);
return 1;
}
// get filesize in order to malloc memory
fseek(f, 0, SEEK_END);
fsize = ftell(f);
fseek(f, 0, SEEK_SET);
if (fsize < 0) {
PrintAndLogEx(FAILED, "Could not determine size of SHA-512 file");
fclose(f);
free(dump);
return 1;
}
if (fsize < 128) {
PrintAndLogEx(FAILED, "SHA-512 file too short");
fclose(f);
free(dump);
return 1;
}
char hashstring[129];
size_t bytes_read = fread(hashstring, 1, 128, f);
hashstring[128] = '\0';
if (f) if (f)
fclose(f); fclose(f);
PrintAndLogEx(SUCCESS, "Smartcard socket firmware uploading to PM3"); uint8_t hash1[64];
if (bytes_read != 128 || param_gethex(hashstring, 0, hash1, 128)) {
PrintAndLogEx(FAILED, "Couldn't read SHA-512 file");
free(dump);
return 1;
}
uint8_t hash2[64];
if (sha512hash(dump, firmware_size, hash2)) {
PrintAndLogEx(FAILED, "Couldn't calculate SHA-512 of firmware");
free(dump);
return 1;
}
if (memcmp(hash1, hash2, 64)) {
PrintAndLogEx(FAILED, "Couldn't verify integrity of firmware file " _RED_("(wrong SHA-512 hash)"));
free(dump);
return 1;
}
PrintAndLogEx(SUCCESS, "Sim module firmware uploading to PM3");
//Send to device //Send to device
uint32_t index = 0; uint32_t index = 0;
uint32_t bytes_sent = 0; uint32_t bytes_sent = 0;
uint32_t bytes_remaining = bytes_read; uint32_t bytes_remaining = firmware_size;
while (bytes_remaining > 0) { while (bytes_remaining > 0) {
uint32_t bytes_in_packet = MIN(USB_CMD_DATA_SIZE, bytes_remaining); uint32_t bytes_in_packet = MIN(USB_CMD_DATA_SIZE, bytes_remaining);
@ -649,10 +746,10 @@ int CmdSmartUpgrade(const char *Cmd) {
} }
free(dump); free(dump);
printf("\n"); printf("\n");
PrintAndLogEx(SUCCESS, "Smartcard socket firmware updating, don\'t turn off your PM3!"); PrintAndLogEx(SUCCESS, "Sim module firmware updating, don\'t turn off your PM3!");
// trigger the firmware upgrade // trigger the firmware upgrade
UsbCommand c = {CMD_SMART_UPGRADE, {bytes_read, 0, 0}}; UsbCommand c = {CMD_SMART_UPGRADE, {firmware_size, 0, 0}};
clearCommandBuffer(); clearCommandBuffer();
SendCommand(&c); SendCommand(&c);
UsbCommand resp; UsbCommand resp;
@ -660,10 +757,12 @@ int CmdSmartUpgrade(const char *Cmd) {
PrintAndLogEx(WARNING, "timeout while waiting for reply."); PrintAndLogEx(WARNING, "timeout while waiting for reply.");
return 1; return 1;
} }
if ((resp.arg[0] & 0xFF)) if ((resp.arg[0] & 0xFF)) {
PrintAndLogEx(SUCCESS, "Smartcard socket firmware upgraded successful"); PrintAndLogEx(SUCCESS, "Sim module firmware upgrade " _GREEN_("successful"));
else PrintAndLogEx(SUCCESS, "\n run " _YELLOW_("`hw status`") " to validate the fw version ");
PrintAndLogEx(FAILED, "Smartcard socket firmware updating failed"); } else {
PrintAndLogEx(FAILED, "Sim module firmware upgrade " _RED_("failed"));
}
return 0; return 0;
} }
@ -874,11 +973,11 @@ static void smart_brute_prim() {
if (len > 2) { if (len > 2) {
//if ( decodeTLV ) { // if ( decodeTLV ) {
//if (!TLVPrintFromBuffer(buf, len-2)) { // if (!TLVPrintFromBuffer(buf, len-2)) {
PrintAndLogEx(SUCCESS, "\tHEX %d |: %s", len, sprint_hex(buf, len)); PrintAndLogEx(SUCCESS, "\tHEX %d |: %s", len, sprint_hex(buf, len));
//} // }
//} // }
} }
len = 0; len = 0;
} }
@ -1129,7 +1228,7 @@ static command_t CommandTable[] = {
{"info", CmdSmartInfo, 1, "Tag information"}, {"info", CmdSmartInfo, 1, "Tag information"},
{"reader", CmdSmartReader, 1, "Act like an IS07816 reader"}, {"reader", CmdSmartReader, 1, "Act like an IS07816 reader"},
{"raw", CmdSmartRaw, 1, "Send raw hex data to tag"}, {"raw", CmdSmartRaw, 1, "Send raw hex data to tag"},
{"upgrade", CmdSmartUpgrade, 1, "Upgrade firmware"}, {"upgrade", CmdSmartUpgrade, 1, "Upgrade sim module firmware"},
{"setclock", CmdSmartSetClock, 1, "Set clock speed"}, {"setclock", CmdSmartSetClock, 1, "Set clock speed"},
{"brute", CmdSmartBruteforceSFI, 1, "Bruteforce SFI"}, {"brute", CmdSmartBruteforceSFI, 1, "Bruteforce SFI"},
{NULL, NULL, 0, NULL} {NULL, NULL, 0, NULL}

View file

@ -25,6 +25,7 @@
#include "emv/emvcore.h" // decodeTVL #include "emv/emvcore.h" // decodeTVL
#include "emv/apduinfo.h" // APDUcode description #include "emv/apduinfo.h" // APDUcode description
#include "emv/dump.h" // dump_buffer #include "emv/dump.h" // dump_buffer
#include "crypto/libpcrypto.h" // sha512hash
extern int CmdSmartcard(const char *Cmd); extern int CmdSmartcard(const char *Cmd);

View file

@ -36,6 +36,7 @@ int usage_trace_list() {
PrintAndLogEx(NORMAL, " 7816 - interpret data as iso7816-4 communications"); PrintAndLogEx(NORMAL, " 7816 - interpret data as iso7816-4 communications");
PrintAndLogEx(NORMAL, " legic - interpret data as LEGIC communications"); PrintAndLogEx(NORMAL, " legic - interpret data as LEGIC communications");
PrintAndLogEx(NORMAL, " felica - interpret data as ISO18092 / FeliCa communications"); PrintAndLogEx(NORMAL, " felica - interpret data as ISO18092 / FeliCa communications");
PrintAndLogEx(NORMAL, " hitag - interpret data as Hitag2 / HitagS communications");
PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, " trace list 14a f"); PrintAndLogEx(NORMAL, " trace list 14a f");
@ -175,6 +176,7 @@ uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, ui
crcStatus = iso15693_CRC_check(frame, data_len); crcStatus = iso15693_CRC_check(frame, data_len);
break; break;
case ISO_7816_4: case ISO_7816_4:
case PROTO_HITAG:
default: default:
break; break;
} }
@ -184,16 +186,17 @@ uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, ui
//2 Not crc-command //2 Not crc-command
//--- Draw the data column //--- Draw the data column
char line[18][110]; char line[18][110] = {{0}};
for (int j = 0; j < data_len && j / 18 < 18; j++) { for (int j = 0; j < data_len && j / 18 < 18; j++) {
uint8_t parityBits = parityBytes[j >> 3]; uint8_t parityBits = parityBytes[j >> 3];
if (protocol != LEGIC && if (protocol != LEGIC
protocol != ISO_14443B && && protocol != ISO_14443B
protocol != ISO_7816_4 && && protocol != ISO_7816_4
(isResponse || protocol == ISO_14443A) && && protocol != PROTO_HITAG
(oddparity8(frame[j]) != ((parityBits >> (7 - (j & 0x0007))) & 0x01))) { && (isResponse || protocol == ISO_14443A)
&& (oddparity8(frame[j]) != ((parityBits >> (7 - (j & 0x0007))) & 0x01))) {
snprintf(line[j / 18] + ((j % 18) * 4), 110, "%02x! ", frame[j]); snprintf(line[j / 18] + ((j % 18) * 4), 110, "%02x! ", frame[j]);
} else { } else {
@ -332,7 +335,7 @@ void printFelica(uint16_t traceLen, uint8_t *trace) {
uint8_t cmd = trace[tracepos]; uint8_t cmd = trace[tracepos];
uint8_t isResponse = cmd & 1; uint8_t isResponse = cmd & 1;
char line[32][110]; char line[32][110] = {{0}};
for (int j = 0; j < len + 1 && j / 8 < 32; j++) { for (int j = 0; j < len + 1 && j / 8 < 32; j++) {
snprintf(line[j / 8] + ((j % 8) * 4), 110, " %02x ", trace[tracepos + j]); snprintf(line[j / 8] + ((j % 8) * 4), 110, " %02x ", trace[tracepos + j]);
} }
@ -565,6 +568,7 @@ int CmdTraceList(const char *Cmd) {
else if (strcmp(type, "15") == 0) protocol = ISO_15693; else if (strcmp(type, "15") == 0) protocol = ISO_15693;
else if (strcmp(type, "felica") == 0) protocol = FELICA; else if (strcmp(type, "felica") == 0) protocol = FELICA;
else if (strcmp(type, "mf") == 0) protocol = PROTO_MIFARE; else if (strcmp(type, "mf") == 0) protocol = PROTO_MIFARE;
else if (strcmp(type, "hitag") == 0) protocol = PROTO_HITAG;
else if (strcmp(type, "raw") == 0) protocol = -1; //No crc, no annotations else if (strcmp(type, "raw") == 0) protocol = -1; //No crc, no annotations
else errors = true; else errors = true;
@ -625,6 +629,8 @@ int CmdTraceList(const char *Cmd) {
PrintAndLogEx(NORMAL, "ISO15693 - Timings are not as accurate"); PrintAndLogEx(NORMAL, "ISO15693 - Timings are not as accurate");
if (protocol == ISO_7816_4) if (protocol == ISO_7816_4)
PrintAndLogEx(NORMAL, "ISO7816-4 / Smartcard - Timings N/A yet"); PrintAndLogEx(NORMAL, "ISO7816-4 / Smartcard - Timings N/A yet");
if (protocol == PROTO_HITAG)
PrintAndLogEx(NORMAL, "Hitag2 / HitagS - Timings in ETU (8us)");
PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, " Start | End | Src | Data (! denotes parity error) | CRC | Annotation"); PrintAndLogEx(NORMAL, " Start | End | Src | Data (! denotes parity error) | CRC | Annotation");
@ -642,8 +648,8 @@ int CmdTraceLoad(const char *Cmd) {
FILE *f = NULL; FILE *f = NULL;
char filename[FILE_PATH_SIZE]; char filename[FILE_PATH_SIZE];
char cmdp = param_getchar(Cmd, 0); char cmdp = tolower(param_getchar(Cmd, 0));
if (strlen(Cmd) < 1 || cmdp == 'h' || cmdp == 'H') return usage_trace_load(); if (strlen(Cmd) < 1 || cmdp == 'h') return usage_trace_load();
param_getstr(Cmd, 0, filename, sizeof(filename)); param_getstr(Cmd, 0, filename, sizeof(filename));
@ -688,13 +694,13 @@ int CmdTraceLoad(const char *Cmd) {
int CmdTraceSave(const char *Cmd) { int CmdTraceSave(const char *Cmd) {
if (traceLen == 0) { if (traceLen == 0) {
PrintAndLogEx(WARNING, "trace is empty, exiting..."); PrintAndLogEx(WARNING, "trace is empty, nothing to save");
return 0; return 0;
} }
char filename[FILE_PATH_SIZE]; char filename[FILE_PATH_SIZE];
char cmdp = param_getchar(Cmd, 0); char cmdp = tolower(param_getchar(Cmd, 0));
if (strlen(Cmd) < 1 || cmdp == 'h' || cmdp == 'H') return usage_trace_save(); if (strlen(Cmd) < 1 || cmdp == 'h') return usage_trace_save();
param_getstr(Cmd, 0, filename, sizeof(filename)); param_getstr(Cmd, 0, filename, sizeof(filename));
saveFile(filename, "bin", trace, traceLen); saveFile(filename, "bin", trace, traceLen);

View file

@ -73,8 +73,7 @@ static bool print_cb(void *data, const struct tlv *tlv, int level, bool is_leaf)
int asn1_print(uint8_t *asn1buf, size_t asn1buflen, char *indent) { int asn1_print(uint8_t *asn1buf, size_t asn1buflen, char *indent) {
struct tlvdb *t = NULL; struct tlvdb *t = tlvdb_parse_multi(asn1buf, asn1buflen);
t = tlvdb_parse_multi(asn1buf, asn1buflen);
if (t) { if (t) {
tlvdb_visit(t, print_cb, NULL, 0); tlvdb_visit(t, print_cb, NULL, 0);
tlvdb_free(t); tlvdb_free(t);

View file

@ -19,6 +19,7 @@
#include <mbedtls/pk.h> #include <mbedtls/pk.h>
#include <mbedtls/ecdsa.h> #include <mbedtls/ecdsa.h>
#include <mbedtls/sha256.h> #include <mbedtls/sha256.h>
#include <mbedtls/sha512.h>
#include <mbedtls/ctr_drbg.h> #include <mbedtls/ctr_drbg.h>
#include <mbedtls/entropy.h> #include <mbedtls/entropy.h>
#include <mbedtls/error.h> #include <mbedtls/error.h>
@ -106,6 +107,20 @@ int sha256hash(uint8_t *input, int length, uint8_t *hash) {
return 0; return 0;
} }
int sha512hash(uint8_t *input, int length, uint8_t *hash) {
if (!hash || !input)
return 1;
mbedtls_sha512_context sctx;
mbedtls_sha512_init(&sctx);
mbedtls_sha512_starts(&sctx, 0); //SHA-512, not 384
mbedtls_sha512_update(&sctx, input, length);
mbedtls_sha512_finish(&sctx, hash);
mbedtls_sha512_free(&sctx);
return 0;
}
int ecdsa_init_str(mbedtls_ecdsa_context *ctx, char *key_d, char *key_x, char *key_y) { int ecdsa_init_str(mbedtls_ecdsa_context *ctx, char *key_d, char *key_x, char *key_y) {
if (!ctx) if (!ctx)
return 1; return 1;

View file

@ -22,6 +22,7 @@ extern int aes_cmac(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *mac, int
extern int aes_cmac8(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *mac, int length); extern int aes_cmac8(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *mac, int length);
extern int sha256hash(uint8_t *input, int length, uint8_t *hash); extern int sha256hash(uint8_t *input, int length, uint8_t *hash);
extern int sha512hash(uint8_t *input, int length, uint8_t *hash);
extern int ecdsa_key_create(uint8_t *key_d, uint8_t *key_xy); extern int ecdsa_key_create(uint8_t *key_d, uint8_t *key_xy);
extern int ecdsa_public_key_from_pk(mbedtls_pk_context *pk, uint8_t *key, size_t keylen); extern int ecdsa_public_key_from_pk(mbedtls_pk_context *pk, uint8_t *key, size_t keylen);

View file

@ -18,6 +18,8 @@ A5B4C3D2,
1C0B5848, 1C0B5848,
# paxton bullit? # paxton bullit?
575F4F4B, 575F4F4B,
#
50520901,
# Default pwd, simple: # Default pwd, simple:
00000000, 00000000,
11111111, 11111111,

View file

@ -0,0 +1,5 @@
#
# Mifare Ultralight Default Keys
# -- iceman fork version --
# -- contribute to this list, sharing is caring --
425245414B4D454946594F5543414E21 -- Sample Key (BREAKMEIFYOUCAN!)

View file

@ -288,6 +288,7 @@ int CmdEMVGPO(const char *cmd) {
PrintAndLogEx(ERR, "Can't create PDOL data."); PrintAndLogEx(ERR, "Can't create PDOL data.");
tlvdb_free(tmp_ext); tlvdb_free(tmp_ext);
tlvdb_free(tlvRoot); tlvdb_free(tlvRoot);
free(pdol_data_tlv);
return 4; return 4;
} }
PrintAndLogEx(INFO, "PDOL data[%d]: %s", pdol_data_tlv_data_len, sprint_hex(pdol_data_tlv_data, pdol_data_tlv_data_len)); PrintAndLogEx(INFO, "PDOL data[%d]: %s", pdol_data_tlv_data_len, sprint_hex(pdol_data_tlv_data, pdol_data_tlv_data_len));
@ -1577,6 +1578,7 @@ int CmdEMVScan(const char *cmd) {
if (!pdol_data_tlv_data) { if (!pdol_data_tlv_data) {
PrintAndLogEx(ERR, "Can't create PDOL data."); PrintAndLogEx(ERR, "Can't create PDOL data.");
tlvdb_free(tlvRoot); tlvdb_free(tlvRoot);
free(pdol_data_tlv);
DropFieldEx(channel); DropFieldEx(channel);
return 6; return 6;
} }

View file

@ -177,7 +177,7 @@ static struct crypto_pk *crypto_pk_polarssl_genkey_rsa(va_list vl) {
int res = mbedtls_rsa_gen_key(&cp->ctx, &myrand, NULL, nbits, exp); int res = mbedtls_rsa_gen_key(&cp->ctx, &myrand, NULL, nbits, exp);
if (res) { if (res) {
fprintf(stderr, "PolarSSL private key generation error res=%x exp=%d nbits=%d.\n", res * -1, exp, nbits); fprintf(stderr, "PolarSSL private key generation error res=%x exp=%u nbits=%u.\n", res * -1, exp, nbits);
free(cp); free(cp);
return NULL; return NULL;
} }

View file

@ -315,7 +315,7 @@ int exec_crypto_test(bool verbose) {
unsigned int kl = keylengths[i]; unsigned int kl = keylengths[i];
ret = test_genkey(kl, message, kl / 8, verbose); ret = test_genkey(kl, message, kl / 8, verbose);
if (ret) { if (ret) {
fprintf(stderr, "Crypto generate key[%d] test: failed\n", kl); fprintf(stderr, "Crypto generate key[%u] test: failed\n", kl);
return ret; return ret;
} }
} }

View file

@ -64,9 +64,9 @@ static int build_segs_from_phdrs(flash_file_t *ctx, FILE *fd, Elf32_Phdr *phdrs,
} }
fprintf(stdout, "%d: V 0x%08x P 0x%08x (0x%08x->0x%08x) [%c%c%c] @0x%x\n", fprintf(stdout, "%d: V 0x%08x P 0x%08x (0x%08x->0x%08x) [%c%c%c] @0x%x\n",
i, vaddr, paddr, filesz, memsz, i, vaddr, paddr, filesz, memsz,
flags & PF_R ? 'R' : ' ', (flags & PF_R) ? 'R' : ' ',
flags & PF_W ? 'W' : ' ', (flags & PF_W) ? 'W' : ' ',
flags & PF_X ? 'X' : ' ', (flags & PF_X) ? 'X' : ' ',
offset); offset);
if (filesz != memsz) { if (filesz != memsz) {
fprintf(stderr, "Error: PHDR file size does not equal memory size\n" fprintf(stderr, "Error: PHDR file size does not equal memory size\n"
@ -179,7 +179,7 @@ static int check_segs(flash_file_t *ctx, int can_write_bl) {
// Load an ELF file and prepare it for flashing // Load an ELF file and prepare it for flashing
int flash_load(flash_file_t *ctx, const char *name, int can_write_bl) { int flash_load(flash_file_t *ctx, const char *name, int can_write_bl) {
FILE *fd = NULL; FILE *fd;
Elf32_Ehdr ehdr; Elf32_Ehdr ehdr;
Elf32_Phdr *phdrs = NULL; Elf32_Phdr *phdrs = NULL;
uint16_t num_phdrs; uint16_t num_phdrs;
@ -410,7 +410,7 @@ int flash_write(flash_file_t *ctx) {
uint32_t blocks = (length + BLOCK_SIZE - 1) / BLOCK_SIZE; uint32_t blocks = (length + BLOCK_SIZE - 1) / BLOCK_SIZE;
uint32_t end = seg->start + length; uint32_t end = seg->start + length;
fprintf(stdout, " 0x%08x..0x%08x [0x%x / %d blocks]", seg->start, end - 1, length, blocks); fprintf(stdout, " 0x%08x..0x%08x [0x%x / %u blocks]", seg->start, end - 1, length, blocks);
fflush(stdout); fflush(stdout);
int block = 0; int block = 0;
uint8_t *data = seg->data; uint8_t *data = seg->data;
@ -423,7 +423,7 @@ int flash_write(flash_file_t *ctx) {
if (write_block(baddr, data, block_size) < 0) { if (write_block(baddr, data, block_size) < 0) {
fprintf(stderr, " ERROR\n"); fprintf(stderr, " ERROR\n");
fprintf(stderr, "Error writing block %d of %d\n", block, blocks); fprintf(stderr, "Error writing block %d of %u\n", block, blocks);
return -1; return -1;
} }

View file

@ -167,7 +167,6 @@ int zlib_compress(FILE *infile[], uint8_t num_infiles, FILE *outfile, bool hardn
fclose(infile[j]); fclose(infile[j]);
} }
fclose(outfile); fclose(outfile);
free(infile);
free(fpga_config); free(fpga_config);
return (EXIT_FAILURE); return (EXIT_FAILURE);
} }
@ -182,7 +181,6 @@ int zlib_compress(FILE *infile[], uint8_t num_infiles, FILE *outfile, bool hardn
fclose(infile[j]); fclose(infile[j]);
} }
fclose(outfile); fclose(outfile);
free(infile);
free(fpga_config); free(fpga_config);
return (EXIT_SUCCESS); return (EXIT_SUCCESS);
@ -322,42 +320,42 @@ static int FpgaGatherVersion(FILE *infile, char *infile_name, char *dst, int len
} }
if (!memcmp("fpga_lf", basename(infile_name), 7)) if (!memcmp("fpga_lf", basename(infile_name), 7))
strncat(dst, "LF", len - 1); strncat(dst, "LF", len - strlen(dst) - 1);
else if (!memcmp("fpga_hf", basename(infile_name), 7)) else if (!memcmp("fpga_hf", basename(infile_name), 7))
strncat(dst, "HF", len - 1); strncat(dst, "HF", len - strlen(dst) - 1);
strncat(dst, " image built", len - 1); strncat(dst, " image built", len - strlen(dst) - 1);
if (bitparse_find_section(infile, 'b', &fpga_info_len)) { if (bitparse_find_section(infile, 'b', &fpga_info_len)) {
strncat(dst, " for ", len - 1); strncat(dst, " for ", len - strlen(dst) - 1);
for (uint16_t i = 0; i < fpga_info_len; i++) { for (uint16_t i = 0; i < fpga_info_len; i++) {
char c = (char)fgetc(infile); char c = (char)fgetc(infile);
if (i < sizeof(tempstr)) { if (i < sizeof(tempstr)) {
tempstr[i] = c; tempstr[i] = c;
} }
} }
strncat(dst, tempstr, len - 1); strncat(dst, tempstr, len - strlen(dst) - 1);
} }
if (bitparse_find_section(infile, 'c', &fpga_info_len)) { if (bitparse_find_section(infile, 'c', &fpga_info_len)) {
strncat(dst, " on ", len - 1); strncat(dst, " on ", len - strlen(dst) - 1);
for (uint16_t i = 0; i < fpga_info_len; i++) { for (uint16_t i = 0; i < fpga_info_len; i++) {
char c = (char)fgetc(infile); char c = (char)fgetc(infile);
if (i < sizeof(tempstr)) { if (i < sizeof(tempstr)) {
tempstr[i] = c; tempstr[i] = c;
} }
} }
strncat(dst, tempstr, len - 1); strncat(dst, tempstr, len - strlen(dst) - 1);
} }
if (bitparse_find_section(infile, 'd', &fpga_info_len)) { if (bitparse_find_section(infile, 'd', &fpga_info_len)) {
strncat(dst, " at ", len - 1); strncat(dst, " at ", len - strlen(dst) - 1);
for (uint16_t i = 0; i < fpga_info_len; i++) { for (uint16_t i = 0; i < fpga_info_len; i++) {
char c = (char)fgetc(infile); char c = (char)fgetc(infile);
if (i < sizeof(tempstr)) { if (i < sizeof(tempstr)) {
tempstr[i] = c; tempstr[i] = c;
} }
} }
strncat(dst, tempstr, len - 1); strncat(dst, tempstr, len - strlen(dst) - 1);
} }
return 0; return 0;
} }
@ -413,21 +411,27 @@ int main(int argc, char **argv) {
infiles = calloc(1, sizeof(FILE *)); infiles = calloc(1, sizeof(FILE *));
if (argc != 4) { if (argc != 4) {
usage(); usage();
free(infiles);
return (EXIT_FAILURE); return (EXIT_FAILURE);
} }
infiles[0] = fopen(argv[2], "rb"); infiles[0] = fopen(argv[2], "rb");
if (infiles[0] == NULL) { if (infiles[0] == NULL) {
fprintf(stderr, "Error. Cannot open input file %s\n\n", argv[2]); fprintf(stderr, "Error. Cannot open input file %s\n\n", argv[2]);
free(infiles);
return (EXIT_FAILURE); return (EXIT_FAILURE);
} }
outfile = fopen(argv[3], "wb"); outfile = fopen(argv[3], "wb");
if (outfile == NULL) { if (outfile == NULL) {
fprintf(stderr, "Error. Cannot open output file %s\n\n", argv[3]); fprintf(stderr, "Error. Cannot open output file %s\n\n", argv[3]);
free(infiles);
return (EXIT_FAILURE); return (EXIT_FAILURE);
} }
return zlib_decompress(infiles[0], outfile);
} else { // Compress or gemerate version info int ret = zlib_decompress(infiles[0], outfile);
free(infiles);
return (ret);
} else { // Compress or generate version info
bool hardnested_mode = false; bool hardnested_mode = false;
bool generate_version_file = false; bool generate_version_file = false;
@ -453,20 +457,29 @@ int main(int argc, char **argv) {
infiles[i] = fopen(infile_names[i], "rb"); infiles[i] = fopen(infile_names[i], "rb");
if (infiles[i] == NULL) { if (infiles[i] == NULL) {
fprintf(stderr, "Error. Cannot open input file %s\n\n", infile_names[i]); fprintf(stderr, "Error. Cannot open input file %s\n\n", infile_names[i]);
free(infile_names);
free(infiles);
return (EXIT_FAILURE); return (EXIT_FAILURE);
} }
} }
outfile = fopen(argv[argc - 1], "wb"); outfile = fopen(argv[argc - 1], "wb");
if (outfile == NULL) { if (outfile == NULL) {
fprintf(stderr, "Error. Cannot open output file %s\n\n", argv[argc - 1]); fprintf(stderr, "Error. Cannot open output file %s\n\n", argv[argc - 1]);
free(infile_names);
free(infiles);
return (EXIT_FAILURE); return (EXIT_FAILURE);
} }
if (generate_version_file) { if (generate_version_file) {
if (generate_fpga_version_info(infiles, infile_names, num_input_files, outfile)) { if (generate_fpga_version_info(infiles, infile_names, num_input_files, outfile)) {
free(infile_names);
free(infiles);
return (EXIT_FAILURE); return (EXIT_FAILURE);
} }
} else { } else {
return zlib_compress(infiles, num_input_files, outfile, hardnested_mode); int ret = zlib_compress(infiles, num_input_files, outfile, hardnested_mode);
free(infile_names);
free(infiles);
return (ret);
} }
} }
} }

View file

@ -44,7 +44,7 @@ static uint16_t PartialSumProperty(uint32_t state, odd_even_t odd_even) {
uint32_t st = state; uint32_t st = state;
uint16_t part_sum = 0; uint16_t part_sum = 0;
if (odd_even == ODD_STATE) { if (odd_even == ODD_STATE) {
for (uint16_t i = 0; i < 5; i++) { for (uint16_t i = 0; i < 4; i++) {
part_sum ^= filter(st); part_sum ^= filter(st);
st = (st << 1) | ((j >> (3 - i)) & 0x01) ; st = (st << 1) | ((j >> (3 - i)) & 0x01) ;
} }
@ -240,7 +240,7 @@ void init_sum_bitarray(uint16_t sum_a0) {
} }
for (odd_even_t odd_even = EVEN_STATE; odd_even <= ODD_STATE; odd_even++) { for (odd_even_t odd_even = EVEN_STATE; odd_even <= ODD_STATE; odd_even++) {
uint32_t count = count_states(sum_a0_bitarray[odd_even]); uint32_t count = count_states(sum_a0_bitarray[odd_even]);
printf("sum_a0_bitarray[%s] has %d states (%5.2f%%)\n", odd_even == EVEN_STATE ? "even" : "odd ", count, (float)count / (1 << 24) * 100.0); printf("sum_a0_bitarray[%s] has %u states (%5.2f%%)\n", odd_even == EVEN_STATE ? "even" : "odd ", count, (float)count / (1 << 24) * 100.0);
} }
printf("done.\n"); printf("done.\n");
} }
@ -350,7 +350,7 @@ static void precalculate_bit0_bitflip_bitarrays(uint8_t const bitflip, uint16_t
for (odd_even_t odd_even = EVEN_STATE; odd_even <= ODD_STATE; odd_even++) { for (odd_even_t odd_even = EVEN_STATE; odd_even <= ODD_STATE; odd_even++) {
count[odd_even] = count_states(test_bitarray[odd_even]); count[odd_even] = count_states(test_bitarray[odd_even]);
if (count[odd_even] != 1 << 24) { if (count[odd_even] != 1 << 24) {
printf("Writing %d possible %s states for bitflip property %03x (%d (%1.2f%%) states eliminated)\n", printf("Writing %u possible %s states for bitflip property %03x (%d (%1.2f%%) states eliminated)\n",
count[odd_even], count[odd_even],
odd_even == EVEN_STATE ? "even" : "odd", odd_even == EVEN_STATE ? "even" : "odd",
bitflip, (1 << 24) - count[odd_even], bitflip, (1 << 24) - count[odd_even],
@ -368,7 +368,7 @@ static void precalculate_bit0_bitflip_bitarrays(uint8_t const bitflip, uint16_t
if (count[odd_even] != 1 << 24) { if (count[odd_even] != 1 << 24) {
for (uint32_t state = 0; state < (1 << 24); state += 1 << 4) { for (uint32_t state = 0; state < (1 << 24); state += 1 << 4) {
uint32_t line = test_bitarray[odd_even][state >> 5]; uint32_t line = test_bitarray[odd_even][state >> 5];
uint16_t half_line = state & 0x000000010 ? line & 0x0000ffff : line >> 16; uint16_t half_line = (state & 0x000000010) ? line & 0x0000ffff : line >> 16;
if (half_line != 0) { if (half_line != 0) {
for (uint32_t low_bits = 0; low_bits < (1 << 4); low_bits++) { for (uint32_t low_bits = 0; low_bits < (1 << 4); low_bits++) {
set_bit24(test_bitarray_2nd, low_bits << 20 | state >> 4); set_bit24(test_bitarray_2nd, low_bits << 20 | state >> 4);
@ -377,7 +377,7 @@ static void precalculate_bit0_bitflip_bitarrays(uint8_t const bitflip, uint16_t
} }
count[odd_even] = count_states(test_bitarray_2nd); count[odd_even] = count_states(test_bitarray_2nd);
if (count[odd_even] != 1 << 24) { if (count[odd_even] != 1 << 24) {
printf("Writing %d possible %s states for bitflip property %03x (%d (%1.2f%%) states eliminated)\n", printf("Writing %u possible %s states for bitflip property %03x (%d (%1.2f%%) states eliminated)\n",
count[odd_even], count[odd_even],
odd_even == EVEN_STATE ? "even" : "odd", odd_even == EVEN_STATE ? "even" : "odd",
bitflip | BITFLIP_2ND_BYTE, (1 << 24) - count[odd_even], bitflip | BITFLIP_2ND_BYTE, (1 << 24) - count[odd_even],
@ -462,7 +462,7 @@ static void precalculate_bit0_bitflip_bitarrays(uint8_t const bitflip, uint16_t
for (odd_even_t odd_even = EVEN_STATE; odd_even <= ODD_STATE; odd_even++) { for (odd_even_t odd_even = EVEN_STATE; odd_even <= ODD_STATE; odd_even++) {
count[odd_even] = count_states(test_not_bitarray[odd_even]); count[odd_even] = count_states(test_not_bitarray[odd_even]);
if (count[odd_even] != 1 << 24) { if (count[odd_even] != 1 << 24) {
printf("Writing %d possible %s states for bitflip property %03x (%d (%1.2f%%) states eliminated)\n", printf("Writing %u possible %s states for bitflip property %03x (%d (%1.2f%%) states eliminated)\n",
count[odd_even], count[odd_even],
odd_even == EVEN_STATE ? "even" : "odd", odd_even == EVEN_STATE ? "even" : "odd",
bitflip | 0x100, (1 << 24) - count[odd_even], bitflip | 0x100, (1 << 24) - count[odd_even],
@ -480,7 +480,7 @@ static void precalculate_bit0_bitflip_bitarrays(uint8_t const bitflip, uint16_t
if (count[odd_even] != 1 << 24) { if (count[odd_even] != 1 << 24) {
for (uint32_t state = 0; state < (1 << 24); state += 1 << 4) { for (uint32_t state = 0; state < (1 << 24); state += 1 << 4) {
uint32_t line = test_not_bitarray[odd_even][state >> 5]; uint32_t line = test_not_bitarray[odd_even][state >> 5];
uint16_t half_line = state & 0x000000010 ? line & 0x0000ffff : line >> 16; uint16_t half_line = (state & 0x000000010) ? line & 0x0000ffff : line >> 16;
if (half_line != 0) { if (half_line != 0) {
for (uint32_t low_bits = 0; low_bits < (1 << 4); low_bits++) { for (uint32_t low_bits = 0; low_bits < (1 << 4); low_bits++) {
set_bit24(test_bitarray_2nd, low_bits << 20 | state >> 4); set_bit24(test_bitarray_2nd, low_bits << 20 | state >> 4);
@ -489,7 +489,7 @@ static void precalculate_bit0_bitflip_bitarrays(uint8_t const bitflip, uint16_t
} }
count[odd_even] = count_states(test_bitarray_2nd); count[odd_even] = count_states(test_bitarray_2nd);
if (count[odd_even] != 1 << 24) { if (count[odd_even] != 1 << 24) {
printf("Writing %d possible %s states for bitflip property %03x (%d (%1.2f%%) states eliminated)\n", printf("Writing %u possible %s states for bitflip property %03x (%d (%1.2f%%) states eliminated)\n",
count[odd_even], count[odd_even],
odd_even == EVEN_STATE ? "even" : "odd", odd_even == EVEN_STATE ? "even" : "odd",
bitflip | 0x100 | BITFLIP_2ND_BYTE, (1 << 24) - count[odd_even], bitflip | 0x100 | BITFLIP_2ND_BYTE, (1 << 24) - count[odd_even],
@ -518,7 +518,7 @@ static void precalculate_bit0_bitflip_bitarrays(uint8_t const bitflip, uint16_t
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
unsigned int bitflip_in; unsigned int bitflip_in;
int sum_a0; int sum_a0 = 0;
printf("Create tables required by hardnested attack.\n"); printf("Create tables required by hardnested attack.\n");
printf("Expect a runtime in the range of days or weeks.\n"); printf("Expect a runtime in the range of days or weeks.\n");

View file

@ -96,7 +96,7 @@ typedef struct {
#define CMD_IO_DEMOD_FSK 0x021A #define CMD_IO_DEMOD_FSK 0x021A
#define CMD_IO_CLONE_TAG 0x021B #define CMD_IO_CLONE_TAG 0x021B
#define CMD_EM410X_DEMOD 0x021c #define CMD_EM410X_DEMOD 0x021c
// Sampling configuration for LF reader/snooper // Sampling configuration for LF reader/sniffer
#define CMD_SET_LF_SAMPLING_CONFIG 0x021d #define CMD_SET_LF_SAMPLING_CONFIG 0x021d
#define CMD_FSK_SIM_TAG 0x021E #define CMD_FSK_SIM_TAG 0x021E
#define CMD_ASK_SIM_TAG 0x021F #define CMD_ASK_SIM_TAG 0x021F
@ -119,10 +119,10 @@ typedef struct {
#define CMD_ISO_15693_COMMAND 0x0313 #define CMD_ISO_15693_COMMAND 0x0313
#define CMD_ISO_15693_COMMAND_DONE 0x0314 #define CMD_ISO_15693_COMMAND_DONE 0x0314
#define CMD_ISO_15693_FIND_AFI 0x0315 #define CMD_ISO_15693_FIND_AFI 0x0315
#define CMD_LF_SNOOP_RAW_ADC_SAMPLES 0x0317 #define CMD_LF_SNIFF_RAW_ADC_SAMPLES 0x0317
// For Hitag2 transponders // For Hitag2 transponders
#define CMD_SNOOP_HITAG 0x0370 #define CMD_SNIFF_HITAG 0x0370
#define CMD_SIMULATE_HITAG 0x0371 #define CMD_SIMULATE_HITAG 0x0371
#define CMD_READER_HITAG 0x0372 #define CMD_READER_HITAG 0x0372
@ -135,8 +135,8 @@ typedef struct {
#define CMD_ANTIFUZZ_ISO_14443a 0x0380 #define CMD_ANTIFUZZ_ISO_14443a 0x0380
#define CMD_SIMULATE_TAG_ISO_14443B 0x0381 #define CMD_SIMULATE_TAG_ISO_14443B 0x0381
#define CMD_SNOOP_ISO_14443B 0x0382 #define CMD_SNIFF_ISO_14443B 0x0382
#define CMD_SNOOP_ISO_14443a 0x0383 #define CMD_SNIFF_ISO_14443a 0x0383
#define CMD_SIMULATE_TAG_ISO_14443a 0x0384 #define CMD_SIMULATE_TAG_ISO_14443a 0x0384
#define CMD_READER_ISO_14443a 0x0385 #define CMD_READER_ISO_14443a 0x0385
@ -151,7 +151,7 @@ typedef struct {
#define CMD_LEGIC_ESET 0x03BD #define CMD_LEGIC_ESET 0x03BD
#define CMD_LEGIC_EGET 0x03BE #define CMD_LEGIC_EGET 0x03BE
#define CMD_SNOOP_ICLASS 0x0392 #define CMD_SNIFF_ICLASS 0x0392
#define CMD_SIMULATE_TAG_ICLASS 0x0393 #define CMD_SIMULATE_TAG_ICLASS 0x0393
#define CMD_READER_ICLASS 0x0394 #define CMD_READER_ICLASS 0x0394
#define CMD_READER_ICLASS_REPLAY 0x0395 #define CMD_READER_ICLASS_REPLAY 0x0395

Binary file not shown.

View file

@ -187,22 +187,22 @@ static JSON_INLINE enum json_error_code json_error_code(const json_error_t *e) {
/* getters, setters, manipulation */ /* getters, setters, manipulation */
void json_object_seed(size_t seed); void json_object_seed(size_t seed);
size_t json_object_size(const json_t *object); size_t json_object_size(const json_t *json);
json_t *json_object_get(const json_t *object, const char *key) JANSSON_ATTRS(warn_unused_result); json_t *json_object_get(const json_t *json, const char *key) JANSSON_ATTRS(warn_unused_result);
int json_object_set_new(json_t *object, const char *key, json_t *value); int json_object_set_new(json_t *json, const char *key, json_t *value);
int json_object_set_new_nocheck(json_t *object, const char *key, json_t *value); int json_object_set_new_nocheck(json_t *json, const char *key, json_t *value);
int json_object_del(json_t *object, const char *key); int json_object_del(json_t *json, const char *key);
int json_object_clear(json_t *object); int json_object_clear(json_t *json);
int json_object_update(json_t *object, json_t *other); int json_object_update(json_t *object, json_t *other);
int json_object_update_existing(json_t *object, json_t *other); int json_object_update_existing(json_t *object, json_t *other);
int json_object_update_missing(json_t *object, json_t *other); int json_object_update_missing(json_t *object, json_t *other);
void *json_object_iter(json_t *object); void *json_object_iter(json_t *json);
void *json_object_iter_at(json_t *object, const char *key); void *json_object_iter_at(json_t *json, const char *key);
void *json_object_key_to_iter(const char *key); void *json_object_key_to_iter(const char *key);
void *json_object_iter_next(json_t *object, void *iter); void *json_object_iter_next(json_t *json, void *iter);
const char *json_object_iter_key(void *iter); const char *json_object_iter_key(void *iter);
json_t *json_object_iter_value(void *iter); json_t *json_object_iter_value(void *iter);
int json_object_iter_set_new(json_t *object, void *iter, json_t *value); int json_object_iter_set_new(json_t *json, void *iter, json_t *value);
#define json_object_foreach(object, key, value) \ #define json_object_foreach(object, key, value) \
for(key = json_object_iter_key(json_object_iter(object)); \ for(key = json_object_iter_key(json_object_iter(object)); \
@ -236,14 +236,14 @@ int json_object_iter_set(json_t *object, void *iter, json_t *value) {
return json_object_iter_set_new(object, iter, json_incref(value)); return json_object_iter_set_new(object, iter, json_incref(value));
} }
size_t json_array_size(const json_t *array); size_t json_array_size(const json_t *json);
json_t *json_array_get(const json_t *array, size_t index) JANSSON_ATTRS(warn_unused_result); json_t *json_array_get(const json_t *json, size_t index) JANSSON_ATTRS(warn_unused_result);
int json_array_set_new(json_t *array, size_t index, json_t *value); int json_array_set_new(json_t *json, size_t index, json_t *value);
int json_array_append_new(json_t *array, json_t *value); int json_array_append_new(json_t *json, json_t *value);
int json_array_insert_new(json_t *array, size_t index, json_t *value); int json_array_insert_new(json_t *json, size_t index, json_t *value);
int json_array_remove(json_t *array, size_t index); int json_array_remove(json_t *json, size_t index);
int json_array_clear(json_t *array); int json_array_clear(json_t *json);
int json_array_extend(json_t *array, json_t *other); int json_array_extend(json_t *json, json_t *other);
static JSON_INLINE static JSON_INLINE
int json_array_set(json_t *array, size_t ind, json_t *value) { int json_array_set(json_t *array, size_t ind, json_t *value) {
@ -260,16 +260,16 @@ int json_array_insert(json_t *array, size_t ind, json_t *value) {
return json_array_insert_new(array, ind, json_incref(value)); return json_array_insert_new(array, ind, json_incref(value));
} }
const char *json_string_value(const json_t *string); const char *json_string_value(const json_t *json);
size_t json_string_length(const json_t *string); size_t json_string_length(const json_t *json);
json_int_t json_integer_value(const json_t *integer); json_int_t json_integer_value(const json_t *integer);
double json_real_value(const json_t *real); double json_real_value(const json_t *real);
double json_number_value(const json_t *json); double json_number_value(const json_t *json);
int json_string_set(json_t *string, const char *value); int json_string_set(json_t *json, const char *value);
int json_string_setn(json_t *string, const char *value, size_t len); int json_string_setn(json_t *json, const char *value, size_t len);
int json_string_set_nocheck(json_t *string, const char *value); int json_string_set_nocheck(json_t *json, const char *value);
int json_string_setn_nocheck(json_t *string, const char *value, size_t len); int json_string_setn_nocheck(json_t *json, const char *value, size_t len);
int json_integer_set(json_t *integer, json_int_t value); int json_integer_set(json_t *integer, json_int_t value);
int json_real_set(json_t *real, double value); int json_real_set(json_t *real, double value);

View file

@ -87,9 +87,7 @@ bool B(State state) {
bool x2 = state.b & 0x20; bool x2 = state.b & 0x20;
bool x3 = state.b & 0x10; bool x3 = state.b & 0x10;
bool x7 = state.b & 0x01; bool x7 = state.b & 0x01;
return x1 ^ x2 ^ x3 ^ x7; return x1 ^ x2 ^ x3 ^ x7;
} }

View file

@ -155,11 +155,12 @@ int saveFileJSON(const char *preferredName, const char *suffix, JSONFileType fty
json_t *root = json_object(); json_t *root = json_object();
JsonSaveStr(root, "Created", "proxmark3"); JsonSaveStr(root, "Created", "proxmark3");
switch (ftype) { switch (ftype) {
case jsfRaw: case jsfRaw: {
JsonSaveStr(root, "FileType", "raw"); JsonSaveStr(root, "FileType", "raw");
JsonSaveBufAsHexCompact(root, "raw", data, datalen); JsonSaveBufAsHexCompact(root, "raw", data, datalen);
break; break;
case jsfCardMemory: }
case jsfCardMemory: {
JsonSaveStr(root, "FileType", "mfcard"); JsonSaveStr(root, "FileType", "mfcard");
for (int i = 0; i < (datalen / 16); i++) { for (int i = 0; i < (datalen / 16); i++) {
char path[PATH_MAX_LENGTH] = {0}; char path[PATH_MAX_LENGTH] = {0};
@ -208,7 +209,8 @@ int saveFileJSON(const char *preferredName, const char *suffix, JSONFileType fty
} }
} }
break; break;
case jsfMfuMemory: }
case jsfMfuMemory: {
JsonSaveStr(root, "FileType", "mfu"); JsonSaveStr(root, "FileType", "mfu");
mfu_dump_t *tmp = (mfu_dump_t *)data; mfu_dump_t *tmp = (mfu_dump_t *)data;
@ -230,13 +232,27 @@ int saveFileJSON(const char *preferredName, const char *suffix, JSONFileType fty
size_t len = (datalen - DUMP_PREFIX_LENGTH) / 4; size_t len = (datalen - DUMP_PREFIX_LENGTH) / 4;
for (int i = 0; i < len; i++) { for (int i = 0; i < len; i++) {
char path[PATH_MAX_LENGTH] = {0}; char path[PATH_MAX_LENGTH] = {0};
sprintf(path, "$.blocks.%d", i); sprintf(path, "$.blocks.%d", i);
JsonSaveBufAsHexCompact(root, path, tmp->data + (i * 4), 4); JsonSaveBufAsHexCompact(root, path, tmp->data + (i * 4), 4);
} }
break; break;
} }
case jsfHitag: {
JsonSaveStr(root, "FileType", "hitag");
uint8_t uid[4] = {0};
memcpy(uid, data, 4);
JsonSaveBufAsHexCompact(root, "$.Card.UID", uid, sizeof(uid));
for (int i = 0; i < (datalen / 4); i++) {
char path[PATH_MAX_LENGTH] = {0};
sprintf(path, "$.blocks.%d", i);
JsonSaveBufAsHexCompact(root, path, data + (i * 4), 4);
}
break;
}
}
int res = json_dump_file(root, fileName, JSON_INDENT(2)); int res = json_dump_file(root, fileName, JSON_INDENT(2));
if (res) { if (res) {
@ -253,7 +269,7 @@ out:
return retval; return retval;
} }
int loadFile(const char *preferredName, const char *suffix, void *data, size_t *datalen) { int loadFile(const char *preferredName, const char *suffix, void *data, size_t maxdatalen, size_t *datalen) {
if (preferredName == NULL) return 1; if (preferredName == NULL) return 1;
if (suffix == NULL) return 1; if (suffix == NULL) return 1;
@ -298,6 +314,11 @@ int loadFile(const char *preferredName, const char *suffix, void *data, size_t *
goto out; goto out;
} }
if (bytes_read != maxdatalen) {
PrintAndLogDevice(WARNING, "Warning, bytes read exeed calling array limit. Max bytes is %d bytes", maxdatalen);
bytes_read = maxdatalen;
}
memcpy((data), dump, bytes_read); memcpy((data), dump, bytes_read);
free(dump); free(dump);
@ -447,8 +468,29 @@ int loadFileJSON(const char *preferredName, const char *suffix, void *data, size
*datalen = sptr; *datalen = sptr;
} }
if (!strcmp(ctype, "hitag")) {
size_t sptr = 0;
for (int i = 0; i < (maxdatalen / 4); i++) {
if (sptr + 4 > maxdatalen) {
retval = 5;
goto out;
}
PrintAndLog("loaded from JSON file " _YELLOW_("%s"), fileName); char path[30] = {0};
sprintf(path, "$.blocks.%d", i);
size_t len = 0;
JsonLoadBufAsHex(root, path, &udata[sptr], 4, &len);
if (!len)
break;
sptr += len;
}
*datalen = sptr;
}
PrintAndLogEx(SUCCESS, "loaded from JSON file " _YELLOW_("%s"), fileName);
out: out:
json_decref(root); json_decref(root);
free(fileName); free(fileName);
@ -497,7 +539,6 @@ int loadFileDICTIONARY(const char *preferredName, const char *suffix, void *data
if (strlen(line) < keylen) if (strlen(line) < keylen)
continue; continue;
// The line start with # is comment, skip // The line start with # is comment, skip
if (line[0] == '#') if (line[0] == '#')
continue; continue;

View file

@ -55,6 +55,11 @@ typedef enum {
jsfRaw, jsfRaw,
jsfCardMemory, jsfCardMemory,
jsfMfuMemory, jsfMfuMemory,
jsfHitag,
// jsf14b,
// jsf15,
// jsfLegic,
// jsfT55xx,
} JSONFileType; } JSONFileType;
int fileExists(const char *filename); int fileExists(const char *filename);
@ -107,10 +112,11 @@ extern int saveFileJSON(const char *preferredName, const char *suffix, JSONFileT
* @param preferredName * @param preferredName
* @param suffix the file suffix. Leave out the ".". * @param suffix the file suffix. Leave out the ".".
* @param data The data array to store the loaded bytes from file * @param data The data array to store the loaded bytes from file
* @param maxdatalen the number of bytes that your data array has
* @param datalen the number of bytes loaded from file * @param datalen the number of bytes loaded from file
* @return 0 for ok, 1 for failz * @return 0 for ok, 1 for failz
*/ */
extern int loadFile(const char *preferredName, const char *suffix, void *data, size_t *datalen); extern int loadFile(const char *preferredName, const char *suffix, void *data, size_t maxdatalen, size_t *datalen);
/** /**
* @brief Utility function to load data from a textfile (EML). This method takes a preferred name. * @brief Utility function to load data from a textfile (EML). This method takes a preferred name.

View file

@ -54,12 +54,12 @@ local function parse14443a(data)
Based on this struct : Based on this struct :
typedef struct { typedef struct {
byte_t uid[10]; uint8_t uid[10];
byte_t uidlen; uint8_t uidlen;
byte_t atqa[2]; uint8_t atqa[2];
byte_t sak; uint8_t sak;
byte_t ats_len; uint8_t ats_len;
byte_t ats[256]; uint8_t ats[256];
} __attribute__((__packed__)) iso14a_card_select_t; } __attribute__((__packed__)) iso14a_card_select_t;
--]] --]]

View file

@ -31,11 +31,11 @@ local function parse1443b(data)
Based on this struct : Based on this struct :
typedef struct { typedef struct {
byte_t uid[10]; uint8_t uid[10];
byte_t uidlen; uint8_t uidlen;
byte_t atqb[7]; uint8_t atqb[7];
byte_t chipid; uint8_t chipid;
byte_t cid; uint8_t cid;
} __attribute__((__packed__)) iso14b_card_select_t; } __attribute__((__packed__)) iso14b_card_select_t;
--]] --]]

View file

@ -95,7 +95,7 @@ bool mfkey32(nonces_t data, uint64_t *outputkey) {
uint8_t counter = 0; uint8_t counter = 0;
uint32_t p640 = prng_successor(data.nonce, 64); uint32_t p640 = prng_successor(data.nonce, 64);
uint32_t p641 = prng_successor(data.nonce2, 64);
s = lfsr_recovery32(data.ar ^ p640, 0); s = lfsr_recovery32(data.ar ^ p640, 0);
for (t = s; t->odd | t->even; ++t) { for (t = s; t->odd | t->even; ++t) {
@ -105,7 +105,7 @@ bool mfkey32(nonces_t data, uint64_t *outputkey) {
crypto1_get_lfsr(t, &key); crypto1_get_lfsr(t, &key);
crypto1_word(t, data.cuid ^ data.nonce, 0); crypto1_word(t, data.cuid ^ data.nonce, 0);
crypto1_word(t, data.nr2, 1); crypto1_word(t, data.nr2, 1);
if (data.ar2 == (crypto1_word(t, 0, 0) ^ p641)) { if (data.ar2 == (crypto1_word(t, 0, 0) ^ p640)) {
outkey = key; outkey = key;
counter++; counter++;
if (counter == 20) break; if (counter == 20) break;

View file

@ -1027,7 +1027,9 @@ void detect_classic_magic(void) {
case 2: case 2:
PrintAndLogEx(SUCCESS, "Answers to magic commands (GEN 1b): " _GREEN_("YES")); PrintAndLogEx(SUCCESS, "Answers to magic commands (GEN 1b): " _GREEN_("YES"));
break; break;
//case 4: PrintAndLogEx(SUCCESS, "Answers to magic commands (GEN 2): " _GREEN_("YES")); break; case 4:
PrintAndLogEx(SUCCESS, "Answers to magic commands (GEN 2 / CUID): " _GREEN_("YES"));
break;
default: default:
PrintAndLogEx(INFO, "Answers to magic commands: " _YELLOW_("NO")); PrintAndLogEx(INFO, "Answers to magic commands: " _YELLOW_("NO"));
break; break;

View file

@ -1,10 +1,10 @@
/* bmpbit.c /* bmpbit.c
* Greg Cook, 26/Jul/2018 * Greg Cook, 23/Feb/2019
*/ */
/* CRC RevEng: arbitrary-precision CRC calculator and algorithm finder /* CRC RevEng: arbitrary-precision CRC calculator and algorithm finder
* Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 * Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018,
* Gregory Cook * 2019 Gregory Cook
* *
* This file is part of CRC RevEng. * This file is part of CRC RevEng.
* *

Some files were not shown because too many files have changed in this diff Show more