diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 230e69eb0..92e9f82f0 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -1237,6 +1237,10 @@ static void PacketReceived(PacketCommandNG *packet) { MifareUWriteBlock(packet->oldarg[0], packet->oldarg[1], packet->data.asBytes); break; } + case CMD_HF_MIFAREU_WRITEBL_COMPAT: { + MifareUWriteBlockCompat(packet->oldarg[0], packet->oldarg[1], packet->data.asBytes); + break; + } case CMD_HF_MIFARE_ACQ_ENCRYPTED_NONCES: { MifareAcquireEncryptedNonces(packet->oldarg[0], packet->oldarg[1], packet->oldarg[2], packet->data.asBytes); break; diff --git a/armsrc/mifarecmd.c b/armsrc/mifarecmd.c index 4cd4eee67..9a4a7e984 100644 --- a/armsrc/mifarecmd.c +++ b/armsrc/mifarecmd.c @@ -554,6 +554,75 @@ void MifareUWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain) { set_tracing(false); } +// Arg0 : Block to write to. +// Arg1 : 0 = use no authentication. +// 1 = use 0x1A authentication. +// 2 = use 0x1B authentication. +// datain : 16 first bytes is data to be written. +// : 4/16 next bytes is authentication key. +void MifareUWriteBlockCompat(uint8_t arg0, uint8_t arg1, uint8_t *datain) { + uint8_t blockNo = arg0; + bool useKey = (arg1 == 1); //UL_C + bool usePwd = (arg1 == 2); //UL_EV1/NTAG + uint8_t blockdata[16] = {0x00}; + + memcpy(blockdata, datain, 16); + + LEDsoff(); + LED_A_ON(); + iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); + + clear_trace(); + set_tracing(true); + + if (!iso14443a_select_card(NULL, NULL, NULL, true, 0, true)) { + if (DBGLEVEL >= DBG_ERROR) Dbprintf("Can't select card"); + OnError(0); + return; + }; + + // UL-C authentication + if (useKey) { + uint8_t key[16] = {0x00}; + memcpy(key, datain + 16, sizeof(key)); + + if (!mifare_ultra_auth(key)) { + OnError(1); + return; + } + } + + // UL-EV1 / NTAG authentication + if (usePwd) { + uint8_t pwd[4] = {0x00}; + memcpy(pwd, datain + 16, 4); + uint8_t pack[4] = {0, 0, 0, 0}; + if (!mifare_ul_ev1_auth(pwd, pack)) { + OnError(1); + return; + } + } + + if (mifare_ultra_writeblock_compat(blockNo, blockdata)) { + if (DBGLEVEL >= DBG_ERROR) Dbprintf("Write block error"); + OnError(0); + return; + }; + + if (mifare_ultra_halt()) { + if (DBGLEVEL >= DBG_ERROR) Dbprintf("Halt error"); + OnError(0); + return; + }; + + if (DBGLEVEL >= 2) DbpString("WRITE BLOCK FINISHED"); + + reply_mix(CMD_ACK, 1, 0, 0, 0, 0); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LEDsoff(); + set_tracing(false); +} + void MifareUSetPwd(uint8_t arg0, uint8_t *datain) { uint8_t pwd[16] = {0x00}; diff --git a/armsrc/mifarecmd.h b/armsrc/mifarecmd.h index 4adceb4db..b024d2d1b 100644 --- a/armsrc/mifarecmd.h +++ b/armsrc/mifarecmd.h @@ -20,7 +20,7 @@ void MifareUC_Auth(uint8_t arg0, uint8_t *keybytes); void MifareUReadCard(uint8_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain); void MifareReadSector(uint8_t arg0, uint8_t arg1, uint8_t *datain); void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain); -//void MifareUWriteBlockCompat(uint8_t arg0,uint8_t *datain); +void MifareUWriteBlockCompat(uint8_t arg0, uint8_t arg1, uint8_t *datain); void MifareUWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain); void MifareNested(uint8_t blockNo, uint8_t keyType, uint8_t targetBlockNo, uint8_t targetKeyType, bool calibrate, uint8_t *key); diff --git a/armsrc/mifareutil.c b/armsrc/mifareutil.c index 6f2629ba6..5d8989ef8 100644 --- a/armsrc/mifareutil.c +++ b/armsrc/mifareutil.c @@ -446,37 +446,37 @@ int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t bl return 0; } -/* // command not needed, but left for future testing int mifare_ultra_writeblock_compat(uint8_t blockNo, uint8_t *blockData) { - uint16_t len; - uint8_t par[3] = {0}; // enough for 18 parity bits - uint8_t d_block[18] = {0x00}; - uint8_t receivedAnswer[MAX_FRAME_SIZE]; - uint8_t receivedAnswerPar[MAX_PARITY_SIZE]; + // variables + uint16_t len = 0; + + uint8_t d_block[18]; + uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0x00}; + uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE] = {0x00}; len = mifare_sendcmd_short(NULL, CRYPT_NONE, ISO14443A_CMD_WRITEBLOCK, blockNo, receivedAnswer, receivedAnswerPar, NULL); - if ((len != 1) || (receivedAnswer[0] != 0x0A)) { // 0x0a - ACK + if (receivedAnswer[0] != 0x0A) { // 0x0a - ACK if (DBGLEVEL >= DBG_ERROR) - Dbprintf("Cmd Addr Error: %02x", receivedAnswer[0]); + Dbprintf("Cmd Send Error: %02x %d", receivedAnswer[0], len); return 1; } memcpy(d_block, blockData, 16); AddCrc14A(d_block, 16); - ReaderTransmitPar(d_block, sizeof(d_block), par, NULL); + ReaderTransmit(d_block, sizeof(d_block), NULL); + // Receive the response len = ReaderReceive(receivedAnswer, receivedAnswerPar); - if ((len != 1) || (receivedAnswer[0] != 0x0A)) { // 0x0a - ACK + if (receivedAnswer[0] != 0x0A) { // 0x0a - ACK if (DBGLEVEL >= DBG_ERROR) - Dbprintf("Cmd Data Error: %02x %d", receivedAnswer[0],len); + Dbprintf("Cmd Send Data Error: %02x %d", receivedAnswer[0], len); return 2; } return 0; } -*/ int mifare_ultra_writeblock(uint8_t blockNo, uint8_t *blockData) { uint16_t len = 0; diff --git a/armsrc/mifareutil.h b/armsrc/mifareutil.h index b1d6396d5..d444dc81f 100644 --- a/armsrc/mifareutil.h +++ b/armsrc/mifareutil.h @@ -73,7 +73,7 @@ int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t bl int mifare_ul_ev1_auth(uint8_t *keybytes, uint8_t *pack); int mifare_ultra_auth(uint8_t *keybytes); int mifare_ultra_readblock(uint8_t blockNo, uint8_t *blockData); -//int mifare_ultra_writeblock_compat(uint8_t blockNo, uint8_t *blockData); +int mifare_ultra_writeblock_compat(uint8_t blockNo, uint8_t *blockData); int mifare_ultra_writeblock(uint8_t blockNo, uint8_t *blockData); int mifare_ultra_halt(void); diff --git a/client/src/cmdhfmfu.c b/client/src/cmdhfmfu.c index 4634b181b..524faa9ce 100644 --- a/client/src/cmdhfmfu.c +++ b/client/src/cmdhfmfu.c @@ -1474,8 +1474,9 @@ static int CmdHF14AMfUWrBl(const char *Cmd) { uint8_t cmdp = 0; uint8_t keylen = 0; - uint8_t blockdata[20] = {0x00}; + uint8_t blockdata[16] = {0x00}; uint8_t data[16] = {0x00}; + uint8_t datalen = 4; uint8_t authenticationkey[16] = {0x00}; uint8_t *authKeyPtr = authenticationkey; @@ -1517,9 +1518,13 @@ static int CmdHF14AMfUWrBl(const char *Cmd) { break; case 'd': if (param_gethex(Cmd, cmdp + 1, blockdata, 8)) { - PrintAndLogEx(WARNING, "Block data must include 8 HEX symbols"); - errors = true; - break; + if (param_gethex(Cmd, cmdp + 1, blockdata, 32)) { + PrintAndLogEx(WARNING, "Block data must include 8 or 32 HEX symbols"); + errors = true; + break; + } else { + datalen = 16; + } } cmdp += 2; break; @@ -1559,9 +1564,8 @@ static int CmdHF14AMfUWrBl(const char *Cmd) { PrintAndLogEx(NORMAL, "Block: %0d (0x%02X) [ %s]", blockNo, blockNo, sprint_hex(blockdata, 4)); //Send write Block - uint8_t cmddata[20]; - memcpy(cmddata, blockdata, 4); - uint8_t datalen = 4; + uint8_t cmddata[32]; + memcpy(cmddata, blockdata, datalen); uint8_t keytype = 0; if (hasAuthKey) { keytype = 1; @@ -1574,7 +1578,13 @@ static int CmdHF14AMfUWrBl(const char *Cmd) { } clearCommandBuffer(); - SendCommandMIX(CMD_HF_MIFAREU_WRITEBL, blockNo, keytype, 0, cmddata, datalen); + if (datalen == 16) { + SendCommandMIX(CMD_HF_MIFAREU_WRITEBL_COMPAT, blockNo, keytype, 0, cmddata, datalen); + } + else + { + SendCommandMIX(CMD_HF_MIFAREU_WRITEBL, blockNo, keytype, 0, cmddata, datalen); + } PacketResponseNG resp; if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { uint8_t isOK = resp.oldarg[0] & 0xff; diff --git a/include/pm3_cmd.h b/include/pm3_cmd.h index 58e527f40..dd11d49d5 100644 --- a/include/pm3_cmd.h +++ b/include/pm3_cmd.h @@ -618,6 +618,7 @@ typedef struct { #define CMD_HF_MIFAREU_READCARD 0x0721 #define CMD_HF_MIFARE_WRITEBL 0x0622 #define CMD_HF_MIFAREU_WRITEBL 0x0722 +#define CMD_HF_MIFAREU_WRITEBL_COMPAT 0x0723 #define CMD_HF_MIFARE_CHKKEYS 0x0623 #define CMD_HF_MIFARE_SETMOD 0x0624