mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-14 10:37:23 -07:00
Sync from Upstream
This commit is contained in:
parent
ea53e1f981
commit
6a52b6074f
161 changed files with 2002 additions and 1463 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -2,6 +2,7 @@
|
|||
# don't push these files to the repository
|
||||
|
||||
.history
|
||||
.bash_history
|
||||
*.log
|
||||
*.eml
|
||||
*.o
|
||||
|
|
29
CHANGELOG.md
29
CHANGELOG.md
|
@ -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)
|
||||
|
|
195
HACKING.txt
195
HACKING.txt
|
@ -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.
|
||||
|
|
8
Makefile
8
Makefile
|
@ -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 \
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -433,4 +433,4 @@ void RunMod() {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,4 +20,4 @@
|
|||
|
||||
#define OPTS 2
|
||||
|
||||
#endif /* __HF_MATTYRUN_H */
|
||||
#endif /* __HF_MATTYRUN_H */
|
||||
|
|
|
@ -259,4 +259,4 @@ void RunMod() {
|
|||
LED(selected + 1, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,4 +19,4 @@
|
|||
|
||||
#define OPTS 2
|
||||
|
||||
#endif /* __HF_YOUNG_H */
|
||||
#endif /* __HF_YOUNG_H */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -164,4 +164,4 @@ void RunMod() {
|
|||
out:
|
||||
DbpString("[=] exiting");
|
||||
LEDsoff();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,4 +18,4 @@
|
|||
|
||||
#define OPTS 2
|
||||
|
||||
#endif /* __LF_PROXBRUTE_H */
|
||||
#endif /* __LF_PROXBRUTE_H */
|
||||
|
|
|
@ -138,4 +138,4 @@ void RunMod() {
|
|||
out:
|
||||
DbpString("[=] exiting");
|
||||
LEDsoff();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,4 +19,4 @@
|
|||
|
||||
#define OPTS 2
|
||||
|
||||
#endif /* __LF_SAMYRUN_H */
|
||||
#endif /* __LF_SAMYRUN_H */
|
||||
|
|
|
@ -16,4 +16,4 @@
|
|||
|
||||
extern void RunMod();
|
||||
|
||||
#endif /* __STANDALONE_H */
|
||||
#endif /* __STANDALONE_H */
|
||||
|
|
|
@ -1167,4 +1167,4 @@ int main() {
|
|||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -83,4 +83,4 @@ void Ring_Little_Star(uint16_t count) {
|
|||
Ring_BEE_TIME(note_1,2*count);
|
||||
LED_B_ON();
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -151,4 +151,4 @@ void Flashmem_print_status(void);
|
|||
|
||||
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
463
armsrc/hitag2.c
463
armsrc/hitag2.c
|
@ -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
23
armsrc/hitag2.h
Normal 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
116
armsrc/hitag2_crypto.c
Normal 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
36
armsrc/hitag2_crypto.h
Normal 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
|
766
armsrc/hitagS.c
766
armsrc/hitagS.c
File diff suppressed because it is too large
Load diff
31
armsrc/hitagS.h
Normal file
31
armsrc/hitagS.h
Normal 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
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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...
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,4 +25,4 @@
|
|||
#include "crc.h"
|
||||
#include "protocols.h"
|
||||
#include "parity.h"
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -77,4 +77,4 @@ void __attribute__((section(".startos"))) Vector(void) {
|
|||
|
||||
AppMain();
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -44,4 +44,4 @@ extern void WaitUS(uint16_t us);
|
|||
extern void WaitMS(uint16_t ms);
|
||||
|
||||
extern void StopTicks(void);
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -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 ...
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -483,4 +483,4 @@ int CmdrevengSearch(const char *Cmd) {
|
|||
|
||||
if (!found) PrintAndLogEx(FAILED, "\nno matches found\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -42,4 +42,4 @@ extern int CmdFlashMemWipe(const char *Cmd);
|
|||
extern int CmdFlashMemInfo(const char *Cmd);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -176,4 +176,4 @@ int CmdHFEPA(const char *Cmd) {
|
|||
clearCommandBuffer();
|
||||
CmdsParse(CommandTable, Cmd);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,4 +24,4 @@
|
|||
extern int CmdHFFido(const char *Cmd);
|
||||
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -1317,4 +1317,4 @@ int CmdHFLegic(const char *Cmd) {
|
|||
int CmdHelp(const char *Cmd) {
|
||||
CmdsHelp(CommandTable);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1251,4 +1251,4 @@ uint64_t GetCrypto1ProbableKey(TAuthData *ad) {
|
|||
crypto1_get_lfsr(revstate, &key);
|
||||
crypto1_destroy(revstate);
|
||||
return key;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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"},
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -15,4 +15,4 @@
|
|||
extern int CmdHFMFP(const char *Cmd);
|
||||
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 }
|
||||
};
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -74,4 +74,4 @@ int CmdRev(const char *Cmd) {
|
|||
//-----------------------------------------------------------------------------
|
||||
int CommandReceived(char *Cmd) {
|
||||
return CmdsParse(CommandTable, Cmd);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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}
|
||||
};
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -577,4 +577,4 @@ int main(int argc, char *argv[]) {
|
|||
free_part_sum_bitarrays();
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -692,4 +692,4 @@ int testElite() {
|
|||
errors += _test_iclass_key_permutation();
|
||||
errors += _testBruteforce();
|
||||
return errors;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -32,4 +32,4 @@ end
|
|||
|
||||
return {
|
||||
waitForTag = waitForTag,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -91,4 +91,4 @@ local PreCalc =
|
|||
return list
|
||||
end,
|
||||
}
|
||||
return PreCalc
|
||||
return PreCalc
|
||||
|
|
|
@ -155,4 +155,4 @@ local library = {
|
|||
ISO14B_COMMAND = ISO14B_COMMAND,
|
||||
}
|
||||
|
||||
return library
|
||||
return library
|
||||
|
|
|
@ -121,4 +121,4 @@ return {
|
|||
|
||||
return m[value] or "no tag-info available"
|
||||
end,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -427,4 +427,4 @@ local Utils =
|
|||
-- end
|
||||
|
||||
}
|
||||
return Utils
|
||||
return Utils
|
||||
|
|
|
@ -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
Loading…
Add table
Add a link
Reference in a new issue