There is a race condition when we go from iclass commands to mf command. Especially noticable when eload large files where we used to spam the device with usb packages.\ntry iclass eload, then mf eload, and you see the client hang. With this change we trigger a preload of the fpga image before we start uploading to the device. Current places I could trigger this bug was in eload and gsave. With this patch only the first call takes some time if fpga image must be loaded. The following goes fast.\n\n if you find that the client hangs when going between, this could be the root cause.

This commit is contained in:
iceman1001 2023-07-26 23:47:55 +02:00
commit fc3a518f28
7 changed files with 64 additions and 21 deletions

View file

@ -3,6 +3,9 @@ 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]
- Removed some empty dump files (@iceman1001)
- Added a fct to choose fpga mode (@iceman1001)
- Changed `hf mf eload/gsave` - fast uploading to emulator memory (@iceman1001)
- Added empty dump files with keys for easy simulation (@iceman1001)
- Added `hf 15 view` - view ISO15693 dump files (@iceman1001)
- Fixed `hf iclass config` - now loops correct in keyroll generation (@iceman1001)

View file

@ -783,6 +783,15 @@ static void PacketReceived(PacketCommandNG *packet) {
g_reply_via_usb = false;
break;
}
case CMD_SET_FPGAMODE: {
uint8_t mode = packet->data.asBytes[0];
if (mode >= FPGA_BITSTREAM_LF && mode <= FPGA_BITSTREAM_HF_15) {
FpgaDownloadAndGo(mode);
reply_ng(CMD_SET_FPGAMODE, PM3_SUCCESS, NULL, 0);
}
reply_ng(CMD_SET_FPGAMODE, PM3_EINVARG, NULL, 0);
break;
}
// emulator
case CMD_SET_DBGMODE: {
g_dbglevel = packet->data.asBytes[0];

View file

@ -36,6 +36,7 @@
#include "crypto/libpcrypto.h"
#include "wiegand_formats.h"
#include "wiegand_formatutils.h"
#include "cmdhw.h" // set_fpga_mode
static int CmdHelp(const char *Cmd);
@ -4350,6 +4351,10 @@ int CmdHF14AMfELoad(const char *Cmd) {
return PM3_SUCCESS;
}
// ICEMAN: bug. if device has been using ICLASS commands,
// the device needs to load the HF fpga image. It takes 1.5 second.
set_fpga_mode(2);
uint8_t *data = NULL;
size_t bytes_read = 0;
int res = pm3_load_dump(filename, (void **)&data, &bytes_read, (block_width * block_cnt + hdr_len));
@ -7919,6 +7924,10 @@ static int CmdHF14AGen4Save(const char *Cmd) {
bool fill_emulator = arg_get_lit(ctx, 7);
CLIParserFree(ctx);
// ICEMAN: bug. if device has been using ICLASS commands,
// the device needs to load the HF fpga image. It takes 1.5 second.
set_fpga_mode(2);
// validations
if (pwd_len != 4 && pwd_len != 0) {
PrintAndLogEx(FAILED, "Must specify 4 bytes, got " _YELLOW_("%u"), pwd_len);

View file

@ -1083,6 +1083,23 @@ static int CmdBreak(const char *Cmd) {
return PM3_SUCCESS;
}
int set_fpga_mode(uint8_t mode) {
if (mode < 1 || mode > 4) {
return PM3_EINVARG;
}
uint8_t d[] = {mode};
clearCommandBuffer();
SendCommandNG(CMD_SET_FPGAMODE, d, sizeof(d));
PacketResponseNG resp;
if (WaitForResponseTimeout(CMD_SET_FPGAMODE, &resp, 1000) == false) {
PrintAndLogEx(WARNING, "command execution timeout");
return PM3_ETIMEOUT;
}
if (resp.status != PM3_SUCCESS) {
PrintAndLogEx(ERR, "failed to set FPGA mode");
}
return resp.status;
}
static command_t CommandTable[] = {
{"-------------", CmdHelp, AlwaysAvailable, "----------------------- " _CYAN_("Hardware") " -----------------------"},

View file

@ -27,5 +27,5 @@ int CmdHW(const char *Cmd);
int handle_tearoff(tearoff_params_t *params, bool verbose);
void pm3_version(bool verbose, bool oneliner);
void pm3_version_short(void);
int set_fpga_mode(uint8_t mode);
#endif

View file

@ -873,13 +873,13 @@ out:
int mfReadSector(uint8_t sectorNo, uint8_t keyType, const uint8_t *key, uint8_t *data) {
clearCommandBuffer();
SendCommandMIX(CMD_HF_MIFARE_READSC, sectorNo, keyType, 0, (uint8_t *)key, 6);
SendCommandMIX(CMD_HF_MIFARE_READSC, sectorNo, keyType, 0, (uint8_t *)key, MIFARE_KEY_SIZE);
PacketResponseNG resp;
if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
uint8_t isOK = resp.oldarg[0] & 0xff;
uint8_t isOK = resp.oldarg[0] & 0xFF;
if (isOK) {
memcpy(data, resp.data.asBytes, mfNumBlocksPerSector(sectorNo) * 16);
memcpy(data, resp.data.asBytes, mfNumBlocksPerSector(sectorNo) * MFBLOCK_SIZE);
return PM3_SUCCESS;
} else {
return PM3_EUNDEF;
@ -902,7 +902,7 @@ int mfReadBlock(uint8_t blockNo, uint8_t keyType, const uint8_t *key, uint8_t *d
SendCommandNG(CMD_HF_MIFARE_READBL, (uint8_t *)&payload, sizeof(mf_readblock_t));
PacketResponseNG resp;
if (WaitForResponseTimeout(CMD_HF_MIFARE_READBL, &resp, 1500)) {
memcpy(data, resp.data.asBytes, 16);
memcpy(data, resp.data.asBytes, MFBLOCK_SIZE);
if (resp.status != PM3_SUCCESS) {
PrintAndLogEx(DEBUG, "failed reading block");
@ -918,7 +918,7 @@ int mfReadBlock(uint8_t blockNo, uint8_t keyType, const uint8_t *key, uint8_t *d
// EMULATOR
int mfEmlGetMem(uint8_t *data, int blockNum, int blocksCount) {
size_t size = blocksCount * 16;
size_t size = blocksCount * MFBLOCK_SIZE;
if (size > PM3_CMD_DATA_SIZE) {
return PM3_ESOFT;
}
@ -982,7 +982,7 @@ int mfEmlSetMem_xt(uint8_t *data, int blockNum, int blocksCount, int blockBtWidt
int mfCSetUID(uint8_t *uid, uint8_t uidlen, const uint8_t *atqa, const uint8_t *sak, uint8_t *old_uid, uint8_t *verifed_uid, uint8_t wipecard) {
uint8_t params = MAGIC_SINGLE;
uint8_t block0[16];
uint8_t block0[MFBLOCK_SIZE];
memset(block0, 0x00, sizeof(block0));
int res = mfCGetBlock(0, block0, params);
@ -1045,11 +1045,11 @@ int mfCSetUID(uint8_t *uid, uint8_t uidlen, const uint8_t *atqa, const uint8_t *
}
int mfCWipe(uint8_t *uid, const uint8_t *atqa, const uint8_t *sak) {
uint8_t block0[16] = {0x00, 0x56, 0x78, 0xBB, 0x95, 0x08, 0x04, 0x00, 0x02, 0xB2, 0x1E, 0x24, 0x23, 0x27, 0x1E, 0x1D};
// uint8_t block0[16] = {0x04, 0x03, 0x02, 0x01, 0x04, 0x08, 0x04, 0x00, 0x64, 0xB9, 0x95, 0x11, 0x4D, 0x20, 0x42, 0x09};
uint8_t blockD[16] = {0x00};
uint8_t block0[MFBLOCK_SIZE] = {0x00, 0x56, 0x78, 0xBB, 0x95, 0x08, 0x04, 0x00, 0x02, 0xB2, 0x1E, 0x24, 0x23, 0x27, 0x1E, 0x1D};
// uint8_t block0[MFBLOCK_SIZE] = {0x04, 0x03, 0x02, 0x01, 0x04, 0x08, 0x04, 0x00, 0x64, 0xB9, 0x95, 0x11, 0x4D, 0x20, 0x42, 0x09};
uint8_t blockD[MFBLOCK_SIZE] = {0x00};
// default transport ACL
uint8_t blockK[16] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x80, 0x69, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
uint8_t blockK[MFBLOCK_SIZE] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x80, 0x69, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
uint8_t params = MAGIC_SINGLE;
if (uid != NULL) {
@ -1095,16 +1095,18 @@ int mfCWipe(uint8_t *uid, const uint8_t *atqa, const uint8_t *sak) {
}
int mfCSetBlock(uint8_t blockNo, uint8_t *data, uint8_t *uid, uint8_t params) {
clearCommandBuffer();
SendCommandMIX(CMD_HF_MIFARE_CSETBL, params, blockNo, 0, data, 16);
SendCommandMIX(CMD_HF_MIFARE_CSETBL, params, blockNo, 0, data, MFBLOCK_SIZE);
PacketResponseNG resp;
if (WaitForResponseTimeout(CMD_ACK, &resp, 3500)) {
uint8_t isOK = resp.oldarg[0] & 0xff;
if (uid != NULL)
if (uid != NULL) {
memcpy(uid, resp.data.asBytes, 4);
if (!isOK)
}
if (!isOK) {
return PM3_EUNDEF;
}
} else {
PrintAndLogEx(WARNING, "command execute timeout");
return PM3_ETIMEOUT;
@ -1118,9 +1120,10 @@ int mfCGetBlock(uint8_t blockNo, uint8_t *data, uint8_t params) {
PacketResponseNG resp;
if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
uint8_t isOK = resp.oldarg[0] & 0xff;
if (!isOK)
if (!isOK) {
return PM3_EUNDEF;
memcpy(data, resp.data.asBytes, 16);
}
memcpy(data, resp.data.asBytes, MFBLOCK_SIZE);
} else {
PrintAndLogEx(WARNING, "command execute timeout");
return PM3_ETIMEOUT;
@ -1145,11 +1148,11 @@ int mfGen3UID(uint8_t *uid, uint8_t uidlen, uint8_t *oldUid) {
int mfGen3Block(uint8_t *block, int blockLen, uint8_t *newBlock) {
clearCommandBuffer();
SendCommandMIX(CMD_HF_MIFARE_GEN3BLK, blockLen, 0, 0, block, 16);
SendCommandMIX(CMD_HF_MIFARE_GEN3BLK, blockLen, 0, 0, block, MFBLOCK_SIZE);
PacketResponseNG resp;
if (WaitForResponseTimeout(CMD_HF_MIFARE_GEN3BLK, &resp, 3500)) {
if (resp.status == PM3_SUCCESS && newBlock) {
memcpy(newBlock, resp.data.asBytes, 16);
memcpy(newBlock, resp.data.asBytes, MFBLOCK_SIZE);
}
return resp.status;
} else {
@ -1187,7 +1190,7 @@ int mfG4GetBlock(uint8_t *pwd, uint8_t blockno, uint8_t *data, uint8_t workFlags
if (resp.status != PM3_SUCCESS) {
return PM3_EUNDEF;
}
memcpy(data, resp.data.asBytes, 16);
memcpy(data, resp.data.asBytes, MFBLOCK_SIZE);
} else {
PrintAndLogEx(WARNING, "command execute timeout");
return PM3_ETIMEOUT;
@ -1199,7 +1202,7 @@ int mfG4SetBlock(uint8_t *pwd, uint8_t blockno, uint8_t *data, uint8_t workFlags
struct p {
uint8_t blockno;
uint8_t pwd[4];
uint8_t data[16];
uint8_t data[MFBLOCK_SIZE];
uint8_t workFlags;
} PACKED payload;
payload.blockno = blockno;

View file

@ -416,6 +416,8 @@ typedef struct {
#define CMD_SPIFFS_WIPE 0x013A
#define CMD_SET_FPGAMODE 0x013F
// This take a +0x2000 as they are high level helper and special functions
// As the others, they may have safety level argument if it makes sense
#define CMD_SPIFFS_PRINT_TREE 0x2130