Merge branch 'master' into hf_mf_sim

This commit is contained in:
vratiskol 2019-03-15 21:17:44 +01:00
commit cbea5d9d02
161 changed files with 2002 additions and 1463 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,35 @@ 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]
- 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

@ -106,8 +106,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
@ -60,7 +60,7 @@ APP_CFLAGS = $(PLATFORM_DEFS) \
SRC_LCD = fonts.c LCD.c SRC_LCD = fonts.c LCD.c
SRC_LF = lfops.c hitag2.c hitagS.c lfsampling.c pcf7931.c lfdemod.c SRC_LF = lfops.c hitag2_crypto.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_ISO14443b = iso14443b.c SRC_ISO14443b = iso14443b.c

View file

@ -650,8 +650,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 +664,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]);
@ -765,8 +765,8 @@ 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], (byte_t *)c->d.asBytes);
@ -786,7 +786,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 +843,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 +862,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 +871,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 +1003,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 +1043,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 +1322,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 +1391,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,24 +222,12 @@ 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);

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);

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
@ -279,7 +151,6 @@ static void hitag_send_frame(const uint8_t *frame, size_t frame_len) {
LOW(GPIO_SSC_DOUT); LOW(GPIO_SSC_DOUT);
} }
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,8 +269,8 @@ 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);
@ -419,7 +290,6 @@ static void hitag_reader_send_bit(int bit) {
// 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 +305,6 @@ static void hitag_reader_send_bit(int bit) {
LED_A_OFF(); LED_A_OFF();
} }
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++) {
@ -605,8 +474,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);
@ -801,7 +670,10 @@ 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) { void SniffHitag(uint32_t type) {
StopTicks();
int frame_count; int frame_count;
int response; int response;
int overflow; int overflow;
@ -814,12 +686,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 +697,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 +720,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_TC1->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 +840,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 +871,46 @@ 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");
} }
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 +931,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_TC1->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 +1007,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 +1024,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 +1043,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 +1084,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 +1091,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 +1100,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 +1108,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 +1120,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 +1133,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 +1169,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 +1254,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
@ -1477,11 +1326,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 +1343,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 +1358,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 +1374,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 +1391,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 +1438,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 +1484,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 +1495,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 +1505,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 +1577,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 +1590,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

@ -2781,7 +2781,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);

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

@ -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);

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

@ -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

@ -417,18 +417,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, 16));
} }
return 1; return 1;
} }
@ -475,14 +473,15 @@ 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
//amplify signal before ST check
if (amp == 'a') if (amp == 'a')
askAmp(bits, BitLen); askAmp(bits, BitLen);
@ -496,8 +495,8 @@ int ASKDemod_ext(const char *Cmd, bool verbose, bool emSearch, uint8_t askType,
clk = (clk == 0) ? foundclk : clk; 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,19 +512,19 @@ 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 // Now output the bitstream to the scrollback by line of 16 bits
printDemodBuff(); printDemodBuff();
} }
@ -624,7 +623,7 @@ int CmdBiphaseDecodeRaw(const char *Cmd) {
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,7 +642,7 @@ 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, 16));
@ -716,7 +715,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 +768,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 +1069,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;
} }
@ -1128,7 +1128,7 @@ int PSKDemod(const char *Cmd, bool verbose) {
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");

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);

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

@ -803,7 +803,7 @@ 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;

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

@ -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;

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;
} }
@ -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

@ -2570,7 +2570,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);
@ -2856,7 +2856,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);
@ -3535,7 +3535,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

@ -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);
@ -896,12 +896,15 @@ int CmdLFfind(const char *Cmd) {
} }
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 +913,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 +948,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

