mirror of
https://github.com/Proxmark/proxmark3.git
synced 2025-08-20 05:13:22 -07:00
reworking magic cheneese card wipe (#365)
Implement hf mf cwipe. Remove wipe parameter from hf mf csetuid.
This commit is contained in:
parent
08b7cd17a5
commit
3a05a1e739
11 changed files with 382 additions and 119 deletions
169
client/cmdhfmf.c
169
client/cmdhfmf.c
|
@ -1783,65 +1783,69 @@ int CmdHF14AMfEKeyPrn(const char *Cmd)
|
|||
|
||||
int CmdHF14AMfCSetUID(const char *Cmd)
|
||||
{
|
||||
uint8_t wipeCard = 0;
|
||||
uint8_t uid[8] = {0x00};
|
||||
uint8_t oldUid[8] = {0x00};
|
||||
uint8_t atqa[2] = {0x00};
|
||||
uint8_t sak[1] = {0x00};
|
||||
uint8_t atqaPresent = 1;
|
||||
uint8_t atqaPresent = 0;
|
||||
int res;
|
||||
char ctmp;
|
||||
int argi=0;
|
||||
|
||||
if (strlen(Cmd) < 1 || param_getchar(Cmd, argi) == 'h') {
|
||||
PrintAndLog("Usage: hf mf csetuid <UID 8 hex symbols> [ATQA 4 hex symbols SAK 2 hex symbols] [w]");
|
||||
PrintAndLog("sample: hf mf csetuid 01020304");
|
||||
PrintAndLog("sample: hf mf csetuid 01020304 0004 08 w");
|
||||
PrintAndLog("Set UID, ATQA, and SAK for magic Chinese card (only works with such cards)");
|
||||
PrintAndLog("If you also want to wipe the card then add 'w' at the end of the command line.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (param_getchar(Cmd, argi) && param_gethex(Cmd, argi, uid, 8)) {
|
||||
uint8_t needHelp = 0;
|
||||
char cmdp = 1;
|
||||
|
||||
if (param_getchar(Cmd, 0) && param_gethex(Cmd, 0, uid, 8)) {
|
||||
PrintAndLog("UID must include 8 HEX symbols");
|
||||
return 1;
|
||||
}
|
||||
argi++;
|
||||
|
||||
ctmp = param_getchar(Cmd, argi);
|
||||
if (ctmp == 'w' || ctmp == 'W') {
|
||||
wipeCard = 1;
|
||||
atqaPresent = 0;
|
||||
}
|
||||
|
||||
if (atqaPresent) {
|
||||
if (param_getchar(Cmd, argi)) {
|
||||
if (param_gethex(Cmd, argi, atqa, 4)) {
|
||||
PrintAndLog("ATQA must include 4 HEX symbols");
|
||||
return 1;
|
||||
}
|
||||
argi++;
|
||||
if (!param_getchar(Cmd, argi) || param_gethex(Cmd, argi, sak, 2)) {
|
||||
PrintAndLog("SAK must include 2 HEX symbols");
|
||||
return 1;
|
||||
}
|
||||
argi++;
|
||||
} else
|
||||
atqaPresent = 0;
|
||||
}
|
||||
|
||||
if(!wipeCard) {
|
||||
ctmp = param_getchar(Cmd, argi);
|
||||
if (ctmp == 'w' || ctmp == 'W') {
|
||||
wipeCard = 1;
|
||||
if (param_getlength(Cmd, 1) > 1 && param_getlength(Cmd, 2) > 1) {
|
||||
atqaPresent = 1;
|
||||
cmdp = 3;
|
||||
|
||||
if (param_gethex(Cmd, 1, atqa, 4)) {
|
||||
PrintAndLog("ATQA must include 4 HEX symbols");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (param_gethex(Cmd, 2, sak, 2)) {
|
||||
PrintAndLog("SAK must include 2 HEX symbols");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
PrintAndLog("--wipe card:%s uid:%s", (wipeCard)?"YES":"NO", sprint_hex(uid, 4));
|
||||
while(param_getchar(Cmd, cmdp) != 0x00)
|
||||
{
|
||||
switch(param_getchar(Cmd, cmdp))
|
||||
{
|
||||
case 'h':
|
||||
case 'H':
|
||||
needHelp = 1;
|
||||
break;
|
||||
default:
|
||||
PrintAndLog("ERROR: Unknown parameter '%c'", param_getchar(Cmd, cmdp));
|
||||
needHelp = 1;
|
||||
break;
|
||||
}
|
||||
cmdp++;
|
||||
}
|
||||
|
||||
res = mfCSetUID(uid, (atqaPresent)?atqa:NULL, (atqaPresent)?sak:NULL, oldUid, wipeCard);
|
||||
if (strlen(Cmd) < 1 || needHelp) {
|
||||
PrintAndLog("");
|
||||
PrintAndLog("Usage: hf mf csetuid <UID 8 hex symbols> [ATQA 4 hex symbols SAK 2 hex symbols]");
|
||||
PrintAndLog("sample: hf mf csetuid 01020304");
|
||||
PrintAndLog("sample: hf mf csetuid 01020304 0004 08");
|
||||
PrintAndLog("Set UID, ATQA, and SAK for magic Chinese card (only works with such cards)");
|
||||
return 0;
|
||||
}
|
||||
|
||||
PrintAndLog("uid:%s", sprint_hex(uid, 4));
|
||||
if (atqaPresent) {
|
||||
PrintAndLog("--atqa:%s sak:%02x", sprint_hex(atqa, 2), sak[0]);
|
||||
}
|
||||
|
||||
res = mfCSetUID(uid, (atqaPresent)?atqa:NULL, (atqaPresent)?sak:NULL, oldUid);
|
||||
if (res) {
|
||||
PrintAndLog("Can't set UID. error=%d", res);
|
||||
PrintAndLog("Can't set UID. Error=%d", res);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -1850,6 +1854,80 @@ int CmdHF14AMfCSetUID(const char *Cmd)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int ParamGetCardSize(const char c) {
|
||||
int numBlocks = 16 * 4;
|
||||
switch (c) {
|
||||
case '0' : numBlocks = 5 * 4; break;
|
||||
case '2' : numBlocks = 32 * 4; break;
|
||||
case '4' : numBlocks = 32 * 4 + 8 * 16; break;
|
||||
default: numBlocks = 16 * 4;
|
||||
}
|
||||
return numBlocks;
|
||||
}
|
||||
|
||||
int CmdHF14AMfCWipe(const char *Cmd)
|
||||
{
|
||||
int res, gen = 0;
|
||||
int numBlocks = 16 * 4;
|
||||
bool wipeCard = false;
|
||||
bool fillCard = false;
|
||||
|
||||
if (strlen(Cmd) < 1 || param_getchar(Cmd, 0) == 'h') {
|
||||
PrintAndLog("Usage: hf mf cwipe [card size] [w] [p]");
|
||||
PrintAndLog("sample: hf mf cwipe 1 w s");
|
||||
PrintAndLog("[card size]: 0 = 320 bytes (Mifare Mini), 1 = 1K (default), 2 = 2K, 4 = 4K");
|
||||
PrintAndLog("w - Wipe magic Chinese card (only works with gen:1a cards)");
|
||||
PrintAndLog("f - Fill the card with default data and keys (works with gen:1a and gen:1b cards only)");
|
||||
return 0;
|
||||
}
|
||||
|
||||
gen = mfCIdentify();
|
||||
if ((gen != 1) && (gen != 2))
|
||||
return 1;
|
||||
|
||||
numBlocks = ParamGetCardSize(param_getchar(Cmd, 0));
|
||||
|
||||
char cmdp = 0;
|
||||
while(param_getchar(Cmd, cmdp) != 0x00){
|
||||
switch(param_getchar(Cmd, cmdp)) {
|
||||
case 'w':
|
||||
case 'W':
|
||||
wipeCard = 1;
|
||||
break;
|
||||
case 'f':
|
||||
case 'F':
|
||||
fillCard = 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
cmdp++;
|
||||
}
|
||||
|
||||
if (!wipeCard && !fillCard)
|
||||
wipeCard = TRUE;
|
||||
|
||||
PrintAndLog("--blocks count:%2d wipe:%c fill:%c", numBlocks, (wipeCard)?'y':'n', (fillCard)?'y':'n');
|
||||
|
||||
if (gen == 2) {
|
||||
/* generation 1b magic card */
|
||||
if (wipeCard) {
|
||||
PrintAndLog("WARNING: can't wipe magic card 1b generation");
|
||||
}
|
||||
res = mfCWipe(numBlocks, true, false, fillCard);
|
||||
} else {
|
||||
/* generation 1a magic card by default */
|
||||
res = mfCWipe(numBlocks, false, wipeCard, fillCard);
|
||||
}
|
||||
|
||||
if (res) {
|
||||
PrintAndLog("Can't wipe. error=%d", res);
|
||||
return 1;
|
||||
}
|
||||
PrintAndLog("OK");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CmdHF14AMfCSetBlk(const char *Cmd)
|
||||
{
|
||||
uint8_t memBlock[16] = {0x00};
|
||||
|
@ -1866,6 +1944,8 @@ int CmdHF14AMfCSetBlk(const char *Cmd)
|
|||
}
|
||||
|
||||
gen = mfCIdentify();
|
||||
if ((gen != 1) && (gen != 2))
|
||||
return 1;
|
||||
|
||||
blockNo = param_get8(Cmd, 0);
|
||||
|
||||
|
@ -2398,6 +2478,7 @@ static command_t CommandTable[] =
|
|||
{"esave", CmdHF14AMfESave, 0, "Save to file emul dump"},
|
||||
{"ecfill", CmdHF14AMfECFill, 0, "Fill simulator memory with help of keys from simulator"},
|
||||
{"ekeyprn", CmdHF14AMfEKeyPrn, 0, "Print keys from simulator memory"},
|
||||
{"cwipe", CmdHF14AMfCWipe, 0, "Wipe magic Chinese card"},
|
||||
{"csetuid", CmdHF14AMfCSetUID, 0, "Set UID for magic Chinese card"},
|
||||
{"csetblk", CmdHF14AMfCSetBlk, 0, "Write block - Magic Chinese card"},
|
||||
{"cgetblk", CmdHF14AMfCGetBlk, 0, "Read block - Magic Chinese card"},
|
||||
|
|
|
@ -34,6 +34,7 @@ extern int CmdHF14AMfELoad(const char* cmd);
|
|||
extern int CmdHF14AMfESave(const char* cmd);
|
||||
extern int CmdHF14AMfECFill(const char* cmd);
|
||||
extern int CmdHF14AMfEKeyPrn(const char* cmd);
|
||||
extern int CmdHF14AMfCWipe(const char* cmd);
|
||||
extern int CmdHF14AMfCSetUID(const char* cmd);
|
||||
extern int CmdHF14AMfCSetBlk(const char* cmd);
|
||||
extern int CmdHF14AMfCGetBlk(const char* cmd);
|
||||
|
|
|
@ -396,7 +396,8 @@ int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo,
|
|||
int mfEmlGetMem(uint8_t *data, int blockNum, int blocksCount) {
|
||||
UsbCommand c = {CMD_MIFARE_EML_MEMGET, {blockNum, blocksCount, 0}};
|
||||
SendCommand(&c);
|
||||
UsbCommand resp;
|
||||
|
||||
UsbCommand resp;
|
||||
if (!WaitForResponseTimeout(CMD_ACK,&resp,1500)) return 1;
|
||||
memcpy(data, resp.d.asBytes, blocksCount * 16);
|
||||
return 0;
|
||||
|
@ -416,6 +417,7 @@ int mfCGetBlock(uint8_t blockNo, uint8_t *data, uint8_t params) {
|
|||
|
||||
UsbCommand c = {CMD_MIFARE_CGETBLOCK, {params, 0, blockNo}};
|
||||
SendCommand(&c);
|
||||
|
||||
UsbCommand resp;
|
||||
if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
|
||||
isOK = resp.arg[0] & 0xff;
|
||||
|
@ -434,8 +436,9 @@ int mfCSetBlock(uint8_t blockNo, uint8_t *data, uint8_t *uid, bool wantWipe, uin
|
|||
UsbCommand c = {CMD_MIFARE_CSETBLOCK, {wantWipe, params & (0xFE | (uid == NULL ? 0:1)), blockNo}};
|
||||
memcpy(c.d.asBytes, data, 16);
|
||||
SendCommand(&c);
|
||||
|
||||
UsbCommand resp;
|
||||
if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
|
||||
if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
|
||||
isOK = resp.arg[0] & 0xff;
|
||||
if (uid != NULL)
|
||||
memcpy(uid, resp.d.asBytes, 4);
|
||||
|
@ -445,25 +448,40 @@ int mfCSetBlock(uint8_t blockNo, uint8_t *data, uint8_t *uid, bool wantWipe, uin
|
|||
PrintAndLog("Command execute timeout");
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mfCSetUID(uint8_t *uid, uint8_t *atqa, uint8_t *sak, uint8_t *oldUID, bool wantWipe) {
|
||||
int mfCWipe(uint32_t numSectors, bool gen1b, bool wantWipe, bool wantFill) {
|
||||
uint8_t isOK = 0;
|
||||
uint8_t cmdParams = wantWipe + wantFill * 0x02 + gen1b * 0x04;
|
||||
UsbCommand c = {CMD_MIFARE_CWIPE, {numSectors, cmdParams, 0}};
|
||||
SendCommand(&c);
|
||||
|
||||
UsbCommand resp;
|
||||
WaitForResponse(CMD_ACK,&resp);
|
||||
isOK = resp.arg[0] & 0xff;
|
||||
|
||||
return isOK;
|
||||
}
|
||||
|
||||
int mfCSetUID(uint8_t *uid, uint8_t *atqa, uint8_t *sak, uint8_t *oldUID) {
|
||||
uint8_t oldblock0[16] = {0x00};
|
||||
uint8_t block0[16] = {0x00};
|
||||
int old, gen = 0;
|
||||
int gen = 0, res;
|
||||
|
||||
gen = mfCIdentify();
|
||||
|
||||
/* generation 1a magic card by default */
|
||||
uint8_t cmdParams = CSETBLOCK_SINGLE_OPER;
|
||||
if (gen == 2) {
|
||||
/* generation 1b magic card */
|
||||
old = mfCGetBlock(0, oldblock0, CSETBLOCK_SINGLE_OPER | CSETBLOCK_MAGIC_1B);
|
||||
} else {
|
||||
/* generation 1a magic card by default */
|
||||
old = mfCGetBlock(0, oldblock0, CSETBLOCK_SINGLE_OPER);
|
||||
cmdParams = CSETBLOCK_SINGLE_OPER | CSETBLOCK_MAGIC_1B;
|
||||
}
|
||||
|
||||
res = mfCGetBlock(0, oldblock0, cmdParams);
|
||||
|
||||
if (old == 0) {
|
||||
if (res == 0) {
|
||||
memcpy(block0, oldblock0, 16);
|
||||
PrintAndLog("old block 0: %s", sprint_hex(block0,16));
|
||||
} else {
|
||||
|
@ -474,25 +492,73 @@ int mfCSetUID(uint8_t *uid, uint8_t *atqa, uint8_t *sak, uint8_t *oldUID, bool w
|
|||
// UID
|
||||
memcpy(block0, uid, 4);
|
||||
// Mifare UID BCC
|
||||
block0[4] = block0[0]^block0[1]^block0[2]^block0[3];
|
||||
block0[4] = block0[0] ^ block0[1] ^ block0[2] ^ block0[3];
|
||||
// mifare classic SAK(byte 5) and ATQA(byte 6 and 7, reversed)
|
||||
if (sak!=NULL)
|
||||
block0[5]=sak[0];
|
||||
if (atqa!=NULL) {
|
||||
block0[6]=atqa[1];
|
||||
block0[7]=atqa[0];
|
||||
if (sak != NULL)
|
||||
block0[5] = sak[0];
|
||||
if (atqa != NULL) {
|
||||
block0[6] = atqa[1];
|
||||
block0[7] = atqa[0];
|
||||
}
|
||||
PrintAndLog("new block 0: %s", sprint_hex(block0,16));
|
||||
PrintAndLog("new block 0: %s", sprint_hex(block0, 16));
|
||||
|
||||
if (gen == 2) {
|
||||
/* generation 1b magic card */
|
||||
return mfCSetBlock(0, block0, oldUID, wantWipe, CSETBLOCK_SINGLE_OPER | CSETBLOCK_MAGIC_1B);
|
||||
} else {
|
||||
/* generation 1a magic card by default */
|
||||
return mfCSetBlock(0, block0, oldUID, wantWipe, CSETBLOCK_SINGLE_OPER);
|
||||
res = mfCSetBlock(0, block0, oldUID, false, cmdParams);
|
||||
if (res) {
|
||||
PrintAndLog("Can't set block 0. Error: %d", res);
|
||||
return res;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mfCIdentify()
|
||||
{
|
||||
UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_CONNECT | ISO14A_NO_DISCONNECT, 0, 0}};
|
||||
SendCommand(&c);
|
||||
|
||||
UsbCommand resp;
|
||||
WaitForResponse(CMD_ACK,&resp);
|
||||
|
||||
iso14a_card_select_t card;
|
||||
memcpy(&card, (iso14a_card_select_t *)resp.d.asBytes, sizeof(iso14a_card_select_t));
|
||||
|
||||
uint64_t select_status = resp.arg[0]; // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS, 3: proprietary Anticollision
|
||||
|
||||
if(select_status != 0) {
|
||||
uint8_t rats[] = { 0xE0, 0x80 }; // FSDI=8 (FSD=256), CID=0
|
||||
c.arg[0] = ISO14A_RAW | ISO14A_APPEND_CRC | ISO14A_NO_DISCONNECT;
|
||||
c.arg[1] = 2;
|
||||
c.arg[2] = 0;
|
||||
memcpy(c.d.asBytes, rats, 2);
|
||||
SendCommand(&c);
|
||||
WaitForResponse(CMD_ACK,&resp);
|
||||
}
|
||||
|
||||
c.cmd = CMD_MIFARE_CIDENT;
|
||||
c.arg[0] = 0;
|
||||
c.arg[1] = 0;
|
||||
c.arg[2] = 0;
|
||||
SendCommand(&c);
|
||||
WaitForResponse(CMD_ACK,&resp);
|
||||
|
||||
uint8_t isGeneration = resp.arg[0] & 0xff;
|
||||
switch( isGeneration ){
|
||||
case 1: PrintAndLog("Chinese magic backdoor commands (GEN 1a) detected"); break;
|
||||
case 2: PrintAndLog("Chinese magic backdoor command (GEN 1b) detected"); break;
|
||||
default: PrintAndLog("No chinese magic backdoor command detected"); break;
|
||||
}
|
||||
|
||||
// disconnect
|
||||
c.cmd = CMD_READER_ISO_14443a;
|
||||
c.arg[0] = 0;
|
||||
c.arg[1] = 0;
|
||||
c.arg[2] = 0;
|
||||
SendCommand(&c);
|
||||
|
||||
return (int) isGeneration;
|
||||
}
|
||||
|
||||
|
||||
// SNIFFER
|
||||
|
||||
// constants
|
||||
|
@ -531,7 +597,7 @@ int isBlockEmpty(int blockN) {
|
|||
}
|
||||
|
||||
int isBlockTrailer(int blockN) {
|
||||
return ((blockN & 0x03) == 0x03);
|
||||
return ((blockN & 0x03) == 0x03);
|
||||
}
|
||||
|
||||
int saveTraceCard(void) {
|
||||
|
@ -593,6 +659,7 @@ int loadTraceCard(uint8_t *tuid) {
|
|||
blockNum++;
|
||||
}
|
||||
fclose(f);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -613,6 +680,7 @@ int mfTraceInit(uint8_t *tuid, uint8_t *atqa, uint8_t sak, bool wantSaveToEmlFil
|
|||
uid = bytes_to_num(tuid + 3, 4);
|
||||
|
||||
traceState = TRACE_IDLE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -815,6 +883,8 @@ int mfTraceDecode(uint8_t *data_src, int len, bool wantSaveToEmlFile) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
// DECODING
|
||||
|
||||
int tryDecryptWord(uint32_t nt, uint32_t ar_enc, uint32_t at_enc, uint8_t *data, int len){
|
||||
/*
|
||||
uint32_t nt; // tag challenge
|
||||
|
@ -835,48 +905,3 @@ int tryDecryptWord(uint32_t nt, uint32_t ar_enc, uint32_t at_enc, uint8_t *data,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int mfCIdentify()
|
||||
{
|
||||
UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_CONNECT | ISO14A_NO_DISCONNECT, 0, 0}};
|
||||
SendCommand(&c);
|
||||
UsbCommand resp;
|
||||
WaitForResponse(CMD_ACK,&resp);
|
||||
|
||||
iso14a_card_select_t card;
|
||||
memcpy(&card, (iso14a_card_select_t *)resp.d.asBytes, sizeof(iso14a_card_select_t));
|
||||
|
||||
uint64_t select_status = resp.arg[0]; // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS, 3: proprietary Anticollision
|
||||
|
||||
if(select_status != 0) {
|
||||
uint8_t rats[] = { 0xE0, 0x80 }; // FSDI=8 (FSD=256), CID=0
|
||||
c.arg[0] = ISO14A_RAW | ISO14A_APPEND_CRC | ISO14A_NO_DISCONNECT;
|
||||
c.arg[1] = 2;
|
||||
c.arg[2] = 0;
|
||||
memcpy(c.d.asBytes, rats, 2);
|
||||
SendCommand(&c);
|
||||
WaitForResponse(CMD_ACK,&resp);
|
||||
}
|
||||
|
||||
c.cmd = CMD_MIFARE_CIDENT;
|
||||
c.arg[0] = 0;
|
||||
c.arg[1] = 0;
|
||||
c.arg[2] = 0;
|
||||
SendCommand(&c);
|
||||
WaitForResponse(CMD_ACK,&resp);
|
||||
|
||||
uint8_t isGeneration = resp.arg[0] & 0xff;
|
||||
switch( isGeneration ){
|
||||
case 1: PrintAndLog("Chinese magic backdoor commands (GEN 1a) detected"); break;
|
||||
case 2: PrintAndLog("Chinese magic backdoor command (GEN 1b) detected"); break;
|
||||
default: PrintAndLog("No chinese magic backdoor command detected"); break;
|
||||
}
|
||||
|
||||
// disconnect
|
||||
c.cmd = CMD_READER_ISO_14443a;
|
||||
c.arg[0] = 0;
|
||||
c.arg[1] = 0;
|
||||
c.arg[2] = 0;
|
||||
SendCommand(&c);
|
||||
|
||||
return (int) isGeneration;
|
||||
}
|
||||
|
|
|
@ -33,7 +33,8 @@ extern int mfCheckKeys (uint8_t blockNo, uint8_t keyType, bool clear_trace, uint
|
|||
extern int mfEmlGetMem(uint8_t *data, int blockNum, int blocksCount);
|
||||
extern int mfEmlSetMem(uint8_t *data, int blockNum, int blocksCount);
|
||||
|
||||
extern int mfCSetUID(uint8_t *uid, uint8_t *atqa, uint8_t *sak, uint8_t *oldUID, bool wantWipe);
|
||||
extern int mfCWipe(uint32_t numSectors, bool gen1b, bool wantWipe, bool wantFill);
|
||||
extern int mfCSetUID(uint8_t *uid, uint8_t *atqa, uint8_t *sak, uint8_t *oldUID);
|
||||
extern int mfCSetBlock(uint8_t blockNo, uint8_t *data, uint8_t *uid, bool wantWipe, uint8_t params);
|
||||
extern int mfCGetBlock(uint8_t blockNo, uint8_t *data, uint8_t params);
|
||||
|
||||
|
|
|
@ -322,7 +322,7 @@ char * printBits(size_t const size, void const * const ptr)
|
|||
|
||||
// -------------------------------------------------------------------------
|
||||
// line - param line
|
||||
// bg, en - symbol numbers in param line of beginning an ending parameter
|
||||
// bg, en - symbol numbers in param line of beginning and ending parameter
|
||||
// paramnum - param number (from 0)
|
||||
// -------------------------------------------------------------------------
|
||||
int param_getptr(const char *line, int *bg, int *en, int paramnum)
|
||||
|
@ -355,6 +355,15 @@ int param_getptr(const char *line, int *bg, int *en, int paramnum)
|
|||
}
|
||||
|
||||
|
||||
int param_getlength(const char *line, int paramnum)
|
||||
{
|
||||
int bg, en;
|
||||
|
||||
if (param_getptr(line, &bg, &en, paramnum)) return 0;
|
||||
|
||||
return en - bg + 1;
|
||||
}
|
||||
|
||||
char param_getchar(const char *line, int paramnum)
|
||||
{
|
||||
int bg, en;
|
||||
|
|
|
@ -51,6 +51,7 @@ extern uint32_t SwapBits(uint32_t value, int nrbits);
|
|||
extern uint8_t *SwapEndian64(const uint8_t *src, const size_t len, const uint8_t blockSize);
|
||||
extern void SwapEndian64ex(const uint8_t *src, const size_t len, const uint8_t blockSize, uint8_t *dest);
|
||||
|
||||
extern int param_getlength(const char *line, int paramnum);
|
||||
extern char param_getchar(const char *line, int paramnum);
|
||||
extern int param_getptr(const char *line, int *bg, int *en, int paramnum);
|
||||
extern uint8_t param_get8(const char *line, int paramnum);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue