From: pwpiwi Date: Thu, 22 Aug 2019 05:53:17 +0000 (+0200) Subject: add: 'hf mf personalize' (personalize UID on Mifare Classic EV1 7byte UID cards) X-Git-Url: http://cvs.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/commitdiff_plain/0b4efbdef20ccf33ba7b5f6dbe36ab80cfe5477a?hp=--cc add: 'hf mf personalize' (personalize UID on Mifare Classic EV1 7byte UID cards) * add/use some #defines * whitespace fixes * #include refactoring * add line to CHANGELOG.md --- 0b4efbdef20ccf33ba7b5f6dbe36ab80cfe5477a diff --git a/CHANGELOG.md b/CHANGELOG.md index 5210edbc..e95ccde6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -42,6 +42,7 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac - Added downlink reference mode option r [ 0 - (or missing) default/fixed bit, 1 - long leading, 2 - leading 0 and 3 - 1 of 4 ] to `lf t55xx detect`, `lf t55xx read`, `lf t55xx write`, and `lf t55xx bruteforce` - Added special option `r 4` to bruteforce, to try all downlink modes (0,1,2 and 3) for each password - `hf mfu info` now checks the NXP Originality Signature if availabe (piwi) +- Added `hf mf personalize` to personalize the UID option of Mifare Classic EV1 cards (piwi) ## [v3.1.0][2018-10-10] diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 9b9acb6f..f5f3c237 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -28,6 +28,7 @@ #include "iso15693.h" #include "lfsampling.h" #include "BigBuf.h" +#include "mifarecmd.h" #include "mifareutil.h" #include "mifaresim.h" #include "pcf7931.h" @@ -1242,6 +1243,9 @@ void UsbPacketReceived(uint8_t *packet, int len) case CMD_MIFARE_WRITEBL: MifareWriteBlock(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); break; + case CMD_MIFARE_PERSONALIZE_UID: + MifarePersonalizeUID(c->arg[0], c->arg[1], c->d.asBytes); + break; //case CMD_MIFAREU_WRITEBL_COMPAT: //MifareUWriteBlockCompat(c->arg[0], c->d.asBytes); //break; diff --git a/armsrc/apps.h b/armsrc/apps.h index 4d9a1482..ae5e3977 100644 --- a/armsrc/apps.h +++ b/armsrc/apps.h @@ -108,41 +108,14 @@ void RAMFUNC SniffMifare(uint8_t param); void EPA_PACE_Collect_Nonce(UsbCommand * c); void EPA_PACE_Replay(UsbCommand *c); -// mifarecmd.h -void MifareReadBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *data); -void MifareUReadBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain); -void MifareUC_Auth(uint8_t arg0, uint8_t *datain); -void MifareUReadCard(uint8_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain); -void MifareReadSector(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain); -void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain); -//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 MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags, uint8_t *datain); -void MifareChkKeys(uint16_t arg0, uint16_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); -void MifareEMemSet(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain); -void MifareEMemGet(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain); -void MifareECardLoad(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain); -void MifareCWipe(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain); // Work with "magic Chinese" card -void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain); -void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain); -void MifareCIdent(); // is "magic chinese" card? -void MifareUSetPwd(uint8_t arg0, uint8_t *datain); - -//desfire -void Mifare_DES_Auth1(uint8_t arg0,uint8_t *datain); -void Mifare_DES_Auth2(uint32_t arg0, uint8_t *datain); - // mifaredesfire.h -bool InitDesfireCard(); -void MifareSendCommand(uint8_t arg0,uint8_t arg1, uint8_t *datain); -void MifareDesfireGetInformation(); -void MifareDES_Auth1(uint8_t arg0,uint8_t arg1,uint8_t arg2, uint8_t *datain); -void ReaderMifareDES(uint32_t param, uint32_t param2, uint8_t * datain); -int DesfireAPDU(uint8_t *cmd, size_t cmd_len, uint8_t *dataout); -size_t CreateAPDU( uint8_t *datain, size_t len, uint8_t *dataout); +bool InitDesfireCard(); +void MifareSendCommand(uint8_t arg0,uint8_t arg1, uint8_t *datain); +void MifareDesfireGetInformation(); +void MifareDES_Auth1(uint8_t arg0,uint8_t arg1,uint8_t arg2, uint8_t *datain); +void ReaderMifareDES(uint32_t param, uint32_t param2, uint8_t * datain); +int DesfireAPDU(uint8_t *cmd, size_t cmd_len, uint8_t *dataout); +size_t CreateAPDU( uint8_t *datain, size_t len, uint8_t *dataout); /// iclass.h @@ -157,7 +130,7 @@ void iClass_ReadBlk(uint8_t blockNo); bool iClass_ReadBlock(uint8_t blockNo, uint8_t *readdata); void iClass_Dump(uint8_t blockno, uint8_t numblks); void iClass_Clone(uint8_t startblock, uint8_t endblock, uint8_t *data); -void iClass_ReadCheck(uint8_t blockNo, uint8_t keyType); +void iClass_ReadCheck(uint8_t blockNo, uint8_t keyType); // cmd.h bool cmd_receive(UsbCommand* cmd); diff --git a/armsrc/mifarecmd.c b/armsrc/mifarecmd.c index 8fe502ca..bed2f076 100644 --- a/armsrc/mifarecmd.c +++ b/armsrc/mifarecmd.c @@ -15,13 +15,23 @@ #include "mifarecmd.h" +#include + +#include "proxmark3.h" +#include "cmd.h" +#include "crapto1/crapto1.h" +#include "iso14443a.h" +#include "BigBuf.h" +#include "mifareutil.h" +#include "apps.h" +#include "protocols.h" #include "util.h" #include "parity.h" #include "crc.h" #include "fpgaloader.h" -#define HARDNESTED_AUTHENTICATION_TIMEOUT 848 // card times out 1ms after wrong authentication (according to NXP documentation) -#define HARDNESTED_PRE_AUTHENTICATION_LEADTIME 400 // some (non standard) cards need a pause after select before they are ready for first authentication +#define HARDNESTED_AUTHENTICATION_TIMEOUT 848 // card times out 1ms after wrong authentication (according to NXP documentation) +#define HARDNESTED_PRE_AUTHENTICATION_LEADTIME 400 // some (non standard) cards need a pause after select before they are ready for first authentication /* // the block number for the ISO14443-4 PCB @@ -73,22 +83,22 @@ void MifareReadBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) while (true) { if(!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) { - if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card"); + if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card"); break; }; if(mifare_classic_auth(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST)) { - if (MF_DBGLEVEL >= 1) Dbprintf("Auth error"); + if (MF_DBGLEVEL >= 1) Dbprintf("Auth error"); break; }; if(mifare_classic_readblock(pcs, cuid, blockNo, dataoutbuf)) { - if (MF_DBGLEVEL >= 1) Dbprintf("Read block error"); + if (MF_DBGLEVEL >= 1) Dbprintf("Read block error"); break; }; if(mifare_classic_halt(pcs, cuid)) { - if (MF_DBGLEVEL >= 1) Dbprintf("Halt error"); + if (MF_DBGLEVEL >= 1) Dbprintf("Halt error"); break; }; @@ -99,7 +109,7 @@ void MifareReadBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) // ----------------------------- crypto1 destroy crypto1_destroy(pcs); - if (MF_DBGLEVEL >= 2) DbpString("READ BLOCK FINISHED"); + if (MF_DBGLEVEL >= 2) DbpString("READ BLOCK FINISHED"); LED_B_ON(); cmd_send(CMD_ACK,isOK,0,0,dataoutbuf,16); @@ -230,25 +240,25 @@ void MifareReadSector(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) isOK = 1; if(!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) { isOK = 0; - if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card"); + if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card"); } if(isOK && mifare_classic_auth(pcs, cuid, FirstBlockOfSector(sectorNo), keyType, ui64Key, AUTH_FIRST)) { isOK = 0; - if (MF_DBGLEVEL >= 1) Dbprintf("Auth error"); + if (MF_DBGLEVEL >= 1) Dbprintf("Auth error"); } for (uint8_t blockNo = 0; isOK && blockNo < NumBlocksPerSector(sectorNo); blockNo++) { if(mifare_classic_readblock(pcs, cuid, FirstBlockOfSector(sectorNo) + blockNo, dataoutbuf + 16 * blockNo)) { isOK = 0; - if (MF_DBGLEVEL >= 1) Dbprintf("Read sector %2d block %2d error", sectorNo, blockNo); + if (MF_DBGLEVEL >= 1) Dbprintf("Read sector %2d block %2d error", sectorNo, blockNo); break; } } if(mifare_classic_halt(pcs, cuid)) { - if (MF_DBGLEVEL >= 1) Dbprintf("Halt error"); + if (MF_DBGLEVEL >= 1) Dbprintf("Halt error"); } // ----------------------------- crypto1 destroy @@ -393,22 +403,22 @@ void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) while (true) { if(!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) { - if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card"); + if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card"); break; }; if(mifare_classic_auth(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST)) { - if (MF_DBGLEVEL >= 1) Dbprintf("Auth error"); + if (MF_DBGLEVEL >= 1) Dbprintf("Auth error"); break; }; if(mifare_classic_writeblock(pcs, cuid, blockNo, blockdata)) { - if (MF_DBGLEVEL >= 1) Dbprintf("Write block error"); + if (MF_DBGLEVEL >= 1) Dbprintf("Write block error"); break; }; if(mifare_classic_halt(pcs, cuid)) { - if (MF_DBGLEVEL >= 1) Dbprintf("Halt error"); + if (MF_DBGLEVEL >= 1) Dbprintf("Halt error"); break; }; @@ -419,7 +429,7 @@ void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) // ----------------------------- crypto1 destroy crypto1_destroy(pcs); - if (MF_DBGLEVEL >= 2) DbpString("WRITE BLOCK FINISHED"); + if (MF_DBGLEVEL >= 2) DbpString("WRITE BLOCK FINISHED"); LED_B_ON(); cmd_send(CMD_ACK,isOK,0,0,0,0); @@ -455,7 +465,7 @@ void MifareUWriteBlockCompat(uint8_t arg0, uint8_t *datain) if(mifare_ultra_writeblock_compat(blockNo, blockdata)) { if (MF_DBGLEVEL >= 1) Dbprintf("Write block error"); OnError(0); - return; }; + return; }; if(mifare_ultra_halt()) { if (MF_DBGLEVEL >= 1) Dbprintf("Halt error"); @@ -672,7 +682,7 @@ void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags, if (!have_uid) { // need a full select cycle to get the uid first iso14a_card_select_t card_info; if(!iso14443a_select_card(uid, &card_info, &cuid, true, 0, true)) { - if (MF_DBGLEVEL >= 1) Dbprintf("AcquireNonces: Can't select card (ALL)"); + if (MF_DBGLEVEL >= 1) Dbprintf("AcquireNonces: Can't select card (ALL)"); continue; } switch (card_info.uidlen) { @@ -684,7 +694,7 @@ void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags, have_uid = true; } else { // no need for anticollision. We can directly select the card if(!iso14443a_select_card(uid, NULL, NULL, false, cascade_levels, true)) { - if (MF_DBGLEVEL >= 1) Dbprintf("AcquireNonces: Can't select card (UID)"); + if (MF_DBGLEVEL >= 1) Dbprintf("AcquireNonces: Can't select card (UID)"); continue; } } @@ -696,14 +706,14 @@ void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags, uint32_t nt1; if (mifare_classic_authex(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST, &nt1, NULL)) { - if (MF_DBGLEVEL >= 1) Dbprintf("AcquireNonces: Auth1 error"); + if (MF_DBGLEVEL >= 1) Dbprintf("AcquireNonces: Auth1 error"); continue; } // nested authentication uint16_t len = mifare_sendcmd_short(pcs, AUTH_NESTED, 0x60 + (targetKeyType & 0x01), targetBlockNo, receivedAnswer, par_enc, NULL); if (len != 4) { - if (MF_DBGLEVEL >= 1) Dbprintf("AcquireNonces: Auth2 error len=%d", len); + if (MF_DBGLEVEL >= 1) Dbprintf("AcquireNonces: Auth2 error len=%d", len); continue; } @@ -712,7 +722,7 @@ void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags, ReaderTransmit(dummy_answer, 1, NULL); timeout = GetCountSspClk() + HARDNESTED_AUTHENTICATION_TIMEOUT; - + num_nonces++; if (num_nonces % 2) { memcpy(buf+i, receivedAnswer, 4); @@ -737,7 +747,7 @@ void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags, cmd_send(CMD_ACK, isOK, cuid, num_nonces, buf, sizeof(buf)); LED_B_OFF(); - if (MF_DBGLEVEL >= 3) DbpString("AcquireEncryptedNonces finished"); + if (MF_DBGLEVEL >= 3) DbpString("AcquireEncryptedNonces finished"); if (field_off) { FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); @@ -794,7 +804,7 @@ void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *dat int16_t isOK = 0; #define NESTED_MAX_TRIES 12 uint16_t unsuccessfull_tries = 0; - if (calibrate) { // for first call only. Otherwise reuse previous calibration + if (calibrate) { // for first call only. Otherwise reuse previous calibration LED_B_ON(); WDT_HIT(); @@ -812,20 +822,20 @@ void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *dat // prepare next select. No need to power down the card. if(mifare_classic_halt(pcs, cuid)) { - if (MF_DBGLEVEL >= 1) Dbprintf("Nested: Halt error"); + if (MF_DBGLEVEL >= 1) Dbprintf("Nested: Halt error"); rtr--; continue; } if(!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) { - if (MF_DBGLEVEL >= 1) Dbprintf("Nested: Can't select card"); + if (MF_DBGLEVEL >= 1) Dbprintf("Nested: Can't select card"); rtr--; continue; }; auth1_time = 0; if(mifare_classic_authex(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST, &nt1, &auth1_time)) { - if (MF_DBGLEVEL >= 1) Dbprintf("Nested: Auth1 error"); + if (MF_DBGLEVEL >= 1) Dbprintf("Nested: Auth1 error"); rtr--; continue; }; @@ -836,12 +846,12 @@ void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *dat auth2_time = 0; } if(mifare_classic_authex(pcs, cuid, blockNo, keyType, ui64Key, AUTH_NESTED, &nt2, &auth2_time)) { - if (MF_DBGLEVEL >= 1) Dbprintf("Nested: Auth2 error"); + if (MF_DBGLEVEL >= 1) Dbprintf("Nested: Auth2 error"); rtr--; continue; }; - nttmp = prng_successor(nt1, 100); //NXP Mifare is typical around 840,but for some unlicensed/compatible mifare card this can be 160 + nttmp = prng_successor(nt1, 100); //NXP Mifare is typical around 840,but for some unlicensed/compatible mifare card this can be 160 for (i = 101; i < 1200; i++) { nttmp = prng_successor(nttmp, 1); if (nttmp == nt2) break; @@ -859,7 +869,7 @@ void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *dat if (MF_DBGLEVEL >= 3) Dbprintf("Nested: calibrating... ntdist=%d", i); } else { unsuccessfull_tries++; - if (unsuccessfull_tries > NESTED_MAX_TRIES) { // card isn't vulnerable to nested attack (random numbers are not predictable) + if (unsuccessfull_tries > NESTED_MAX_TRIES) { // card isn't vulnerable to nested attack (random numbers are not predictable) isOK = -3; } } @@ -887,18 +897,18 @@ void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *dat // prepare next select. No need to power down the card. if(mifare_classic_halt(pcs, cuid)) { - if (MF_DBGLEVEL >= 1) Dbprintf("Nested: Halt error"); + if (MF_DBGLEVEL >= 1) Dbprintf("Nested: Halt error"); continue; } if(!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) { - if (MF_DBGLEVEL >= 1) Dbprintf("Nested: Can't select card"); + if (MF_DBGLEVEL >= 1) Dbprintf("Nested: Can't select card"); continue; }; auth1_time = 0; if(mifare_classic_authex(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST, &nt1, &auth1_time)) { - if (MF_DBGLEVEL >= 1) Dbprintf("Nested: Auth1 error"); + if (MF_DBGLEVEL >= 1) Dbprintf("Nested: Auth1 error"); continue; }; @@ -906,7 +916,7 @@ void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *dat auth2_time = auth1_time + delta_time; len = mifare_sendcmd_short(pcs, AUTH_NESTED, 0x60 + (targetKeyType & 0x01), targetBlockNo, receivedAnswer, par, &auth2_time); if (len != 4) { - if (MF_DBGLEVEL >= 1) Dbprintf("Nested: Auth2 error len=%d", len); + if (MF_DBGLEVEL >= 1) Dbprintf("Nested: Auth2 error len=%d", len); continue; }; @@ -925,7 +935,7 @@ void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *dat ks1 = nt2 ^ nttest; if (valid_nonce(nttest, nt2, ks1, par_array)){ - if (ncount > 0) { // we are only interested in disambiguous nonces, try again + if (ncount > 0) { // we are only interested in disambiguous nonces, try again if (MF_DBGLEVEL >= 3) Dbprintf("Nonce#%d: dismissed (ambigous), ntdist=%d", i+1, j); target_nt[i] = 0; break; @@ -961,7 +971,7 @@ void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *dat cmd_send(CMD_ACK, isOK, 0, targetBlockNo + (targetKeyType * 0x100), buf, sizeof(buf)); LED_B_OFF(); - if (MF_DBGLEVEL >= 3) DbpString("NESTED FINISHED"); + if (MF_DBGLEVEL >= 3) DbpString("NESTED FINISHED"); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LEDsoff(); @@ -996,7 +1006,7 @@ void MifareChkKeys(uint16_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain) if (set14aTimeout){ iso14a_set_timeout(set14aTimeout * 10); // timeout: ms = x/106 35-minimum, 50-OK 106-recommended 500-safe } - + if (multisectorCheck) { TKeyIndex keyIndex = {{0}}; uint8_t sectorCnt = blockNo; @@ -1026,6 +1036,60 @@ void MifareChkKeys(uint16_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain) LED_A_OFF(); } + +//----------------------------------------------------------------------------- +// MIFARE Personalize UID. Only for Mifare Classic EV1 7Byte UID +//----------------------------------------------------------------------------- +void MifarePersonalizeUID(uint8_t keyType, uint8_t perso_option, uint8_t *data) { + + uint8_t uid[10]; + uint32_t cuid; + struct Crypto1State mpcs = {0, 0}; + struct Crypto1State *pcs; + pcs = &mpcs; + + LED_A_ON(); + clear_trace(); + + iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); + + bool isOK = false; + while (true) { + if (!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) { + if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card"); + break; + } + + uint8_t block_number = 0; + uint64_t key = bytes_to_num(data, 6); + if (mifare_classic_auth(pcs, cuid, block_number, keyType, key, AUTH_FIRST)) { + if (MF_DBGLEVEL >= 1) Dbprintf("Auth error"); + break; + } + + uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE]; + uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE]; + int len = mifare_sendcmd_short(pcs, true, MIFARE_EV1_PERSONAL_UID, perso_option, receivedAnswer, receivedAnswerPar, NULL); + if (len != 1 || receivedAnswer[0] != CARD_ACK) { + if (MF_DBGLEVEL >= 1) Dbprintf("Cmd Error: %02x", receivedAnswer[0]); + break;; + } + isOK = true; + break; + } + + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LED_D_OFF(); + + crypto1_destroy(pcs); + + if (MF_DBGLEVEL >= 2) DbpString("PERSONALIZE UID FINISHED"); + + cmd_send(CMD_ACK, isOK, 0, 0, NULL, 0); + + LED_A_OFF(); +} + //----------------------------------------------------------------------------- // MIFARE commands set debug level // @@ -1093,7 +1157,7 @@ void MifareECardLoad(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai if(!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) { isOK = false; - if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card"); + if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card"); } for (uint8_t sectorNo = 0; isOK && sectorNo < numSectors; sectorNo++) { @@ -1101,13 +1165,13 @@ void MifareECardLoad(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai if (sectorNo == 0){ if(isOK && mifare_classic_auth(pcs, cuid, FirstBlockOfSector(sectorNo), keyType, ui64Key, AUTH_FIRST)) { isOK = false; - if (MF_DBGLEVEL >= 1) Dbprintf("Sector[%2d]. Auth error", sectorNo); + if (MF_DBGLEVEL >= 1) Dbprintf("Sector[%2d]. Auth error", sectorNo); break; } } else { if(isOK && mifare_classic_auth(pcs, cuid, FirstBlockOfSector(sectorNo), keyType, ui64Key, AUTH_NESTED)) { isOK = false; - if (MF_DBGLEVEL >= 1) Dbprintf("Sector[%2d]. Auth nested error", sectorNo); + if (MF_DBGLEVEL >= 1) Dbprintf("Sector[%2d]. Auth nested error", sectorNo); break; } } @@ -1115,13 +1179,13 @@ void MifareECardLoad(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai for (uint8_t blockNo = 0; isOK && blockNo < NumBlocksPerSector(sectorNo); blockNo++) { if(isOK && mifare_classic_readblock(pcs, cuid, FirstBlockOfSector(sectorNo) + blockNo, dataoutbuf)) { isOK = false; - if (MF_DBGLEVEL >= 1) Dbprintf("Error reading sector %2d block %2d", sectorNo, blockNo); + if (MF_DBGLEVEL >= 1) Dbprintf("Error reading sector %2d block %2d", sectorNo, blockNo); break; }; if (isOK) { if (blockNo < NumBlocksPerSector(sectorNo) - 1) { emlSetMem(dataoutbuf, FirstBlockOfSector(sectorNo) + blockNo, 1); - } else { // sector trailer, keep the keys, set only the AC + } else { // sector trailer, keep the keys, set only the AC emlGetMem(dataoutbuf2, FirstBlockOfSector(sectorNo) + blockNo, 1); memcpy(&dataoutbuf2[6], &dataoutbuf[6], 4); emlSetMem(dataoutbuf2, FirstBlockOfSector(sectorNo) + blockNo, 1); @@ -1132,7 +1196,7 @@ void MifareECardLoad(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai } if(mifare_classic_halt(pcs, cuid)) { - if (MF_DBGLEVEL >= 1) Dbprintf("Halt error"); + if (MF_DBGLEVEL >= 1) Dbprintf("Halt error"); }; // ----------------------------- crypto1 destroy @@ -1173,20 +1237,20 @@ void MifareCWipe(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){ bool needWipe = cmdParams & 0x01; bool needFill = cmdParams & 0x02; bool gen1b = cmdParams & 0x04; - + uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE]; uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE]; - + uint8_t block0[16] = {0x01, 0x02, 0x03, 0x04, 0x04, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBE, 0xAF}; uint8_t block1[16] = {0x00}; uint8_t blockK[16] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x08, 0x77, 0x8F, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; uint8_t d_block[18] = {0x00}; - + // card commands uint8_t wupC1[] = { 0x40 }; uint8_t wupC2[] = { 0x43 }; uint8_t wipeC[] = { 0x41 }; - + // iso14443 setup LED_A_ON(); LED_B_OFF(); @@ -1196,54 +1260,54 @@ void MifareCWipe(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){ // tracing clear_trace(); set_tracing(true); - + while (true){ // wipe if (needWipe){ ReaderTransmitBitsPar(wupC1,7,0, NULL); - if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) { - if (MF_DBGLEVEL >= 1) Dbprintf("wupC1 error"); + if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != CARD_ACK)) { + if (MF_DBGLEVEL >= 1) Dbprintf("wupC1 error"); break; }; ReaderTransmit(wipeC, sizeof(wipeC), NULL); - if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) { - if (MF_DBGLEVEL >= 1) Dbprintf("wipeC error"); + if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != CARD_ACK)) { + if (MF_DBGLEVEL >= 1) Dbprintf("wipeC error"); break; }; if(mifare_classic_halt(NULL, 0)) { - if (MF_DBGLEVEL > 2) Dbprintf("Halt error"); + if (MF_DBGLEVEL > 2) Dbprintf("Halt error"); }; }; - + // put default data if (needFill){ // select commands ReaderTransmitBitsPar(wupC1, 7, 0, NULL); - // gen1b magic tag : do no issue wupC2 and don't expect 0x0a response after SELECT_UID (after getting UID from chip in 'hf mf csetuid' command) - if (!gen1b) { + // gen1b magic tag : do no issue wupC2 and don't expect CARD_ACK response after SELECT_UID (after getting UID from chip in 'hf mf csetuid' command) + if (!gen1b) { - if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) { - if (MF_DBGLEVEL >= 1) Dbprintf("wupC1 error"); + if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != CARD_ACK)) { + if (MF_DBGLEVEL >= 1) Dbprintf("wupC1 error"); break; }; ReaderTransmit(wupC2, sizeof(wupC2), NULL); - if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) { - if (MF_DBGLEVEL >= 1) Dbprintf("wupC2 error"); + if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != CARD_ACK)) { + if (MF_DBGLEVEL >= 1) Dbprintf("wupC2 error"); break; }; } // send blocks command for (int blockNo = 0; blockNo < numBlocks; blockNo++) { - if ((mifare_sendcmd_short(NULL, 0, 0xA0, blockNo, receivedAnswer, receivedAnswerPar, NULL) != 1) || (receivedAnswer[0] != 0x0a)) { - if (MF_DBGLEVEL >= 1) Dbprintf("write block send command error"); + if ((mifare_sendcmd_short(NULL, 0, 0xA0, blockNo, receivedAnswer, receivedAnswerPar, NULL) != 1) || (receivedAnswer[0] != CARD_ACK)) { + if (MF_DBGLEVEL >= 1) Dbprintf("write block send command error"); break; }; - + // check type of block and add crc if (!isBlockTrailer(blockNo)){ memcpy(d_block, block1, 16); @@ -1257,33 +1321,33 @@ void MifareCWipe(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){ // send write command ReaderTransmit(d_block, sizeof(d_block), NULL); - if ((ReaderReceive(receivedAnswer, receivedAnswerPar) != 1) || (receivedAnswer[0] != 0x0a)) { - if (MF_DBGLEVEL >= 1) Dbprintf("write block send data error"); + if ((ReaderReceive(receivedAnswer, receivedAnswerPar) != 1) || (receivedAnswer[0] != CARD_ACK)) { + if (MF_DBGLEVEL >= 1) Dbprintf("write block send data error"); break; }; } - + // halt - // do no issue halt command for gen1b + // do no issue halt command for gen1b if (!gen1b) { if (mifare_classic_halt(NULL, 0)) { - if (MF_DBGLEVEL > 2) Dbprintf("Halt error"); + if (MF_DBGLEVEL > 2) Dbprintf("Halt error"); break; } } } break; - } + } // send USB response LED_B_ON(); cmd_send(CMD_ACK,isOK,0,0,NULL,0); LED_B_OFF(); - + // reset fpga FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LEDsoff(); - + return; } @@ -1330,13 +1394,13 @@ void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai // get UID from chip if (workFlags & 0x01) { if(!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) { - if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card"); + if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card"); // Continue, if we set wrong UID or wrong UID checksum or some ATQA or SAK we will can't select card. But we need to write block 0 to make card work. //break; }; if(mifare_classic_halt(NULL, cuid)) { - if (MF_DBGLEVEL > 2) Dbprintf("Halt error"); + if (MF_DBGLEVEL > 2) Dbprintf("Halt error"); // Continue, some magic tags misbehavies and send an answer to it. // break; }; @@ -1346,21 +1410,21 @@ void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai // Wipe command don't work with gen1b if (needWipe && !(workFlags & 0x40)){ ReaderTransmitBitsPar(wupC1,7,0, NULL); - if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) { - if (MF_DBGLEVEL >= 1) Dbprintf("wupC1 error"); + if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != CARD_ACK)) { + if (MF_DBGLEVEL >= 1) Dbprintf("wupC1 error"); break; }; ReaderTransmit(wipeC, sizeof(wipeC), NULL); - if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) { - if (MF_DBGLEVEL >= 1) Dbprintf("wipeC error"); + if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != CARD_ACK)) { + if (MF_DBGLEVEL >= 1) Dbprintf("wipeC error"); break; }; if(mifare_classic_halt(NULL, 0)) { - if (MF_DBGLEVEL > 2) Dbprintf("Halt error"); + if (MF_DBGLEVEL > 2) Dbprintf("Halt error"); // Continue, some magic tags misbehavies and send an answer to it. - // break; + // break; }; }; @@ -1368,24 +1432,24 @@ void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai if (workFlags & 0x02) { ReaderTransmitBitsPar(wupC1,7,0, NULL); - // gen1b magic tag : do no issue wupC2 and don't expect 0x0a response after SELECT_UID (after getting UID from chip in 'hf mf csetuid' command) + // gen1b magic tag : do no issue wupC2 and don't expect CARD_ACK response after SELECT_UID (after getting UID from chip in 'hf mf csetuid' command) if (!(workFlags & 0x40)) { - if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) { - if (MF_DBGLEVEL >= 1) Dbprintf("wupC1 error"); + if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != CARD_ACK)) { + if (MF_DBGLEVEL >= 1) Dbprintf("wupC1 error"); break; }; ReaderTransmit(wupC2, sizeof(wupC2), NULL); - if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) { - if (MF_DBGLEVEL >= 1) Dbprintf("wupC2 error"); + if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != CARD_ACK)) { + if (MF_DBGLEVEL >= 1) Dbprintf("wupC2 error"); break; }; } } - if ((mifare_sendcmd_short(NULL, 0, 0xA0, blockNo, receivedAnswer, receivedAnswerPar, NULL) != 1) || (receivedAnswer[0] != 0x0a)) { - if (MF_DBGLEVEL >= 1) Dbprintf("write block send command error"); + if ((mifare_sendcmd_short(NULL, 0, 0xA0, blockNo, receivedAnswer, receivedAnswerPar, NULL) != 1) || (receivedAnswer[0] != CARD_ACK)) { + if (MF_DBGLEVEL >= 1) Dbprintf("write block send command error"); break; }; @@ -1393,8 +1457,8 @@ void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai AppendCrc14443a(d_block, 16); ReaderTransmit(d_block, sizeof(d_block), NULL); - if ((ReaderReceive(receivedAnswer, receivedAnswerPar) != 1) || (receivedAnswer[0] != 0x0a)) { - if (MF_DBGLEVEL >= 1) Dbprintf("write block send data error"); + if ((ReaderReceive(receivedAnswer, receivedAnswerPar) != 1) || (receivedAnswer[0] != CARD_ACK)) { + if (MF_DBGLEVEL >= 1) Dbprintf("write block send data error"); break; }; @@ -1402,7 +1466,7 @@ void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai // do no issue halt command for gen1b magic tag (#db# halt error. response len: 1) if (!(workFlags & 0x40)) { if (mifare_classic_halt(NULL, 0)) { - if (MF_DBGLEVEL > 2) Dbprintf("Halt error"); + if (MF_DBGLEVEL > 2) Dbprintf("Halt error"); // Continue, some magic tags misbehavies and send an answer to it. // break; } @@ -1461,15 +1525,15 @@ void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai while (true) { if (workFlags & 0x02) { ReaderTransmitBitsPar(wupC1,7,0, NULL); - if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) { - if (MF_DBGLEVEL >= 1) Dbprintf("wupC1 error"); + if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != CARD_ACK)) { + if (MF_DBGLEVEL >= 1) Dbprintf("wupC1 error"); break; }; // do no issue for gen1b magic tag if (!(workFlags & 0x40)) { ReaderTransmit(wupC2, sizeof(wupC2), NULL); - if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) { - if (MF_DBGLEVEL >= 1) Dbprintf("wupC2 error"); + if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != CARD_ACK)) { + if (MF_DBGLEVEL >= 1) Dbprintf("wupC2 error"); break; }; } @@ -1477,7 +1541,7 @@ void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai // read block if ((mifare_sendcmd_short(NULL, 0, 0x30, blockNo, receivedAnswer, receivedAnswerPar, NULL) != 18)) { - if (MF_DBGLEVEL >= 1) Dbprintf("read block send command error"); + if (MF_DBGLEVEL >= 1) Dbprintf("read block send command error"); break; }; memcpy(data, receivedAnswer, 18); @@ -1486,9 +1550,9 @@ void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai // do no issue halt command for gen1b magic tag (#db# halt error. response len: 1) if (!(workFlags & 0x40)) { if (mifare_classic_halt(NULL, cuid)) { - if (MF_DBGLEVEL > 1) Dbprintf("Halt error"); + if (MF_DBGLEVEL > 1) Dbprintf("Halt error"); // Continue, some magic tags misbehavies and send an answer to it. - // break; + // break; } } } @@ -1523,34 +1587,34 @@ void MifareCIdent(){ uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE]; uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE]; - + LED_A_ON(); LED_B_OFF(); LED_C_OFF(); iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); clear_trace(); - set_tracing(true); + set_tracing(true); ReaderTransmitBitsPar(wupC1,7,0, NULL); - if(ReaderReceive(receivedAnswer, receivedAnswerPar) && (receivedAnswer[0] == 0x0a)) { + if(ReaderReceive(receivedAnswer, receivedAnswerPar) && (receivedAnswer[0] == CARD_ACK)) { isOK = 2; ReaderTransmit(wupC2, sizeof(wupC2), NULL); - if(ReaderReceive(receivedAnswer, receivedAnswerPar) && (receivedAnswer[0] == 0x0a)) { + if(ReaderReceive(receivedAnswer, receivedAnswerPar) && (receivedAnswer[0] == CARD_ACK)) { isOK = 1; }; }; // From iceman1001: removed the if, since some magic tags misbehavies and send an answer to it. mifare_classic_halt(NULL, 0); - + LED_B_ON(); cmd_send(CMD_ACK,isOK,0,0,0,0); LED_B_OFF(); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - LEDsoff(); + LEDsoff(); } // @@ -1580,7 +1644,7 @@ void Mifare_DES_Auth1(uint8_t arg0, uint8_t *datain){ } if (MF_DBGLEVEL >= MF_DBG_EXTENDED) DbpString("AUTH 1 FINISHED"); - cmd_send(CMD_ACK,1,cuid,0,dataout, sizeof(dataout)); + cmd_send(CMD_ACK,1,cuid,0,dataout, sizeof(dataout)); } void Mifare_DES_Auth2(uint32_t arg0, uint8_t *datain){ diff --git a/armsrc/mifarecmd.h b/armsrc/mifarecmd.h index e17fa998..c16c3a3e 100644 --- a/armsrc/mifarecmd.h +++ b/armsrc/mifarecmd.h @@ -10,18 +10,36 @@ // Routines to support ISO 14443 type A. //----------------------------------------------------------------------------- -#ifndef __MIFARECMD_H -#define __MIFARECMD_H +#ifndef MIFARECMD_H__ +#define MIFARECMD_H__ -#include "proxmark3.h" -#include "apps.h" -#include "util.h" +#include -#include "iso14443crc.h" -#include "iso14443a.h" -#include "crapto1/crapto1.h" -#include "mifareutil.h" -#include "common.h" +extern void MifareReadBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *data); +extern void MifareUReadBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain); +extern void MifareUC_Auth(uint8_t arg0, uint8_t *datain); +extern void MifareUReadCard(uint8_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain); +extern void MifareReadSector(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain); +extern void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain); +//extern void MifareUWriteBlockCompat(uint8_t arg0,uint8_t *datain); +extern void MifareUWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain); +extern void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain); +extern void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags, uint8_t *datain); +extern void MifareChkKeys(uint16_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain); +extern void MifareSetDbgLvl(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain); +extern void MifareEMemClr(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain); +extern void MifareEMemSet(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain); +extern void MifareEMemGet(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain); +extern void MifareECardLoad(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain); +extern void MifareCWipe(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain); // Work with "magic Chinese" card +extern void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain); +extern void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain); +extern void MifareCIdent(); // is "magic chinese" card? +extern void MifareUSetPwd(uint8_t arg0, uint8_t *datain); +extern void MifarePersonalizeUID(uint8_t keyType, uint8_t perso_option, uint8_t *datain); +//desfire +extern void Mifare_DES_Auth1(uint8_t arg0,uint8_t *datain); +extern void Mifare_DES_Auth2(uint32_t arg0, uint8_t *datain); -#endif \ No newline at end of file +#endif diff --git a/armsrc/mifareutil.c b/armsrc/mifareutil.c index 647305e8..fe5a7485 100644 --- a/armsrc/mifareutil.c +++ b/armsrc/mifareutil.c @@ -22,6 +22,7 @@ #include "iso14443a.h" #include "crapto1/crapto1.h" #include "mbedtls/des.h" +#include "protocols.h" int MF_DBGLEVEL = MF_DBG_INFO; @@ -163,7 +164,7 @@ int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockN uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE]; // Transmit MIFARE_CLASSIC_AUTH - len = mifare_sendcmd_short(pcs, isNested, 0x60 + (keyType & 0x01), blockNo, receivedAnswer, receivedAnswerPar, timing); + len = mifare_sendcmd_short(pcs, isNested, keyType & 0x01 ? MIFARE_AUTH_KEYB : MIFARE_AUTH_KEYA, blockNo, receivedAnswer, receivedAnswerPar, timing); if (MF_DBGLEVEL >= 4) Dbprintf("rand tag nonce len: %x", len); if (len != 4) return 1; @@ -250,7 +251,7 @@ int mifare_classic_readblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blo uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE]; // command MIFARE_CLASSIC_READBLOCK - len = mifare_sendcmd_short(pcs, 1, 0x30, blockNo, receivedAnswer, receivedAnswerPar, NULL); + len = mifare_sendcmd_short(pcs, 1, MIFARE_CMD_READBLOCK, blockNo, receivedAnswer, receivedAnswerPar, NULL); if (len == 1) { if (MF_DBGLEVEL >= 1) Dbprintf("Cmd Error: %02x", receivedAnswer[0]); return 1; @@ -282,7 +283,7 @@ int mifare_ul_ev1_auth(uint8_t *keybytes, uint8_t *pack){ if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("EV1 Auth : %02x%02x%02x%02x", key[0], key[1], key[2], key[3]); - len = mifare_sendcmd(0x1B, key, sizeof(key), resp, respPar, NULL); + len = mifare_sendcmd(MIFARE_ULEV1_AUTH, key, sizeof(key), resp, respPar, NULL); //len = mifare_sendcmd_short_mfuev1auth(NULL, 0, 0x1B, key, resp, respPar, NULL); if (len != 4) { if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x %u", resp[0], len); @@ -314,7 +315,7 @@ int mifare_ultra_auth(uint8_t *keybytes){ uint8_t respPar[3] = {0,0,0}; // REQUEST AUTHENTICATION - len = mifare_sendcmd_short(NULL, 1, 0x1A, 0x00, resp, respPar ,NULL); + len = mifare_sendcmd_short(NULL, 1, MIFARE_ULC_AUTH_1, 0x00, resp, respPar ,NULL); if (len != 11) { if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x", resp[0]); return 0; @@ -364,7 +365,7 @@ int mifare_ultra_auth(uint8_t *keybytes){ ); //len = mifare_sendcmd_short_mfucauth(NULL, 1, 0xAF, rnd_ab, resp, respPar, NULL); - len = mifare_sendcmd(0xAF, rnd_ab, sizeof(rnd_ab), resp, respPar, NULL); + len = mifare_sendcmd(MIFARE_ULC_AUTH_2, rnd_ab, sizeof(rnd_ab), resp, respPar, NULL); if (len != 11) { if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x", resp[0]); return 0; @@ -421,7 +422,7 @@ int mifare_ultra_readblock(uint8_t blockNo, uint8_t *blockData) int result = 0; for (retries = 0; retries < MFU_MAX_RETRIES; retries++) { - len = mifare_sendcmd_short(NULL, 1, 0x30, blockNo, receivedAnswer, receivedAnswerPar, NULL); + len = mifare_sendcmd_short(NULL, 1, MIFARE_CMD_READBLOCK, blockNo, receivedAnswer, receivedAnswerPar, NULL); if (len == 1) { if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x", receivedAnswer[0]); result = 1; @@ -468,7 +469,7 @@ int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t bl uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE]; // command MIFARE_CLASSIC_WRITEBLOCK - len = mifare_sendcmd_short(pcs, 1, 0xA0, blockNo, receivedAnswer, receivedAnswerPar, NULL); + len = mifare_sendcmd_short(pcs, 1, MIFARE_CMD_WRITEBLOCK, blockNo, receivedAnswer, receivedAnswerPar, NULL); if ((len != 1) || (receivedAnswer[0] != 0x0A)) { // 0x0a - ACK if (MF_DBGLEVEL >= 1) Dbprintf("Cmd Error: %02x", receivedAnswer[0]); @@ -511,7 +512,7 @@ int mifare_ultra_writeblock_compat(uint8_t blockNo, uint8_t *blockData) uint8_t receivedAnswer[MAX_FRAME_SIZE]; uint8_t receivedAnswerPar[MAX_PARITY_SIZE]; - len = mifare_sendcmd_short(NULL, true, 0xA0, blockNo, receivedAnswer, receivedAnswerPar, NULL); + len = mifare_sendcmd_short(NULL, true, MIFARE_CMD_WRITEBLOCK, blockNo, receivedAnswer, receivedAnswerPar, NULL); if ((len != 1) || (receivedAnswer[0] != 0x0A)) { // 0x0a - ACK if (MF_DBGLEVEL >= MF_DBG_ERROR) @@ -563,7 +564,7 @@ int mifare_classic_halt(struct Crypto1State *pcs, uint32_t uid) uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE]; uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE]; - len = mifare_sendcmd_short(pcs, pcs == NULL ? false:true, 0x50, 0x00, receivedAnswer, receivedAnswerPar, NULL); + len = mifare_sendcmd_short(pcs, pcs == NULL ? false:true, ISO14443A_CMD_HALT, 0x00, receivedAnswer, receivedAnswerPar, NULL); if (len != 0) { if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("halt error. response len: %x", len); @@ -579,7 +580,7 @@ int mifare_ultra_halt() uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE]; uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE]; - len = mifare_sendcmd_short(NULL, true, 0x50, 0x00, receivedAnswer, receivedAnswerPar, NULL); + len = mifare_sendcmd_short(NULL, true, ISO14443A_CMD_HALT, 0x00, receivedAnswer, receivedAnswerPar, NULL); if (len != 0) { if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("halt error. response len: %x", len); diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index c38e276e..9ecf99fb 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -34,6 +34,7 @@ #include "mifare/mad.h" #include "mifare/ndef.h" #include "emv/dump.h" +#include "protocols.h" #define NESTED_SECTOR_RETRY 10 // how often we try mfested() until we give up @@ -92,10 +93,10 @@ int CmdHF14AMfWrBl(const char *Cmd) PrintAndLog("--block no:%d, key type:%c, key:%s", blockNo, keyType?'B':'A', sprint_hex(key, 6)); PrintAndLog("--data: %s", sprint_hex(bldata, 16)); - UsbCommand c = {CMD_MIFARE_WRITEBL, {blockNo, keyType, 0}}; + UsbCommand c = {CMD_MIFARE_WRITEBL, {blockNo, keyType, 0}}; memcpy(c.d.asBytes, key, 6); memcpy(c.d.asBytes + 10, bldata, 16); - SendCommand(&c); + SendCommand(&c); UsbCommand resp; if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) { @@ -136,9 +137,9 @@ int CmdHF14AMfRdBl(const char *Cmd) } PrintAndLog("--block no:%d, key type:%c, key:%s ", blockNo, keyType?'B':'A', sprint_hex(key, 6)); - UsbCommand c = {CMD_MIFARE_READBL, {blockNo, keyType, 0}}; + UsbCommand c = {CMD_MIFARE_READBL, {blockNo, keyType, 0}}; memcpy(c.d.asBytes, key, 6); - SendCommand(&c); + SendCommand(&c); UsbCommand resp; if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) { @@ -167,7 +168,7 @@ int CmdHF14AMfRdBl(const char *Cmd) return 2; } - return 0; + return 0; } int CmdHF14AMfRdSc(const char *Cmd) @@ -233,7 +234,7 @@ int CmdHF14AMfRdSc(const char *Cmd) PrintAndLog("Command execute timeout"); } - return 0; + return 0; } uint8_t FirstBlockOfSector(uint8_t sectorNo) @@ -1086,7 +1087,7 @@ int CmdHF14AMfChk(const char *Cmd) bool createDumpFile = 0; bool singleBlock = false; // Flag to ID if a single or multi key check uint8_t keyFoundCount = 0; // Counter to display the number of keys found/transfered to emulator - + sector_t *e_sector = NULL; keyBlock = calloc(stKeyBlock, 6); @@ -1132,7 +1133,7 @@ int CmdHF14AMfChk(const char *Cmd) return 1; }; } - + parseParamTDS(Cmd, 2, &transferToEml, &createDumpFile, &btimeout14a); if (singleBlock & createDumpFile) { @@ -1244,7 +1245,7 @@ int CmdHF14AMfChk(const char *Cmd) uint32_t max_keys = keycnt > USB_CMD_DATA_SIZE / 6 ? USB_CMD_DATA_SIZE / 6 : keycnt; // !SingleKey, so all key check (if SectorsCnt > 0) - if (!singleBlock) { + if (!singleBlock) { PrintAndLog("To cancel this operation press the button on the proxmark..."); printf("--"); for (uint32_t c = 0; c < keycnt; c += max_keys) { @@ -1265,7 +1266,7 @@ int CmdHF14AMfChk(const char *Cmd) PrintAndLog("Command execute timeout"); } } - } else { + } else { int keyAB = keyType; do { for (uint32_t c = 0; c < keycnt; c += max_keys) { @@ -1275,16 +1276,16 @@ int CmdHF14AMfChk(const char *Cmd) clearTraceLog = false; if (res != 1) { - if (!res) { + if (!res) { // Use the common format below // PrintAndLog("Found valid key:[%d:%c]%012" PRIx64, blockNo, (keyAB & 0x01)?'B':'A', key64); foundAKey = true; - + // Store the Single Key for display list // For a single block check, SectorsCnt = Sector that contains the block - e_sector[SectorsCnt-1].foundKey[(keyAB & 0x01)] = true; // flag key found - e_sector[SectorsCnt-1].Key[(keyAB & 0x01)] = key64; // Save key data - + e_sector[SectorsCnt-1].foundKey[(keyAB & 0x01)] = true; // flag key found + e_sector[SectorsCnt-1].Key[(keyAB & 0x01)] = key64; // Save key data + } } else { PrintAndLog("Command execute timeout"); @@ -1327,7 +1328,7 @@ int CmdHF14AMfChk(const char *Cmd) for (uint16_t t = 0; t < 2; t++) { if (e_sector[sectorNo].foundKey[t]) { num_to_bytes(e_sector[sectorNo].Key[t], 6, block + t * 10); - keyFoundCount++; // Key found count for information + keyFoundCount++; // Key found count for information } } mfEmlSetMem(block, FirstBlockOfSector(sectorNo) + NumBlocksPerSector(sectorNo) - 1, 1); @@ -1355,7 +1356,7 @@ int CmdHF14AMfChk(const char *Cmd) fclose(fkeys); PrintAndLog("Found keys have been dumped to file dumpkeys.bin. 0xffffffffffff has been inserted for unknown keys."); } - + free(e_sector); free(keyBlock); PrintAndLog(""); @@ -1710,10 +1711,10 @@ int CmdHF14AMfDbg(const char *Cmd) return 0; } - UsbCommand c = {CMD_MIFARE_SET_DBGMODE, {dbgMode, 0, 0}}; - SendCommand(&c); + UsbCommand c = {CMD_MIFARE_SET_DBGMODE, {dbgMode, 0, 0}}; + SendCommand(&c); - return 0; + return 0; } int CmdHF14AMfEGet(const char *Cmd) @@ -1736,7 +1737,7 @@ int CmdHF14AMfEGet(const char *Cmd) PrintAndLog("Command execute timeout"); } - return 0; + return 0; } int CmdHF14AMfEClear(const char *Cmd) @@ -1747,9 +1748,9 @@ int CmdHF14AMfEClear(const char *Cmd) return 0; } - UsbCommand c = {CMD_MIFARE_EML_MEMCLR, {0, 0, 0}}; - SendCommand(&c); - return 0; + UsbCommand c = {CMD_MIFARE_EML_MEMCLR, {0, 0, 0}}; + SendCommand(&c); + return 0; } @@ -1956,7 +1957,7 @@ int CmdHF14AMfESave(const char *Cmd) PrintAndLog("Saved %d blocks to file: %s", numBlocks, filename); - return 0; + return 0; } @@ -2026,7 +2027,7 @@ int CmdHF14AMfEKeyPrn(const char *Cmd) case '\0': numSectors = 16; break; case '2' : numSectors = 32; break; case '4' : numSectors = 40; break; - case 'd' : + case 'd' : case 'D' : createDumpFile = true; break; } cmdp++; @@ -3009,51 +3010,130 @@ int CmdHFMFNDEF(const char *cmd) { return 0; } -static command_t CommandTable[] = -{ - {"help", CmdHelp, 1, "This help"}, - {"dbg", CmdHF14AMfDbg, 0, "Set default debug mode"}, - {"rdbl", CmdHF14AMfRdBl, 0, "Read MIFARE classic block"}, - {"rdsc", CmdHF14AMfRdSc, 0, "Read MIFARE classic sector"}, - {"dump", CmdHF14AMfDump, 0, "Dump MIFARE classic tag to binary file"}, - {"restore", CmdHF14AMfRestore, 0, "Restore MIFARE classic binary file to BLANK tag"}, - {"wrbl", CmdHF14AMfWrBl, 0, "Write MIFARE classic block"}, - {"auth4", CmdHF14AMfAuth4, 0, "ISO14443-4 AES authentication"}, - {"chk", CmdHF14AMfChk, 0, "Test block keys"}, - {"mifare", CmdHF14AMifare, 0, "Read parity error messages."}, - {"hardnested", CmdHF14AMfNestedHard, 0, "Nested attack for hardened Mifare cards"}, - {"nested", CmdHF14AMfNested, 0, "Test nested authentication"}, - {"sniff", CmdHF14AMfSniff, 0, "Sniff card-reader communication"}, - {"sim", CmdHF14AMfSim, 0, "Simulate MIFARE card"}, - {"eclr", CmdHF14AMfEClear, 0, "Clear simulator memory"}, - {"eget", CmdHF14AMfEGet, 0, "Get simulator memory block"}, - {"eset", CmdHF14AMfESet, 0, "Set simulator memory block"}, - {"eload", CmdHF14AMfELoad, 0, "Load from file emul dump"}, - {"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"}, - {"cgetsc", CmdHF14AMfCGetSc, 0, "Read sector - Magic Chinese card"}, - {"cload", CmdHF14AMfCLoad, 0, "Load dump into magic Chinese card"}, - {"csave", CmdHF14AMfCSave, 0, "Save dump from magic Chinese card into file or emulator"}, - {"decrypt", CmdDecryptTraceCmds, 1, "[nt] [ar_enc] [at_enc] [data] - to decrypt snoop or trace"}, - {"mad", CmdHF14AMfMAD, 0, "Checks and prints MAD"}, - {"ndef", CmdHFMFNDEF, 0, "Prints NDEF records from card"}, - {NULL, NULL, 0, NULL} +int CmdHFMFPersonalize(const char *cmd) { + + CLIParserInit("hf mf personalize", + "Personalize the UID of a Mifare Classic EV1 card. This is only possible if it is a 7Byte UID card and if it is not already personalized.", + "Usage:\n\thf mf personalize UIDF0 -> double size UID according to ISO/IEC14443-3\n" + "\thf mf personalize UIDF1 -> double size UID according to ISO/IEC14443-3, optional usage of selection process shortcut\n" + "\thf mf personalize UIDF2 -> single size random ID according to ISO/IEC14443-3\n" + "\thf mf personalize UIDF3 -> single size NUID according to ISO/IEC14443-3\n" + "\thf mf personalize -t B -k B0B1B2B3B4B5 UIDF3 -> use key B = 0xB0B1B2B3B4B5 instead of default key A\n"); + + void *argtable[] = { + arg_param_begin, + arg_str0("tT", "keytype", "", "key type (A or B) to authenticate sector 0 (default: A)"), + arg_str0("kK", "key", "", "key to authenticate sector 0 (default: FFFFFFFFFFFF)"), + arg_str1(NULL, NULL, "", "Personalization Option"), + arg_param_end + }; + CLIExecWithReturn(cmd, argtable, true); + + char keytypestr[2] = "A"; + uint8_t keytype = 0x00; + int keytypestr_len; + int res = CLIParamStrToBuf(arg_get_str(1), (uint8_t*)keytypestr, 1, &keytypestr_len); + if (res || (keytypestr[0] != 'a' && keytypestr[0] != 'A' && keytypestr[0] != 'b' && keytypestr[0] != 'B')) { + PrintAndLog("ERROR: not a valid key type. Key type must be A or B"); + CLIParserFree(); + return 1; + } + if (keytypestr[0] == 'B' || keytypestr[0] == 'b') { + keytype = 0x01; + } + + uint8_t key[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + int key_len; + res = CLIParamHexToBuf(arg_get_str(2), key, 6, &key_len); + if (res || (!res && key_len > 0 && key_len != 6)) { + PrintAndLog("ERROR: not a valid key. Key must be 12 hex digits"); + CLIParserFree(); + return 1; + } + + char pers_optionstr[6]; + int opt_len; + uint8_t pers_option; + res = CLIParamStrToBuf(arg_get_str(3), (uint8_t*)pers_optionstr, 5, &opt_len); + if (res || (!res && opt_len > 0 && opt_len != 5) + || (strncmp(pers_optionstr, "UIDF0", 5) && strncmp(pers_optionstr, "UIDF1", 5) && strncmp(pers_optionstr, "UIDF2", 5) && strncmp(pers_optionstr, "UIDF3", 5))) { + PrintAndLog("ERROR: invalid personalization option. Must be one of UIDF0, UIDF1, UIDF2, or UIDF3"); + CLIParserFree(); + return 1; + } + if (!strncmp(pers_optionstr, "UIDF0", 5)) { + pers_option = MIFARE_EV1_UIDF0; + } else if (!strncmp(pers_optionstr, "UIDF1", 5)) { + pers_option = MIFARE_EV1_UIDF1; + } else if (!strncmp(pers_optionstr, "UIDF2", 5)) { + pers_option = MIFARE_EV1_UIDF2; + } else { + pers_option = MIFARE_EV1_UIDF3; + } + + CLIParserFree(); + + UsbCommand c = {CMD_MIFARE_PERSONALIZE_UID, {keytype, pers_option, 0}}; + memcpy(c.d.asBytes, key, 6); + SendCommand(&c); + + UsbCommand resp; + if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { + uint8_t isOK = resp.arg[0] & 0xff; + PrintAndLog("Personalization %s", isOK ? "FAILED" : "SUCCEEDED"); + } else { + PrintAndLog("Command execute timeout"); + } + + return 0; +} + + +static command_t CommandTable[] = { + {"help", CmdHelp, 1, "This help"}, + {"dbg", CmdHF14AMfDbg, 0, "Set default debug mode"}, + {"rdbl", CmdHF14AMfRdBl, 0, "Read MIFARE classic block"}, + {"rdsc", CmdHF14AMfRdSc, 0, "Read MIFARE classic sector"}, + {"dump", CmdHF14AMfDump, 0, "Dump MIFARE classic tag to binary file"}, + {"restore", CmdHF14AMfRestore, 0, "Restore MIFARE classic binary file to BLANK tag"}, + {"wrbl", CmdHF14AMfWrBl, 0, "Write MIFARE classic block"}, + {"auth4", CmdHF14AMfAuth4, 0, "ISO14443-4 AES authentication"}, + {"chk", CmdHF14AMfChk, 0, "Test block keys"}, + {"mifare", CmdHF14AMifare, 0, "Read parity error messages."}, + {"hardnested", CmdHF14AMfNestedHard, 0, "Nested attack for hardened Mifare cards"}, + {"nested", CmdHF14AMfNested, 0, "Test nested authentication"}, + {"sniff", CmdHF14AMfSniff, 0, "Sniff card-reader communication"}, + {"sim", CmdHF14AMfSim, 0, "Simulate MIFARE card"}, + {"eclr", CmdHF14AMfEClear, 0, "Clear simulator memory"}, + {"eget", CmdHF14AMfEGet, 0, "Get simulator memory block"}, + {"eset", CmdHF14AMfESet, 0, "Set simulator memory block"}, + {"eload", CmdHF14AMfELoad, 0, "Load from file emul dump"}, + {"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"}, + {"cgetsc", CmdHF14AMfCGetSc, 0, "Read sector - Magic Chinese card"}, + {"cload", CmdHF14AMfCLoad, 0, "Load dump into magic Chinese card"}, + {"csave", CmdHF14AMfCSave, 0, "Save dump from magic Chinese card into file or emulator"}, + {"decrypt", CmdDecryptTraceCmds, 1, "[nt] [ar_enc] [at_enc] [data] - to decrypt snoop or trace"}, + {"mad", CmdHF14AMfMAD, 0, "Checks and prints MAD"}, + {"ndef", CmdHFMFNDEF, 0, "Prints NDEF records from card"}, + {"personalize", CmdHFMFPersonalize, 0, "Personalize UID (Mifare Classic EV1 only)"}, + {NULL, NULL, 0, NULL} }; -int CmdHFMF(const char *Cmd) -{ + +int CmdHFMF(const char *Cmd) { (void)WaitForResponseTimeout(CMD_ACK,NULL,100); CmdsParse(CommandTable, Cmd); return 0; } -int CmdHelp(const char *Cmd) -{ - CmdsHelp(CommandTable); - return 0; + +int CmdHelp(const char *Cmd) { + CmdsHelp(CommandTable); + return 0; } diff --git a/client/util.c b/client/util.c index cd18fc00..7e230488 100644 --- a/client/util.c +++ b/client/util.c @@ -26,7 +26,7 @@ #ifndef _WIN32 #include -#include +#include #include int ukbhit(void) @@ -42,11 +42,11 @@ int ukbhit(void) Ntty.c_oflag = 0x0000; // output mode Ntty.c_lflag &= ~ICANON; // control mode = raw Ntty.c_cc[VMIN] = 1; // return if at least 1 character is in the queue - Ntty.c_cc[VTIME] = 0; // no timeout. Wait forever - + Ntty.c_cc[VTIME] = 0; // no timeout. Wait forever + if (0 == (error = tcsetattr(STDIN_FILENO, TCSANOW, &Ntty))) { // set new attributes - error += ioctl(STDIN_FILENO, FIONREAD, &cnt); // get number of characters availabe - error += tcsetattr(STDIN_FILENO, TCSANOW, &Otty); // reset attributes + error += ioctl(STDIN_FILENO, FIONREAD, &cnt); // get number of characters availabe + error += tcsetattr(STDIN_FILENO, TCSANOW, &Otty); // reset attributes } return ( error == 0 ? cnt : -1 ); @@ -78,13 +78,13 @@ int ukbhit(void) { // log files functions void AddLogLine(char *file, char *extData, char *c) { FILE *fLog = NULL; - char filename[FILE_PATH_SIZE] = {0x00}; - int len = 0; + char filename[FILE_PATH_SIZE] = {0x00}; + int len = 0; + + len = strlen(file); + if (len > FILE_PATH_SIZE) len = FILE_PATH_SIZE; + memcpy(filename, file, len); - len = strlen(file); - if (len > FILE_PATH_SIZE) len = FILE_PATH_SIZE; - memcpy(filename, file, len); - fLog = fopen(filename, "a"); if (!fLog) { printf("Could not append log file %s", filename); @@ -119,10 +119,10 @@ void AddLogCurrentDT(char *fileName) { void FillFileNameByUID(char *fileName, uint8_t *uid, char *ext, int byteCount) { char * fnameptr = fileName; - + for (int j = 0; j < byteCount; j++, fnameptr += 2) - sprintf(fnameptr, "%02x", (unsigned int) uid[j]); - sprintf(fnameptr, "%s", ext); + sprintf(fnameptr, "%02x", (unsigned int) uid[j]); + sprintf(fnameptr, "%s", ext); } // fill buffer from structure [{uint8_t data, size_t length},...] @@ -130,25 +130,25 @@ int FillBuffer(uint8_t *data, size_t maxDataLength, size_t *dataLength, ...) { *dataLength = 0; va_list valist; va_start(valist, dataLength); - + uint8_t *vdata = NULL; size_t vlength = 0; do{ vdata = va_arg(valist, uint8_t *); if (!vdata) break; - + vlength = va_arg(valist, size_t); if (*dataLength + vlength > maxDataLength) { va_end(valist); return 1; } - + memcpy(&data[*dataLength], vdata, vlength); *dataLength += vlength; - + } while (vdata); - + va_end(valist); return 0; @@ -161,13 +161,13 @@ bool CheckStringIsHEXValue(const char *value) { if (strlen(value) % 2) return false; - + return true; } -void hex_to_buffer(const uint8_t *buf, const uint8_t *hex_data, const size_t hex_len, const size_t hex_max_len, +void hex_to_buffer(const uint8_t *buf, const uint8_t *hex_data, const size_t hex_len, const size_t hex_max_len, const size_t min_str_len, const size_t spaces_between, bool uppercase) { - + char *tmp = (char *)buf; size_t i; memset(tmp, 0x00, hex_max_len); @@ -175,17 +175,17 @@ void hex_to_buffer(const uint8_t *buf, const uint8_t *hex_data, const size_t hex int maxLen = ( hex_len > hex_max_len) ? hex_max_len : hex_len; for (i = 0; i < maxLen; ++i, tmp += 2 + spaces_between) { - sprintf(tmp, (uppercase) ? "%02X" : "%02x", (unsigned int) hex_data[i]); - + sprintf(tmp, (uppercase) ? "%02X" : "%02x", (unsigned int) hex_data[i]); + for (int j = 0; j < spaces_between; j++) sprintf(tmp + 2 + j, " "); } - + i *= (2 + spaces_between); int minStrLen = min_str_len > i ? min_str_len : 0; if (minStrLen > hex_max_len) minStrLen = hex_max_len; - for(; i < minStrLen; i++, tmp += 1) + for(; i < minStrLen; i++, tmp += 1) sprintf(tmp, " "); return; @@ -195,7 +195,7 @@ void hex_to_buffer(const uint8_t *buf, const uint8_t *hex_data, const size_t hex char *sprint_hex(const uint8_t *data, const size_t len) { static char buf[4097] = {0}; - + hex_to_buffer((uint8_t *)buf, data, len, sizeof(buf) - 1, 0, 1, false); return buf; @@ -259,16 +259,16 @@ char *sprint_ascii_ex(const uint8_t *data, const size_t len, const size_t min_st tmp[i] = ((c < 32) || (c == 127)) ? '.' : c; ++i; } - + int minStrLen = min_str_len > i ? min_str_len : 0; - for(; i < minStrLen; ++i) + for(; i < minStrLen; ++i) tmp[i] = ' '; - + return buf; } char *sprint_ascii(const uint8_t *data, const size_t len) { - return sprint_ascii_ex(data, len, 0); + return sprint_ascii_ex(data, len, 0); } void num_to_bytes(uint64_t n, size_t len, uint8_t* dest) @@ -290,7 +290,7 @@ uint64_t bytes_to_num(uint8_t* src, size_t len) return num; } -void num_to_bytebits(uint64_t n, size_t len, uint8_t *dest) { +void num_to_bytebits(uint64_t n, size_t len, uint8_t *dest) { while (len--) { dest[len] = n & 1; n >>= 1; @@ -333,22 +333,22 @@ uint8_t *SwapEndian64(const uint8_t *src, const size_t len, const uint8_t blockS //assumes little endian char *printBits(size_t const size, void const * const ptr) { - unsigned char *b = (unsigned char*) ptr; - unsigned char byte; + unsigned char *b = (unsigned char*) ptr; + unsigned char byte; static char buf[1024]; char *tmp = buf; - int i, j; - - for (i=size-1;i>=0;i--) - { - for (j=7;j>=0;j--) - { - byte = b[i] & (1<>= j; - sprintf(tmp, "%u", (unsigned int)byte); + int i, j; + + for (i=size-1;i>=0;i--) + { + for (j=7;j>=0;j--) + { + byte = b[i] & (1<>= j; + sprintf(tmp, "%u", (unsigned int)byte); tmp++; - } - } + } + } return buf; } @@ -382,10 +382,10 @@ int param_getptr(const char *line, int *bg, int *en, int paramnum) { int i; int len = strlen(line); - + *bg = 0; *en = 0; - + // skip spaces while (line[*bg] ==' ' || line[*bg]=='\t') (*bg)++; if (*bg >= len) { @@ -395,13 +395,13 @@ int param_getptr(const char *line, int *bg, int *en, int paramnum) for (i = 0; i < paramnum; i++) { while (line[*bg]!=' ' && line[*bg]!='\t' && line[*bg] != '\0') (*bg)++; while (line[*bg]==' ' || line[*bg]=='\t') (*bg)++; - + if (line[*bg] == '\0') return 1; } - + *en = *bg; while (line[*en] != ' ' && line[*en] != '\t' && line[*en] != '\0') (*en)++; - + (*en)--; return 0; @@ -411,7 +411,7 @@ 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; @@ -423,12 +423,12 @@ char param_getchar(const char *line, int paramnum) { char param_getchar_indx(const char *line, int indx, int paramnum) { int bg, en; - + if (param_getptr(line, &bg, &en, paramnum)) return 0x00; if (bg + indx > en) return '\0'; - + return line[bg + indx]; } @@ -461,7 +461,7 @@ uint8_t param_isdec(const char *line, int paramnum) int bg, en; //TODO, check more thorougly if (!param_getptr(line, &bg, &en, paramnum)) return 1; - // return strtoul(&line[bg], NULL, 10) & 0xff; + // return strtoul(&line[bg], NULL, 10) & 0xff; return 0; } @@ -470,7 +470,7 @@ uint8_t param_get8ex(const char *line, int paramnum, int deflt, int base) { int bg, en; - if (!param_getptr(line, &bg, &en, paramnum)) + if (!param_getptr(line, &bg, &en, paramnum)) return strtoul(&line[bg], NULL, base) & 0xff; else return deflt; @@ -480,7 +480,7 @@ uint32_t param_get32ex(const char *line, int paramnum, int deflt, int base) { int bg, en; - if (!param_getptr(line, &bg, &en, paramnum)) + if (!param_getptr(line, &bg, &en, paramnum)) return strtoul(&line[bg], NULL, base); else return deflt; @@ -490,30 +490,30 @@ uint64_t param_get64ex(const char *line, int paramnum, int deflt, int base) { int bg, en; - if (!param_getptr(line, &bg, &en, paramnum)) + if (!param_getptr(line, &bg, &en, paramnum)) return strtoull(&line[bg], NULL, base); else return deflt; } -int param_gethex(const char *line, int paramnum, uint8_t * data, int hexcnt) +int param_gethex(const char *line, int paramnum, uint8_t *data, int hexcnt) { int bg, en, temp, i; if (hexcnt % 2) return 1; - + if (param_getptr(line, &bg, &en, paramnum)) return 1; - if (en - bg + 1 != hexcnt) + if (en - bg + 1 != hexcnt) return 1; for(i = 0; i < hexcnt; i += 2) { - if (!(isxdigit((unsigned char)line[bg + i]) && isxdigit((unsigned char)line[bg + i + 1])) ) return 1; - + if (!(isxdigit((unsigned char)line[bg + i]) && isxdigit((unsigned char)line[bg + i + 1])) ) return 1; + sscanf((char[]){line[bg + i], line[bg + i + 1], 0}, "%X", &temp); data[i / 2] = temp & 0xff; - } + } return 0; } @@ -523,22 +523,22 @@ int param_gethex_ex(const char *line, int paramnum, uint8_t *data, int *hexcnt) int bg, en, temp, i; //if (hexcnt % 2) - // return 1; - + // return 1; + if (param_getptr(line, &bg, &en, paramnum)) return 1; if (en - bg + 1 > *hexcnt) return 1; - + *hexcnt = en - bg + 1; if (*hexcnt % 2) //error if not complete hex bytes return 1; for(i = 0; i < *hexcnt; i += 2) { - if (!(isxdigit((unsigned char)line[bg + i]) && isxdigit((unsigned char)line[bg + i + 1])) ) return 1; - + if (!(isxdigit((unsigned char)line[bg + i]) && isxdigit((unsigned char)line[bg + i + 1])) ) return 1; + sscanf((char[]){line[bg + i], line[bg + i + 1], 0}, "%X", &temp); data[i / 2] = temp & 0xff; - } + } return 0; } @@ -551,21 +551,21 @@ int param_gethex_to_eol(const char *line, int paramnum, uint8_t * data, int maxd if (param_getptr(line, &bg, &en, paramnum)) return 1; *datalen = 0; - + int indx = bg; while (line[indx]) { if (line[indx] == '\t' || line[indx] == ' ') { indx++; continue; } - + if (isxdigit((unsigned char)line[indx])) { buf[strlen(buf) + 1] = 0x00; buf[strlen(buf)] = line[indx]; } else { // if we have symbols other than spaces and hex return 1; - } + } if (*datalen >= maxdatalen) { // if we dont have space in buffer and have symbols to translate @@ -578,14 +578,14 @@ int param_gethex_to_eol(const char *line, int paramnum, uint8_t * data, int maxd *buf = 0; (*datalen)++; } - + indx++; } - if (strlen(buf) > 0) + if (strlen(buf) > 0) //error when not completed hex bytes return 3; - + return 0; } @@ -593,7 +593,7 @@ int param_getstr(const char *line, int paramnum, char * str, size_t buffersize) { int bg, en; - if (param_getptr(line, &bg, &en, paramnum)) { + if (param_getptr(line, &bg, &en, paramnum)) { return 0; } @@ -602,10 +602,10 @@ int param_getstr(const char *line, int paramnum, char * str, size_t buffersize) printf("out of bounds error: want %d bytes have %zd bytes\n", en - bg + 1 + 1, buffersize); return 0; } - + memcpy(str, line + bg, en - bg + 1); str[en - bg + 1] = 0; - + return en - bg + 1; } @@ -618,100 +618,100 @@ https://github.com/ApertureLabsLtd/RFIDler/blob/master/firmware/Pic32/RFIDler.X/ // returns number of bits converted int hextobinarray(char *target, char *source) { - int length, i, count= 0; - char* start = source; - char x; - - length = strlen(source); - // process 4 bits (1 hex digit) at a time - while(length--) - { - x= *(source++); - // capitalize - if (x >= 'a' && x <= 'f') - x -= 32; - // convert to numeric value - if (x >= '0' && x <= '9') - x -= '0'; - else if (x >= 'A' && x <= 'F') - x -= 'A' - 10; - else { - printf("Discovered unknown character %c %d at idx %tu of %s\n", x, x, source - start, start); - return 0; - } - // output - for(i= 0 ; i < 4 ; ++i, ++count) - *(target++)= (x >> (3 - i)) & 1; - } - - return count; + int length, i, count= 0; + char* start = source; + char x; + + length = strlen(source); + // process 4 bits (1 hex digit) at a time + while(length--) + { + x= *(source++); + // capitalize + if (x >= 'a' && x <= 'f') + x -= 32; + // convert to numeric value + if (x >= '0' && x <= '9') + x -= '0'; + else if (x >= 'A' && x <= 'F') + x -= 'A' - 10; + else { + printf("Discovered unknown character %c %d at idx %tu of %s\n", x, x, source - start, start); + return 0; + } + // output + for(i= 0 ; i < 4 ; ++i, ++count) + *(target++)= (x >> (3 - i)) & 1; + } + + return count; } // convert binary array of 0x00/0x01 values to hex (safe to do in place as target will always be shorter than source) // return number of bits converted int binarraytohex(char *target,char *source, int length) { - unsigned char i, x; - int j = length; + unsigned char i, x; + int j = length; - if(j % 4) - return 0; + if(j % 4) + return 0; - while(j) - { - for(i= x= 0 ; i < 4 ; ++i) - x += ( source[i] << (3 - i)); - sprintf(target,"%X", (unsigned int)x); - ++target; - source += 4; - j -= 4; - } - return length; + while(j) + { + for(i= x= 0 ; i < 4 ; ++i) + x += ( source[i] << (3 - i)); + sprintf(target,"%X", (unsigned int)x); + ++target; + source += 4; + j -= 4; + } + return length; } // return parity bit required to match type uint8_t GetParity( uint8_t *bits, uint8_t type, int length) { - int x; + int x; - for(x= 0 ; length > 0 ; --length) - x += bits[length - 1]; - x %= 2; + for(x= 0 ; length > 0 ; --length) + x += bits[length - 1]; + x %= 2; - return x ^ type; + return x ^ type; } // add HID parity to binary array: EVEN prefix for 1st half of ID, ODD suffix for 2nd half void wiegand_add_parity(uint8_t *target, uint8_t *source, uint8_t length) { - *(target++)= GetParity(source, EVEN, length / 2); - memcpy(target, source, length); - target += length; - *(target)= GetParity(source + length / 2, ODD, length / 2); + *(target++)= GetParity(source, EVEN, length / 2); + memcpy(target, source, length); + target += length; + *(target)= GetParity(source + length / 2, ODD, length / 2); } // xor two arrays together for len items. The dst array contains the new xored values. void xor(unsigned char *dst, unsigned char *src, size_t len) { for( ; len > 0; len--,dst++,src++) - *dst ^= *src; + *dst ^= *src; } // RotateLeft - Ultralight, Desfire, works on byte level // 00-01-02 >> 01-02-00 void rol(uint8_t *data, const size_t len){ - uint8_t first = data[0]; - for (size_t i = 0; i < len-1; i++) { - data[i] = data[i+1]; - } - data[len-1] = first; + uint8_t first = data[0]; + for (size_t i = 0; i < len-1; i++) { + data[i] = data[i+1]; + } + data[len-1] = first; } // Replace unprintable characters with a dot in char buffer void clean_ascii(unsigned char *buf, size_t len) { for (size_t i = 0; i < len; i++) { - if (!isprint(buf[i])) - buf[i] = '.'; + if (!isprint(buf[i])) + buf[i] = '.'; } } @@ -724,8 +724,8 @@ void strcleanrn(char *buf, size_t len) { // replace char in buffer void strcreplace(char *buf, size_t len, char from, char to) { for (size_t i = 0; i < len; i++) { - if (buf[i] == from) - buf[i] = to; + if (buf[i] == from) + buf[i] = to; } } @@ -734,7 +734,7 @@ char *strmcopy(char *buf) { if ((str = (char*) malloc(strlen(buf) + 1)) != NULL) { memset(str, 0, strlen(buf) + 1); strcpy(str, buf); - } + } return str; } diff --git a/common/protocols.h b/common/protocols.h index ab556516..51fe579e 100644 --- a/common/protocols.h +++ b/common/protocols.h @@ -125,6 +125,10 @@ NXP/Philips CUSTOM COMMANDS #define MIFARE_CMD_TRANSFER 0xB0 #define MIFARE_EV1_PERSONAL_UID 0x40 +#define MIFARE_EV1_UIDF0 0x00 +#define MIFARE_EV1_UIDF1 0x40 +#define MIFARE_EV1_UIDF2 0x20 +#define MIFARE_EV1_UIDF3 0x60 #define MIFARE_EV1_SETMODE 0x43 #define MIFARE_ULC_WRITE 0xA2 diff --git a/include/usb_cmd.h b/include/usb_cmd.h index c998bf94..1bc5e5ba 100644 --- a/include/usb_cmd.h +++ b/include/usb_cmd.h @@ -197,17 +197,17 @@ typedef struct{ #define CMD_MIFARE_ACQUIRE_ENCRYPTED_NONCES 0x0613 #define CMD_MIFARE_READBL 0x0620 -#define CMD_MIFAREU_READBL 0x0720 #define CMD_MIFARE_READSC 0x0621 -#define CMD_MIFAREU_READCARD 0x0721 #define CMD_MIFARE_WRITEBL 0x0622 -#define CMD_MIFAREU_WRITEBL 0x0722 -#define CMD_MIFAREU_WRITEBL_COMPAT 0x0723 - #define CMD_MIFARE_CHKKEYS 0x0623 - +#define CMD_MIFARE_PERSONALIZE_UID 0x0624 #define CMD_MIFARE_SNIFFER 0x0630 + //ultralightC +#define CMD_MIFAREU_READBL 0x0720 +#define CMD_MIFAREU_READCARD 0x0721 +#define CMD_MIFAREU_WRITEBL 0x0722 +#define CMD_MIFAREU_WRITEBL_COMPAT 0x0723 #define CMD_MIFAREUC_AUTH 0x0724 //0x0725 and 0x0726 no longer used #define CMD_MIFAREUC_SETPWD 0x0727