hf mfp check sketch

This commit is contained in:
merlokk 2019-11-28 00:49:12 +02:00
commit 17a2379ddd
7 changed files with 84 additions and 47 deletions

View file

@ -134,6 +134,7 @@ CORESRCS = uart_posix.c \
CMDSRCS = crapto1/crapto1.c \ CMDSRCS = crapto1/crapto1.c \
crapto1/crypto1.c \ crapto1/crypto1.c \
mifare/mifaredefault.c \
mifare/mfkey.c \ mifare/mfkey.c \
tea.c \ tea.c \
fido/additional_ca.c \ fido/additional_ca.c \

View file

@ -551,30 +551,29 @@ int CmdHF14ASniff(const char *Cmd) {
return PM3_SUCCESS; return PM3_SUCCESS;
} }
int ExchangeRAW14a(uint8_t *datain, int datainlen, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen) { int ExchangeRAW14a(uint8_t *datain, int datainlen, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen, bool silentMode) {
static uint8_t responseNum = 0; static uint8_t responseNum = 0;
uint16_t cmdc = 0; uint16_t cmdc = 0;
*dataoutlen = 0; *dataoutlen = 0;
if (activateField) { if (activateField) {
responseNum = 1;
PacketResponseNG resp; PacketResponseNG resp;
// Anticollision + SELECT card // Anticollision + SELECT card
SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT | ISO14A_NO_DISCONNECT, 0, 0, NULL, 0); SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT | ISO14A_NO_DISCONNECT, 0, 0, NULL, 0);
if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
PrintAndLogEx(ERR, "Proxmark3 connection timeout."); if (!silentMode) PrintAndLogEx(ERR, "Proxmark3 connection timeout.");
return 1; return 1;
} }
// check result // check result
if (resp.oldarg[0] == 0) { if (resp.oldarg[0] == 0) {
PrintAndLogEx(ERR, "No card in field."); if (!silentMode) PrintAndLogEx(ERR, "No card in field.");
return 1; return 1;
} }
if (resp.oldarg[0] != 1 && resp.oldarg[0] != 2) { if (resp.oldarg[0] != 1 && resp.oldarg[0] != 2) {
PrintAndLogEx(ERR, "Card not in iso14443-4. res=%" PRId64 ".", resp.oldarg[0]); if (!silentMode) PrintAndLogEx(ERR, "Card not in iso14443-4. res=%" PRId64 ".", resp.oldarg[0]);
return 1; return 1;
} }
@ -583,12 +582,12 @@ int ExchangeRAW14a(uint8_t *datain, int datainlen, bool activateField, bool leav
uint8_t rats[] = { 0xE0, 0x80 }; // FSDI=8 (FSD=256), CID=0 uint8_t rats[] = { 0xE0, 0x80 }; // FSDI=8 (FSD=256), CID=0
SendCommandOLD(CMD_HF_ISO14443A_READER, ISO14A_RAW | ISO14A_APPEND_CRC | ISO14A_NO_DISCONNECT, 2, 0, rats, 2); SendCommandOLD(CMD_HF_ISO14443A_READER, ISO14A_RAW | ISO14A_APPEND_CRC | ISO14A_NO_DISCONNECT, 2, 0, rats, 2);
if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
PrintAndLogEx(ERR, "Proxmark3 connection timeout."); if (!silentMode) PrintAndLogEx(ERR, "Proxmark3 connection timeout.");
return 1; return 1;
} }
if (resp.oldarg[0] == 0) { // ats_len if (resp.oldarg[0] == 0) { // ats_len
PrintAndLogEx(ERR, "Can't get ATS."); if (!silentMode) PrintAndLogEx(ERR, "Can't get ATS.");
return 1; return 1;
} }
} }
@ -610,7 +609,7 @@ int ExchangeRAW14a(uint8_t *datain, int datainlen, bool activateField, bool leav
int iLen = resp.oldarg[0]; int iLen = resp.oldarg[0];
if (!iLen) { if (!iLen) {
PrintAndLogEx(ERR, "No card response."); if (!silentMode) PrintAndLogEx(ERR, "No card response.");
return 1; return 1;
} }
@ -619,12 +618,12 @@ int ExchangeRAW14a(uint8_t *datain, int datainlen, bool activateField, bool leav
*dataoutlen = 0; *dataoutlen = 0;
if (maxdataoutlen && *dataoutlen > maxdataoutlen) { if (maxdataoutlen && *dataoutlen > maxdataoutlen) {
PrintAndLogEx(ERR, "Buffer too small(%d). Needs %d bytes", *dataoutlen, maxdataoutlen); if (!silentMode) PrintAndLogEx(ERR, "Buffer too small(%d). Needs %d bytes", *dataoutlen, maxdataoutlen);
return 2; return 2;
} }
if (recv[0] != data[0]) { if (recv[0] != data[0]) {
PrintAndLogEx(ERR, "iso14443-4 framing error. Card send %2x must be %2x", dataout[0], data[0]); if (!silentMode) PrintAndLogEx(ERR, "iso14443-4 framing error. Card send %2x must be %2x", dataout[0], data[0]);
return 2; return 2;
} }
@ -632,12 +631,12 @@ int ExchangeRAW14a(uint8_t *datain, int datainlen, bool activateField, bool leav
// CRC Check // CRC Check
if (iLen == -1) { if (iLen == -1) {
PrintAndLogEx(ERR, "ISO 14443A CRC error."); if (!silentMode) PrintAndLogEx(ERR, "ISO 14443A CRC error.");
return 3; return 3;
} }
} else { } else {
PrintAndLogEx(ERR, "Reply timeout."); if (!silentMode) PrintAndLogEx(ERR, "Reply timeout.");
return 4; return 4;
} }

View file

@ -30,6 +30,6 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search);
const char *getTagInfo(uint8_t uid); const char *getTagInfo(uint8_t uid);
int Hf14443_4aGetCardData(iso14a_card_select_t *card); int Hf14443_4aGetCardData(iso14a_card_select_t *card);
int ExchangeAPDU14a(uint8_t *datain, int datainlen, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen); int ExchangeAPDU14a(uint8_t *datain, int datainlen, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen);
int ExchangeRAW14a(uint8_t *datain, int datainlen, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen); int ExchangeRAW14a(uint8_t *datain, int datainlen, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen, bool silentMode);
#endif #endif