@ -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), "%d", (config >> (7 - i)) & 1);
bs++;
}
PrintAndLogEx(INFO, "\n\nHitag2 tag information ");
PrintAndLogEx(INFO, "------------------------------------");
//configuration byte
PrintAndLogEx(SUCCESS, "Config byte : %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

@ -1882,7 +1882,7 @@ 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) return 0;
bit++; bit++;
@ -1897,7 +1897,7 @@ 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) {
@ -1916,7 +1916,7 @@ int CmdT55xxRecoverPW(const char *Cmd) {
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) {

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;

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,77 @@ 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.");
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);
return 1;
}
if (fsize < 128) {
PrintAndLogEx(FAILED, "SHA-512 file too short");
fclose(f);
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");
return 1;
}
uint8_t hash2[64];
if (sha512hash(dump, firmware_size, hash2)) {
PrintAndLogEx(FAILED, "Couldn't calculate SHA-512 of firmware");
return 1;
}
if (memcmp(hash1, hash2, 64)) {
PrintAndLogEx(FAILED, "Couldn't verify integrity of firmware file " _RED_("(wrong SHA-512 hash)"));
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 +740,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 +751,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 +967,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 +1222,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;
} }
@ -189,11 +191,12 @@ uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, ui
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 {
@ -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

@ -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

@ -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

@ -322,42 +322,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;
} }

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

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);

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

@ -5,7 +5,7 @@
// 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.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Snooper binary // Sniff binary
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#include "util_posix.h" #include "util_posix.h"
@ -19,7 +19,7 @@
int main() { int main() {
usb_init(); usb_init();
SetLogFilename("snooper.log"); SetLogFilename("sniffer.log");
return_on_error = 1; return_on_error = 1;
@ -27,7 +27,7 @@ int main() {
while (!OpenProxmark()) { sleep(1); } while (!OpenProxmark()) { sleep(1); }
while (1) { while (1) {
UsbCommand cmdbuf; UsbCommand cmdbuf;
CommandReceived("hf 14a snoop"); CommandReceived("hf 14a sniff");
HANDLE_ERROR; HANDLE_ERROR;
ReceiveCommand(&cmdbuf); ReceiveCommand(&cmdbuf);
HANDLE_ERROR; HANDLE_ERROR;

View file

@ -252,6 +252,9 @@ char *sprint_bin_break(const uint8_t *data, const size_t len, const uint8_t brea
// loop through the out_index to make sure we don't go too far // loop through the out_index to make sure we don't go too far
for (out_index = 0; out_index < rowlen; out_index++) { for (out_index = 0; out_index < rowlen; out_index++) {
// set character // set character
if (data[in_index] == 7) // Manchester wrong bit marker
sprintf(tmp++, ".");
else
sprintf(tmp++, "%u", data[in_index]); sprintf(tmp++, "%u", data[in_index]);
// check if a line break is needed and we have room to print it in our array // check if a line break is needed and we have room to print it in our array
if ((breaks > 0) && !((in_index + 1) % breaks) && (out_index + 1 != rowlen)) { if ((breaks > 0) && !((in_index + 1) % breaks) && (out_index + 1 != rowlen)) {
@ -683,24 +686,45 @@ int hextobinstring(char *target, char *source) {
return length; return length;
} }
// convert binary array of 0x00/0x01 values to hex (safe to do in place as target will always be shorter than source) // convert binary array of 0x00/0x01 values to hex
// return number of bits converted // return number of bits converted
int binarraytohex(char *target, char *source, int length) { int binarraytohex(char *target, const size_t targetlen, char *source, size_t srclen) {
unsigned char i, x; uint8_t i = 0, x = 0;
int j = length; uint32_t t = 0; // written target chars
uint32_t r = 0; // consumed bits
if (j % 4) uint8_t w = 0; // wrong bits separator printed
return 0; for (size_t s = 0 ; s < srclen; s++) {
if ((source[s] == 0) || (source[s] == 1)) {
while (j) { w = 0;
for (i = x = 0 ; i < 4 ; ++i) x += (source[s] << (3 - i));
x += (source[i] << (3 - i)); i++;
sprintf(target, "%X", x); if (i == 4) {
++target; if (t >= targetlen - 2) return r;
source += 4; sprintf(target + t, "%X", x);
j -= 4; t++;
r += 4;
x = 0;
i = 0;
} }
return length; } else {
if (i > 0) {
if (t >= targetlen - 5) return r;
w = 0;
sprintf(target + t, "%X[%i]", x, i);
t += 4;
r += i;
x = 0;
i = 0;
}
if (w == 0) {
if (t >= targetlen - 2) return r;
sprintf(target + t, " ");
t++;
}
r++;
}
}
return r;
} }
// convert binary array to human readable binary // convert binary array to human readable binary

View file

@ -241,7 +241,7 @@ extern int param_getstr(const char *line, int paramnum, char *str, size_t buffer
extern int hextobinarray(char *target, char *source); extern int hextobinarray(char *target, char *source);
extern int hextobinstring(char *target, char *source); extern int hextobinstring(char *target, char *source);
extern int binarraytohex(char *target, char *source, int length); extern int binarraytohex(char *target, const size_t targetlen, char *source, size_t srclen);
extern void binarraytobinstring(char *target, char *source, int length); extern void binarraytobinstring(char *target, char *source, int length);
extern uint8_t GetParity(uint8_t *string, uint8_t type, int length); extern uint8_t GetParity(uint8_t *string, uint8_t type, int length);
extern void wiegand_add_parity(uint8_t *target, uint8_t *source, uint8_t length); extern void wiegand_add_parity(uint8_t *target, uint8_t *source, uint8_t length);

View file

@ -14,9 +14,10 @@
// return: ptr to string // return: ptr to string
char *Iso15693sprintUID(char *target, uint8_t *uid) { char *Iso15693sprintUID(char *target, uint8_t *uid) {
static char tempbuf[2 * 8 + 1] = {0}; static char tempbuf[3 * 8 + 1] = {0};
if (target == NULL) if (target == NULL)
target = tempbuf; target = tempbuf;
sprintf(target, "%02X %02X %02X %02X %02X %02X %02X %02X", sprintf(target, "%02X %02X %02X %02X %02X %02X %02X %02X",
uid[7], uid[6], uid[5], uid[4], uid[7], uid[6], uid[5], uid[4],
uid[3], uid[2], uid[1], uid[0] uid[3], uid[2], uid[1], uid[0]

View file

@ -1357,6 +1357,7 @@ int BiphaseRawDecode(uint8_t *bits, size_t *size, int *offset, int invert) {
//by marshmellow //by marshmellow
//take 10 and 01 and manchester decode //take 10 and 01 and manchester decode
//run through 2 times and take least errCnt //run through 2 times and take least errCnt
// "7" indicates 00 or 11 wrong bit
int manrawdecode(uint8_t *bits, size_t *size, uint8_t invert, uint8_t *alignPos) { int manrawdecode(uint8_t *bits, size_t *size, uint8_t invert, uint8_t *alignPos) {
// sanity check // sanity check
@ -1368,7 +1369,7 @@ int manrawdecode(uint8_t *bits, size_t *size, uint8_t invert, uint8_t *alignPos)
//find correct start position [alignment] //find correct start position [alignment]
for (k = 0; k < 2; ++k) { for (k = 0; k < 2; ++k) {
for (i = k; i < *size - 3; i += 2) { for (i = k; i < *size - 1; i += 2) {
if (bits[i] == bits[i + 1]) if (bits[i] == bits[i + 1])
errCnt++; errCnt++;
} }
@ -1380,7 +1381,7 @@ int manrawdecode(uint8_t *bits, size_t *size, uint8_t invert, uint8_t *alignPos)
} }
*alignPos = bestRun; *alignPos = bestRun;
//decode //decode
for (i = bestRun; i < *size - 3; i += 2) { for (i = bestRun; i < *size - 1; i += 2) {
if (bits[i] == 1 && (bits[i + 1] == 0)) { if (bits[i] == 1 && (bits[i + 1] == 0)) {
bits[bitnum++] = invert; bits[bitnum++] = invert;
} else if ((bits[i] == 0) && bits[i + 1] == 1) { } else if ((bits[i] == 0) && bits[i + 1] == 1) {

View file

@ -22,7 +22,7 @@
#include "util.h" // for ARRAYLEN #include "util.h" // for ARRAYLEN
//might not be high enough for noisy environments //might not be high enough for noisy environments
#define NOISE_AMPLITUDE_THRESHOLD 10 #define NOISE_AMPLITUDE_THRESHOLD 15
//ignore buffer with less than x samples //ignore buffer with less than x samples
#define SIGNAL_MIN_SAMPLES 100 #define SIGNAL_MIN_SAMPLES 100
//ignore first x samples of the buffer //ignore first x samples of the buffer

View file

@ -277,6 +277,7 @@ ISO 7816-4 Basic interindustry commands. For command APDU's.
#define ISO_15693 7 #define ISO_15693 7
#define FELICA 8 #define FELICA 8
#define PROTO_MIFARE 9 #define PROTO_MIFARE 9
#define PROTO_HITAG 10
//-- Picopass fuses //-- Picopass fuses
#define FUSE_FPERS 0x80 #define FUSE_FPERS 0x80

View file

@ -375,7 +375,7 @@ typedef struct _AT91S_DBGU {
#define AT91C_US_TXBUFE (0x1 << 11) // (DBGU) TXBUFE Interrupt #define AT91C_US_TXBUFE (0x1 << 11) // (DBGU) TXBUFE Interrupt
#define AT91C_US_RXBUFF (0x1 << 12) // (DBGU) RXBUFF Interrupt #define AT91C_US_RXBUFF (0x1 << 12) // (DBGU) RXBUFF Interrupt
#define AT91C_US_COMM_TX (0x1 << 30) // (DBGU) COMM_TX Interrupt #define AT91C_US_COMM_TX (0x1 << 30) // (DBGU) COMM_TX Interrupt
#define AT91C_US_COMM_RX (0x1 << 31) // (DBGU) COMM_RX Interrupt #define AT91C_US_COMM_RX (0x1u << 31) // (DBGU) COMM_RX Interrupt
// -------- DBGU_IDR : (DBGU Offset: 0xc) Debug Unit Interrupt Disable Register -------- // -------- DBGU_IDR : (DBGU Offset: 0xc) Debug Unit Interrupt Disable Register --------
// -------- DBGU_IMR : (DBGU Offset: 0x10) Debug Unit Interrupt Mask Register -------- // -------- DBGU_IMR : (DBGU Offset: 0x10) Debug Unit Interrupt Mask Register --------
// -------- DBGU_CSR : (DBGU Offset: 0x14) Debug Unit Channel Status Register -------- // -------- DBGU_CSR : (DBGU Offset: 0x14) Debug Unit Channel Status Register --------

117
include/hitag.h Normal file
View file

@ -0,0 +1,117 @@
//-----------------------------------------------------------------------------
// 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, HitagS
//
// (c) 2012 Roel Verdult
// (c) 2016 Oguzhan Cicek, Hendrik Schwartke, Ralf Spenneberg
// <info@os-s.de>
//-----------------------------------------------------------------------------
#ifndef HITAG_H__
#define HITAG_H__
#ifdef _MSC_VER
#define PACKED
#else
#define PACKED __attribute__((packed))
#endif
typedef enum {
RHTSF_CHALLENGE = 01,
RHTSF_KEY = 02,
WHTSF_CHALLENGE = 03,
WHTSF_KEY = 04,
RHT2F_PASSWORD = 21,
RHT2F_AUTHENTICATE = 22,
RHT2F_CRYPTO = 23,
WHT2F_CRYPTO = 24,
RHT2F_TEST_AUTH_ATTEMPTS = 25,
RHT2F_UID_ONLY = 26,
} hitag_function;
typedef struct {
uint8_t password[4];
} PACKED rht2d_password;
typedef struct {
uint8_t NrAr[8];
uint8_t data[4];
} PACKED rht2d_authenticate;
typedef struct {
uint8_t key[6];
uint8_t data[4];
} PACKED rht2d_crypto;
typedef union {
rht2d_password pwd;
rht2d_authenticate auth;
rht2d_crypto crypto;
} hitag_data;
//---------------------------------------------------------
// Hitag S
//---------------------------------------------------------
// protocol-state
typedef enum PROTO_STATE {
HT_READY = 0,
HT_INIT,
HT_AUTHENTICATE,
HT_SELECTED,
HT_QUIET,
HT_TTF,
HT_FAIL
} PSTATE;
typedef enum TAG_STATE {
HT_NO_OP = 0,
HT_READING_PAGE,
HT_WRITING_PAGE_ACK,
HT_WRITING_PAGE_DATA,
HT_WRITING_BLOCK_DATA
} TSATE;
//number of start-of-frame bits
typedef enum SOF_TYPE {
HT_STANDARD = 0,
HT_ADVANCED,
HT_FAST_ADVANCED,
HT_ONE,
HT_NO_BITS
} stype;
struct hitagS_tag {
PSTATE pstate; //protocol-state
TSATE tstate; //tag-state
uint32_t uid;
uint8_t pages[64][4];
uint64_t key;
uint8_t pwdl0, pwdl1, pwdh0;
//con0
int max_page;
stype mode;
//con1
bool auth; //0=Plain 1=Auth
bool TTFC; //Transponder Talks first coding. 0=Manchester 1=Biphase
int TTFDR; //data rate in TTF Mode
int TTFM; //the number of pages that are sent to the RWD
bool LCON; //0=con1/2 read write 1=con1 read only and con2 OTP
bool LKP; //0=page2/3 read write 1=page2/3 read only in Plain mode and no access in authenticate mode
//con2
//0=read write 1=read only
bool LCK7; //page4/5
bool LCK6; //page6/7
bool LCK5; //page8-11
bool LCK4; //page12-15
bool LCK3; //page16-23
bool LCK2; //page24-31
bool LCK1; //page32-47
bool LCK0; //page48-63
};
#endif

View file

@ -72,7 +72,8 @@ typedef enum ISO14B_COMMAND {
ISO14B_REQUEST_TRIGGER = (1 << 4), ISO14B_REQUEST_TRIGGER = (1 << 4),
ISO14B_APPEND_CRC = (1 << 5), ISO14B_APPEND_CRC = (1 << 5),
ISO14B_SELECT_STD = (1 << 6), ISO14B_SELECT_STD = (1 << 6),
ISO14B_SELECT_SR = (1 << 7) ISO14B_SELECT_SR = (1 << 7),
ISO14B_SET_TIMEOUT = (1 << 8),
} iso14b_command_t; } iso14b_command_t;
typedef enum ISO15_COMMAND { typedef enum ISO15_COMMAND {

View file

@ -129,7 +129,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
@ -154,10 +154,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
@ -170,9 +170,9 @@ 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
@ -192,7 +192,7 @@ typedef struct {
#define CMD_ICLASS_READCHECK 0x038F #define CMD_ICLASS_READCHECK 0x038F
#define CMD_ICLASS_CLONE 0x0390 #define CMD_ICLASS_CLONE 0x0390
#define CMD_ICLASS_DUMP 0x0391 #define CMD_ICLASS_DUMP 0x0391
#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
@ -204,7 +204,7 @@ typedef struct {
// For ISO1092 / FeliCa // For ISO1092 / FeliCa
#define CMD_FELICA_SIMULATE_TAG 0x03A0 #define CMD_FELICA_SIMULATE_TAG 0x03A0
#define CMD_FELICA_SNOOP 0x03A1 #define CMD_FELICA_SNIFF 0x03A1
#define CMD_FELICA_COMMAND 0x03A2 #define CMD_FELICA_COMMAND 0x03A2
//temp //temp
#define CMD_FELICA_LITE_DUMP 0x03AA #define CMD_FELICA_LITE_DUMP 0x03AA

View file

@ -2,7 +2,7 @@
function wait4proxmark_Linux { function wait4proxmark_Linux {
echo >&2 "Waiting for Proxmark to appear..." echo >&2 "Waiting for Proxmark to appear..."
while [ ! -c /dev/ttyACM? -a ! -L /dev/pm3-? ]; do while [ ! -c /dev/ttyACM? -a ! -c /dev/pm3-? ]; do
sleep .1 sleep .1
done done
local PM3=`ls -1 /dev/pm3-? /dev/ttyACM? 2>/dev/null | head -1` local PM3=`ls -1 /dev/pm3-? /dev/ttyACM? 2>/dev/null | head -1`