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]
+## [unreleased][unreleased]
+
+
+## [2.2.0][2015-07-12]
### Changed
- Changed `hf 14b write` to `hf 14b sriwrite` as it only applied to sri tags (marshmellow)
- Added `hf 14b info` to `hf search` (marshmellow)
+- Added compression of fpga config and data, *BOOTROM REFLASH REQUIRED* (piwi)
+- Implemented better detection of mifare-tags that are not vulnerable to classic attacks (`hf mf mifare`, `hf mf nested`) (piwi)
### Added
- Add `hf 14b info` to find and print info about std 14b tags and sri tags (using 14b raw commands in the client) (marshmellow)
extern uint8_t *BigBuf_get_addr(void);
extern uint8_t *BigBuf_get_EM_addr(void);
extern uint16_t BigBuf_max_traceLen(void);
-void BigBuf_Clear(void);
+extern void BigBuf_Clear(void);
extern uint8_t *BigBuf_malloc(uint16_t);
extern void BigBuf_free(void);
extern void BigBuf_free_keep_EM(void);
-uint16_t BigBuf_get_traceLen(void);
-void clear_trace();
-void set_tracing(bool enable);
-bool RAMFUNC LogTrace(const uint8_t *btBytes, uint16_t iLen, uint32_t timestamp_start, uint32_t timestamp_end, uint8_t *parity, bool readerToTag);
-int LogTraceHitag(const uint8_t * btBytes, int iBits, int iSamples, uint32_t dwParity, int bReader);
-uint8_t emlSet(uint8_t *data, uint32_t offset, uint32_t length);
+extern uint16_t BigBuf_get_traceLen(void);
+extern void clear_trace();
+extern void set_tracing(bool enable);
+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 */
//void MifareUWriteBlockCompat(uint8_t arg0,uint8_t *datain);
void MifareUWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain);
void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);
-void MifareChkKeys(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain);
+void MifareChkKeys(uint16_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain);
void Mifare1ksim(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain);
void MifareSetDbgLvl(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);
void MifareEMemClr(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);
// free eventually allocated BigBuf memory\r
BigBuf_free();\r
\r
- clear_trace();\r
- set_tracing(false);\r
+ if (calibrate) clear_trace();\r
+ set_tracing(true);\r
\r
// statistics on nonce distance\r
int16_t isOK = 0;\r
\r
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
LEDsoff();\r
- set_tracing(TRUE);\r
}\r
\r
//-----------------------------------------------------------------------------\r
// MIFARE check keys. key count up to 85. \r
// \r
//-----------------------------------------------------------------------------\r
-void MifareChkKeys(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)\r
+void MifareChkKeys(uint16_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)\r
{\r
// params\r
- uint8_t blockNo = arg0;\r
- uint8_t keyType = arg1;\r
+ uint8_t blockNo = arg0 & 0xff;\r
+ uint8_t keyType = (arg0 >> 8) & 0xff;\r
+ bool clearTrace = arg1;\r
uint8_t keyCount = arg2;\r
uint64_t ui64Key = 0;\r
\r
LED_C_OFF();\r
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);\r
\r
- clear_trace();\r
+ if (clearTrace) clear_trace();\r
set_tracing(TRUE);\r
\r
for (i = 0; i < keyCount; i++) {\r
oddparity ^= (((frame[j] & 0xFF) >> k) & 0x01);
}
uint8_t parityBits = parityBytes[j>>3];
- if (protocol != ISO_14443B && isResponse && (oddparity != ((parityBits >> (7-(j&0x0007))) & 0x01))) {
+ if (protocol != ISO_14443B && (isResponse || protocol == ISO_14443A) && (oddparity != ((parityBits >> (7-(j&0x0007))) & 0x01))) {
snprintf(line[j/16]+(( j % 16) * 4),110, "%02x! ", frame[j]);
} else {
uint32_t nt = 0, nr = 0;\r
uint64_t par_list = 0, ks_list = 0, r_key = 0;\r
int16_t isOK = 0;\r
- uint8_t keyBlock[8] = {0};\r
\r
UsbCommand c = {CMD_READER_MIFARE, {true, 0, 0}};\r
\r
if (nonce2key(uid, nt, nr, par_list, ks_list, &r_key)) {\r
isOK = 2;\r
PrintAndLog("Key not found (lfsr_common_prefix list is null). Nt=%08x", nt); \r
- } else {\r
- printf("------------------------------------------------------------------\n");\r
- PrintAndLog("Key found:%012"llx" \n", r_key);\r
-\r
- num_to_bytes(r_key, 6, keyBlock);\r
- isOK = mfCheckKeys(0, 0, 1, keyBlock, &r_key);\r
- }\r
- \r
- if (!isOK) \r
- PrintAndLog("Found valid key:%012"llx, r_key);\r
- else\r
- {\r
- if (isOK != 2) PrintAndLog("Found invalid key. "); \r
PrintAndLog("Failing is expected to happen in 25%% of all cases. Trying again with a different reader nonce...");\r
c.arg[0] = false;\r
goto start;\r
+ } else {\r
+ isOK = 0;\r
+ printf("------------------------------------------------------------------\n");\r
+ PrintAndLog("Found valid key:%012"llx" \n", r_key);\r
}\r
\r
PrintAndLog("");\r
for (j = 0; j < 2; j++) {\r
if (e_sector[i].foundKey[j]) continue;\r
\r
- res = mfCheckKeys(FirstBlockOfSector(i), j, 6, keyBlock, &key64);\r
+ res = mfCheckKeys(FirstBlockOfSector(i), j, true, 6, keyBlock, &key64);\r
\r
if (!res) {\r
e_sector[i].Key[j] = key64;\r
uint32_t max_keys = keycnt>USB_CMD_DATA_SIZE/6?USB_CMD_DATA_SIZE/6:keycnt;\r
for (uint32_t c = 0; c < keycnt; c+=max_keys) {\r
uint32_t size = keycnt-c>max_keys?max_keys:keycnt-c;\r
- res = mfCheckKeys(b, t, size, &keyBlock[6*c], &key64);\r
+ res = mfCheckKeys(b, t, true, size, &keyBlock[6*c], &key64);\r
if (res != 1) {\r
if (!res) {\r
PrintAndLog("Found valid key:[%012"llx"]",key64);\r
crypto1_get_lfsr(statelists[0].head.slhead + i, &key64);\r
num_to_bytes(key64, 6, keyBlock);\r
key64 = 0;\r
- if (!mfCheckKeys(statelists[0].blockNo, statelists[0].keyType, 1, keyBlock, &key64)) {\r
+ if (!mfCheckKeys(statelists[0].blockNo, statelists[0].keyType, false, 1, keyBlock, &key64)) {\r
num_to_bytes(key64, 6, resultKey);\r
break;\r
}\r
return 0;\r
}\r
\r
-int mfCheckKeys (uint8_t blockNo, uint8_t keyType, uint8_t keycnt, uint8_t * keyBlock, uint64_t * key){\r
+int mfCheckKeys (uint8_t blockNo, uint8_t keyType, bool clear_trace, uint8_t keycnt, uint8_t * keyBlock, uint64_t * key){\r
\r
*key = 0;\r
\r
- UsbCommand c = {CMD_MIFARE_CHKKEYS, {blockNo, keyType, keycnt}};\r
+ UsbCommand c = {CMD_MIFARE_CHKKEYS, {((blockNo & 0xff) | ((keyType&0xff)<<8)), clear_trace, keycnt}};\r
memcpy(c.d.asBytes, keyBlock, 6 * keycnt);\r
SendCommand(&c);\r
\r
extern char logHexFileName[FILE_PATH_SIZE];\r
\r
int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t * key, uint8_t trgBlockNo, uint8_t trgKeyType, uint8_t * ResultKeys, bool calibrate);\r
-int mfCheckKeys (uint8_t blockNo, uint8_t keyType, uint8_t keycnt, uint8_t * keyBlock, uint64_t * key);\r
+int mfCheckKeys (uint8_t blockNo, uint8_t keyType, bool clear_trace, uint8_t keycnt, uint8_t * keyBlock, uint64_t * key);\r
\r
int mfEmlGetMem(uint8_t *data, int blockNum, int blocksCount);\r
int mfEmlSetMem(uint8_t *data, int blockNum, int blocksCount);\r
key64 = *(last_keylist + i);
num_to_bytes(key64, 6, keyBlock);
key64 = 0;
- if (!mfCheckKeys(0, 0, 1, keyBlock, &key64)) {
+ if (!mfCheckKeys(0, 0, false, 1, keyBlock, &key64)) {
*key = key64;
free(last_keylist);
last_keylist = NULL;
while not core.ukbhit() do
local result = core.WaitForResponseTimeout(cmds.CMD_ACK,1000)
if result then
- -- Unpacking the three arg-parameters
- local count,cmd,isOK = bin.unpack('LL',result)
- if isOK ~= 1 then return nil, "Error occurred" end
+ --[[
+ I don't understand, they cmd and args are defined as uint32_t, however,
+ looking at the returned data, they all look like 64-bit things:
+
+ print("result", bin.unpack("HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH", result))
+
+ FF 00 00 00 00 00 00 00 <-- 64 bits of data
+ FE FF FF FF 00 00 00 00 <-- 64 bits of data
+ 00 00 00 00 00 00 00 00 <-- 64 bits of data
+ 00 00 00 00 00 00 00 00 <-- 64 bits of data
+ 04 7F 12 E2 00 <-- this is where 'data' starts
+
+ So below I use LI to pick out the "FEFF FFFF", don't know why it works..
+ --]]
+ -- Unpacking the arg-parameters
+ local count,cmd,isOK = bin.unpack('LI',result)
+ --print("response", isOK)--FF FF FF FF
+ if isOK == 0xFFFFFFFF then
+ return nil, "Button pressed. Aborted."
+ elseif isOK == 0xFFFFFFFE then
+ return nil, "Card is not vulnerable to Darkside attack (doesn't send NACK on authentication requests). You can try 'script run mfkeys' or 'hf mf chk' to test various known keys."
+ elseif isOK == 0xFFFFFFFD then
+ return nil, "Card is not vulnerable to Darkside attack (its random number generator is not predictable). You can try 'script run mfkeys' or 'hf mf chk' to test various known keys."
+ elseif isOK ~= 1 then
+ return nil, "Error occurred"
+ end
-- The data-part is left