diff --git a/armsrc/mifarecmd.c b/armsrc/mifarecmd.c index 32e90d56a3..dfdad54a17 100644 --- a/armsrc/mifarecmd.c +++ b/armsrc/mifarecmd.c @@ -58,8 +58,8 @@ static uint8_t dummy_answer = 0; //----------------------------------------------------------------------------- // Select, Authenticate, Read a MIFARE tag. -// key_auth_cmd is one of MIFARE_AUTH_KEYA, MIFARE_AUTH_KEYB, or MIFARE_MAGIC_GDM_AUTH_KEY -// read_cmd is one of ISO14443A_CMD_READBLOCK, MIFARE_MAGIC_GDM_READBLOCK, or MIFARE_MAGIC_GDM_READ_CFG +// key_auth_cmd is one of MIFARE_AUTH_KEYA, MIFARE_AUTH_KEYB, or MIFARE_MAGIC_USCUID_AUTH_KEY +// read_cmd is one of ISO14443A_CMD_READBLOCK, MIFARE_MAGIC_USCUID_READBLOCK, or MIFARE_MAGIC_USCUID_READ_CFG // block_data must be 16*count bytes large // block_no through block_no+count-1 normally needs to be within the same sector //----------------------------------------------------------------------------- @@ -127,8 +127,8 @@ int16_t mifare_cmd_readblocks(uint8_t key_auth_cmd, uint8_t *key, uint8_t read_c //----------------------------------------------------------------------------- // Select, Authenticate, Write a MIFARE tag. -// key_auth_cmd is one of MIFARE_AUTH_KEYA, MIFARE_AUTH_KEYB, or MIFARE_MAGIC_GDM_AUTH_KEY -// write_cmd is one of ISO14443A_CMD_WRITEBLOCK, MIFARE_MAGIC_GDM_WRITEBLOCK, or MIFARE_MAGIC_GDM_WRITE_CFG +// key_auth_cmd is one of MIFARE_AUTH_KEYA, MIFARE_AUTH_KEYB, or MIFARE_MAGIC_USCUID_AUTH_KEY +// write_cmd is one of ISO14443A_CMD_WRITEBLOCK, MIFARE_MAGIC_USCUID_WRITEBLOCK, or MIFARE_MAGIC_USCUID_WRITE_CFG // block_data must be 16*count bytes large // block_no through block_no+count-1 normally needs to be within the same sector //----------------------------------------------------------------------------- @@ -2208,7 +2208,9 @@ int MifareECardLoad(uint8_t sectorcnt, uint8_t keytype) { //----------------------------------------------------------------------------- // magic uid card generation 1 commands static uint8_t wupC1[] = { MIFARE_MAGICWUPC1 }; +static uint8_t wupU1[] = { MIFARE_MAGICWUPU1 }; static uint8_t wupC2[] = { MIFARE_MAGICWUPC2 }; +//static uint8_t wupU2[] = { MIFARE_MAGICWUPU2 }; static uint8_t wipeC[] = { MIFARE_MAGICWIPEC }; void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain) { @@ -2418,13 +2420,17 @@ void MifareCIdent(bool is_mfc) { uint8_t isGen = 0; uint8_t rec[1] = {0x00}; uint8_t recpar[1] = {0x00}; + uint8_t usc_getcfg[4] = {0xE0, 0x00, 0x39, 0xF7}; uint8_t rats[4] = {ISO14443A_CMD_RATS, 0x80, 0x31, 0x73}; uint8_t rdblf0[4] = {ISO14443A_CMD_READBLOCK, 0xF0, 0x8D, 0x5f}; uint8_t rdbl00[4] = {ISO14443A_CMD_READBLOCK, 0x00, 0x02, 0xa8}; - uint8_t gen4gdm[4] = {MIFARE_MAGIC_GDM_AUTH_KEY, 0x00, 0x6C, 0x92}; - uint8_t gen4GetConf[8] = {GEN_4GTU_CMD, 0x00, 0x00, 0x00, 0x00, GEN_4GTU_GETCNF, 0, 0}; + uint8_t gen4usc[4] = {MIFARE_MAGIC_USCUID_AUTH_KEY, 0x00, 0x6C, 0x92}; + uint8_t tidfind[7] = {0x02, 0x00, 0xEC, 0x00, 0x00, 0xdc, 0xba}; // PLEASE warn if this command changes something in the tag. It seems not to. + uint8_t sidfind[8] = {0x02, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x4b, 0xe3}; + uint8_t sidfind2[8] = {0x02, 0x00, 0xFB, 0x00, 0x00, 0x00, 0xdb, 0x88}; + uint8_t gen4GetVer[8] = {GEN_4UMC_CMD, 0x00, 0x00, 0x00, 0x00, GEN_4UMC_VER, 0, 0}; uint8_t superGen1[9] = {0x0A, 0x00, 0x00, 0xA6, 0xB0, 0x00, 0x10, 0x14, 0x1D}; - + uint8_t superFurui[18] = {0xAA, 0xA5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; uint8_t *par = BigBuf_malloc(MAX_PARITY_SIZE); uint8_t *buf = BigBuf_malloc(PM3_CMD_DATA_SIZE); uint8_t *uid = BigBuf_malloc(10); @@ -2445,11 +2451,20 @@ void MifareCIdent(bool is_mfc) { if (!ReaderReceive(rec, recpar) || (rec[0] != 0x0a)) { isGen = MAGIC_GEN_1B; goto OUT; - }; + } + ReaderTransmit(usc_getcfg, sizeof(usc_getcfg), NULL); + if (ReaderReceive(rec, recpar) && rec[0] == 0x7A ){ + isGen = MAGIC_GEN_4USC; // If we detect a configuration, consider tag as USCUID (even if it is UFUID/...) + goto OUT; + } isGen = MAGIC_GEN_1A; goto OUT; + } else { + ReaderTransmitBitsPar(wupU1, 7, NULL, NULL); // send 0x20 command for USCUID chips + if (ReaderReceive(rec, recpar) && (rec[0] == 0x0a)) { + isGen = MAGIC_GEN_4USC; // as there is no "B" variant of USCUID, only 0x20 ACK is sufficient } - +} // reset card FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); SpinDelay(40); @@ -2457,14 +2472,25 @@ void MifareCIdent(bool is_mfc) { int res = iso14443a_select_card(uid, NULL, &cuid, true, 0, true); if (res == 2) { - // Check for Magic Gen4 GTU with default password: - // Get config should return 30 or 32 bytes - AddCrc14A(gen4GetConf, sizeof(gen4GetConf) - 2); - ReaderTransmit(gen4GetConf, sizeof(gen4GetConf), NULL); + // Find Furui supercard using cloner method + AddCrc14A(superFurui, sizeof(superFurui) - 2); + ReaderTransmit(superFurui, sizeof(superFurui), NULL); + res = ReaderReceive(buf, par); + if (res == 2){ + isGen = MAGIC_SUPER_FURUI; + goto OUT; + } + // Check for Ultimate magic with default password: + // Get version should give 5 bytes + AddCrc14A(gen4GetVer, sizeof(gen4GetVer) - 2); + ReaderTransmit(gen4GetVer, sizeof(gen4GetVer), NULL); res = ReaderReceive(buf, par); - if (res == 32 || res == 34) { - isGen = MAGIC_GEN_4GTU; - goto OUT; + if (memcmp(buf, "\x00\x00\x00\x03\xA0\x34\x8F", 7) == 0){ + isGen = MAGIC_GEN_4UMC3; + goto OUT; + } else if (memcmp(buf, "\x00\x00\x00\x06\xA0\x8C\xF1", 7) == 0) { + isGen = MAGIC_GEN_4UMC6; + goto OUT; } } @@ -2483,6 +2509,25 @@ void MifareCIdent(bool is_mfc) { ReaderTransmit(rats, sizeof(rats), NULL); res = ReaderReceive(buf, par); if (res) { + // Find CPU magic tag (SID/TID) + // As they have ATS based on UID, need to issue APDU + ReaderTransmit(tidfind, sizeof(tidfind), NULL); + res = ReaderReceive(buf, par); + if (memcmp(buf, "\x90\x00\xFD\x07", 4) == 0) { // Must make sure it was a 9000 because FMCOS needs Lc (this doesn't) + isGen = MAGIC_TID; + goto OUT; + } + // Separator + ReaderTransmit(sidfind, sizeof(sidfind), NULL); + res = ReaderReceive(buf, par); + if (res > 9) { // Because it's unknown whether "DEFAULT" can change, we're checking for its presence + ReaderTransmit(sidfind2, sizeof(sidfind2), NULL); + res=ReaderReceive(buf, par); + if (memcmp(buf, "\x6A\x82\x9f\x21", 4) == 0){ + isGen = MAGIC_SID; + goto OUT; + } + } // test for super card ReaderTransmit(superGen1, sizeof(superGen1), NULL); res = ReaderReceive(buf, par); @@ -2501,7 +2546,6 @@ void MifareCIdent(bool is_mfc) { if (res == 18) { isGen = MAGIC_SUPER_GEN2; } - goto OUT; } // test for some MFC gen2 @@ -2568,34 +2612,34 @@ void MifareCIdent(bool is_mfc) { } } - // magic MFC Gen4 GDM test + // magic MFC USCUID test if (isGen != MAGIC_GEN_3) { FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); SpinDelay(40); iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); res = iso14443a_select_card(uid, NULL, &cuid, true, 0, true); if (res == 2) { - ReaderTransmit(gen4gdm, sizeof(gen4gdm), NULL); + ReaderTransmit(gen4usc, sizeof(gen4usc), NULL); res = ReaderReceive(buf, par); if (res == 4) { - isGen = MAGIC_GEN_4GDM; + isGen = MAGIC_GEN_4USC; } } - if (isGen != MAGIC_GEN_4GDM) { - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - SpinDelay(40); - iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); - res = iso14443a_select_card(uid, NULL, &cuid, true, 0, true); - if (res == 2) { - struct Crypto1State mpcs = {0, 0}; - struct Crypto1State *pcs; - pcs = &mpcs; - if (mifare_classic_authex(pcs, cuid, 68, MF_KEY_B, 0x707B11FC1481, AUTH_FIRST, NULL, NULL) == 0) { - isGen = MAGIC_QL88; - } - crypto1_deinit(pcs); - } + if (isGen != MAGIC_GEN_4USC) { + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + SpinDelay(40); + iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); + res = iso14443a_select_card(uid, NULL, &cuid, true, 0, true); + if (res == 2) { + struct Crypto1State mpcs = {0, 0}; + struct Crypto1State *pcs; + pcs = &mpcs; + if (mifare_classic_authex(pcs, cuid, 68, MF_KEY_B, 0x707B11FC1481, AUTH_FIRST, NULL, NULL) == 0) { + isGen = MAGIC_QL88; + } + crypto1_deinit(pcs); + } } } @@ -2879,7 +2923,7 @@ void MifareG4ReadBlk(uint8_t blockno, uint8_t *pwd, uint8_t workFlags) { iso14a_set_timeout(13560000 / 1000 / (8 * 16) * 1000); // 2 seconds timeout } - uint8_t cmd[] = { GEN_4GTU_CMD, 0x00, 0x00, 0x00, 0x00, GEN_4GTU_READ, blockno, + uint8_t cmd[] = { GEN_4UMC_CMD, 0x00, 0x00, 0x00, 0x00, GEN_4UMC_READ, blockno, 0x00, 0x00 }; @@ -2898,7 +2942,7 @@ void MifareG4ReadBlk(uint8_t blockno, uint8_t *pwd, uint8_t workFlags) { LED_B_OFF(); OUT: - reply_ng(CMD_HF_MIFARE_G4_RDBL, retval, buf, res); + reply_ng(CMD_HF_MIFARE_UMC_RDBL, retval, buf, res); // turns off if (done || retval != 0) FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LEDsoff(); @@ -2955,7 +2999,7 @@ void MifareG4WriteBlk(uint8_t blockno, uint8_t *pwd, uint8_t *data, uint8_t work iso14a_set_timeout(13560000 / 1000 / (8 * 16) * 1000); // 2 seconds timeout } - uint8_t cmd[] = { GEN_4GTU_CMD, 0x00, 0x00, 0x00, 0x00, GEN_4GTU_WRITE, blockno, + uint8_t cmd[] = { GEN_4UMC_CMD, 0x00, 0x00, 0x00, 0x00, GEN_4UMC_WRITE, blockno, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 @@ -2977,7 +3021,7 @@ void MifareG4WriteBlk(uint8_t blockno, uint8_t *pwd, uint8_t *data, uint8_t work LED_B_OFF(); OUT: - reply_ng(CMD_HF_MIFARE_G4_WRBL, retval, buf, res); + reply_ng(CMD_HF_MIFARE_UMC_WRBL, retval, buf, res); // turns off if (done || retval != 0) FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LEDsoff();