View file

@ -4211,7 +4211,7 @@ static int CmdHF14AMfAuth4(const char *Cmd) {
return PM3_ESOFT; return PM3_ESOFT;
} }
return MifareAuth4(NULL, keyn, key, true, false, true); return MifareAuth4(NULL, keyn, key, true, false, true, true, false);
} }
// https://www.nxp.com/docs/en/application-note/AN10787.pdf // https://www.nxp.com/docs/en/application-note/AN10787.pdf

View file

@ -88,7 +88,7 @@ static int CmdHFMFPInfo(const char *cmd) {
int datalen = 0; int datalen = 0;
// https://github.com/Proxmark/proxmark3/blob/master/client/luascripts/mifarePlus.lua#L161 // https://github.com/Proxmark/proxmark3/blob/master/client/luascripts/mifarePlus.lua#L161
uint8_t cmd[3 + 16] = {0xa8, 0x90, 0x90, 0x00}; uint8_t cmd[3 + 16] = {0xa8, 0x90, 0x90, 0x00};
int res = ExchangeRAW14a(cmd, sizeof(cmd), false, false, data, sizeof(data), &datalen); int res = ExchangeRAW14a(cmd, sizeof(cmd), false, false, data, sizeof(data), &datalen, false);
if (!res && datalen > 1 && data[0] == 0x09) { if (!res && datalen > 1 && data[0] == 0x09) {
SLmode = 0; SLmode = 0;
} }
@ -105,7 +105,7 @@ static int CmdHFMFPInfo(const char *cmd) {
DropField(); DropField();
return 0; return PM3_SUCCESS;
} }
static int CmdHFMFPWritePerso(const char *cmd) { static int CmdHFMFPWritePerso(const char *cmd) {
@ -169,7 +169,7 @@ static int CmdHFMFPWritePerso(const char *cmd) {
} }
PrintAndLogEx(INFO, "Write OK."); PrintAndLogEx(INFO, "Write OK.");
return 0; return PM3_SUCCESS;
} }
uint16_t CardAddresses[] = {0x9000, 0x9001, 0x9002, 0x9003, 0x9004, 0xA000, 0xA001, 0xA080, 0xA081, 0xC000, 0xC001}; uint16_t CardAddresses[] = {0x9000, 0x9001, 0x9002, 0x9003, 0x9004, 0xA000, 0xA001, 0xA080, 0xA081, 0xC000, 0xC001};
@ -245,7 +245,7 @@ static int CmdHFMFPInitPerso(const char *cmd) {
PrintAndLogEx(INFO, "Done."); PrintAndLogEx(INFO, "Done.");
return 0; return PM3_SUCCESS;
} }
static int CmdHFMFPCommitPerso(const char *cmd) { static int CmdHFMFPCommitPerso(const char *cmd) {
@ -286,7 +286,7 @@ static int CmdHFMFPCommitPerso(const char *cmd) {
} }
PrintAndLogEx(INFO, "Switch level OK."); PrintAndLogEx(INFO, "Switch level OK.");
return 0; return PM3_SUCCESS;
} }
static int CmdHFMFPAuth(const char *cmd) { static int CmdHFMFPAuth(const char *cmd) {
@ -324,7 +324,7 @@ static int CmdHFMFPAuth(const char *cmd) {
return 1; return 1;
} }
return MifareAuth4(NULL, keyn, key, true, false, verbose); return MifareAuth4(NULL, keyn, key, true, false, true, verbose, false);
} }
static int CmdHFMFPRdbl(const char *cmd) { static int CmdHFMFPRdbl(const char *cmd) {
@ -392,7 +392,7 @@ static int CmdHFMFPRdbl(const char *cmd) {
PrintAndLogEx(INFO, "--block:%d sector[%d]:%02x key:%04x", blockn, mfNumBlocksPerSector(sectorNum), sectorNum, uKeyNum); PrintAndLogEx(INFO, "--block:%d sector[%d]:%02x key:%04x", blockn, mfNumBlocksPerSector(sectorNum), sectorNum, uKeyNum);
mf4Session mf4session; mf4Session mf4session;
int res = MifareAuth4(&mf4session, keyn, key, true, true, verbose); int res = MifareAuth4(&mf4session, keyn, key, true, true, true, verbose, false);
if (res) { if (res) {
PrintAndLogEx(ERR, "Authentication error: %d", res); PrintAndLogEx(ERR, "Authentication error: %d", res);
return res; return res;
@ -491,7 +491,7 @@ static int CmdHFMFPRdsc(const char *cmd) {
PrintAndLogEx(INFO, "--sector[%d]:%02x key:%04x", mfNumBlocksPerSector(sectorNum), sectorNum, uKeyNum); PrintAndLogEx(INFO, "--sector[%d]:%02x key:%04x", mfNumBlocksPerSector(sectorNum), sectorNum, uKeyNum);
mf4Session mf4session; mf4Session mf4session;
int res = MifareAuth4(&mf4session, keyn, key, true, true, verbose); int res = MifareAuth4(&mf4session, keyn, key, true, true, true, verbose, false);
if (res) { if (res) {
PrintAndLogEx(ERR, "Authentication error: %d", res); PrintAndLogEx(ERR, "Authentication error: %d", res);
return res; return res;
@ -532,7 +532,7 @@ static int CmdHFMFPRdsc(const char *cmd) {
} }
DropField(); DropField();
return 0; return PM3_SUCCESS;
} }
static int CmdHFMFPWrbl(const char *cmd) { static int CmdHFMFPWrbl(const char *cmd) {
@ -595,7 +595,7 @@ static int CmdHFMFPWrbl(const char *cmd) {
PrintAndLogEx(INFO, "--block:%d sector[%d]:%02x key:%04x", blockNum & 0xff, mfNumBlocksPerSector(sectorNum), sectorNum, uKeyNum); PrintAndLogEx(INFO, "--block:%d sector[%d]:%02x key:%04x", blockNum & 0xff, mfNumBlocksPerSector(sectorNum), sectorNum, uKeyNum);
mf4Session mf4session; mf4Session mf4session;
int res = MifareAuth4(&mf4session, keyn, key, true, true, verbose); int res = MifareAuth4(&mf4session, keyn, key, true, true, true, verbose, false);
if (res) { if (res) {
PrintAndLogEx(ERR, "Authentication error: %d", res); PrintAndLogEx(ERR, "Authentication error: %d", res);
return res; return res;
@ -634,7 +634,40 @@ static int CmdHFMFPWrbl(const char *cmd) {
DropField(); DropField();
PrintAndLogEx(INFO, "Write OK."); PrintAndLogEx(INFO, "Write OK.");
return 0; return PM3_SUCCESS;
}
static int CmdHFMFPChk() {
int res;
bool selectCard = true;
uint8_t startSector = 0;
uint8_t endSector = 0;
uint8_t startKeyAB = 0;
uint8_t endKeyAB = 0;
uint8_t keyn[2] = {0};
uint8_t key[16] = {0};
// sector number from 0
for (uint8_t sector = startSector; sector <= endSector; sector++) {
// 0-keyA 1-keyB
for(uint8_t keyAB = startKeyAB; keyAB <= endKeyAB; keyAB++) {
// main cycle with key check
for (int i = 0; i < g_mifare_plus_default_keys_len; i++) {
uint16_t uKeyNum = 0x4000 + sector * 2 + keyAB;
keyn[0] = uKeyNum >> 8;
keyn[1] = uKeyNum & 0xff;
res = MifareAuth4(NULL, keyn, key, selectCard, true, false, false, true);
selectCard = false;
PrintAndLogEx(WARNING, "sector %d key %d [%s] res: %d", sector, key, g_mifare_plus_default_keys[i], res);
}
}
}
DropField();
return PM3_SUCCESS;
} }
static int CmdHFMFPMAD(const char *cmd) { static int CmdHFMFPMAD(const char *cmd) {
@ -728,7 +761,7 @@ static int CmdHFMFPMAD(const char *cmd) {
} }
} }
return 0; return PM3_SUCCESS;
} }
static int CmdHFMFPNDEF(const char *cmd) { static int CmdHFMFPNDEF(const char *cmd) {
@ -832,7 +865,7 @@ static int CmdHFMFPNDEF(const char *cmd) {
NDEFDecodeAndPrint(data, datalen, verbose); NDEFDecodeAndPrint(data, datalen, verbose);
return 0; return PM3_SUCCESS;
} }
static command_t CommandTable[] = { static command_t CommandTable[] = {
@ -845,6 +878,7 @@ static command_t CommandTable[] = {
{"rdbl", CmdHFMFPRdbl, IfPm3Iso14443a, "Read blocks"}, {"rdbl", CmdHFMFPRdbl, IfPm3Iso14443a, "Read blocks"},
{"rdsc", CmdHFMFPRdsc, IfPm3Iso14443a, "Read sectors"}, {"rdsc", CmdHFMFPRdsc, IfPm3Iso14443a, "Read sectors"},
{"wrbl", CmdHFMFPWrbl, IfPm3Iso14443a, "Write blocks"}, {"wrbl", CmdHFMFPWrbl, IfPm3Iso14443a, "Write blocks"},
{"chk", CmdHFMFPChk, IfPm3Iso14443a, "Check keys"},
{"mad", CmdHFMFPMAD, IfPm3Iso14443a, "Checks and prints MAD"}, {"mad", CmdHFMFPMAD, IfPm3Iso14443a, "Checks and prints MAD"},
{"ndef", CmdHFMFPNDEF, IfPm3Iso14443a, "Prints NDEF records from card"}, {"ndef", CmdHFMFPNDEF, IfPm3Iso14443a, "Prints NDEF records from card"},
{NULL, NULL, 0, NULL} {NULL, NULL, 0, NULL}
@ -853,7 +887,7 @@ static command_t CommandTable[] = {
static int CmdHelp(const char *Cmd) { static int CmdHelp(const char *Cmd) {
(void)Cmd; // Cmd is not used so far (void)Cmd; // Cmd is not used so far
CmdsHelp(CommandTable); CmdsHelp(CommandTable);
return 0; return PM3_SUCCESS;
} }
int CmdHFMFP(const char *Cmd) { int CmdHFMFP(const char *Cmd) {

View file

@ -168,21 +168,24 @@ int CalculateMAC(mf4Session *session, MACType_t mtype, uint8_t blockNum, uint8_t
return aes_cmac8(NULL, session->Kmac, macdata, mac, macdatalen); return aes_cmac8(NULL, session->Kmac, macdata, mac, macdatalen);
} }
int MifareAuth4(mf4Session *session, uint8_t *keyn, uint8_t *key, bool activateField, bool leaveSignalON, bool verbose) { int MifareAuth4(mf4Session *session, uint8_t *keyn, uint8_t *key, bool activateField, bool leaveSignalON, bool dropFieldIfError, bool verbose, bool silentMode) {
uint8_t data[257] = {0}; uint8_t data[257] = {0};
int datalen = 0; int datalen = 0;
uint8_t RndA[17] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00}; uint8_t RndA[17] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00};
uint8_t RndB[17] = {0}; uint8_t RndB[17] = {0};
if (silentMode)
verbose = false;
if (session) if (session)
session->Authenticated = false; session->Authenticated = false;
uint8_t cmd1[] = {0x70, keyn[1], keyn[0], 0x00}; uint8_t cmd1[] = {0x70, keyn[1], keyn[0], 0x00};
int res = ExchangeRAW14a(cmd1, sizeof(cmd1), activateField, true, data, sizeof(data), &datalen); int res = ExchangeRAW14a(cmd1, sizeof(cmd1), activateField, true, data, sizeof(data), &datalen, silentMode);
if (res) { if (res) {
PrintAndLogEx(ERR, "Exchande raw error: %d", res); if (!silentMode) PrintAndLogEx(ERR, "Exchande raw error: %d", res);
DropField(); if (dropFieldIfError) DropField();
return 2; return 2;
} }
@ -190,20 +193,20 @@ int MifareAuth4(mf4Session *session, uint8_t *keyn, uint8_t *key, bool activateF
PrintAndLogEx(INFO, "<phase1: %s", sprint_hex(data, datalen)); PrintAndLogEx(INFO, "<phase1: %s", sprint_hex(data, datalen));
if (datalen < 1) { if (datalen < 1) {
PrintAndLogEx(ERR, "Card response wrong length: %d", datalen); if (!silentMode) PrintAndLogEx(ERR, "Card response wrong length: %d", datalen);
DropField(); if (dropFieldIfError) DropField();
return 3; return 3;
} }
if (data[0] != 0x90) { if (data[0] != 0x90) {
PrintAndLogEx(ERR, "Card response error: %02x", data[2]); if (!silentMode) PrintAndLogEx(ERR, "Card response error: %02x", data[2]);
DropField(); if (dropFieldIfError) DropField();
return 3; return 3;
} }
if (datalen != 19) { // code 1b + 16b + crc 2b if (datalen != 19) { // code 1b + 16b + crc 2b
PrintAndLogEx(ERR, "Card response must be 19 bytes long instead of: %d", datalen); if (!silentMode) PrintAndLogEx(ERR, "Card response must be 19 bytes long instead of: %d", datalen);
DropField(); if (dropFieldIfError) DropField();
return 3; return 3;
} }
@ -223,10 +226,10 @@ int MifareAuth4(mf4Session *session, uint8_t *keyn, uint8_t *key, bool activateF
if (verbose) if (verbose)
PrintAndLogEx(INFO, ">phase2: %s", sprint_hex(cmd2, 33)); PrintAndLogEx(INFO, ">phase2: %s", sprint_hex(cmd2, 33));
res = ExchangeRAW14a(cmd2, sizeof(cmd2), false, true, data, sizeof(data), &datalen); res = ExchangeRAW14a(cmd2, sizeof(cmd2), false, true, data, sizeof(data), &datalen, silentMode);
if (res) { if (res) {
PrintAndLogEx(ERR, "Exchande raw error: %d", res); if (!silentMode) PrintAndLogEx(ERR, "Exchande raw error: %d", res);
DropField(); if (dropFieldIfError) DropField();
return 4; return 4;
} }
@ -241,12 +244,12 @@ int MifareAuth4(mf4Session *session, uint8_t *keyn, uint8_t *key, bool activateF
} }
if (memcmp(&raw[4], &RndA[1], 16)) { if (memcmp(&raw[4], &RndA[1], 16)) {
PrintAndLogEx(ERR, "\nAuthentication FAILED. rnd not equal"); if (!silentMode) PrintAndLogEx(ERR, "\nAuthentication FAILED. rnd is not equal");
if (verbose) { if (verbose) {
PrintAndLogEx(ERR, "RndA reader: %s", sprint_hex(&RndA[1], 16)); PrintAndLogEx(ERR, "RndA reader: %s", sprint_hex(&RndA[1], 16));
PrintAndLogEx(ERR, "RndA card: %s", sprint_hex(&raw[4], 16)); PrintAndLogEx(ERR, "RndA card: %s", sprint_hex(&raw[4], 16));
} }
DropField(); if (dropFieldIfError) DropField();
return 5; return 5;
} }
@ -311,7 +314,7 @@ static int intExchangeRAW14aPlus(uint8_t *datain, int datainlen, bool activateFi
if (VerboseMode) if (VerboseMode)
PrintAndLogEx(INFO, ">>> %s", sprint_hex(datain, datainlen)); PrintAndLogEx(INFO, ">>> %s", sprint_hex(datain, datainlen));
int res = ExchangeRAW14a(datain, datainlen, activateField, leaveSignalON, dataout, maxdataoutlen, dataoutlen); int res = ExchangeRAW14a(datain, datainlen, activateField, leaveSignalON, dataout, maxdataoutlen, dataoutlen, false);
if (VerboseMode) if (VerboseMode)
PrintAndLogEx(INFO, "<<< %s", sprint_hex(dataout, *dataoutlen)); PrintAndLogEx(INFO, "<<< %s", sprint_hex(dataout, *dataoutlen));
@ -380,7 +383,7 @@ int mfpReadSector(uint8_t sectorNo, uint8_t keyType, uint8_t *key, uint8_t *data
PrintAndLogEx(INFO, "--sector[%d]:%02x key:%04x", mfNumBlocksPerSector(sectorNo), sectorNo, uKeyNum); PrintAndLogEx(INFO, "--sector[%d]:%02x key:%04x", mfNumBlocksPerSector(sectorNo), sectorNo, uKeyNum);
mf4Session session; mf4Session session;
int res = MifareAuth4(&session, keyn, key, true, true, verbose); int res = MifareAuth4(&session, keyn, key, true, true, true, verbose, false);
if (res) { if (res) {
PrintAndLogEx(ERR, "Sector %d authentication error: %d", sectorNo, res); PrintAndLogEx(ERR, "Sector %d authentication error: %d", sectorNo, res);
return res; return res;

View file

@ -45,7 +45,7 @@ void mfpSetVerboseMode(bool verbose);
const char *mfpGetErrorDescription(uint8_t errorCode); const char *mfpGetErrorDescription(uint8_t errorCode);
int CalculateMAC(mf4Session *session, MACType_t mtype, uint8_t blockNum, uint8_t blockCount, uint8_t *data, int datalen, uint8_t *mac, bool verbose); int CalculateMAC(mf4Session *session, MACType_t mtype, uint8_t blockNum, uint8_t blockCount, uint8_t *data, int datalen, uint8_t *mac, bool verbose);
int MifareAuth4(mf4Session *session, uint8_t *keyn, uint8_t *key, bool activateField, bool leaveSignalON, bool verbose); int MifareAuth4(mf4Session *session, uint8_t *keyn, uint8_t *key, bool activateField, bool leaveSignalON, bool dropFieldIfError, bool verbose, bool silentMode);
int MFPWritePerso(uint8_t *keyNum, uint8_t *key, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen); int MFPWritePerso(uint8_t *keyNum, uint8_t *key, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen);
int MFPCommitPerso(bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen); int MFPCommitPerso(bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen);