Sync from Upstream

This commit is contained in:
vratiskol 2019-03-15 21:17:07 +01:00
commit 6a52b6074f
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
.history
.bash_history
*.log
*.eml
*.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...
## [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)
- Add 'make platform' - compile for non-rdv4 devices made simpler (@doegox)
- Change Makefiles optimizations when recompiling (@doegox)

View file

@ -1,38 +1,26 @@
"Coding styles are like assholes, everyone has one and no one likes anyone elses."
--Eric Warmenhoven
"Coding styles are like assholes, everyone has one and no one likes anyone elses."
--Eric Warmenhoven
The Proxmark3 codebase is pretty messy and in the process of being cleaned up,
so we don't have clear guidelines on how to place new code just yet. However,
please don't make things worse.
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
sense and good taste. If breaking a rule leads to cleaner code, you can do so,
but laziness is not an excuse.
clean up the code consistently and keep it consistent in the future.
Look around and respect the same style.
Helper script to get some uniformity in the style:
$ make style
It makes use of "astyle" so be sure to install it first.
=== 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)
&& 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.
If you use "make style", this will be done for you.
=== WIDTH ===
@ -65,24 +53,28 @@ 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
'const' where things are const. Try to use size_t for sizes.
Pointers are:
void *ptr;
Pointers and reference operators are attached to the variable name:
void *ptr;
not:
void* ptr;
void* ptr;
otherwise you're tempted to write:
void* in, out;
void* in, out;
and you'll fail.
"make style" will take care of pointers & reference operators.
=== EXPRESSIONS ===
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
if (5*a<b&&some_bool_var)
if (5*a<b&&some_bool_var)
For equality with constants, use i == 0xF00, not 0xF00 == i. The compiler warns
you about = vs == anyway, and you shouldn't be screwing that one up by now
@ -90,93 +82,73 @@ anyway.
=== IF / FOR / WHILE / etc. ===
Put the opening brace on the same line, with a space before it. Exception: if
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.
Put the opening brace on the same line, with a space before it.
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
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 (int i = 0; i < 10; i++) {
...
}
for (int i = 0; i < 10; i++) {
...
}
Note the spaces after the semicolons.
if/else should be laid out as follows:
if (foo) {
...
} else if (bar) {
...
} else {
...
}
if (foo) {
...
} else if (bar) {
...
} else {
...
}
or
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.
You can skip braces around 1 line statements but don't mix braces vs. no braces.
=== FUNCTIONS ===
Functions with no arguments are declared as f(void), not f(). Put the return
type on the same line. 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). Put a space
after a comma in argument lists.
Put the return type on the same line.
Put a space after a comma in argument lists.
Open the brace after the declaration (after a space).
"make style" will take care of all that.
void foo(int a_thing, int something_else)
{
...
void foo(int a_thing, int something_else) {
...
}
void baz(void)
{
foo(bluh, blah);
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);
}
Function names should be separated_with_underscores(), except for standard
functions (memcpy, etc.). It may make sense to break this rule for very common,
generic functions that look like library functions (e.g. dprintf()).
Don't use single-character arguments. Exception: very short functions with one
argument that's really obvious:
Don't use single-character arguments.
Exception: very short functions with one argument that's really obvious:
static int ascii(char c)
{
if (c < 0x20 || c >= 0x7f)
return '.';
else
return c;
static int ascii(char c) {
if (c < 0x20 || c >= 0x7f)
return '.';
else
return c;
}
vs.
static void hexdump(void *buf, size_t len)
{
...
static void hexdump(void *buf, size_t len) {
...
}
As a general guideline, functions shouldn't usually be much more than 30-50
@ -188,7 +160,7 @@ probably missing some factoring/restructuring opportunity.
Use typedefs when defining structs. The type should be named something_t.
typedef struct {
blah blah;
blah blah;
} prox_cmd_t;
You can use anonymous enums to replace lots of sequential or mostly-sequential
@ -199,16 +171,18 @@ You can use anonymous enums to replace lots of sequential or mostly-sequential
Indent once for the case: labels, then again for the body. Like this:
switch(bar) {
case OPTION_A:
do_stuff();
break;
case OPTION_B:
do_other_stuff();
break;
case OPTION_A:
do_stuff();
break;
case OPTION_B:
do_other_stuff();
break;
}
If you fall through into another case, add an explicit comment; otherwise, it
can look confusing.
"make style" will take care of the indentation.
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.
Split off the cases into functions, break the switch() into parent and children
@ -218,12 +192,12 @@ the like. In other words, use common sense and your brain.
If you need local scope variables for a case, you can add braces:
switch(bar) {
case OPTION_A: {
int baz = 5*bar;
do_stuff(baz);
break;
}
...
case OPTION_A: {
int baz = 5 * bar;
do_stuff(baz);
break;
}
...
But at that point you should probably consider using a separate function.
@ -266,7 +240,7 @@ License/description header first:
//-----------------------------------------------------------------------------
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 ===
@ -284,8 +258,7 @@ you shouldn't use it (same for _FOOBAR_H).
=== WHITESPACE ===
Avoid trailing whitespace (no line should end in tab or space). People forget
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.
Avoid trailing whitespace (no line should end in tab or space).
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 $* = $($*)
style:
# Make sure astyle is installed
@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 \
--indent=spaces=4 --indent-switches --indent-preprocessor \
--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
To make sure you got the latest sim module firmware.
_Lastest version is v3.10_
_Lastest version is v3.11_
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.
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.

View file

@ -195,47 +195,6 @@ bool RAMFUNC LogTrace(const uint8_t *btBytes, uint16_t iLen, uint32_t timestamp_
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
uint8_t emlSet(uint8_t *data, uint32_t offset, uint32_t length) {
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 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 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);
#endif /* __BIGBUF_H */

View file

@ -38,7 +38,7 @@ APP_CFLAGS = $(PLATFORM_DEFS) \
-DWITH_ISO14443a \
-DWITH_ICLASS \
-DWITH_FELICA \
-DWITH_HFSNOOP \
-DWITH_HFSNIFF \
-DWITH_LF_SAMYRUN \
-fno-strict-aliasing -ffunction-sections -fdata-sections
@ -60,7 +60,7 @@ APP_CFLAGS = $(PLATFORM_DEFS) \
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_ISO14443a = iso14443a.c mifareutil.c mifarecmd.c epa.c mifaresim.c
SRC_ISO14443a = iso14443a.c mifareutil.c mifarecmd.c epa.c

View file

@ -433,4 +433,4 @@ void RunMod() {
}
}
}
}
}

View file

@ -20,4 +20,4 @@
#define OPTS 2
#endif /* __HF_MATTYRUN_H */
#endif /* __HF_MATTYRUN_H */

View file

@ -259,4 +259,4 @@ void RunMod() {
LED(selected + 1, 0);
}
}
}
}

View file

@ -19,4 +19,4 @@
#define OPTS 2
#endif /* __HF_YOUNG_H */
#endif /* __HF_YOUNG_H */

View file

@ -21,4 +21,4 @@
void hid_corporate_1000_calculate_checksum_and_set(uint32_t *high, uint32_t *low, uint32_t cardnum, uint32_t fc);
#endif /* __LF_HIDBRUTE_H */
#endif /* __LF_HIDBRUTE_H */

View file

@ -164,4 +164,4 @@ void RunMod() {
out:
DbpString("[=] exiting");
LEDsoff();
}
}

View file

@ -18,4 +18,4 @@
#define OPTS 2
#endif /* __LF_PROXBRUTE_H */
#endif /* __LF_PROXBRUTE_H */

View file

@ -138,4 +138,4 @@ void RunMod() {
out:
DbpString("[=] exiting");
LEDsoff();
}
}

View file

@ -19,4 +19,4 @@
#define OPTS 2
#endif /* __LF_SAMYRUN_H */
#endif /* __LF_SAMYRUN_H */

View file

@ -16,4 +16,4 @@
extern void RunMod();
#endif /* __STANDALONE_H */
#endif /* __STANDALONE_H */

View file

@ -1167,4 +1167,4 @@ int main() {
return 0;
}
#endif
#endif

View file

@ -31,4 +31,4 @@ int AesCtxIni(AesCtx *pCtx, unsigned char *pIV, unsigned char *pKey, unsigned in
int AesEncrypt(AesCtx *pCtx, unsigned char *pData, unsigned char *pCipher, unsigned int DataLen);
int AesDecrypt(AesCtx *pCtx, unsigned char *pCipher, unsigned char *pData, unsigned int CipherLen);
#endif
#endif

View file

@ -650,8 +650,8 @@ void UsbPacketReceived(uint8_t *packet, int len) {
case CMD_MOD_THEN_ACQUIRE_RAW_ADC_SAMPLES_125K:
ModThenAcquireRawAdcSamples125k(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes);
break;
case CMD_LF_SNOOP_RAW_ADC_SAMPLES: {
uint32_t bits = SnoopLF();
case CMD_LF_SNIFF_RAW_ADC_SAMPLES: {
uint32_t bits = SniffLF();
cmd_send(CMD_ACK, bits, 0, 0, 0, 0);
break;
}
@ -664,13 +664,13 @@ void UsbPacketReceived(uint8_t *packet, int len) {
CmdHIDsimTAG(c->arg[0], c->arg[1], 1);
break;
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;
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;
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;
case CMD_HID_CLONE_TAG:
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
#ifdef WITH_HITAG
case CMD_SNOOP_HITAG: // Eavesdrop Hitag tag, args = type
SnoopHitag(c->arg[0]);
case CMD_SNIFF_HITAG: // Eavesdrop Hitag tag, args = type
SniffHitag(c->arg[0]);
break;
case CMD_SIMULATE_HITAG: // Simulate Hitag tag, args = memory content
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
if ((hitag_function)c->arg[0] < 10) {
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]);
}
break;
@ -843,7 +843,7 @@ void UsbPacketReceived(uint8_t *packet, int len) {
case CMD_READ_SRI_TAG:
ReadSTMemoryIso14443b(c->arg[0]);
break;
case CMD_SNOOP_ISO_14443B:
case CMD_SNIFF_ISO_14443B:
SniffIso14443b();
break;
case CMD_SIMULATE_TAG_ISO_14443B:
@ -862,7 +862,7 @@ void UsbPacketReceived(uint8_t *packet, int len) {
case CMD_FELICA_LITE_SIM:
felica_sim_lite(c->arg[0]);
break;
case CMD_FELICA_SNOOP:
case CMD_FELICA_SNIFF:
felica_sniff(c->arg[0], c->arg[1]);
break;
case CMD_FELICA_LITE_DUMP:
@ -871,7 +871,7 @@ void UsbPacketReceived(uint8_t *packet, int len) {
#endif
#ifdef WITH_ISO14443a
case CMD_SNOOP_ISO_14443a:
case CMD_SNIFF_ISO_14443a:
SniffIso14443a(c->arg[0]);
break;
case CMD_READER_ISO_14443a:
@ -1003,7 +1003,7 @@ void UsbPacketReceived(uint8_t *packet, int len) {
#ifdef WITH_ICLASS
// Makes use of ISO14443a FPGA Firmware
case CMD_SNOOP_ICLASS:
case CMD_SNIFF_ICLASS:
SniffIClass();
break;
case CMD_SIMULATE_TAG_ICLASS:
@ -1043,9 +1043,9 @@ void UsbPacketReceived(uint8_t *packet, int len) {
break;
#endif
#ifdef WITH_HFSNOOP
#ifdef WITH_HFSNIFF
case CMD_HF_SNIFFER:
HfSnoop(c->arg[0], c->arg[1]);
HfSniff(c->arg[0], c->arg[1]);
break;
#endif
@ -1322,10 +1322,12 @@ void UsbPacketReceived(uint8_t *packet, int len) {
// first mem page
res = Flash_WriteDataCont(startidx, data, first_len);
isok = (res == first_len) ? 1 : 0;
// second mem page
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 {
res = Flash_WriteDataCont(startidx, data, len);
@ -1389,6 +1391,7 @@ void UsbPacketReceived(uint8_t *packet, int len) {
FlashStop();
cmd_send(CMD_ACK, 1, 0, 0, 0, 0);
BigBuf_free();
LED_B_OFF();
break;
}

View file

@ -85,9 +85,9 @@ void SimulateTagLowFrequency(int period, int gap, int ledcontrol);
void SimulateTagLowFrequencyBidir(int divisor, int max_bitlen);
void CmdHIDsimTAGEx(uint32_t hi, uint32_t lo, int ledcontrol, int numcycles);
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 CmdASKsimTag(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);
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, int ledcontrol);
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 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);
@ -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_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
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);
// util.h
void HfSnoop(int, int);
void HfSniff(int, int);
//felica.c
extern void felica_sendraw(UsbCommand *c);

View file

@ -83,4 +83,4 @@ void Ring_Little_Star(uint16_t count) {
Ring_BEE_TIME(note_1,2*count);
LED_B_ON();
*/
}
}

View file

@ -630,4 +630,4 @@ void mifare_cypher_blocks_chained(desfiretag_t tag, desfirekey_t key, uint8_t *i
mifare_cypher_single_block(key, data + offset, ivect, direction, operation, block_size);
offset += block_size;
}
}
}

View file

@ -152,4 +152,4 @@ void Desfire_session_key_new(const uint8_t rnda[], const uint8_t rndb[], desfire
Desfire_aes_key_new(buffer, key);
break;
}
}
}

View file

@ -17,4 +17,4 @@ void Desfire_aes_key_new_with_version(const uint8_t value[16], uint8_t version,
uint8_t Desfire_key_get_version(desfirekey_t key);
void Desfire_key_set_version(desfirekey_t key, uint8_t version);
void Desfire_session_key_new(const uint8_t rnda[], const uint8_t rndb[], desfirekey_t authkey, desfirekey_t key);
#endif
#endif

View file

@ -305,6 +305,11 @@ void EPA_PACE_Collect_Nonce(UsbCommand *c) {
// initiate the PACE protocol
// use the CAN for the password since that doesn't change
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
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);
// check if the command succeeded
if (func_return < 0) {
EPA_PACE_Collect_Nonce_Abort(4, func_return);
EPA_PACE_Collect_Nonce_Abort(5, func_return);
return;
}

View file

@ -544,7 +544,7 @@ void felica_sniff(uint32_t samplesToSkip, uint32_t triggersToSkip) {
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);

View file

@ -151,4 +151,4 @@ void Flashmem_print_status(void);
#endif
#endif

View file

@ -4,9 +4,9 @@
#include "util.h"
#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
uint16_t *dest = (uint16_t *)BigBuf_get_addr();
@ -23,7 +23,7 @@ static void RAMFUNC optimizedSnoop(void) {
set_tracelen(BigBuf_max_traceLen());
}
void HfSnoop(int samplesToSkip, int triggersToSkip) {
void HfSniff(int samplesToSkip, int triggersToSkip) {
BigBuf_free();
BigBuf_Clear();
@ -66,14 +66,14 @@ void HfSnoop(int samplesToSkip, int triggersToSkip) {
if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY))
waitcount--;
}
optimizedSnoop();
optimizedSniff();
Dbprintf("Trigger kicked! Value: %d, Dumping Samples Hispeed now.", r);
}
//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);
DbpString("HF Snoop end");
DbpString("HF Sniffing end");
FpgaWriteConfWord(FPGA_MAJOR_MODE_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
// the license.
//-----------------------------------------------------------------------------
// Hitag2 emulation (preliminary test version)
// Hitag2 emulation
//
// (c) 2009 Henryk Plötz <henryk@ploetzli.ch>
//-----------------------------------------------------------------------------
// Hitag2 complete rewrite of the code
// - Fixed modulation/encoding issues
// - Rewrote code for transponder emulation
// - Added snooping of transponder communication
// - Added sniffing of transponder communication
// - Added reader functionality
//
// (c) 2012 Roel Verdult
//-----------------------------------------------------------------------------
// Piwi, 2019
// Iceman, 2019
#include "hitag2.h"
#include "hitag2_crypto.h"
#include "hitag.h"
#include "proxmark3.h"
#include "apps.h"
#include "util.h"
#include "hitag2.h"
#include "string.h"
#include "BigBuf.h"
static bool bQuiet;
static bool bCrypto;
static bool bAuthenticating;
static bool bPwd;
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 = {
.state = TAG_STATE_RESET,
.sectors = { // Password mode: | Crypto mode:
@ -81,87 +70,6 @@ static uint8_t key[8];
static uint8_t writedata[4];
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) {
tag.state = TAG_STATE_RESET;
tag.crypto_active = 0;
@ -173,48 +81,13 @@ static int hitag2_init(void) {
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)
// 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)
// T0 = TIMER_CLOCK1 / 125000 = 192
#ifndef T0
#define T0 192
#define SHORT_COIL() LOW(GPIO_SSC_DOUT)
#define OPEN_COIL() HIGH(GPIO_SSC_DOUT)
#endif
#define HITAG_FRAME_LEN 20
#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_FOUR_HALF 57
static void hitag_send_bit(int bit) {
LED_A_ON();
// 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);
}
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];
@ -398,8 +269,8 @@ static void hitag2_handle_reader_command(uint8_t *rx, const size_t rxlen, uint8_
break;
}
// LogTraceHitag(rx,rxlen,0,0,false);
// LogTraceHitag(tx,*txlen,0,0,true);
// LogTrace(rx, nbytes(rxlen), 0, 0, NULL, false);
// LogTrace(tx, nbytes(txlen), 0, 0, NULL, true);
if (tag.crypto_active) {
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
while (AT91C_BASE_TC0->TC_CV < T0 * 6);
// SpinDelayUs(8*8);
// Disable modulation, just activates the field again
LOW(GPIO_SSC_DOUT);
@ -435,7 +305,6 @@ static void hitag_reader_send_bit(int bit) {
LED_A_OFF();
}
static void hitag_reader_send_frame(const uint8_t *frame, size_t frame_len) {
// Send the content of the frame
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) {
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;
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);
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);
memset(tx, 0x00, 4);
memset(tx + 4, 0xff, 4);
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;
}
void SnoopHitag(uint32_t type) {
void SniffHitag(uint32_t type) {
StopTicks();
int frame_count;
int response;
int overflow;
@ -814,12 +686,8 @@ void SnoopHitag(uint32_t type) {
size_t rxlen = 0;
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
// free eventually allocated BigBuf memory
BigBuf_free();
BigBuf_Clear_ext(false);
// Clean up trace and prepare it for storing frames
clear_trace();
set_tracing(true);
@ -829,19 +697,18 @@ void SnoopHitag(uint32_t type) {
auth_table = (uint8_t *)BigBuf_malloc(AUTH_TABLE_LENGTH);
memset(auth_table, 0x00, AUTH_TABLE_LENGTH);
DbpString("Starting Hitag2 snoop");
DbpString("Starting Hitag2 sniffing");
LED_D_ON();
// Set up eavesdropping mode, frequency divisor which will drive the FPGA
// and analog mux selection.
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);
RELAY_OFF();
// Configure output 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;
AT91C_BASE_PIOA->PIO_OER |= GPIO_SSC_DOUT;
AT91C_BASE_PIOA->PIO_PER |= GPIO_SSC_DOUT;
// Disable modulation, we are going to eavesdrop, not modulate ;)
LOW(GPIO_SSC_DOUT);
@ -853,14 +720,16 @@ void SnoopHitag(uint32_t type) {
// Disable timer during configuration
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.
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 = t1_channel_mode;
AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK | AT91C_TC_ETRGEDG_BOTH | AT91C_TC_ABETRG | AT91C_TC_LDRA_BOTH;
// Enable and reset counter
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
memset(rx, 0x00, sizeof(rx));
frame_count = 0;
@ -971,10 +840,7 @@ void SnoopHitag(uint32_t type) {
// Check if frame was captured
if (rxlen > 0) {
frame_count++;
if (!LogTraceHitag(rx, rxlen, response, 0, reader_frame)) {
DbpString("Trace full");
break;
}
LogTrace(rx, nbytes(rxlen), response, 0, NULL, reader_frame);
// Check if we recognize a valid authentication attempt
if (nbytes(rxlen) == 8) {
@ -1005,49 +871,46 @@ void SnoopHitag(uint32_t type) {
// Reset the timer to restart while-loop that receives frames
AT91C_BASE_TC1->TC_CCR = AT91C_TC_SWTRG;
}
LED_A_ON();
LED_B_OFF();
LED_C_OFF();
LED_D_OFF();
LEDsoff();
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
set_tracing(false);
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS;
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LED_A_OFF();
set_tracing(false);
// Dbprintf("frame received: %d",frame_count);
// Dbprintf("Authentication Attempts: %d",(auth_table_len/8));
// DbpString("All done");
// release allocated memory from BigBuff.
BigBuf_free();
StartTicks();
DbpString("Hitag2 sniffing end, use `lf hitag list` for annotations");
}
void SimulateHitagTag(bool tag_mem_supplied, uint8_t *data) {
int frame_count;
int response;
int overflow;
StopTicks();
int frame_count = 0, response = 0, overflow = 0;
uint8_t rx[HITAG_FRAME_LEN];
size_t rxlen = 0;
uint8_t tx[HITAG_FRAME_LEN];
size_t txlen = 0;
bool bQuitTraceFull = false;
bQuiet = false;
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
// free eventually allocated BigBuf memory
BigBuf_free();
BigBuf_Clear_ext(false);
// Clean up trace and prepare it for storing frames
clear_trace();
set_tracing(true);
auth_table_len = 0;
auth_table_pos = 0;
uint8_t *auth_table;
auth_table = (uint8_t *)BigBuf_malloc(AUTH_TABLE_LENGTH);
uint8_t *auth_table = BigBuf_malloc(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");
LED_D_ON();
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
// and analog mux selection.
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT);
SpinDelay(50);
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
RELAY_OFF();
// Configure output 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;
AT91C_BASE_PIOA->PIO_OER |= GPIO_SSC_DOUT;
AT91C_BASE_PIOA->PIO_PER |= GPIO_SSC_DOUT;
// Disable modulation at default, which means release resistance
LOW(GPIO_SSC_DOUT);
// 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_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;
// Disable timer during configuration
AT91C_BASE_TC0->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.
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
AT91C_BASE_TC0->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()) {
// Watchdog hit
WDT_HIT();
@ -1144,16 +1007,7 @@ void SimulateHitagTag(bool tag_mem_supplied, uint8_t *data) {
// Check if frame was captured
if (rxlen > 4) {
frame_count++;
if (!bQuiet) {
if (!LogTraceHitag(rx, rxlen, response, 0, true)) {
DbpString("Trace full");
if (bQuitTraceFull) {
break;
} else {
bQuiet = true;
}
}
}
LogTrace(rx, nbytes(rxlen), response, response, NULL, true);
// Disable timer 1 with external trigger to avoid triggers during our own modulation
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)
if (txlen) {
// Transmit the tag frame
hitag_send_frame(tx, txlen);
// Store the frame in the trace
if (!bQuiet) {
if (!LogTraceHitag(tx, txlen, 0, 0, false)) {
DbpString("Trace full");
if (bQuitTraceFull) {
break;
} else {
bQuiet = true;
}
}
}
LogTrace(tx, nbytes(txlen), 0, 0, NULL, false);
}
// 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
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_TC0->TC_CCR = AT91C_TC_CLKDIS;
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
// release allocated memory from BigBuff.
BigBuf_free();
StartTicks();
DbpString("Sim Stopped");
set_tracing(false);
}
void ReaderHitag(hitag_function htf, hitag_data *htd) {
StopTicks();
int frame_count = 0;
int response = 0;
uint8_t rx[HITAG_FRAME_LEN];
@ -1233,7 +1084,6 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) {
Dbprintf("List identifier in password mode");
memcpy(password, htd->pwd.password, 4);
blocknr = 0;
bQuiet = false;
bPwd = false;
break;
}
@ -1241,7 +1091,6 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) {
DbpString("Authenticating using nr,ar pair:");
memcpy(NrAr, htd->auth.NrAr, 8);
Dbhexdump(8, NrAr, false);
bQuiet = false;
bCrypto = false;
bAuthenticating = false;
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.
Dbhexdump(6, key, false);
blocknr = 0;
bQuiet = false;
bCrypto = false;
bAuthenticating = false;
break;
@ -1260,13 +1108,11 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) {
Dbprintf("Testing %d authentication attempts", (auth_table_len / 8));
auth_table_pos = 0;
memcpy(NrAr, auth_table, 8);
bQuiet = false;
bCrypto = false;
break;
}
case RHT2F_UID_ONLY: {
blocknr = 0;
bQuiet = false;
bCrypto = false;
bAuthenticating = false;
break;
@ -1274,45 +1120,48 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) {
default: {
Dbprintf("Error, unknown function: %d", htf);
set_tracing(false);
StartTicks();
return;
}
}
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
BigBuf_free();
BigBuf_free();
clear_trace();
set_tracing(true);
LED_D_ON();
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
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_READER_FIELD);
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
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
LOW(GPIO_SSC_DOUT);
// Give it a bit of time for the resonant antenna to settle.
SpinDelay(30);
// Enable Peripheral Clock for
// 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);
// PIO_A - BSR
AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME;
// Disable timer during configuration
AT91C_BASE_TC0->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.
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_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.)
if (htf < 10) {
// hitagS settings
reset_sof = 1;
t_wait = 200;
// DbpString("Configured for hitagS reader");
} else if (htf < 20) {
// hitag1 settings
reset_sof = 1;
t_wait = 200;
// DbpString("Configured for hitag1 reader");
} else if (htf < 30) {
// hitag2 settings
reset_sof = 4;
t_wait = HITAG_T_WAIT_2;
// DbpString("Configured for hitag2 reader");
} else {
Dbprintf("Error, unknown hitag reader type: %d", htf);
goto out;
goto out;
}
uint8_t attempt_count = 0;
while (!bStop && !BUTTON_PRESS() && !usb_poll_validate_length() ) {
while (!bStop && !BUTTON_PRESS() && !usb_poll_validate_length()) {
WDT_HIT();
// Check if frame was captured and store it
if (rxlen > 0) {
frame_count++;
LogTraceHitag(rx, rxlen, response, 0, false);
LogTrace(rx, nbytes(rxlen), response, response, NULL, false);
}
// By default reset the transmission buffer
@ -1376,7 +1225,7 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) {
attempt_count++; //attempt 3 times to get uid then quit
if (!bStop && attempt_count == 3)
bStop = true;
break;
}
default: {
@ -1405,7 +1254,7 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) {
// Add transmitted frame to total count
if (txlen > 0) {
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
@ -1474,14 +1323,19 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) {
}
}
}
out:
out:
LEDsoff();
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS;
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
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)
cmd_send(CMD_ACK, bSuccessful, 0, 0, (uint8_t *)tag.sectors, 48);
else
@ -1489,8 +1343,10 @@ out:
}
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];
size_t rxlen = 0;
uint8_t txbuf[HITAG_FRAME_LEN];
@ -1502,17 +1358,13 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) {
int tag_sof;
int t_wait = HITAG_T_WAIT_MAX;
bool bStop;
bool bQuitTraceFull = false;
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
// Reset the return status
bSuccessful = false;
// Clean up trace and prepare it for storing frames
set_tracing(true);
clear_trace();
// DbpString("Starting Hitag reader family");
// Reset the return status
bSuccessful = false;
// Check configuration
switch (htf) {
@ -1522,15 +1374,14 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) {
memcpy(writedata, htd->crypto.data, 4);
Dbhexdump(6, key, false);
blocknr = page;
bQuiet = false;
bCrypto = false;
bAuthenticating = false;
bQuitTraceFull = true;
writestate = WRITE_STATE_START;
}
break;
default: {
Dbprintf("Error, unknown function: %d", htf);
StartTicks();
return;
}
break;
@ -1540,44 +1391,45 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) {
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;
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
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
SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
RELAY_OFF();
// Disable modulation at default, which means enable the field
LOW(GPIO_SSC_DOUT);
// Give it a bit of time for the resonant antenna to settle.
SpinDelay(30);
// Enable Peripheral Clock for
// 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;
// Disable timer during configuration
AT91C_BASE_TC0->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.
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
AT91C_BASE_TC0->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
frame_count = 0;
response = 0;
lastbit = 1;
bStop = false;
@ -1586,38 +1438,27 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) {
// hitagS settings
reset_sof = 1;
t_wait = 200;
// DbpString("Configured for hitagS reader");
} else if (htf < 20) {
// hitag1 settings
reset_sof = 1;
t_wait = 200;
// DbpString("Configured for hitag1 reader");
} else if (htf < 30) {
// hitag2 settings
reset_sof = 4;
t_wait = HITAG_T_WAIT_2;
// DbpString("Configured for hitag2 reader");
} else {
Dbprintf("Error, unknown hitag reader type: %d", htf);
return;
}
while (!bStop && !BUTTON_PRESS()) {
// Watchdog hit
while (!bStop && !BUTTON_PRESS() && !usb_poll_validate_length()) {
WDT_HIT();
// Check if frame was captured and store it
if (rxlen > 0) {
frame_count++;
if (!bQuiet) {
if (!LogTraceHitag(rx, rxlen, response, 0, false)) {
DbpString("Trace full");
if (bQuitTraceFull) {
break;
} else {
bQuiet = true;
}
}
}
LogTrace(rx, nbytes(rxlen), response, response, NULL, false);
}
// 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,
// we need to wait (T_Wait2 + half_tag_period) when the last was a 'one'.
// All timer values are in terms of T0 units
while (AT91C_BASE_TC0->TC_CV < T0 * (t_wait + (HITAG_T_TAG_HALF_PERIOD * lastbit)));
// Dbprintf("DEBUG: Sending reader frame");
while (AT91C_BASE_TC0->TC_CV < T0 * (t_wait + (HITAG_T_TAG_HALF_PERIOD * lastbit))) {};
// Transmit the reader frame
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
if (txlen > 0) {
frame_count++;
if (!bQuiet) {
// Store the frame in the trace
if (!LogTraceHitag(tx, txlen, HITAG_T_WAIT_2, 0, true)) {
if (bQuitTraceFull) {
break;
} else {
bQuiet = true;
}
}
}
LogTrace(tx, nbytes(txlen), HITAG_T_WAIT_2, HITAG_T_WAIT_2, NULL, true);
}
// Reset values for receiving frames
@ -1675,7 +1505,6 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) {
bSkip = true;
tag_sof = reset_sof;
response = 0;
// Dbprintf("DEBUG: Waiting to receive frame");
uint32_t errorCount = 0;
// 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 (errorCount > 100) break;
// 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 (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));
}
}
// Dbprintf("DEBUG: Done waiting for frame");
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_TC0->TC_CCR = AT91C_TC_CLKDIS;
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
// Dbprintf("frame received: %d",frame_count);
// DbpString("All done");
StartTicks();
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:
// ====
// 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:
//
// + 22279: : 0c 03 e8 01
@ -2456,4 +2456,4 @@ void iClass_Clone(uint8_t startblock, uint8_t endblock, uint8_t *data) {
cmd_send(CMD_ACK, 1, 0, 0, 0, 0);
switch_off();
}
}

View file

@ -2747,7 +2747,7 @@ void DetectNACKbug() {
bool received_nack;
// 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_Clear_ext(false);

View file

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

View file

@ -621,8 +621,8 @@ void Iso15693InitReader(void) {
// Encode (into the ToSend buffers) an identify request, which is the first
// 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) {
uint8_t cmd[CMD_ID_RESP] = {0, ISO15_CMD_INVENTORY, 0, 0, 0};
// flags
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
// It expects "out" to be at least CMD_INV_RESP large
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};
@ -686,7 +687,7 @@ static void BuildInventoryResponse(uint8_t *out, uint8_t *uid) {
// CRC
AddCrc(cmd, 10);
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
@ -739,50 +740,50 @@ void DbdecodeIso15693Answer(int len, uint8_t *d) {
if (len > 3) {
if (d[0] & (1 << 3))
strncat(status, "ProtExt ", DBD15STATLEN);
strncat(status, "ProtExt ", DBD15STATLEN - strlen(status));
if (d[0] & 1) {
// error
strncat(status, "Error ", DBD15STATLEN);
strncat(status, "Error ", DBD15STATLEN - strlen(status));
switch (d[1]) {
case 0x01:
strncat(status, "01: not supported", DBD15STATLEN);
strncat(status, "01: not supported", DBD15STATLEN - strlen(status));
break;
case 0x02:
strncat(status, "02: not recognized", DBD15STATLEN);
strncat(status, "02: not recognized", DBD15STATLEN - strlen(status));
break;
case 0x03:
strncat(status, "03: opt not supported", DBD15STATLEN);
strncat(status, "03: opt not supported", DBD15STATLEN - strlen(status));
break;
case 0x0f:
strncat(status, "0F: no info", DBD15STATLEN);
strncat(status, "0F: no info", DBD15STATLEN - strlen(status));
break;
case 0x10:
strncat(status, "10: dont exist", DBD15STATLEN);
strncat(status, "10: dont exist", DBD15STATLEN - strlen(status));
break;
case 0x11:
strncat(status, "11: lock again", DBD15STATLEN);
strncat(status, "11: lock again", DBD15STATLEN - strlen(status));
break;
case 0x12:
strncat(status, "12: locked", DBD15STATLEN);
strncat(status, "12: locked", DBD15STATLEN - strlen(status));
break;
case 0x13:
strncat(status, "13: program error", DBD15STATLEN);
strncat(status, "13: program error", DBD15STATLEN - strlen(status));
break;
case 0x14:
strncat(status, "14: lock error", DBD15STATLEN);
strncat(status, "14: lock error", DBD15STATLEN - strlen(status));
break;
default:
strncat(status, "unknown error", DBD15STATLEN);
strncat(status, "unknown error", DBD15STATLEN - strlen(status));
}
strncat(status, " ", DBD15STATLEN);
strncat(status, " ", DBD15STATLEN - strlen(status));
} else {
strncat(status, "No error ", DBD15STATLEN);
strncat(status, "No error ", DBD15STATLEN - strlen(status));
}
if (CheckCrc(d, len))
strncat(status, "[+] crc OK", DBD15STATLEN);
strncat(status, "[+] crc OK", DBD15STATLEN - strlen(status));
else
strncat(status, "[!] crc fail", DBD15STATLEN);
strncat(status, "[!] crc fail", DBD15STATLEN - strlen(status));
if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("%s", status);
}
@ -999,4 +1000,4 @@ void DirectTag15693Command(uint32_t datalen, uint32_t speed, uint32_t recv, uint
} else {
cmd_send(CMD_ACK, 1, 0, 0, 0, 0);
}
}
}

View file

@ -21,13 +21,6 @@
#include "common.h"
#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 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)
@ -317,7 +310,7 @@ void ReadTItag(void) {
// expected for either the low or high frequency
if ((samples > (sampleslo - threshold)) && (samples < (sampleslo + threshold))) {
// low frequency represents a 1
shift3 |= (1 << 31);
shift3 |= (1u << 31);
} else if ((samples > (sampleshi - threshold)) && (samples < (sampleshi + threshold))) {
// high frequency represents a 0
} else {
@ -481,7 +474,7 @@ void AcquireTiType(void) {
// unpack buffer
for (i = TIBUFLEN - 1; i >= 0; i--) {
for (j = 0; j < 32; j++) {
if (buf[i] & (1 << j)) {
if (buf[i] & (1u << j)) {
dest[--n] = 1;
} else {
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 wavesPerClock = clock / fc;
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
for (uint8_t idx = 0; idx < wavesPerClock; idx++) {
@ -740,19 +731,23 @@ static void fcAll(uint8_t fc, int *n, uint8_t clock, uint16_t *modCnt) {
memset(dest + (*n) + (fc - halfFC), 1, halfFC);
*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 ((*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) + (fc - halfFC), 1, halfFC);
*n += fc;
if (modAdjOk) { //fsk2
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) + (fc - halfFC), 1, halfFC);
*n += fc;
}
}
if (!modAdjOk) { //fsk1
memset(dest + (*n), 0, mod - (mod >> 1));
memset(dest + (*n) + (mod - (mod >> 1)), 1, mod >> 1);
*n += mod;
}
}
if (mod > 0 && !modAdjOk) { //fsk1
memset(dest + (*n), 0, mod - (mod >> 1));
memset(dest + (*n) + (mod - (mod >> 1)), 1, mod >> 1);
*n += mod;
}
}
@ -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
// simulate a FSK tag until the button is pressed
// 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);
// 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();
set_tracing(false);
int ledcontrol = 1, n = 0, i = 0;
int n = 0, i = 0;
uint8_t fcHigh = arg1 >> 8;
uint8_t fcLow = arg1 & 0xFF;
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
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);
set_tracing(false);
int ledcontrol = 1, n = 0, i = 0;
int n = 0, i = 0;
uint8_t clk = (arg1 >> 8) & 0xFF;
uint8_t encoding = arg1 & 0xFF;
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,
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);
set_tracing(false);
int ledcontrol = 1, n = 0, i = 0;
int n = 0, i = 0;
uint8_t clk = arg1 >> 8;
uint8_t carrier = arg1 & 0xFF;
uint8_t invert = arg2 & 0xFF;
@ -1066,12 +1061,8 @@ 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
bitlen = 37;
fc = 0;
cardnum = 0;
if (bitlen == 37) {
cardnum = (lo >> 1) & 0x7FFFF;
fc = ((hi & 0xF) << 12) | (lo >> 20);
}
cardnum = (lo >> 1) & 0x7FFFF;
fc = ((hi & 0xF) << 12) | (lo >> 20);
}
Dbprintf("TAG ID: %x%08x (%d) - Format Len: %dbit - FC: %d - Card: %d",
hi,
@ -1382,8 +1373,6 @@ void T55xxResetRead(void) {
//clear buffer now so it does not interfere with timing later
BigBuf_Clear_keep_EM();
StartTicks();
// Set up FPGA, 125kHz
LFSetupFPGAForADC(95, true);
// 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;
uint32_t i = 0;
StartTicks();
// Set up FPGA, 125kHz
LFSetupFPGAForADC(95, true);
@ -1491,7 +1478,7 @@ void T55xxWriteBlock(uint32_t Data, uint8_t Block, uint32_t Pwd, uint8_t arg) {
// Read one card block in page [page]
void T55xxReadBlock(uint16_t arg0, uint8_t Block, uint32_t Pwd) {
LED_A_ON();
bool PwdMode = arg0 & 0x1;
bool PwdMode = arg0 & 0x1;
uint8_t Page = (arg0 & 0x2) >> 1;
bool brute_mem = arg0 & 0x4;
@ -1513,8 +1500,6 @@ void T55xxReadBlock(uint16_t arg0, uint8_t Block, uint32_t Pwd) {
//make sure block is at max 7
Block &= 0x7;
StartTicks();
// Set up FPGA, 125kHz to power up the tag
LFSetupFPGAForADC(95, true);
// make sure tag is fully powered up...
@ -1591,26 +1576,23 @@ void T55xx_ChkPwds() {
uint32_t candidate = 0;
#ifdef WITH_FLASH
bool use_flashmem = true;
if (use_flashmem) {
BigBuf_Clear_EM();
uint16_t isok = 0;
uint8_t counter[2] = {0x00, 0x00};
isok = Flash_ReadData(DEFAULT_T55XX_KEYS_OFFSET, counter, sizeof(counter));
if (isok != sizeof(counter))
goto OUT;
BigBuf_Clear_EM();
uint16_t isok = 0;
uint8_t counter[2] = {0x00, 0x00};
isok = Flash_ReadData(DEFAULT_T55XX_KEYS_OFFSET, counter, sizeof(counter));
if (isok != sizeof(counter))
goto OUT;
pwdCount = counter[1] << 8 | counter[0];
pwdCount = counter[1] << 8 | counter[0];
if (pwdCount == 0 && pwdCount == 0xFFFF)
goto OUT;
if (pwdCount == 0 || pwdCount == 0xFFFF)
goto OUT;
isok = Flash_ReadData(DEFAULT_T55XX_KEYS_OFFSET + 2, pwds, pwdCount * 4);
if (isok != pwdCount * 4)
goto OUT;
isok = Flash_ReadData(DEFAULT_T55XX_KEYS_OFFSET + 2, pwds, pwdCount * 4);
if (isok != pwdCount * 4)
goto OUT;
Dbprintf("[=] Password dictionary count %d ", pwdCount);
}
Dbprintf("[=] Password dictionary count %d ", pwdCount);
#endif
uint32_t pwd = 0, curr = 0, prev = 0;
@ -1661,8 +1643,6 @@ void T55xxWakeUp(uint32_t Pwd) {
LED_B_ON();
uint32_t i = 0;
StartTicks();
// Set up FPGA, 125kHz
LFSetupFPGAForADC(95, true);
// 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
* 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,
* such as functions to read the UID from a prox tag or similar.
@ -239,9 +239,9 @@ uint32_t ReadLF(bool activeField, bool silent, int sample_size) {
if (!silent)
printConfig();
LFSetupFPGAForADC(config.divisor, activeField);
uint32_t ret = DoAcquisition_config(silent, sample_size);
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
return ret;
uint32_t ret = DoAcquisition_config(silent, sample_size);
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
return ret;
}
/**
@ -250,15 +250,15 @@ uint32_t ReadLF(bool activeField, bool silent, int sample_size) {
**/
uint32_t SampleLF(bool printCfg, int sample_size) {
BigBuf_Clear_ext(false);
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
**/
uint32_t SnoopLF() {
uint32_t SniffLF() {
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) {
prev = curr;
curr = 1;
}
else if ( sample < COTAG_ZERO_THRESHOLD) {
} else if (sample < COTAG_ZERO_THRESHOLD) {
prev = curr;
curr = 0;
}
else {
} else {
curr = prev;
}

View file

@ -30,10 +30,10 @@ void doT55x7Acquisition(size_t 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
**/
uint32_t SnoopLF();
uint32_t SniffLF();
// adds sample size to default options
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
* 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,
* 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];
if (keyCount == 0 && keyCount == 0xFFFF)
if (keyCount == 0 || keyCount == 0xFFFF)
goto OUT;
datain = BigBuf_malloc(keyCount * 6);
@ -2098,4 +2098,4 @@ void Mifare_DES_Auth2(uint32_t arg0, uint8_t *datain) {
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LEDsoff();
set_tracing(false);
}
}

View file

@ -25,4 +25,4 @@
#include "crc.h"
#include "protocols.h"
#include "parity.h"
#endif
#endif

View file

@ -322,4 +322,4 @@ void RAMFUNC MfSniffSend() {
LED_B_ON();
cmd_send(CMD_ACK, 2, 0, 0, 0, 0); // 2 == data transfer finished.
LED_B_OFF();
}
}

View file

@ -39,4 +39,4 @@ bool RAMFUNC MfSniffLogic(const uint8_t *data, uint16_t len, uint8_t *parity, ui
void RAMFUNC MfSniffSend(void);
void MfSniffEnd(void);
#endif
#endif

View file

@ -518,4 +518,4 @@ bool AddPatternPCF7931(uint32_t a, uint32_t b, uint32_t c, uint32_t *tab) {
tab[u + 2] = c + tab[u + 1];
return 0;
}
}

View file

@ -17,4 +17,4 @@ bool AddBitPCF7931(bool b, uint32_t *tab, int32_t l, int32_t p);
bool AddPatternPCF7931(uint32_t a, uint32_t b, uint32_t c, uint32_t *tab);
void WritePCF7931(uint8_t pass1, uint8_t pass2, uint8_t pass3, uint8_t pass4, uint8_t pass5, uint8_t pass6, uint8_t pass7, uint16_t init_delay, int32_t l, int32_t p, uint8_t address, uint8_t byte, uint8_t data);
#endif
#endif

View file

@ -77,4 +77,4 @@ void __attribute__((section(".startos"))) Vector(void) {
AppMain();
}
#endif
#endif

View file

@ -24,4 +24,4 @@ char *strcat(char *dest, const char *src);
void strreverse(char s[]);
void itoa(int n, char s[]);
#endif /* __STRING_H */
#endif /* __STRING_H */

View file

@ -44,4 +44,4 @@ extern void WaitUS(uint16_t us);
extern void WaitMS(uint16_t ms);
extern void StopTicks(void);
#endif
#endif

View file

@ -17,7 +17,18 @@
#include "BigBuf.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 )
#endif
#define LED_RED 1
#define LED_ORANGE 2
@ -43,6 +54,34 @@
# define NTIME(n) for (int _index = 0; _index < n; _index++)
#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);
extern uint32_t reflect(uint32_t v, int b); // used in crc.c ...

View file

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

View file

@ -21,7 +21,7 @@ int main(int argc, char **argv) {
if (argc != 3 && argc != 4) {
printf("\n\tusage: cli <command 1> <command 2> [logfile (default cli.log)]\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");
return -1;
}

View file

@ -483,4 +483,4 @@ int CmdrevengSearch(const char *Cmd) {
if (!found) PrintAndLogEx(FAILED, "\nno matches found\n");
return 1;
}
}

View file

@ -417,18 +417,16 @@ int CmdPrintDemodBuff(const char *Cmd) {
return 0;
}
length = (length > (DemodBufferLen - offset)) ? DemodBufferLen - offset : length;
int numBits = (length) & 0x00FFC; //make sure we don't exceed our string
if (hexMode) {
char *buf = (char *)(DemodBuffer + offset);
numBits = (numBits > sizeof(hex)) ? sizeof(hex) : numBits;
numBits = binarraytohex(hex, buf, numBits);
int numBits = binarraytohex(hex, sizeof(hex), buf, length);
if (numBits == 0) {
return 0;
}
PrintAndLogEx(NORMAL, "DemodBuffer: %s", hex);
} 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;
}
@ -475,14 +473,15 @@ int ASKDemod_ext(const char *Cmd, bool verbose, bool emSearch, uint8_t askType,
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 (maxLen < BitLen && maxLen != 0) BitLen = maxLen;
int foundclk = 0;
//amp before ST check
//amplify signal before ST check
if (amp == 'a')
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;
CursorCPos = ststart;
CursorDPos = stend;
if (verbose || g_debugMode)
PrintAndLogEx(NORMAL, "Found Sequence Terminator - First one is shown by orange and blue graph markers");
if (verbose)
PrintAndLogEx(DEBUG, "Found Sequence Terminator - First one is shown by orange / blue graph markers");
}
int startIdx = 0;
@ -513,19 +512,19 @@ int ASKDemod_ext(const char *Cmd, bool verbose, bool emSearch, uint8_t askType,
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
setDemodBuf(bits, BitLen, 0);
setClockGrid(clk, startIdx);
if (verbose || g_debugMode) {
if (verbose) {
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)
PrintAndLogEx(NORMAL, "ASK/Manchester - Clock: %d - Decoded bitstream:", clk);
PrintAndLogEx(DEBUG, "ASK/Manchester - Clock: %d - Decoded bitstream:", clk);
else
PrintAndLogEx(NORMAL, "ASK/Raw - Clock: %d - Decoded bitstream:", clk);
PrintAndLogEx(DEBUG, "ASK/Raw - Clock: %d - Decoded bitstream:", clk);
// Now output the bitstream to the scrollback by line of 16 bits
printDemodBuff();
}
@ -624,7 +623,7 @@ int CmdBiphaseDecodeRaw(const char *Cmd) {
sscanf(Cmd, "%i %i %i", &offset, &invert, &maxErr);
if (DemodBufferLen == 0) {
PrintAndLogEx(NORMAL, "DemodBuffer Empty - run 'data rawdemod ar' first");
PrintAndLogEx(WARNING, "DemodBuffer Empty - run " _YELLOW_("'data rawdemod ar'")" first");
return 0;
}
@ -643,7 +642,7 @@ int CmdBiphaseDecodeRaw(const char *Cmd) {
}
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, "%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
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
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 bar = (int)((int)((hi + hi_1) / 2) * 0.03);
int bar = (int)((int)((hi + hi_1) / 2) * 0.04);
if (verbose && foo < bar) {
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)) {
PrintAndLogEx(SUCCESS, "possible correlation %4d samples", correlation);
} else {
@ -1069,7 +1069,7 @@ int FSKrawDemod(const char *Cmd, bool verbose) {
}
return 1;
} else {
if (g_debugMode) PrintAndLogEx(NORMAL, "no FSK data found");
PrintAndLogEx(DEBUG, "no FSK data found");
}
return 0;
}
@ -1128,7 +1128,7 @@ int PSKDemod(const char *Cmd, bool verbose) {
return 1;
}
int CmdPSKIdteck(const char *Cmd) {
int CmdIdteckDemod(const char *Cmd) {
if (!PSKDemod("", false)) {
PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck PSKDemod failed");

View file

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

View file

@ -245,7 +245,7 @@ int CmdFlashMemLoad(const char *Cmd) {
break;
default:
res = loadFile(filename, "bin", data, &datalen);
res = loadFile(filename, "bin", data, FLASH_MEM_MAX_SIZE, &datalen);
//int res = loadFileEML( filename, "eml", data, &datalen);
if (res) {
free(data);

View file

@ -42,4 +42,4 @@ extern int CmdFlashMemWipe(const char *Cmd);
extern int CmdFlashMemInfo(const char *Cmd);
#endif
#endif
#endif

View file

@ -21,7 +21,7 @@ int usage_hf_search() {
return 0;
}
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, "Press button to quit the sniffing.\n");
PrintAndLogEx(NORMAL, "Usage: hf sniff <skip pairs> <skip triggers>");
@ -42,7 +42,7 @@ int CmdHFSearch(const char *Cmd) {
if (cmdp == 'h') return usage_hf_search();
PrintAndLogEx(INFO, "Checking for known tags...\n");
int ans = CmdHF14AInfo("s");
if (ans > 0) {
PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("ISO14443-A tag") " found\n");

View file

@ -803,7 +803,7 @@ int CmdHF14ASniff(const char *Cmd) {
if (ctmp == 'c') param |= 0x01;
if (ctmp == 'r') param |= 0x02;
}
UsbCommand c = {CMD_SNOOP_ISO_14443a, {param, 0, 0}};
UsbCommand c = {CMD_SNIFF_ISO_14443a, {param, 0, 0}};
clearCommandBuffer();
SendCommand(&c);
return 0;

View file

@ -33,7 +33,7 @@ int usage_hf_14b_reader(void) {
return 0;
}
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, " -h this help");
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, " -s active signal field ON with select");
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, " hf 14b raw -s -c -p 0200a40400");
return 0;
@ -145,20 +146,20 @@ int CmdHF14BSniff(const char *Cmd) {
char cmdp = tolower(param_getchar(Cmd, 0));
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();
SendCommand(&c);
return 0;
}
int CmdHF14BCmdRaw(const char *Cmd) {
bool reply = true, power = false, select = false;
bool reply = true, power = false, select = false, hasTimeout = false;
char buf[5] = "";
int i = 0;
uint8_t data[USB_CMD_DATA_SIZE] = {0x00};
uint16_t datalen = 0;
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();
@ -189,6 +190,13 @@ int CmdHF14BCmdRaw(const char *Cmd) {
flags |= ISO14B_SELECT_STD;
}
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:
return usage_hf_14b_raw();
}
@ -214,7 +222,17 @@ int CmdHF14BCmdRaw(const char *Cmd) {
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;
if (datalen > 0)
@ -223,7 +241,7 @@ int CmdHF14BCmdRaw(const char *Cmd) {
// Max buffer is USB_CMD_DATA_SIZE
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);
clearCommandBuffer();
SendCommand(&c);

View file

@ -684,15 +684,15 @@ int CmdHF15Dump(const char *Cmd) {
//Validations
if (errors) return usage_15_dump();
if (!getUID(uid)) {
PrintAndLogEx(WARNING, "No tag found.");
return 1;
}
if (fileNameLen < 1) {
PrintAndLogEx(INFO, "Using UID as filename");
if (!getUID(uid)) {
PrintAndLogEx(WARNING, "No tag found.");
return 1;
}
fptr += sprintf(fptr, "hf-15-");
FillFileNameByUID(fptr, uid, "-dump", sizeof(uid));
}
@ -796,7 +796,7 @@ int CmdHF15Restore(const char *Cmd) {
case '2':
case 'o':
strncpy(newCmdPrefix, " ", sizeof(newCmdPrefix) - 1);
strncat(newCmdPrefix, param, sizeof(newCmdPrefix) - 1);
strncat(newCmdPrefix, param, sizeof(newCmdPrefix) - strlen(newCmdPrefix) - 1);
break;
default:
PrintAndLogEx(WARNING, "Unknown parameter '%s'", param);
@ -1315,4 +1315,4 @@ int CmdHF15(const char *Cmd) {
int CmdHF15Help(const char *Cmd) {
CmdsHelp(CommandTable15);
return 0;
}
}

View file

@ -176,4 +176,4 @@ int CmdHFEPA(const char *Cmd) {
clearCommandBuffer();
CmdsParse(CommandTable, Cmd);
return 0;
}
}

View file

@ -218,7 +218,7 @@ int CmdHFFelicaSniff(const char *Cmd) {
//Validations
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();
SendCommand(&c);
return 0;
@ -609,4 +609,4 @@ int CmdHFFelica(const char *Cmd) {
int CmdHelp(const char *Cmd) {
CmdsHelp(CommandTable);
return 0;
}
}

View file

@ -24,4 +24,4 @@
extern int CmdHFFido(const char *Cmd);
#endif
#endif

View file

@ -279,7 +279,7 @@ int CmdHFiClassList(const char *Cmd) {
int CmdHFiClassSniff(const char *Cmd) {
char cmdp = tolower(param_getchar(Cmd, 0));
if (cmdp == 'h') return usage_hf_iclass_sniff();
UsbCommand c = {CMD_SNOOP_ICLASS};
UsbCommand c = {CMD_SNIFF_ICLASS};
SendCommand(&c);
return 0;
}
@ -1375,11 +1375,14 @@ int CmdHFiClassCloneTag(const char *Cmd) {
return 2;
}
fclose(f);
uint8_t MAC[4] = {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;
}
UsbCommand w = {CMD_ICLASS_CLONE, {startblock, endblock}};
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, " MAC |%02x%02x%02x%02x|\n", p[8], p[9], p[10], p[11]);
}
UsbCommand resp;
clearCommandBuffer();
SendCommand(&w);

View file

@ -1317,4 +1317,4 @@ int CmdHFLegic(const char *Cmd) {
int CmdHelp(const char *Cmd) {
CmdsHelp(CommandTable);
return 0;
}
}

View file

@ -1251,4 +1251,4 @@ uint64_t GetCrypto1ProbableKey(TAuthData *ad) {
crypto1_get_lfsr(revstate, &key);
crypto1_destroy(revstate);
return key;
}
}

View file

@ -2541,7 +2541,7 @@ int CmdHF14AMfELoad(const char *Cmd) {
uint8_t *data = calloc(4096, sizeof(uint8_t));
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);
if (res) {
free(data);
@ -2827,7 +2827,7 @@ int CmdHF14AMfCLoad(const char *Cmd) {
size_t datalen = 0;
int res = 0;
if (fillFromBin) {
res = loadFile(fileName, "bin", data, &datalen);
res = loadFile(fileName, "bin", data, maxdatalen, &datalen);
} else {
if (fillFromJson) {
res = loadFileJSON(fileName, "json", data, maxdatalen, &datalen);
@ -3506,7 +3506,7 @@ static command_t CommandTable[] = {
{"nack", CmdHf14AMfNack, 0, "Test for Mifare NACK bug"},
{"chk", CmdHF14AMfChk, 0, "Check keys"},
{"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, ""},
{"dbg", CmdHF14AMfDbg, 0, "Set default debug mode"},
{"rdbl", CmdHF14AMfRdBl, 0, "Read MIFARE classic block"},

View file

@ -2,4 +2,4 @@
static int CmdHelp(const char *Cmd);
int CmdHF14AMfDESAuth(const char *Cmd);
int CmdHFMFDesfire(const char *Cmd);
int CmdHelp(const char *Cmd);
int CmdHelp(const char *Cmd);

View file

@ -15,4 +15,4 @@
extern int CmdHFMFP(const char *Cmd);
#endif
#endif

View file

@ -70,8 +70,8 @@ int usage_lf_config(void) {
PrintAndLogEx(NORMAL, " a resolution of 4 bits per sample.");
PrintAndLogEx(NORMAL, " lf read");
PrintAndLogEx(NORMAL, " Performs a read (active field)");
PrintAndLogEx(NORMAL, " lf snoop");
PrintAndLogEx(NORMAL, " Performs a snoop (no active field)");
PrintAndLogEx(NORMAL, " lf sniff");
PrintAndLogEx(NORMAL, " Performs a sniff (no active field)");
return 0;
}
int usage_lf_simfsk(void) {
@ -216,7 +216,7 @@ int CmdFlexdemod(const char *Cmd) {
}
if (start == size - LONG_WAIT) {
PrintAndLogEx(WARNING, "nothing to wait for");
PrintAndLogEx(WARNING, "nothing to wait for");
return 0;
}
@ -389,7 +389,7 @@ int CmdLFSniff(const char *Cmd) {
uint8_t cmdp = tolower(param_getchar(Cmd, 0));
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();
SendCommand(&c);
WaitForResponse(CMD_ACK, NULL);
@ -839,12 +839,12 @@ bool CheckChipType(bool getDeviceData) {
//check for t55xx chip...
if (tryDetectP1(true)) {
PrintAndLogEx(SUCCESS, "\nChipset detection : " _GREEN_("Atmel T55xx") " found");
PrintAndLogEx(SUCCESS, "\nChipset detection : " _GREEN_("Atmel T55xx") " found");
PrintAndLogEx(SUCCESS, "Try " _YELLOW_("`lf t55xx`")" commands");
retval = true;
goto out;
}
out:
save_restoreGB(GRAPH_RESTORE);
save_restoreDB(GRAPH_RESTORE);
@ -896,12 +896,15 @@ int CmdLFfind(const char *Cmd) {
}
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 (CmdParadoxDemod("")) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Paradox 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 (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 (CmdPSKIdteck("")) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Idteck ID") " found!"); goto out;}
if (CmdIdteckDemod("")) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Idteck 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 (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 (CmdKeriDemod("")) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("KERI 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 (CmdPyramidDemod("")) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Pyramid 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;
if (ASKDemod_ext("0 0 0", true, false, 1, &st)) {
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;
}
if (CmdPSK1rawDemod("")) {
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 NRZ - try " _YELLOW_("'data rawdemod nr") );
PrintAndLogEx(NORMAL, " Could also be NRZ - try " _YELLOW_("'data rawdemod nr"));
goto out;
}
PrintAndLogEx(FAILED, _RED_("\nNo data found!") );
PrintAndLogEx(FAILED, _RED_("\nNo data found!"));
}
out:
// identify chipset

View file

@ -17,23 +17,68 @@
#include "common.h"
#include "util.h"
#include "parity.h"
#include "hitag2.h"
#include "hitagS.h"
#include "hitag.h"
#include "util_posix.h"
#include "comms.h"
#include "cmddata.h"
#include "loclass/fileutils.h" // savefile
static int CmdHelp(const char *Cmd);
size_t nbytes(size_t nbits) {
return (nbits / 8) + ((nbits % 8) > 0);
}
int usage_hitag_reader(void)
{
PrintAndLogEx(NORMAL, "Usage: lf hitag reader [h] <reader function #>");
int usage_hitag_sniff(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, "Options:");
PrintAndLogEx(NORMAL, " h This help");
PrintAndLogEx(NORMAL, " HitagS (0*)");
PrintAndLogEx(NORMAL, " 01 <nr> <ar> Challenge, read all pages from a Hitag S tag");
PrintAndLogEx(NORMAL, " 02 <key> Set to 0 if no authentication is needed. Read all pages from a Hitag S tag");
@ -43,11 +88,41 @@ int usage_hitag_reader(void)
PrintAndLogEx(NORMAL, " 22 <nr> <ar> Authentication");
PrintAndLogEx(NORMAL, " 23 <key> Authentication, key is in format: ISK high + ISK low");
PrintAndLogEx(NORMAL, " 25 Test recorded authentications");
PrintAndLogEx(NORMAL, " 26 Just read UID");
PrintAndLogEx(NORMAL, " 26 Just read UID");
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) {
CmdTraceList("hitag");
return 0;
/*
uint8_t *got = calloc(USB_CMD_DATA_SIZE, sizeof(uint8_t));
if (!got) {
PrintAndLogEx(WARNING, "Cannot allocate memory for trace");
@ -172,10 +247,15 @@ int CmdLFHitagList(const char *Cmd) {
free(got);
return 0;
*/
}
int CmdLFHitagSnoop(const char *Cmd) {
UsbCommand c = {CMD_SNOOP_HITAG};
int CmdLFHitagSniff(const char *Cmd) {
char ctmp = tolower(param_getchar(Cmd, 0));
if (ctmp == 'h') return usage_hitag_sniff();
UsbCommand c = {CMD_SNIFF_HITAG, {0, 0, 0}};
clearCommandBuffer();
SendCommand(&c);
return 0;
@ -183,40 +263,249 @@ int CmdLFHitagSnoop(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 };
FILE *f;
bool tag_mem_supplied;
int len = strlen(Cmd);
if (len > FILE_PATH_SIZE) len = FILE_PATH_SIZE;
memcpy(filename, Cmd, len);
UsbCommand c = {CMD_SIMULATE_HITAG, {0, 0, 0}};
if (strlen(filename) > 0) {
f = fopen(filename, "rb+");
if (!f) {
PrintAndLogEx(WARNING, "Error: Could not open file [%s]", filename);
return 1;
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
switch (tolower(param_getchar(Cmd, cmdp))) {
case 'h':
free(data);
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;
cmdp += 2;
break;
case 'j':
param_getstr(Cmd, cmdp + 1, filename, sizeof(filename));
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;
}
tag_mem_supplied = true;
size_t bytes_read = fread(c.d.asBytes, 1, 48, f);
if (bytes_read == 48) {
PrintAndLogEx(WARNING, "Error: File reading error");
fclose(f);
return 1;
}
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;
if (tag_mem_supplied) {
memcpy(c.d.asBytes, data, datalen);
}
clearCommandBuffer();
SendCommand(&c);
free(data);
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) {
UsbCommand c = {CMD_READER_HITAG, {0, 0, 0} };
@ -228,25 +517,25 @@ int CmdLFHitagReader(const char *Cmd) {
c.cmd = CMD_READ_HITAG_S;
num_to_bytes(param_get32ex(Cmd, 1, 0, 16), 4, htd->auth.NrAr);
num_to_bytes(param_get32ex(Cmd, 2, 0, 16), 4, htd->auth.NrAr + 4);
break;
break;
}
case RHTSF_KEY: {
c.cmd = CMD_READ_HITAG_S;
num_to_bytes(param_get64ex(Cmd, 1, 0, 16), 6, htd->crypto.key);
break;
break;
}
case RHT2F_PASSWORD: {
num_to_bytes(param_get32ex(Cmd, 1, 0, 16), 4, htd->pwd.password);
break;
break;
}
case RHT2F_AUTHENTICATE: {
num_to_bytes(param_get32ex(Cmd, 1, 0, 16), 4, htd->auth.NrAr);
num_to_bytes(param_get32ex(Cmd, 2, 0, 16), 4, htd->auth.NrAr + 4);
break;
break;
}
case RHT2F_CRYPTO: {
num_to_bytes(param_get64ex(Cmd, 1, 0, 16), 6, htd->crypto.key);
break;
break;
}
case RHT2F_TEST_AUTH_ATTEMPTS: {
// No additional parameters needed
@ -257,7 +546,6 @@ int CmdLFHitagReader(const char *Cmd) {
break;
}
default: {
PrintAndLogEx(NORMAL, "\nError: unkown reader function %d", htf);
return usage_hitag_reader();
}
}
@ -278,150 +566,136 @@ int CmdLFHitagReader(const char *Cmd) {
uint32_t id = bytes_to_num(resp.d.asBytes, 4);
if (htf == RHT2F_UID_ONLY) {
PrintAndLogEx(NORMAL, "Valid Hitag2 tag found - UID: %08x", id);
} else {
PrintAndLogEx(SUCCESS, "Valid Hitag2 tag found - UID: %08x", id);
if (htf != RHT2F_UID_ONLY) {
PrintAndLogEx(SUCCESS, "Dumping tag memory..." );
uint8_t *data = resp.d.asBytes;
char filename[FILE_PATH_SIZE];
FILE *f = NULL;
sprintf(filename, "%08x_%04x.ht2", id, (rand() & 0xffff));
f = fopen(filename, "wb");
if (!f) {
PrintAndLogEx(WARNING, "Error: Could not open file [%s]", filename);
return 1;
}
char *fnameptr = filename;
fnameptr += sprintf(fnameptr, "lf-hitag-");
FillFileNameByUID(fnameptr, data, "-dump", 4);
// Write the 48 tag memory bytes to file and finalize
fwrite(resp.d.asBytes, 1, 48, f);
fclose(f);
PrintAndLogEx(NORMAL, "Succesfully saved tag memory to [%s]", filename);
saveFile(filename, "bin", data, 48);
saveFileEML(filename, "eml", data, 48, 4);
saveFileJSON(filename, "json", jsfHitag, data, 48);
// block3, 1 byte
printHitagConfiguration(data[4*3] );
}
return 0;
}
int CmdLFHitagSimS(const char *Cmd) {
UsbCommand c = { CMD_SIMULATE_HITAG_S };
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;
}
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) {
f = fopen(filename, "rb+");
if (!f) {
PrintAndLogEx(WARNING, "Error: Could not open file [%s]", filename);
return 1;
UsbCommand c = { CMD_TEST_HITAGS_TRACES, {0, 0, 0}};
char filename[FILE_PATH_SIZE] = { 0x00 };
size_t datalen = 0;
int res = 0;
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;
cmdp += 2;
break;
default:
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
errors = true;
break;
}
file_given = true;
size_t bytes_read = fread(c.d.asBytes, 1, 8 * 60, f);
if (bytes_read == 8 * 60) {
PrintAndLogEx(WARNING, "Error: File reading error");
fclose(f);
return 1;
}
fclose(f);
} else {
file_given = false;
}
//Validations
if (errors) {
free(data);
return usage_hitag_checkchallenges();
}
//file with all the challenges to try
c.arg[0] = (uint32_t)file_given;
clearCommandBuffer();
SendCommand(&c);
free(data);
return 0;
}
int CmdLFHitagWP(const char *Cmd) {
UsbCommand c = { CMD_WR_HITAG_S };
int CmdLFHitagWriter(const char *Cmd) {
UsbCommand c = { CMD_WR_HITAG_S, {0, 0, 0}};
hitag_data *htd = (hitag_data *)c.d.asBytes;
hitag_function htf = param_get32ex(Cmd, 0, 0, 10);
switch (htf) {
case 03: { //WHTSF_CHALLENGE
case WHTSF_CHALLENGE: {
num_to_bytes(param_get64ex(Cmd, 1, 0, 16), 8, htd->auth.NrAr);
c.arg[2] = param_get32ex(Cmd, 2, 0, 10);
num_to_bytes(param_get32ex(Cmd, 3, 0, 16), 4, htd->auth.data);
break;
}
break;
case 04:
case 24: {
//WHTSF_KEY
case WHTSF_KEY:
case WHT2F_CRYPTO: {
num_to_bytes(param_get64ex(Cmd, 1, 0, 16), 6, htd->crypto.key);
c.arg[2] = param_get32ex(Cmd, 2, 0, 10);
num_to_bytes(param_get32ex(Cmd, 3, 0, 16), 4, htd->crypto.data);
break;
}
break;
default: {
PrintAndLogEx(WARNING, "Error: unkown writer function %d", htf);
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;
return usage_hitag_writer();
}
break;
}
// Copy the hitag function into the first argument
c.arg[0] = htf;
clearCommandBuffer();
SendCommand(&c);
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) return 1;
if (resp.arg[0] == false) {
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;
}
static command_t CommandTable[] = {
{"help", CmdHelp, 1, "This help"},
{"list", CmdLFHitagList, 1, "<outfile> List Hitag trace history"},
{"reader", CmdLFHitagReader, 1, "Act like a Hitag Reader"},
{"sim", CmdLFHitagSim, 1, "<infile> Simulate Hitag transponder"},
{"simS", CmdLFHitagSimS, 1, "<hitagS.hts> Simulate HitagS transponder" },
{"snoop", CmdLFHitagSnoop, 1, "Eavesdrop Hitag communication"},
{"writer", CmdLFHitagWP, 1, "Act like a Hitag Writer" },
{"check_challenges", CmdLFHitagCheckChallenges, 1, "<challenges.cc> test all challenges" },
{"help", CmdHelp, 1, "This help" },
{"list", CmdLFHitagList, 0, "List Hitag trace history" },
{"info", CmdLFHitagInfo, 1, "Tag information" },
{"reader", CmdLFHitagReader, 1, "Act like a Hitag Reader" },
{"sim", CmdLFHitagSim, 1, "Simulate Hitag transponder" },
{"sniff", CmdLFHitagSniff, 1, "Eavesdrop Hitag communication" },
{"writer", CmdLFHitagWriter, 1, "Act like a Hitag Writer" },
{"cc", CmdLFHitagCheckChallenges, 1, "Test all challenges" },
{ NULL, NULL, 0, NULL }
};

View file

@ -14,11 +14,12 @@
extern int CmdLFHitag(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 CmdLFHitagSimS(const char *Cmd);
extern int CmdLFHitagSnoop(const char *Cmd);
extern int CmdLFHitagWP(const char *Cmd);
extern int CmdLFHitagInfo(const char *Cmd);
extern int CmdLFHitagReader(const char *Cmd);
extern int CmdLFHitagCheckChallenges(const char *Cmd);
extern int CmdLFHitagWriter(const char *Cmd);
extern int CmdLFHitagDump(const char *cmd);
#endif

View file

@ -1882,7 +1882,7 @@ int CmdT55xxRecoverPW(const char *Cmd) {
// first try fliping each bit in the expected password
while (bit < 32) {
curr_password = orig_password ^ (1 << bit);
curr_password = orig_password ^ (1u << bit);
found = tryOnePassword(curr_password);
if (found == -1) return 0;
bit++;
@ -1897,7 +1897,7 @@ int CmdT55xxRecoverPW(const char *Cmd) {
// from low bit to high bit
bit = 0;
while (bit < 32) {
mask += (1 << bit);
mask += (1u << bit);
curr_password = orig_password & mask;
// if updated mask didn't change the password, don't try it again
if (prev_password == curr_password) {
@ -1916,7 +1916,7 @@ int CmdT55xxRecoverPW(const char *Cmd) {
bit = 0;
mask = 0xffffffff;
while (bit < 32) {
mask -= (1 << bit);
mask -= (1u << bit);
curr_password = orig_password & mask;
// if updated mask didn't change the password, don't try it again
if (prev_password == curr_password) {

View file

@ -191,7 +191,7 @@ int CmdTIDemod(const char *Cmd) {
bits[i] = '1';
maxPos += highLen;
// bitstream arrives lsb first so shift right
shift3 |= (1 << 31);
shift3 |= (1u << 31);
} else {
bits[i] = '.';
maxPos += lowLen;

View file

@ -74,4 +74,4 @@ int CmdRev(const char *Cmd) {
//-----------------------------------------------------------------------------
int CommandReceived(char *Cmd) {
return CmdsParse(CommandTable, Cmd);
}
}

View file

@ -193,4 +193,4 @@ int CmdScript(const char *Cmd) {
int CmdHelp(const char *Cmd) {
PrintAndLogEx(NORMAL, "This is a feature to run Lua-scripts. You can place lua-scripts within the scripts/-folder. ");
return 0;
}
}

View file

@ -49,13 +49,13 @@ int usage_sm_info(void) {
return 0;
}
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, " h : this help");
PrintAndLogEx(NORMAL, " f <filename> : firmware file name");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, " sc upgrade f myfile");
PrintAndLogEx(NORMAL, " sc upgrade f ../tools/simmodule/SIM011.BIN");
return 0;
}
int usage_sm_setclock(void) {
@ -116,7 +116,7 @@ uint8_t GetATRTA1(uint8_t *atr, size_t atrlen) {
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[] = {
@ -196,6 +196,8 @@ static int PrintATR(uint8_t *atr, size_t atrlen) {
uint8_t T0 = atr[1];
uint8_t K = T0 & 0x0F;
uint8_t TD1 = 0, T1len = 0, TD1len = 0, TDilen = 0;
bool protocol_T0_present = true;
bool protocol_T15_present = false;
if (T0 & 0x10) {
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) {
TD1 = atr[2 + T1len];
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++;
if (TD1 & 0x10) {
@ -232,6 +242,12 @@ static int PrintATR(uint8_t *atr, size_t atrlen) {
if (TD1 & 0x80) {
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);
if ((TDi & 0x0f) == 0) {
protocol_T0_present = true;
}
if ((TDi & 0x0f) == 15) {
protocol_T15_present = true;
}
TD1len++;
bool nextCycle = true;
@ -262,19 +278,20 @@ static int PrintATR(uint8_t *atr, size_t atrlen) {
}
}
uint8_t vxor = 0;
for (int i = 1; i < atrlen; i++)
vxor ^= atr[i];
if (!protocol_T0_present || protocol_T15_present) { // there is CRC Check Byte TCK
uint8_t vxor = 0;
for (int i = 1; i < atrlen; i++)
vxor ^= atr[i];
if (vxor)
PrintAndLogEx(WARNING, "Check summ error. Must be 0 got 0x%02X", vxor);
else
PrintAndLogEx(INFO, "Check summ OK.");
if (vxor)
PrintAndLogEx(WARNING, "Check sum error. Must be 0 got 0x%02X", vxor);
else
PrintAndLogEx(INFO, "Check sum OK.");
}
if (atr[0] != 0x3b)
PrintAndLogEx(WARNING, "Not a direct convention [ 0x%02x ]", atr[0]);
uint8_t calen = 2 + T1len + TD1len + TDilen + K;
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) {
PrintAndLogEx(WARNING, "WARNING - Smartcard socket firmware upgrade.");
PrintAndLogEx(WARNING, "A dangerous command, do wrong and you will brick the smart card socket");
PrintAndLogEx(WARNING, "WARNING - Sim module firmware upgrade.");
PrintAndLogEx(WARNING, "A dangerous command, do wrong and you could brick the sim module");
PrintAndLogEx(NORMAL, "");
FILE *f;
char filename[FILE_PATH_SIZE] = {0};
@ -592,10 +610,33 @@ int CmdSmartUpgrade(const char *Cmd) {
//Validations
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");
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;
}
@ -605,27 +646,77 @@ int CmdSmartUpgrade(const char *Cmd) {
fseek(f, 0, SEEK_SET);
if (fsize < 0) {
PrintAndLogDevice(WARNING, "error, when getting filesize");
PrintAndLogEx(WARNING, "error, when getting filesize");
fclose(f);
return 1;
}
uint8_t *dump = calloc(fsize, sizeof(uint8_t));
if (!dump) {
PrintAndLogDevice(WARNING, "error, cannot allocate memory ");
PrintAndLogEx(WARNING, "error, cannot allocate memory ");
fclose(f);
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)
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
uint32_t index = 0;
uint32_t bytes_sent = 0;
uint32_t bytes_remaining = bytes_read;
uint32_t bytes_remaining = firmware_size;
while (bytes_remaining > 0) {
uint32_t bytes_in_packet = MIN(USB_CMD_DATA_SIZE, bytes_remaining);
@ -649,10 +740,10 @@ int CmdSmartUpgrade(const char *Cmd) {
}
free(dump);
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
UsbCommand c = {CMD_SMART_UPGRADE, {bytes_read, 0, 0}};
UsbCommand c = {CMD_SMART_UPGRADE, {firmware_size, 0, 0}};
clearCommandBuffer();
SendCommand(&c);
UsbCommand resp;
@ -660,10 +751,12 @@ int CmdSmartUpgrade(const char *Cmd) {
PrintAndLogEx(WARNING, "timeout while waiting for reply.");
return 1;
}
if ((resp.arg[0] & 0xFF))
PrintAndLogEx(SUCCESS, "Smartcard socket firmware upgraded successful");
else
PrintAndLogEx(FAILED, "Smartcard socket firmware updating failed");
if ((resp.arg[0] & 0xFF)) {
PrintAndLogEx(SUCCESS, "Sim module firmware upgrade " _GREEN_("successful"));
PrintAndLogEx(SUCCESS, "\n run " _YELLOW_("`hw status`") " to validate the fw version ");
} else {
PrintAndLogEx(FAILED, "Sim module firmware upgrade " _RED_("failed"));
}
return 0;
}
@ -874,11 +967,11 @@ static void smart_brute_prim() {
if (len > 2) {
//if ( decodeTLV ) {
//if (!TLVPrintFromBuffer(buf, len-2)) {
// if ( decodeTLV ) {
// if (!TLVPrintFromBuffer(buf, len-2)) {
PrintAndLogEx(SUCCESS, "\tHEX %d |: %s", len, sprint_hex(buf, len));
//}
//}
// }
// }
}
len = 0;
}
@ -1124,14 +1217,14 @@ int CmdSmartBruteforceSFI(const char *Cmd) {
}
static command_t CommandTable[] = {
{"help", CmdHelp, 1, "This help"},
{"list", CmdSmartList, 0, "List ISO 7816 history"},
{"info", CmdSmartInfo, 1, "Tag information"},
{"reader", CmdSmartReader, 1, "Act like an IS07816 reader"},
{"raw", CmdSmartRaw, 1, "Send raw hex data to tag"},
{"upgrade", CmdSmartUpgrade, 1, "Upgrade firmware"},
{"help", CmdHelp, 1, "This help"},
{"list", CmdSmartList, 0, "List ISO 7816 history"},
{"info", CmdSmartInfo, 1, "Tag information"},
{"reader", CmdSmartReader, 1, "Act like an IS07816 reader"},
{"raw", CmdSmartRaw, 1, "Send raw hex data to tag"},
{"upgrade", CmdSmartUpgrade, 1, "Upgrade sim module firmware"},
{"setclock", CmdSmartSetClock, 1, "Set clock speed"},
{"brute", CmdSmartBruteforceSFI, 1, "Bruteforce SFI"},
{"brute", CmdSmartBruteforceSFI, 1, "Bruteforce SFI"},
{NULL, NULL, 0, NULL}
};

View file

@ -25,6 +25,7 @@
#include "emv/emvcore.h" // decodeTVL
#include "emv/apduinfo.h" // APDUcode description
#include "emv/dump.h" // dump_buffer
#include "crypto/libpcrypto.h" // sha512hash
extern int CmdSmartcard(const char *Cmd);
@ -40,4 +41,4 @@ extern int usage_sm_raw(void);
extern int usage_sm_reader(void);
extern int usage_sm_info(void);
extern int usage_sm_upgrade(void);
#endif
#endif

View file

@ -36,6 +36,7 @@ int usage_trace_list() {
PrintAndLogEx(NORMAL, " 7816 - interpret data as iso7816-4 communications");
PrintAndLogEx(NORMAL, " legic - interpret data as LEGIC communications");
PrintAndLogEx(NORMAL, " felica - interpret data as ISO18092 / FeliCa communications");
PrintAndLogEx(NORMAL, " hitag - interpret data as Hitag2 / HitagS communications");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:");
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);
break;
case ISO_7816_4:
case PROTO_HITAG:
default:
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++) {
uint8_t parityBits = parityBytes[j >> 3];
if (protocol != LEGIC &&
protocol != ISO_14443B &&
protocol != ISO_7816_4 &&
(isResponse || protocol == ISO_14443A) &&
(oddparity8(frame[j]) != ((parityBits >> (7 - (j & 0x0007))) & 0x01))) {
if (protocol != LEGIC
&& protocol != ISO_14443B
&& protocol != ISO_7816_4
&& protocol != PROTO_HITAG
&& (isResponse || protocol == ISO_14443A)
&& (oddparity8(frame[j]) != ((parityBits >> (7 - (j & 0x0007))) & 0x01))) {
snprintf(line[j / 18] + ((j % 18) * 4), 110, "%02x! ", frame[j]);
} else {
@ -556,16 +559,17 @@ int CmdTraceList(const char *Cmd) {
// validate type of output
if (strcmp(type, "iclass") == 0) protocol = ICLASS;
else if (strcmp(type, "14a") == 0) protocol = ISO_14443A;
else if (strcmp(type, "14b") == 0) protocol = ISO_14443B;
else if (strcmp(type, "topaz") == 0) protocol = TOPAZ;
else if (strcmp(type, "7816") == 0) protocol = ISO_7816_4;
else if (strcmp(type, "des") == 0) protocol = MFDES;
else if (strcmp(type, "legic") == 0) protocol = LEGIC;
else if (strcmp(type, "15") == 0) protocol = ISO_15693;
else if (strcmp(type, "felica") == 0) protocol = FELICA;
else if (strcmp(type, "mf") == 0) protocol = PROTO_MIFARE;
else if (strcmp(type, "raw") == 0) protocol = -1; //No crc, no annotations
else if (strcmp(type, "14a") == 0) protocol = ISO_14443A;
else if (strcmp(type, "14b") == 0) protocol = ISO_14443B;
else if (strcmp(type, "topaz") == 0) protocol = TOPAZ;
else if (strcmp(type, "7816") == 0) protocol = ISO_7816_4;
else if (strcmp(type, "des") == 0) protocol = MFDES;
else if (strcmp(type, "legic") == 0) protocol = LEGIC;
else if (strcmp(type, "15") == 0) protocol = ISO_15693;
else if (strcmp(type, "felica") == 0) protocol = FELICA;
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 errors = true;
cmdp++;
@ -625,6 +629,8 @@ int CmdTraceList(const char *Cmd) {
PrintAndLogEx(NORMAL, "ISO15693 - Timings are not as accurate");
if (protocol == ISO_7816_4)
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, " Start | End | Src | Data (! denotes parity error) | CRC | Annotation");
@ -642,8 +648,8 @@ int CmdTraceLoad(const char *Cmd) {
FILE *f = NULL;
char filename[FILE_PATH_SIZE];
char cmdp = param_getchar(Cmd, 0);
if (strlen(Cmd) < 1 || cmdp == 'h' || cmdp == 'H') return usage_trace_load();
char cmdp = tolower(param_getchar(Cmd, 0));
if (strlen(Cmd) < 1 || cmdp == 'h') return usage_trace_load();
param_getstr(Cmd, 0, filename, sizeof(filename));
@ -688,13 +694,13 @@ int CmdTraceLoad(const char *Cmd) {
int CmdTraceSave(const char *Cmd) {
if (traceLen == 0) {
PrintAndLogEx(WARNING, "trace is empty, exiting...");
PrintAndLogEx(WARNING, "trace is empty, nothing to save");
return 0;
}
char filename[FILE_PATH_SIZE];
char cmdp = param_getchar(Cmd, 0);
if (strlen(Cmd) < 1 || cmdp == 'h' || cmdp == 'H') return usage_trace_save();
char cmdp = tolower(param_getchar(Cmd, 0));
if (strlen(Cmd) < 1 || cmdp == 'h') return usage_trace_save();
param_getstr(Cmd, 0, filename, sizeof(filename));
saveFile(filename, "bin", trace, traceLen);

View file

@ -19,6 +19,7 @@
#include <mbedtls/pk.h>
#include <mbedtls/ecdsa.h>
#include <mbedtls/sha256.h>
#include <mbedtls/sha512.h>
#include <mbedtls/ctr_drbg.h>
#include <mbedtls/entropy.h>
#include <mbedtls/error.h>
@ -106,6 +107,20 @@ int sha256hash(uint8_t *input, int length, uint8_t *hash) {
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) {
if (!ctx)
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 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_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.");
tlvdb_free(tmp_ext);
tlvdb_free(tlvRoot);
free(pdol_data_tlv);
return 4;
}
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) {
PrintAndLogEx(ERR, "Can't create PDOL data.");
tlvdb_free(tlvRoot);
free(pdol_data_tlv);
DropFieldEx(channel);
return 6;
}

View file

@ -38,4 +38,4 @@ extern int JsonLoadBufAsHex(json_t *elm, char *path, uint8_t *data, size_t maxbu
extern bool ParamLoadFromJson(struct tlvdb *tlv);
#endif
#endif

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))
strncat(dst, "LF", len - 1);
strncat(dst, "LF", len - strlen(dst) - 1);
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)) {
strncat(dst, " for ", len - 1);
strncat(dst, " for ", len - strlen(dst) - 1);
for (uint16_t i = 0; i < fpga_info_len; i++) {
char c = (char)fgetc(infile);
if (i < sizeof(tempstr)) {
tempstr[i] = c;
}
}
strncat(dst, tempstr, len - 1);
strncat(dst, tempstr, len - strlen(dst) - 1);
}
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++) {
char c = (char)fgetc(infile);
if (i < sizeof(tempstr)) {
tempstr[i] = c;
}
}
strncat(dst, tempstr, len - 1);
strncat(dst, tempstr, len - strlen(dst) - 1);
}
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++) {
char c = (char)fgetc(infile);
if (i < sizeof(tempstr)) {
tempstr[i] = c;
}
}
strncat(dst, tempstr, len - 1);
strncat(dst, tempstr, len - strlen(dst) - 1);
}
return 0;
}

View file

@ -577,4 +577,4 @@ int main(int argc, char *argv[]) {
free_part_sum_bitarrays();
return 0;
}
}

View file

@ -96,7 +96,7 @@ typedef struct {
#define CMD_IO_DEMOD_FSK 0x021A
#define CMD_IO_CLONE_TAG 0x021B
#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_FSK_SIM_TAG 0x021E
#define CMD_ASK_SIM_TAG 0x021F
@ -119,10 +119,10 @@ typedef struct {
#define CMD_ISO_15693_COMMAND 0x0313
#define CMD_ISO_15693_COMMAND_DONE 0x0314
#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
#define CMD_SNOOP_HITAG 0x0370
#define CMD_SNIFF_HITAG 0x0370
#define CMD_SIMULATE_HITAG 0x0371
#define CMD_READER_HITAG 0x0372
@ -135,8 +135,8 @@ typedef struct {
#define CMD_ANTIFUZZ_ISO_14443a 0x0380
#define CMD_SIMULATE_TAG_ISO_14443B 0x0381
#define CMD_SNOOP_ISO_14443B 0x0382
#define CMD_SNOOP_ISO_14443a 0x0383
#define CMD_SNIFF_ISO_14443B 0x0382
#define CMD_SNIFF_ISO_14443a 0x0383
#define CMD_SIMULATE_TAG_ISO_14443a 0x0384
#define CMD_READER_ISO_14443a 0x0385
@ -151,7 +151,7 @@ typedef struct {
#define CMD_LEGIC_ESET 0x03BD
#define CMD_LEGIC_EGET 0x03BE
#define CMD_SNOOP_ICLASS 0x0392
#define CMD_SNIFF_ICLASS 0x0392
#define CMD_SIMULATE_TAG_ICLASS 0x0393
#define CMD_READER_ICLASS 0x0394
#define CMD_READER_ICLASS_REPLAY 0x0395

View file

@ -692,4 +692,4 @@ int testElite() {
errors += _test_iclass_key_permutation();
errors += _testBruteforce();
return errors;
}
}

View file

@ -155,11 +155,12 @@ int saveFileJSON(const char *preferredName, const char *suffix, JSONFileType fty
json_t *root = json_object();
JsonSaveStr(root, "Created", "proxmark3");
switch (ftype) {
case jsfRaw:
case jsfRaw: {
JsonSaveStr(root, "FileType", "raw");
JsonSaveBufAsHexCompact(root, "raw", data, datalen);
break;
case jsfCardMemory:
}
case jsfCardMemory: {
JsonSaveStr(root, "FileType", "mfcard");
for (int i = 0; i < (datalen / 16); i++) {
char path[PATH_MAX_LENGTH] = {0};
@ -208,7 +209,8 @@ int saveFileJSON(const char *preferredName, const char *suffix, JSONFileType fty
}
}
break;
case jsfMfuMemory:
}
case jsfMfuMemory: {
JsonSaveStr(root, "FileType", "mfu");
mfu_dump_t *tmp = (mfu_dump_t *)data;
@ -230,12 +232,26 @@ int saveFileJSON(const char *preferredName, const char *suffix, JSONFileType fty
size_t len = (datalen - DUMP_PREFIX_LENGTH) / 4;
for (int i = 0; i < len; i++) {
char path[PATH_MAX_LENGTH] = {0};
sprintf(path, "$.blocks.%d", i);
JsonSaveBufAsHexCompact(root, path, tmp->data + (i * 4), 4);
}
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));
@ -253,7 +269,7 @@ out:
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 (suffix == NULL) return 1;
@ -298,6 +314,11 @@ int loadFile(const char *preferredName, const char *suffix, void *data, size_t *
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);
free(dump);
@ -447,8 +468,29 @@ int loadFileJSON(const char *preferredName, const char *suffix, void *data, size
*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:
json_decref(root);
free(fileName);

View file

@ -55,6 +55,11 @@ typedef enum {
jsfRaw,
jsfCardMemory,
jsfMfuMemory,
jsfHitag,
// jsf14b,
// jsf15,
// jsfLegic,
// jsfT55xx,
} JSONFileType;
int fileExists(const char *filename);
@ -107,10 +112,11 @@ extern int saveFileJSON(const char *preferredName, const char *suffix, JSONFileT
* @param preferredName
* @param suffix the file suffix. Leave out the ".".
* @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
* @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.

View file

@ -75,4 +75,4 @@ _errorcodes.tostring = function(command)
end
return ("Error, numeric or string argument expected, got : %s"):format(tostring(command))
end
return _errorcodes
return _errorcodes

View file

@ -32,4 +32,4 @@ end
return {
waitForTag = waitForTag,
}
}

View file

@ -91,4 +91,4 @@ local PreCalc =
return list
end,
}
return PreCalc
return PreCalc

View file

@ -155,4 +155,4 @@ local library = {
ISO14B_COMMAND = ISO14B_COMMAND,
}
return library
return library

View file

@ -121,4 +121,4 @@ return {
return m[value] or "no tag-info available"
end,
}
}

View file

@ -427,4 +427,4 @@ local Utils =
-- end
}
return Utils
return Utils

View file

@ -100,4 +100,4 @@ extern int detect_classic_prng(void);
extern int detect_classic_nackbug(bool verbose);
extern void detect_classic_magic(void);
extern void mf_crypto1_decrypt(struct Crypto1State *pcs, uint8_t *data, int len, bool isEncrypted);
#endif
#endif

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