From 4745afb647c96a80f3f088f2afebf9686499680d Mon Sep 17 00:00:00 2001 From: marshmellow42 Date: Tue, 28 Apr 2015 15:35:23 -0400 Subject: [PATCH 01/49] Iceman's Issue #96 fix --- client/cmdhf14a.c | 49 ++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 40 insertions(+), 9 deletions(-) diff --git a/client/cmdhf14a.c b/client/cmdhf14a.c index d36ebb8be..200c9dcd6 100644 --- a/client/cmdhf14a.c +++ b/client/cmdhf14a.c @@ -152,18 +152,43 @@ int CmdHF14AReader(const char *Cmd) return 0; } - PrintAndLog("ATQA : %02x %02x", card.atqa[1], card.atqa[0]); - PrintAndLog(" UID : %s", sprint_hex(card.uid, card.uidlen)); - PrintAndLog(" SAK : %02x [%d]", card.sak, resp.arg[0]); - - // Double & triple sized UID, can be mapped to a manufacturer. - // HACK: does this apply for Ultralight cards? - if ( card.uidlen > 4 ) { - PrintAndLog("MANUFACTURER : %s", getTagInfo(card.uid[0])); + if(select_status == 3) { + PrintAndLog("Card doesn't support standard iso14443-3 anticollision"); + PrintAndLog("ATQA : %02x %02x", card.atqa[1], card.atqa[0]); + // disconnect + c.arg[0] = 0; + c.arg[1] = 0; + c.arg[2] = 0; + SendCommand(&c); + return 0; } + PrintAndLog(" UID : %s", sprint_hex(card.uid, card.uidlen)); + PrintAndLog("ATQA : %02x %02x", card.atqa[1], card.atqa[0]); + PrintAndLog(" SAK : %02x [%d]", card.sak, resp.arg[0]); + switch (card.sak) { - case 0x00: PrintAndLog("TYPE : NXP MIFARE Ultralight | Ultralight C"); break; + case 0x00: + // check if the tag answers to GETVERSION (0x60) + c.arg[0] = ISO14A_RAW | ISO14A_APPEND_CRC | ISO14A_NO_DISCONNECT; + c.arg[1] = 1; + c.arg[2] = 0; + c.d.asBytes[0] = 0x60; + SendCommand(&c); + WaitForResponse(CMD_ACK,&resp); + + uint8_t version[8] = {0,0,0,0,0,0,0,0}; + memcpy(&version, resp.d.asBytes, resp.arg[0]); + uint8_t len = resp.arg[0] & 0xff; + switch ( len ){ + // todo, identify "Magic UL-C tags". // they usually have a static nonce response to 0x1A command. + // UL-EV1, size, check version[6] == 0x0b (smaller) 0x0b * 4 == 48 + case 0x0A:PrintAndLog("TYPE : NXP MIFARE Ultralight EV1 %d bytes", (version[6] == 0xB) ? 48 : 128);break; + case 0x01:PrintAndLog("TYPE : NXP MIFARE Ultralight C");break; + case 0x00:PrintAndLog("TYPE : NXP MIFARE Ultralight");break; + } + + break; case 0x01: PrintAndLog("TYPE : NXP TNP3xxx Activision Game Appliance"); break; case 0x04: PrintAndLog("TYPE : NXP MIFARE (various !DESFire !DESFire EV1)"); break; case 0x08: PrintAndLog("TYPE : NXP MIFARE CLASSIC 1k | Plus 2k SL1"); break; @@ -180,6 +205,12 @@ int CmdHF14AReader(const char *Cmd) default: ; } + // Double & triple sized UID, can be mapped to a manufacturer. + // HACK: does this apply for Ultralight cards? + if ( card.uidlen > 4 ) { + PrintAndLog("MANUFACTURER : %s", getTagInfo(card.uid[0])); + } + // try to request ATS even if tag claims not to support it if (select_status == 2) { uint8_t rats[] = { 0xE0, 0x80 }; // FSDI=8 (FSD=256), CID=0 From e9b8d0dd6edea3ecac7d663024d38ad549c62f42 Mon Sep 17 00:00:00 2001 From: marshmellow42 Date: Tue, 28 Apr 2015 15:43:58 -0400 Subject: [PATCH 02/49] Iceman's mf sim 7bt UID fix from #97 --- armsrc/iso14443a.c | 1 + 1 file changed, 1 insertion(+) diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c index ac839cfdc..64bbcbf50 100644 --- a/armsrc/iso14443a.c +++ b/armsrc/iso14443a.c @@ -2270,6 +2270,7 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * if (_7BUID) { rATQA[0] = 0x44; rUIDBCC1[0] = 0x88; + rUIDBCC1[4] = rUIDBCC1[0] ^ rUIDBCC1[1] ^ rUIDBCC1[2] ^ rUIDBCC1[3]; rUIDBCC2[4] = rUIDBCC2[0] ^ rUIDBCC2[1] ^ rUIDBCC2[2] ^ rUIDBCC2[3]; } From bdfb62b405a3588e4ce72e02c5e6cee7b977efdb Mon Sep 17 00:00:00 2001 From: marshmellow42 Date: Tue, 28 Apr 2015 15:53:07 -0400 Subject: [PATCH 03/49] Iceman's script aes fix #93 Thanks Iceman (note I did not have a tag to double test this one. :) --- client/scripting.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/scripting.c b/client/scripting.c index 0ccdeeec7..d7f51c234 100644 --- a/client/scripting.c +++ b/client/scripting.c @@ -261,7 +261,7 @@ static int l_aes(lua_State *L) aes_context ctx; aes_init(&ctx); - aes_setkey_enc(&ctx,(const unsigned char *)p_key,128); + aes_setkey_dec(&ctx, aes_key, 128); aes_crypt_cbc(&ctx,AES_DECRYPT,sizeof(indata), iv, indata,outdata ); //Push decrypted array as a string lua_pushlstring(L,(const char *)&outdata, sizeof(outdata)); From b0c76dd2cfd63d8a632637166a16f5f0e31a5563 Mon Sep 17 00:00:00 2001 From: Drewgoo Date: Tue, 28 Apr 2015 22:47:49 -0600 Subject: [PATCH 04/49] Update README.txt typo --- README.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.txt b/README.txt index cb2c7f3c7..1a4ddb6d0 100644 --- a/README.txt +++ b/README.txt @@ -40,7 +40,7 @@ your operating system. Please refer to the Wiki for details. OBTAINING HARDWARE: -The Proxmark 3 is available for purcahse (assembled and tested) from the +The Proxmark 3 is available for purchase (assembled and tested) from the following locations: * http://proxmark3.com/ From f168b2633b28e52e8ca08ace5f3e62f1767d9df2 Mon Sep 17 00:00:00 2001 From: marshmellow42 Date: Wed, 29 Apr 2015 18:27:31 -0400 Subject: [PATCH 05/49] MF Ultralight - Iceman's updates + mine Beginning of Ultralight additions. detection of Ultralight Types added dump command now auto detects type can authenticate Ultralight C --- armsrc/appmain.c | 15 +- armsrc/apps.h | 3 +- armsrc/des.c | 39 ++ armsrc/des.h | 3 + armsrc/mifarecmd.c | 416 ++++++++++++++-------- armsrc/mifareutil.c | 300 ++++++++-------- armsrc/mifareutil.h | 44 +-- client/cmdhfmfu.c | 692 +++++++++++++++++++++++++++--------- client/cmdhfmfu.h | 6 + client/lualibs/commands.lua | 20 +- include/usb_cmd.h | 20 +- 11 files changed, 1040 insertions(+), 518 deletions(-) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 6e0b58b3d..128f4063b 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -738,7 +738,7 @@ void UsbPacketReceived(uint8_t *packet, int len) ReaderHitag((hitag_function)c->arg[0],(hitag_data*)c->d.asBytes); break; #endif - + #ifdef WITH_ISO15693 case CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693: AcquireRawAdcSamplesIso15693(); @@ -818,13 +818,13 @@ void UsbPacketReceived(uint8_t *packet, int len) break; case CMD_READER_MIFARE: - ReaderMifare(c->arg[0]); + ReaderMifare(c->arg[0]); break; case CMD_MIFARE_READBL: MifareReadBlock(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); break; case CMD_MIFAREU_READBL: - MifareUReadBlock(c->arg[0],c->d.asBytes); + MifareUReadBlock(c->arg[0],c->arg[1], c->d.asBytes); break; case CMD_MIFAREUC_AUTH1: MifareUC_Auth1(c->arg[0],c->d.asBytes); @@ -838,6 +838,9 @@ void UsbPacketReceived(uint8_t *packet, int len) case CMD_MIFAREUC_READCARD: MifareUReadCard(c->arg[0], c->arg[1], c->d.asBytes); break; + case CMD_MIFAREUC_SETPWD: + MifareUSetPwd(c->arg[0], c->d.asBytes); + break; case CMD_MIFARE_READSC: MifareReadSector(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); break; @@ -846,10 +849,10 @@ void UsbPacketReceived(uint8_t *packet, int len) break; case CMD_MIFAREU_WRITEBL_COMPAT: MifareUWriteBlock(c->arg[0], c->d.asBytes); - break; + break; case CMD_MIFAREU_WRITEBL: - MifareUWriteBlock_Special(c->arg[0], c->d.asBytes); - break; + MifareUWriteBlock_Special(c->arg[0], c->d.asBytes); + break; case CMD_MIFARE_NESTED: MifareNested(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); break; diff --git a/armsrc/apps.h b/armsrc/apps.h index 928a3075f..7e4aa5e1a 100644 --- a/armsrc/apps.h +++ b/armsrc/apps.h @@ -165,7 +165,7 @@ void EPA_PACE_Collect_Nonce(UsbCommand * c); void ReaderMifare(bool first_try); int32_t dist_nt(uint32_t nt1, uint32_t nt2); void MifareReadBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *data); -void MifareUReadBlock(uint8_t arg0,uint8_t *datain); +void MifareUReadBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain); void MifareUC_Auth1(uint8_t arg0, uint8_t *datain); void MifareUC_Auth2(uint32_t arg0, uint8_t *datain); void MifareUReadCard(uint8_t arg0, int Pages, uint8_t *datain); @@ -184,6 +184,7 @@ void MifareECardLoad(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain); // Work with "magic Chinese" card 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); diff --git a/armsrc/des.c b/armsrc/des.c index 0a27503e0..dbe62da99 100644 --- a/armsrc/des.c +++ b/armsrc/des.c @@ -378,6 +378,45 @@ void tdes_dec(void* out, void* in, const uint8_t* key){ des_dec(out, out, (uint8_t*)key + 0); } +void tdes_2key_enc(void* out, const void* in, size_t length, const void* key){ + + if( length % 8 ) return; + + uint8_t* tin = (uint8_t*) in; + uint8_t* tout = (uint8_t*) out; + + while( length > 0 ) + { + des_enc(tout, tin, (uint8_t*)key + 0); + des_dec(tout, tout, (uint8_t*)key + 8); + des_enc(tout, tout, (uint8_t*)key + 0); + + tin += 8; + tout += 8; + length -= 8; + } +} + +void tdes_2key_dec(void* out, const void* in, size_t length, const void* key){ + + if( length % 8 ) return; + + uint8_t* tin = (uint8_t*) in; + uint8_t* tout = (uint8_t*) out; + + while( length > 0 ) + { + des_dec(tout, tin, (uint8_t*)key + 0); + des_enc(tout, tout, (uint8_t*)key + 8); + des_dec(tout, tout, (uint8_t*)key + 0); + + tin += 8; + tout += 8; + length -= 8; + } +} + + /******************************************************************************/ diff --git a/armsrc/des.h b/armsrc/des.h index 652886fd7..cc1d59b01 100644 --- a/armsrc/des.h +++ b/armsrc/des.h @@ -97,6 +97,9 @@ void tdes_enc(void* out, const void* in, const void* key); */ void tdes_dec(void* out, const void* in, const void* key); + void tdes_2key_enc(void* out, const void* in, size_t length, const void* key); + void tdes_2key_dec(void* out, const void* in, size_t length, const void* key); + #endif /*DES_H_*/ // Copied from des.h in desfire imp. diff --git a/armsrc/mifarecmd.c b/armsrc/mifarecmd.c index a16cbf166..3d5dcdef1 100644 --- a/armsrc/mifarecmd.c +++ b/armsrc/mifarecmd.c @@ -17,8 +17,15 @@ #include "apps.h" #include "util.h" +#include "des.h" #include "crc.h" +// the block number for the ISO14443-4 PCB +uint8_t pcb_blocknum = 0; +// Deselect card by sending a s-block. the crc is precalced for speed +static uint8_t deselect_cmd[] = {0xc2,0xe0,0xb4}; + + //----------------------------------------------------------------------------- // Select, Authenticate, Read a MIFARE tag. // read block @@ -86,111 +93,164 @@ void MifareReadBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) LEDsoff(); } - void MifareUC_Auth1(uint8_t arg0, uint8_t *datain){ - byte_t isOK = 0; byte_t dataoutbuf[16] = {0x00}; uint8_t uid[10] = {0x00}; - uint32_t cuid; + uint32_t cuid = 0x00; - LED_A_ON(); - LED_B_OFF(); - LED_C_OFF(); + LED_A_ON(); LED_B_OFF(); LED_C_OFF(); clear_trace(); iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); if(!iso14443a_select_card(uid, NULL, &cuid)) { - if (MF_DBGLEVEL >= MF_DBG_ERROR) - Dbprintf("Can't select card"); - //OnError(0); + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Can't select card"); + OnError(0); return; }; - if(mifare_ultra_auth1(cuid, dataoutbuf)){ - if (MF_DBGLEVEL >= MF_DBG_ERROR) - Dbprintf("Authentication part1: Fail."); - //OnError(1); + if(mifare_ultra_auth1(dataoutbuf)){ + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Authentication part1: Fail."); + OnError(1); return; } - isOK = 1; - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) - DbpString("AUTH 1 FINISHED"); + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) DbpString("AUTH 1 FINISHED"); - cmd_send(CMD_ACK,isOK,cuid,0,dataoutbuf,11); + cmd_send(CMD_ACK,1,cuid,0,dataoutbuf,11); LEDsoff(); } void MifareUC_Auth2(uint32_t arg0, uint8_t *datain){ - uint32_t cuid = arg0; uint8_t key[16] = {0x00}; - byte_t isOK = 0; byte_t dataoutbuf[16] = {0x00}; memcpy(key, datain, 16); - LED_A_ON(); - LED_B_OFF(); - LED_C_OFF(); + LED_A_ON(); LED_B_OFF(); LED_C_OFF(); - if(mifare_ultra_auth2(cuid, key, dataoutbuf)){ - if (MF_DBGLEVEL >= MF_DBG_ERROR) - Dbprintf("Authentication part2: Fail..."); - //OnError(1); + if(mifare_ultra_auth2(key, dataoutbuf)){ + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Authentication part2: Fail..."); + OnError(1); return; } - isOK = 1; - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) - DbpString("AUTH 2 FINISHED"); + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) DbpString("AUTH 2 FINISHED"); - cmd_send(CMD_ACK,isOK,0,0,dataoutbuf,11); + cmd_send(CMD_ACK,1,0,0,dataoutbuf,11); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LEDsoff(); } -void MifareUReadBlock(uint8_t arg0,uint8_t *datain) +void MifareUReadBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain) { uint8_t blockNo = arg0; byte_t dataout[16] = {0x00}; uint8_t uid[10] = {0x00}; - uint32_t cuid; - - LED_A_ON(); - LED_B_OFF(); - LED_C_OFF(); - + uint8_t key[16] = {0x00}; + bool usePwd = (arg1 == 1); + + LED_A_ON(); LED_B_OFF(); LED_C_OFF(); + clear_trace(); iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); - - int len = iso14443a_select_card(uid, NULL, &cuid); + + int len = iso14443a_select_card(uid, NULL, NULL); if(!len) { - if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Can't select card"); - //OnError(1); + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Can't select card (RC:%02X)",len); + OnError(1); return; - }; - - len = mifare_ultra_readblock(cuid, blockNo, dataout); - if(len) { - if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Read block error"); - //OnError(2); - return; - }; - - len = mifare_ultra_halt(cuid); - if(len) { - if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Halt error"); - //OnError(3); - return; - }; + } + + // authenticate here. + if ( usePwd ) { + + memcpy(key, datain, 16); + + // Dbprintf("KEY: %02x %02x %02x %02x %02x %02x %02x %02x", key[0],key[1],key[2],key[3],key[4],key[5],key[6],key[7] ); + // Dbprintf("KEY: %02x %02x %02x %02x %02x %02x %02x %02x", key[8],key[9],key[10],key[11],key[12],key[13],key[14],key[15] ); + + uint8_t a[8] = {1,1,1,1,1,1,1,1 }; + uint8_t b[8] = {0x00}; + uint8_t enc_b[8] = {0x00}; + uint8_t ab[16] = {0x00}; + uint8_t enc_ab[16] = {0x00}; + uint8_t enc_key[8] = {0x00}; - cmd_send(CMD_ACK,1,0,0,dataout,16); + uint16_t len; + uint8_t receivedAnswer[MAX_FRAME_SIZE]; + uint8_t receivedAnswerPar[MAX_PARITY_SIZE]; + + len = mifare_sendcmd_short(NULL, 1, 0x1A, 0x00, receivedAnswer,receivedAnswerPar ,NULL); + if (len != 11) { + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x", receivedAnswer[0]); + OnError(1); + return; + } + + // tag nonce. + memcpy(enc_b,receivedAnswer+1,8); + + // decrypt nonce. + tdes_2key_dec(b, enc_b, 8, key ); + + Dbprintf("enc_B: %02x %02x %02x %02x %02x %02x %02x %02x", enc_b[0],enc_b[1],enc_b[2],enc_b[3],enc_b[4],enc_b[5],enc_b[6],enc_b[7] ); + Dbprintf(" B: %02x %02x %02x %02x %02x %02x %02x %02x", b[0],b[1],b[2],b[3],b[4],b[5],b[6],b[7] ); + rol(b,8); + + memcpy(ab ,a,8); + memcpy(ab+8,b,8); + + Dbprintf("AB: %02x %02x %02x %02x %02x %02x %02x %02x", ab[0],ab[1],ab[2],ab[3],ab[4],ab[5],ab[6],ab[7] ); + Dbprintf("AB: %02x %02x %02x %02x %02x %02x %02x %02x", ab[8],ab[9],ab[10],ab[11],ab[12],ab[13],ab[14],ab[15] ); + + // encrypt + tdes_2key_enc(enc_ab, ab, 16, key); + + Dbprintf("e_AB: %02x %02x %02x %02x %02x %02x %02x %02x", enc_ab[0],enc_ab[1],enc_ab[2],enc_ab[3],enc_ab[4],enc_ab[5],enc_ab[6],enc_ab[7] ); + Dbprintf("e_enc_ab: %02x %02x %02x %02x %02x %02x %02x %02x", enc_ab[8],enc_ab[9],enc_ab[10],enc_ab[11],enc_ab[12],enc_ab[13],enc_ab[14],enc_ab[15] ); + + len = mifare_sendcmd_short_mfucauth(NULL, 1, 0xAF, enc_ab, receivedAnswer, receivedAnswerPar, NULL); + if (len != 11) { + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x", receivedAnswer[0]); + OnError(1); + return; + } + + // the tags' encryption of our nonce, A. + memcpy(enc_key, receivedAnswer+1, 8); + + // clear B. + memset(b, 0x00, 8); + + // decrypt + tdes_2key_dec(b, enc_key, 8, key ); + if ( memcmp(a, b, 8) == 0 ) + Dbprintf("Verified key"); + else + Dbprintf("failed authentication"); + + Dbprintf("a: %02x %02x %02x %02x %02x %02x %02x %02x", a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7] ); + Dbprintf("b: %02x %02x %02x %02x %02x %02x %02x %02x", b[0],b[1],b[2],b[3],b[4],b[5],b[6],b[7] ); + } + + if( mifare_ultra_readblock(blockNo, dataout) ) { + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Read block error"); + OnError(2); + return; + } + + if( mifare_ultra_halt() ) { + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Halt error"); + OnError(3); + return; + } + + cmd_send(CMD_ACK,1,0,0,dataout,16); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LEDsoff(); } - //----------------------------------------------------------------------------- // Select, Authenticate, Read a MIFARE tag. // read sector (data = 4 x 16 bytes = 64 bytes, or 16 x 16 bytes = 256 bytes) @@ -261,71 +321,58 @@ void MifareReadSector(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) void MifareUReadCard(uint8_t arg0, int arg1, uint8_t *datain) { - // params - uint8_t sectorNo = arg0; + // params + uint8_t sectorNo = arg0; int Pages = arg1; - int count_Pages = 0; + int countpages = 0; byte_t dataout[176] = {0x00};; - uint8_t uid[10] = {0x00}; - uint32_t cuid; + uint32_t cuid = 0x00; - LED_A_ON(); - LED_B_OFF(); - LED_C_OFF(); - - if (MF_DBGLEVEL >= MF_DBG_ALL) - Dbprintf("Pages %d",Pages); - + LED_A_ON(); LED_B_OFF(); LED_C_OFF(); clear_trace(); iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); - int len = iso14443a_select_card(uid, NULL, &cuid); - + int len = iso14443a_select_card(NULL, NULL, &cuid); if (!len) { - if (MF_DBGLEVEL >= MF_DBG_ERROR) - Dbprintf("Can't select card"); - //OnError(1); + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Can't select card (RC:%d)",len); + OnError(1); return; } for (int i = 0; i < Pages; i++){ - len = mifare_ultra_readblock(cuid, sectorNo * 4 + i, dataout + 4 * i); + len = mifare_ultra_readblock(sectorNo * 4 + i, dataout + 4 * i); if (len) { - if (MF_DBGLEVEL >= MF_DBG_ERROR) - Dbprintf("Read block %d error",i); - //OnError(2); + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Read block %d error",i); + OnError(2); return; } else { - count_Pages++; + countpages++; } } - len = mifare_ultra_halt(cuid); + len = mifare_ultra_halt(); if (len) { - if (MF_DBGLEVEL >= MF_DBG_ERROR) - Dbprintf("Halt error"); - //OnError(3); + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Halt error"); + OnError(3); return; } - if (MF_DBGLEVEL >= MF_DBG_ALL) { - Dbprintf("Pages read %d", count_Pages); - } + if (MF_DBGLEVEL >= MF_DBG_ALL) Dbprintf("Pages read %d", countpages); + +// len = 16*4; //64 bytes - len = 16*4; //64 bytes - // Read a UL-C - if (Pages == 44 && count_Pages > 16) - len = 176; +// if (Pages == 44 && countpages > 16) +// len = 176; + len = Pages * 4; cmd_send(CMD_ACK, 1, 0, 0, dataout, len); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LEDsoff(); } - //----------------------------------------------------------------------------- // Select, Authenticate, Write a MIFARE tag. // read block @@ -400,94 +447,144 @@ void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) void MifareUWriteBlock(uint8_t arg0, uint8_t *datain) { - // params - uint8_t blockNo = arg0; + uint8_t blockNo = arg0; byte_t blockdata[16] = {0x00}; - memcpy(blockdata, datain,16); - - // variables - byte_t isOK = 0; + memcpy(blockdata, datain, 16); + uint8_t uid[10] = {0x00}; - uint32_t cuid; - clear_trace(); - iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); + LED_A_ON(); LED_B_OFF(); LED_C_OFF(); - LED_A_ON(); - LED_B_OFF(); - LED_C_OFF(); + clear_trace(); + iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); - while (true) { - if(!iso14443a_select_card(uid, NULL, &cuid)) { - if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card"); - break; - }; + if(!iso14443a_select_card(uid, NULL, NULL)) { + if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card"); + OnError(0); + return; + }; - if(mifare_ultra_writeblock(cuid, blockNo, blockdata)) { - if (MF_DBGLEVEL >= 1) Dbprintf("Write block error"); - break; - }; + if(mifare_ultra_writeblock(blockNo, blockdata)) { + if (MF_DBGLEVEL >= 1) Dbprintf("Write block error"); + OnError(0); + return; }; - if(mifare_ultra_halt(cuid)) { - if (MF_DBGLEVEL >= 1) Dbprintf("Halt error"); - break; - }; - - isOK = 1; - break; - } - - if (MF_DBGLEVEL >= 2) DbpString("WRITE BLOCK FINISHED"); + if(mifare_ultra_halt()) { + if (MF_DBGLEVEL >= 1) Dbprintf("Halt error"); + OnError(0); + return; + }; - cmd_send(CMD_ACK,isOK,0,0,0,0); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - LEDsoff(); + if (MF_DBGLEVEL >= 2) DbpString("WRITE BLOCK FINISHED"); + + cmd_send(CMD_ACK,1,0,0,0,0); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LEDsoff(); } void MifareUWriteBlock_Special(uint8_t arg0, uint8_t *datain) { - // params uint8_t blockNo = arg0; byte_t blockdata[4] = {0x00}; memcpy(blockdata, datain,4); - // variables - byte_t isOK = 0; uint8_t uid[10] = {0x00}; - uint32_t cuid; - + + LED_A_ON(); LED_B_OFF(); LED_C_OFF(); clear_trace(); iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); - LED_A_ON(); - LED_B_OFF(); - LED_C_OFF(); + if(!iso14443a_select_card(uid, NULL, NULL)) { + if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card"); + OnError(0); + return; + }; - while (true) { - if(!iso14443a_select_card(uid, NULL, &cuid)) { - if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card"); - break; - }; + if(mifare_ultra_special_writeblock(blockNo, blockdata)) { + if (MF_DBGLEVEL >= 1) Dbprintf("Write block error"); + OnError(0); + return; + }; - if(mifare_ultra_special_writeblock(cuid, blockNo, blockdata)) { - if (MF_DBGLEVEL >= 1) Dbprintf("Write block error"); - break; - }; + if(mifare_ultra_halt()) { + if (MF_DBGLEVEL >= 1) Dbprintf("Halt error"); + OnError(0); + return; + }; - if(mifare_ultra_halt(cuid)) { - if (MF_DBGLEVEL >= 1) Dbprintf("Halt error"); - break; - }; + if (MF_DBGLEVEL >= 2) DbpString("WRITE BLOCK FINISHED"); - isOK = 1; - break; - } + cmd_send(CMD_ACK,1,0,0,0,0); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LEDsoff(); +} - if (MF_DBGLEVEL >= 2) DbpString("WRITE BLOCK FINISHED"); +void MifareUSetPwd(uint8_t arg0, uint8_t *datain){ + + uint8_t pwd[16] = {0x00}; + byte_t blockdata[4] = {0x00}; + + memcpy(pwd, datain, 16); + + LED_A_ON(); LED_B_OFF(); LED_C_OFF(); + clear_trace(); + iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); - cmd_send(CMD_ACK,isOK,0,0,0,0); + if(!iso14443a_select_card(NULL, NULL, NULL)) { + if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card"); + OnError(0); + return; + }; + + blockdata[0] = pwd[7]; + blockdata[1] = pwd[6]; + blockdata[2] = pwd[5]; + blockdata[3] = pwd[4]; + if(mifare_ultra_special_writeblock( 44, blockdata)) { + if (MF_DBGLEVEL >= 1) Dbprintf("Write block error"); + OnError(44); + return; + }; + + blockdata[0] = pwd[3]; + blockdata[1] = pwd[2]; + blockdata[2] = pwd[1]; + blockdata[3] = pwd[0]; + if(mifare_ultra_special_writeblock( 45, blockdata)) { + if (MF_DBGLEVEL >= 1) Dbprintf("Write block error"); + OnError(45); + return; + }; + + blockdata[0] = pwd[15]; + blockdata[1] = pwd[14]; + blockdata[2] = pwd[13]; + blockdata[3] = pwd[12]; + if(mifare_ultra_special_writeblock( 46, blockdata)) { + if (MF_DBGLEVEL >= 1) Dbprintf("Write block error"); + OnError(46); + return; + }; + + blockdata[0] = pwd[11]; + blockdata[1] = pwd[10]; + blockdata[2] = pwd[9]; + blockdata[3] = pwd[8]; + if(mifare_ultra_special_writeblock( 47, blockdata)) { + if (MF_DBGLEVEL >= 1) Dbprintf("Write block error"); + OnError(47); + return; + }; + + if(mifare_ultra_halt()) { + if (MF_DBGLEVEL >= 1) Dbprintf("Halt error"); + OnError(0); + return; + }; + + cmd_send(CMD_ACK,1,0,0,0,0); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LEDsoff(); } @@ -1184,3 +1281,18 @@ void Mifare_DES_Auth2(uint32_t arg0, uint8_t *datain){ FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LEDsoff(); } + +void OnSuccess(){ + pcb_blocknum = 0; + ReaderTransmit(deselect_cmd, 3 , NULL); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LEDsoff(); +} + +void OnError(uint8_t reason){ + pcb_blocknum = 0; + ReaderTransmit(deselect_cmd, 3 , NULL); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + cmd_send(CMD_ACK,0,reason,0,0,0); + LEDsoff(); +} diff --git a/armsrc/mifareutil.c b/armsrc/mifareutil.c index f79c2ede2..b7408cf1d 100644 --- a/armsrc/mifareutil.c +++ b/armsrc/mifareutil.c @@ -67,24 +67,24 @@ uint8_t mf_crypto1_encrypt4bit(struct Crypto1State *pcs, uint8_t data) { // send commands int mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t data, uint8_t* answer, uint8_t *answer_parity, uint32_t *timing) { - return mifare_sendcmd_shortex(pcs, crypted, cmd, data, answer, answer_parity, timing); -} - -int mifare_sendcmd_short_special(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t* data, uint8_t* answer, uint8_t *answer_parity, uint32_t *timing) -{ - uint8_t dcmd[8]; - dcmd[0] = cmd; - dcmd[1] = data[0]; - dcmd[2] = data[1]; - dcmd[3] = data[2]; - dcmd[4] = data[3]; - dcmd[5] = data[4]; - AppendCrc14443a(dcmd, 6); - ReaderTransmit(dcmd, sizeof(dcmd), NULL); - int len = ReaderReceive(answer, answer_parity); - if(!len) { - if (MF_DBGLEVEL >= 1) Dbprintf("Authentication failed. Card timeout."); - return 2; + return mifare_sendcmd_shortex(pcs, crypted, cmd, data, answer, answer_parity, timing); +} + +int mifare_sendcmd_short_special(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t* data, uint8_t* answer, uint8_t *answer_parity, uint32_t *timing) +{ + uint8_t dcmd[8]; + dcmd[0] = cmd; + dcmd[1] = data[0]; + dcmd[2] = data[1]; + dcmd[3] = data[2]; + dcmd[4] = data[3]; + dcmd[5] = data[4]; + AppendCrc14443a(dcmd, 6); + ReaderTransmit(dcmd, sizeof(dcmd), NULL); + int len = ReaderReceive(answer, answer_parity); + if(!len) { + if (MF_DBGLEVEL >= 1) Dbprintf("Authentication failed. Card timeout."); + return 2; } return len; } @@ -106,13 +106,13 @@ int mifare_sendcmd_short_mfucauth(struct Crypto1State *pcs, uint8_t crypted, uin if(len==1) { if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("NAK - Authentication failed."); return 1; - } - return len; -} - -int mifare_sendcmd_shortex(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t data, uint8_t *answer, uint8_t *answer_parity, uint32_t *timing) -{ - uint8_t dcmd[4], ecmd[4]; + } + return len; +} + +int mifare_sendcmd_shortex(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t data, uint8_t *answer, uint8_t *answer_parity, uint32_t *timing) +{ + uint8_t dcmd[4], ecmd[4]; uint16_t pos, res; uint8_t par[1]; // 1 Byte parity is enough here dcmd[0] = cmd; @@ -284,24 +284,21 @@ int mifare_classic_readblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blo } memcpy(blockData, receivedAnswer, 16); - return 0; -} - + return 0; +} + // mifare ultralight commands -int mifare_ultra_auth1(uint32_t uid, uint8_t *blockData){ +int mifare_ultra_auth1(uint8_t *blockData){ uint16_t len; - uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE]; - uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE]; + uint8_t receivedAnswer[MAX_FRAME_SIZE]; + uint8_t receivedAnswerPar[MAX_PARITY_SIZE]; len = mifare_sendcmd_short(NULL, 1, 0x1A, 0x00, receivedAnswer,receivedAnswerPar ,NULL); - if (len == 1) { - if (MF_DBGLEVEL >= MF_DBG_ERROR) - Dbprintf("Cmd Error: %02x", receivedAnswer[0]); + if (len != 11) { + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x", receivedAnswer[0]); return 1; } - if (len != 11) - return 1; if (MF_DBGLEVEL >= MF_DBG_EXTENDED) { Dbprintf("Auth1 Resp: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", @@ -313,20 +310,17 @@ int mifare_ultra_auth1(uint32_t uid, uint8_t *blockData){ return 0; } -int mifare_ultra_auth2(uint32_t uid, uint8_t *key, uint8_t *blockData){ +int mifare_ultra_auth2(uint8_t *key, uint8_t *blockData){ uint16_t len; - uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE]; - uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE]; + uint8_t receivedAnswer[MAX_FRAME_SIZE]; + uint8_t receivedAnswerPar[MAX_PARITY_SIZE]; len = mifare_sendcmd_short_mfucauth(NULL, 1, 0xAF, key, receivedAnswer, receivedAnswerPar, NULL); - if (len == 1) { - if (MF_DBGLEVEL >= MF_DBG_ERROR) - Dbprintf("Cmd Error: %02x", receivedAnswer[0]); + if (len != 11) { + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x", receivedAnswer[0]); return 1; } - if (len != 11) - return 1; if (MF_DBGLEVEL >= MF_DBG_EXTENDED) { Dbprintf("Auth2 Resp: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", @@ -338,43 +332,39 @@ int mifare_ultra_auth2(uint32_t uid, uint8_t *key, uint8_t *blockData){ return 0; } -int mifare_ultra_readblock(uint32_t uid, uint8_t blockNo, uint8_t *blockData) -{ - uint16_t len; - uint8_t bt[2]; - uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE]; - uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE]; - +int mifare_ultra_readblock(uint8_t blockNo, uint8_t *blockData) +{ + uint16_t len; + uint8_t bt[2]; + uint8_t receivedAnswer[MAX_FRAME_SIZE]; + uint8_t receivedAnswerPar[MAX_PARITY_SIZE]; - // command MIFARE_CLASSIC_READBLOCK - len = mifare_sendcmd_short(NULL, 1, 0x30, blockNo, receivedAnswer, receivedAnswerPar, NULL); - if (len == 1) { - if (MF_DBGLEVEL >= MF_DBG_ERROR) - Dbprintf("Cmd Error: %02x", receivedAnswer[0]); - return 1; - } - if (len != 18) { - if (MF_DBGLEVEL >= MF_DBG_ERROR) - Dbprintf("Cmd Error: card timeout. len: %x", len); - return 2; - } - - memcpy(bt, receivedAnswer + 16, 2); - AppendCrc14443a(receivedAnswer, 16); - if (bt[0] != receivedAnswer[16] || bt[1] != receivedAnswer[17]) { - if (MF_DBGLEVEL >= MF_DBG_ERROR) - Dbprintf("Cmd CRC response error."); - return 3; - } - - memcpy(blockData, receivedAnswer, 14); - return 0; -} - - -int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData) -{ - // variables + len = mifare_sendcmd_short(NULL, 1, 0x30, blockNo, receivedAnswer, receivedAnswerPar, NULL); + if (len == 1) { + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x", receivedAnswer[0]); + return 1; + } + if (len != 18) { + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: card timeout. len: %x", len); + return 2; + } + + memcpy(bt, receivedAnswer + 16, 2); + AppendCrc14443a(receivedAnswer, 16); + if (bt[0] != receivedAnswer[16] || bt[1] != receivedAnswer[17]) { + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd CRC response error."); + return 3; + } + + memcpy(blockData, receivedAnswer, 14); + return 0; +} + + + +int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData) +{ + // variables uint16_t len, i; uint32_t pos; uint8_t par[3] = {0}; // enough for 18 Bytes to send @@ -416,65 +406,65 @@ int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t bl return 2; } - return 0; -} - -int mifare_ultra_writeblock(uint32_t uid, 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}; + return 0; +} + +int mifare_ultra_writeblock(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]; + + // command MIFARE_CLASSIC_WRITEBLOCK + len = mifare_sendcmd_short(NULL, true, 0xA0, blockNo, receivedAnswer, receivedAnswerPar, NULL); + + if ((len != 1) || (receivedAnswer[0] != 0x0A)) { // 0x0a - ACK + if (MF_DBGLEVEL >= MF_DBG_ERROR) + Dbprintf("Cmd Addr Error: %02x", receivedAnswer[0]); + return 1; + } + + memcpy(d_block, blockData, 16); + AppendCrc14443a(d_block, 16); + + ReaderTransmitPar(d_block, sizeof(d_block), par, NULL); + + len = ReaderReceive(receivedAnswer, receivedAnswerPar); + + if ((len != 1) || (receivedAnswer[0] != 0x0A)) { // 0x0a - ACK + if (MF_DBGLEVEL >= MF_DBG_ERROR) + Dbprintf("Cmd Data Error: %02x %d", receivedAnswer[0],len); + return 2; + } + return 0; +} + +int mifare_ultra_special_writeblock(uint8_t blockNo, uint8_t *blockData) +{ + uint16_t len; + uint8_t d_block[8] = {0x00}; uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE]; uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE]; - - // command MIFARE_CLASSIC_WRITEBLOCK - len = mifare_sendcmd_short(NULL, true, 0xA0, blockNo, receivedAnswer, receivedAnswerPar, NULL); - - if ((len != 1) || (receivedAnswer[0] != 0x0A)) { // 0x0a - ACK + + // command MIFARE_CLASSIC_WRITEBLOCK + d_block[0]= blockNo; + memcpy(d_block+1,blockData,4); + AppendCrc14443a(d_block, 6); + + len = mifare_sendcmd_short_special(NULL, 1, 0xA2, d_block, receivedAnswer, receivedAnswerPar, NULL); + + if (receivedAnswer[0] != 0x0A) { // 0x0a - ACK if (MF_DBGLEVEL >= MF_DBG_ERROR) - Dbprintf("Cmd Addr Error: %02x", receivedAnswer[0]); - return 1; - } - - memcpy(d_block, blockData, 16); - AppendCrc14443a(d_block, 16); - - ReaderTransmitPar(d_block, sizeof(d_block), par, NULL); - - len = ReaderReceive(receivedAnswer, receivedAnswerPar); - - if ((len != 1) || (receivedAnswer[0] != 0x0A)) { // 0x0a - ACK - if (MF_DBGLEVEL >= MF_DBG_ERROR) - Dbprintf("Cmd Data Error: %02x %d", receivedAnswer[0],len); - return 2; - } - return 0; -} - -int mifare_ultra_special_writeblock(uint32_t uid, uint8_t blockNo, uint8_t *blockData) -{ - uint16_t len; - uint8_t d_block[8] = {0x00}; - uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE]; - uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE]; - - // command MIFARE_CLASSIC_WRITEBLOCK - d_block[0]= blockNo; - memcpy(d_block+1,blockData,4); - AppendCrc14443a(d_block, 6); - - len = mifare_sendcmd_short_special(NULL, 1, 0xA2, d_block, receivedAnswer, receivedAnswerPar, NULL); - - if (receivedAnswer[0] != 0x0A) { // 0x0a - ACK - if (MF_DBGLEVEL >= MF_DBG_ERROR) - Dbprintf("Cmd Send Error: %02x %d", receivedAnswer[0],len); - return 1; - } - return 0; -} - -int mifare_classic_halt(struct Crypto1State *pcs, uint32_t uid) -{ + Dbprintf("Cmd Send Error: %02x %d", receivedAnswer[0],len); + return 1; + } + return 0; +} + +int mifare_classic_halt(struct Crypto1State *pcs, uint32_t uid) +{ uint16_t len; uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE]; uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE]; @@ -486,24 +476,24 @@ int mifare_classic_halt(struct Crypto1State *pcs, uint32_t uid) return 1; } - return 0; -} - -int mifare_ultra_halt(uint32_t uid) -{ - uint16_t len; + return 0; +} + +int mifare_ultra_halt() +{ + uint16_t len; 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); - if (len != 0) { + + len = mifare_sendcmd_short(NULL, true, 0x50, 0x00, receivedAnswer, receivedAnswerPar, NULL); + if (len != 0) { if (MF_DBGLEVEL >= MF_DBG_ERROR) - Dbprintf("halt error. response len: %x", len); - return 1; - } - return 0; -} - + Dbprintf("halt error. response len: %x", len); + return 1; + } + return 0; +} + // Mifare Memory Structure: up to 32 Sectors with 4 blocks each (1k and 2k cards), // plus evtl. 8 sectors with 16 blocks each (4k cards) @@ -525,9 +515,9 @@ uint8_t FirstBlockOfSector(uint8_t sectorNo) } -// work with emulator memory -void emlSetMem(uint8_t *data, int blockNum, int blocksCount) { - uint8_t* emCARD = BigBuf_get_EM_addr(); +// work with emulator memory +void emlSetMem(uint8_t *data, int blockNum, int blocksCount) { + uint8_t* emCARD = BigBuf_get_EM_addr(); memcpy(emCARD + blockNum * 16, data, blocksCount * 16); } @@ -706,4 +696,4 @@ int mifare_desfire_des_auth2(uint32_t uid, uint8_t *key, uint8_t *blockData){ return 0; } return 1; -} +} diff --git a/armsrc/mifareutil.h b/armsrc/mifareutil.h index 195afa534..ee3ae7c6e 100644 --- a/armsrc/mifareutil.h +++ b/armsrc/mifareutil.h @@ -52,33 +52,33 @@ extern int MF_DBGLEVEL; #define cardSTATE_TO_IDLE() cardSTATE = MFEMUL_IDLE; LED_B_OFF(); LED_C_OFF(); -//functions -int mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t data, uint8_t* answer, uint8_t *answer_parity, uint32_t *timing); -int mifare_sendcmd_short_special(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t *data, uint8_t* answer, uint8_t *answer_parity, uint32_t *timing); +//functions +int mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t data, uint8_t* answer, uint8_t *answer_parity, uint32_t *timing); +int mifare_sendcmd_short_special(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t *data, uint8_t* answer, uint8_t *answer_parity, uint32_t *timing); int mifare_sendcmd_short_mfucauth(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t *data, uint8_t *answer, uint8_t *answer_parity, uint32_t *timing); -int mifare_sendcmd_shortex(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t data, uint8_t* answer, uint8_t *answer_parity, uint32_t *timing); - +int mifare_sendcmd_shortex(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t data, uint8_t* answer, uint8_t *answer_parity, uint32_t *timing); + int mifare_classic_auth(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested); -int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested, uint32_t * ntptr, uint32_t *timing); -int mifare_classic_readblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData); -int mifare_ultra_auth1(uint32_t cuid, uint8_t *blockData); -int mifare_ultra_auth2(uint32_t cuid, uint8_t *key, uint8_t *blockData); -int mifare_ultra_readblock(uint32_t uid, uint8_t blockNo, uint8_t *blockData); -int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData); -int mifare_ultra_writeblock(uint32_t uid, uint8_t blockNo, uint8_t *blockData); -int mifare_ultra_special_writeblock(uint32_t uid, uint8_t blockNo, uint8_t *blockData); -int mifare_classic_halt(struct Crypto1State *pcs, uint32_t uid); -int mifare_ultra_halt(uint32_t uid); +int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested, uint32_t * ntptr, uint32_t *timing); +int mifare_classic_readblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData); +int mifare_ultra_auth1(uint8_t *blockData); +int mifare_ultra_auth2(uint8_t *key, uint8_t *blockData); +int mifare_ultra_readblock(uint8_t blockNo, uint8_t *blockData); +int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData); +int mifare_ultra_writeblock(uint8_t blockNo, uint8_t *blockData); +int mifare_ultra_special_writeblock(uint8_t blockNo, uint8_t *blockData); +int mifare_classic_halt(struct Crypto1State *pcs, uint32_t uid); +int mifare_ultra_halt(); // desfire int mifare_sendcmd_special(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t* data, uint8_t* answer, uint8_t *answer_parity, uint32_t *timing); int mifare_sendcmd_special2(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t* data, uint8_t* answer,uint8_t *answer_parity, uint32_t *timing); int mifare_desfire_des_auth1(uint32_t uid, uint8_t *blockData); int mifare_desfire_des_auth2(uint32_t uid, uint8_t *key, uint8_t *blockData); - -// crypto functions -void mf_crypto1_decrypt(struct Crypto1State *pcs, uint8_t *receivedCmd, int len); + +// crypto functions +void mf_crypto1_decrypt(struct Crypto1State *pcs, uint8_t *receivedCmd, int len); void mf_crypto1_encrypt(struct Crypto1State *pcs, uint8_t *data, uint16_t len, uint8_t *par); uint8_t mf_crypto1_encrypt4bit(struct Crypto1State *pcs, uint8_t data); @@ -93,7 +93,7 @@ void emlGetMem(uint8_t *data, int blockNum, int blocksCount); void emlGetMemBt(uint8_t *data, int bytePtr, int byteCount); uint64_t emlGetKey(int sectorNum, int keyType); int emlGetValBl(uint32_t *blReg, uint8_t *blBlock, int blockNum); -int emlSetValBl(uint32_t blReg, uint8_t blBlock, int blockNum); -int emlCheckValBl(int blockNum); - -#endif +int emlSetValBl(uint32_t blReg, uint8_t blBlock, int blockNum); +int emlCheckValBl(int blockNum); + +#endif diff --git a/client/cmdhfmfu.c b/client/cmdhfmfu.c index 8dfb9a3b1..1886fc3d8 100644 --- a/client/cmdhfmfu.c +++ b/client/cmdhfmfu.c @@ -7,25 +7,67 @@ //----------------------------------------------------------------------------- // High frequency MIFARE ULTRALIGHT (C) commands //----------------------------------------------------------------------------- -//#include #include "loclass/des.h" #include "cmdhfmfu.h" #include "cmdhfmf.h" #include "cmdhf14a.h" +#include "mifare.h" +#define MAX_UL_BLOCKS 0x0f +#define MAX_ULC_BLOCKS 0x2f +#define MAX_ULEV1a_BLOCKS 0x0b; +#define MAX_ULEV1b_BLOCKS 0x20; -#define MAX_ULTRA_BLOCKS 0x0f -#define MAX_ULTRAC_BLOCKS 0x2f -//#define MAX_ULTRAC_BLOCKS 0x2c - - +uint8_t default_3des_keys[7][16] = { + { 0x42,0x52,0x45,0x41,0x4b,0x4d,0x45,0x49,0x46,0x59,0x4f,0x55,0x43,0x41,0x4e,0x21 },// 3des std key + { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },// all zeroes + { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f },// 0x00-0x0F + { 0x49,0x45,0x4D,0x4B,0x41,0x45,0x52,0x42,0x21,0x4E,0x41,0x43,0x55,0x4F,0x59,0x46 },// NFC-key + { 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01 },// all ones + { 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF },// all FF + { 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xAA,0xBB,0xCC,0xDD,0xEE,0xFF } // 11 22 33 + }; + static int CmdHelp(const char *Cmd); -int CmdHF14AMfUInfo(const char *Cmd){ +// return 1 if tag responded to 0x1A. +uint8_t requestAuthentication( uint8_t* nonce){ - uint8_t datatemp[7] = {0x00}; + UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_CONNECT | ISO14A_RAW | ISO14A_APPEND_CRC ,2 ,0}}; + c.d.asBytes[0] = 0x1A; + c.d.asBytes[1] = 0x00; + SendCommand(&c); + UsbCommand resp; + WaitForResponse(CMD_ACK, &resp); // skip select answer. + + if ( !(resp.arg[0] & 0xff) ) + return 0; + + if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { + + if ( resp.arg[0] & 0xff ) { + memcpy(nonce, resp.d.asBytes+1, 8); + return 1; + } + } + return 0; +} + +typedef enum TAGTYPE_UL { + UNKNOWN = 0x00, + UL = 0x01, + UL_C = 0x02, + UL_EV1_48 = 0x04, + UL_EV1_128 = 0x08, + UL_MAGIC = 0x11, + UL_C_MAGIC = 0x12, + MAGIC = 0x10, + UL_ERROR = 0xFF, +} TagTypeUL_t; + +uint8_t GetHF14AMfU_Type(uint8_t *data, uint8_t dataSize){ + TagTypeUL_t tagtype = UNKNOWN; uint8_t isOK = 0; - uint8_t *data = NULL; UsbCommand c = {CMD_MIFAREU_READCARD, {0, 4}}; SendCommand(&c); @@ -33,52 +75,127 @@ int CmdHF14AMfUInfo(const char *Cmd){ if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { isOK = resp.arg[0] & 0xff; - data = resp.d.asBytes; + memcpy(data, resp.d.asBytes, dataSize); if (!isOK) { PrintAndLog("Error reading from tag"); - return -1; + return UL_ERROR; } } else { PrintAndLog("Command execute timed out"); - return -1; + return UL_ERROR; } - PrintAndLog(""); - PrintAndLog("-- Mifare Ultralight / Ultralight-C Tag Information ---------"); - PrintAndLog("-------------------------------------------------------------"); + c.cmd = CMD_READER_ISO_14443a; + c.arg[0] = ISO14A_CONNECT | ISO14A_RAW | ISO14A_APPEND_CRC; + c.arg[1] = 1; + c.arg[2] = 0; + c.d.asBytes[0] = 0x60; + SendCommand(&c); + WaitForResponse(CMD_ACK, &resp); + + if ( resp.arg[0] ) { + if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { + uint8_t version[8] = {0,0,0,0,0,0,0,0}; + memcpy(&version, resp.d.asBytes, sizeof(version)); + uint8_t len = resp.arg[0] & 0xff; + + if ( len == 0x0A && version[6] == 0x0B ) + tagtype = UL_EV1_48; + else if ( len == 0x0A && version[6] != 0x0B ) + tagtype = UL_EV1_128; + else if ( len == 0x01 ) + tagtype = UL_C; + else if ( len == 0x00 ) + tagtype = UL; //| UL_MAGIC | UL_C_MAGIC + } + } + + // Magic UL-C, mine have a static nonce response to 0x1A command. + uint8_t nonce1[8] = {0,0,0,0,0,0,0,0}; + uint8_t nonce2[8] = {0,0,0,0,0,0,0,0}; + uint8_t status = requestAuthentication(nonce1); + if ( status ) { + requestAuthentication(nonce2); + if ( !memcmp(nonce1, nonce2, 8) ) + tagtype ^= MAGIC; + } else { + // Magic Ultralight test here - TODO + } + return tagtype; +} + +int CmdHF14AMfUInfo(const char *Cmd){ + + TagTypeUL_t tagtype = UNKNOWN; + + uint8_t datatemp[7] = {0x00}; + uint8_t data[16] = {0x00}; + + tagtype = GetHF14AMfU_Type(data, sizeof(data)); + if (tagtype == UL_ERROR) return -1; + + PrintAndLog("\n-- Tag Information ---------"); + PrintAndLog("-------------------------------------------------------------"); + switch(tagtype){ + case UNKNOWN : PrintAndLog(" TYPE : Unknown"); return 0; + case UL : PrintAndLog(" TYPE : MIFARE Ultralight");break; + case UL_C : PrintAndLog(" TYPE : MIFARE Ultralight C");break; + case UL_EV1_48 : PrintAndLog(" TYPE : MIFARE Ultralight EV1 48 bytes"); break; + case UL_EV1_128 : PrintAndLog(" TYPE : MIFARE Ultralight EV1 128 bytes"); break; + case UL_MAGIC : PrintAndLog(" TYPE : MIFARE Ultralight (MAGIC)");break; + case UL_C_MAGIC : PrintAndLog(" TYPE : MIFARE Ultralight-C (MAGIC)");break; + default : PrintAndLog(" TYPE : Unknown %x",tagtype);break; + } + // UID memcpy( datatemp, data, 3); memcpy( datatemp+3, data+4, 4); - PrintAndLog("MANUFACTURER : %s", getTagInfo(datatemp[0])); - PrintAndLog(" UID : %s ", sprint_hex(datatemp, 7)); + PrintAndLog(" UID : %s ", sprint_hex(datatemp, 7)); + PrintAndLog(" UID[0] : (Manufacturer Byte) = %02x, Manufacturer: %s", datatemp[0], getTagInfo(datatemp[0]) ); + // BBC // CT (cascade tag byte) 0x88 xor SN0 xor SN1 xor SN2 int crc0 = 0x88 ^ data[0] ^ data[1] ^data[2]; if ( data[3] == crc0 ) - PrintAndLog(" BCC0 : %02x - Ok", data[3]); + PrintAndLog(" BCC0 : %02x - Ok", data[3]); else - PrintAndLog(" BCC0 : %02x - crc should be %02x", data[3], crc0); + PrintAndLog(" BCC0 : %02x - crc should be %02x", data[3], crc0); int crc1 = data[4] ^ data[5] ^ data[6] ^data[7]; if ( data[8] == crc1 ) - PrintAndLog(" BCC1 : %02x - Ok", data[8]); + PrintAndLog(" BCC1 : %02x - Ok", data[8]); else - PrintAndLog(" BCC1 : %02x - crc should be %02x", data[8], crc1 ); + PrintAndLog(" BCC1 : %02x - crc should be %02x", data[8], crc1 ); - PrintAndLog(" Internal : %s ", sprint_hex(data + 9, 1)); + PrintAndLog(" Internal : %s ", sprint_hex(data + 9, 1)); memcpy(datatemp, data+10, 2); - PrintAndLog(" Lock : %s - %s", sprint_hex(datatemp, 2),printBits( 2, &datatemp) ); - PrintAndLog(" OneTimePad : %s ", sprint_hex(data + 3*4, 4)); + PrintAndLog(" Lock : %s - %s", sprint_hex(datatemp, 2),printBits( 2, &datatemp) ); + PrintAndLog("OneTimePad : %s ", sprint_hex(data + 3*4, 4)); PrintAndLog(""); - - int len = CmdHF14AMfucAuth("K 0"); -// PrintAndLog("CODE: %d",len); - PrintAndLog("Seems to be a Ultralight %s", (len==0) ? "-C" :""); + + PrintAndLog("--- "); + if ((tagtype & UL_C)){ + + PrintAndLog("Trying some default 3des keys"); + uint8_t *key; + + for (uint8_t i = 0; i < 5; ++i ){ + key = default_3des_keys[i]; + if (try3DesAuthentication(key)){ + PrintAndLog("Found default 3des key: %s", sprint_hex(key,16)); + return 0; + } + } + } + else if ((tagtype & (UL_EV1_48 | UL_EV1_128))) { + //********** TODO ******************************** + //PrintAndLog("Trying some known EV1 passwords."); + } return 0; } @@ -105,7 +222,7 @@ int CmdHF14AMfUWrBl(const char *Cmd){ blockNo = param_get8(Cmd, 0); - if (blockNo > MAX_ULTRA_BLOCKS){ + if (blockNo > MAX_UL_BLOCKS){ PrintAndLog("Error: Maximum number of blocks is 15 for Ultralight Cards!"); return 1; } @@ -155,40 +272,41 @@ int CmdHF14AMfUWrBl(const char *Cmd){ // Mifare Ultralight Read Single Block // int CmdHF14AMfURdBl(const char *Cmd){ - - uint8_t blockNo = -1; + UsbCommand resp; + uint8_t blockNo = -1; char cmdp = param_getchar(Cmd, 0); if (strlen(Cmd) < 1 || cmdp == 'h' || cmdp == 'H') { PrintAndLog("Usage: hf mfu rdbl "); PrintAndLog(" sample: hfu mfu rdbl 0"); return 0; - } - + } + blockNo = param_get8(Cmd, 0); - if (blockNo > MAX_ULTRA_BLOCKS){ - PrintAndLog("Error: Maximum number of blocks is 15 for Ultralight Cards!"); - return 1; + if (blockNo > MAX_UL_BLOCKS){ + PrintAndLog("Error: Maximum number of blocks is 15 for Ultralight"); + return 1; } - - PrintAndLog("--block no:0x%02X (%d)", (int)blockNo, blockNo); + UsbCommand c = {CMD_MIFAREU_READBL, {blockNo}}; SendCommand(&c); - UsbCommand resp; + if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) { - uint8_t isOK = resp.arg[0] & 0xff; - uint8_t * data = resp.d.asBytes; - - PrintAndLog("isOk: %02x", isOK); - - if (isOK) - PrintAndLog("Data: %s", sprint_hex(data, 4)); + uint8_t isOK = resp.arg[0] & 0xff; + if (isOK) { + uint8_t *data = resp.d.asBytes; + PrintAndLog("Block: %0d (0x%02X) [ %s]", (int)blockNo, blockNo, sprint_hex(data, 4)); + } + else { + PrintAndLog("Failed reading block: (%02x)", isOK); + } } else { - PrintAndLog("Command execute timeout"); + PrintAndLog("Command execute time-out"); } + return 0; } @@ -224,7 +342,7 @@ int CmdHF14AMfUDump(const char *Cmd){ PrintAndLog("Reads all pages from Mifare Ultralight or Ultralight-C tag."); PrintAndLog("It saves binary dump into the file `filename.bin` or `cardUID.bin`"); PrintAndLog("Usage: hf mfu dump "); - PrintAndLog(" optional cardtype c == Ultralight-C, if not defaults to Ultralight"); + PrintAndLog(" optional cardtype c == Ultralight-C, Defaults to Ultralight"); PrintAndLog(" sample: hf mfu dump"); PrintAndLog(" : hf mfu dump myfile"); PrintAndLog(" : hf mfu dump c myfile"); @@ -234,7 +352,36 @@ int CmdHF14AMfUDump(const char *Cmd){ // UL or UL-C? Pages = (cmdp == 'c' || cmdp == 'C') ? 44 : 16; - PrintAndLog("Dumping Ultralight%s Card Data...", (Pages ==16)?"":"-C"); + uint8_t data2[16] = {0x00}; + TagTypeUL_t tagtype = GetHF14AMfU_Type(data2, sizeof(data2)); + switch(tagtype){ + case UL_C: + Pages = 44; + PrintAndLog("Dumping Ultralight_C Card Data..."); + break; + case UL_EV1_48: + Pages = 18; + PrintAndLog("Dumping Ultralight EV1_48 Card Data..."); + break; + case UL_EV1_128: + Pages = 32; + PrintAndLog("Dumping Ultralight EV1_128 Card Data..."); + break; + case UL_MAGIC: + Pages = 16; + PrintAndLog("Dumping Ultralight (Magic) Card Data..."); + break; + case UL_C_MAGIC: + Pages = 44; + PrintAndLog("Dumping Ultralight_C (Magic) Card Data..."); + break; + case UL: + default: + Pages = 16; + PrintAndLog("Dumping Ultralight Card Data..."); + break; + } + //PrintAndLog("Dumping Ultralight%s Card Data...", (Pages ==16)?"":"-C"); UsbCommand c = {CMD_MIFAREU_READCARD, {BlockNo,Pages}}; SendCommand(&c); @@ -248,7 +395,7 @@ int CmdHF14AMfUDump(const char *Cmd){ } data = resp.d.asBytes; } else { - PrintAndLog("Command execute timeout"); + PrintAndLog("Command execute time-out"); return 0; } @@ -376,130 +523,107 @@ void rol (uint8_t *data, const size_t len){ // int CmdHF14AMfucAuth(const char *Cmd){ - uint8_t default_keys[5][16] = { - { 0x42,0x52,0x45,0x41,0x4b,0x4d,0x45,0x49,0x46,0x59,0x4f,0x55,0x43,0x41,0x4e,0x21 },// 3des std key - { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },// all zeroes - { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f },// 0x00-0x0F - { 0x49,0x45,0x4D,0x4B,0x41,0x45,0x52,0x42,0x21,0x4E,0x41,0x43,0x55,0x4F,0x59,0x46 },// NFC-key - { 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01 } // all ones - }; - - char cmdp = param_getchar(Cmd, 0); - uint8_t keyNo = 0; bool errors = false; + + char cmdp = param_getchar(Cmd, 0); + //Change key to user defined one if (cmdp == 'k' || cmdp == 'K'){ keyNo = param_get8(Cmd, 1); - if(keyNo >= 4) errors = true; + if(keyNo > 6) + errors = true; } - if (cmdp == 'h' || cmdp == 'H') { + if (cmdp == 'h' || cmdp == 'H') errors = true; - } - + if (errors) { PrintAndLog("Usage: hf mfu cauth k "); PrintAndLog(" 0 (default): 3DES standard key"); - PrintAndLog(" 1 : all zeros key"); + PrintAndLog(" 1 : all 0x00 key"); PrintAndLog(" 2 : 0x00-0x0F key"); PrintAndLog(" 3 : nfc key"); - PrintAndLog(" 4 : all ones key"); - PrintAndLog(" sample : hf mfu cauth k"); + PrintAndLog(" 4 : all 0x01 key"); + PrintAndLog(" 5 : all 0xff key"); + PrintAndLog(" 6 : 0x00-0xFF key"); + PrintAndLog("\n sample : hf mfu cauth k"); PrintAndLog(" : hf mfu cauth k 3"); return 0; } - uint8_t random_a[8] = { 1,1,1,1,1,1,1,1 }; - //uint8_t enc_random_a[8] = { 0 }; - uint8_t random_b[8] = { 0 }; - uint8_t enc_random_b[8] = { 0 }; - uint8_t random_a_and_b[16] = { 0 }; - des3_context ctx = { 0 }; - uint8_t *key = default_keys[keyNo]; + uint8_t *key = default_3des_keys[keyNo]; + if (try3DesAuthentication(key)) + PrintAndLog("Authentication successful. 3des key: %s",sprint_hex(key, 8)); + else + PrintAndLog("Authentication failed"); + + return 0; +} + +int try3DesAuthentication( uint8_t *key){ + uint8_t blockNo = 0; uint32_t cuid = 0; - //Auth1 + des3_context ctx = { 0 }; + + uint8_t random_a[8] = { 1,1,1,1,1,1,1,1 }; + uint8_t random_b[8] = { 0 }; + uint8_t enc_random_b[8] = { 0 }; + uint8_t rnd_ab[16] = { 0 }; + uint8_t iv[8] = { 0 }; + UsbCommand c = {CMD_MIFAREUC_AUTH1, {blockNo}}; SendCommand(&c); UsbCommand resp; - if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) { - uint8_t isOK = resp.arg[0] & 0xff; - cuid = resp.arg[1]; - uint8_t * data= resp.d.asBytes; - - if (isOK){ - PrintAndLog("enc(RndB):%s", sprint_hex(data+1, 8)); - memcpy(enc_random_b,data+1,8); - } else { - PrintAndLog("Auth failed"); - return 2; // auth failed. - } - } else { - PrintAndLog("Command execute timeout"); - return 1; - } - - uint8_t iv[8] = { 0 }; - // Do we need random ? Right now we use all ones, is that random enough ? -// DES_random_key(&RndA); - - PrintAndLog(" RndA :%s",sprint_hex(random_a, 8)); - PrintAndLog(" e_RndB:%s",sprint_hex(enc_random_b, 8)); + if ( !WaitForResponseTimeout(CMD_ACK, &resp, 1500) ) return -1; + if ( !(resp.arg[0] & 0xff) ) return -2; + + cuid = resp.arg[1]; + memcpy(enc_random_b,resp.d.asBytes+1,8); des3_set2key_dec(&ctx, key); - - des3_crypt_cbc(&ctx // des3_context *ctx - , DES_DECRYPT // int mode - , sizeof(random_b) // size_t length - , iv // unsigned char iv[8] - , enc_random_b // const unsigned char *input - , random_b // unsigned char *output - ); - - PrintAndLog(" RndB:%s",sprint_hex(random_b, 8)); + // context, mode, length, IV, input, output + des3_crypt_cbc( &ctx, DES_DECRYPT, sizeof(random_b), iv , enc_random_b , random_b); rol(random_b,8); - memcpy(random_a_and_b ,random_a,8); - memcpy(random_a_and_b+8,random_b,8); - - PrintAndLog(" RA+B:%s",sprint_hex(random_a_and_b, 16)); + memcpy(rnd_ab ,random_a,8); + memcpy(rnd_ab+8,random_b,8); des3_set2key_enc(&ctx, key); - - des3_crypt_cbc(&ctx // des3_context *ctx - , DES_ENCRYPT // int mode - , sizeof(random_a_and_b) // size_t length - , enc_random_b // unsigned char iv[8] - , random_a_and_b // const unsigned char *input - , random_a_and_b // unsigned char *output - ); - - PrintAndLog("enc(RA+B):%s",sprint_hex(random_a_and_b, 16)); + // context, mode, length, IV, input, output + des3_crypt_cbc(&ctx, DES_ENCRYPT, sizeof(rnd_ab), enc_random_b, rnd_ab, rnd_ab); //Auth2 - UsbCommand d = {CMD_MIFAREUC_AUTH2, {cuid}}; - memcpy(d.d.asBytes,random_a_and_b, 16); - SendCommand(&d); + c.cmd = CMD_MIFAREUC_AUTH2; + c.arg[0] = cuid; + memcpy(c.d.asBytes, rnd_ab, 16); + SendCommand(&c); - UsbCommand respb; - if (WaitForResponseTimeout(CMD_ACK,&respb,1500)) { - uint8_t isOK = respb.arg[0] & 0xff; - uint8_t * data2= respb.d.asBytes; + if ( !WaitForResponseTimeout(CMD_ACK, &resp, 1500)) return -1; + if ( !(resp.arg[0] & 0xff)) return -2; + + uint8_t enc_resp[8] = { 0 }; + uint8_t resp_random_a[8] = { 0 }; + memcpy(enc_resp, resp.d.asBytes+1, 8); - if (isOK){ - PrintAndLog("enc(RndA'):%s", sprint_hex(data2+1, 8)); - } else { - return 2; - } - - } else { - PrintAndLog("Command execute timeout"); - return 1; - } + des3_set2key_dec(&ctx, key); + // context, mode, length, IV, input, output + des3_crypt_cbc( &ctx, DES_DECRYPT, 8, enc_random_b, enc_resp, resp_random_a); + + if ( !memcmp(resp_random_a, random_a, 8)) + return 1; return 0; + + //PrintAndLog(" RndA :%s", sprint_hex(random_a, 8)); + //PrintAndLog(" enc(RndB) :%s", sprint_hex(enc_random_b, 8)); + //PrintAndLog(" RndB :%s", sprint_hex(random_b, 8)); + //PrintAndLog(" A+B :%s", sprint_hex(random_a_and_b, 16)); + //PrintAndLog(" enc(A+B) :%s", sprint_hex(random_a_and_b, 16)); + //PrintAndLog(" enc(RndA') :%s", sprint_hex(data2+1, 8)); } + /** A test function to validate that the polarssl-function works the same was as the openssl-implementation. @@ -601,12 +725,17 @@ int CmdTestDES(const char * cmd) // int CmdHF14AMfUCRdBl(const char *Cmd) { + UsbCommand resp; + bool hasPwd = FALSE; uint8_t blockNo = -1; + unsigned char key[16]; char cmdp = param_getchar(Cmd, 0); if (strlen(Cmd) < 1 || cmdp == 'h' || cmdp == 'H') { - PrintAndLog("Usage: hf mfu crdbl "); - PrintAndLog(" sample: hf mfu crdbl 0"); + PrintAndLog("Usage: hf mfu crdbl "); + PrintAndLog(""); + PrintAndLog("sample: hf mfu crdbl 0"); + PrintAndLog(" hf mfu crdbl 0 112233445566778899AABBCCDDEEFF"); return 0; } @@ -616,27 +745,40 @@ int CmdHF14AMfUCRdBl(const char *Cmd) return 1; } - if (blockNo > MAX_ULTRAC_BLOCKS ){ - PrintAndLog("Error: Maximum number of readable blocks is 47 for Ultralight-C Cards!"); + if (blockNo > MAX_ULC_BLOCKS ){ + PrintAndLog("Error: Maximum number of blocks is 47 for Ultralight-C"); return 1; } - PrintAndLog("--block no: 0x%02X (%d)", (int)blockNo, blockNo); + // key + if ( strlen(Cmd) > 3){ + if (param_gethex(Cmd, 1, key, 32)) { + PrintAndLog("Key must include %d HEX symbols", 32); + return 1; + } else { + hasPwd = TRUE; + } + } //Read Block - UsbCommand e = {CMD_MIFAREU_READBL, {blockNo}}; - SendCommand(&e); - UsbCommand resp_c; - if (WaitForResponseTimeout(CMD_ACK,&resp_c,1500)) { - uint8_t isOK = resp_c.arg[0] & 0xff; - uint8_t *data = resp_c.d.asBytes; - - PrintAndLog("isOk: %02x", isOK); - if (isOK) - PrintAndLog("Data: %s", sprint_hex(data, 4)); - + UsbCommand c = {CMD_MIFAREU_READBL, {blockNo}}; + if ( hasPwd ) { + c.arg[1] = 1; + memcpy(c.d.asBytes,key,16); + } + SendCommand(&c); + + if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) { + uint8_t isOK = resp.arg[0] & 0xff; + if (isOK) { + uint8_t *data = resp.d.asBytes; + PrintAndLog("Block: %0d (0x%02X) [ %s]", (int)blockNo, blockNo, sprint_hex(data, 4)); + } + else { + PrintAndLog("Failed reading block: (%02x)", isOK); + } } else { - PrintAndLog("Command execute timeout"); + PrintAndLog("Command execute time-out"); } return 0; } @@ -665,7 +807,7 @@ int CmdHF14AMfUCWrBl(const char *Cmd){ } blockNo = param_get8(Cmd, 0); - if (blockNo > MAX_ULTRAC_BLOCKS ){ + if (blockNo > MAX_ULC_BLOCKS ){ PrintAndLog("Error: Maximum number of blocks is 47 for Ultralight-C Cards!"); return 1; } @@ -711,6 +853,228 @@ int CmdHF14AMfUCWrBl(const char *Cmd){ return 0; } +// +// Mifare Ultralight C - Set password +// +int CmdHF14AMfucSetPwd(const char *Cmd){ + + uint8_t pwd[16] = {0x00}; + + char cmdp = param_getchar(Cmd, 0); + + if (strlen(Cmd) == 0 || cmdp == 'h' || cmdp == 'H') { + PrintAndLog("Usage: hf mfu setpwd "); + PrintAndLog(" [password] - (32 hex symbols)"); + PrintAndLog(""); + PrintAndLog("sample: hf mfu setpwd 000102030405060708090a0b0c0d0e0f"); + PrintAndLog(""); + return 0; + } + + if (param_gethex(Cmd, 0, pwd, 32)) { + PrintAndLog("Password must include 32 HEX symbols"); + return 1; + } + + UsbCommand c = {CMD_MIFAREUC_SETPWD}; + memcpy( c.d.asBytes, pwd, 16); + SendCommand(&c); + + UsbCommand resp; + + if (WaitForResponseTimeout(CMD_ACK,&resp,1500) ) { + if ( (resp.arg[0] & 0xff) == 1) + PrintAndLog("Ultralight-C new password: %s", sprint_hex(pwd,16)); + else{ + PrintAndLog("Failed writing at block %d", resp.arg[1] & 0xff); + return 1; + } + } + else { + PrintAndLog("command execution time out"); + return 1; + } + + return 0; +} + +// +// Mifare Ultraligh - Set UID +// +int CmdHF14AMfucSetUid(const char *Cmd){ + + UsbCommand c; + UsbCommand resp; + uint8_t uid[7] = {0x00}; + char cmdp = param_getchar(Cmd, 0); + + if (strlen(Cmd) == 0 || cmdp == 'h' || cmdp == 'H') { + PrintAndLog("Usage: hf mfu setuid "); + PrintAndLog(" [uid] - (14 hex symbols)"); + PrintAndLog("\nThis only works for Magic Ultralight tags."); + PrintAndLog(""); + PrintAndLog("sample: hf mfu setuid 11223344556677"); + PrintAndLog(""); + return 0; + } + + if (param_gethex(Cmd, 0, uid, 14)) { + PrintAndLog("UID must include 14 HEX symbols"); + return 1; + } + + // read block2. + c.cmd = CMD_MIFAREU_READBL; + c.arg[0] = 2; + SendCommand(&c); + if (!WaitForResponseTimeout(CMD_ACK,&resp,1500)) { + PrintAndLog("Command execute timeout"); + return 2; + } + + // save old block2. + uint8_t oldblock2[4] = {0x00}; + memcpy(resp.d.asBytes, oldblock2, 4); + + // block 0. + c.cmd = CMD_MIFAREU_WRITEBL; + c.arg[0] = 0; + c.d.asBytes[0] = uid[0]; + c.d.asBytes[1] = uid[1]; + c.d.asBytes[2] = uid[2]; + c.d.asBytes[3] = 0x88 ^ uid[0] ^ uid[1] ^ uid[2]; + SendCommand(&c); + if (!WaitForResponseTimeout(CMD_ACK,&resp,1500)) { + PrintAndLog("Command execute timeout"); + return 3; + } + + // block 1. + c.arg[0] = 1; + c.d.asBytes[0] = uid[3]; + c.d.asBytes[1] = uid[4]; + c.d.asBytes[2] = uid[5]; + c.d.asBytes[3] = uid[6]; + SendCommand(&c); + if (!WaitForResponseTimeout(CMD_ACK,&resp,1500) ) { + PrintAndLog("Command execute timeout"); + return 4; + } + + // block 2. + c.arg[0] = 2; + c.d.asBytes[0] = uid[3] ^ uid[4] ^ uid[5] ^ uid[6]; + c.d.asBytes[1] = oldblock2[1]; + c.d.asBytes[2] = oldblock2[2]; + c.d.asBytes[3] = oldblock2[3]; + SendCommand(&c); + if (!WaitForResponseTimeout(CMD_ACK,&resp,1500) ) { + PrintAndLog("Command execute timeout"); + return 5; + } + + return 0; +} + +int CmdHF14AMfuGenDiverseKeys(const char *Cmd){ + + uint8_t iv[8] = { 0x00 }; + uint8_t block = 0x07; + + // UL-EV1 + //04 57 b6 e2 05 3f 80 UID + //4a f8 4b 19 PWD + uint8_t uid[] = { 0xF4,0xEA, 0x54, 0x8E }; + uint8_t mifarekeyA[] = { 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5 }; + uint8_t mifarekeyB[] = { 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5 }; + uint8_t dkeyA[8] = { 0x00 }; + uint8_t dkeyB[8] = { 0x00 }; + + uint8_t masterkey[] = { 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xaa,0xbb,0xcc,0xdd,0xee,0xff }; + + uint8_t mix[8] = { 0x00 }; + uint8_t divkey[8] = { 0x00 }; + + memcpy(mix, mifarekeyA, 4); + + mix[4] = mifarekeyA[4] ^ uid[0]; + mix[5] = mifarekeyA[5] ^ uid[1]; + mix[6] = block ^ uid[2]; + mix[7] = uid[3]; + + des3_context ctx = { 0x00 }; + des3_set2key_enc(&ctx, masterkey); + + des3_crypt_cbc(&ctx // des3_context + , DES_ENCRYPT // int mode + , sizeof(mix) // length + , iv // iv[8] + , mix // input + , divkey // output + ); + + PrintAndLog("3DES version"); + PrintAndLog("Masterkey :\t %s", sprint_hex(masterkey,sizeof(masterkey))); + PrintAndLog("UID :\t %s", sprint_hex(uid, sizeof(uid))); + PrintAndLog("Sector :\t %0d", block); + PrintAndLog("Mifare key :\t %s", sprint_hex(mifarekeyA, sizeof(mifarekeyA))); + PrintAndLog("Message :\t %s", sprint_hex(mix, sizeof(mix))); + PrintAndLog("Diversified key: %s", sprint_hex(divkey+1, 6)); + + PrintAndLog("\n DES version"); + + for (int i=0; i < sizeof(mifarekeyA); ++i){ + dkeyA[i] = (mifarekeyA[i] << 1) & 0xff; + dkeyA[6] |= ((mifarekeyA[i] >> 7) & 1) << (i+1); + } + + for (int i=0; i < sizeof(mifarekeyB); ++i){ + dkeyB[1] |= ((mifarekeyB[i] >> 7) & 1) << (i+1); + dkeyB[2+i] = (mifarekeyB[i] << 1) & 0xff; + } + + uint8_t zeros[8] = {0x00}; + uint8_t newpwd[8] = {0x00}; + uint8_t dmkey[24] = {0x00}; + memcpy(dmkey, dkeyA, 8); + memcpy(dmkey+8, dkeyB, 8); + memcpy(dmkey+16, dkeyA, 8); + memset(iv, 0x00, 8); + + des3_set3key_enc(&ctx, dmkey); + + des3_crypt_cbc(&ctx // des3_context + , DES_ENCRYPT // int mode + , sizeof(newpwd) // length + , iv // iv[8] + , zeros // input + , newpwd // output + ); + + PrintAndLog("Mifare dkeyA :\t %s", sprint_hex(dkeyA, sizeof(dkeyA))); + PrintAndLog("Mifare dkeyB :\t %s", sprint_hex(dkeyB, sizeof(dkeyB))); + PrintAndLog("Mifare ABA :\t %s", sprint_hex(dmkey, sizeof(dmkey))); + PrintAndLog("Mifare Pwd :\t %s", sprint_hex(newpwd, sizeof(newpwd))); + + return 0; +} + +// static uint8_t * diversify_key(uint8_t * key){ + + // for(int i=0; i<16; i++){ + // if(i<=6) key[i]^=cuid[i]; + // if(i>6) key[i]^=cuid[i%7]; + // } + // return key; +// } + +// static void GenerateUIDe( uint8_t *uid, uint8_t len){ + // for (int i=0; i Date: Thu, 30 Apr 2015 09:28:43 -0400 Subject: [PATCH 06/49] Iceman's updates to MFU info and dump --- armsrc/mifarecmd.c | 13 +-- client/cmdhfmfu.c | 285 +++++++++++++++++++++------------------------ client/cmdhfmfu.h | 3 + 3 files changed, 143 insertions(+), 158 deletions(-) diff --git a/armsrc/mifarecmd.c b/armsrc/mifarecmd.c index 3d5dcdef1..03e191e04 100644 --- a/armsrc/mifarecmd.c +++ b/armsrc/mifarecmd.c @@ -326,13 +326,13 @@ void MifareUReadCard(uint8_t arg0, int arg1, uint8_t *datain) int Pages = arg1; int countpages = 0; byte_t dataout[176] = {0x00};; - uint32_t cuid = 0x00; - LED_A_ON(); LED_B_OFF(); LED_C_OFF(); + LEDsoff(); + LED_A_ON(); clear_trace(); iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); - int len = iso14443a_select_card(NULL, NULL, &cuid); + int len = iso14443a_select_card(NULL, NULL, NULL); if (!len) { if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Can't select card (RC:%d)",len); OnError(1); @@ -359,13 +359,8 @@ void MifareUReadCard(uint8_t arg0, int arg1, uint8_t *datain) return; } - if (MF_DBGLEVEL >= MF_DBG_ALL) Dbprintf("Pages read %d", countpages); + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("Pages read %d", countpages); -// len = 16*4; //64 bytes - - // Read a UL-C -// if (Pages == 44 && countpages > 16) -// len = 176; len = Pages * 4; cmd_send(CMD_ACK, 1, 0, 0, dataout, len); diff --git a/client/cmdhfmfu.c b/client/cmdhfmfu.c index 1886fc3d8..2f7fa2c92 100644 --- a/client/cmdhfmfu.c +++ b/client/cmdhfmfu.c @@ -59,57 +59,46 @@ typedef enum TAGTYPE_UL { UL_C = 0x02, UL_EV1_48 = 0x04, UL_EV1_128 = 0x08, - UL_MAGIC = 0x11, - UL_C_MAGIC = 0x12, MAGIC = 0x10, + UL_MAGIC = UL | MAGIC, + UL_C_MAGIC = UL_C | MAGIC, UL_ERROR = 0xFF, } TagTypeUL_t; -uint8_t GetHF14AMfU_Type(uint8_t *data, uint8_t dataSize){ +uint8_t GetHF14AMfU_Type(void){ + TagTypeUL_t tagtype = UNKNOWN; - uint8_t isOK = 0; + iso14a_card_select_t card; - UsbCommand c = {CMD_MIFAREU_READCARD, {0, 4}}; - SendCommand(&c); - UsbCommand resp; - - if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { - isOK = resp.arg[0] & 0xff; - memcpy(data, resp.d.asBytes, dataSize); - - if (!isOK) { - PrintAndLog("Error reading from tag"); - return UL_ERROR; - } - } else { - PrintAndLog("Command execute timed out"); - return UL_ERROR; - } - - c.cmd = CMD_READER_ISO_14443a; - c.arg[0] = ISO14A_CONNECT | ISO14A_RAW | ISO14A_APPEND_CRC; - c.arg[1] = 1; - c.arg[2] = 0; + // select and run 0x60 (GET_VERSION - EV1 command) + UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_CONNECT | ISO14A_RAW | ISO14A_APPEND_CRC, 1, 0}}; c.d.asBytes[0] = 0x60; SendCommand(&c); + UsbCommand resp; WaitForResponse(CMD_ACK, &resp); - if ( resp.arg[0] ) { - if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { + if ( resp.arg[0] == 0 ) return UL_ERROR; + + memcpy(&card, (iso14a_card_select_t *)resp.d.asBytes, sizeof(iso14a_card_select_t)); - uint8_t version[8] = {0,0,0,0,0,0,0,0}; - memcpy(&version, resp.d.asBytes, sizeof(version)); - uint8_t len = resp.arg[0] & 0xff; - - if ( len == 0x0A && version[6] == 0x0B ) - tagtype = UL_EV1_48; - else if ( len == 0x0A && version[6] != 0x0B ) - tagtype = UL_EV1_128; - else if ( len == 0x01 ) - tagtype = UL_C; - else if ( len == 0x00 ) - tagtype = UL; //| UL_MAGIC | UL_C_MAGIC - } + // Ultralight - ATQA / SAK + if ( card.atqa[1] != 0x00 && card.atqa[0] != 0x44 && card.sak != 0x00 ) return UL_ERROR; + + // EV1 GetVersion + if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { + + uint8_t version[8] = {0,0,0,0,0,0,0,0}; + memcpy(&version, resp.d.asBytes, sizeof(version)); + uint8_t len = resp.arg[0] & 0xff; + + if ( len == 0x0A && version[6] == 0x0B ) + tagtype = UL_EV1_48; + else if ( len == 0x0A && version[6] != 0x0B ) + tagtype = UL_EV1_128; + else if ( len == 0x01 ) + tagtype = UL_C; + else if ( len == 0x00 ) + tagtype = UL; } // Magic UL-C, mine have a static nonce response to 0x1A command. @@ -118,8 +107,9 @@ uint8_t GetHF14AMfU_Type(uint8_t *data, uint8_t dataSize){ uint8_t status = requestAuthentication(nonce1); if ( status ) { requestAuthentication(nonce2); - if ( !memcmp(nonce1, nonce2, 8) ) - tagtype ^= MAGIC; + if ( !memcmp(nonce1, nonce2, 8) ){ + tagtype = UL_C_MAGIC; + } } else { // Magic Ultralight test here - TODO } @@ -128,27 +118,46 @@ uint8_t GetHF14AMfU_Type(uint8_t *data, uint8_t dataSize){ int CmdHF14AMfUInfo(const char *Cmd){ - TagTypeUL_t tagtype = UNKNOWN; - uint8_t datatemp[7] = {0x00}; + uint8_t isOK = 0; uint8_t data[16] = {0x00}; + uint8_t *key; - tagtype = GetHF14AMfU_Type(data, sizeof(data)); + TagTypeUL_t tagtype = GetHF14AMfU_Type(); if (tagtype == UL_ERROR) return -1; PrintAndLog("\n-- Tag Information ---------"); PrintAndLog("-------------------------------------------------------------"); - switch(tagtype){ - case UNKNOWN : PrintAndLog(" TYPE : Unknown"); return 0; - case UL : PrintAndLog(" TYPE : MIFARE Ultralight");break; - case UL_C : PrintAndLog(" TYPE : MIFARE Ultralight C");break; - case UL_EV1_48 : PrintAndLog(" TYPE : MIFARE Ultralight EV1 48 bytes"); break; - case UL_EV1_128 : PrintAndLog(" TYPE : MIFARE Ultralight EV1 128 bytes"); break; - case UL_MAGIC : PrintAndLog(" TYPE : MIFARE Ultralight (MAGIC)");break; - case UL_C_MAGIC : PrintAndLog(" TYPE : MIFARE Ultralight-C (MAGIC)");break; - default : PrintAndLog(" TYPE : Unknown %x",tagtype);break; + + if ( tagtype & UL ) + PrintAndLog(" TYPE : MIFARE Ultralight %s", (tagtype & MAGIC)?"(magic)":""); + else if ( tagtype & UL_C) + PrintAndLog(" TYPE : MIFARE Ultralight C %s", (tagtype & MAGIC)?"(magic)":"" ); + else if ( tagtype & UL_EV1_48) + PrintAndLog(" TYPE : MIFARE Ultralight EV1 48 bytes"); + else if ( tagtype & UL_EV1_128) + PrintAndLog(" TYPE : MIFARE Ultralight EV1 128 bytes"); + else + PrintAndLog(" TYPE : Unknown %x",tagtype); + + // read pages 0,1,2,4 + UsbCommand c = {CMD_MIFAREU_READCARD, {0, 4}}; + SendCommand(&c); + UsbCommand resp; + + if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { + isOK = resp.arg[0] & 0xff; + memcpy(data, resp.d.asBytes, sizeof(data)); + + if (!isOK) { + PrintAndLog("Error reading from tag"); + return -1; + } + } else { + PrintAndLog("Command execute timed out"); + return -1; } - + // UID memcpy( datatemp, data, 3); memcpy( datatemp+3, data+4, 4); @@ -182,7 +191,6 @@ int CmdHF14AMfUInfo(const char *Cmd){ if ((tagtype & UL_C)){ PrintAndLog("Trying some default 3des keys"); - uint8_t *key; for (uint8_t i = 0; i < 5; ++i ){ key = default_3des_keys[i]; @@ -194,6 +202,7 @@ int CmdHF14AMfUInfo(const char *Cmd){ } else if ((tagtype & (UL_EV1_48 | UL_EV1_128))) { //********** TODO ******************************** + // --problem, there is a failed pwd tries counter in UL-EV1 //PrintAndLog("Trying some known EV1 passwords."); } return 0; @@ -310,108 +319,95 @@ int CmdHF14AMfURdBl(const char *Cmd){ return 0; } +int usage_hf_mfu_dump(void) +{ + PrintAndLog("Reads all pages from Ultralight, Ultralight-C, Ultralight EV1"); + PrintAndLog("and saves binary dump into the file `filename.bin` or `cardUID.bin`"); + PrintAndLog("It autodetects card type.\n"); + PrintAndLog("Usage: hf mfu dump "); + PrintAndLog(" sample : hf mfu dump"); + PrintAndLog(" : hf mfu dump myfile"); + PrintAndLog(" : hf mfu dump 1 myfile"); + return 0; +} // -// Mifare Ultralight / Ultralight-C; Read and Dump Card Contents +// Mifare Ultralight / Ultralight-C / Ultralight-EV1 +// Read and Dump Card Contents, using auto detection of tag size. // +// TODO: take a password to read UL-C / UL-EV1 tags. int CmdHF14AMfUDump(const char *Cmd){ + char cmdp = param_getchar(Cmd, 0); + if (cmdp == 'h' || cmdp == 'H') + return usage_hf_mfu_dump(); + FILE *fout; char filename[FILE_PATH_SIZE] = {0x00}; - char * fnameptr = filename; + char *fnameptr = filename; + char *str = "Dumping Ultralight%s%s Card Data..."; uint8_t *lockbytes_t = NULL; uint8_t lockbytes[2] = {0x00}; - uint8_t *lockbytes_t2 = NULL; uint8_t lockbytes2[2] = {0x00}; - bool bit[16] = {0x00}; bool bit2[16] = {0x00}; + uint8_t data[176] = {0x00}; - int i; - uint8_t BlockNo = 0; - int Pages = 16; + int i = 0; + int Pages = 16; + bool tmplockbit = false; - bool tmplockbit = false; - uint8_t isOK = 0; - uint8_t *data = NULL; + TagTypeUL_t tagtype = GetHF14AMfU_Type(); + if (tagtype == UL_ERROR) return -1; - char cmdp = param_getchar(Cmd, 0); - - if (cmdp == 'h' || cmdp == 'H') { - PrintAndLog("Reads all pages from Mifare Ultralight or Ultralight-C tag."); - PrintAndLog("It saves binary dump into the file `filename.bin` or `cardUID.bin`"); - PrintAndLog("Usage: hf mfu dump "); - PrintAndLog(" optional cardtype c == Ultralight-C, Defaults to Ultralight"); - PrintAndLog(" sample: hf mfu dump"); - PrintAndLog(" : hf mfu dump myfile"); - PrintAndLog(" : hf mfu dump c myfile"); - return 0; + if ( tagtype & UL ) { + Pages = 16; + PrintAndLog(str,"", (tagtype & MAGIC)?" (magic)":"" ); + } + else if ( tagtype & UL_C ) { + Pages = 44; + PrintAndLog(str,"-C", (tagtype & MAGIC)?" (magic)":"" ); + } + else if ( tagtype & UL_EV1_48 ) { + Pages = 18; + PrintAndLog(str," EV1_48",""); + } + else if ( tagtype & UL_EV1_128 ) { + Pages = 32; + PrintAndLog(str," EV1_128",""); + } else { + Pages = 16; + PrintAndLog("Dumping unknown Ultralight, using default values."); } - // UL or UL-C? - Pages = (cmdp == 'c' || cmdp == 'C') ? 44 : 16; - - uint8_t data2[16] = {0x00}; - TagTypeUL_t tagtype = GetHF14AMfU_Type(data2, sizeof(data2)); - switch(tagtype){ - case UL_C: - Pages = 44; - PrintAndLog("Dumping Ultralight_C Card Data..."); - break; - case UL_EV1_48: - Pages = 18; - PrintAndLog("Dumping Ultralight EV1_48 Card Data..."); - break; - case UL_EV1_128: - Pages = 32; - PrintAndLog("Dumping Ultralight EV1_128 Card Data..."); - break; - case UL_MAGIC: - Pages = 16; - PrintAndLog("Dumping Ultralight (Magic) Card Data..."); - break; - case UL_C_MAGIC: - Pages = 44; - PrintAndLog("Dumping Ultralight_C (Magic) Card Data..."); - break; - case UL: - default: - Pages = 16; - PrintAndLog("Dumping Ultralight Card Data..."); - break; - } - //PrintAndLog("Dumping Ultralight%s Card Data...", (Pages ==16)?"":"-C"); - - UsbCommand c = {CMD_MIFAREU_READCARD, {BlockNo,Pages}}; + UsbCommand c = {CMD_MIFAREU_READCARD, {0,Pages}}; SendCommand(&c); UsbCommand resp; - if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) { - isOK = resp.arg[0] & 0xff; - if (!isOK) { - PrintAndLog("Command error"); - return 0; - } - data = resp.d.asBytes; - } else { + if (!WaitForResponseTimeout(CMD_ACK,&resp,1500)) { PrintAndLog("Command execute time-out"); return 0; } - + + if (!resp.arg[0] ) { + PrintAndLog("Read command failed"); + return 0; + } + memcpy(data, resp.d.asBytes, sizeof(data)); + // Load lock bytes. int j = 0; - + lockbytes_t = data + 8; lockbytes[0] = lockbytes_t[2]; lockbytes[1] = lockbytes_t[3]; for(j = 0; j < 16; j++){ bit[j] = lockbytes[j/8] & ( 1 <<(7-j%8)); - } - + } + // Load bottom lockbytes if available if ( Pages == 44 ) { - lockbytes_t2 = data + (40*4); lockbytes2[0] = lockbytes_t2[2]; lockbytes2[1] = lockbytes_t2[3]; @@ -421,12 +417,10 @@ int CmdHF14AMfUDump(const char *Cmd){ } for (i = 0; i < Pages; ++i) { - if ( i < 3 ) { PrintAndLog("Block %02x:%s ", i,sprint_hex(data + i * 4, 4)); continue; } - switch(i){ case 3: tmplockbit = bit[4]; break; case 4: tmplockbit = bit[3]; break; @@ -473,27 +467,20 @@ int CmdHF14AMfUDump(const char *Cmd){ } PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),tmplockbit); } - - int len = 0; - if ( Pages == 16 ) - len = param_getstr(Cmd,0,filename); - else - len = param_getstr(Cmd,1,filename); - if (len > FILE_PATH_SIZE-5) len = FILE_PATH_SIZE-5; + int len = param_getstr(Cmd,0,filename); + if (len > FILE_PATH_SIZE-5) + len = FILE_PATH_SIZE-5; // user supplied filename? if (len < 1) { - // UID = data 0-1-2 4-5-6-7 (skips a beat) sprintf(fnameptr,"%02X%02X%02X%02X%02X%02X%02X.bin", data[0],data[1], data[2], data[4],data[5],data[6], data[7]); - } else { sprintf(fnameptr + len," .bin"); } - if ((fout = fopen(filename,"wb")) == NULL) { PrintAndLog("Could not create file name %s", filename); return 1; @@ -899,7 +886,7 @@ int CmdHF14AMfucSetPwd(const char *Cmd){ } // -// Mifare Ultraligh - Set UID +// Magic UL / UL-C tags - Set UID // int CmdHF14AMfucSetUid(const char *Cmd){ @@ -1080,17 +1067,17 @@ int CmdHF14AMfuGenDiverseKeys(const char *Cmd){ //------------------------------------ static command_t CommandTable[] = { - {"help", CmdHelp, 1,"This help"}, - {"dbg", CmdHF14AMfDbg, 0,"Set default debug mode"}, - {"info", CmdHF14AMfUInfo, 0,"Taginfo"}, - {"dump", CmdHF14AMfUDump, 0,"Dump MIFARE Ultralight / Ultralight-C tag to binary file"}, - {"rdbl", CmdHF14AMfURdBl, 0,"Read block - MIFARE Ultralight"}, - {"wrbl", CmdHF14AMfUWrBl, 0,"Write block - MIFARE Ultralight"}, - {"crdbl", CmdHF14AMfUCRdBl, 0,"Read block - MIFARE Ultralight C"}, - {"cwrbl", CmdHF14AMfUCWrBl, 0,"Write block - MIFARE Ultralight C"}, - {"cauth", CmdHF14AMfucAuth, 0,"Ultralight C Authentication"}, - {"setpwd", CmdHF14AMfucSetPwd , 1, "Set 3des password [Ultralight-C only]"}, - {"setuid", CmdHF14AMfucSetUid , 1, "Set UID"}, + {"help", CmdHelp, 1, "This help"}, + {"dbg", CmdHF14AMfDbg, 0, "Set default debug mode"}, + {"info", CmdHF14AMfUInfo, 0, "Tag information"}, + {"dump", CmdHF14AMfUDump, 0, "Dump Ultralight / Ultralight-C tag to binary file"}, + {"rdbl", CmdHF14AMfURdBl, 0, "Read block - Ultralight"}, + {"wrbl", CmdHF14AMfUWrBl, 0, "Write block - Ultralight"}, + {"crdbl", CmdHF14AMfUCRdBl, 0, "Read block - Ultralight C"}, + {"cwrbl", CmdHF14AMfUCWrBl, 0, "Write block - Ultralight C"}, + {"cauth", CmdHF14AMfucAuth, 0, "Authentication - Ultralight C"}, + {"setpwd", CmdHF14AMfucSetPwd, 1, "Set 3des password - Ultralight-C"}, + {"setuid", CmdHF14AMfucSetUid, 1, "Set UID - MAGIC tags only"}, {"gen", CmdHF14AMfuGenDiverseKeys , 1, "Generate 3des mifare diversified keys"}, {NULL, NULL, 0, NULL} }; diff --git a/client/cmdhfmfu.h b/client/cmdhfmfu.h index 721933902..64f32a49f 100644 --- a/client/cmdhfmfu.h +++ b/client/cmdhfmfu.h @@ -19,6 +19,9 @@ void rol (uint8_t *data, const size_t len); uint8_t requestAuthentication( uint8_t *nonce); int try3DesAuthentication( uint8_t *key); +uint8_t GetHF14AMfU_Type(void); + +int usage_hf_mfu_dump(void); int CmdHFMFUltra(const char *Cmd); int CmdHF14AMfUInfo(const char *Cmd); From 7eec1204e7ab07e2840b64c274715422af5f1393 Mon Sep 17 00:00:00 2001 From: marshmellow42 Date: Thu, 30 Apr 2015 10:34:20 -0400 Subject: [PATCH 07/49] fix bug in mfu cauth --- client/cmdhfmfu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/cmdhfmfu.c b/client/cmdhfmfu.c index 2f7fa2c92..8b906904a 100644 --- a/client/cmdhfmfu.c +++ b/client/cmdhfmfu.c @@ -540,8 +540,8 @@ int CmdHF14AMfucAuth(const char *Cmd){ } uint8_t *key = default_3des_keys[keyNo]; - if (try3DesAuthentication(key)) - PrintAndLog("Authentication successful. 3des key: %s",sprint_hex(key, 8)); + if (try3DesAuthentication(key)>0) + PrintAndLog("Authentication successful. 3des key: %s",sprint_hex(key, 16)); else PrintAndLog("Authentication failed"); From b3125340f39856e7d8b3fbdcaeacc0baf0e71336 Mon Sep 17 00:00:00 2001 From: marshmellow42 Date: Sun, 3 May 2015 15:41:11 -0400 Subject: [PATCH 08/49] Icemans UL-C Auth dev side fix plus a few other ... ... small UL fixes --- armsrc/des.c | 19 +++++++- armsrc/des.h | 4 +- armsrc/mifarecmd.c | 105 +++++++++++++++++++++++++++------------------ client/cmdhfmfu.c | 17 +++++--- 4 files changed, 93 insertions(+), 52 deletions(-) diff --git a/armsrc/des.c b/armsrc/des.c index dbe62da99..a81df9c8d 100644 --- a/armsrc/des.c +++ b/armsrc/des.c @@ -378,38 +378,53 @@ void tdes_dec(void* out, void* in, const uint8_t* key){ des_dec(out, out, (uint8_t*)key + 0); } -void tdes_2key_enc(void* out, const void* in, size_t length, const void* key){ +void tdes_2key_enc(void* out, const void* in, size_t length, const void* key, unsigned char iv[8]){ if( length % 8 ) return; + uint8_t i; uint8_t* tin = (uint8_t*) in; uint8_t* tout = (uint8_t*) out; while( length > 0 ) { + for ( i = 0; i < 8; i++ ) + tout[i] = (unsigned char)(tin[i] ^ iv[i]); + des_enc(tout, tin, (uint8_t*)key + 0); des_dec(tout, tout, (uint8_t*)key + 8); des_enc(tout, tout, (uint8_t*)key + 0); + memcpy(iv, tout, 8); + tin += 8; tout += 8; length -= 8; } } -void tdes_2key_dec(void* out, const void* in, size_t length, const void* key){ +void tdes_2key_dec(void* out, const void* in, size_t length, const void* key, unsigned char iv[8]){ if( length % 8 ) return; + uint8_t i; + unsigned char temp[8]; uint8_t* tin = (uint8_t*) in; uint8_t* tout = (uint8_t*) out; while( length > 0 ) { + memcpy(temp, tin, 8); + des_dec(tout, tin, (uint8_t*)key + 0); des_enc(tout, tout, (uint8_t*)key + 8); des_dec(tout, tout, (uint8_t*)key + 0); + for (i = 0; i < 8; i++) + tout[i] = (unsigned char)(tout[i] ^ iv[i]); + + memcpy(iv, temp, 8); + tin += 8; tout += 8; length -= 8; diff --git a/armsrc/des.h b/armsrc/des.h index cc1d59b01..90f742464 100644 --- a/armsrc/des.h +++ b/armsrc/des.h @@ -97,8 +97,8 @@ void tdes_enc(void* out, const void* in, const void* key); */ void tdes_dec(void* out, const void* in, const void* key); - void tdes_2key_enc(void* out, const void* in, size_t length, const void* key); - void tdes_2key_dec(void* out, const void* in, size_t length, const void* key); + void tdes_2key_enc(void* out, const void* in, size_t length, const void* key, unsigned char iv[8]); + void tdes_2key_dec(void* out, const void* in, size_t length, const void* key, unsigned char iv[8]); #endif /*DES_H_*/ diff --git a/armsrc/mifarecmd.c b/armsrc/mifarecmd.c index 03e191e04..3a9324092 100644 --- a/armsrc/mifarecmd.c +++ b/armsrc/mifarecmd.c @@ -171,13 +171,12 @@ void MifareUReadBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain) // Dbprintf("KEY: %02x %02x %02x %02x %02x %02x %02x %02x", key[0],key[1],key[2],key[3],key[4],key[5],key[6],key[7] ); // Dbprintf("KEY: %02x %02x %02x %02x %02x %02x %02x %02x", key[8],key[9],key[10],key[11],key[12],key[13],key[14],key[15] ); - uint8_t a[8] = {1,1,1,1,1,1,1,1 }; - uint8_t b[8] = {0x00}; - uint8_t enc_b[8] = {0x00}; - uint8_t ab[16] = {0x00}; - uint8_t enc_ab[16] = {0x00}; - uint8_t enc_key[8] = {0x00}; - + uint8_t random_a[8] = {1,1,1,1,1,1,1,1 }; + uint8_t random_b[8] = {0x00}; + uint8_t enc_random_b[8] = {0x00}; + uint8_t rnd_ab[16] = {0x00}; + uint8_t IV[8] = {0x00}; + uint16_t len; uint8_t receivedAnswer[MAX_FRAME_SIZE]; uint8_t receivedAnswerPar[MAX_PARITY_SIZE]; @@ -188,69 +187,93 @@ void MifareUReadBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain) OnError(1); return; } - + // tag nonce. - memcpy(enc_b,receivedAnswer+1,8); + memcpy(enc_random_b,receivedAnswer+1,8); // decrypt nonce. - tdes_2key_dec(b, enc_b, 8, key ); + tdes_2key_dec(random_b, enc_random_b, sizeof(random_b), key, IV ); - Dbprintf("enc_B: %02x %02x %02x %02x %02x %02x %02x %02x", enc_b[0],enc_b[1],enc_b[2],enc_b[3],enc_b[4],enc_b[5],enc_b[6],enc_b[7] ); - Dbprintf(" B: %02x %02x %02x %02x %02x %02x %02x %02x", b[0],b[1],b[2],b[3],b[4],b[5],b[6],b[7] ); - rol(b,8); + + rol(random_b,8); - memcpy(ab ,a,8); - memcpy(ab+8,b,8); + memcpy(rnd_ab ,random_a,8); + memcpy(rnd_ab+8,random_b,8); - Dbprintf("AB: %02x %02x %02x %02x %02x %02x %02x %02x", ab[0],ab[1],ab[2],ab[3],ab[4],ab[5],ab[6],ab[7] ); - Dbprintf("AB: %02x %02x %02x %02x %02x %02x %02x %02x", ab[8],ab[9],ab[10],ab[11],ab[12],ab[13],ab[14],ab[15] ); + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) { + Dbprintf("enc_B: %02x %02x %02x %02x %02x %02x %02x %02x", + enc_random_b[0],enc_random_b[1],enc_random_b[2],enc_random_b[3], + enc_random_b[4],enc_random_b[5],enc_random_b[6],enc_random_b[7]); + + Dbprintf(" B: %02x %02x %02x %02x %02x %02x %02x %02x", + random_b[0],random_b[1],random_b[2],random_b[3], + random_b[4],random_b[5],random_b[6],random_b[7]); - // encrypt - tdes_2key_enc(enc_ab, ab, 16, key); + Dbprintf("rnd_ab: %02x %02x %02x %02x %02x %02x %02x %02x", + rnd_ab[0],rnd_ab[1],rnd_ab[2],rnd_ab[3], + rnd_ab[4],rnd_ab[5],rnd_ab[6],rnd_ab[7]); + + Dbprintf("rnd_ab: %02x %02x %02x %02x %02x %02x %02x %02x", + rnd_ab[8],rnd_ab[9],rnd_ab[10],rnd_ab[11], + rnd_ab[12],rnd_ab[13],rnd_ab[14],rnd_ab[15] ); + } + + // encrypt out, in, length, key, iv + tdes_2key_enc(rnd_ab, rnd_ab, sizeof(rnd_ab), key, enc_random_b); - Dbprintf("e_AB: %02x %02x %02x %02x %02x %02x %02x %02x", enc_ab[0],enc_ab[1],enc_ab[2],enc_ab[3],enc_ab[4],enc_ab[5],enc_ab[6],enc_ab[7] ); - Dbprintf("e_enc_ab: %02x %02x %02x %02x %02x %02x %02x %02x", enc_ab[8],enc_ab[9],enc_ab[10],enc_ab[11],enc_ab[12],enc_ab[13],enc_ab[14],enc_ab[15] ); - - len = mifare_sendcmd_short_mfucauth(NULL, 1, 0xAF, enc_ab, receivedAnswer, receivedAnswerPar, NULL); + + len = mifare_sendcmd_short_mfucauth(NULL, 1, 0xAF, rnd_ab, receivedAnswer, receivedAnswerPar, NULL); if (len != 11) { if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x", receivedAnswer[0]); OnError(1); return; } - // the tags' encryption of our nonce, A. - memcpy(enc_key, receivedAnswer+1, 8); - - // clear B. - memset(b, 0x00, 8); - - // decrypt - tdes_2key_dec(b, enc_key, 8, key ); - if ( memcmp(a, b, 8) == 0 ) - Dbprintf("Verified key"); - else + uint8_t enc_resp[8] = { 0 }; + uint8_t resp_random_a[8] = { 0 }; + memcpy(enc_resp, receivedAnswer+1, 8); + + // decrypt out, in, length, key, iv + tdes_2key_dec(resp_random_a, enc_resp, 8, key, enc_random_b); + if ( memcmp(resp_random_a, random_a, 8) != 0 ) Dbprintf("failed authentication"); - - Dbprintf("a: %02x %02x %02x %02x %02x %02x %02x %02x", a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7] ); - Dbprintf("b: %02x %02x %02x %02x %02x %02x %02x %02x", b[0],b[1],b[2],b[3],b[4],b[5],b[6],b[7] ); - } + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) { + Dbprintf("e_AB: %02x %02x %02x %02x %02x %02x %02x %02x", + rnd_ab[0],rnd_ab[1],rnd_ab[2],rnd_ab[3], + rnd_ab[4],rnd_ab[5],rnd_ab[6],rnd_ab[7]); + + Dbprintf("e_AB: %02x %02x %02x %02x %02x %02x %02x %02x", + rnd_ab[8],rnd_ab[9],rnd_ab[10],rnd_ab[11], + rnd_ab[12],rnd_ab[13],rnd_ab[14],rnd_ab[15]); + + Dbprintf("a: %02x %02x %02x %02x %02x %02x %02x %02x", + random_a[0],random_a[1],random_a[2],random_a[3], + random_a[4],random_a[5],random_a[6],random_a[7]); + + Dbprintf("b: %02x %02x %02x %02x %02x %02x %02x %02x", + resp_random_a[0],resp_random_a[1],resp_random_a[2],resp_random_a[3], + resp_random_a[4],resp_random_a[5],resp_random_a[6],resp_random_a[7]); + } + } + if( mifare_ultra_readblock(blockNo, dataout) ) { if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Read block error"); OnError(2); return; } - + if( mifare_ultra_halt() ) { if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Halt error"); OnError(3); return; } - - cmd_send(CMD_ACK,1,0,0,dataout,16); + + cmd_send(CMD_ACK,1,0,0,dataout,16); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LEDsoff(); } + //----------------------------------------------------------------------------- // Select, Authenticate, Read a MIFARE tag. // read sector (data = 4 x 16 bytes = 64 bytes, or 16 x 16 bytes = 256 bytes) diff --git a/client/cmdhfmfu.c b/client/cmdhfmfu.c index 8b906904a..9825f9281 100644 --- a/client/cmdhfmfu.c +++ b/client/cmdhfmfu.c @@ -87,7 +87,7 @@ uint8_t GetHF14AMfU_Type(void){ // EV1 GetVersion if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { - uint8_t version[8] = {0,0,0,0,0,0,0,0}; + uint8_t version[10] = {0,0,0,0,0,0,0,0}; memcpy(&version, resp.d.asBytes, sizeof(version)); uint8_t len = resp.arg[0] & 0xff; @@ -722,7 +722,7 @@ int CmdHF14AMfUCRdBl(const char *Cmd) PrintAndLog("Usage: hf mfu crdbl "); PrintAndLog(""); PrintAndLog("sample: hf mfu crdbl 0"); - PrintAndLog(" hf mfu crdbl 0 112233445566778899AABBCCDDEEFF"); + PrintAndLog(" hf mfu crdbl 0 00112233445566778899AABBCCDDEEFF"); return 0; } @@ -803,14 +803,15 @@ int CmdHF14AMfUCWrBl(const char *Cmd){ PrintAndLog("Block data must include 8 HEX symbols"); return 1; } - + if (strchr(Cmd,'w') != 0 || strchr(Cmd,'W') != 0 ) { chinese_card = TRUE; } - + if ( blockNo <= 3 ) { if (!chinese_card){ - PrintAndLog("Access Denied"); + PrintAndLog("Access Denied"); + return 1; } else { PrintAndLog("--Special block no: 0x%02x", blockNo); PrintAndLog("--Data: %s", sprint_hex(bldata, 4)); @@ -822,8 +823,9 @@ int CmdHF14AMfUCWrBl(const char *Cmd){ PrintAndLog("isOk:%02x", isOK); } else { PrintAndLog("Command execute timeout"); - } - } + return 1; + } + } } else { PrintAndLog("--Block no : 0x%02x", blockNo); PrintAndLog("--Data: %s", sprint_hex(bldata, 4)); @@ -835,6 +837,7 @@ int CmdHF14AMfUCWrBl(const char *Cmd){ PrintAndLog("isOk : %02x", isOK); } else { PrintAndLog("Command execute timeout"); + return 1; } } return 0; From 4b36037948fb7f0de45ac1033e6da335810c4993 Mon Sep 17 00:00:00 2001 From: Martin Holst Swende Date: Sun, 3 May 2015 22:09:52 +0200 Subject: [PATCH 09/49] Fixes to issue #100 --- client/cmdhf14a.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client/cmdhf14a.c b/client/cmdhf14a.c index 200c9dcd6..d4285eeab 100644 --- a/client/cmdhf14a.c +++ b/client/cmdhf14a.c @@ -177,8 +177,8 @@ int CmdHF14AReader(const char *Cmd) SendCommand(&c); WaitForResponse(CMD_ACK,&resp); - uint8_t version[8] = {0,0,0,0,0,0,0,0}; - memcpy(&version, resp.d.asBytes, resp.arg[0]); + uint8_t version[10] = {0}; + memcpy(version, resp.d.asBytes, resp.arg[0] < sizeof(version) ? resp.arg[0] : sizeof(version)); uint8_t len = resp.arg[0] & 0xff; switch ( len ){ // todo, identify "Magic UL-C tags". // they usually have a static nonce response to 0x1A command. @@ -221,7 +221,7 @@ int CmdHF14AReader(const char *Cmd) SendCommand(&c); WaitForResponse(CMD_ACK,&resp); - memcpy(&card.ats, resp.d.asBytes, resp.arg[0]); + memcpy(card.ats, resp.d.asBytes, resp.arg[0]); card.ats_len = resp.arg[0]; // note: ats_len includes CRC Bytes } From f9848fd647ce3c708510d8ead6d1b56b26c57ad9 Mon Sep 17 00:00:00 2001 From: marshmellow42 Date: Sun, 3 May 2015 23:17:11 -0400 Subject: [PATCH 10/49] MFU dump UL-C with key adding UL-C auth and keys to dump cmd swapped endian for input of hf mfu crdbl to match output of hf mfu info cmd and tag info app --- client/cmdhfmfu.c | 115 +++++++++++++++++++++++++++++++++------------- client/util.c | 14 ++++++ client/util.h | 1 + 3 files changed, 98 insertions(+), 32 deletions(-) diff --git a/client/cmdhfmfu.c b/client/cmdhfmfu.c index 9825f9281..620f1b0e1 100644 --- a/client/cmdhfmfu.c +++ b/client/cmdhfmfu.c @@ -12,6 +12,7 @@ #include "cmdhfmf.h" #include "cmdhf14a.h" #include "mifare.h" +#include "util.h" #define MAX_UL_BLOCKS 0x0f #define MAX_ULC_BLOCKS 0x2f @@ -87,8 +88,8 @@ uint8_t GetHF14AMfU_Type(void){ // EV1 GetVersion if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { - uint8_t version[10] = {0,0,0,0,0,0,0,0}; - memcpy(&version, resp.d.asBytes, sizeof(version)); + uint8_t version[10] = {0,0,0,0,0,0,0,0,0,0}; + memcpy(version, resp.d.asBytes, resp.arg[0] < sizeof(version) ? resp.arg[0] : sizeof(version)); uint8_t len = resp.arg[0] & 0xff; if ( len == 0x0A && version[6] == 0x0B ) @@ -324,10 +325,9 @@ int usage_hf_mfu_dump(void) PrintAndLog("Reads all pages from Ultralight, Ultralight-C, Ultralight EV1"); PrintAndLog("and saves binary dump into the file `filename.bin` or `cardUID.bin`"); PrintAndLog("It autodetects card type.\n"); - PrintAndLog("Usage: hf mfu dump "); + PrintAndLog("Usage: hf mfu dump k n "); PrintAndLog(" sample : hf mfu dump"); - PrintAndLog(" : hf mfu dump myfile"); - PrintAndLog(" : hf mfu dump 1 myfile"); + PrintAndLog(" : hf mfu dump n myfile"); return 0; } // @@ -337,26 +337,66 @@ int usage_hf_mfu_dump(void) // TODO: take a password to read UL-C / UL-EV1 tags. int CmdHF14AMfUDump(const char *Cmd){ - char cmdp = param_getchar(Cmd, 0); - if (cmdp == 'h' || cmdp == 'H') - return usage_hf_mfu_dump(); - FILE *fout; char filename[FILE_PATH_SIZE] = {0x00}; char *fnameptr = filename; char *str = "Dumping Ultralight%s%s Card Data..."; - uint8_t *lockbytes_t = NULL; uint8_t lockbytes[2] = {0x00}; uint8_t *lockbytes_t2 = NULL; uint8_t lockbytes2[2] = {0x00}; bool bit[16] = {0x00}; bool bit2[16] = {0x00}; - uint8_t data[176] = {0x00}; - + uint8_t data[1024] = {0x00}; + bool hasPwd = false; int i = 0; int Pages = 16; bool tmplockbit = false; + uint8_t dataLen=0; + uint8_t cmdp =0; + uint8_t *key= NULL; + size_t fileNlen = 0; + bool errors = FALSE; + + while(param_getchar(Cmd, cmdp) != 0x00) + { + switch(param_getchar(Cmd, cmdp)) + { + case 'h': + case 'H': + return usage_hf_mfu_dump(); + case 'k': + case 'K': + dataLen = param_gethex(Cmd, cmdp+1, data, 32); + if (dataLen) { + errors = true; + } else { + key = SwapEndian64(data, 16); + PrintAndLog("3des key: %s",sprint_hex(key, 16)); + } + cmdp += 2; + hasPwd = true; + break; + case 'n': + case 'N': + fileNlen = param_getstr(Cmd, cmdp+1, filename); + if (!fileNlen) errors = true; + if (fileNlen > FILE_PATH_SIZE-5) fileNlen = FILE_PATH_SIZE-5; + cmdp += 2; + break; + default: + PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp)); + errors = true; + break; + } + if(errors) break; + } + + //Validations + if(errors) + { + return usage_hf_mfu_dump(); + } TagTypeUL_t tagtype = GetHF14AMfU_Type(); if (tagtype == UL_ERROR) return -1; @@ -381,21 +421,29 @@ int CmdHF14AMfUDump(const char *Cmd){ PrintAndLog("Dumping unknown Ultralight, using default values."); } - UsbCommand c = {CMD_MIFAREU_READCARD, {0,Pages}}; - SendCommand(&c); - UsbCommand resp; + for (uint8_t i = 0; i FILE_PATH_SIZE-5) - len = FILE_PATH_SIZE-5; - // user supplied filename? - if (len < 1) { + if (fileNlen < 1) { // UID = data 0-1-2 4-5-6-7 (skips a beat) sprintf(fnameptr,"%02X%02X%02X%02X%02X%02X%02X.bin", data[0],data[1], data[2], data[4],data[5],data[6], data[7]); } else { - sprintf(fnameptr + len," .bin"); + sprintf(fnameptr + fileNlen," .bin"); } if ((fout = fopen(filename,"wb")) == NULL) { @@ -707,6 +756,7 @@ int CmdTestDES(const char * cmd) return 0; } **/ + // // Ultralight C Read Single Block // @@ -715,7 +765,7 @@ int CmdHF14AMfUCRdBl(const char *Cmd) UsbCommand resp; bool hasPwd = FALSE; uint8_t blockNo = -1; - unsigned char key[16]; + uint8_t key[16]; char cmdp = param_getchar(Cmd, 0); if (strlen(Cmd) < 1 || cmdp == 'h' || cmdp == 'H') { @@ -746,12 +796,13 @@ int CmdHF14AMfUCRdBl(const char *Cmd) hasPwd = TRUE; } } + uint8_t *key2 = SwapEndian64(key, 16); //Read Block UsbCommand c = {CMD_MIFAREU_READBL, {blockNo}}; if ( hasPwd ) { c.arg[1] = 1; - memcpy(c.d.asBytes,key,16); + memcpy(c.d.asBytes,key2,16); } SendCommand(&c); diff --git a/client/util.c b/client/util.c index 709e20149..5bb98fd77 100644 --- a/client/util.c +++ b/client/util.c @@ -158,6 +158,20 @@ uint64_t bytes_to_num(uint8_t* src, size_t len) return num; } +// aa,bb,cc,dd,ee,ff,gg,hh, ii,jj,kk,ll,mm,nn,oo,pp +// to +// hh,gg,ff,ee,dd,cc,bb,aa, pp,oo,nn,mm,ll,kk,jj,ii +// up to 64 bytes or 512 bits +uint8_t *SwapEndian64(uint8_t *src, size_t len){ + static uint8_t temp[64]={0}; + for (uint8_t block=0; block < (uint8_t)len/8; block++){ + for (size_t i = 0; i < 8; i++){ + temp[i+(8*block)] = src[(7-i)+(8*block)]; + } + } + return temp; +} + //assumes little endian char * printBits(size_t const size, void const * const ptr) { diff --git a/client/util.h b/client/util.h index a6d0f49f2..fb587da0b 100644 --- a/client/util.h +++ b/client/util.h @@ -44,6 +44,7 @@ char * sprint_bin_break(const uint8_t *data, const size_t len, const uint8_t bre void num_to_bytes(uint64_t n, size_t len, uint8_t* dest); uint64_t bytes_to_num(uint8_t* src, size_t len); char * printBits(size_t const size, void const * const ptr); +uint8_t *SwapEndian64(uint8_t *src, size_t len); char param_getchar(const char *line, int paramnum); uint8_t param_get8(const char *line, int paramnum); From 75377d29d6f63cf67e427727706fe19149640861 Mon Sep 17 00:00:00 2001 From: marshmellow42 Date: Wed, 6 May 2015 00:55:29 -0400 Subject: [PATCH 11/49] MFU - Icemans further improvements add UL-C device side read card with authentication add MF_UL-Annotations add ntag, and more ul descriptions in hf mfu info --- armsrc/appmain.c | 4 +- armsrc/apps.h | 2 +- armsrc/mifarecmd.c | 93 ++++-- client/cmdhf.c | 43 ++- client/cmdhfmfu.c | 730 ++++++++++++++++++++++++++++++++++----------- client/cmdhfmfu.h | 2 +- 6 files changed, 667 insertions(+), 207 deletions(-) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 128f4063b..48b8c0dd2 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -833,10 +833,8 @@ void UsbPacketReceived(uint8_t *packet, int len) MifareUC_Auth2(c->arg[0],c->d.asBytes); break; case CMD_MIFAREU_READCARD: - MifareUReadCard(c->arg[0], c->arg[1], c->d.asBytes); - break; case CMD_MIFAREUC_READCARD: - MifareUReadCard(c->arg[0], c->arg[1], c->d.asBytes); + MifareUReadCard(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); break; case CMD_MIFAREUC_SETPWD: MifareUSetPwd(c->arg[0], c->d.asBytes); diff --git a/armsrc/apps.h b/armsrc/apps.h index 7e4aa5e1a..d01c6478c 100644 --- a/armsrc/apps.h +++ b/armsrc/apps.h @@ -168,7 +168,7 @@ 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_Auth1(uint8_t arg0, uint8_t *datain); void MifareUC_Auth2(uint32_t arg0, uint8_t *datain); -void MifareUReadCard(uint8_t arg0, int Pages, 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 MifareUWriteBlock(uint8_t arg0,uint8_t *datain); diff --git a/armsrc/mifarecmd.c b/armsrc/mifarecmd.c index 3a9324092..c51a30dc9 100644 --- a/armsrc/mifarecmd.c +++ b/armsrc/mifarecmd.c @@ -143,6 +143,9 @@ void MifareUC_Auth2(uint32_t arg0, uint8_t *datain){ LEDsoff(); } +// Arg0 = BlockNo, +// Arg1 = UsePwd bool +// datain = PWD bytes, void MifareUReadBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain) { uint8_t blockNo = arg0; @@ -151,8 +154,8 @@ void MifareUReadBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain) uint8_t key[16] = {0x00}; bool usePwd = (arg1 == 1); - LED_A_ON(); LED_B_OFF(); LED_C_OFF(); - + LEDsoff(); + LED_A_ON(); clear_trace(); iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); @@ -193,10 +196,7 @@ void MifareUReadBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain) // decrypt nonce. tdes_2key_dec(random_b, enc_random_b, sizeof(random_b), key, IV ); - - rol(random_b,8); - memcpy(rnd_ab ,random_a,8); memcpy(rnd_ab+8,random_b,8); @@ -221,7 +221,6 @@ void MifareUReadBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain) // encrypt out, in, length, key, iv tdes_2key_enc(rnd_ab, rnd_ab, sizeof(rnd_ab), key, enc_random_b); - len = mifare_sendcmd_short_mfucauth(NULL, 1, 0xAF, rnd_ab, receivedAnswer, receivedAnswerPar, NULL); if (len != 11) { if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x", receivedAnswer[0]); @@ -342,13 +341,14 @@ void MifareReadSector(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) LEDsoff(); } -void MifareUReadCard(uint8_t arg0, int arg1, uint8_t *datain) +void MifareUReadCard(uint8_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain) { // params - uint8_t sectorNo = arg0; - int Pages = arg1; - int countpages = 0; - byte_t dataout[176] = {0x00};; + uint8_t blockNo = arg0; + uint16_t blocks = arg1; + bool useKey = (arg2 == 1); + int countblocks = 0; + uint8_t dataout[176] = {0x00}; LEDsoff(); LED_A_ON(); @@ -361,32 +361,81 @@ void MifareUReadCard(uint8_t arg0, int arg1, uint8_t *datain) OnError(1); return; } - - for (int i = 0; i < Pages; i++){ - - len = mifare_ultra_readblock(sectorNo * 4 + i, dataout + 4 * i); - + + // authenticate + if ( useKey ) { + uint8_t key[16] = {0x00}; + memcpy(key, datain, 16); + + uint8_t random_a[8] = {1,1,1,1,1,1,1,1 }; + uint8_t random_b[8] = {0x00}; + uint8_t enc_random_b[8] = {0x00}; + uint8_t rnd_ab[16] = {0x00}; + uint8_t IV[8] = {0x00}; + + uint16_t len; + uint8_t receivedAnswer[MAX_FRAME_SIZE]; + uint8_t receivedAnswerPar[MAX_PARITY_SIZE]; + + len = mifare_sendcmd_short(NULL, 1, 0x1A, 0x00, receivedAnswer,receivedAnswerPar ,NULL); + if (len != 11) { + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x", receivedAnswer[0]); + OnError(1); + return; + } + + // tag nonce. + memcpy(enc_random_b,receivedAnswer+1,8); + + // decrypt nonce. + tdes_2key_dec(random_b, enc_random_b, sizeof(random_b), key, IV ); + rol(random_b,8); + memcpy(rnd_ab ,random_a,8); + memcpy(rnd_ab+8,random_b,8); + + // encrypt out, in, length, key, iv + tdes_2key_enc(rnd_ab, rnd_ab, sizeof(rnd_ab), key, enc_random_b); + + len = mifare_sendcmd_short_mfucauth(NULL, 1, 0xAF, rnd_ab, receivedAnswer, receivedAnswerPar, NULL); + if (len != 11) { + OnError(1); + return; + } + + uint8_t enc_resp[8] = { 0 }; + uint8_t resp_random_a[8] = { 0 }; + memcpy(enc_resp, receivedAnswer+1, 8); + + // decrypt out, in, length, key, iv + tdes_2key_dec(resp_random_a, enc_resp, 8, key, enc_random_b); + if ( memcmp(resp_random_a, random_a, 8) != 0 ) + Dbprintf("failed authentication"); + } + + for (int i = 0; i < blocks; i++){ + len = mifare_ultra_readblock(blockNo * 4 + i, dataout + 4 * i); + if (len) { if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Read block %d error",i); OnError(2); return; } else { - countpages++; + countblocks++; } } - + len = mifare_ultra_halt(); if (len) { if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Halt error"); OnError(3); return; } - - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("Pages read %d", countpages); - len = Pages * 4; + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("Blocks read %d", countblocks); - cmd_send(CMD_ACK, 1, 0, 0, dataout, len); + len = blocks * 4; + + cmd_send(CMD_ACK, 1, len, 0, dataout, len); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LEDsoff(); } diff --git a/client/cmdhf.c b/client/cmdhf.c index 22063bbbe..b2950ed08 100644 --- a/client/cmdhf.c +++ b/client/cmdhf.c @@ -71,11 +71,52 @@ void annotateIso14443a(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize) case MIFARE_CMD_DEC: snprintf(exp,size,"DEC(%d)",cmd[1]); break; case MIFARE_CMD_RESTORE: snprintf(exp,size,"RESTORE(%d)",cmd[1]); break; case MIFARE_CMD_TRANSFER: snprintf(exp,size,"TRANSFER(%d)",cmd[1]); break; - case MIFARE_AUTH_KEYA: snprintf(exp,size,"AUTH-A(%d)",cmd[1]); break; + case MIFARE_AUTH_KEYA:{ + if ( cmdsize > 3) + snprintf(exp,size,"AUTH-A(%d)",cmd[1]); + else + // case MIFARE_ULEV1_VERSION : both 0x60. + snprintf(exp,size,"EV1 VERSION"); + break; + } case MIFARE_AUTH_KEYB: snprintf(exp,size,"AUTH-B(%d)",cmd[1]); break; case MIFARE_MAGICWUPC1: snprintf(exp,size,"MAGIC WUPC1"); break; case MIFARE_MAGICWUPC2: snprintf(exp,size,"MAGIC WUPC2"); break; case MIFARE_MAGICWIPEC: snprintf(exp,size,"MAGIC WIPEC"); break; + case MIFARE_ULC_AUTH_1: snprintf(exp,size,"AUTH "); break; + case MIFARE_ULC_AUTH_2: snprintf(exp,size,"AUTH_ANSW"); break; + case MIFARE_ULEV1_AUTH: snprintf(exp,size,"PWD-AUTH"); break; + case MIFARE_ULEV1_FASTREAD:{ + if ( cmdsize >=3 && cmd[2] < 0x21) + snprintf(exp,size,"READ RANGE (%d-%d)",cmd[1],cmd[2]); + else + snprintf(exp,size,"?"); + break; + } + case MIFARE_ULEV1_WRITE:{ + if ( cmd[1] < 0x21 ) + snprintf(exp,size,"WRITEBLOCK(%d)",cmd[1]); + else + snprintf(exp,size,"?"); + break; + } + case MIFARE_ULEV1_READ_CNT:{ + if ( cmd[1] < 5 ) + snprintf(exp,size,"READ CNT(%d)",cmd[1]); + else + snprintf(exp,size,"?"); + break; + } + case MIFARE_ULEV1_INCR_CNT:{ + if ( cmd[1] < 5 ) + snprintf(exp,size,"INCR(%d)",cmd[1]); + else + snprintf(exp,size,"?"); + break; + } + case MIFARE_ULEV1_READSIG: snprintf(exp,size,"READ_SIG"); break; + case MIFARE_ULEV1_CHECKTEAR: snprintf(exp,size,"CHK_TEARING(%d)",cmd[1]); break; + case MIFARE_ULEV1_VCSL: snprintf(exp,size,"VCSL"); break; default: snprintf(exp,size,"?"); break; } return; diff --git a/client/cmdhfmfu.c b/client/cmdhfmfu.c index 620f1b0e1..396eb239e 100644 --- a/client/cmdhfmfu.c +++ b/client/cmdhfmfu.c @@ -13,11 +13,31 @@ #include "cmdhf14a.h" #include "mifare.h" #include "util.h" +#include "protocols.h" -#define MAX_UL_BLOCKS 0x0f -#define MAX_ULC_BLOCKS 0x2f -#define MAX_ULEV1a_BLOCKS 0x0b; -#define MAX_ULEV1b_BLOCKS 0x20; +#define MAX_UL_BLOCKS 0x0f +#define MAX_ULC_BLOCKS 0x2f +#define MAX_ULEV1a_BLOCKS 0x0b +#define MAX_ULEV1b_BLOCKS 0x20 +#define MAX_NTAG_213 0x2c +#define MAX_NTAG_215 0x86 +#define MAX_NTAG_216 0xe6 + +typedef enum TAGTYPE_UL { + UNKNOWN = 0x0000, + UL = 0x0001, + UL_C = 0x0002, + UL_EV1_48 = 0x0004, + UL_EV1_128 = 0x0008, + NTAG = 0x0010, + NTAG_213 = 0x0020, + NTAG_215 = 0x0040, + NTAG_216 = 0x0080, + MAGIC = 0x0100, + UL_MAGIC = UL | MAGIC, + UL_C_MAGIC = UL_C | MAGIC, + UL_ERROR = 0xFFFF, +} TagTypeUL_t; uint8_t default_3des_keys[7][16] = { { 0x42,0x52,0x45,0x41,0x4b,0x4d,0x45,0x49,0x46,0x59,0x4f,0x55,0x43,0x41,0x4e,0x21 },// 3des std key @@ -27,185 +47,531 @@ uint8_t default_3des_keys[7][16] = { { 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01 },// all ones { 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF },// all FF { 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xAA,0xBB,0xCC,0xDD,0xEE,0xFF } // 11 22 33 - }; - +}; + static int CmdHelp(const char *Cmd); -// return 1 if tag responded to 0x1A. -uint8_t requestAuthentication( uint8_t* nonce){ +char* getProductTypeStr( uint8_t id){ - UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_CONNECT | ISO14A_RAW | ISO14A_APPEND_CRC ,2 ,0}}; - c.d.asBytes[0] = 0x1A; - c.d.asBytes[1] = 0x00; + static char buf[20]; + char *retStr = buf; + + switch(id) { + case 3: + sprintf(retStr, "0x%02X %s", id, "(Ultralight)"); + break; + case 4: + sprintf(retStr, "0x%02X %s", id, "(NTAG)"); + break; + default: + sprintf(retStr, "0x%02X %s", id, "(unknown)"); + break; + } + return buf; +} + +/* + The 7 MSBits (=n) code the storage size itself based on 2^n, + the LSBit is set to '0' if the size is exactly 2^n + and set to '1' if the storage size is between 2^n and 2^(n+1). +*/ +char* getUlev1CardSizeStr( uint8_t fsize ){ + + static char buf[30]; + char *retStr = buf; + + uint8_t usize = 1 << ((fsize >>1) + 1); + uint8_t lsize = 1 << (fsize >>1); + + // is LSB set? + if ( fsize & 1 ) + sprintf(retStr, "0x%02X (%u - %u bytes)",fsize, usize, lsize); + else + sprintf(retStr, "0x%02X (%u bytes)", fsize, lsize); + return buf; +} + +static void ul_switch_on_field(void) { + UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_CONNECT | ISO14A_NO_DISCONNECT, 0, 0}}; SendCommand(&c); - UsbCommand resp; - WaitForResponse(CMD_ACK, &resp); // skip select answer. +} - if ( !(resp.arg[0] & 0xff) ) - return 0; +static void ul_switch_off_field(void) { + UsbCommand c = {CMD_READER_ISO_14443a, {0, 0, 0}}; + SendCommand(&c); +} + +static int ul_send_cmd_raw( uint8_t *cmd, uint8_t cmdlen, uint8_t *response, uint16_t responseLength ) { + UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_RAW | ISO14A_NO_DISCONNECT | ISO14A_APPEND_CRC, cmdlen, 0}}; + memcpy(c.d.asBytes, cmd, cmdlen); + SendCommand(&c); + UsbCommand resp; + if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) return -1; + + uint16_t resplen = (resp.arg[0] < responseLength) ? resp.arg[0] : responseLength; + if (resp.arg[0] > 0) { + memcpy(response, resp.d.asBytes, resplen); + return resplen; + } else return -1; +} +/* +static int ul_send_cmd_raw_crc( uint8_t *cmd, uint8_t cmdlen, uint8_t *response, uint16_t responseLength, bool append_crc ) { + UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_RAW | ISO14A_NO_DISCONNECT , cmdlen, 0}}; + if (append_crc) + c.arg[0] |= ISO14A_APPEND_CRC; + + memcpy(c.d.asBytes, cmd, cmdlen); + SendCommand(&c); + UsbCommand resp; + if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) return -1; + + uint16_t resplen = (resp.arg[0] < responseLength) ? resp.arg[0] : responseLength; + if (resp.arg[0] > 0) { + memcpy(response, resp.d.asBytes, resplen); + return resplen; + } else return -1; +} +*/ +static int ul_select( iso14a_card_select_t *card ){ + + ul_switch_on_field(); + + UsbCommand resp; + if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) return -1; + if (resp.arg[0] < 1) return -1; + + memcpy(card, resp.d.asBytes, sizeof(iso14a_card_select_t)); + return resp.arg[0]; +} + +// This read command will at least return 16bytes. +static int ul_read( uint8_t page, uint8_t *response, uint16_t responseLength ){ + + uint8_t cmd[] = {ISO14443A_CMD_READBLOCK, page}; + int len = ul_send_cmd_raw(cmd, sizeof(cmd), response, responseLength); + if ( len == -1 ) + ul_switch_off_field(); + return len; +} + +static int ulc_requestAuthentication( uint8_t blockNo, uint8_t *nonce, uint16_t nonceLength ){ + + uint8_t cmd[] = {MIFARE_ULC_AUTH_1, blockNo}; + int len = ul_send_cmd_raw(cmd, sizeof(cmd), nonce, nonceLength); + if ( len == -1 ) + ul_switch_off_field(); + return len; +} + +static int ulev1_requestAuthentication( uint8_t *pwd, uint8_t *pack, uint16_t packLength ){ + + uint8_t cmd[] = {MIFARE_ULEV1_AUTH, pwd[0], pwd[1], pwd[2], pwd[3]}; + int len = ul_send_cmd_raw(cmd, sizeof(cmd), pack, packLength); + if ( len == -1) + ul_switch_off_field(); + return len; +} + +static int ulev1_getVersion( uint8_t *response, uint16_t responseLength ){ + + uint8_t cmd[] = {MIFARE_ULEV1_VERSION}; + int len = ul_send_cmd_raw(cmd, sizeof(cmd), response, responseLength); + if ( len == -1 ) + ul_switch_off_field(); + return len; +} + +// static int ulev1_fastRead( uint8_t startblock, uint8_t endblock, uint8_t *response ){ - if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { + // uint8_t cmd[] = {MIFARE_ULEV1_FASTREAD, startblock, endblock}; - if ( resp.arg[0] & 0xff ) { - memcpy(nonce, resp.d.asBytes+1, 8); - return 1; - } - } + // if ( !ul_send_cmd_raw(cmd, sizeof(cmd), response)){ + // ul_switch_off_field(); + // return -1; + // } + // return 0; +// } + +static int ulev1_readCounter( uint8_t counter, uint8_t *response, uint16_t responseLength ){ + + uint8_t cmd[] = {MIFARE_ULEV1_READ_CNT, counter}; + int len = ul_send_cmd_raw(cmd, sizeof(cmd), response, responseLength); + if (len == -1) + ul_switch_off_field(); + return len; +} + +static int ul_print_default( uint8_t *data){ + + uint8_t uid[7]; + + uid[0] = data[0]; + uid[1] = data[1]; + uid[2] = data[2]; + uid[3] = data[4]; + uid[4] = data[5]; + uid[5] = data[6]; + uid[6] = data[7]; + + PrintAndLog(" UID : %s ", sprint_hex(uid, 7)); + PrintAndLog(" UID[0] : (Manufacturer Byte) = %02x, Manufacturer: %s", uid[0], getTagInfo(uid[0]) ); + + // BBC + // CT (cascade tag byte) 0x88 xor SN0 xor SN1 xor SN2 + int crc0 = 0x88 ^ data[0] ^ data[1] ^data[2]; + if ( data[3] == crc0 ) + PrintAndLog(" BCC0 : 0x%02X - Ok", data[3]); + else + PrintAndLog(" BCC0 : 0x%02X - crc should be %02x", data[3], crc0); + + int crc1 = data[4] ^ data[5] ^ data[6] ^data[7]; + if ( data[8] == crc1 ) + PrintAndLog(" BCC1 : 0x%02X - Ok", data[8]); + else + PrintAndLog(" BCC1 : 0x%02X - crc should be 0x%02X", data[8], crc1 ); + + PrintAndLog(" Internal : 0x%02X - %s default", data[9], (data[9]==0x48)?"":"not" ); + PrintAndLog(" Lock : %s - %s", sprint_hex(data+10, 2),printBits( 2, data+10) ); + PrintAndLog("OneTimePad : %s ", sprint_hex(data + 12, 4)); + PrintAndLog(""); return 0; } -typedef enum TAGTYPE_UL { - UNKNOWN = 0x00, - UL = 0x01, - UL_C = 0x02, - UL_EV1_48 = 0x04, - UL_EV1_128 = 0x08, - MAGIC = 0x10, - UL_MAGIC = UL | MAGIC, - UL_C_MAGIC = UL_C | MAGIC, - UL_ERROR = 0xFF, -} TagTypeUL_t; +static int ul_print_CC(uint8_t *data) { + if(data[0] != 0xe1) { + PrintAndLog("no NDEF message"); + return -1; // no NDEF message + } -uint8_t GetHF14AMfU_Type(void){ + PrintAndLog("Capability Container: %s", sprint_hex(data,4) ); + PrintAndLog(" %02X: NDEF Magic Number", data[0]); + PrintAndLog(" %02X: version %d.%d supported by tag", data[1], (data[1] & 0xF0) >> 4, data[1] & 0x0f); + PrintAndLog(" %02X: Physical Memory Size of this tag: %d bytes", data[2], (data[2] + 1) * 8); + PrintAndLog(" %02X: %s / %s", data[3], + (data[3] & 0xF0) ? "(RFU)" : "Read access granted without any security", + (data[3] & 0x0F)==0 ? "Write access granted without any security" : (data[3] & 0x0F)==0x0F ? "No write access granted at all" : "(RFU)"); + return 0; +} + +static int ul_print_version(uint8_t *data){ + PrintAndLog("\n--- UL-EV1 / NTAG Version"); + PrintAndLog("Raw version bytes: %s", sprint_hex(data, 8) ); + PrintAndLog(" Vendor ID : 0x%02X, Manufacturer: %s", data[1], getTagInfo(data[1])); + PrintAndLog(" Product type : %s" , getProductTypeStr(data[2])); + PrintAndLog(" Product subtype : 0x%02X %s" , data[3], (data[3]==1) ?"17 pF":"50pF"); + PrintAndLog(" Major version : 0x%02X" , data[4]); + PrintAndLog(" Minor version : 0x%02X" , data[5]); + PrintAndLog(" Size : %s", getUlev1CardSizeStr(data[6])); + PrintAndLog(" Protocol type : 0x%02X" , data[7]); + return 0; +} + +static int ul_print_type(uint16_t tagtype){ + if ( tagtype & UL ) + PrintAndLog(" TYPE : MIFARE Ultralight (MF0ICU1) %s", (tagtype & MAGIC)?"":""); + else if ( tagtype & UL_C) + PrintAndLog(" TYPE : MIFARE Ultralight C (MF0ULC) %s [%x]", (tagtype & MAGIC)?"":"", tagtype ); + else if ( tagtype & UL_EV1_48) + PrintAndLog(" TYPE : MIFARE Ultralight EV1 48bytes (MF0UL1101)"); + else if ( tagtype & UL_EV1_128) + PrintAndLog(" TYPE : MIFARE Ultralight EV1 128bytes (MF0UL2101)"); + else if ( tagtype & NTAG_213 ) + PrintAndLog(" TYPE : MIFARE NTAG 213 144bytes (NT2H1311G0DU)"); + else if ( tagtype & NTAG_215 ) + PrintAndLog(" TYPE : MIFARE NTAG 215 504bytes (NT2H1511G0DU)"); + else if ( tagtype & NTAG_216 ) + PrintAndLog(" TYPE : MIFARE NTAG 216 888bytes (NT2H1611G0DU)"); + else + PrintAndLog(" TYPE : Unknown %04x",tagtype); + return 0; +} + +static int ulc_print_3deskey( uint8_t *data){ + PrintAndLog(" deskey1 [44/0x2C]: %s", sprint_hex(data ,4)); + PrintAndLog(" deskey1 [45/0x2D]: %s", sprint_hex(data+4 ,4)); + PrintAndLog(" deskey2 [46/0x2E]: %s", sprint_hex(data+8 ,4)); + PrintAndLog(" deskey2 [47/0x2F]: %s", sprint_hex(data+12,4)); + PrintAndLog(" 3des key : %s", sprint_hex(SwapEndian64(data, 16), 16)); + return 0; +} + +static int ulc_print_configuration( uint8_t *data){ + + PrintAndLog("--- UL-C Configuration"); + PrintAndLog(" Higher Lockbits [40/0x28]: %s %s", sprint_hex(data, 4), printBits(2, data)); + PrintAndLog(" Counter [41/0x29]: %s %s", sprint_hex(data+4, 4), printBits(2, data+4)); + + bool validAuth = (data[8] >= 0x03 && data[8] <= 0x30); + if ( validAuth ) + PrintAndLog(" Auth0 [42/0x2A]: %s - Pages above %d needs authentication", sprint_hex(data+8, 4), data[8] ); + else{ + if ( data[8] == 0){ + PrintAndLog(" Auth0 [42/0x2A]: %s - default", sprint_hex(data+8, 4) ); + } else { + PrintAndLog(" Auth0 [42/0x2A]: %s - auth byte is out-of-range", sprint_hex(data+8, 4) ); + } + } + PrintAndLog(" Auth1 [43/0x2B]: %s - %s", + sprint_hex(data+12, 4), + (data[12] & 1) ? "write access restricted": "read and write access restricted" + ); + return 0; +} + +static int ulev1_print_configuration( uint8_t *data){ + + PrintAndLog("\n--- UL-EV1 Configuration"); + + bool strg_mod_en = (data[0] & 2); + uint8_t authlim = (data[4] & 0x07); + bool cfglck = (data[4] & 0x40); + bool prot = (data[4] & 0x80); + uint8_t vctid = data[5]; + + PrintAndLog(" cfg0 [16/0x10]: %s", sprint_hex(data, 4)); + PrintAndLog(" - pages above %d needs authentication",data[3]); + PrintAndLog(" - strong modulation mode %s", (strg_mod_en) ? "enabled":"disabled"); + PrintAndLog(" cfg1 [17/0x11]: %s", sprint_hex(data+4, 4) ); + if ( authlim == 0) + PrintAndLog(" - Max number of password attempts is unlimited"); + else + PrintAndLog(" - Max number of password attempts is %d", authlim); + PrintAndLog(" - user configuration %s", cfglck ? "permanently locked":"writeable"); + PrintAndLog(" - %s access is protected with password", prot ? "read and write":"write"); + PrintAndLog(" 0x%02X - Virtual Card Type Identifier is %s default", vctid, (vctid==0x05)? "":"not"); + PrintAndLog(" PWD [18/0x12]: %s", sprint_hex(data+8, 4)); + PrintAndLog(" PACK [19/0x13]: %s", sprint_hex(data+12, 4)); + return 0; +} + +static int ulev1_print_counters(){ + PrintAndLog("--- UL-EV1 Counters"); + uint8_t counter[3] = {0,0,0}; + for ( uint8_t i = 0; i<3; ++i) { + ulev1_readCounter(i,counter, sizeof(counter) ); + PrintAndLog("Counter [%d] : %s", i, sprint_hex(counter,3)); + } + return 0; +} + +uint16_t GetHF14AMfU_Type(void){ TagTypeUL_t tagtype = UNKNOWN; iso14a_card_select_t card; + uint8_t version[10] = {0x00}; + uint8_t nonce1[11] = {0x00}; + uint8_t nonce2[11] = {0x00}; + int status = 0; + int len; - // select and run 0x60 (GET_VERSION - EV1 command) - UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_CONNECT | ISO14A_RAW | ISO14A_APPEND_CRC, 1, 0}}; - c.d.asBytes[0] = 0x60; - SendCommand(&c); - UsbCommand resp; - WaitForResponse(CMD_ACK, &resp); - - if ( resp.arg[0] == 0 ) return UL_ERROR; - - memcpy(&card, (iso14a_card_select_t *)resp.d.asBytes, sizeof(iso14a_card_select_t)); + status = ul_select(&card); + if ( status < 1 ){ + PrintAndLog("Error: couldn't select"); + ul_switch_off_field(); + return UL_ERROR; + } // Ultralight - ATQA / SAK - if ( card.atqa[1] != 0x00 && card.atqa[0] != 0x44 && card.sak != 0x00 ) return UL_ERROR; - - // EV1 GetVersion - if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { - - uint8_t version[10] = {0,0,0,0,0,0,0,0,0,0}; - memcpy(version, resp.d.asBytes, resp.arg[0] < sizeof(version) ? resp.arg[0] : sizeof(version)); - uint8_t len = resp.arg[0] & 0xff; - - if ( len == 0x0A && version[6] == 0x0B ) - tagtype = UL_EV1_48; - else if ( len == 0x0A && version[6] != 0x0B ) - tagtype = UL_EV1_128; - else if ( len == 0x01 ) - tagtype = UL_C; - else if ( len == 0x00 ) - tagtype = UL; + if ( card.atqa[1] != 0x00 && card.atqa[0] != 0x44 && card.sak != 0x00 ) { + ul_switch_off_field(); + return UL_ERROR; } - - // Magic UL-C, mine have a static nonce response to 0x1A command. - uint8_t nonce1[8] = {0,0,0,0,0,0,0,0}; - uint8_t nonce2[8] = {0,0,0,0,0,0,0,0}; - uint8_t status = requestAuthentication(nonce1); - if ( status ) { - requestAuthentication(nonce2); - if ( !memcmp(nonce1, nonce2, 8) ){ - tagtype = UL_C_MAGIC; + + len = ulev1_getVersion(version, sizeof(version)); + ul_switch_off_field(); + + switch (len) { + case -1: + tagtype = (UL | UL_C); + break; + case 0x0A: { + + if ( version[2] == 0x03 && version[6] == 0x0B ) + tagtype = UL_EV1_48; + else if ( version[2] == 0x03 && version[6] != 0x0B ) + tagtype = UL_EV1_128; + else if ( version[2] == 0x04 && version[6] == 0x0F ) + tagtype = NTAG_213; + else if ( version[2] == 0x04 && version[6] != 0x11 ) + tagtype = NTAG_215; + else if ( version[2] == 0x04 && version[6] == 0x13 ) + tagtype = NTAG_216; + else if ( version[2] == 0x04 ) + tagtype = NTAG; + + break; + } + case 0x01:{ + tagtype = UL_C; + break; + } + case 0x00: { + tagtype = UL; + break; + } + default :{ + tagtype = UNKNOWN; + break; } - } else { - // Magic Ultralight test here - TODO } + + if ((tagtype & ( UL_C | UL ))) { + // Magic UL-C, by observation, + // it seems to have a static nonce response to 0x1A command. + status = ul_select(&card); + status = ulc_requestAuthentication(0, nonce1, sizeof(nonce1)); + if ( status > 0 ) { + + status = ulc_requestAuthentication(0, nonce2, sizeof(nonce2)); + + tagtype =( !memcmp(nonce1, nonce2, 11) ) ? UL_C_MAGIC : UL_C; + + } else { + tagtype = UL; + } + ul_switch_off_field(); + } + + //PrintAndLog("ICE %d", tagtype); + //Magic Ultralight test here. It takes present UID, and tries to write it back. + if ( (tagtype & UL) ){ + // read 3des key or PWD, + // if response bytes == all zeros its a NORMAL tag. + //return UL_MAGIC; + } + return tagtype; } int CmdHF14AMfUInfo(const char *Cmd){ - uint8_t datatemp[7] = {0x00}; - uint8_t isOK = 0; + uint8_t data[16] = {0x00}; + iso14a_card_select_t card; uint8_t *key; + int status; + + PrintAndLog("\n--- Tag Information ---------"); + PrintAndLog("-------------------------------------------------------------"); TagTypeUL_t tagtype = GetHF14AMfU_Type(); if (tagtype == UL_ERROR) return -1; - - PrintAndLog("\n-- Tag Information ---------"); - PrintAndLog("-------------------------------------------------------------"); - if ( tagtype & UL ) - PrintAndLog(" TYPE : MIFARE Ultralight %s", (tagtype & MAGIC)?"(magic)":""); - else if ( tagtype & UL_C) - PrintAndLog(" TYPE : MIFARE Ultralight C %s", (tagtype & MAGIC)?"(magic)":"" ); - else if ( tagtype & UL_EV1_48) - PrintAndLog(" TYPE : MIFARE Ultralight EV1 48 bytes"); - else if ( tagtype & UL_EV1_128) - PrintAndLog(" TYPE : MIFARE Ultralight EV1 128 bytes"); - else - PrintAndLog(" TYPE : Unknown %x",tagtype); + ul_print_type(tagtype); - // read pages 0,1,2,4 - UsbCommand c = {CMD_MIFAREU_READCARD, {0, 4}}; - SendCommand(&c); - UsbCommand resp; - - if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { - isOK = resp.arg[0] & 0xff; - memcpy(data, resp.d.asBytes, sizeof(data)); - - if (!isOK) { - PrintAndLog("Error reading from tag"); - return -1; - } - } else { - PrintAndLog("Command execute timed out"); - return -1; + status = ul_select(&card); + if ( status < 1 ){ + PrintAndLog("Error: couldn't select"); + ul_switch_off_field(); + return status; } - // UID - memcpy( datatemp, data, 3); - memcpy( datatemp+3, data+4, 4); - - PrintAndLog(" UID : %s ", sprint_hex(datatemp, 7)); - PrintAndLog(" UID[0] : (Manufacturer Byte) = %02x, Manufacturer: %s", datatemp[0], getTagInfo(datatemp[0]) ); - - // BBC - // CT (cascade tag byte) 0x88 xor SN0 xor SN1 xor SN2 - int crc0 = 0x88 ^ data[0] ^ data[1] ^data[2]; - if ( data[3] == crc0 ) - PrintAndLog(" BCC0 : %02x - Ok", data[3]); - else - PrintAndLog(" BCC0 : %02x - crc should be %02x", data[3], crc0); - - int crc1 = data[4] ^ data[5] ^ data[6] ^data[7]; - if ( data[8] == crc1 ) - PrintAndLog(" BCC1 : %02x - Ok", data[8]); - else - PrintAndLog(" BCC1 : %02x - crc should be %02x", data[8], crc1 ); - - PrintAndLog(" Internal : %s ", sprint_hex(data + 9, 1)); - - memcpy(datatemp, data+10, 2); - PrintAndLog(" Lock : %s - %s", sprint_hex(datatemp, 2),printBits( 2, &datatemp) ); - PrintAndLog("OneTimePad : %s ", sprint_hex(data + 3*4, 4)); - PrintAndLog(""); - - - PrintAndLog("--- "); + // read pages 0,1,2,4 (should read 4pages) + status = ul_read(0, data, sizeof(data)); + if ( status == -1 ){ + PrintAndLog("Error: tag didn't answer to READ A"); + ul_switch_off_field(); + return status; + } + + ul_print_default(data); + if ((tagtype & UL_C)){ - - PrintAndLog("Trying some default 3des keys"); - - for (uint8_t i = 0; i < 5; ++i ){ - key = default_3des_keys[i]; - if (try3DesAuthentication(key)){ - PrintAndLog("Found default 3des key: %s", sprint_hex(key,16)); - return 0; + + // read pages 0x28, 0x29, 0x2A, 0x2B + uint8_t ulc_conf[16] = {0x00}; + status = ul_read(0x28, ulc_conf, sizeof(ulc_conf)); + if ( status == -1 ){ + PrintAndLog("Error: tag didn't answer to READ - possibly locked"); + //ul_switch_off_field(); + //return status; + + //tag may be locked + } else ulc_print_configuration(ulc_conf); + + if ((tagtype & MAGIC)){ + + uint8_t ulc_deskey[16] = {0x00}; + status = ul_read(0x2C, ulc_deskey, sizeof(ulc_deskey)); + if ( status == -1 ){ + PrintAndLog("Error: tag didn't answer to READ B"); + ul_switch_off_field(); + return status; } - } + + ulc_print_3deskey(ulc_deskey); + + } + else { + PrintAndLog("Trying some default 3des keys"); + ul_switch_off_field(); + for (uint8_t i = 0; i < 7; ++i ){ + key = default_3des_keys[i]; + if (try3DesAuthentication(key) == 1){ + PrintAndLog("Found default 3des key: %s", sprint_hex(key,16)); + return 0; + } + } + } } - else if ((tagtype & (UL_EV1_48 | UL_EV1_128))) { + + if ((tagtype & (UL_EV1_48 | UL_EV1_128))) { + + ulev1_print_counters(); + + uint8_t startconfigblock = (tagtype & UL_EV1_48) ? 0x10 : 0x24; + uint8_t ulev1_conf[16] = {0x00}; + status = ul_read(startconfigblock, ulev1_conf, sizeof(ulev1_conf)); + if ( status == -1 ){ + PrintAndLog("Error: tag didn't answer to READ C"); + ul_switch_off_field(); + return status; + } + + ulev1_print_configuration(ulev1_conf); + } + + if ((tagtype & (UL_EV1_48 | UL_EV1_128 | NTAG_213 | NTAG_215 | NTAG_216))) { + + uint8_t version[10] = {0x00}; + status = ulev1_getVersion(version, sizeof(version)); + if ( status == -1 ){ + PrintAndLog("Error: tag didn't answer to GETVERSION"); + ul_switch_off_field(); + return status; + } + ul_print_version(version); + //********** TODO ******************************** // --problem, there is a failed pwd tries counter in UL-EV1 - //PrintAndLog("Trying some known EV1 passwords."); + PrintAndLog("\nTrying some known EV1/NTAG passwords."); + + uint8_t password[4] ={0xff,0xff,0xff,0xff}; + uint8_t pack[4] = {0,0,0,0}; + status = ulev1_requestAuthentication(password, pack, sizeof(pack)); + if ( status == -1 ){ + PrintAndLog("Error: tag didn't answer to AUTHENTICATE"); + ul_switch_off_field(); + return status; + } + PrintAndLog("Found default password: %s",sprint_hex(password, sizeof(password))); + PrintAndLog("Got PACK : %s", sprint_hex(pack,sizeof(pack))); } + + if ((tagtype & (NTAG_213 | NTAG_215 | NTAG_216))){ + + PrintAndLog("\n--- NTAG NDEF Message"); + uint8_t cc[16] = {0x00}; + status = ul_read(2, cc, sizeof(cc)); + if ( status == -1 ){ + PrintAndLog("Error: tag didn't answer to READ D"); + ul_switch_off_field(); + return status; + } + ul_print_CC(cc); + } + + ul_switch_off_field(); return 0; } @@ -326,6 +692,11 @@ int usage_hf_mfu_dump(void) PrintAndLog("and saves binary dump into the file `filename.bin` or `cardUID.bin`"); PrintAndLog("It autodetects card type.\n"); PrintAndLog("Usage: hf mfu dump k n "); + PrintAndLog(" Options : "); + PrintAndLog(" k : Enter key for authentication"); + PrintAndLog(" n : Enter filename w/o .bin to save the dump as"); + PrintAndLog(" s : Swap entered key's endianness for auth"); + PrintAndLog(""); PrintAndLog(" sample : hf mfu dump"); PrintAndLog(" : hf mfu dump n myfile"); return 0; @@ -354,9 +725,11 @@ int CmdHF14AMfUDump(const char *Cmd){ bool tmplockbit = false; uint8_t dataLen=0; uint8_t cmdp =0; - uint8_t *key= NULL; + uint8_t key[16] = {0x00}; + uint8_t *keyPtr = key; size_t fileNlen = 0; - bool errors = FALSE; + bool errors = false; + bool swapEndian = false; while(param_getchar(Cmd, cmdp) != 0x00) { @@ -371,8 +744,7 @@ int CmdHF14AMfUDump(const char *Cmd){ if (dataLen) { errors = true; } else { - key = SwapEndian64(data, 16); - PrintAndLog("3des key: %s",sprint_hex(key, 16)); + memcpy(key, data, 16); } cmdp += 2; hasPwd = true; @@ -384,6 +756,9 @@ int CmdHF14AMfUDump(const char *Cmd){ if (fileNlen > FILE_PATH_SIZE-5) fileNlen = FILE_PATH_SIZE-5; cmdp += 2; break; + case 's': + swapEndian = true; + cmdp++; default: PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp)); errors = true; @@ -393,10 +768,10 @@ int CmdHF14AMfUDump(const char *Cmd){ } //Validations - if(errors) - { - return usage_hf_mfu_dump(); - } + if(errors) return usage_hf_mfu_dump(); + + if (swapEndian) + keyPtr = SwapEndian64(data, 16); TagTypeUL_t tagtype = GetHF14AMfU_Type(); if (tagtype == UL_ERROR) return -1; @@ -421,27 +796,24 @@ int CmdHF14AMfUDump(const char *Cmd){ PrintAndLog("Dumping unknown Ultralight, using default values."); } - for (uint8_t i = 0; i "); + PrintAndLog("Usage: hf mfu crdbl "); PrintAndLog(""); PrintAndLog("sample: hf mfu crdbl 0"); PrintAndLog(" hf mfu crdbl 0 00112233445566778899AABBCCDDEEFF"); return 0; - } - + } + blockNo = param_get8(Cmd, 0); if (blockNo < 0) { PrintAndLog("Wrong block number"); return 1; } - + if (blockNo > MAX_ULC_BLOCKS ){ PrintAndLog("Error: Maximum number of blocks is 47 for Ultralight-C"); return 1; @@ -796,13 +1168,13 @@ int CmdHF14AMfUCRdBl(const char *Cmd) hasPwd = TRUE; } } - uint8_t *key2 = SwapEndian64(key, 16); + //uint8_t *key2 = SwapEndian64(key, 16); //Read Block UsbCommand c = {CMD_MIFAREU_READBL, {blockNo}}; if ( hasPwd ) { c.arg[1] = 1; - memcpy(c.d.asBytes,key2,16); + memcpy(c.d.asBytes,key,16); } SendCommand(&c); diff --git a/client/cmdhfmfu.h b/client/cmdhfmfu.h index 64f32a49f..8e96775cd 100644 --- a/client/cmdhfmfu.h +++ b/client/cmdhfmfu.h @@ -19,7 +19,7 @@ void rol (uint8_t *data, const size_t len); uint8_t requestAuthentication( uint8_t *nonce); int try3DesAuthentication( uint8_t *key); -uint8_t GetHF14AMfU_Type(void); +uint16_t GetHF14AMfU_Type(void); int usage_hf_mfu_dump(void); From abab60ae216172735f511e116eb3dc87004d168d Mon Sep 17 00:00:00 2001 From: marshmellow42 Date: Wed, 6 May 2015 09:27:03 -0400 Subject: [PATCH 12/49] MFU info adjustments --- client/cmdhfmfu.c | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/client/cmdhfmfu.c b/client/cmdhfmfu.c index 396eb239e..607cad96d 100644 --- a/client/cmdhfmfu.c +++ b/client/cmdhfmfu.c @@ -107,12 +107,11 @@ static int ul_send_cmd_raw( uint8_t *cmd, uint8_t cmdlen, uint8_t *response, uin SendCommand(&c); UsbCommand resp; if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) return -1; + if (resp.arg[0] < 1) return -1; uint16_t resplen = (resp.arg[0] < responseLength) ? resp.arg[0] : responseLength; - if (resp.arg[0] > 0) { - memcpy(response, resp.d.asBytes, resplen); - return resplen; - } else return -1; + memcpy(response, resp.d.asBytes, resplen); + return resplen; } /* static int ul_send_cmd_raw_crc( uint8_t *cmd, uint8_t cmdlen, uint8_t *response, uint16_t responseLength, bool append_crc ) { @@ -370,9 +369,9 @@ uint16_t GetHF14AMfU_Type(void){ ul_switch_off_field(); return UL_ERROR; } - // Ultralight - ATQA / SAK - if ( card.atqa[1] != 0x00 && card.atqa[0] != 0x44 && card.sak != 0x00 ) { + if ( card.atqa[1] != 0x00 || card.atqa[0] != 0x44 || card.sak != 0x00 ) { + PrintAndLog ("Tag is not UL or NTAG, ATQA1: %x, ATQA0: %x, SAK: %d", card.atqa[1],card.atqa[0],card.sak); ul_switch_off_field(); return UL_ERROR; } @@ -419,13 +418,15 @@ uint16_t GetHF14AMfU_Type(void){ // Magic UL-C, by observation, // it seems to have a static nonce response to 0x1A command. status = ul_select(&card); + if ( status < 1 ){ + PrintAndLog("Error: couldn't select B"); + ul_switch_off_field(); + return UL_ERROR; + } status = ulc_requestAuthentication(0, nonce1, sizeof(nonce1)); if ( status > 0 ) { - status = ulc_requestAuthentication(0, nonce2, sizeof(nonce2)); - tagtype =( !memcmp(nonce1, nonce2, 11) ) ? UL_C_MAGIC : UL_C; - } else { tagtype = UL; } @@ -451,12 +452,12 @@ int CmdHF14AMfUInfo(const char *Cmd){ uint8_t *key; int status; - PrintAndLog("\n--- Tag Information ---------"); - PrintAndLog("-------------------------------------------------------------"); TagTypeUL_t tagtype = GetHF14AMfU_Type(); if (tagtype == UL_ERROR) return -1; + PrintAndLog("\n--- Tag Information ---------"); + PrintAndLog("-------------------------------------------------------------"); ul_print_type(tagtype); status = ul_select(&card); @@ -483,11 +484,11 @@ int CmdHF14AMfUInfo(const char *Cmd){ status = ul_read(0x28, ulc_conf, sizeof(ulc_conf)); if ( status == -1 ){ PrintAndLog("Error: tag didn't answer to READ - possibly locked"); - //ul_switch_off_field(); - //return status; + ul_switch_off_field(); + return status; + } - //tag may be locked - } else ulc_print_configuration(ulc_conf); + ulc_print_configuration(ulc_conf); if ((tagtype & MAGIC)){ From 45673b94571cd29b00ef5e76b3bee395c2b9480f Mon Sep 17 00:00:00 2001 From: marshmellow42 Date: Wed, 6 May 2015 10:16:31 -0400 Subject: [PATCH 13/49] MFU adjustment to allow 0 len returns from raw cmds --- client/cmdhfmfu.c | 1 - 1 file changed, 1 deletion(-) diff --git a/client/cmdhfmfu.c b/client/cmdhfmfu.c index 607cad96d..a94d8767d 100644 --- a/client/cmdhfmfu.c +++ b/client/cmdhfmfu.c @@ -107,7 +107,6 @@ static int ul_send_cmd_raw( uint8_t *cmd, uint8_t cmdlen, uint8_t *response, uin SendCommand(&c); UsbCommand resp; if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) return -1; - if (resp.arg[0] < 1) return -1; uint16_t resplen = (resp.arg[0] < responseLength) ? resp.arg[0] : responseLength; memcpy(response, resp.d.asBytes, resplen); From 372a82570b3a30ba3714bee9fbafbfe757439dc0 Mon Sep 17 00:00:00 2001 From: marshmellow42 Date: Wed, 6 May 2015 10:17:39 -0400 Subject: [PATCH 14/49] MFU adj to allow 0 len returns on raw cmds --- client/cmdhfmfu.c | 1 + 1 file changed, 1 insertion(+) diff --git a/client/cmdhfmfu.c b/client/cmdhfmfu.c index a94d8767d..e24e3fad1 100644 --- a/client/cmdhfmfu.c +++ b/client/cmdhfmfu.c @@ -107,6 +107,7 @@ static int ul_send_cmd_raw( uint8_t *cmd, uint8_t cmdlen, uint8_t *response, uin SendCommand(&c); UsbCommand resp; if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) return -1; + if (!resp.arg[0] && responseLength) return -1; uint16_t resplen = (resp.arg[0] < responseLength) ? resp.arg[0] : responseLength; memcpy(response, resp.d.asBytes, resplen); From c585a5cf0b96d30119e1adb45c69e579e475d046 Mon Sep 17 00:00:00 2001 From: marshmellow42 Date: Wed, 6 May 2015 22:15:41 -0400 Subject: [PATCH 15/49] further MFU info updates (mainly icemans) --- client/cmdhf.c | 2 +- client/cmdhfmfu.c | 241 ++++++++++++++++++++++++++++++---------------- client/util.c | 2 + 3 files changed, 160 insertions(+), 85 deletions(-) diff --git a/client/cmdhf.c b/client/cmdhf.c index b2950ed08..020ea94cb 100644 --- a/client/cmdhf.c +++ b/client/cmdhf.c @@ -93,7 +93,7 @@ void annotateIso14443a(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize) snprintf(exp,size,"?"); break; } - case MIFARE_ULEV1_WRITE:{ + case MIFARE_ULC_WRITE:{ if ( cmd[1] < 0x21 ) snprintf(exp,size,"WRITEBLOCK(%d)",cmd[1]); else diff --git a/client/cmdhfmfu.c b/client/cmdhfmfu.c index e24e3fad1..f8d38919b 100644 --- a/client/cmdhfmfu.c +++ b/client/cmdhfmfu.c @@ -49,6 +49,12 @@ uint8_t default_3des_keys[7][16] = { { 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xAA,0xBB,0xCC,0xDD,0xEE,0xFF } // 11 22 33 }; +uint8_t default_pwd_pack[3][4] = { + {0xFF,0xFF,0xFF,0xFF}, // PACK 0x00,0x00 -- factory default + {0x4A,0xF8,0x4B,0x19}, // PACK 0xE5,0xBE -- italian bus (sniffed) + {0x05,0x22,0xE6,0xB4} // PACK 0x80,0x80 -- Amiiboo (sniffed) +}; + static int CmdHelp(const char *Cmd); char* getProductTypeStr( uint8_t id){ @@ -123,12 +129,11 @@ static int ul_send_cmd_raw_crc( uint8_t *cmd, uint8_t cmdlen, uint8_t *response, SendCommand(&c); UsbCommand resp; if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) return -1; + if (!resp.arg[0] && responseLength) return -1; uint16_t resplen = (resp.arg[0] < responseLength) ? resp.arg[0] : responseLength; - if (resp.arg[0] > 0) { - memcpy(response, resp.d.asBytes, resplen); - return resplen; - } else return -1; + memcpy(response, resp.d.asBytes, resplen); + return resplen; } */ static int ul_select( iso14a_card_select_t *card ){ @@ -153,6 +158,26 @@ static int ul_read( uint8_t page, uint8_t *response, uint16_t responseLength ){ return len; } +static int ul_comp_write( uint8_t page, uint8_t *data, uint8_t datalen ){ + + uint8_t cmd[18]; + memset(cmd, 0x00, sizeof(cmd)); + datalen = ( datalen > 16) ? 16 : datalen; + + cmd[0] = ISO14443A_CMD_WRITEBLOCK; + cmd[1] = page; + memcpy(cmd+2, data, datalen); + + uint8_t response[1] = {0xff}; + int len = ul_send_cmd_raw(cmd, 2+datalen, response, sizeof(response)); + if ( len == -1 ) + ul_switch_off_field(); + // ACK + if ( response[0] == 0x0a ) return 0; + // NACK + return -1; +} + static int ulc_requestAuthentication( uint8_t blockNo, uint8_t *nonce, uint16_t nonceLength ){ uint8_t cmd[] = {MIFARE_ULC_AUTH_1, blockNo}; @@ -200,6 +225,15 @@ static int ulev1_readCounter( uint8_t counter, uint8_t *response, uint16_t respo return len; } +static int ulev1_readSignature( uint8_t *response, uint16_t responseLength ){ + + uint8_t cmd[] = {MIFARE_ULEV1_READSIG, 0x00}; + int len = ul_send_cmd_raw(cmd, sizeof(cmd), response, responseLength); + if (len == -1) + ul_switch_off_field(); + return len; +} + static int ul_print_default( uint8_t *data){ uint8_t uid[7]; @@ -236,7 +270,7 @@ static int ul_print_default( uint8_t *data){ return 0; } -static int ul_print_CC(uint8_t *data) { +static int ntag_print_CC(uint8_t *data) { if(data[0] != 0xe1) { PrintAndLog("no NDEF message"); return -1; // no NDEF message @@ -245,16 +279,23 @@ static int ul_print_CC(uint8_t *data) { PrintAndLog("Capability Container: %s", sprint_hex(data,4) ); PrintAndLog(" %02X: NDEF Magic Number", data[0]); PrintAndLog(" %02X: version %d.%d supported by tag", data[1], (data[1] & 0xF0) >> 4, data[1] & 0x0f); - PrintAndLog(" %02X: Physical Memory Size of this tag: %d bytes", data[2], (data[2] + 1) * 8); + PrintAndLog(" %02X: Physical Memory Size: %d bytes", data[2], (data[2] + 1) * 8); + if ( data[2] == 0x12 ) + PrintAndLog(" %02X: NDEF Memory Size: &d bytes", data[2], 144); + else if ( data[2] == 0x3e ) + PrintAndLog(" %02X: NDEF Memory Size: &d bytes", data[2], 496); + else if ( data[2] == 0x6d ) + PrintAndLog(" %02X: NDEF Memory Size: &d bytes", data[2], 872); + PrintAndLog(" %02X: %s / %s", data[3], (data[3] & 0xF0) ? "(RFU)" : "Read access granted without any security", (data[3] & 0x0F)==0 ? "Write access granted without any security" : (data[3] & 0x0F)==0x0F ? "No write access granted at all" : "(RFU)"); - return 0; + return 0; } -static int ul_print_version(uint8_t *data){ +static int ulev1_print_version(uint8_t *data){ PrintAndLog("\n--- UL-EV1 / NTAG Version"); - PrintAndLog("Raw version bytes: %s", sprint_hex(data, 8) ); + PrintAndLog(" Raw bytes : %s", sprint_hex(data, 8) ); PrintAndLog(" Vendor ID : 0x%02X, Manufacturer: %s", data[1], getTagInfo(data[1])); PrintAndLog(" Product type : %s" , getProductTypeStr(data[2])); PrintAndLog(" Product subtype : 0x%02X %s" , data[3], (data[3]==1) ?"17 pF":"50pF"); @@ -286,10 +327,10 @@ static int ul_print_type(uint16_t tagtype){ } static int ulc_print_3deskey( uint8_t *data){ - PrintAndLog(" deskey1 [44/0x2C]: %s", sprint_hex(data ,4)); - PrintAndLog(" deskey1 [45/0x2D]: %s", sprint_hex(data+4 ,4)); - PrintAndLog(" deskey2 [46/0x2E]: %s", sprint_hex(data+8 ,4)); - PrintAndLog(" deskey2 [47/0x2F]: %s", sprint_hex(data+12,4)); + PrintAndLog(" deskey1 [44/0x2C]: %s [%.4s]", sprint_hex(data ,4),data); + PrintAndLog(" deskey1 [45/0x2D]: %s [%.4s]", sprint_hex(data+4 ,4),data+4); + PrintAndLog(" deskey2 [46/0x2E]: %s [%.4s]", sprint_hex(data+8 ,4),data+8); + PrintAndLog(" deskey2 [47/0x2F]: %s [%.4s]", sprint_hex(data+12,4),data+12); PrintAndLog(" 3des key : %s", sprint_hex(SwapEndian64(data, 16), 16)); return 0; } @@ -353,13 +394,69 @@ static int ulev1_print_counters(){ return 0; } +static int ulev1_print_signature( uint8_t *data, uint8_t len){ + PrintAndLog("\n--- UL-EV1 Signature"); + PrintAndLog("IC signature public key name : NXP NTAG21x 2013"); + PrintAndLog("IC signature public key value : 04494e1a386d3d3cfe3dc10e5de68a499b1c202db5b132393e89ed19fe5be8bc61"); + PrintAndLog(" Elliptic curve parameters : secp128r1"); + PrintAndLog(" Tag ECC Signature : %s", sprint_hex(data, len)); + //to do: verify if signature is valid + //PrintAndLog("IC signature status: %s valid", (iseccvalid() )?"":"not"); + return 0; +} + +static int ulc_magic_test(){ + // Magic Ultralight test + // Magic UL-C, by observation, + // 1) it seems to have a static nonce response to 0x1A command. + // 2) the deskey bytes is not-zero:d out on as datasheet states. + // 3) UID - changeable, not only, but pages 0-1-2-3. + // 4) use the ul_magic_test ! magic tags answers specially! + int returnValue = UL_ERROR; + iso14a_card_select_t card; + uint8_t nonce1[11] = {0x00}; + uint8_t nonce2[11] = {0x00}; + int status = ul_select(&card); + if ( status < 1 ){ + PrintAndLog("Error: couldn't select ulc_magic_test"); + ul_switch_off_field(); + return UL_ERROR; + } + status = ulc_requestAuthentication(0, nonce1, sizeof(nonce1)); + if ( status > 0 ) { + status = ulc_requestAuthentication(0, nonce2, sizeof(nonce2)); + returnValue = ( !memcmp(nonce1, nonce2, 11) ) ? UL_C_MAGIC : UL_C; + } else { + returnValue = UL; + } + ul_switch_off_field(); + return returnValue; +} + +static int ul_magic_test(){ + + // Magic Ultralight tests + // 1) take present UID, and try to write it back. OBSOLETE + // 2) make a wrong length write to page0, and see if tag answers with ACK/NACK: + iso14a_card_select_t card; + int status = ul_select(&card); + if ( status < 1 ){ + PrintAndLog("Error: couldn't select ul_magic_test"); + ul_switch_off_field(); + return UL_ERROR; + } + status = ul_comp_write(0, NULL, 0); + ul_switch_off_field(); + if ( status == 0) + return UL_MAGIC; + return UL; +} + uint16_t GetHF14AMfU_Type(void){ TagTypeUL_t tagtype = UNKNOWN; iso14a_card_select_t card; uint8_t version[10] = {0x00}; - uint8_t nonce1[11] = {0x00}; - uint8_t nonce2[11] = {0x00}; int status = 0; int len; @@ -380,9 +477,6 @@ uint16_t GetHF14AMfU_Type(void){ ul_switch_off_field(); switch (len) { - case -1: - tagtype = (UL | UL_C); - break; case 0x0A: { if ( version[2] == 0x03 && version[6] == 0x0B ) @@ -400,59 +494,26 @@ uint16_t GetHF14AMfU_Type(void){ break; } - case 0x01:{ - tagtype = UL_C; - break; - } - case 0x00: { - tagtype = UL; - break; - } - default :{ - tagtype = UNKNOWN; - break; - } + case 0x01: tagtype = UL_C; break; + case 0x00: tagtype = UL; break; + case -1 : tagtype = (UL | UL_C); break; + default : tagtype = UNKNOWN; break; } - if ((tagtype & ( UL_C | UL ))) { - // Magic UL-C, by observation, - // it seems to have a static nonce response to 0x1A command. - status = ul_select(&card); - if ( status < 1 ){ - PrintAndLog("Error: couldn't select B"); - ul_switch_off_field(); - return UL_ERROR; - } - status = ulc_requestAuthentication(0, nonce1, sizeof(nonce1)); - if ( status > 0 ) { - status = ulc_requestAuthentication(0, nonce2, sizeof(nonce2)); - tagtype =( !memcmp(nonce1, nonce2, 11) ) ? UL_C_MAGIC : UL_C; - } else { - tagtype = UL; - } - ul_switch_off_field(); - } - - //PrintAndLog("ICE %d", tagtype); - //Magic Ultralight test here. It takes present UID, and tries to write it back. - if ( (tagtype & UL) ){ - // read 3des key or PWD, - // if response bytes == all zeros its a NORMAL tag. - //return UL_MAGIC; - } + if ((tagtype & ( UL_C | UL ))) tagtype = ulc_magic_test(); + if ((tagtype & UL)) tagtype = ul_magic_test(); return tagtype; } int CmdHF14AMfUInfo(const char *Cmd){ - + uint8_t authlim = 0xff; uint8_t data[16] = {0x00}; iso14a_card_select_t card; uint8_t *key; int status; - TagTypeUL_t tagtype = GetHF14AMfU_Type(); if (tagtype == UL_ERROR) return -1; @@ -499,17 +560,16 @@ int CmdHF14AMfUInfo(const char *Cmd){ ul_switch_off_field(); return status; } - ulc_print_3deskey(ulc_deskey); - } - else { + } else { PrintAndLog("Trying some default 3des keys"); ul_switch_off_field(); for (uint8_t i = 0; i < 7; ++i ){ key = default_3des_keys[i]; if (try3DesAuthentication(key) == 1){ - PrintAndLog("Found default 3des key: %s", sprint_hex(key,16)); + PrintAndLog("Found default 3des key: "); //%s", sprint_hex(key,16)); + ulc_print_3deskey(SwapEndian64(key,16)); return 0; } } @@ -517,10 +577,8 @@ int CmdHF14AMfUInfo(const char *Cmd){ } if ((tagtype & (UL_EV1_48 | UL_EV1_128))) { - - ulev1_print_counters(); - - uint8_t startconfigblock = (tagtype & UL_EV1_48) ? 0x10 : 0x24; + + uint8_t startconfigblock = (tagtype & UL_EV1_48) ? 0x10 : 0x25; uint8_t ulev1_conf[16] = {0x00}; status = ul_read(startconfigblock, ulev1_conf, sizeof(ulev1_conf)); if ( status == -1 ){ @@ -528,8 +586,21 @@ int CmdHF14AMfUInfo(const char *Cmd){ ul_switch_off_field(); return status; } - + // save AUTHENTICATION LIMITS for later: + authlim = (ulev1_conf[4] & 0x07); + ulev1_print_configuration(ulev1_conf); + + uint8_t ulev1_signature[32] = {0x00}; + status = ulev1_readSignature( ulev1_signature, sizeof(ulev1_signature)); + if ( status == -1 ){ + PrintAndLog("Error: tag didn't answer to READ SIGNATURE"); + ul_switch_off_field(); + return status; + } + ulev1_print_signature( ulev1_signature, sizeof(ulev1_signature)); + + ulev1_print_counters(); } if ((tagtype & (UL_EV1_48 | UL_EV1_128 | NTAG_213 | NTAG_215 | NTAG_216))) { @@ -541,26 +612,28 @@ int CmdHF14AMfUInfo(const char *Cmd){ ul_switch_off_field(); return status; } - ul_print_version(version); + ulev1_print_version(version); - //********** TODO ******************************** - // --problem, there is a failed pwd tries counter in UL-EV1 - PrintAndLog("\nTrying some known EV1/NTAG passwords."); - - uint8_t password[4] ={0xff,0xff,0xff,0xff}; - uint8_t pack[4] = {0,0,0,0}; - status = ulev1_requestAuthentication(password, pack, sizeof(pack)); - if ( status == -1 ){ - PrintAndLog("Error: tag didn't answer to AUTHENTICATE"); + // AUTHLIMIT, (number of failed authentications) + // 0 = limitless. + // 1-7 = ... should we even try then? + if ( authlim == 0 ){ + PrintAndLog("\n--- Known EV1/NTAG passwords."); + + uint8_t pack[4] = {0,0,0,0}; + + for (uint8_t i = 0; i < 3; ++i ){ + key = default_pwd_pack[i]; + if ( ulev1_requestAuthentication(key, pack, sizeof(pack)) > -1 ){ + PrintAndLog("Found a default password: %s || Pack: %02X %02X",sprint_hex(key, 4), pack[0], pack[1]); + } + } ul_switch_off_field(); - return status; } - PrintAndLog("Found default password: %s",sprint_hex(password, sizeof(password))); - PrintAndLog("Got PACK : %s", sprint_hex(pack,sizeof(pack))); } - + if ((tagtype & (NTAG_213 | NTAG_215 | NTAG_216))){ - + PrintAndLog("\n--- NTAG NDEF Message"); uint8_t cc[16] = {0x00}; status = ul_read(2, cc, sizeof(cc)); @@ -569,9 +642,9 @@ int CmdHF14AMfUInfo(const char *Cmd){ ul_switch_off_field(); return status; } - ul_print_CC(cc); + ntag_print_CC(cc); } - + ul_switch_off_field(); return 0; } diff --git a/client/util.c b/client/util.c index 5bb98fd77..548234226 100644 --- a/client/util.c +++ b/client/util.c @@ -112,6 +112,7 @@ char * sprint_hex(const uint8_t * data, const size_t len) { int maxLen = ( len > 1024/3) ? 1024/3 : len; static char buf[1024]; + memset(buf, 0x00, 1024); char * tmp = buf; size_t i; @@ -125,6 +126,7 @@ char *sprint_bin_break(const uint8_t *data, const size_t len, const uint8_t brea int maxLen = ( len > 1024) ? 1024 : len; static char buf[1024]; + memset(buf, 0x00, 1024); char *tmp = buf; for (size_t i=0; i < maxLen; ++i){ From f805ac7a2b23e0508bd598c0afd438fb2cdb284d Mon Sep 17 00:00:00 2001 From: marshmellow42 Date: Fri, 8 May 2015 13:01:27 -0400 Subject: [PATCH 16/49] minor adjustments to mfu info --- client/cmdhfmfu.c | 33 ++++++++++++++------------------- 1 file changed, 14 insertions(+), 19 deletions(-) diff --git a/client/cmdhfmfu.c b/client/cmdhfmfu.c index f8d38919b..523f505c7 100644 --- a/client/cmdhfmfu.c +++ b/client/cmdhfmfu.c @@ -432,7 +432,7 @@ static int ulc_magic_test(){ ul_switch_off_field(); return returnValue; } - +/* static int ul_magic_test(){ // Magic Ultralight tests @@ -451,7 +451,7 @@ static int ul_magic_test(){ return UL_MAGIC; return UL; } - +*/ uint16_t GetHF14AMfU_Type(void){ TagTypeUL_t tagtype = UNKNOWN; @@ -474,7 +474,7 @@ uint16_t GetHF14AMfU_Type(void){ } len = ulev1_getVersion(version, sizeof(version)); - ul_switch_off_field(); + if (len > -1) ul_switch_off_field(); //if -1 it is already off switch (len) { case 0x0A: { @@ -496,12 +496,12 @@ uint16_t GetHF14AMfU_Type(void){ } case 0x01: tagtype = UL_C; break; case 0x00: tagtype = UL; break; - case -1 : tagtype = (UL | UL_C); break; + case -1 : tagtype = (UL | UL_C); break; //when does this happen? default : tagtype = UNKNOWN; break; } - if ((tagtype & ( UL_C | UL ))) tagtype = ulc_magic_test(); - if ((tagtype & UL)) tagtype = ul_magic_test(); + tagtype = (ul_magic_test() == UL_MAGIC) ? (tagtype | MAGIC) : tagtype; + //if ((tagtype & UL)) tagtype = ul_magic_test(); return tagtype; } @@ -531,7 +531,7 @@ int CmdHF14AMfUInfo(const char *Cmd){ // read pages 0,1,2,4 (should read 4pages) status = ul_read(0, data, sizeof(data)); if ( status == -1 ){ - PrintAndLog("Error: tag didn't answer to READ A"); + PrintAndLog("Error: tag didn't answer to READ"); ul_switch_off_field(); return status; } @@ -545,7 +545,6 @@ int CmdHF14AMfUInfo(const char *Cmd){ status = ul_read(0x28, ulc_conf, sizeof(ulc_conf)); if ( status == -1 ){ PrintAndLog("Error: tag didn't answer to READ - possibly locked"); - ul_switch_off_field(); return status; } @@ -556,8 +555,7 @@ int CmdHF14AMfUInfo(const char *Cmd){ uint8_t ulc_deskey[16] = {0x00}; status = ul_read(0x2C, ulc_deskey, sizeof(ulc_deskey)); if ( status == -1 ){ - PrintAndLog("Error: tag didn't answer to READ B"); - ul_switch_off_field(); + PrintAndLog("Error: tag didn't answer to READ magic"); return status; } ulc_print_3deskey(ulc_deskey); @@ -582,8 +580,7 @@ int CmdHF14AMfUInfo(const char *Cmd){ uint8_t ulev1_conf[16] = {0x00}; status = ul_read(startconfigblock, ulev1_conf, sizeof(ulev1_conf)); if ( status == -1 ){ - PrintAndLog("Error: tag didn't answer to READ C"); - ul_switch_off_field(); + PrintAndLog("Error: tag didn't answer to READ EV1"); return status; } // save AUTHENTICATION LIMITS for later: @@ -595,7 +592,6 @@ int CmdHF14AMfUInfo(const char *Cmd){ status = ulev1_readSignature( ulev1_signature, sizeof(ulev1_signature)); if ( status == -1 ){ PrintAndLog("Error: tag didn't answer to READ SIGNATURE"); - ul_switch_off_field(); return status; } ulev1_print_signature( ulev1_signature, sizeof(ulev1_signature)); @@ -609,7 +605,6 @@ int CmdHF14AMfUInfo(const char *Cmd){ status = ulev1_getVersion(version, sizeof(version)); if ( status == -1 ){ PrintAndLog("Error: tag didn't answer to GETVERSION"); - ul_switch_off_field(); return status; } ulev1_print_version(version); @@ -621,14 +616,15 @@ int CmdHF14AMfUInfo(const char *Cmd){ PrintAndLog("\n--- Known EV1/NTAG passwords."); uint8_t pack[4] = {0,0,0,0}; - + int len=0; //if len goes to -1 the connection will be turned off. for (uint8_t i = 0; i < 3; ++i ){ key = default_pwd_pack[i]; - if ( ulev1_requestAuthentication(key, pack, sizeof(pack)) > -1 ){ + if ( len > -1 ){ + len = ulev1_requestAuthentication(key, pack, sizeof(pack)); PrintAndLog("Found a default password: %s || Pack: %02X %02X",sprint_hex(key, 4), pack[0], pack[1]); } } - ul_switch_off_field(); + if (len > -1) ul_switch_off_field(); } } @@ -638,8 +634,7 @@ int CmdHF14AMfUInfo(const char *Cmd){ uint8_t cc[16] = {0x00}; status = ul_read(2, cc, sizeof(cc)); if ( status == -1 ){ - PrintAndLog("Error: tag didn't answer to READ D"); - ul_switch_off_field(); + PrintAndLog("Error: tag didn't answer to READ ntag"); return status; } ntag_print_CC(cc); From f04ef473110b2b44edd7a69327b324a4966f584d Mon Sep 17 00:00:00 2001 From: marshmellow42 Date: Mon, 11 May 2015 14:49:37 -0400 Subject: [PATCH 17/49] hf mfu info bug fixes --- client/cmdhfmfu.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/client/cmdhfmfu.c b/client/cmdhfmfu.c index 523f505c7..3080cdbba 100644 --- a/client/cmdhfmfu.c +++ b/client/cmdhfmfu.c @@ -177,7 +177,7 @@ static int ul_comp_write( uint8_t page, uint8_t *data, uint8_t datalen ){ // NACK return -1; } - +/* static int ulc_requestAuthentication( uint8_t blockNo, uint8_t *nonce, uint16_t nonceLength ){ uint8_t cmd[] = {MIFARE_ULC_AUTH_1, blockNo}; @@ -186,7 +186,7 @@ static int ulc_requestAuthentication( uint8_t blockNo, uint8_t *nonce, uint16_t ul_switch_off_field(); return len; } - +*/ static int ulev1_requestAuthentication( uint8_t *pwd, uint8_t *pack, uint16_t packLength ){ uint8_t cmd[] = {MIFARE_ULEV1_AUTH, pwd[0], pwd[1], pwd[2], pwd[3]}; @@ -281,11 +281,11 @@ static int ntag_print_CC(uint8_t *data) { PrintAndLog(" %02X: version %d.%d supported by tag", data[1], (data[1] & 0xF0) >> 4, data[1] & 0x0f); PrintAndLog(" %02X: Physical Memory Size: %d bytes", data[2], (data[2] + 1) * 8); if ( data[2] == 0x12 ) - PrintAndLog(" %02X: NDEF Memory Size: &d bytes", data[2], 144); + PrintAndLog(" %02X: NDEF Memory Size: %d bytes", data[2], 144); else if ( data[2] == 0x3e ) - PrintAndLog(" %02X: NDEF Memory Size: &d bytes", data[2], 496); + PrintAndLog(" %02X: NDEF Memory Size: %d bytes", data[2], 496); else if ( data[2] == 0x6d ) - PrintAndLog(" %02X: NDEF Memory Size: &d bytes", data[2], 872); + PrintAndLog(" %02X: NDEF Memory Size: %d bytes", data[2], 872); PrintAndLog(" %02X: %s / %s", data[3], (data[3] & 0xF0) ? "(RFU)" : "Read access granted without any security", @@ -404,7 +404,7 @@ static int ulev1_print_signature( uint8_t *data, uint8_t len){ //PrintAndLog("IC signature status: %s valid", (iseccvalid() )?"":"not"); return 0; } - +/* static int ulc_magic_test(){ // Magic Ultralight test // Magic UL-C, by observation, @@ -432,7 +432,7 @@ static int ulc_magic_test(){ ul_switch_off_field(); return returnValue; } -/* +*/ static int ul_magic_test(){ // Magic Ultralight tests @@ -451,7 +451,7 @@ static int ul_magic_test(){ return UL_MAGIC; return UL; } -*/ + uint16_t GetHF14AMfU_Type(void){ TagTypeUL_t tagtype = UNKNOWN; @@ -622,6 +622,7 @@ int CmdHF14AMfUInfo(const char *Cmd){ if ( len > -1 ){ len = ulev1_requestAuthentication(key, pack, sizeof(pack)); PrintAndLog("Found a default password: %s || Pack: %02X %02X",sprint_hex(key, 4), pack[0], pack[1]); + break; } } if (len > -1) ul_switch_off_field(); @@ -632,7 +633,7 @@ int CmdHF14AMfUInfo(const char *Cmd){ PrintAndLog("\n--- NTAG NDEF Message"); uint8_t cc[16] = {0x00}; - status = ul_read(2, cc, sizeof(cc)); + status = ul_read(3, cc, sizeof(cc)); if ( status == -1 ){ PrintAndLog("Error: tag didn't answer to READ ntag"); return status; From 345fb24aaa0ba6586c3ac2b4835eefdebcaf3314 Mon Sep 17 00:00:00 2001 From: marshmellow42 Date: Mon, 11 May 2015 15:56:12 -0400 Subject: [PATCH 18/49] hf mfu info - ICEMANS bug fixes. --- client/cmdhfmfu.c | 229 ++++++++++++++++++++++++++++------------------ 1 file changed, 142 insertions(+), 87 deletions(-) diff --git a/client/cmdhfmfu.c b/client/cmdhfmfu.c index 3080cdbba..ce3457896 100644 --- a/client/cmdhfmfu.c +++ b/client/cmdhfmfu.c @@ -24,22 +24,27 @@ #define MAX_NTAG_216 0xe6 typedef enum TAGTYPE_UL { - UNKNOWN = 0x0000, - UL = 0x0001, - UL_C = 0x0002, - UL_EV1_48 = 0x0004, - UL_EV1_128 = 0x0008, - NTAG = 0x0010, - NTAG_213 = 0x0020, - NTAG_215 = 0x0040, - NTAG_216 = 0x0080, - MAGIC = 0x0100, - UL_MAGIC = UL | MAGIC, - UL_C_MAGIC = UL_C | MAGIC, - UL_ERROR = 0xFFFF, + UNKNOWN = 0x0000, + UL = 0x0001, + UL_C = 0x0002, + UL_EV1_48 = 0x0004, + UL_EV1_128 = 0x0008, + NTAG = 0x0010, + NTAG_213 = 0x0020, + NTAG_215 = 0x0040, + NTAG_216 = 0x0080, + MY_D = 0x0100, + MY_D_NFC = 0x0200, + MY_D_MOVE = 0x0400, + MY_D_MOVE_NFC = 0x0800, + MAGIC = 0x1000, + UL_MAGIC = UL | MAGIC, + UL_C_MAGIC = UL_C | MAGIC, + UL_ERROR = 0xFFFF, } TagTypeUL_t; -uint8_t default_3des_keys[7][16] = { +#define KEYS_3DES_COUNT 7 +uint8_t default_3des_keys[KEYS_3DES_COUNT][16] = { { 0x42,0x52,0x45,0x41,0x4b,0x4d,0x45,0x49,0x46,0x59,0x4f,0x55,0x43,0x41,0x4e,0x21 },// 3des std key { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },// all zeroes { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f },// 0x00-0x0F @@ -49,10 +54,16 @@ uint8_t default_3des_keys[7][16] = { { 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xAA,0xBB,0xCC,0xDD,0xEE,0xFF } // 11 22 33 }; -uint8_t default_pwd_pack[3][4] = { +#define KEYS_PWD_COUNT 8 +uint8_t default_pwd_pack[KEYS_PWD_COUNT][4] = { {0xFF,0xFF,0xFF,0xFF}, // PACK 0x00,0x00 -- factory default {0x4A,0xF8,0x4B,0x19}, // PACK 0xE5,0xBE -- italian bus (sniffed) - {0x05,0x22,0xE6,0xB4} // PACK 0x80,0x80 -- Amiiboo (sniffed) + {0x33,0x6B,0xA1,0x19}, // PACK 0x9c,0x2d -- italian bus (sniffed) + {0xFF,0x90,0x6C,0xB2}, // PACK 0x12,0x9e -- italian bus (sniffed) + {0x05,0x22,0xE6,0xB4}, // PACK 0x80,0x80 -- Amiiboo (sniffed) pikachu-b UID: + {0x7E,0x22,0xE6,0xB4}, // PACK 0x80,0x80 -- AMiiboo (sniffed) + {0x02,0xE1,0xEE,0x36}, // PACK 0x80,0x80 -- AMiiboo (sniffed) sonic UID: 04d257 7ae33e8027 + {0x32,0x0C,0x16,0x17}, // PACK 0x80,0x80 -- AMiiboo (sniffed) }; static int CmdHelp(const char *Cmd); @@ -83,7 +94,7 @@ char* getProductTypeStr( uint8_t id){ */ char* getUlev1CardSizeStr( uint8_t fsize ){ - static char buf[30]; + static char buf[40]; char *retStr = buf; uint8_t usize = 1 << ((fsize >>1) + 1); @@ -91,9 +102,9 @@ char* getUlev1CardSizeStr( uint8_t fsize ){ // is LSB set? if ( fsize & 1 ) - sprintf(retStr, "0x%02X (%u - %u bytes)",fsize, usize, lsize); + sprintf(retStr, "%02X (%u <-> %u bytes)",fsize, usize, lsize); else - sprintf(retStr, "0x%02X (%u bytes)", fsize, lsize); + sprintf(retStr, "%02X (%u bytes)", fsize, lsize); return buf; } @@ -177,7 +188,7 @@ static int ul_comp_write( uint8_t page, uint8_t *data, uint8_t datalen ){ // NACK return -1; } -/* + static int ulc_requestAuthentication( uint8_t blockNo, uint8_t *nonce, uint16_t nonceLength ){ uint8_t cmd[] = {MIFARE_ULC_AUTH_1, blockNo}; @@ -186,7 +197,7 @@ static int ulc_requestAuthentication( uint8_t blockNo, uint8_t *nonce, uint16_t ul_switch_off_field(); return len; } -*/ + static int ulev1_requestAuthentication( uint8_t *pwd, uint8_t *pack, uint16_t packLength ){ uint8_t cmd[] = {MIFARE_ULEV1_AUTH, pwd[0], pwd[1], pwd[2], pwd[3]}; @@ -247,9 +258,15 @@ static int ul_print_default( uint8_t *data){ uid[6] = data[7]; PrintAndLog(" UID : %s ", sprint_hex(uid, 7)); - PrintAndLog(" UID[0] : (Manufacturer Byte) = %02x, Manufacturer: %s", uid[0], getTagInfo(uid[0]) ); - - // BBC + PrintAndLog(" UID[0] : %02x, Manufacturer: %s", uid[0], getTagInfo(uid[0]) ); + if ( uid[0] == 0x05 ) { + uint8_t chip = (data[8] & 0xC7); // 11000111 mask, bit 3,4,5 RFU + switch (chip){ + case 0xc2: PrintAndLog(" IC type : SLE 66R04P"); break; + case 0xc4: PrintAndLog(" IC type : SLE 66R16P"); break; + case 0xc6: PrintAndLog(" IC type : SLE 66R32P"); break; + } + } // CT (cascade tag byte) 0x88 xor SN0 xor SN1 xor SN2 int crc0 = 0x88 ^ data[0] ^ data[1] ^data[2]; if ( data[3] == crc0 ) @@ -266,11 +283,13 @@ static int ul_print_default( uint8_t *data){ PrintAndLog(" Internal : 0x%02X - %s default", data[9], (data[9]==0x48)?"":"not" ); PrintAndLog(" Lock : %s - %s", sprint_hex(data+10, 2),printBits( 2, data+10) ); PrintAndLog("OneTimePad : %s ", sprint_hex(data + 12, 4)); - PrintAndLog(""); return 0; } static int ntag_print_CC(uint8_t *data) { + + PrintAndLog("\n--- NTAG NDEF Message"); + if(data[0] != 0xe1) { PrintAndLog("no NDEF message"); return -1; // no NDEF message @@ -290,30 +309,17 @@ static int ntag_print_CC(uint8_t *data) { PrintAndLog(" %02X: %s / %s", data[3], (data[3] & 0xF0) ? "(RFU)" : "Read access granted without any security", (data[3] & 0x0F)==0 ? "Write access granted without any security" : (data[3] & 0x0F)==0x0F ? "No write access granted at all" : "(RFU)"); - return 0; -} - -static int ulev1_print_version(uint8_t *data){ - PrintAndLog("\n--- UL-EV1 / NTAG Version"); - PrintAndLog(" Raw bytes : %s", sprint_hex(data, 8) ); - PrintAndLog(" Vendor ID : 0x%02X, Manufacturer: %s", data[1], getTagInfo(data[1])); - PrintAndLog(" Product type : %s" , getProductTypeStr(data[2])); - PrintAndLog(" Product subtype : 0x%02X %s" , data[3], (data[3]==1) ?"17 pF":"50pF"); - PrintAndLog(" Major version : 0x%02X" , data[4]); - PrintAndLog(" Minor version : 0x%02X" , data[5]); - PrintAndLog(" Size : %s", getUlev1CardSizeStr(data[6])); - PrintAndLog(" Protocol type : 0x%02X" , data[7]); return 0; } static int ul_print_type(uint16_t tagtype){ if ( tagtype & UL ) - PrintAndLog(" TYPE : MIFARE Ultralight (MF0ICU1) %s", (tagtype & MAGIC)?"":""); + PrintAndLog(" TYPE : MIFARE Ultralight (MF0ICU1) %s [%x]", (tagtype & MAGIC)?"":"", tagtype); else if ( tagtype & UL_C) PrintAndLog(" TYPE : MIFARE Ultralight C (MF0ULC) %s [%x]", (tagtype & MAGIC)?"":"", tagtype ); else if ( tagtype & UL_EV1_48) PrintAndLog(" TYPE : MIFARE Ultralight EV1 48bytes (MF0UL1101)"); - else if ( tagtype & UL_EV1_128) + else if ( tagtype & UL_EV1_128) PrintAndLog(" TYPE : MIFARE Ultralight EV1 128bytes (MF0UL2101)"); else if ( tagtype & NTAG_213 ) PrintAndLog(" TYPE : MIFARE NTAG 213 144bytes (NT2H1311G0DU)"); @@ -321,6 +327,14 @@ static int ul_print_type(uint16_t tagtype){ PrintAndLog(" TYPE : MIFARE NTAG 215 504bytes (NT2H1511G0DU)"); else if ( tagtype & NTAG_216 ) PrintAndLog(" TYPE : MIFARE NTAG 216 888bytes (NT2H1611G0DU)"); + else if ( tagtype & MY_D ) + PrintAndLog(" TYPE : INFINEON my-d\x99"); + else if ( tagtype & MY_D_NFC ) + PrintAndLog(" TYPE : INFINEON my-d\x99 NFC"); + else if ( tagtype & MY_D_MOVE ) + PrintAndLog(" TYPE : INFINEON my-d\x99 move"); + else if ( tagtype & MY_D_MOVE_NFC ) + PrintAndLog(" TYPE : INFINEON my-d\x99 move NFC"); else PrintAndLog(" TYPE : Unknown %04x",tagtype); return 0; @@ -338,20 +352,20 @@ static int ulc_print_3deskey( uint8_t *data){ static int ulc_print_configuration( uint8_t *data){ PrintAndLog("--- UL-C Configuration"); - PrintAndLog(" Higher Lockbits [40/0x28]: %s %s", sprint_hex(data, 4), printBits(2, data)); - PrintAndLog(" Counter [41/0x29]: %s %s", sprint_hex(data+4, 4), printBits(2, data+4)); + PrintAndLog(" Higher Lockbits [40/0x28]: %s - %s", sprint_hex(data, 4), printBits(2, data)); + PrintAndLog(" Counter [41/0x29]: %s - %s", sprint_hex(data+4, 4), printBits(2, data+4)); bool validAuth = (data[8] >= 0x03 && data[8] <= 0x30); if ( validAuth ) - PrintAndLog(" Auth0 [42/0x2A]: %s - Pages above %d needs authentication", sprint_hex(data+8, 4), data[8] ); + PrintAndLog(" Auth0 [42/0x2A]: %s Pages above %d needs authentication", sprint_hex(data+8, 4), data[8] ); else{ if ( data[8] == 0){ - PrintAndLog(" Auth0 [42/0x2A]: %s - default", sprint_hex(data+8, 4) ); + PrintAndLog(" Auth0 [42/0x2A]: %s default", sprint_hex(data+8, 4) ); } else { - PrintAndLog(" Auth0 [42/0x2A]: %s - auth byte is out-of-range", sprint_hex(data+8, 4) ); + PrintAndLog(" Auth0 [42/0x2A]: %s auth byte is out-of-range", sprint_hex(data+8, 4) ); } } - PrintAndLog(" Auth1 [43/0x2B]: %s - %s", + PrintAndLog(" Auth1 [43/0x2B]: %s %s", sprint_hex(data+12, 4), (data[12] & 1) ? "write access restricted": "read and write access restricted" ); @@ -369,16 +383,19 @@ static int ulev1_print_configuration( uint8_t *data){ uint8_t vctid = data[5]; PrintAndLog(" cfg0 [16/0x10]: %s", sprint_hex(data, 4)); - PrintAndLog(" - pages above %d needs authentication",data[3]); + if ( data[3] < 0xff ) + PrintAndLog(" - pages above %d needs authentication",data[3]); + else + PrintAndLog(" - pages don't need authentication"); PrintAndLog(" - strong modulation mode %s", (strg_mod_en) ? "enabled":"disabled"); PrintAndLog(" cfg1 [17/0x11]: %s", sprint_hex(data+4, 4) ); if ( authlim == 0) - PrintAndLog(" - Max number of password attempts is unlimited"); + PrintAndLog(" - Unlimited password attempts"); else PrintAndLog(" - Max number of password attempts is %d", authlim); PrintAndLog(" - user configuration %s", cfglck ? "permanently locked":"writeable"); PrintAndLog(" - %s access is protected with password", prot ? "read and write":"write"); - PrintAndLog(" 0x%02X - Virtual Card Type Identifier is %s default", vctid, (vctid==0x05)? "":"not"); + PrintAndLog(" %02X - Virtual Card Type Identifier is %s default", vctid, (vctid==0x05)? "":"not"); PrintAndLog(" PWD [18/0x12]: %s", sprint_hex(data+8, 4)); PrintAndLog(" PACK [19/0x13]: %s", sprint_hex(data+12, 4)); return 0; @@ -389,7 +406,7 @@ static int ulev1_print_counters(){ uint8_t counter[3] = {0,0,0}; for ( uint8_t i = 0; i<3; ++i) { ulev1_readCounter(i,counter, sizeof(counter) ); - PrintAndLog("Counter [%d] : %s", i, sprint_hex(counter,3)); + PrintAndLog(" [%0d] : %s", i, sprint_hex(counter,3)); } return 0; } @@ -404,6 +421,20 @@ static int ulev1_print_signature( uint8_t *data, uint8_t len){ //PrintAndLog("IC signature status: %s valid", (iseccvalid() )?"":"not"); return 0; } + +static int ulev1_print_version(uint8_t *data){ + PrintAndLog("\n--- UL-EV1 / NTAG Version"); + PrintAndLog(" Raw bytes : %s", sprint_hex(data, 8) ); + PrintAndLog(" Vendor ID : %02X, Manufacturer: %s", data[1], getTagInfo(data[1])); + PrintAndLog(" Product type : %s", getProductTypeStr(data[2])); + PrintAndLog(" Product subtype : %02X %s", data[3], (data[3]==1) ?"17 pF":"50pF"); + PrintAndLog(" Major version : %02X", data[4]); + PrintAndLog(" Minor version : %02X", data[5]); + PrintAndLog(" Size : %s", getUlev1CardSizeStr(data[6])); + PrintAndLog(" Protocol type : %02X", data[7]); + return 0; +} + /* static int ulc_magic_test(){ // Magic Ultralight test @@ -468,36 +499,63 @@ uint16_t GetHF14AMfU_Type(void){ } // Ultralight - ATQA / SAK if ( card.atqa[1] != 0x00 || card.atqa[0] != 0x44 || card.sak != 0x00 ) { - PrintAndLog ("Tag is not UL or NTAG, ATQA1: %x, ATQA0: %x, SAK: %d", card.atqa[1],card.atqa[0],card.sak); + PrintAndLog("Tag is not Ultralight | NTAG | MY-D [ATQA: %02X %02x SAK: %02X]\n", card.atqa[1], card.atqa[0], card.sak); ul_switch_off_field(); return UL_ERROR; } - len = ulev1_getVersion(version, sizeof(version)); - if (len > -1) ul_switch_off_field(); //if -1 it is already off + if ( card.uid[0] != 0x05) { - switch (len) { - case 0x0A: { + len = ulev1_getVersion(version, sizeof(version)); + if (len > -1) ul_switch_off_field(); //if -1 it is already off - if ( version[2] == 0x03 && version[6] == 0x0B ) - tagtype = UL_EV1_48; - else if ( version[2] == 0x03 && version[6] != 0x0B ) - tagtype = UL_EV1_128; - else if ( version[2] == 0x04 && version[6] == 0x0F ) - tagtype = NTAG_213; - else if ( version[2] == 0x04 && version[6] != 0x11 ) - tagtype = NTAG_215; - else if ( version[2] == 0x04 && version[6] == 0x13 ) - tagtype = NTAG_216; - else if ( version[2] == 0x04 ) - tagtype = NTAG; + switch (len) { + case 0x0A: { - break; + if ( version[2] == 0x03 && version[6] == 0x0B ) + tagtype = UL_EV1_48; + else if ( version[2] == 0x03 && version[6] != 0x0B ) + tagtype = UL_EV1_128; + else if ( version[2] == 0x04 && version[6] == 0x0F ) + tagtype = NTAG_213; + else if ( version[2] == 0x04 && version[6] == 0x11 ) + tagtype = NTAG_215; + else if ( version[2] == 0x04 && version[6] == 0x13 ) + tagtype = NTAG_216; + else if ( version[2] == 0x04 ) + tagtype = NTAG; + + break; + } + case 0x01: tagtype = UL_C; break; + case 0x00: tagtype = UL; break; + case -1 : tagtype = (UL | UL_C); break; //when does this happen? + default : tagtype = UNKNOWN; break; + } + if (tagtype == (UL | UL_C)) { + status = ul_select(&card); + if ( status < 1 ){ + PrintAndLog("Error: couldn't select 2"); + ul_switch_off_field(); + return UL_ERROR; + } + uint8_t nonce1[11] = {0x00}; + status = ulc_requestAuthentication(0, nonce1, sizeof(nonce1)); + if ( status > 0 ) + tagtype = UL_C; + else + tagtype = UL; + + if (status != -1) ul_switch_off_field(); + } + } else { + // Infinition MY-D tests Exam high nibble + uint8_t nib = (card.uid[1] & 0xf0) >> 4; + switch ( nib ){ + case 1: tagtype = MY_D; break; + case 2: tagtype = (MY_D | MY_D_NFC); break; + case 3: tagtype = (MY_D_MOVE | MY_D_MOVE_NFC); break; } - case 0x01: tagtype = UL_C; break; - case 0x00: tagtype = UL; break; - case -1 : tagtype = (UL | UL_C); break; //when does this happen? - default : tagtype = UNKNOWN; break; } tagtype = (ul_magic_test() == UL_MAGIC) ? (tagtype | MAGIC) : tagtype; @@ -532,7 +590,6 @@ int CmdHF14AMfUInfo(const char *Cmd){ status = ul_read(0, data, sizeof(data)); if ( status == -1 ){ PrintAndLog("Error: tag didn't answer to READ"); - ul_switch_off_field(); return status; } @@ -547,7 +604,6 @@ int CmdHF14AMfUInfo(const char *Cmd){ PrintAndLog("Error: tag didn't answer to READ - possibly locked"); return status; } - ulc_print_configuration(ulc_conf); if ((tagtype & MAGIC)){ @@ -575,7 +631,17 @@ int CmdHF14AMfUInfo(const char *Cmd){ } if ((tagtype & (UL_EV1_48 | UL_EV1_128))) { - + //do counters and signature first (don't neet auth) + ulev1_print_counters(); + + uint8_t ulev1_signature[32] = {0x00}; + status = ulev1_readSignature( ulev1_signature, sizeof(ulev1_signature)); + if ( status == -1 ){ + PrintAndLog("Error: tag didn't answer to READ SIGNATURE"); + return status; + } + ulev1_print_signature( ulev1_signature, sizeof(ulev1_signature)); + uint8_t startconfigblock = (tagtype & UL_EV1_48) ? 0x10 : 0x25; uint8_t ulev1_conf[16] = {0x00}; status = ul_read(startconfigblock, ulev1_conf, sizeof(ulev1_conf)); @@ -585,18 +651,7 @@ int CmdHF14AMfUInfo(const char *Cmd){ } // save AUTHENTICATION LIMITS for later: authlim = (ulev1_conf[4] & 0x07); - ulev1_print_configuration(ulev1_conf); - - uint8_t ulev1_signature[32] = {0x00}; - status = ulev1_readSignature( ulev1_signature, sizeof(ulev1_signature)); - if ( status == -1 ){ - PrintAndLog("Error: tag didn't answer to READ SIGNATURE"); - return status; - } - ulev1_print_signature( ulev1_signature, sizeof(ulev1_signature)); - - ulev1_print_counters(); } if ((tagtype & (UL_EV1_48 | UL_EV1_128 | NTAG_213 | NTAG_215 | NTAG_216))) { @@ -631,7 +686,6 @@ int CmdHF14AMfUInfo(const char *Cmd){ if ((tagtype & (NTAG_213 | NTAG_215 | NTAG_216))){ - PrintAndLog("\n--- NTAG NDEF Message"); uint8_t cc[16] = {0x00}; status = ul_read(3, cc, sizeof(cc)); if ( status == -1 ){ @@ -642,6 +696,7 @@ int CmdHF14AMfUInfo(const char *Cmd){ } ul_switch_off_field(); + PrintAndLog(""); return 0; } From 4693c188ab721316469e5f3ce39865e874d1b122 Mon Sep 17 00:00:00 2001 From: marshmellow42 Date: Mon, 11 May 2015 16:25:11 -0400 Subject: [PATCH 19/49] minor hf mfu output consistancies --- client/cmdhfmfu.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/client/cmdhfmfu.c b/client/cmdhfmfu.c index ce3457896..8b800874c 100644 --- a/client/cmdhfmfu.c +++ b/client/cmdhfmfu.c @@ -258,7 +258,7 @@ static int ul_print_default( uint8_t *data){ uid[6] = data[7]; PrintAndLog(" UID : %s ", sprint_hex(uid, 7)); - PrintAndLog(" UID[0] : %02x, Manufacturer: %s", uid[0], getTagInfo(uid[0]) ); + PrintAndLog(" UID[0] : %02X, Manufacturer: %s", uid[0], getTagInfo(uid[0]) ); if ( uid[0] == 0x05 ) { uint8_t chip = (data[8] & 0xC7); // 11000111 mask, bit 3,4,5 RFU switch (chip){ @@ -270,19 +270,20 @@ static int ul_print_default( uint8_t *data){ // CT (cascade tag byte) 0x88 xor SN0 xor SN1 xor SN2 int crc0 = 0x88 ^ data[0] ^ data[1] ^data[2]; if ( data[3] == crc0 ) - PrintAndLog(" BCC0 : 0x%02X - Ok", data[3]); + PrintAndLog(" BCC0 : %02X - Ok", data[3]); else - PrintAndLog(" BCC0 : 0x%02X - crc should be %02x", data[3], crc0); + PrintAndLog(" BCC0 : %02X - crc should be %02X", data[3], crc0); int crc1 = data[4] ^ data[5] ^ data[6] ^data[7]; if ( data[8] == crc1 ) - PrintAndLog(" BCC1 : 0x%02X - Ok", data[8]); + PrintAndLog(" BCC1 : %02X - Ok", data[8]); else - PrintAndLog(" BCC1 : 0x%02X - crc should be 0x%02X", data[8], crc1 ); + PrintAndLog(" BCC1 : %02X - crc should be %02X", data[8], crc1 ); - PrintAndLog(" Internal : 0x%02X - %s default", data[9], (data[9]==0x48)?"":"not" ); + PrintAndLog(" Internal : %02X - %s default", data[9], (data[9]==0x48)?"":"not" ); PrintAndLog(" Lock : %s - %s", sprint_hex(data+10, 2),printBits( 2, data+10) ); PrintAndLog("OneTimePad : %s ", sprint_hex(data + 12, 4)); + PrintAndLog(""); return 0; } @@ -499,7 +500,7 @@ uint16_t GetHF14AMfU_Type(void){ } // Ultralight - ATQA / SAK if ( card.atqa[1] != 0x00 || card.atqa[0] != 0x44 || card.sak != 0x00 ) { - PrintAndLog("Tag is not Ultralight | NTAG | MY-D [ATQA: %02X %02x SAK: %02X]\n", card.atqa[1], card.atqa[0], card.sak); + PrintAndLog("Tag is not Ultralight | NTAG | MY-D [ATQA: %02X %02X SAK: %02X]\n", card.atqa[1], card.atqa[0], card.sak); ul_switch_off_field(); return UL_ERROR; } From 2be768af57ffa83d416f7728fbf790fe9e405c54 Mon Sep 17 00:00:00 2001 From: marshmellow42 Date: Mon, 11 May 2015 18:22:50 -0400 Subject: [PATCH 20/49] hf mfu info bugs --- client/cmdhfmfu.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/client/cmdhfmfu.c b/client/cmdhfmfu.c index 8b800874c..fec7a85ec 100644 --- a/client/cmdhfmfu.c +++ b/client/cmdhfmfu.c @@ -96,9 +96,10 @@ char* getUlev1CardSizeStr( uint8_t fsize ){ static char buf[40]; char *retStr = buf; + memset(buf, 0, sizeof(buf)); - uint8_t usize = 1 << ((fsize >>1) + 1); - uint8_t lsize = 1 << (fsize >>1); + uint16_t usize = 1 << ((fsize >>1) + 1); + uint16_t lsize = 1 << (fsize >>1); // is LSB set? if ( fsize & 1 ) @@ -885,6 +886,7 @@ int CmdHF14AMfUDump(const char *Cmd){ case 's': swapEndian = true; cmdp++; + break; default: PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp)); errors = true; From 8ceb6b03e5caee0cc7292894bfa25fa4a3f85c4c Mon Sep 17 00:00:00 2001 From: marshmellow42 Date: Tue, 12 May 2015 00:19:44 -0400 Subject: [PATCH 21/49] hf search - prelim - re-use hf mfu GetTagType... in hf 14a reader to identify UL(+) still a work in progress. --- client/cmdhf.c | 22 +++++++++++++++++--- client/cmdhf14a.c | 39 ++++++++++++++++++++++++++++++++++- client/cmdhfmfu.c | 52 ++++++++++++++++------------------------------- client/cmdhfmfu.h | 22 ++++++++++++++++++++ 4 files changed, 97 insertions(+), 38 deletions(-) diff --git a/client/cmdhf.c b/client/cmdhf.c index 020ea94cb..524d9c2e1 100644 --- a/client/cmdhf.c +++ b/client/cmdhf.c @@ -544,6 +544,21 @@ int CmdHFList(const char *Cmd) return 0; } +int CmdHFSearch(const char *Cmd){ + int ans = 0; + ans = CmdHF14AReader(Cmd); + if (ans > 0) return ans; + + ans = CmdHF15Reader(Cmd); + //if (ans > 0) return ans; + + ans = CmdHF14BRead(Cmd); + //if (ans > 0) return ans; + + ans = CmdHFiClassReader(Cmd); + //if (ans > 0) return ans; + return 0; +} static command_t CommandTable[] = { @@ -554,10 +569,11 @@ static command_t CommandTable[] = {"epa", CmdHFEPA, 1, "{ German Identification Card... }"}, {"legic", CmdHFLegic, 0, "{ LEGIC RFIDs... }"}, {"iclass", CmdHFiClass, 1, "{ ICLASS RFIDs... }"}, - {"mf", CmdHFMF, 1, "{ MIFARE RFIDs... }"}, - {"mfu", CmdHFMFUltra, 1, "{ MIFARE Ultralight RFIDs... }"}, + {"mf", CmdHFMF, 1, "{ MIFARE RFIDs... }"}, + {"mfu", CmdHFMFUltra, 1, "{ MIFARE Ultralight RFIDs... }"}, {"tune", CmdHFTune, 0, "Continuously measure HF antenna tuning"}, - {"list", CmdHFList, 1, "List protocol data in trace buffer"}, + {"list", CmdHFList, 1, "List protocol data in trace buffer"}, + {"search", CmdHFSearch, 1, "Search for known HF tags"}, {NULL, NULL, 0, NULL} }; diff --git a/client/cmdhf14a.c b/client/cmdhf14a.c index d4285eeab..d1f8b3634 100644 --- a/client/cmdhf14a.c +++ b/client/cmdhf14a.c @@ -23,6 +23,7 @@ #include "common.h" #include "cmdmain.h" #include "mifare.h" +#include "cmdhfmfu.h" static int CmdHelp(const char *Cmd); static void waitCmd(uint8_t iLen); @@ -169,6 +170,42 @@ int CmdHF14AReader(const char *Cmd) switch (card.sak) { case 0x00: + + //***************************************test**************** + // disconnect + c.arg[0] = 0; + c.arg[1] = 0; + c.arg[2] = 0; + SendCommand(&c); + + uint16_t tagT = GetHF14AMfU_Type(); + ul_print_type(tagT, 0); + + //reconnect for further tests + c.arg[0] = ISO14A_CONNECT | ISO14A_NO_DISCONNECT; + c.arg[1] = 0; + c.arg[2] = 0; + + SendCommand(&c); + + UsbCommand resp; + WaitForResponse(CMD_ACK,&resp); + + memcpy(&card, (iso14a_card_select_t *)resp.d.asBytes, sizeof(iso14a_card_select_t)); + + select_status = resp.arg[0]; // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS + + if(select_status == 0) { + //PrintAndLog("iso14443a card select failed"); + // disconnect + c.arg[0] = 0; + c.arg[1] = 0; + c.arg[2] = 0; + SendCommand(&c); + return 0; + } + + /* orig // check if the tag answers to GETVERSION (0x60) c.arg[0] = ISO14A_RAW | ISO14A_APPEND_CRC | ISO14A_NO_DISCONNECT; c.arg[1] = 1; @@ -187,7 +224,7 @@ int CmdHF14AReader(const char *Cmd) case 0x01:PrintAndLog("TYPE : NXP MIFARE Ultralight C");break; case 0x00:PrintAndLog("TYPE : NXP MIFARE Ultralight");break; } - + */ break; case 0x01: PrintAndLog("TYPE : NXP TNP3xxx Activision Game Appliance"); break; case 0x04: PrintAndLog("TYPE : NXP MIFARE (various !DESFire !DESFire EV1)"); break; diff --git a/client/cmdhfmfu.c b/client/cmdhfmfu.c index fec7a85ec..884ed3ff8 100644 --- a/client/cmdhfmfu.c +++ b/client/cmdhfmfu.c @@ -23,26 +23,6 @@ #define MAX_NTAG_215 0x86 #define MAX_NTAG_216 0xe6 -typedef enum TAGTYPE_UL { - UNKNOWN = 0x0000, - UL = 0x0001, - UL_C = 0x0002, - UL_EV1_48 = 0x0004, - UL_EV1_128 = 0x0008, - NTAG = 0x0010, - NTAG_213 = 0x0020, - NTAG_215 = 0x0040, - NTAG_216 = 0x0080, - MY_D = 0x0100, - MY_D_NFC = 0x0200, - MY_D_MOVE = 0x0400, - MY_D_MOVE_NFC = 0x0800, - MAGIC = 0x1000, - UL_MAGIC = UL | MAGIC, - UL_C_MAGIC = UL_C | MAGIC, - UL_ERROR = 0xFFFF, -} TagTypeUL_t; - #define KEYS_3DES_COUNT 7 uint8_t default_3des_keys[KEYS_3DES_COUNT][16] = { { 0x42,0x52,0x45,0x41,0x4b,0x4d,0x45,0x49,0x46,0x59,0x4f,0x55,0x43,0x41,0x4e,0x21 },// 3des std key @@ -314,31 +294,35 @@ static int ntag_print_CC(uint8_t *data) { return 0; } -static int ul_print_type(uint16_t tagtype){ +int ul_print_type(uint16_t tagtype, uint8_t spaces){ + char spc[11] = " "; + spc[10]=0x00; + char *spacer = spc + (10-spaces); + if ( tagtype & UL ) - PrintAndLog(" TYPE : MIFARE Ultralight (MF0ICU1) %s [%x]", (tagtype & MAGIC)?"":"", tagtype); + PrintAndLog("%sTYPE : MIFARE Ultralight (MF0ICU1) %s [%x]", spacer, (tagtype & MAGIC)?"":"", tagtype); else if ( tagtype & UL_C) - PrintAndLog(" TYPE : MIFARE Ultralight C (MF0ULC) %s [%x]", (tagtype & MAGIC)?"":"", tagtype ); + PrintAndLog("%sTYPE : MIFARE Ultralight C (MF0ULC) %s [%x]", spacer, (tagtype & MAGIC)?"":"", tagtype ); else if ( tagtype & UL_EV1_48) - PrintAndLog(" TYPE : MIFARE Ultralight EV1 48bytes (MF0UL1101)"); + PrintAndLog("%sTYPE : MIFARE Ultralight EV1 48bytes (MF0UL1101)", spacer); else if ( tagtype & UL_EV1_128) - PrintAndLog(" TYPE : MIFARE Ultralight EV1 128bytes (MF0UL2101)"); + PrintAndLog("%sTYPE : MIFARE Ultralight EV1 128bytes (MF0UL2101)", spacer); else if ( tagtype & NTAG_213 ) - PrintAndLog(" TYPE : MIFARE NTAG 213 144bytes (NT2H1311G0DU)"); + PrintAndLog("%sTYPE : MIFARE NTAG 213 144bytes (NT2H1311G0DU)", spacer); else if ( tagtype & NTAG_215 ) - PrintAndLog(" TYPE : MIFARE NTAG 215 504bytes (NT2H1511G0DU)"); + PrintAndLog("%sTYPE : MIFARE NTAG 215 504bytes (NT2H1511G0DU)", spacer); else if ( tagtype & NTAG_216 ) - PrintAndLog(" TYPE : MIFARE NTAG 216 888bytes (NT2H1611G0DU)"); + PrintAndLog("%sTYPE : MIFARE NTAG 216 888bytes (NT2H1611G0DU)", spacer); else if ( tagtype & MY_D ) - PrintAndLog(" TYPE : INFINEON my-d\x99"); + PrintAndLog("%sTYPE : INFINEON my-d\x99", spacer); else if ( tagtype & MY_D_NFC ) - PrintAndLog(" TYPE : INFINEON my-d\x99 NFC"); + PrintAndLog("%sTYPE : INFINEON my-d\x99 NFC", spacer); else if ( tagtype & MY_D_MOVE ) - PrintAndLog(" TYPE : INFINEON my-d\x99 move"); + PrintAndLog("%sTYPE : INFINEON my-d\x99 move", spacer); else if ( tagtype & MY_D_MOVE_NFC ) - PrintAndLog(" TYPE : INFINEON my-d\x99 move NFC"); + PrintAndLog("%sTYPE : INFINEON my-d\x99 move NFC", spacer); else - PrintAndLog(" TYPE : Unknown %04x",tagtype); + PrintAndLog("%sTYPE : Unknown %04x", spacer, tagtype); return 0; } @@ -579,7 +563,7 @@ int CmdHF14AMfUInfo(const char *Cmd){ PrintAndLog("\n--- Tag Information ---------"); PrintAndLog("-------------------------------------------------------------"); - ul_print_type(tagtype); + ul_print_type(tagtype, 6); status = ul_select(&card); if ( status < 1 ){ diff --git a/client/cmdhfmfu.h b/client/cmdhfmfu.h index 8e96775cd..23f97cac3 100644 --- a/client/cmdhfmfu.h +++ b/client/cmdhfmfu.h @@ -20,9 +20,31 @@ void rol (uint8_t *data, const size_t len); uint8_t requestAuthentication( uint8_t *nonce); int try3DesAuthentication( uint8_t *key); uint16_t GetHF14AMfU_Type(void); +int ul_print_type(uint16_t tagtype, uint8_t spacer); int usage_hf_mfu_dump(void); int CmdHFMFUltra(const char *Cmd); int CmdHF14AMfUInfo(const char *Cmd); + +typedef enum TAGTYPE_UL { + UNKNOWN = 0x0000, + UL = 0x0001, + UL_C = 0x0002, + UL_EV1_48 = 0x0004, + UL_EV1_128 = 0x0008, + NTAG = 0x0010, + NTAG_213 = 0x0020, + NTAG_215 = 0x0040, + NTAG_216 = 0x0080, + MY_D = 0x0100, + MY_D_NFC = 0x0200, + MY_D_MOVE = 0x0400, + MY_D_MOVE_NFC = 0x0800, + MAGIC = 0x1000, + UL_MAGIC = UL | MAGIC, + UL_C_MAGIC = UL_C | MAGIC, + UL_ERROR = 0xFFFF, +} TagTypeUL_t; + #endif From 6ce0e5386a5dd4ce8eb171437e2b62ca55a328ea Mon Sep 17 00:00:00 2001 From: marshmellow42 Date: Tue, 12 May 2015 16:45:48 -0400 Subject: [PATCH 22/49] HF Search - refactoring cmds to work with it --- armsrc/iclass.c | 18 ++++++++++-------- client/cmdhf.c | 29 ++++++++++++++++++++--------- client/cmdhf14a.c | 2 +- client/cmdhf15.c | 18 ++++++++++++++++-- client/cmdhf15.h | 1 + client/cmdhficlass.c | 31 ++++++++++++++++++++++--------- client/cmdhficlass.h | 1 + include/usb_cmd.h | 9 +++++---- 8 files changed, 76 insertions(+), 33 deletions(-) diff --git a/armsrc/iclass.c b/armsrc/iclass.c index 56bc29db5..9139d3bd9 100644 --- a/armsrc/iclass.c +++ b/armsrc/iclass.c @@ -1677,7 +1677,7 @@ void ReaderIClass(uint8_t arg0) { uint8_t card_data[6 * 8]={0}; memset(card_data, 0xFF, sizeof(card_data)); - uint8_t last_csn[8]={0}; + uint8_t last_csn[8]={0}; //Read conf block CRC(0x01) => 0xfa 0x22 uint8_t readConf[] = { ICLASS_CMD_READ_OR_IDENTIFY,0x01, 0xfa, 0x22}; @@ -1685,16 +1685,18 @@ void ReaderIClass(uint8_t arg0) { uint8_t readAA[] = { ICLASS_CMD_READ_OR_IDENTIFY,0x05, 0xde, 0x64}; - int read_status= 0; + int read_status= 0; uint8_t result_status = 0; - bool abort_after_read = arg0 & FLAG_ICLASS_READER_ONLY_ONCE; - + bool abort_after_read = arg0 & FLAG_ICLASS_READER_ONLY_ONCE; + bool try_once = arg0 & FLAG_ICLASS_READER_ONE_TRY; set_tracing(TRUE); - setupIclassReader(); + setupIclassReader(); + uint16_t tryCnt=0; while(!BUTTON_PRESS()) - { - + { + if (try_once && tryCnt > 5) break; + tryCnt++; if(!tracing) { DbpString("Trace full"); break; @@ -1761,7 +1763,7 @@ void ReaderIClass(uint8_t arg0) { } LED_B_OFF(); - } + } cmd_send(CMD_ACK,0,0,0,card_data, 0); LED_A_OFF(); } diff --git a/client/cmdhf.c b/client/cmdhf.c index 524d9c2e1..8853a7f3f 100644 --- a/client/cmdhf.c +++ b/client/cmdhf.c @@ -87,7 +87,7 @@ void annotateIso14443a(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize) case MIFARE_ULC_AUTH_2: snprintf(exp,size,"AUTH_ANSW"); break; case MIFARE_ULEV1_AUTH: snprintf(exp,size,"PWD-AUTH"); break; case MIFARE_ULEV1_FASTREAD:{ - if ( cmdsize >=3 && cmd[2] < 0x21) + if ( cmdsize >=3 && cmd[2] <= 0xE6) snprintf(exp,size,"READ RANGE (%d-%d)",cmd[1],cmd[2]); else snprintf(exp,size,"?"); @@ -546,17 +546,28 @@ int CmdHFList(const char *Cmd) int CmdHFSearch(const char *Cmd){ int ans = 0; - ans = CmdHF14AReader(Cmd); - if (ans > 0) return ans; + PrintAndLog(""); + ans = CmdHF14AReader("s"); + if (ans > 0) { + PrintAndLog("\nValid ISO14443A Tag Found - Quiting Search\n"); + return ans; + } + ans = HFiClassReader("", false, false); + if (ans) { + PrintAndLog("\nValid iClass Tag (or PicoPass Tag) Found - Quiting Search\n"); + return ans; + } + ans = HF15Reader("", false); + if (ans) { + PrintAndLog("\nValid ISO15693 Tag Found - Quiting Search\n"); + return ans; + } - ans = CmdHF15Reader(Cmd); - //if (ans > 0) return ans; - ans = CmdHF14BRead(Cmd); + //14b has issues currently... + //ans = CmdHF14BRead(Cmd); //if (ans > 0) return ans; - ans = CmdHFiClassReader(Cmd); - //if (ans > 0) return ans; return 0; } @@ -573,7 +584,7 @@ static command_t CommandTable[] = {"mfu", CmdHFMFUltra, 1, "{ MIFARE Ultralight RFIDs... }"}, {"tune", CmdHFTune, 0, "Continuously measure HF antenna tuning"}, {"list", CmdHFList, 1, "List protocol data in trace buffer"}, - {"search", CmdHFSearch, 1, "Search for known HF tags"}, + {"search", CmdHFSearch, 1, "Search for known HF tags [preliminary]"}, {NULL, NULL, 0, NULL} }; diff --git a/client/cmdhf14a.c b/client/cmdhf14a.c index d1f8b3634..1973ff222 100644 --- a/client/cmdhf14a.c +++ b/client/cmdhf14a.c @@ -144,7 +144,7 @@ int CmdHF14AReader(const char *Cmd) uint64_t select_status = resp.arg[0]; // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS if(select_status == 0) { - PrintAndLog("iso14443a card select failed"); + if (Cmd[0] != 's') PrintAndLog("iso14443a card select failed"); // disconnect c.arg[0] = 0; c.arg[1] = 0; diff --git a/client/cmdhf15.c b/client/cmdhf15.c index c3ff7dd6d..8ddbea89b 100644 --- a/client/cmdhf15.c +++ b/client/cmdhf15.c @@ -374,6 +374,20 @@ int CmdHF15Record(const char *Cmd) return 0; } +int HF15Reader(const char *Cmd, bool verbose) +{ + uint8_t uid[8]; + + if (!getUID(uid)) { + if (verbose) PrintAndLog("No Tag found."); + return 0; + } + + PrintAndLog("Tag UID : %s",sprintUID(NULL,uid)); + PrintAndLog("Tag Info: %s",getTagInfo(uid)); + return 1; +} + int CmdHF15Reader(const char *Cmd) { UsbCommand c = {CMD_READER_ISO_15693, {strtol(Cmd, NULL, 0), 0, 0}}; @@ -469,7 +483,7 @@ int CmdHF15DumpMem(const char*Cmd) { // PrintAndLog("bn=%i",blocknum); } else { PrintAndLog("Tag returned Error %i: %s",recv[1],TagErrorStr(recv[1])); - return 0; + return 1; } } // else PrintAndLog("crc"); } // else PrintAndLog("r null"); @@ -481,7 +495,7 @@ int CmdHF15DumpMem(const char*Cmd) { // PrintAndLog("CRC Failed"); // else // PrintAndLog("Tag returned Error %i: %s",recv[1],TagErrorStr(recv[1])); - return 0; + return 1; } diff --git a/client/cmdhf15.h b/client/cmdhf15.h index 8d78e13f1..c62646046 100644 --- a/client/cmdhf15.h +++ b/client/cmdhf15.h @@ -15,6 +15,7 @@ int CmdHF15(const char *Cmd); int CmdHF15Demod(const char *Cmd); int CmdHF15Read(const char *Cmd); +int HF15Reader(const char *Cmd, bool verbose); int CmdHF15Reader(const char *Cmd); int CmdHF15Sim(const char *Cmd); int CmdHF15Record(const char *Cmd); diff --git a/client/cmdhficlass.c b/client/cmdhficlass.c index b83371960..824aaa367 100644 --- a/client/cmdhficlass.c +++ b/client/cmdhficlass.c @@ -165,34 +165,47 @@ int CmdHFiClassSim(const char *Cmd) return 0; } -int CmdHFiClassReader(const char *Cmd) +int HFiClassReader(const char *Cmd, bool loop, bool verbose) { + bool tagFound = false; UsbCommand c = {CMD_READER_ICLASS, {FLAG_ICLASS_READER_CSN| FLAG_ICLASS_READER_CONF|FLAG_ICLASS_READER_AA}}; + if (!loop) c.arg[0] |= FLAG_ICLASS_READER_ONLY_ONCE | FLAG_ICLASS_READER_ONE_TRY; SendCommand(&c); UsbCommand resp; while(!ukbhit()){ - if (WaitForResponseTimeout(CMD_ACK,&resp,4500)) { - uint8_t readStatus = resp.arg[0] & 0xff; - uint8_t * data = resp.d.asBytes; + if (WaitForResponseTimeout(CMD_ACK,&resp, 4500)) { + uint8_t readStatus = resp.arg[0] & 0xff; + uint8_t *data = resp.d.asBytes; - PrintAndLog("Readstatus:%02x", readStatus); + if (verbose) + PrintAndLog("Readstatus:%02x", readStatus); if( readStatus == 0){ //Aborted - PrintAndLog("Quitting..."); + if (verbose) PrintAndLog("Quitting..."); return 0; } - if( readStatus & FLAG_ICLASS_READER_CSN) PrintAndLog("CSN: %s",sprint_hex(data,8)); + if( readStatus & FLAG_ICLASS_READER_CSN){ + PrintAndLog("CSN: %s",sprint_hex(data,8)); + tagFound = true; + } if( readStatus & FLAG_ICLASS_READER_CC) PrintAndLog("CC: %s",sprint_hex(data+16,8)); if( readStatus & FLAG_ICLASS_READER_CONF){ printIclassDumpInfo(data); } + if (tagFound && !loop) return 1; } else { - PrintAndLog("Command execute timeout"); + if (verbose) PrintAndLog("Command execute timeout"); } + if (!loop) break; } - return 0; + +} + +int CmdHFiClassReader(const char *Cmd) +{ + return HFiClassReader(Cmd, true, true); } int CmdHFiClassReader_Replay(const char *Cmd) diff --git a/client/cmdhficlass.h b/client/cmdhficlass.h index e4048eb17..30c6a8a7b 100644 --- a/client/cmdhficlass.h +++ b/client/cmdhficlass.h @@ -17,6 +17,7 @@ int CmdHFiClass(const char *Cmd); int CmdHFiClassSnoop(const char *Cmd); int CmdHFiClassSim(const char *Cmd); int CmdHFiClassList(const char *Cmd); +int HFiClassReader(const char *Cmd, bool loop, bool verbose); int CmdHFiClassReader(const char *Cmd); int CmdHFiClassReader_Replay(const char *Cmd); diff --git a/include/usb_cmd.h b/include/usb_cmd.h index 31498e2a4..f67eac580 100644 --- a/include/usb_cmd.h +++ b/include/usb_cmd.h @@ -201,10 +201,11 @@ typedef struct{ //Iclass reader flags #define FLAG_ICLASS_READER_ONLY_ONCE 0x01 -#define FLAG_ICLASS_READER_CC 0x02 -#define FLAG_ICLASS_READER_CSN 0x04 -#define FLAG_ICLASS_READER_CONF 0x08 -#define FLAG_ICLASS_READER_AA 0x10 +#define FLAG_ICLASS_READER_CC 0x02 +#define FLAG_ICLASS_READER_CSN 0x04 +#define FLAG_ICLASS_READER_CONF 0x08 +#define FLAG_ICLASS_READER_AA 0x10 +#define FLAG_ICLASS_READER_ONE_TRY 0x20 From a2e2bb8a154fbf786700574e71b6b0a36fdd4ff9 Mon Sep 17 00:00:00 2001 From: marshmellow42 Date: Tue, 12 May 2015 18:16:55 -0400 Subject: [PATCH 23/49] hf mfu info - ICEMANS updates plus slight change to UL_EV1 auth annotation. --- client/cmdhf.c | 7 ++- client/cmdhfmfu.c | 139 +++++++++++++++++++++++++++++++++++++--------- client/cmdhfmfu.h | 13 +++-- 3 files changed, 128 insertions(+), 31 deletions(-) diff --git a/client/cmdhf.c b/client/cmdhf.c index 8853a7f3f..16f7bb0f3 100644 --- a/client/cmdhf.c +++ b/client/cmdhf.c @@ -85,7 +85,12 @@ void annotateIso14443a(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize) case MIFARE_MAGICWIPEC: snprintf(exp,size,"MAGIC WIPEC"); break; case MIFARE_ULC_AUTH_1: snprintf(exp,size,"AUTH "); break; case MIFARE_ULC_AUTH_2: snprintf(exp,size,"AUTH_ANSW"); break; - case MIFARE_ULEV1_AUTH: snprintf(exp,size,"PWD-AUTH"); break; + case MIFARE_ULEV1_AUTH: + if ( cmdsize == 7 ) + snprintf(exp,size,"PWD-AUTH KEY: 0x%02x%02x%02x%02x", cmd[1], cmd[2], cmd[3], cmd[4] ); + else + snprintf(exp,size,"PWD-AUTH"); + break; case MIFARE_ULEV1_FASTREAD:{ if ( cmdsize >=3 && cmd[2] <= 0xE6) snprintf(exp,size,"READ RANGE (%d-%d)",cmd[1],cmd[2]); diff --git a/client/cmdhfmfu.c b/client/cmdhfmfu.c index 884ed3ff8..7b9367922 100644 --- a/client/cmdhfmfu.c +++ b/client/cmdhfmfu.c @@ -94,7 +94,7 @@ static void ul_switch_on_field(void) { SendCommand(&c); } -static void ul_switch_off_field(void) { +void ul_switch_off_field(void) { UsbCommand c = {CMD_READER_ISO_14443a, {0, 0, 0}}; SendCommand(&c); } @@ -170,9 +170,9 @@ static int ul_comp_write( uint8_t page, uint8_t *data, uint8_t datalen ){ return -1; } -static int ulc_requestAuthentication( uint8_t blockNo, uint8_t *nonce, uint16_t nonceLength ){ +static int ulc_requestAuthentication( uint8_t *nonce, uint16_t nonceLength ){ - uint8_t cmd[] = {MIFARE_ULC_AUTH_1, blockNo}; + uint8_t cmd[] = {MIFARE_ULC_AUTH_1, 0x00}; int len = ul_send_cmd_raw(cmd, sizeof(cmd), nonce, nonceLength); if ( len == -1 ) ul_switch_off_field(); @@ -217,6 +217,15 @@ static int ulev1_readCounter( uint8_t counter, uint8_t *response, uint16_t respo return len; } +static int ulev1_readTearing( uint8_t counter, uint8_t *response, uint16_t responseLength ){ + + uint8_t cmd[] = {MIFARE_ULEV1_CHECKTEAR, counter}; + int len = ul_send_cmd_raw(cmd, sizeof(cmd), response, responseLength); + if (len == -1) + ul_switch_off_field(); + return len; +} + static int ulev1_readSignature( uint8_t *response, uint16_t responseLength ){ uint8_t cmd[] = {MIFARE_ULEV1_READSIG, 0x00}; @@ -331,7 +340,7 @@ static int ulc_print_3deskey( uint8_t *data){ PrintAndLog(" deskey1 [45/0x2D]: %s [%.4s]", sprint_hex(data+4 ,4),data+4); PrintAndLog(" deskey2 [46/0x2E]: %s [%.4s]", sprint_hex(data+8 ,4),data+8); PrintAndLog(" deskey2 [47/0x2F]: %s [%.4s]", sprint_hex(data+12,4),data+12); - PrintAndLog(" 3des key : %s", sprint_hex(SwapEndian64(data, 16), 16)); + PrintAndLog("\n 3des key : %s", sprint_hex(SwapEndian64(data, 16), 16)); return 0; } @@ -343,7 +352,7 @@ static int ulc_print_configuration( uint8_t *data){ bool validAuth = (data[8] >= 0x03 && data[8] <= 0x30); if ( validAuth ) - PrintAndLog(" Auth0 [42/0x2A]: %s Pages above %d needs authentication", sprint_hex(data+8, 4), data[8] ); + PrintAndLog(" Auth0 [42/0x2A]: %s Page %d and above need authentication", sprint_hex(data+8, 4), data[8] ); else{ if ( data[8] == 0){ PrintAndLog(" Auth0 [42/0x2A]: %s default", sprint_hex(data+8, 4) ); @@ -370,7 +379,7 @@ static int ulev1_print_configuration( uint8_t *data){ PrintAndLog(" cfg0 [16/0x10]: %s", sprint_hex(data, 4)); if ( data[3] < 0xff ) - PrintAndLog(" - pages above %d needs authentication",data[3]); + PrintAndLog(" - page %d and above need authentication",data[3]); else PrintAndLog(" - pages don't need authentication"); PrintAndLog(" - strong modulation mode %s", (strg_mod_en) ? "enabled":"disabled"); @@ -389,10 +398,13 @@ static int ulev1_print_configuration( uint8_t *data){ static int ulev1_print_counters(){ PrintAndLog("--- UL-EV1 Counters"); + uint8_t tear[1] = {0}; uint8_t counter[3] = {0,0,0}; for ( uint8_t i = 0; i<3; ++i) { + ulev1_readTearing(i,tear,sizeof(tear)); ulev1_readCounter(i,counter, sizeof(counter) ); PrintAndLog(" [%0d] : %s", i, sprint_hex(counter,3)); + PrintAndLog(" - %02X tearing %s", tear[0], ( tear[0]==0xBD)?"Ok":"failure"); } return 0; } @@ -439,9 +451,9 @@ static int ulc_magic_test(){ ul_switch_off_field(); return UL_ERROR; } - status = ulc_requestAuthentication(0, nonce1, sizeof(nonce1)); + status = ulc_requestAuthentication(nonce1, sizeof(nonce1)); if ( status > 0 ) { - status = ulc_requestAuthentication(0, nonce2, sizeof(nonce2)); + status = ulc_requestAuthentication(nonce2, sizeof(nonce2)); returnValue = ( !memcmp(nonce1, nonce2, 11) ) ? UL_C_MAGIC : UL_C; } else { returnValue = UL; @@ -458,13 +470,13 @@ static int ul_magic_test(){ iso14a_card_select_t card; int status = ul_select(&card); if ( status < 1 ){ - PrintAndLog("Error: couldn't select ul_magic_test"); + PrintAndLog("iso14443a card select failed"); ul_switch_off_field(); return UL_ERROR; } status = ul_comp_write(0, NULL, 0); ul_switch_off_field(); - if ( status == 0) + if ( status == 0 ) return UL_MAGIC; return UL; } @@ -518,19 +530,17 @@ uint16_t GetHF14AMfU_Type(void){ case -1 : tagtype = (UL | UL_C); break; //when does this happen? default : tagtype = UNKNOWN; break; } + // UL-C test if (tagtype == (UL | UL_C)) { status = ul_select(&card); if ( status < 1 ){ - PrintAndLog("Error: couldn't select 2"); + PrintAndLog("iso14443a card select failed (UL-C)"); ul_switch_off_field(); return UL_ERROR; } uint8_t nonce1[11] = {0x00}; - status = ulc_requestAuthentication(0, nonce1, sizeof(nonce1)); - if ( status > 0 ) - tagtype = UL_C; - else - tagtype = UL; + status = ulc_requestAuthentication(nonce1, sizeof(nonce1)); + tagtype = ( status > 0 ) ? UL_C : UL; if (status != -1) ul_switch_off_field(); } @@ -557,7 +567,51 @@ int CmdHF14AMfUInfo(const char *Cmd){ iso14a_card_select_t card; uint8_t *key; int status; + bool errors = false; + bool hasAuthKey = false; + uint8_t cmdp = 0; + uint8_t datalen = 0; + uint8_t authenticationkey[16] = {0x00}; + uint8_t pack[4] = {0,0,0,0}; + while(param_getchar(Cmd, cmdp) != 0x00) + { + switch(param_getchar(Cmd, cmdp)) + { + case 'h': + case 'H': + return usage_hf_mfu_info(); + case 'k': + case 'K': + // EV1/NTAG size key + datalen = param_gethex(Cmd, cmdp+1, data, 8); + if ( !datalen ) { + memcpy(authenticationkey, data, 4); + cmdp += 2; + hasAuthKey = true; + break; + } + // UL-C size key + datalen = param_gethex(Cmd, cmdp+1, data, 32); + if (!datalen){ + memcpy(authenticationkey, data, 16); + cmdp += 2; + hasAuthKey = true; + break; + } + errors = true; + break; + default: + PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp)); + errors = true; + break; + } + if(errors) break; + } + + //Validations + if(errors) return usage_hf_mfu_info(); + TagTypeUL_t tagtype = GetHF14AMfU_Type(); if (tagtype == UL_ERROR) return -1; @@ -567,11 +621,18 @@ int CmdHF14AMfUInfo(const char *Cmd){ status = ul_select(&card); if ( status < 1 ){ - PrintAndLog("Error: couldn't select"); + PrintAndLog("iso14443a card select failed"); ul_switch_off_field(); return status; } + if ( hasAuthKey ) { + if ((tagtype & UL_C)) + try3DesAuthentication(authenticationkey); + else + ulev1_requestAuthentication(authenticationkey, pack, sizeof(pack)); + } + // read pages 0,1,2,4 (should read 4pages) status = ul_read(0, data, sizeof(data)); if ( status == -1 ){ @@ -587,7 +648,7 @@ int CmdHF14AMfUInfo(const char *Cmd){ uint8_t ulc_conf[16] = {0x00}; status = ul_read(0x28, ulc_conf, sizeof(ulc_conf)); if ( status == -1 ){ - PrintAndLog("Error: tag didn't answer to READ - possibly locked"); + PrintAndLog("Error: tag didn't answer to READ UL-C"); return status; } ulc_print_configuration(ulc_conf); @@ -603,14 +664,17 @@ int CmdHF14AMfUInfo(const char *Cmd){ ulc_print_3deskey(ulc_deskey); } else { + // if we called info with key, just return + if ( hasAuthKey ) return 1; + PrintAndLog("Trying some default 3des keys"); ul_switch_off_field(); - for (uint8_t i = 0; i < 7; ++i ){ + for (uint8_t i = 0; i < KEYS_3DES_COUNT; ++i ){ key = default_3des_keys[i]; if (try3DesAuthentication(key) == 1){ PrintAndLog("Found default 3des key: "); //%s", sprint_hex(key,16)); ulc_print_3deskey(SwapEndian64(key,16)); - return 0; + return 1; } } } @@ -637,6 +701,11 @@ int CmdHF14AMfUInfo(const char *Cmd){ } // save AUTHENTICATION LIMITS for later: authlim = (ulev1_conf[4] & 0x07); + bool allZeros = true; + for (uint8_t idx=0; idx<8; idx++) + if (ulev1_conf[idx]) allZeros = false; + + if (allZeros) authlim=7; ulev1_print_configuration(ulev1_conf); } @@ -650,13 +719,15 @@ int CmdHF14AMfUInfo(const char *Cmd){ } ulev1_print_version(version); + // if we called info with key, just return + if ( hasAuthKey ) return 1; + // AUTHLIMIT, (number of failed authentications) // 0 = limitless. // 1-7 = ... should we even try then? if ( authlim == 0 ){ PrintAndLog("\n--- Known EV1/NTAG passwords."); - uint8_t pack[4] = {0,0,0,0}; int len=0; //if len goes to -1 the connection will be turned off. for (uint8_t i = 0; i < 3; ++i ){ key = default_pwd_pack[i]; @@ -683,7 +754,7 @@ int CmdHF14AMfUInfo(const char *Cmd){ ul_switch_off_field(); PrintAndLog(""); - return 0; + return 1; } // @@ -797,12 +868,29 @@ int CmdHF14AMfURdBl(const char *Cmd){ return 0; } +int usage_hf_mfu_info(void) +{ + PrintAndLog("It gathers information about the tag and tries to detect what kind it is."); + PrintAndLog("Sometimes the tags are locked down, and you may need a key to be able to read the information"); + PrintAndLog("The following tags can be identified:\n"); + PrintAndLog("Ultralight, Ultralight-C, Ultralight EV1"); + PrintAndLog("NTAG 213, NTAG 215, NTAG 216"); + PrintAndLog("my-d, my-d NFC, my-d move, my-d move NFC\n"); + PrintAndLog("Usage: hf mfu info k "); + PrintAndLog(" Options : "); + PrintAndLog(" k : key for authentication [UL-C 16bytes, EV1/NTAG 4bytes]"); + PrintAndLog(""); + PrintAndLog(" sample : hf mfu info"); + PrintAndLog(" : hf mfu info k 11223344"); + return 0; +} + int usage_hf_mfu_dump(void) { PrintAndLog("Reads all pages from Ultralight, Ultralight-C, Ultralight EV1"); PrintAndLog("and saves binary dump into the file `filename.bin` or `cardUID.bin`"); PrintAndLog("It autodetects card type.\n"); - PrintAndLog("Usage: hf mfu dump k n "); + PrintAndLog("Usage: hf mfu dump s k n "); PrintAndLog(" Options : "); PrintAndLog(" k : Enter key for authentication"); PrintAndLog(" n : Enter filename w/o .bin to save the dump as"); @@ -810,8 +898,10 @@ int usage_hf_mfu_dump(void) PrintAndLog(""); PrintAndLog(" sample : hf mfu dump"); PrintAndLog(" : hf mfu dump n myfile"); + PrintAndLog(" : hf mfu dump k 00112233445566778899AABBCCDDEEFF"); return 0; } + // // Mifare Ultralight / Ultralight-C / Ultralight-EV1 // Read and Dump Card Contents, using auto detection of tag size. @@ -1083,7 +1173,6 @@ int CmdHF14AMfucAuth(const char *Cmd){ int try3DesAuthentication( uint8_t *key){ - uint8_t blockNo = 0; uint32_t cuid = 0; des3_context ctx = { 0 }; @@ -1094,7 +1183,7 @@ int try3DesAuthentication( uint8_t *key){ uint8_t rnd_ab[16] = { 0 }; uint8_t iv[8] = { 0 }; - UsbCommand c = {CMD_MIFAREUC_AUTH1, {blockNo}}; + UsbCommand c = {CMD_MIFAREUC_AUTH1, {0x00}}; SendCommand(&c); UsbCommand resp; if ( !WaitForResponseTimeout(CMD_ACK, &resp, 1500) ) return -1; diff --git a/client/cmdhfmfu.h b/client/cmdhfmfu.h index 23f97cac3..0ec82b2dc 100644 --- a/client/cmdhfmfu.h +++ b/client/cmdhfmfu.h @@ -13,19 +13,22 @@ int CmdHF14AMfUCRdBl(const char *Cmd); int CmdHF14AMfUCRdCard(const char *Cmd); int CmdHF14AMfucAuth(const char *Cmd); -//general stuff -int CmdHF14AMfUDump(const char *Cmd); -void rol (uint8_t *data, const size_t len); - uint8_t requestAuthentication( uint8_t *nonce); int try3DesAuthentication( uint8_t *key); + +//general stuff +int CmdHF14AMfUDump(const char *Cmd); +int CmdHF14AMfUInfo(const char *Cmd); uint16_t GetHF14AMfU_Type(void); + +void rol (uint8_t *data, const size_t len); int ul_print_type(uint16_t tagtype, uint8_t spacer); +void ul_switch_off_field(void); int usage_hf_mfu_dump(void); +int usage_hf_mfu_info(void); int CmdHFMFUltra(const char *Cmd); -int CmdHF14AMfUInfo(const char *Cmd); typedef enum TAGTYPE_UL { UNKNOWN = 0x0000, From 2b3af97df2b9368ea02cab49898b931d1c3d0598 Mon Sep 17 00:00:00 2001 From: marshmellow42 Date: Wed, 13 May 2015 11:07:47 -0400 Subject: [PATCH 24/49] various bug fixes --- armsrc/lfops.c | 2 +- client/cmddata.c | 4 ++-- client/cmddata.h | 2 +- client/cmdhfmfu.c | 10 ++++++---- client/util.c | 14 ++++++++------ client/util.h | 2 +- 6 files changed, 19 insertions(+), 15 deletions(-) diff --git a/armsrc/lfops.c b/armsrc/lfops.c index e45b55fcb..c3fa8a0e6 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -651,7 +651,7 @@ void CmdASKsimTag(uint16_t arg1, uint16_t arg2, size_t size, uint8_t *BitStream) int ledcontrol = 1; int n=0, i=0; uint8_t clk = (arg1 >> 8) & 0xFF; - uint8_t encoding = arg1 & 1; + uint8_t encoding = arg1 & 0xFF; uint8_t separator = arg2 & 1; uint8_t invert = (arg2 >> 8) & 1; diff --git a/client/cmddata.c b/client/cmddata.c index 556ede06b..3ea756135 100644 --- a/client/cmddata.c +++ b/client/cmddata.c @@ -26,7 +26,7 @@ uint8_t DemodBuffer[MAX_DEMOD_BUF_LEN]; uint8_t g_debugMode; -int DemodBufferLen; +size_t DemodBufferLen; static int CmdHelp(const char *Cmd); //set the demod buffer with given array of binary (one bit per byte) @@ -1484,7 +1484,7 @@ int CmdIndalaDecode(const char *Cmd) return 0; } uint8_t invert=0; - ans = indala26decode(DemodBuffer,(size_t *) &DemodBufferLen, &invert); + ans = indala26decode(DemodBuffer, &DemodBufferLen, &invert); if (ans < 1) { if (g_debugMode==1) PrintAndLog("Error2: %d",ans); diff --git a/client/cmddata.h b/client/cmddata.h index 57f040012..c62307368 100644 --- a/client/cmddata.h +++ b/client/cmddata.h @@ -70,7 +70,7 @@ int getSamples(const char *Cmd, bool silent); #define MAX_DEMOD_BUF_LEN (1024*128) extern uint8_t DemodBuffer[MAX_DEMOD_BUF_LEN]; -extern int DemodBufferLen; +extern size_t DemodBufferLen; extern uint8_t g_debugMode; #define BIGBUF_SIZE 40000 diff --git a/client/cmdhfmfu.c b/client/cmdhfmfu.c index 7b9367922..e7b90b4c8 100644 --- a/client/cmdhfmfu.c +++ b/client/cmdhfmfu.c @@ -340,7 +340,7 @@ static int ulc_print_3deskey( uint8_t *data){ PrintAndLog(" deskey1 [45/0x2D]: %s [%.4s]", sprint_hex(data+4 ,4),data+4); PrintAndLog(" deskey2 [46/0x2E]: %s [%.4s]", sprint_hex(data+8 ,4),data+8); PrintAndLog(" deskey2 [47/0x2F]: %s [%.4s]", sprint_hex(data+12,4),data+12); - PrintAndLog("\n 3des key : %s", sprint_hex(SwapEndian64(data, 16), 16)); + PrintAndLog("\n 3des key : %s", sprint_hex(SwapEndian64(data, 16, 8), 16)); return 0; } @@ -673,7 +673,9 @@ int CmdHF14AMfUInfo(const char *Cmd){ key = default_3des_keys[i]; if (try3DesAuthentication(key) == 1){ PrintAndLog("Found default 3des key: "); //%s", sprint_hex(key,16)); - ulc_print_3deskey(SwapEndian64(key,16)); + uint8_t keySwap[16]; + memcpy(keySwap, SwapEndian64(key,16,8), 16); + ulc_print_3deskey(keySwap); return 1; } } @@ -973,7 +975,7 @@ int CmdHF14AMfUDump(const char *Cmd){ if(errors) return usage_hf_mfu_dump(); if (swapEndian) - keyPtr = SwapEndian64(data, 16); + keyPtr = SwapEndian64(data, 16, 8); TagTypeUL_t tagtype = GetHF14AMfU_Type(); if (tagtype == UL_ERROR) return -1; @@ -1369,7 +1371,7 @@ int CmdHF14AMfUCRdBl(const char *Cmd) hasPwd = TRUE; } } - //uint8_t *key2 = SwapEndian64(key, 16); + //uint8_t *key2 = SwapEndian64(key, 16, 8); //Read Block UsbCommand c = {CMD_MIFAREU_READBL, {blockNo}}; diff --git a/client/util.c b/client/util.c index 548234226..0dd6905e7 100644 --- a/client/util.c +++ b/client/util.c @@ -164,14 +164,16 @@ uint64_t bytes_to_num(uint8_t* src, size_t len) // to // hh,gg,ff,ee,dd,cc,bb,aa, pp,oo,nn,mm,ll,kk,jj,ii // up to 64 bytes or 512 bits -uint8_t *SwapEndian64(uint8_t *src, size_t len){ - static uint8_t temp[64]={0}; - for (uint8_t block=0; block < (uint8_t)len/8; block++){ - for (size_t i = 0; i < 8; i++){ - temp[i+(8*block)] = src[(7-i)+(8*block)]; +uint8_t *SwapEndian64(const uint8_t *src, const size_t len, const uint8_t blockSize){ + static uint8_t buf[64]; + memset(buf, 0x00, 64); + uint8_t *tmp = buf; + for (uint8_t block=0; block < (uint8_t)(len/blockSize); block++){ + for (size_t i = 0; i < blockSize; i++){ + tmp[i+(blockSize*block)] = src[(blockSize-1-i)+(blockSize*block)]; } } - return temp; + return tmp; } //assumes little endian diff --git a/client/util.h b/client/util.h index fb587da0b..f58f64cb4 100644 --- a/client/util.h +++ b/client/util.h @@ -44,7 +44,7 @@ char * sprint_bin_break(const uint8_t *data, const size_t len, const uint8_t bre void num_to_bytes(uint64_t n, size_t len, uint8_t* dest); uint64_t bytes_to_num(uint8_t* src, size_t len); char * printBits(size_t const size, void const * const ptr); -uint8_t *SwapEndian64(uint8_t *src, size_t len); +uint8_t *SwapEndian64(const uint8_t *src, const size_t len, const uint8_t blockSize); char param_getchar(const char *line, int paramnum); uint8_t param_get8(const char *line, int paramnum); From e6432f05795ba0eaf1e34bb47b2a7f87a762de29 Mon Sep 17 00:00:00 2001 From: marshmellow42 Date: Wed, 13 May 2015 11:14:17 -0400 Subject: [PATCH 25/49] @iceman1001 s coverity scan fixes --- client/cmddata.c | 2 +- client/cmdhfmf.c | 10 ++++++---- client/cmdhfmfu.c | 2 +- client/cmdscript.c | 2 +- client/mifarehost.c | 10 ++-------- client/scripting.c | 1 + client/util.c | 2 +- 7 files changed, 13 insertions(+), 16 deletions(-) diff --git a/client/cmddata.c b/client/cmddata.c index 3ea756135..b9069bc19 100644 --- a/client/cmddata.c +++ b/client/cmddata.c @@ -1892,7 +1892,7 @@ int getSamples(const char *Cmd, bool silent) PrintAndLog("Unpacking..."); BitstreamOut bout = { got, bits_per_sample * n, 0}; int j =0; - for (j = 0; j * bits_per_sample < n * 8 && j < sizeof(GraphBuffer); j++) { + for (j = 0; j * bits_per_sample < n * 8 && j < n; j++) { uint8_t sample = getByte(bits_per_sample, &bout); GraphBuffer[j] = ((int) sample )- 128; } diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index b96c9c1a7..aa3b66dc6 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -547,7 +547,7 @@ int CmdHF14AMfNested(const char *Cmd) uint8_t trgKeyType = 0; uint8_t SectorsCnt = 0; uint8_t key[6] = {0, 0, 0, 0, 0, 0}; - uint8_t keyBlock[13*6]; + uint8_t keyBlock[14*6]; uint64_t key64 = 0; bool transferToEml = false; @@ -1202,7 +1202,7 @@ int CmdHF14AMfELoad(const char *Cmd) if (len > FILE_PATH_SIZE) len = FILE_PATH_SIZE; - fnameptr += len; + fnameptr += len-4; sprintf(fnameptr, ".eml"); @@ -1311,7 +1311,7 @@ int CmdHF14AMfESave(const char *Cmd) for (j = 0; j < 7; j++, fnameptr += 2) sprintf(fnameptr, "%02X", buf[j]); } else { - fnameptr += len; + fnameptr += len-4; } // add file extension @@ -1575,7 +1575,7 @@ int CmdHF14AMfCLoad(const char *Cmd) if (len > FILE_PATH_SIZE) len = FILE_PATH_SIZE; memcpy(filename, Cmd, len); - fnameptr += len; + fnameptr += len-4; sprintf(fnameptr, ".eml"); @@ -1592,6 +1592,7 @@ int CmdHF14AMfCLoad(const char *Cmd) memset(buf, 0, sizeof(buf)); if (fgets(buf, sizeof(buf), f) == NULL) { + fclose(f); PrintAndLog("File reading error."); return 2; } @@ -1600,6 +1601,7 @@ int CmdHF14AMfCLoad(const char *Cmd) if(strlen(buf) && feof(f)) break; PrintAndLog("File content error. Block data must include 32 HEX symbols"); + fclose(f); return 2; } for (i = 0; i < 32; i += 2) diff --git a/client/cmdhfmfu.c b/client/cmdhfmfu.c index e7b90b4c8..112828574 100644 --- a/client/cmdhfmfu.c +++ b/client/cmdhfmfu.c @@ -1103,7 +1103,7 @@ int CmdHF14AMfUDump(const char *Cmd){ sprintf(fnameptr,"%02X%02X%02X%02X%02X%02X%02X.bin", data[0],data[1], data[2], data[4],data[5],data[6], data[7]); } else { - sprintf(fnameptr + fileNlen," .bin"); + sprintf(fnameptr + fileNlen,".bin"); } if ((fout = fopen(filename,"wb")) == NULL) { diff --git a/client/cmdscript.c b/client/cmdscript.c index 928a216d7..730f4e96a 100644 --- a/client/cmdscript.c +++ b/client/cmdscript.c @@ -83,7 +83,7 @@ int CmdList(const char *Cmd) { while ((ep = readdir (dp)) != NULL) { - if(ep->d_name != NULL && str_ends_with(ep->d_name, ".lua")) + if(str_ends_with(ep->d_name, ".lua")) PrintAndLog("%-16s %s", ep->d_name, "A script file"); } (void) closedir (dp); diff --git a/client/mifarehost.c b/client/mifarehost.c index 35499b836..237979c1b 100644 --- a/client/mifarehost.c +++ b/client/mifarehost.c @@ -354,10 +354,7 @@ int loadTraceCard(uint8_t *tuid) { FillFileNameByUID(traceFileName, tuid, ".eml", 7); f = fopen(traceFileName, "r"); - if (!f) { - fclose(f); - return 1; - } + if (!f) return 1; blockNum = 0; @@ -394,10 +391,7 @@ int saveTraceCard(void) { if ((!strlen(traceFileName)) || (isTraceCardEmpty())) return 0; f = fopen(traceFileName, "w+"); - if ( !f ) { - fclose(f); - return 1; - } + if ( !f ) return 1; for (int i = 0; i < 64; i++) { // blocks for (int j = 0; j < 16; j++) // bytes diff --git a/client/scripting.c b/client/scripting.c index d7f51c234..a7cf27d74 100644 --- a/client/scripting.c +++ b/client/scripting.c @@ -298,6 +298,7 @@ int setLuaPath( lua_State* L, const char* path ) lua_pushstring( L, buf ); // push the new one lua_setfield( L, -2, "path" ); // set the field "path" in table at -2 with value at top of stack lua_pop( L, 1 ); // get rid of package table from top of stack + free(buf); return 0; // all done! } diff --git a/client/util.c b/client/util.c index 0dd6905e7..cea9f7d73 100644 --- a/client/util.c +++ b/client/util.c @@ -124,7 +124,7 @@ char * sprint_hex(const uint8_t * data, const size_t len) { char *sprint_bin_break(const uint8_t *data, const size_t len, const uint8_t breaks) { - int maxLen = ( len > 1024) ? 1024 : len; + int maxLen = ( len > 1020) ? 1020 : len; static char buf[1024]; memset(buf, 0x00, 1024); char *tmp = buf; From 6fdf42c61cd4c1a71c2b1de2887e28ed33b4cd70 Mon Sep 17 00:00:00 2001 From: marshmellow42 Date: Wed, 13 May 2015 11:22:27 -0400 Subject: [PATCH 26/49] minor hf mfu info adjustment from @iceman1001 --- client/cmdhfmfu.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/client/cmdhfmfu.c b/client/cmdhfmfu.c index 112828574..d80608947 100644 --- a/client/cmdhfmfu.c +++ b/client/cmdhfmfu.c @@ -271,9 +271,14 @@ static int ul_print_default( uint8_t *data){ PrintAndLog(" BCC1 : %02X - crc should be %02X", data[8], crc1 ); PrintAndLog(" Internal : %02X - %s default", data[9], (data[9]==0x48)?"":"not" ); - PrintAndLog(" Lock : %s - %s", sprint_hex(data+10, 2),printBits( 2, data+10) ); - PrintAndLog("OneTimePad : %s ", sprint_hex(data + 12, 4)); - PrintAndLog(""); + PrintAndLog(" Lock : %s - %s", + sprint_hex(data+10, 2), + printBits(2, data+10) + ); + PrintAndLog("OneTimePad : %s - %s\n", + sprint_hex(data + 12, 4), + printBits(4, data+12) + ); return 0; } From d730878d8c932cdbdd1c386e8491af27f3764dae Mon Sep 17 00:00:00 2001 From: marshmellow42 Date: Wed, 13 May 2015 21:14:35 -0400 Subject: [PATCH 27/49] scripting updates from @iceman1001 it compiles but i'm not sure how to fully test it... :) --- client/Makefile | 1 + client/scripting.c | 419 +++++++++++++++++++++++++-------------------- common/crc64.c | 85 +++++++++ common/crc64.h | 14 ++ 4 files changed, 332 insertions(+), 187 deletions(-) create mode 100644 common/crc64.c create mode 100644 common/crc64.h diff --git a/client/Makefile b/client/Makefile index 81af01499..7954d1ea2 100644 --- a/client/Makefile +++ b/client/Makefile @@ -68,6 +68,7 @@ CMDSRCS = nonce2key/crapto1.c\ mifarehost.c\ crc.c \ crc16.c \ + crc64.c \ iso14443crc.c \ iso15693tools.c \ data.c \ diff --git a/client/scripting.c b/client/scripting.c index a7cf27d74..152fd9d44 100644 --- a/client/scripting.c +++ b/client/scripting.c @@ -19,6 +19,7 @@ #include "nonce2key/nonce2key.h" #include "../common/iso15693tools.h" #include "../common/crc16.h" +#include "../common/crc64.h" #include "aes.h" /** * The following params expected: @@ -29,34 +30,34 @@ */ static int l_SendCommand(lua_State *L){ - /* - * - The SendCommand (native) expects the following structure: + /* + * + The SendCommand (native) expects the following structure: - typedef struct { - uint64_t cmd; //8 bytes - uint64_t arg[3]; // 8*3 bytes = 24 bytes - union { - uint8_t asBytes[USB_CMD_DATA_SIZE]; // 1 byte * 512 = 512 bytes (OR) - uint32_t asDwords[USB_CMD_DATA_SIZE/4]; // 4 byte * 128 = 512 bytes - } d; - } PACKED UsbCommand; + typedef struct { + uint64_t cmd; //8 bytes + uint64_t arg[3]; // 8*3 bytes = 24 bytes + union { + uint8_t asBytes[USB_CMD_DATA_SIZE]; // 1 byte * 512 = 512 bytes (OR) + uint32_t asDwords[USB_CMD_DATA_SIZE/4]; // 4 byte * 128 = 512 bytes + } d; + } PACKED UsbCommand; - ==> A 544 byte buffer will do. - **/ - //Pop cmd - size_t size; - const char *data = luaL_checklstring(L, 1, &size); - if(size != sizeof(UsbCommand)) - { - printf("Got data size %d, expected %d" , (int) size,(int) sizeof(UsbCommand)); - lua_pushstring(L,"Wrong data size"); - return 1; - } + ==> A 544 byte buffer will do. + **/ + //Pop cmd + size_t size; + const char *data = luaL_checklstring(L, 1, &size); + if(size != sizeof(UsbCommand)) + { + printf("Got data size %d, expected %d" , (int) size,(int) sizeof(UsbCommand)); + lua_pushstring(L,"Wrong data size"); + return 1; + } // UsbCommand c = (*data); - SendCommand((UsbCommand* )data); - return 0; // no return values + SendCommand((UsbCommand* )data); + return 0; // no return values } /** * @brief The following params expected: @@ -67,105 +68,105 @@ static int l_SendCommand(lua_State *L){ */ static int l_WaitForResponseTimeout(lua_State *L){ - uint32_t cmd = 0; - size_t ms_timeout = -1; + uint32_t cmd = 0; + size_t ms_timeout = -1; - //Check number of arguments - int n = lua_gettop(L); - if(n == 0) - { - //signal error by returning Nil, errorstring - lua_pushnil(L); - lua_pushstring(L,"You need to supply at least command to wait for"); - return 2; // two return values - } - if(n >= 1) - { - //pop cmd - cmd = luaL_checkunsigned(L,1); - } - if(n >= 2) - { - //Did the user send a timeout ? - //Check if the current top of stack is an integer - ms_timeout = luaL_checkunsigned(L,2); - //printf("Timeout set to %dms\n" , (int) ms_timeout); - } + //Check number of arguments + int n = lua_gettop(L); + if(n == 0) + { + //signal error by returning Nil, errorstring + lua_pushnil(L); + lua_pushstring(L,"You need to supply at least command to wait for"); + return 2; // two return values + } + if(n >= 1) + { + //pop cmd + cmd = luaL_checkunsigned(L,1); + } + if(n >= 2) + { + //Did the user send a timeout ? + //Check if the current top of stack is an integer + ms_timeout = luaL_checkunsigned(L,2); + //printf("Timeout set to %dms\n" , (int) ms_timeout); + } - UsbCommand response; + UsbCommand response; - if(WaitForResponseTimeout(cmd, &response, ms_timeout)) - { - //Push it as a string - lua_pushlstring(L,(const char *)&response,sizeof(UsbCommand)); + if(WaitForResponseTimeout(cmd, &response, ms_timeout)) + { + //Push it as a string + lua_pushlstring(L,(const char *)&response,sizeof(UsbCommand)); - return 1;// return 1 to signal one return value - }else{ - //Push a Nil instead - lua_pushnil(L); - return 1;// one return value - } + return 1;// return 1 to signal one return value + }else{ + //Push a Nil instead + lua_pushnil(L); + return 1;// one return value + } } static int returnToLuaWithError(lua_State *L, const char* fmt, ...) { - char buffer[200]; - va_list args; - va_start(args,fmt); - vsnprintf(buffer, sizeof(buffer), fmt,args); - va_end(args); + char buffer[200]; + va_list args; + va_start(args,fmt); + vsnprintf(buffer, sizeof(buffer), fmt,args); + va_end(args); - lua_pushnil(L); - lua_pushstring(L,buffer); - return 2; + lua_pushnil(L); + lua_pushstring(L,buffer); + return 2; } static int l_nonce2key(lua_State *L){ - size_t size; - const char *p_uid = luaL_checklstring(L, 1, &size); - if(size != 4) return returnToLuaWithError(L,"Wrong size of uid, got %d bytes, expected 4", (int) size); + size_t size; + const char *p_uid = luaL_checklstring(L, 1, &size); + if(size != 4) return returnToLuaWithError(L,"Wrong size of uid, got %d bytes, expected 4", (int) size); - const char *p_nt = luaL_checklstring(L, 2, &size); - if(size != 4) return returnToLuaWithError(L,"Wrong size of nt, got %d bytes, expected 4", (int) size); + const char *p_nt = luaL_checklstring(L, 2, &size); + if(size != 4) return returnToLuaWithError(L,"Wrong size of nt, got %d bytes, expected 4", (int) size); - const char *p_nr = luaL_checklstring(L, 3, &size); - if(size != 4) return returnToLuaWithError(L,"Wrong size of nr, got %d bytes, expected 4", (int) size); + const char *p_nr = luaL_checklstring(L, 3, &size); + if(size != 4) return returnToLuaWithError(L,"Wrong size of nr, got %d bytes, expected 4", (int) size); - const char *p_par_info = luaL_checklstring(L, 4, &size); - if(size != 8) return returnToLuaWithError(L,"Wrong size of par_info, got %d bytes, expected 8", (int) size); + const char *p_par_info = luaL_checklstring(L, 4, &size); + if(size != 8) return returnToLuaWithError(L,"Wrong size of par_info, got %d bytes, expected 8", (int) size); - const char *p_pks_info = luaL_checklstring(L, 5, &size); - if(size != 8) return returnToLuaWithError(L,"Wrong size of ks_info, got %d bytes, expected 8", (int) size); + const char *p_pks_info = luaL_checklstring(L, 5, &size); + if(size != 8) return returnToLuaWithError(L,"Wrong size of ks_info, got %d bytes, expected 8", (int) size); - uint32_t uid = bytes_to_num(( uint8_t *)p_uid,4); - uint32_t nt = bytes_to_num(( uint8_t *)p_nt,4); + uint32_t uid = bytes_to_num(( uint8_t *)p_uid,4); + uint32_t nt = bytes_to_num(( uint8_t *)p_nt,4); - uint32_t nr = bytes_to_num(( uint8_t*)p_nr,4); - uint64_t par_info = bytes_to_num(( uint8_t *)p_par_info,8); - uint64_t ks_info = bytes_to_num(( uint8_t *)p_pks_info,8); + uint32_t nr = bytes_to_num(( uint8_t*)p_nr,4); + uint64_t par_info = bytes_to_num(( uint8_t *)p_par_info,8); + uint64_t ks_info = bytes_to_num(( uint8_t *)p_pks_info,8); - uint64_t key = 0; + uint64_t key = 0; - int retval = nonce2key(uid,nt, nr, par_info,ks_info, &key); + int retval = nonce2key(uid,nt, nr, par_info,ks_info, &key); - //Push the retval on the stack - lua_pushinteger(L,retval); - - //Push the key onto the stack - uint8_t dest_key[8]; - num_to_bytes(key,sizeof(dest_key),dest_key); + //Push the retval on the stack + lua_pushinteger(L,retval); - //printf("Pushing to lua stack: %012"llx"\n",key); - lua_pushlstring(L,(const char *) dest_key,sizeof(dest_key)); + //Push the key onto the stack + uint8_t dest_key[8]; + num_to_bytes(key,sizeof(dest_key),dest_key); - return 2; //Two return values + //printf("Pushing to lua stack: %012"llx"\n",key); + lua_pushlstring(L,(const char *) dest_key,sizeof(dest_key)); + + return 2; //Two return values } //static int l_PrintAndLog(lua_State *L){ return CmdHF14AMfDump(luaL_checkstring(L, 1));} static int l_clearCommandBuffer(lua_State *L){ - clearCommandBuffer(); - return 0; + clearCommandBuffer(); + return 0; } /** * @brief l_foobar is a dummy function to test lua-integration with @@ -174,23 +175,23 @@ static int l_clearCommandBuffer(lua_State *L){ */ static int l_foobar(lua_State *L) { - //Check number of arguments - int n = lua_gettop(L); - printf("foobar called with %d arguments" , n); - lua_settop(L, 0); - printf("Arguments discarded, stack now contains %d elements", lua_gettop(L)); - - // todo: this is not used, where was it intended for? - // UsbCommand response = {CMD_MIFARE_READBL, {1337, 1338, 1339}}; - - printf("Now returning a uint64_t as a string"); - uint64_t x = 0xDEADBEEF; - uint8_t destination[8]; - num_to_bytes(x,sizeof(x),destination); - lua_pushlstring(L,(const char *)&x,sizeof(x)); - lua_pushlstring(L,(const char *)destination,sizeof(destination)); + //Check number of arguments + int n = lua_gettop(L); + printf("foobar called with %d arguments" , n); + lua_settop(L, 0); + printf("Arguments discarded, stack now contains %d elements", lua_gettop(L)); - return 2; + // todo: this is not used, where was it intended for? + // UsbCommand response = {CMD_MIFARE_READBL, {1337, 1338, 1339}}; + + printf("Now returning a uint64_t as a string"); + uint64_t x = 0xDEADBEEF; + uint8_t destination[8]; + num_to_bytes(x,sizeof(x),destination); + lua_pushlstring(L,(const char *)&x,sizeof(x)); + lua_pushlstring(L,(const char *)destination,sizeof(destination)); + + return 2; } @@ -201,8 +202,8 @@ static int l_foobar(lua_State *L) */ static int l_ukbhit(lua_State *L) { - lua_pushboolean(L,ukbhit() ? true : false); - return 1; + lua_pushboolean(L,ukbhit() ? true : false); + return 1; } /** * @brief Calls the command line parser to deal with the command. This enables @@ -212,58 +213,78 @@ static int l_ukbhit(lua_State *L) */ static int l_CmdConsole(lua_State *L) { - CommandReceived((char *)luaL_checkstring(L, 1)); - return 0; + CommandReceived((char *)luaL_checkstring(L, 1)); + return 0; } static int l_iso15693_crc(lua_State *L) { - // uint16_t Iso15693Crc(uint8_t *v, int n); - size_t size; - const char *v = luaL_checklstring(L, 1, &size); - uint16_t retval = Iso15693Crc((uint8_t *) v, size); - lua_pushinteger(L, (int) retval); - return 1; + // uint16_t Iso15693Crc(uint8_t *v, int n); + size_t size; + const char *v = luaL_checklstring(L, 1, &size); + uint16_t retval = Iso15693Crc((uint8_t *) v, size); + lua_pushinteger(L, (int) retval); + return 1; } /* Simple AES 128 cbc hook up to OpenSSL. params: key, input */ -static int l_aes(lua_State *L) +static int l_aes128decrypt(lua_State *L) { //Check number of arguments int i; - size_t size; - const char *p_key = luaL_checklstring(L, 1, &size); - if(size != 32) return returnToLuaWithError(L,"Wrong size of key, got %d bytes, expected 32", (int) size); + size_t size; + const char *p_key = luaL_checklstring(L, 1, &size); + if(size != 32) return returnToLuaWithError(L,"Wrong size of key, got %d bytes, expected 32", (int) size); + + const char *p_encTxt = luaL_checklstring(L, 2, &size); - const char *p_encTxt = luaL_checklstring(L, 2, &size); - unsigned char indata[16] = {0x00}; unsigned char outdata[16] = {0x00}; - unsigned char aes_key[16] = {0x00}; + unsigned char aes_key[16] = {0x00}; unsigned char iv[16] = {0x00}; - - // convert key to bytearray + + // convert key to bytearray and convert input to bytearray for (i = 0; i < 32; i += 2) { sscanf(&p_encTxt[i], "%02x", (unsigned int *)&indata[i / 2]); - } - - // convert input to bytearray - for (i = 0; i < 32; i += 2) { sscanf(&p_key[i], "%02x", (unsigned int *)&aes_key[i / 2]); } - - //AES_KEY key; - //AES_set_decrypt_key(aes_key, 128, &key); - //AES_cbc_encrypt(indata, outdata, sizeof(indata), &key, iv, AES_DECRYPT); - aes_context ctx; - aes_init(&ctx); - aes_setkey_dec(&ctx, aes_key, 128); + aes_context ctx; + aes_init(&ctx); + aes_setkey_dec(&ctx, aes_key, 128); aes_crypt_cbc(&ctx,AES_DECRYPT,sizeof(indata), iv, indata,outdata ); - //Push decrypted array as a string + //Push decrypted array as a string + lua_pushlstring(L,(const char *)&outdata, sizeof(outdata)); + return 1;// return 1 to signal one return value +} +static int l_aes128encrypt(lua_State *L) +{ + //Check number of arguments + int i; + size_t size; + const char *p_key = luaL_checklstring(L, 1, &size); + if(size != 32) return returnToLuaWithError(L,"Wrong size of key, got %d bytes, expected 32", (int) size); + + const char *p_txt = luaL_checklstring(L, 2, &size); + + unsigned char indata[16] = {0x00}; + unsigned char outdata[16] = {0x00}; + unsigned char aes_key[16] = {0x00}; + unsigned char iv[16] = {0x00}; + + for (i = 0; i < 32; i += 2) { + sscanf(&p_txt[i], "%02x", (unsigned int *)&indata[i / 2]); + sscanf(&p_key[i], "%02x", (unsigned int *)&aes_key[i / 2]); + } + + aes_context ctx; + aes_init(&ctx); + aes_setkey_enc(&ctx, aes_key, 128); + aes_crypt_cbc(&ctx, AES_ENCRYPT, sizeof(indata), iv, indata, outdata ); + //Push encrypted array as a string lua_pushlstring(L,(const char *)&outdata, sizeof(outdata)); return 1;// return 1 to signal one return value } @@ -272,10 +293,32 @@ static int l_crc16(lua_State *L) { size_t size; const char *p_str = luaL_checklstring(L, 1, &size); - + uint16_t retval = crc16_ccitt( (uint8_t*) p_str, size); - lua_pushinteger(L, (int) retval); - return 1; + lua_pushinteger(L, (int) retval); + return 1; +} + +static int l_crc64(lua_State *L) +{ + size_t size; + uint64_t crc = 0; + unsigned char outdata[8] = {0x00}; + + const char *p_str = luaL_checklstring(L, 1, &size); + + crc64( (uint8_t*) p_str, size, &crc); + + outdata[0] = (uint8_t)(crc >> 56) & 0xff; + outdata[1] = (uint8_t)(crc >> 48) & 0xff; + outdata[2] = (uint8_t)(crc >> 40) & 0xff; + outdata[3] = (uint8_t)(crc >> 32) & 0xff; + outdata[4] = (uint8_t)(crc >> 24) & 0xff; + outdata[5] = (uint8_t)(crc >> 16) & 0xff; + outdata[6] = (uint8_t)(crc >> 8) & 0xff; + outdata[7] = crc & 0xff; + lua_pushlstring(L,(const char *)&outdata, sizeof(outdata)); + return 1; } /** @@ -288,58 +331,60 @@ static int l_crc16(lua_State *L) */ int setLuaPath( lua_State* L, const char* path ) { - lua_getglobal( L, "package" ); - lua_getfield( L, -1, "path" ); // get field "path" from table at top of stack (-1) - const char* cur_path = lua_tostring( L, -1 ); // grab path string from top of stack - int requiredLength = strlen(cur_path)+ strlen(path)+10; //A few bytes too many, whatever we can afford it - char * buf = malloc(requiredLength); - snprintf(buf, requiredLength, "%s;%s", cur_path, path); - lua_pop( L, 1 ); // get rid of the string on the stack we just pushed on line 5 - lua_pushstring( L, buf ); // push the new one - lua_setfield( L, -2, "path" ); // set the field "path" in table at -2 with value at top of stack - lua_pop( L, 1 ); // get rid of package table from top of stack - free(buf); - return 0; // all done! + lua_getglobal( L, "package" ); + lua_getfield( L, -1, "path" ); // get field "path" from table at top of stack (-1) + const char* cur_path = lua_tostring( L, -1 ); // grab path string from top of stack + int requiredLength = strlen(cur_path)+ strlen(path)+10; //A few bytes too many, whatever we can afford it + char * buf = malloc(requiredLength); + snprintf(buf, requiredLength, "%s;%s", cur_path, path); + lua_pop( L, 1 ); // get rid of the string on the stack we just pushed on line 5 + lua_pushstring( L, buf ); // push the new one + lua_setfield( L, -2, "path" ); // set the field "path" in table at -2 with value at top of stack + lua_pop( L, 1 ); // get rid of package table from top of stack + free(buf); + return 0; // all done! } int set_pm3_libraries(lua_State *L) { - static const luaL_Reg libs[] = { - {"SendCommand", l_SendCommand}, - {"WaitForResponseTimeout", l_WaitForResponseTimeout}, - {"nonce2key", l_nonce2key}, - //{"PrintAndLog", l_PrintAndLog}, - {"foobar", l_foobar}, - {"ukbhit", l_ukbhit}, - {"clearCommandBuffer", l_clearCommandBuffer}, - {"console", l_CmdConsole}, - {"iso15693_crc", l_iso15693_crc}, - {"aes", l_aes}, + static const luaL_Reg libs[] = { + {"SendCommand", l_SendCommand}, + {"WaitForResponseTimeout", l_WaitForResponseTimeout}, + {"nonce2key", l_nonce2key}, + //{"PrintAndLog", l_PrintAndLog}, + {"foobar", l_foobar}, + {"ukbhit", l_ukbhit}, + {"clearCommandBuffer", l_clearCommandBuffer}, + {"console", l_CmdConsole}, + {"iso15693_crc", l_iso15693_crc}, + {"aes128_decrypt", l_aes128decrypt}, + {"aes128_encrypt", l_aes128encrypt}, {"crc16", l_crc16}, - {NULL, NULL} - }; + {"crc64", l_crc64}, + {NULL, NULL} + }; - lua_pushglobaltable(L); - // Core library is in this table. Contains ' - //this is 'pm3' table - lua_newtable(L); + lua_pushglobaltable(L); + // Core library is in this table. Contains ' + //this is 'pm3' table + lua_newtable(L); - //Put the function into the hash table. - for (int i = 0; libs[i].name; i++) { - lua_pushcfunction(L, libs[i].func); - lua_setfield(L, -2, libs[i].name);//set the name, pop stack - } - //Name of 'core' - lua_setfield(L, -2, "core"); + //Put the function into the hash table. + for (int i = 0; libs[i].name; i++) { + lua_pushcfunction(L, libs[i].func); + lua_setfield(L, -2, libs[i].name);//set the name, pop stack + } + //Name of 'core' + lua_setfield(L, -2, "core"); - //-- remove the global environment table from the stack - lua_pop(L, 1); + //-- remove the global environment table from the stack + lua_pop(L, 1); - //-- Last but not least, add to the LUA_PATH (package.path in lua) - // so we can load libraries from the ./lualib/ - directory - setLuaPath(L,"./lualibs/?.lua"); + //-- Last but not least, add to the LUA_PATH (package.path in lua) + // so we can load libraries from the ./lualib/ - directory + setLuaPath(L,"./lualibs/?.lua"); - return 1; + return 1; } diff --git a/common/crc64.c b/common/crc64.c new file mode 100644 index 000000000..709c64d67 --- /dev/null +++ b/common/crc64.c @@ -0,0 +1,85 @@ +#include +#include +#include "crc64.h" + +#define CRC64_ISO_PRESET 0xFFFFFFFFFFFFFFFF +#define CRC64_ECMA_PRESET 0x0000000000000000 + +const uint64_t crc64_table[] = { + 0x0000000000000000, 0x42F0E1EBA9EA3693, 0x85E1C3D753D46D26, 0xC711223CFA3E5BB5, + 0x493366450E42ECDF, 0x0BC387AEA7A8DA4C, 0xCCD2A5925D9681F9, 0x8E224479F47CB76A, + 0x9266CC8A1C85D9BE, 0xD0962D61B56FEF2D, 0x17870F5D4F51B498, 0x5577EEB6E6BB820B, + 0xDB55AACF12C73561, 0x99A54B24BB2D03F2, 0x5EB4691841135847, 0x1C4488F3E8F96ED4, + 0x663D78FF90E185EF, 0x24CD9914390BB37C, 0xE3DCBB28C335E8C9, 0xA12C5AC36ADFDE5A, + 0x2F0E1EBA9EA36930, 0x6DFEFF5137495FA3, 0xAAEFDD6DCD770416, 0xE81F3C86649D3285, + 0xF45BB4758C645C51, 0xB6AB559E258E6AC2, 0x71BA77A2DFB03177, 0x334A9649765A07E4, + 0xBD68D2308226B08E, 0xFF9833DB2BCC861D, 0x388911E7D1F2DDA8, 0x7A79F00C7818EB3B, + 0xCC7AF1FF21C30BDE, 0x8E8A101488293D4D, 0x499B3228721766F8, 0x0B6BD3C3DBFD506B, + 0x854997BA2F81E701, 0xC7B97651866BD192, 0x00A8546D7C558A27, 0x4258B586D5BFBCB4, + 0x5E1C3D753D46D260, 0x1CECDC9E94ACE4F3, 0xDBFDFEA26E92BF46, 0x990D1F49C77889D5, + 0x172F5B3033043EBF, 0x55DFBADB9AEE082C, 0x92CE98E760D05399, 0xD03E790CC93A650A, + 0xAA478900B1228E31, 0xE8B768EB18C8B8A2, 0x2FA64AD7E2F6E317, 0x6D56AB3C4B1CD584, + 0xE374EF45BF6062EE, 0xA1840EAE168A547D, 0x66952C92ECB40FC8, 0x2465CD79455E395B, + 0x3821458AADA7578F, 0x7AD1A461044D611C, 0xBDC0865DFE733AA9, 0xFF3067B657990C3A, + 0x711223CFA3E5BB50, 0x33E2C2240A0F8DC3, 0xF4F3E018F031D676, 0xB60301F359DBE0E5, + 0xDA050215EA6C212F, 0x98F5E3FE438617BC, 0x5FE4C1C2B9B84C09, 0x1D14202910527A9A, + 0x93366450E42ECDF0, 0xD1C685BB4DC4FB63, 0x16D7A787B7FAA0D6, 0x5427466C1E109645, + 0x4863CE9FF6E9F891, 0x0A932F745F03CE02, 0xCD820D48A53D95B7, 0x8F72ECA30CD7A324, + 0x0150A8DAF8AB144E, 0x43A04931514122DD, 0x84B16B0DAB7F7968, 0xC6418AE602954FFB, + 0xBC387AEA7A8DA4C0, 0xFEC89B01D3679253, 0x39D9B93D2959C9E6, 0x7B2958D680B3FF75, + 0xF50B1CAF74CF481F, 0xB7FBFD44DD257E8C, 0x70EADF78271B2539, 0x321A3E938EF113AA, + 0x2E5EB66066087D7E, 0x6CAE578BCFE24BED, 0xABBF75B735DC1058, 0xE94F945C9C3626CB, + 0x676DD025684A91A1, 0x259D31CEC1A0A732, 0xE28C13F23B9EFC87, 0xA07CF2199274CA14, + 0x167FF3EACBAF2AF1, 0x548F120162451C62, 0x939E303D987B47D7, 0xD16ED1D631917144, + 0x5F4C95AFC5EDC62E, 0x1DBC74446C07F0BD, 0xDAAD56789639AB08, 0x985DB7933FD39D9B, + 0x84193F60D72AF34F, 0xC6E9DE8B7EC0C5DC, 0x01F8FCB784FE9E69, 0x43081D5C2D14A8FA, + 0xCD2A5925D9681F90, 0x8FDAB8CE70822903, 0x48CB9AF28ABC72B6, 0x0A3B7B1923564425, + 0x70428B155B4EAF1E, 0x32B26AFEF2A4998D, 0xF5A348C2089AC238, 0xB753A929A170F4AB, + 0x3971ED50550C43C1, 0x7B810CBBFCE67552, 0xBC902E8706D82EE7, 0xFE60CF6CAF321874, + 0xE224479F47CB76A0, 0xA0D4A674EE214033, 0x67C58448141F1B86, 0x253565A3BDF52D15, + 0xAB1721DA49899A7F, 0xE9E7C031E063ACEC, 0x2EF6E20D1A5DF759, 0x6C0603E6B3B7C1CA, + 0xF6FAE5C07D3274CD, 0xB40A042BD4D8425E, 0x731B26172EE619EB, 0x31EBC7FC870C2F78, + 0xBFC9838573709812, 0xFD39626EDA9AAE81, 0x3A28405220A4F534, 0x78D8A1B9894EC3A7, + 0x649C294A61B7AD73, 0x266CC8A1C85D9BE0, 0xE17DEA9D3263C055, 0xA38D0B769B89F6C6, + 0x2DAF4F0F6FF541AC, 0x6F5FAEE4C61F773F, 0xA84E8CD83C212C8A, 0xEABE6D3395CB1A19, + 0x90C79D3FEDD3F122, 0xD2377CD44439C7B1, 0x15265EE8BE079C04, 0x57D6BF0317EDAA97, + 0xD9F4FB7AE3911DFD, 0x9B041A914A7B2B6E, 0x5C1538ADB04570DB, 0x1EE5D94619AF4648, + 0x02A151B5F156289C, 0x4051B05E58BC1E0F, 0x87409262A28245BA, 0xC5B073890B687329, + 0x4B9237F0FF14C443, 0x0962D61B56FEF2D0, 0xCE73F427ACC0A965, 0x8C8315CC052A9FF6, + 0x3A80143F5CF17F13, 0x7870F5D4F51B4980, 0xBF61D7E80F251235, 0xFD913603A6CF24A6, + 0x73B3727A52B393CC, 0x31439391FB59A55F, 0xF652B1AD0167FEEA, 0xB4A25046A88DC879, + 0xA8E6D8B54074A6AD, 0xEA16395EE99E903E, 0x2D071B6213A0CB8B, 0x6FF7FA89BA4AFD18, + 0xE1D5BEF04E364A72, 0xA3255F1BE7DC7CE1, 0x64347D271DE22754, 0x26C49CCCB40811C7, + 0x5CBD6CC0CC10FAFC, 0x1E4D8D2B65FACC6F, 0xD95CAF179FC497DA, 0x9BAC4EFC362EA149, + 0x158E0A85C2521623, 0x577EEB6E6BB820B0, 0x906FC95291867B05, 0xD29F28B9386C4D96, + 0xCEDBA04AD0952342, 0x8C2B41A1797F15D1, 0x4B3A639D83414E64, 0x09CA82762AAB78F7, + 0x87E8C60FDED7CF9D, 0xC51827E4773DF90E, 0x020905D88D03A2BB, 0x40F9E43324E99428, + 0x2CFFE7D5975E55E2, 0x6E0F063E3EB46371, 0xA91E2402C48A38C4, 0xEBEEC5E96D600E57, + 0x65CC8190991CB93D, 0x273C607B30F68FAE, 0xE02D4247CAC8D41B, 0xA2DDA3AC6322E288, + 0xBE992B5F8BDB8C5C, 0xFC69CAB42231BACF, 0x3B78E888D80FE17A, 0x7988096371E5D7E9, + 0xF7AA4D1A85996083, 0xB55AACF12C735610, 0x724B8ECDD64D0DA5, 0x30BB6F267FA73B36, + 0x4AC29F2A07BFD00D, 0x08327EC1AE55E69E, 0xCF235CFD546BBD2B, 0x8DD3BD16FD818BB8, + 0x03F1F96F09FD3CD2, 0x41011884A0170A41, 0x86103AB85A2951F4, 0xC4E0DB53F3C36767, + 0xD8A453A01B3A09B3, 0x9A54B24BB2D03F20, 0x5D45907748EE6495, 0x1FB5719CE1045206, + 0x919735E51578E56C, 0xD367D40EBC92D3FF, 0x1476F63246AC884A, 0x568617D9EF46BED9, + 0xE085162AB69D5E3C, 0xA275F7C11F7768AF, 0x6564D5FDE549331A, 0x279434164CA30589, + 0xA9B6706FB8DFB2E3, 0xEB46918411358470, 0x2C57B3B8EB0BDFC5, 0x6EA7525342E1E956, + 0x72E3DAA0AA188782, 0x30133B4B03F2B111, 0xF7021977F9CCEAA4, 0xB5F2F89C5026DC37, + 0x3BD0BCE5A45A6B5D, 0x79205D0E0DB05DCE, 0xBE317F32F78E067B, 0xFCC19ED95E6430E8, + 0x86B86ED5267CDBD3, 0xC4488F3E8F96ED40, 0x0359AD0275A8B6F5, 0x41A94CE9DC428066, + 0xCF8B0890283E370C, 0x8D7BE97B81D4019F, 0x4A6ACB477BEA5A2A, 0x089A2AACD2006CB9, + 0x14DEA25F3AF9026D, 0x562E43B4931334FE, 0x913F6188692D6F4B, 0xD3CF8063C0C759D8, + 0x5DEDC41A34BBEEB2, 0x1F1D25F19D51D821, 0xD80C07CD676F8394, 0x9AFCE626CE85B507 +}; + +void crc64 (const uint8_t *data, const size_t len, uint64_t *crc) { + + for (size_t i = 0; i < len; i++) + { + //uint8_t tableIndex = (((uint8_t)(*crc >> 56)) ^ data[i]) & 0xff; + uint8_t tableIndex = (((uint8_t)(*crc >> 56)) ^ data[i]) & 0xff; + *crc = crc64_table[tableIndex] ^ (*crc << 8); + } +} + +//suint8_t x = (c & 0xFF00000000000000 ) >> 56; \ No newline at end of file diff --git a/common/crc64.h b/common/crc64.h new file mode 100644 index 000000000..e28fba144 --- /dev/null +++ b/common/crc64.h @@ -0,0 +1,14 @@ +//----------------------------------------------------------------------------- +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// CRC64 ECMA +//----------------------------------------------------------------------------- + +#ifndef __CRC64_H +#define __CRC64_H + +void crc64 (const uint8_t *data, const size_t len, uint64_t *crc) ; + +#endif From ab7fdfcbed90cb96f281b13c079741df099ce6d2 Mon Sep 17 00:00:00 2001 From: marshmellow42 Date: Wed, 13 May 2015 21:20:23 -0400 Subject: [PATCH 28/49] @iceman1001 updated scripts --- client/scripts/formatMifare.lua | 6 +-- client/scripts/tnp3clone.lua | 16 +++++--- client/scripts/tnp3dump.lua | 11 ++++-- client/scripts/tnp3sim.lua | 65 ++++++++++++++++++++------------- 4 files changed, 59 insertions(+), 39 deletions(-) diff --git a/client/scripts/formatMifare.lua b/client/scripts/formatMifare.lua index 0d735e98f..66a61fba9 100644 --- a/client/scripts/formatMifare.lua +++ b/client/scripts/formatMifare.lua @@ -80,14 +80,14 @@ function GetCardInfo() core.clearCommandBuffer() - if 0x18 == result.sak then --NXP MIFARE Classic 4k | Plus 4k + if 0x18 == result.sak then -- NXP MIFARE Classic 4k | Plus 4k -- IFARE Classic 4K offers 4096 bytes split into forty sectors, -- of which 32 are same size as in the 1K with eight more that are quadruple size sectors. numSectors = 40 - elseif 0x08 == result.sak then -- NXP MIFARE CLASSIC 1k | Plus 2k + elseif 0x08 == result.sak then -- NXP MIFARE CLASSIC 1k | Plus 2k -- 1K offers 1024 bytes of data storage, split into 16 sector numSectors = 16 - elseif 0x09 == result.sak then -- NXP MIFARE Mini 0.3k + elseif 0x09 == result.sak then -- NXP MIFARE Mini 0.3k -- MIFARE Classic mini offers 320 bytes split into five sectors. numSectors = 5 elseif 0x10 == result.sak then -- NXP MIFARE Plus 2k diff --git a/client/scripts/tnp3clone.lua b/client/scripts/tnp3clone.lua index 6c4a148c2..e87c338ea 100644 --- a/client/scripts/tnp3clone.lua +++ b/client/scripts/tnp3clone.lua @@ -13,6 +13,7 @@ local band = bit32.band example =[[ script run tnp3clone script run tnp3clone -h + script run tnp3clone -l script run tnp3clone -t aa00 -s 0030 ]] @@ -23,7 +24,8 @@ This script will try making a barebone clone of a tnp3 tag on to a magic generat Arguments: -h : this help - -t : toytype id, 4hex symbols. + -l : list all known toy tokens + -t : toytype id, 4hex symbols -s : subtype id, 4hex symbols For fun, try the following subtype id: @@ -32,7 +34,7 @@ Arguments: 0138 - Series 2 0234 - Special 023c - Special - + 0020 - Swapforce ]] @@ -74,7 +76,7 @@ local function readmagicblock( blocknum ) -- Read block 0 local CSETBLOCK_SINGLE_OPERATION = 0x1F cmd = Command:new{cmd = cmds.CMD_MIFARE_CGETBLOCK, arg1 = CSETBLOCK_SINGLE_OPERATION, arg2 = 0, arg3 = blocknum} - err = core.SendCommand(cmd:getBytes()) + err = core.SendCommand(cmd:getBytes()) if err then return nil, err end local block0, err = waitCmd() if err then return nil, err end @@ -98,12 +100,13 @@ local function main(args) local DEBUG = true -- Arguments for the script - for o, a in getopt.getopt(args, 'ht:s:') do + for o, a in getopt.getopt(args, 'ht:s:l') do if o == "h" then return help() end if o == "t" then toytype = a end if o == "s" then subtype = a end + if o == "l" then return toys.List() end end - + if #toytype ~= 4 then return oops('Wrong size - toytype. (4hex symbols)') end if #subtype ~= 4 then return oops('Wrong size - subtype. (4hex symbols)') end @@ -139,8 +142,9 @@ local function main(args) -- wipe card. local cmd = (csetuid..'%s 0004 08 w'):format(result.uid) core.console(cmd) + + local b1 = toytype..string.rep('00',10)..subtype - local b1 = toytype..'00000000000000000000'..subtype local calc = utils.Crc16(b0..b1) local calcEndian = bor(rsh(calc,8), lsh(band(calc, 0xff), 8)) diff --git a/client/scripts/tnp3dump.lua b/client/scripts/tnp3dump.lua index cd547e8ad..211d146fd 100644 --- a/client/scripts/tnp3dump.lua +++ b/client/scripts/tnp3dump.lua @@ -205,18 +205,19 @@ local function main(args) if blockNo < 8 then -- Block 0-7 not encrypted - blocks[blockNo+1] = ('%02d :: %s'):format(blockNo,blockdata) + blocks[blockNo+1] = ('%02d :: %s'):format(blockNo,blockdata) else -- blocks with zero not encrypted. if string.find(blockdata, '^0+$') then - blocks[blockNo+1] = ('%02d :: %s'):format(blockNo,blockdata) + blocks[blockNo+1] = ('%02d :: %s'):format(blockNo,blockdata) else local baseStr = utils.ConvertHexToAscii(tmpHash:format(blockNo)) local key = md5.sumhexa(baseStr) local aestest = core.aes128_decrypt(key, blockdata) - local hex = utils.ConvertAsciiToBytes(aestest) + local hex = utils.ConvertAsciiToBytes(aestest) hex = utils.ConvertBytesToHex(hex) - blocks[blockNo+1] = ('%02d :: %s'):format(blockNo,hex) + blocks[blockNo+1] = ('%02d :: %s'):format(blockNo,hex) + io.write(blockNo..',') end end else @@ -273,5 +274,7 @@ local function main(args) print( (' UID : 0x%s'):format(uid) ) print( (' CARDID : 0x%s'):format(cardid ) ) print( string.rep('--',20) ) + + core.clearCommandBuffer() end main(args) \ No newline at end of file diff --git a/client/scripts/tnp3sim.lua b/client/scripts/tnp3sim.lua index af3d2d4cf..4e10eb753 100644 --- a/client/scripts/tnp3sim.lua +++ b/client/scripts/tnp3sim.lua @@ -23,10 +23,22 @@ Arguments: -h : this help -m : Maxed out items (experimental) -i : filename for the datadump to read (bin) -]] + + ]] local TIMEOUT = 2000 -- Shouldn't take longer than 2 seconds -local DEBUG = true -- the debug flag +local DEBUG = false -- the debug flag +local RANDOM = '20436F707972696768742028432920323031302041637469766973696F6E2E20416C6C205269676874732052657365727665642E20' + +local band = bit32.band +local bor = bit32.bor +local lshift = bit32.lshift +local rshift = bit32.rshift +local byte = string.byte +local char = string.char +local sub = string.sub +local format = string.format + local band = bit32.band @@ -197,8 +209,6 @@ local function ValidateCheckSums(blocks) io.write( ('TYPE 3 area 2: %04x = %04x -- %s\n'):format(crc,calc,isOk)) end -local function LoadEmulator(blocks) - local HASHCONSTANT = '20436F707972696768742028432920323031302041637469766973696F6E2E20416C6C205269676874732052657365727665642E20' local cmd local blockdata for _,b in pairs(blocks) do @@ -207,10 +217,10 @@ local function LoadEmulator(blocks) if _%4 ~= 3 then if (_ >= 8 and _<=21) or (_ >= 36 and _<=49) then - local base = ('%s%s%02x%s'):format(blocks[0], blocks[1], _ , HASHCONSTANT) + local base = ('%s%s%02x%s'):format(blocks[0], blocks[1], _ , RANDOM) local baseStr = utils.ConvertHexToAscii(base) local key = md5.sumhexa(baseStr) - local enc = core.aes(key, blockdata) + local enc = core.aes128_encrypt(key, blockdata) local hex = utils.ConvertAsciiToBytes(enc) hex = utils.ConvertBytesToHex(hex) @@ -346,21 +356,6 @@ local function main(args) local cmdSetDbgOff = "hf mf dbg 0" core.console( cmdSetDbgOff) - -- if not loadFromDump then - -- -- Look for tag present on reader, - -- result, err = lib14a.read1443a(false) - -- if not result then return oops(err) end - - -- core.clearCommandBuffer() - - -- if 0x01 ~= result.sak then -- NXP MIFARE TNP3xxx - -- return oops('This is not a TNP3xxx tag. aborting.') - -- end - - -- -- Show tag info - -- print((' Found tag : %s'):format(result.name)) - -- end - -- Load dump.bin file print( (' Load data from %s'):format(inputTemplate)) hex, err = utils.ReadDumpFile(inputTemplate) @@ -374,7 +369,7 @@ local function main(args) end if DEBUG then - print('Validating checksums in the loaded datadump') + print(' Validating checksums') ValidateCheckSums(blocks) end @@ -393,7 +388,7 @@ local function main(args) local item = toys.Find( toytype, subtype) if item then local itemStr = ('%s - %s (%s)'):format(item[6],item[5], item[4]) - print(' ITEM TYPE :'..itemStr ) + print(' ITEM TYPE : '..itemStr ) else print( (' ITEM TYPE : 0x%s 0x%s'):format(toytype, subtype) ) end @@ -407,12 +402,19 @@ local function main(args) print( string.rep('--',20) ) - -- lets do something. - -- + -- Experience should be: local experience = blocks[8]:sub(1,6) - print(('Experience : %d'):format(utils.SwapEndianness(experience,24))) + print(('Experience : %d'):format(utils.SwapEndianness(experience,16))) + local money = blocks[8]:sub(7,10) print(('Money : %d'):format(utils.SwapEndianness(money,16))) + + -- + + -- Sequence number + local seqnum = blocks[8]:sub(18,19) + print(('Sequence number : %d'):format( tonumber(seqnum,16))) + local fairy = blocks[9]:sub(1,8) --FD0F = Left, FF0F = Right local path = 'not choosen' @@ -425,6 +427,12 @@ local function main(args) local hat = blocks[9]:sub(8,11) print(('Hat : %d'):format(utils.SwapEndianness(hat,16))) + + local level = blocks[13]:sub(27,28) + print(('LEVEL : %d'):format( tonumber(level,16))) + --hälsa: 667 029b + --local health = blocks[]:sub(); + --print(('Health : %d'):format( tonumber(health,16)) --0x0D 0x29 0x0A 0x02 16-bit hero points value. Maximum 100. local heropoints = blocks[13]:sub(20,23) @@ -434,6 +442,11 @@ local function main(args) local challenges = blocks[16]:sub(25,32) print(('Finished hero challenges : %d'):format(utils.SwapEndianness(challenges,32))) + -- Character Name + local name1 = blocks[10]:sub(1,32) + local name2 = blocks[12]:sub(1,32) + print('Custom name : '..utils.ConvertHexToAscii(name1..name2)) + if maxed then print('Lets try to max out some values') -- max out money, experience From 9ccfb3a8bcadeba557c285783f8ebbe2cde5fd3b Mon Sep 17 00:00:00 2001 From: marshmellow42 Date: Wed, 13 May 2015 21:36:20 -0400 Subject: [PATCH 29/49] @iceman1001 's updated lualibs --- client/lualibs/commands.lua | 20 +- client/lualibs/default_toys.lua | 60 ++++- client/lualibs/html_dumplib.lua | 4 +- client/lualibs/md5.lua | 384 +++++++++++++++++++++++++++++ client/lualibs/mf_default_keys.lua | 26 +- client/lualibs/precalc.lua | 94 +++++++ client/lualibs/read14a.lua | 4 +- client/lualibs/utils.lua | 65 ++++- 8 files changed, 627 insertions(+), 30 deletions(-) create mode 100644 client/lualibs/md5.lua create mode 100644 client/lualibs/precalc.lua diff --git a/client/lualibs/commands.lua b/client/lualibs/commands.lua index 0a0d98cc8..b0257ef0e 100644 --- a/client/lualibs/commands.lua +++ b/client/lualibs/commands.lua @@ -135,10 +135,11 @@ local _commands = { CMD_MIFARE_SNIFFER = 0x0630, --//ultralightC - CMD_MIFAREUC_AUTH1 = 0x0724, - CMD_MIFAREUC_AUTH2 = 0x0725, - CMD_MIFAREUC_READCARD = 0x0726, - CMD_MIFAREUC_SETPWD = 0x0727, + CMD_MIFAREUC_AUTH1 = 0x0724, + CMD_MIFAREUC_AUTH2 = 0x0725, + CMD_MIFAREUC_READCARD = 0x0726, + CMD_MIFAREUC_SETPWD = 0x0727, + CMD_MIFAREU_SETUID = 0x0728, --// mifare desfire CMD_MIFARE_DESFIRE_READBL = 0x0728, @@ -154,10 +155,10 @@ local _commands = { local _reverse_lookup,k,v = {} -for k, v in pairs(_commands) do - _reverse_lookup[v] = k -end -_commands.tostring = function(command) + for k, v in pairs(_commands) do + _reverse_lookup[v] = k + end + _commands.tostring = function(command) if(type(command) == 'number') then return ("%s (%d)"):format(_reverse_lookup[command]or "ERROR UNDEFINED!", command) end @@ -218,7 +219,6 @@ function Command:getBytes() local data = self.data local cmd = self.cmd local arg1, arg2, arg3 = self.arg1, self.arg2, self.arg3 - - return bin.pack("LLLLH",cmd, arg1, arg2, arg3,data); + return bin.pack("LLLLH",cmd, arg1, arg2, arg3, data); end return _commands diff --git a/client/lualibs/default_toys.lua b/client/lualibs/default_toys.lua index f34d510d6..cb603ec0c 100644 --- a/client/lualibs/default_toys.lua +++ b/client/lualibs/default_toys.lua @@ -24,6 +24,7 @@ local _names = { {"13", "0d00", "0030", "water", "regular", "Wham Shell"}, {"14", "0e00", "0030", "water", "regular", "Gill Grunt"}, --{"14", "0e00", "0030", "water", "regular", "Elite Gill Grunt"}, +--{"14", "0e00", "0030", "water", "regular", "Tidal Wave Gill Grunt"}, {"15", "0f00", "0030", "water", "regular", "Slam Bam"}, --{"15", "0f00", "0030", "water", "regular", "Surfer Slam Bam"}, {"16", "1000", "0030", "magic", "regular", "Spyro"}, @@ -43,7 +44,8 @@ local _names = { {"25", "1900", "0030", "life", "regular", "Zook"}, {"26", "1a00", "0030", "life", "regular", "Stealth Elf"}, --{"26", "1a00", "0030", "life", "regular", "Elite Stealth Elf"}, ---{"26", "1a00", "0030", "life", "regular", "Dark Stealth Elf"}, +--{"26", "1a00", "0528", "life", "regular", "Dark Stealth Elf"}, +{"26", "1a00", "0528", "life", "swapforce", "Ninja Stealth Elf"}, {"27", "1b00", "0030", "life", "regular", "Stump Smash"}, {"27", "1b00", "0118", "life", "regular", "Stump Smash"}, --{"27", "1b00", "0030", "life", "regular", "Autumn Stump Smash"}, @@ -59,6 +61,7 @@ local _names = { --{"32", "2000", "0030", "undead", "regular", "Skeletal Cynder"}, {"100", "6400", "0030", "air", "giant", "Jet Vac"}, +--{"100", "6400", "0030", "air", "giant", "Full blast Jet Vac"}, {"101", "6500", "0030", "air", "giant", "Swarm"}, {"102", "6600", "0030", "earth", "giant", "Crusher"}, {"103", "6700", "0030", "earth", "giant", "Flashwing"}, @@ -73,12 +76,14 @@ local _names = { --{"108", "6c00", "0030", "magic", "giant", "Hoppity Pop Fizz"}, {"108", "6c00", "023c", "magic", "giant", "Love Potion Pop Fizz"}, --{"108", "6c00", "0030", "magic", "giant", "Punch Pop Fizz"}, +--{"108", "6c00", "0030", "magic", "giant", "Fizzy Frenzy Pop Fizz"}, {"109", "6d00", "0030", "magic", "giant", "Nin Jini"}, {"110", "6e00", "0030", "tech", "giant", "Bouncer"}, {"111", "6f00", "0030", "tech", "giant", "Sprocket"}, {"112", "7000", "0030", "life", "giant", "Tree Rex"}, --{"112", "7000", "0030", "life", "giant", "Gnarly Tree Rex"}, -{"113", "7100", "0030", "life", "giant", "Shroomboom"}, --lightcore +{"113", "7100", "0030", "life", "giant", "Shroomboom"}, +--{"113", "7100", "0030", "life", "giant", "Sure shot Shroomboom"}, {"114", "7200", "0030", "undead", "giant", "Eye Broawl"}, {"115", "7300", "0030", "undead", "giant", "Fright Rider"}, @@ -268,27 +273,35 @@ local _names = { {"485", "e501", "0030", "dark", "regular", "Blackout"}, --{"485", "e501", "0234", "dark", "regular", "Special Blackout"}, +-- MINI's {"502", "f601", "0030", "earth", "mini", "Bop"}, -{"503", "f701", "0030", "magic", "mini", "Spry"}, -{"504", "f801", "0030", "undead", "mini", "Hijinx"}, {"505", "f901", "0030", "earth", "mini", "Terrabite"}, + {"506", "fa01", "0030", "air", "mini", "Breeze"}, -{"507", "fb01", "0030", "fire", "mini", "Weeruptor"}, ---{"507", "fb01", "0030", "fire", "mini", "Eggsellent Weeruptor"}, {"508", "fc01", "0030", "air", "mini", "Pet Vac"}, --{"508", "fc01", "0030", "air", "mini", "Power Punch Pet Vac"}, + +{"507", "fb01", "0030", "fire", "mini", "Weeruptor"}, +--{"507", "fb01", "0030", "fire", "mini", "Eggsellent Weeruptor"}, {"509", "fd01", "0030", "fire", "mini", "Small Fry"}, + {"510", "fe01", "0030", "tech", "mini", "Drobit"}, -{"514", "0202", "0030", "water", "mini", "Gill Runt"}, {"519", "0702", "0030", "tech", "mini", "Trigger Snappy"}, + {"526", "0e02", "0030", "life", "mini", "Whisper Elf"}, {"540", "1c02", "0030", "life", "mini", "Barkley"}, --{"540", "1c02", "0030", "life", "mini", "Gnarly Barkley"}, + {"541", "1d02", "0030", "water", "mini", "Thumpling"}, +{"514", "0202", "0030", "water", "mini", "Gill Runt"}, + {"542", "1e02", "0030", "magic", "mini", "mini Jini"}, +{"503", "f701", "0030", "magic", "mini", "Spry"}, + +{"504", "f801", "0030", "undead", "mini", "Hijinx"}, {"543", "1f02", "0030", "undead", "mini", "Eye Small"}, -{"3000", "b80b", "0030", "air", "SWAPFORCE", "Scratch"}, +{"3000", "b80b", "0030", "air", "mini", "Scratch", "SWAPFORCE"}, {"3001", "b90b", "0030", "air", "SWAPFORCE", "Pop Thorn"}, --{"3001", "b90b", "0030", "air", "SWAPFORCE", "Buttered Pop Thorn"}, {"3002", "ba0b", "0030", "earth", "SWAPFORCE", "Slobber Tooth"}, @@ -315,6 +328,29 @@ local _names = { {"3013", "c50b", "0030", "undead", "SWAPFORCE", "Grim Creeper"}, {"3014", "c60b", "0030", "water", "SWAPFORCE", "Rip Tide"}, {"3015", "c70b", "0030", "water", "SWAPFORCE", "Punk Shock"}, + +--{"", "", "0030", "water", "SWAPFORCE", "Hoot Loop"}, +--{"", "", "0030", "water", "SWAPFORCE", "Trap Shadow"}, +--{"", "", "0030", "water", "SWAPFORCE", "Wash Buckler"}, +--{"", "", "0030", "water", "SWAPFORCE", "Freeze Blade"}, +--{"", "", "0030", "fire", "SWAPFORCE", "Magna Charge"}, +--{"", "", "0030", "fire", "SWAPFORCE", "Spy Rise"}, + +--{"", "", "0030", "fire", "SWAPFORCE", "Doom Stone"}, +--{"", "", "0030", "fire", "SWAPFORCE", "Rubble Rouser"}, + +--{"", "", "0030", "fire", "SWAPFORCE", "Blast Zone"} +--{"", "", "0030", "fire", "SWAPFORCE", "Fire Kraken"}, + +--{"", "", "0030", "fire", "SWAPFORCE", "Rattle Shake"}, +--{"", "", "0030", "fire", "SWAPFORCE", "Night Shift"}, + +--{"", "", "0030", "life", "SWAPFORCE", "Stink Bomb"}, +--{"", "", "0030", "life", "SWAPFORCE", "Grilla Drilla"}, + +--{"", "", "0030", "air", "SWAPFORCE", "Free Ranger"}, +--{"", "", "0030", "air", "SWAPFORCE", "Boom Jet"}, + } local function find( main, sub) @@ -327,7 +363,15 @@ local function find( main, sub) end return nil end +local function list() + print ("Type\tSub\tElement\tGame Name") + print (string.rep('=', 54)) + for k, v in pairs(_names) do + print(("%s\t%s\t%s\t%-9s\t%s"):format(v[2],v[3],v[4], v[5], v[6] )) + end +end return { Find = find, + List = list, } diff --git a/client/lualibs/html_dumplib.lua b/client/lualibs/html_dumplib.lua index 3a28d5ae6..566128f7d 100644 --- a/client/lualibs/html_dumplib.lua +++ b/client/lualibs/html_dumplib.lua @@ -192,7 +192,7 @@ end return { convert_bin_to_html = convert_bin_to_html, convert_eml_to_html = convert_eml_to_html, - convert_eml_to_bin = convert_eml_to_bin, - SaveAsBinary = save_BIN, + convert_eml_to_bin = convert_eml_to_bin, + SaveAsBinary = save_BIN, SaveAsText = save_TEXT, } diff --git a/client/lualibs/md5.lua b/client/lualibs/md5.lua new file mode 100644 index 000000000..2390f957a --- /dev/null +++ b/client/lualibs/md5.lua @@ -0,0 +1,384 @@ +local md5 = { + _VERSION = "md5.lua 0.5.0", + _DESCRIPTION = "MD5 computation in Lua (5.1)", + _URL = "https://github.com/kikito/md5.lua", + _LICENSE = [[ + MIT LICENSE + + Copyright (c) 2013 Enrique García Cota + Adam Baldwin + hanzao + Equi 4 Software + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + ]] +} + +-- bit lib implementions + +local floor, abs, max = math.floor, math.abs, math.max +local char, byte, format, rep, sub = + string.char, string.byte, string.format, string.rep, string.sub + +local function check_int(n) + -- checking not float + if(n - floor(n) > 0) then + error("trying to use bitwise operation on non-integer!") + end +end + +local function tbl2number(tbl) + local n = #tbl + + local rslt = 0 + local power = 1 + for i = 1, n do + rslt = rslt + tbl[i]*power + power = power*2 + end + + return rslt +end + +local function expand(tbl_m, tbl_n) + local big = {} + local small = {} + if(#tbl_m > #tbl_n) then + big = tbl_m + small = tbl_n + else + big = tbl_n + small = tbl_m + end + -- expand small + for i = #small + 1, #big do + small[i] = 0 + end + +end + +local to_bits -- needs to be declared before bit_not + +local function bit_not(n) + local tbl = to_bits(n) + local size = max(#tbl, 32) + for i = 1, size do + if(tbl[i] == 1) then + tbl[i] = 0 + else + tbl[i] = 1 + end + end + return tbl2number(tbl) +end + +-- defined as local above +to_bits = function (n) + check_int(n) + if(n < 0) then + -- negative + return to_bits(bit_not(abs(n)) + 1) + end + -- to bits table + local tbl = {} + local cnt = 1 + while (n > 0) do + local last = math.fmod(n,2) + if(last == 1) then + tbl[cnt] = 1 + else + tbl[cnt] = 0 + end + n = (n-last)/2 + cnt = cnt + 1 + end + + return tbl +end + +local function bit_or(m, n) + local tbl_m = to_bits(m) + local tbl_n = to_bits(n) + expand(tbl_m, tbl_n) + + local tbl = {} + local rslt = max(#tbl_m, #tbl_n) + for i = 1, rslt do + if(tbl_m[i]== 0 and tbl_n[i] == 0) then + tbl[i] = 0 + else + tbl[i] = 1 + end + end + + return tbl2number(tbl) +end + +local function bit_and(m, n) + local tbl_m = to_bits(m) + local tbl_n = to_bits(n) + expand(tbl_m, tbl_n) + + local tbl = {} + local rslt = max(#tbl_m, #tbl_n) + for i = 1, rslt do + if(tbl_m[i]== 0 or tbl_n[i] == 0) then + tbl[i] = 0 + else + tbl[i] = 1 + end + end + + return tbl2number(tbl) +end + +local function bit_xor(m, n) + local tbl_m = to_bits(m) + local tbl_n = to_bits(n) + expand(tbl_m, tbl_n) + + local tbl = {} + local rslt = max(#tbl_m, #tbl_n) + for i = 1, rslt do + if(tbl_m[i] ~= tbl_n[i]) then + tbl[i] = 1 + else + tbl[i] = 0 + end + end + + return tbl2number(tbl) +end + +local function bit_rshift(n, bits) + check_int(n) + + local high_bit = 0 + if(n < 0) then + -- negative + n = bit_not(abs(n)) + 1 + high_bit = 2147483648 -- 0x80000000 + end + + for i=1, bits do + n = n/2 + n = bit_or(floor(n), high_bit) + end + return floor(n) +end + +local function bit_lshift(n, bits) + check_int(n) + + if(n < 0) then + -- negative + n = bit_not(abs(n)) + 1 + end + + for i=1, bits do + n = n*2 + end + return bit_and(n, 4294967295) -- 0xFFFFFFFF +end + +-- convert little-endian 32-bit int to a 4-char string +local function lei2str(i) + local f=function (s) return char( bit_and( bit_rshift(i, s), 255)) end + return f(0)..f(8)..f(16)..f(24) +end + +-- convert raw string to big-endian int +local function str2bei(s) + local v=0 + for i=1, #s do + v = v * 256 + byte(s, i) + end + return v +end + +-- convert raw string to little-endian int +local function str2lei(s) + local v=0 + for i = #s,1,-1 do + v = v*256 + byte(s, i) + end + return v +end + +-- cut up a string in little-endian ints of given size +local function cut_le_str(s,...) + local o, r = 1, {} + local args = {...} + for i=1, #args do + table.insert(r, str2lei(sub(s, o, o + args[i] - 1))) + o = o + args[i] + end + return r +end + +local swap = function (w) return str2bei(lei2str(w)) end + +local function hex2binaryaux(hexval) + return char(tonumber(hexval, 16)) +end + +local function hex2binary(hex) + local result, _ = hex:gsub('..', hex2binaryaux) + return result +end + +-- An MD5 mplementation in Lua, requires bitlib (hacked to use LuaBit from above, ugh) +-- 10/02/2001 jcw@equi4.com + +local FF = 0xffffffff +local CONSTS = { + 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, + 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, + 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, + 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, + 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, + 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8, + 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, + 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a, + 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, + 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, + 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05, + 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665, + 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, + 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1, + 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, + 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391, + 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476 +} + +local f=function (x,y,z) return bit_or(bit_and(x,y),bit_and(-x-1,z)) end +local g=function (x,y,z) return bit_or(bit_and(x,z),bit_and(y,-z-1)) end +local h=function (x,y,z) return bit_xor(x,bit_xor(y,z)) end +local i=function (x,y,z) return bit_xor(y,bit_or(x,-z-1)) end +local z=function (f,a,b,c,d,x,s,ac) + a=bit_and(a+f(b,c,d)+x+ac,FF) + -- be *very* careful that left shift does not cause rounding! + return bit_or(bit_lshift(bit_and(a,bit_rshift(FF,s)),s),bit_rshift(a,32-s))+b +end + +local function transform(A,B,C,D,X) + local a,b,c,d=A,B,C,D + local t=CONSTS + + a=z(f,a,b,c,d,X[ 0], 7,t[ 1]) + d=z(f,d,a,b,c,X[ 1],12,t[ 2]) + c=z(f,c,d,a,b,X[ 2],17,t[ 3]) + b=z(f,b,c,d,a,X[ 3],22,t[ 4]) + a=z(f,a,b,c,d,X[ 4], 7,t[ 5]) + d=z(f,d,a,b,c,X[ 5],12,t[ 6]) + c=z(f,c,d,a,b,X[ 6],17,t[ 7]) + b=z(f,b,c,d,a,X[ 7],22,t[ 8]) + a=z(f,a,b,c,d,X[ 8], 7,t[ 9]) + d=z(f,d,a,b,c,X[ 9],12,t[10]) + c=z(f,c,d,a,b,X[10],17,t[11]) + b=z(f,b,c,d,a,X[11],22,t[12]) + a=z(f,a,b,c,d,X[12], 7,t[13]) + d=z(f,d,a,b,c,X[13],12,t[14]) + c=z(f,c,d,a,b,X[14],17,t[15]) + b=z(f,b,c,d,a,X[15],22,t[16]) + + a=z(g,a,b,c,d,X[ 1], 5,t[17]) + d=z(g,d,a,b,c,X[ 6], 9,t[18]) + c=z(g,c,d,a,b,X[11],14,t[19]) + b=z(g,b,c,d,a,X[ 0],20,t[20]) + a=z(g,a,b,c,d,X[ 5], 5,t[21]) + d=z(g,d,a,b,c,X[10], 9,t[22]) + c=z(g,c,d,a,b,X[15],14,t[23]) + b=z(g,b,c,d,a,X[ 4],20,t[24]) + a=z(g,a,b,c,d,X[ 9], 5,t[25]) + d=z(g,d,a,b,c,X[14], 9,t[26]) + c=z(g,c,d,a,b,X[ 3],14,t[27]) + b=z(g,b,c,d,a,X[ 8],20,t[28]) + a=z(g,a,b,c,d,X[13], 5,t[29]) + d=z(g,d,a,b,c,X[ 2], 9,t[30]) + c=z(g,c,d,a,b,X[ 7],14,t[31]) + b=z(g,b,c,d,a,X[12],20,t[32]) + + a=z(h,a,b,c,d,X[ 5], 4,t[33]) + d=z(h,d,a,b,c,X[ 8],11,t[34]) + c=z(h,c,d,a,b,X[11],16,t[35]) + b=z(h,b,c,d,a,X[14],23,t[36]) + a=z(h,a,b,c,d,X[ 1], 4,t[37]) + d=z(h,d,a,b,c,X[ 4],11,t[38]) + c=z(h,c,d,a,b,X[ 7],16,t[39]) + b=z(h,b,c,d,a,X[10],23,t[40]) + a=z(h,a,b,c,d,X[13], 4,t[41]) + d=z(h,d,a,b,c,X[ 0],11,t[42]) + c=z(h,c,d,a,b,X[ 3],16,t[43]) + b=z(h,b,c,d,a,X[ 6],23,t[44]) + a=z(h,a,b,c,d,X[ 9], 4,t[45]) + d=z(h,d,a,b,c,X[12],11,t[46]) + c=z(h,c,d,a,b,X[15],16,t[47]) + b=z(h,b,c,d,a,X[ 2],23,t[48]) + + a=z(i,a,b,c,d,X[ 0], 6,t[49]) + d=z(i,d,a,b,c,X[ 7],10,t[50]) + c=z(i,c,d,a,b,X[14],15,t[51]) + b=z(i,b,c,d,a,X[ 5],21,t[52]) + a=z(i,a,b,c,d,X[12], 6,t[53]) + d=z(i,d,a,b,c,X[ 3],10,t[54]) + c=z(i,c,d,a,b,X[10],15,t[55]) + b=z(i,b,c,d,a,X[ 1],21,t[56]) + a=z(i,a,b,c,d,X[ 8], 6,t[57]) + d=z(i,d,a,b,c,X[15],10,t[58]) + c=z(i,c,d,a,b,X[ 6],15,t[59]) + b=z(i,b,c,d,a,X[13],21,t[60]) + a=z(i,a,b,c,d,X[ 4], 6,t[61]) + d=z(i,d,a,b,c,X[11],10,t[62]) + c=z(i,c,d,a,b,X[ 2],15,t[63]) + b=z(i,b,c,d,a,X[ 9],21,t[64]) + + return A+a,B+b,C+c,D+d +end + +---------------------------------------------------------------- + +function md5.sumhexa(s) + local msgLen = #s + local padLen = 56 - msgLen % 64 + + if msgLen % 64 > 56 then padLen = padLen + 64 end + + if padLen == 0 then padLen = 64 end + + s = s .. char(128) .. rep(char(0),padLen-1) .. lei2str(8*msgLen) .. lei2str(0) + + assert(#s % 64 == 0) + + local t = CONSTS + local a,b,c,d = t[65],t[66],t[67],t[68] + + for i=1,#s,64 do + local X = cut_le_str(sub(s,i,i+63),4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4) + assert(#X == 16) + X[0] = table.remove(X,1) -- zero based! + a,b,c,d = transform(a,b,c,d,X) + end + + return format("%08x%08x%08x%08x",swap(a),swap(b),swap(c),swap(d)) +end + +function md5.sum(s) + return hex2binary(md5.sumhexa(s)) +end + +return md5 diff --git a/client/lualibs/mf_default_keys.lua b/client/lualibs/mf_default_keys.lua index 757112c67..804d4a842 100644 --- a/client/lualibs/mf_default_keys.lua +++ b/client/lualibs/mf_default_keys.lua @@ -2,6 +2,7 @@ local _keys = { + --[[ These keys are from the pm3 c-codebase. @@ -157,9 +158,30 @@ local _keys = { '9de89e070277', 'eff603e1efe9', '644672bd4afe', - 'b5ff67cba951', - } + + --[[ + hotel system cards, + http://www.proxmark.org/forum/viewtopic.php?id=2430 + --]] + '44ab09010845', + '85fed980ea5a', + + --[[ + VIGIK1 + --]] + '314B49474956', + '564c505f4d41', + + --[[ + BCARD keyB + --]] + 'f4a9ef2afc6d', + + --[[ + --]] + 'a9f953def0a3', +} --- -- The keys above have just been pasted in, for completeness sake. They contain duplicates. diff --git a/client/lualibs/precalc.lua b/client/lualibs/precalc.lua new file mode 100644 index 000000000..ce58998a8 --- /dev/null +++ b/client/lualibs/precalc.lua @@ -0,0 +1,94 @@ +--[[ + This is an experimental lib. +--]] +local utils = require('utils') + +-- LOOKUP Tables +local perm = {} +perm [1]= { 0x0, 0x1, 0x3, 0x2, 0x7, 0x6, 0x4, 0x5, 0xF, 0xE, 0xC, 0xD, 0x8, 0x9, 0xB, 0xA } +perm [2]= { 0x1, 0x0, 0x2, 0x3, 0x6, 0x7, 0x5, 0x4, 0xE, 0xF, 0xD, 0xC, 0x9, 0x8, 0xA, 0xB } +perm [3]= { 0x2, 0x3, 0x1, 0x0, 0x5, 0x4, 0x6, 0x7, 0xD, 0xC, 0xE, 0xF, 0xA, 0xB, 0x9, 0x8 } +perm [4]= { 0x3, 0x2, 0x0, 0x1, 0x4, 0x5, 0x7, 0x6, 0xC, 0xD, 0xF, 0xE, 0xB, 0xA, 0x8, 0x9 } +perm [5]= { 0x4, 0x5, 0x7, 0x6, 0x3, 0x2, 0x0, 0x1, 0xB, 0xA, 0x8, 0x9, 0xC, 0xD, 0xF, 0xE } +perm [6]= { 0x5, 0x4, 0x6, 0x7, 0x2, 0x3, 0x1, 0x0, 0xA, 0xB, 0x9, 0x8, 0xD, 0xC, 0xE, 0xF } +perm [7]= { 0x6, 0x7, 0x5, 0x4, 0x1, 0x0, 0x2, 0x3, 0x9, 0x8, 0xA, 0xB, 0xE, 0xF, 0xD, 0xC } +perm [8]= { 0x7, 0x6, 0x4, 0x5, 0x0, 0x1, 0x3, 0x2, 0x8, 0x9, 0xB, 0xA, 0xF, 0xE, 0xC, 0xD } +perm [9]= { 0x8, 0x9, 0xB, 0xA, 0xF, 0xE, 0xC, 0xD, 0x7, 0x6, 0x4, 0x5, 0x0, 0x1, 0x3, 0x2 } +perm [10]= { 0x9, 0x8, 0xA, 0xB, 0xE, 0xF, 0xD, 0xC, 0x6, 0x7, 0x5, 0x4, 0x1, 0x0, 0x2, 0x3 } +perm [11]= { 0xA, 0xB, 0x9, 0x8, 0xD, 0xC, 0xE, 0xF, 0x5, 0x4, 0x6, 0x7, 0x2, 0x3, 0x1, 0x0 } +perm [12]= { 0xB, 0xA, 0x8, 0x9, 0xC, 0xD, 0xF, 0xE, 0x4, 0x5, 0x7, 0x6, 0x3, 0x2, 0x0, 0x1 } +perm [13]= { 0xC, 0xD, 0xF, 0xE, 0xB, 0xA, 0x8, 0x9, 0x3, 0x2, 0x0, 0x1, 0x4, 0x5, 0x7, 0x6 } +perm [14]= { 0xD, 0xC, 0xE, 0xF, 0xA, 0xB, 0x9, 0x8, 0x2, 0x3, 0x1, 0x0, 0x5, 0x4, 0x6, 0x7 } +perm [15]= { 0xE, 0xF, 0xD, 0xC, 0x9, 0x8, 0xA, 0xB, 0x1, 0x0, 0x2, 0x3, 0x6, 0x7, 0x5, 0x4 } +perm [16]= { 0xF, 0xE, 0xC, 0xD, 0x8, 0x9, 0xB, 0xA, 0x0, 0x1, 0x3, 0x2, 0x7, 0x6, 0x4, 0x5 } + +local shifts = {} +shifts[1]= { 0x4, 0x5, 0x7, 0x6, 0x3, 0x2, 0x0, 0x1, 0xB, 0xA, 0x8, 0x9, 0xC, 0xD, 0xF, 0xE } +shifts[2]= { 0x4, 0xB, 0xB, 0x4, 0xB, 0x4, 0x4, 0xB, 0xA, 0x5, 0x5, 0xA, 0x5, 0xA, 0xA, 0x5 } +shifts[3]= { 0xB, 0x6, 0x0, 0xD, 0xD, 0x0, 0x6, 0xB, 0x6, 0xB, 0xD, 0x0, 0x0, 0xD, 0xB, 0x6 } +shifts[4]= { 0xE, 0x5, 0x9, 0x2, 0x0, 0xB, 0x7, 0xC, 0x3, 0x8, 0x4, 0xF, 0xD, 0x6, 0xA, 0x1 } +shifts[5]= { 0x4, 0xE, 0x1, 0xB, 0xF, 0x5, 0xA, 0x0, 0x3, 0x9, 0x6, 0xC, 0x8, 0x2, 0xD, 0x7 } +shifts[6]= { 0xA, 0x4, 0x7, 0x9, 0x0, 0xE, 0xD, 0x3, 0xE, 0x0, 0x3, 0xD, 0x4, 0xA, 0x9, 0x7 } +shifts[7]= { 0xE, 0x6, 0xE, 0x6, 0xF, 0x7, 0xF, 0x7, 0xD, 0x5, 0xD, 0x5, 0xC, 0x4, 0xC, 0x4 } +shifts[8]= { 0x7, 0x1, 0xB, 0xD, 0xE, 0x8, 0x2, 0x4, 0x4, 0x2, 0x8, 0xE, 0xD, 0xB, 0x1, 0x7 } +shifts[9]= { 0xD, 0xB, 0x0, 0x6, 0x6, 0x0, 0xB, 0xD, 0xA, 0xC, 0x7, 0x1, 0x1, 0x7, 0xC, 0xA } +shifts[10]= { 0xe, 0x1, 0x1, 0xe, 0x1, 0xe, 0xe, 0x1, 0x1, 0xe, 0xe, 0x1, 0xe, 0x1, 0x1, 0xe } + +local function ApplyPermutationAndShifts( pos, value, nibble) + local shiftbytes = shifts[pos] + local shiftElem = shiftbytes[nibble+1] --one indexed + local shiftOne = shiftbytes[1] + local rs = bit32.bxor(value, bit32.bxor(shiftOne, shiftElem)) + return rs +end + +local function GetOne( uid, block ) + + if uid == nil then return nil, 'empty uid string' end + if #uid == 0 then return nil, 'empty uid string' end + if #uid ~= 8 then return nil, 'uid wrong length. Should be 4 hex bytes' end + if type(block) ~= 'number' then return nil, 'block is not number' end + if block > 16 or block < 0 then return nil, 'block is out-of-range' end + + local s = ('%s%02X'):format(uid,block) + local nibble1 = tonumber(s:sub(1,1),16) + 1 + + local permuted = '' + for i = 1, #s do + local el_row = shifts[i] + local el_value = el_row[nibble1] + j = 1 + while j <= i do + if i-j > 0 then + local nibble = tonumber(s:sub(j+1,j+1),16) + el_value = ApplyPermutationAndShifts(i-j, el_value, nibble) + end + j = j+1 + end + permuted =('%s%X'):format(permuted,el_value) + end + + permuted = 'C2'..permuted + local crc64numStr = utils.Crc64(permuted) + local keybytes = utils.ConvertAsciiToBytes(crc64numStr, true) + local key = utils.ConvertBytesToHex(keybytes) + return key:sub(1,12) +end + +local PreCalc = +{ + GetAll = function(id) + if id == nil then return nil, 'empty string' end + if #id == 0 then return nil, 'empty string' end + if #id ~= 8 then return nil, 'wrong length. Should be 4 hex bytes' end + + local list = '4b0b20107ccb' + for i = 1,15 do + local key, err = GetOne(id,i) + if not key then return oops(err) end + list = list..key + end + return list + end, +} +return PreCalc \ No newline at end of file diff --git a/client/lualibs/read14a.lua b/client/lualibs/read14a.lua index 10e7c2d4a..943a17224 100644 --- a/client/lualibs/read14a.lua +++ b/client/lualibs/read14a.lua @@ -20,7 +20,9 @@ local ISO14A_COMMAND = { ISO14A_RAW = 8, ISO14A_REQUEST_TRIGGER = 0x10, ISO14A_APPEND_CRC = 0x20, - ISO14A_SET_TIMEOUT = 0x40 + ISO14A_SET_TIMEOUT = 0x40, + ISO14A_NO_SELECT = 0x80, + ISO14A_TOPAZMODE = 0x100 } local ISO14443a_TYPES = {} diff --git a/client/lualibs/utils.lua b/client/lualibs/utils.lua index c5baa4069..a968fde2a 100644 --- a/client/lualibs/utils.lua +++ b/client/lualibs/utils.lua @@ -71,8 +71,8 @@ local Utils = return outResults end, - ------------ CRC-16 ccitt checksums + ------------ CRC-16 ccitt checksums -- Takes a hex string and calculates a crc16 Crc16 = function(s) if s == nil then return nil end @@ -85,7 +85,22 @@ local Utils = end return nil end, - + + ------------ CRC-64 ecma checksums + -- Takes a hex string and calculates a crc64 ecma + Crc64 = function(s) + if s == nil then return nil end + if #s == 0 then return nil end + if type(s) == 'string' then + local utils = require('utils') + local asc = utils.ConvertHexToAscii(s) + local hash = core.crc64(asc) + return hash + end + return nil + end, + + -- input parameter is a string -- Swaps the endianess and returns a number, -- IE: 'cd7a' -> '7acd' -> 0x7acd @@ -135,7 +150,7 @@ local Utils = while IN>0 do I=I+1 IN , D = math.floor(IN/B), math.modf(IN,B)+1 - OUT=string.sub(K,D,D)..OUT + OUT = string.sub(K,D,D)..OUT end return OUT end, @@ -147,7 +162,7 @@ local Utils = end local s={} for i = 1, #(bytes) do - s[i] = string.format("%02X",bytes[i]) + s[i] = string.format("%02X",bytes[i]) end return table.concat(s) end, @@ -171,16 +186,28 @@ local Utils = end return t end, - ConvertAsciiToBytes = function(s) - local t={} + ConvertAsciiToBytes = function(s, reverse) + local t = {} if s == nil then return t end if #s == 0 then return t end for k in s:gmatch"(.)" do table.insert(t, string.byte(k)) end - return t + + if not reverse then + return t + end + + local rev = {} + if reverse then + for i = #t, 1,-1 do + table.insert(rev, t[i] ) + end + end + return rev end, + ConvertHexToAscii = function(s) local t={} if s == nil then return t end @@ -191,6 +218,30 @@ local Utils = return table.concat(t) end, + Chars2num = function(s) + return (s:byte(1)*16777216)+(s:byte(2)*65536)+(s:byte(3)*256)+(s:byte(4)) + end, + + -- use length of string to determine 8,16,32,64 bits + bytes_to_int = function(str,endian,signed) + local t={str:byte(1,-1)} + if endian=="big" then --reverse bytes + local tt={} + for k=1,#t do + tt[#t-k+1]=t[k] + end + t=tt + end + local n=0 + for k=1,#t do + n=n+t[k]*2^((k-1)*8) + end + if signed then + n = (n > 2^(#t*8-1) -1) and (n - 2^(#t*8)) or n -- if last bit set, negative. + end + return n + end, + -- function convertStringToBytes(str) -- local bytes = {} -- local strLength = string.len(str) From 93737008ee29d7748ccc9fcffa1ff4c5c706ea7f Mon Sep 17 00:00:00 2001 From: marshmellow42 Date: Thu, 14 May 2015 22:55:18 -0400 Subject: [PATCH 30/49] @iceman1001 s default keys --- client/default_keys.dic | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/client/default_keys.dic b/client/default_keys.dic index 5c2773008..520317bf3 100644 --- a/client/default_keys.dic +++ b/client/default_keys.dic @@ -11,7 +11,7 @@ d3f7d3f7d3f7, 587ee5f9350f, a0478cc39091, 533cb6c723f6, -8fd0a4f256e9 +8fd0a4f256e9, # more Keys from mf_default_keys.lua 000000000001, 000000000002, @@ -42,6 +42,7 @@ a0478cc39091, 47524f555041,--RKFJOJOGROUPKeyA 47524f555042,--RKFJOJOGROUPKeyB 4AF9D7ADEBE4,--DirectoryandeventlogKeyA +4b0b20107ccb,--TNP3xxx 505249564141,--RKFJOJOPRIVAKeyA 505249564142,--RKFJOJOPRIVAKeyB 505249565441, @@ -49,14 +50,19 @@ a0478cc39091, 54726176656c,--VästtrafikenKeyA 555555555555, 55f5a5dd38c9, +569369c5a0e5,--kiev 5c598c9c58b5,--RKFSLKeyB +632193be1c3c,--kiev +644672bd4afe,--kiev 666666666666, 722bfcc5375f,--RKFRejskortDanmarkKeyA 776974687573,--VästtrafikenKeyB 777777777777, 888888888888, +8fe644038790,--kiev 999999999999, 99c636334433, +9de89e070277,--kiev a00000000000, a053a292a4af, a64598a77478,--RKFSLKeyA @@ -65,6 +71,7 @@ aaaaaaaaaaaa, abcdef123456,--Keyfromladyada.net b00000000000, b127c6f41436, +b5ff67cba951,--kiev bbbbbbbbbbbb, bd493a3962b6, c934fe34d934, @@ -73,7 +80,15 @@ dddddddddddd, e4d2770a89be,--RKFSLKeyB ee0042f88840,--VästtrafikenKeyB eeeeeeeeeeee, +eff603e1efe9,--kiev +f14ee7cae863,--kiev f1a97341a9fc, f1d83f964314,--RKFRejskortDanmarkKeyB fc00018778f7,--VästtrafikenKeyA fc0001877bf7,--RKFÖstgötaTrafikenKeyA +44ab09010845,-- hotel system +85fed980ea5a,-- hotel system +314B49474956,--VIGIK1KeyA +564c505f4d41,--VIGIK1KeyB +f4a9ef2afc6d,--BCARD KeyB +a9f953def0a3,-- \ No newline at end of file From 5b99376a8f30ab4946b10176ea5fe7e6596d5281 Mon Sep 17 00:00:00 2001 From: marshmellow42 Date: Fri, 15 May 2015 00:57:51 -0400 Subject: [PATCH 31/49] hf mfu dump testing --- client/cmdhfmfu.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/client/cmdhfmfu.c b/client/cmdhfmfu.c index d80608947..37f7f0c07 100644 --- a/client/cmdhfmfu.c +++ b/client/cmdhfmfu.c @@ -17,7 +17,7 @@ #define MAX_UL_BLOCKS 0x0f #define MAX_ULC_BLOCKS 0x2f -#define MAX_ULEV1a_BLOCKS 0x0b +#define MAX_ULEV1a_BLOCKS 0x12 #define MAX_ULEV1b_BLOCKS 0x20 #define MAX_NTAG_213 0x2c #define MAX_NTAG_215 0x86 @@ -46,6 +46,14 @@ uint8_t default_pwd_pack[KEYS_PWD_COUNT][4] = { {0x32,0x0C,0x16,0x17}, // PACK 0x80,0x80 -- AMiiboo (sniffed) }; +#define MAX_UL_TYPES 13 +uint16_t UL_TYPES_ARRAY[MAX_UL_TYPES] = {UNKNOWN, UL, UL_C, UL_EV1_48, UL_EV1_128, + NTAG, NTAG_213, NTAG_215, NTAG_216, MY_D, MY_D_NFC, MY_D_MOVE, MY_D_MOVE_NFC}; +uint8_t UL_MEMORY_ARRAY[MAX_UL_TYPES] = {MAX_UL_BLOCKS, MAX_UL_BLOCKS, MAX_ULC_BLOCKS, + MAX_ULEV1a_BLOCKS, MAX_ULEV1b_BLOCKS, MAX_NTAG_213, MAX_NTAG_213, MAX_NTAG_215, + MAX_NTAG_216, MAX_UL_BLOCKS, MAX_UL_BLOCKS, MAX_UL_BLOCKS, MAX_UL_BLOCKS}; + + static int CmdHelp(const char *Cmd); char* getProductTypeStr( uint8_t id){ @@ -919,7 +927,7 @@ int CmdHF14AMfUDump(const char *Cmd){ FILE *fout; char filename[FILE_PATH_SIZE] = {0x00}; char *fnameptr = filename; - char *str = "Dumping Ultralight%s%s Card Data..."; + //char *str = "Dumping Ultralight%s%s Card Data..."; uint8_t *lockbytes_t = NULL; uint8_t lockbytes[2] = {0x00}; uint8_t *lockbytes_t2 = NULL; @@ -985,6 +993,13 @@ int CmdHF14AMfUDump(const char *Cmd){ TagTypeUL_t tagtype = GetHF14AMfU_Type(); if (tagtype == UL_ERROR) return -1; + for (uint8_t idx = 0; idx < MAX_UL_TYPES; idx++) + if (tagtype & UL_TYPES_ARRAY[idx]) + Pages = UL_MEMORY_ARRAY[idx]+1; + + ul_print_type(tagtype, 0); + PrintAndLog("Dumping tag memory..."); + /* if ( tagtype & UL ) { Pages = 16; PrintAndLog(str,"", (tagtype & MAGIC)?" (magic)":"" ); @@ -1004,7 +1019,7 @@ int CmdHF14AMfUDump(const char *Cmd){ Pages = 16; PrintAndLog("Dumping unknown Ultralight, using default values."); } - + */ UsbCommand c = {CMD_MIFAREUC_READCARD, {0,Pages}}; if ( hasPwd ) { c.arg[2] = 1; From ae8303c13ca731ef70a35ae2ff5e79c4b1d6559d Mon Sep 17 00:00:00 2001 From: marshmellow42 Date: Fri, 15 May 2015 01:19:58 -0400 Subject: [PATCH 32/49] mfu dump - beginning of additions --- client/cmdhfmfu.c | 72 ++++++++++++++++++++++++++++++++--------------- 1 file changed, 49 insertions(+), 23 deletions(-) diff --git a/client/cmdhfmfu.c b/client/cmdhfmfu.c index 37f7f0c07..e1169659b 100644 --- a/client/cmdhfmfu.c +++ b/client/cmdhfmfu.c @@ -946,7 +946,8 @@ int CmdHF14AMfUDump(const char *Cmd){ size_t fileNlen = 0; bool errors = false; bool swapEndian = false; - + bool manualPages = false; + uint8_t startPage = 0; while(param_getchar(Cmd, cmdp) != 0x00) { switch(param_getchar(Cmd, cmdp)) @@ -972,10 +973,29 @@ int CmdHF14AMfUDump(const char *Cmd){ if (fileNlen > FILE_PATH_SIZE-5) fileNlen = FILE_PATH_SIZE-5; cmdp += 2; break; + case 'p': + case 'P': + startPage = param_get8(Cmd, cmdp+1); + manualPages = true; + cmdp += 2; + break; + case 'q': + case 'Q': + Pages = param_get8(Cmd, cmdp+1); + cmdp += 2; + manualPages = true; + break; case 's': + case 'S': swapEndian = true; cmdp++; break; + case 't': + case 'T': + //key type - ul-c or ev1/ntag + //TODO + cmdp += 2; + break; default: PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp)); errors = true; @@ -993,12 +1013,13 @@ int CmdHF14AMfUDump(const char *Cmd){ TagTypeUL_t tagtype = GetHF14AMfU_Type(); if (tagtype == UL_ERROR) return -1; - for (uint8_t idx = 0; idx < MAX_UL_TYPES; idx++) - if (tagtype & UL_TYPES_ARRAY[idx]) - Pages = UL_MEMORY_ARRAY[idx]+1; - + if (!manualPages) + for (uint8_t idx = 0; idx < MAX_UL_TYPES; idx++) + if (tagtype & UL_TYPES_ARRAY[idx]) + Pages = UL_MEMORY_ARRAY[idx]+1; + ul_print_type(tagtype, 0); - PrintAndLog("Dumping tag memory..."); + PrintAndLog("Reading tag memory..."); /* if ( tagtype & UL ) { Pages = 16; @@ -1020,24 +1041,29 @@ int CmdHF14AMfUDump(const char *Cmd){ PrintAndLog("Dumping unknown Ultralight, using default values."); } */ - UsbCommand c = {CMD_MIFAREUC_READCARD, {0,Pages}}; - if ( hasPwd ) { - c.arg[2] = 1; - memcpy(c.d.asBytes, key, 16); - } - SendCommand(&c); - UsbCommand resp; - if (!WaitForResponseTimeout(CMD_ACK, &resp,1500)) { - PrintAndLog("Command execute time-out"); - return 1; - } - PrintAndLog ("%u,%u",resp.arg[0],resp.arg[1]); - uint8_t isOK = resp.arg[0] & 0xff; - if (isOK) { - memcpy(data, resp.d.asBytes, resp.arg[1]); + if (!hasPwd || (tagtype & UL_C)){ + UsbCommand c = {CMD_MIFAREUC_READCARD, {startPage,Pages}}; + if ( hasPwd ) { + c.arg[2] = 1; + memcpy(c.d.asBytes, key, 16); + } + SendCommand(&c); + UsbCommand resp; + if (!WaitForResponseTimeout(CMD_ACK, &resp,1500)) { + PrintAndLog("Command execute time-out"); + return 1; + } + PrintAndLog ("%u,%u",resp.arg[0],resp.arg[1]); + uint8_t isOK = resp.arg[0] & 0xff; + if (isOK) { + memcpy(data, resp.d.asBytes, resp.arg[1]); + } else { + PrintAndLog("Failed reading block: (%02x)", i); + return 1; + } } else { - PrintAndLog("Failed reading block: (%02x)", i); - return 1; + PrintAndLog("EV1 and NTAG pwd mode not ready yet"); + return 0; } // Load lock bytes. From cceabb79e6f1bc8e9c2cab766f6edb3a4200bb74 Mon Sep 17 00:00:00 2001 From: marshmellow42 Date: Sat, 16 May 2015 01:00:31 -0400 Subject: [PATCH 33/49] mfu info / dump attempt at missing auths NOT TESTED. will test soon. probably has bugs! --- armsrc/apps.h | 2 +- armsrc/mifarecmd.c | 33 ++++++--- armsrc/mifareutil.c | 20 ++++++ armsrc/mifareutil.h | 3 +- client/cmdhfmfu.c | 160 ++++++++++++++++++++++---------------------- client/cmdhfmfu.h | 2 +- 6 files changed, 129 insertions(+), 91 deletions(-) diff --git a/armsrc/apps.h b/armsrc/apps.h index d01c6478c..d325dbe8d 100644 --- a/armsrc/apps.h +++ b/armsrc/apps.h @@ -167,7 +167,7 @@ int32_t dist_nt(uint32_t nt1, uint32_t nt2); 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_Auth1(uint8_t arg0, uint8_t *datain); -void MifareUC_Auth2(uint32_t arg0, uint8_t *datain); +void MifareUC_Auth2(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); diff --git a/armsrc/mifarecmd.c b/armsrc/mifarecmd.c index c51a30dc9..cf36b95a0 100644 --- a/armsrc/mifarecmd.c +++ b/armsrc/mifarecmd.c @@ -121,7 +121,7 @@ void MifareUC_Auth1(uint8_t arg0, uint8_t *datain){ cmd_send(CMD_ACK,1,cuid,0,dataoutbuf,11); LEDsoff(); } -void MifareUC_Auth2(uint32_t arg0, uint8_t *datain){ +void MifareUC_Auth2(uint8_t arg0, uint8_t *datain){ uint8_t key[16] = {0x00}; byte_t dataoutbuf[16] = {0x00}; @@ -139,8 +139,10 @@ void MifareUC_Auth2(uint32_t arg0, uint8_t *datain){ if (MF_DBGLEVEL >= MF_DBG_EXTENDED) DbpString("AUTH 2 FINISHED"); cmd_send(CMD_ACK,1,0,0,dataoutbuf,11); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - LEDsoff(); + if (arg0) { + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LEDsoff(); + } } // Arg0 = BlockNo, @@ -346,7 +348,8 @@ void MifareUReadCard(uint8_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain) // params uint8_t blockNo = arg0; uint16_t blocks = arg1; - bool useKey = (arg2 == 1); + bool useKey = (arg2 == 1); //UL_C + bool usePwd = (arg2 == 2); //UL_EV1/NTAG int countblocks = 0; uint8_t dataout[176] = {0x00}; @@ -373,12 +376,12 @@ void MifareUReadCard(uint8_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain) uint8_t rnd_ab[16] = {0x00}; uint8_t IV[8] = {0x00}; - uint16_t len; + uint16_t len2; uint8_t receivedAnswer[MAX_FRAME_SIZE]; uint8_t receivedAnswerPar[MAX_PARITY_SIZE]; - len = mifare_sendcmd_short(NULL, 1, 0x1A, 0x00, receivedAnswer,receivedAnswerPar ,NULL); - if (len != 11) { + len2 = mifare_sendcmd_short(NULL, 1, 0x1A, 0x00, receivedAnswer,receivedAnswerPar ,NULL); + if (len2 != 11) { if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x", receivedAnswer[0]); OnError(1); return; @@ -396,8 +399,8 @@ void MifareUReadCard(uint8_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain) // encrypt out, in, length, key, iv tdes_2key_enc(rnd_ab, rnd_ab, sizeof(rnd_ab), key, enc_random_b); - len = mifare_sendcmd_short_mfucauth(NULL, 1, 0xAF, rnd_ab, receivedAnswer, receivedAnswerPar, NULL); - if (len != 11) { + len2 = mifare_sendcmd_short_mfucauth(NULL, 1, 0xAF, rnd_ab, receivedAnswer, receivedAnswerPar, NULL); + if (len2 != 11) { OnError(1); return; } @@ -412,6 +415,18 @@ void MifareUReadCard(uint8_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain) Dbprintf("failed authentication"); } + if (usePwd) { //ev1 or ntag auth + uint8_t Pwd[4] = {0x00}; + memcpy(Pwd, datain, 4); + uint8_t pack[4] = {0,0,0,0}; + + if (mifare_ul_ev1_auth(Pwd, pack)){ + OnError(1); + Dbprintf("failed authentication"); + return; + } + } + for (int i = 0; i < blocks; i++){ len = mifare_ultra_readblock(blockNo * 4 + i, dataout + 4 * i); diff --git a/armsrc/mifareutil.c b/armsrc/mifareutil.c index b7408cf1d..cc54b7402 100644 --- a/armsrc/mifareutil.c +++ b/armsrc/mifareutil.c @@ -288,6 +288,26 @@ int mifare_classic_readblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blo } // mifare ultralight commands +int mifare_ul_ev1_auth(uint8_t *key, uint8_t *pack){ + + uint16_t len; + uint8_t receivedAnswer[MAX_FRAME_SIZE]; + uint8_t receivedAnswerPar[MAX_PARITY_SIZE]; + + len = mifare_sendcmd_short_mfucauth(NULL, 0, 0x1B, key, receivedAnswer, receivedAnswerPar, NULL); + if (len != 4) { + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x %u", receivedAnswer[0], len); + return 1; + } + + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) { + Dbprintf("Auth Resp: %02x%02x%02x%02x", + receivedAnswer[0],receivedAnswer[1],receivedAnswer[2],receivedAnswer[3]); + } + memcpy(pack, receivedAnswer, 4); + return 0; +} + int mifare_ultra_auth1(uint8_t *blockData){ uint16_t len; diff --git a/armsrc/mifareutil.h b/armsrc/mifareutil.h index ee3ae7c6e..03a545b48 100644 --- a/armsrc/mifareutil.h +++ b/armsrc/mifareutil.h @@ -61,7 +61,8 @@ int mifare_sendcmd_shortex(struct Crypto1State *pcs, uint8_t crypted, uint8_t cm int mifare_classic_auth(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested); int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested, uint32_t * ntptr, uint32_t *timing); -int mifare_classic_readblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData); +int mifare_classic_readblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData); +int mifare_ul_ev1_auth(uint8_t *key, uint8_t *pack); int mifare_ultra_auth1(uint8_t *blockData); int mifare_ultra_auth2(uint8_t *key, uint8_t *blockData); int mifare_ultra_readblock(uint8_t blockNo, uint8_t *blockData); diff --git a/client/cmdhfmfu.c b/client/cmdhfmfu.c index e1169659b..a502a23d9 100644 --- a/client/cmdhfmfu.c +++ b/client/cmdhfmfu.c @@ -586,6 +586,7 @@ int CmdHF14AMfUInfo(const char *Cmd){ uint8_t datalen = 0; uint8_t authenticationkey[16] = {0x00}; uint8_t pack[4] = {0,0,0,0}; + int len=0; while(param_getchar(Cmd, cmdp) != 0x00) { @@ -640,12 +641,25 @@ int CmdHF14AMfUInfo(const char *Cmd){ } if ( hasAuthKey ) { - if ((tagtype & UL_C)) - try3DesAuthentication(authenticationkey); - else - ulev1_requestAuthentication(authenticationkey, pack, sizeof(pack)); + if ((tagtype & UL_C)) { + ul_switch_off_field(); + //will select card automatically + if (try3DesAuthentication(authenticationkey, false) != 1) { + ul_switch_off_field(); + PrintAndLog("Error: Authentication Failed UL-C"); + return 0; + } + } else { + len = ulev1_requestAuthentication(authenticationkey, pack, sizeof(pack)); + if (len < 1) { + if (!len) ul_switch_off_field(); + PrintAndLog("Error: Authentication Failed UL-EV1/NTAG"); + return 0; + } + } } + // read pages 0,1,2,4 (should read 4pages) status = ul_read(0, data, sizeof(data)); if ( status == -1 ){ @@ -681,17 +695,18 @@ int CmdHF14AMfUInfo(const char *Cmd){ if ( hasAuthKey ) return 1; PrintAndLog("Trying some default 3des keys"); - ul_switch_off_field(); + ul_switch_off_field(); //will select again in try3DesAuth... for (uint8_t i = 0; i < KEYS_3DES_COUNT; ++i ){ key = default_3des_keys[i]; - if (try3DesAuthentication(key) == 1){ + if (try3DesAuthentication(key, true) == 1){ PrintAndLog("Found default 3des key: "); //%s", sprint_hex(key,16)); uint8_t keySwap[16]; memcpy(keySwap, SwapEndian64(key,16,8), 16); ulc_print_3deskey(keySwap); return 1; - } + } } + return 1; //return even if key not found (UL_C is done) } } @@ -743,13 +758,14 @@ int CmdHF14AMfUInfo(const char *Cmd){ if ( authlim == 0 ){ PrintAndLog("\n--- Known EV1/NTAG passwords."); - int len=0; //if len goes to -1 the connection will be turned off. for (uint8_t i = 0; i < 3; ++i ){ key = default_pwd_pack[i]; if ( len > -1 ){ len = ulev1_requestAuthentication(key, pack, sizeof(pack)); - PrintAndLog("Found a default password: %s || Pack: %02X %02X",sprint_hex(key, 4), pack[0], pack[1]); - break; + if (len == 1) { + PrintAndLog("Found a default password: %s || Pack: %02X %02X",sprint_hex(key, 4), pack[0], pack[1]); + break; + } } } if (len > -1) ul_switch_off_field(); @@ -907,9 +923,12 @@ int usage_hf_mfu_dump(void) PrintAndLog("It autodetects card type.\n"); PrintAndLog("Usage: hf mfu dump s k n "); PrintAndLog(" Options : "); - PrintAndLog(" k : Enter key for authentication"); - PrintAndLog(" n : Enter filename w/o .bin to save the dump as"); - PrintAndLog(" s : Swap entered key's endianness for auth"); + PrintAndLog(" k : key for authentication [UL-C 16bytes, EV1/NTAG 4bytes]"); + PrintAndLog(" l : swap entered key's endianness for auth"); + PrintAndLog(" n : filename w/o .bin to save the dump as"); + PrintAndLog(" p : starting Page number to manually set a page to start the dump at"); + PrintAndLog(" q : number of Pages to manually set how many pages to dump"); + PrintAndLog(""); PrintAndLog(" sample : hf mfu dump"); PrintAndLog(" : hf mfu dump n myfile"); @@ -948,6 +967,8 @@ int CmdHF14AMfUDump(const char *Cmd){ bool swapEndian = false; bool manualPages = false; uint8_t startPage = 0; + char tempStr[50]; + while(param_getchar(Cmd, cmdp) != 0x00) { switch(param_getchar(Cmd, cmdp)) @@ -957,15 +978,25 @@ int CmdHF14AMfUDump(const char *Cmd){ return usage_hf_mfu_dump(); case 'k': case 'K': - dataLen = param_gethex(Cmd, cmdp+1, data, 32); - if (dataLen) { - errors = true; - } else { - memcpy(key, data, 16); - } + dataLen = param_getstr(Cmd, cmdp+1, tempStr); + if (dataLen == 32) //ul-c + errors = param_gethex(tempStr, 0, key, dataLen); + else if (dataLen == 8) //ev1/ntag + errors = param_gethex(tempStr, 0, key, dataLen); + else + errors = true; + + if (!errors) + memcpy(key, data, dataLen/2); + cmdp += 2; hasPwd = true; break; + case 'l': + case 'L': + swapEndian = true; + cmdp++; + break; case 'n': case 'N': fileNlen = param_getstr(Cmd, cmdp+1, filename); @@ -985,17 +1016,6 @@ int CmdHF14AMfUDump(const char *Cmd){ cmdp += 2; manualPages = true; break; - case 's': - case 'S': - swapEndian = true; - cmdp++; - break; - case 't': - case 'T': - //key type - ul-c or ev1/ntag - //TODO - cmdp += 2; - break; default: PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp)); errors = true; @@ -1007,7 +1027,7 @@ int CmdHF14AMfUDump(const char *Cmd){ //Validations if(errors) return usage_hf_mfu_dump(); - if (swapEndian) + if (swapEndian && dataLen == 32) keyPtr = SwapEndian64(data, 16, 8); TagTypeUL_t tagtype = GetHF14AMfU_Type(); @@ -1020,50 +1040,29 @@ int CmdHF14AMfUDump(const char *Cmd){ ul_print_type(tagtype, 0); PrintAndLog("Reading tag memory..."); - /* - if ( tagtype & UL ) { - Pages = 16; - PrintAndLog(str,"", (tagtype & MAGIC)?" (magic)":"" ); + + UsbCommand c = {CMD_MIFAREUC_READCARD, {startPage,Pages}}; + if ( hasPwd ) { + if (tagtype & UL_C) + c.arg[2] = 1; //UL_C auth + else + c.arg[2] = 2; //UL_EV1/NTAG auth + + memcpy(c.d.asBytes, key, dataLen/2); } - else if ( tagtype & UL_C ) { - Pages = 44; - PrintAndLog(str,"-C", (tagtype & MAGIC)?" (magic)":"" ); + SendCommand(&c); + UsbCommand resp; + if (!WaitForResponseTimeout(CMD_ACK, &resp,1500)) { + PrintAndLog("Command execute time-out"); + return 1; } - else if ( tagtype & UL_EV1_48 ) { - Pages = 18; - PrintAndLog(str," EV1_48",""); - } - else if ( tagtype & UL_EV1_128 ) { - Pages = 32; - PrintAndLog(str," EV1_128",""); + PrintAndLog ("%u,%u",resp.arg[0],resp.arg[1]); + uint8_t isOK = resp.arg[0] & 0xff; + if (isOK) { + memcpy(data, resp.d.asBytes, resp.arg[1]); } else { - Pages = 16; - PrintAndLog("Dumping unknown Ultralight, using default values."); - } - */ - if (!hasPwd || (tagtype & UL_C)){ - UsbCommand c = {CMD_MIFAREUC_READCARD, {startPage,Pages}}; - if ( hasPwd ) { - c.arg[2] = 1; - memcpy(c.d.asBytes, key, 16); - } - SendCommand(&c); - UsbCommand resp; - if (!WaitForResponseTimeout(CMD_ACK, &resp,1500)) { - PrintAndLog("Command execute time-out"); - return 1; - } - PrintAndLog ("%u,%u",resp.arg[0],resp.arg[1]); - uint8_t isOK = resp.arg[0] & 0xff; - if (isOK) { - memcpy(data, resp.d.asBytes, resp.arg[1]); - } else { - PrintAndLog("Failed reading block: (%02x)", i); - return 1; - } - } else { - PrintAndLog("EV1 and NTAG pwd mode not ready yet"); - return 0; + PrintAndLog("Failed reading block: (%02x)", i); + return 1; } // Load lock bytes. @@ -1077,6 +1076,7 @@ int CmdHF14AMfUDump(const char *Cmd){ } // Load bottom lockbytes if available + // HOW DOES THIS APPLY TO EV1 and/or NTAG??? if ( Pages == 44 ) { lockbytes_t2 = data + (40*4); lockbytes2[0] = lockbytes_t2[2]; @@ -1087,10 +1087,12 @@ int CmdHF14AMfUDump(const char *Cmd){ } // add keys - if (hasPwd){ + if (hasPwd && dataLen == 32){ //UL_C memcpy(data + Pages*4, key, 16); Pages += 4; - } + } + //TODO add key MEM location for other tags + for (i = 0; i < Pages; ++i) { if ( i < 3 ) { PrintAndLog("Block %02x:%s ", i,sprint_hex(data + i * 4, 4)); @@ -1211,7 +1213,7 @@ int CmdHF14AMfucAuth(const char *Cmd){ } uint8_t *key = default_3des_keys[keyNo]; - if (try3DesAuthentication(key)>0) + if (try3DesAuthentication(key, true) > 0) PrintAndLog("Authentication successful. 3des key: %s",sprint_hex(key, 16)); else PrintAndLog("Authentication failed"); @@ -1219,9 +1221,9 @@ int CmdHF14AMfucAuth(const char *Cmd){ return 0; } -int try3DesAuthentication( uint8_t *key){ +int try3DesAuthentication( uint8_t *key, bool switch_off_field ){ - uint32_t cuid = 0; + //uint32_t cuid = 0; des3_context ctx = { 0 }; @@ -1237,7 +1239,7 @@ int try3DesAuthentication( uint8_t *key){ if ( !WaitForResponseTimeout(CMD_ACK, &resp, 1500) ) return -1; if ( !(resp.arg[0] & 0xff) ) return -2; - cuid = resp.arg[1]; + //cuid = resp.arg[1]; memcpy(enc_random_b,resp.d.asBytes+1,8); des3_set2key_dec(&ctx, key); @@ -1254,7 +1256,7 @@ int try3DesAuthentication( uint8_t *key){ //Auth2 c.cmd = CMD_MIFAREUC_AUTH2; - c.arg[0] = cuid; + c.arg[0] = switch_off_field; memcpy(c.d.asBytes, rnd_ab, 16); SendCommand(&c); diff --git a/client/cmdhfmfu.h b/client/cmdhfmfu.h index 0ec82b2dc..806c27d34 100644 --- a/client/cmdhfmfu.h +++ b/client/cmdhfmfu.h @@ -14,7 +14,7 @@ int CmdHF14AMfUCRdCard(const char *Cmd); int CmdHF14AMfucAuth(const char *Cmd); uint8_t requestAuthentication( uint8_t *nonce); -int try3DesAuthentication( uint8_t *key); +int try3DesAuthentication( uint8_t *key, bool switch_off_field); //general stuff int CmdHF14AMfUDump(const char *Cmd); From 8258f409697ab41a6858ef9bdcdf406989223bbb Mon Sep 17 00:00:00 2001 From: marshmellow42 Date: Sun, 17 May 2015 20:49:25 -0400 Subject: [PATCH 34/49] Iceman1001 s MFU clean up cleaned up MF UL_C auth code device side. --- armsrc/appmain.c | 7 +- armsrc/apps.h | 3 +- armsrc/mifarecmd.c | 230 +++++++++----------------------------------- armsrc/mifareutil.c | 157 +++++++++++++++++++++--------- armsrc/mifareutil.h | 4 +- client/cmdhfmfu.c | 156 +++++++++--------------------- 6 files changed, 211 insertions(+), 346 deletions(-) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 48b8c0dd2..7b94f8a3c 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -826,11 +826,8 @@ void UsbPacketReceived(uint8_t *packet, int len) case CMD_MIFAREU_READBL: MifareUReadBlock(c->arg[0],c->arg[1], c->d.asBytes); break; - case CMD_MIFAREUC_AUTH1: - MifareUC_Auth1(c->arg[0],c->d.asBytes); - break; - case CMD_MIFAREUC_AUTH2: - MifareUC_Auth2(c->arg[0],c->d.asBytes); + case CMD_MIFAREUC_AUTH: + MifareUC_Auth(c->arg[0],c->d.asBytes); break; case CMD_MIFAREU_READCARD: case CMD_MIFAREUC_READCARD: diff --git a/armsrc/apps.h b/armsrc/apps.h index d325dbe8d..57fb55fd3 100644 --- a/armsrc/apps.h +++ b/armsrc/apps.h @@ -166,8 +166,7 @@ void ReaderMifare(bool first_try); int32_t dist_nt(uint32_t nt1, uint32_t nt2); 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_Auth1(uint8_t arg0, uint8_t *datain); -void MifareUC_Auth2(uint8_t arg0, 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); diff --git a/armsrc/mifarecmd.c b/armsrc/mifarecmd.c index cf36b95a0..1f8f4ee8e 100644 --- a/armsrc/mifarecmd.c +++ b/armsrc/mifarecmd.c @@ -17,7 +17,6 @@ #include "apps.h" #include "util.h" -#include "des.h" #include "crc.h" // the block number for the ISO14443-4 PCB @@ -93,53 +92,28 @@ void MifareReadBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) LEDsoff(); } -void MifareUC_Auth1(uint8_t arg0, uint8_t *datain){ +void MifareUC_Auth(uint8_t arg0, uint8_t *keybytes){ - byte_t dataoutbuf[16] = {0x00}; - uint8_t uid[10] = {0x00}; - uint32_t cuid = 0x00; + bool turnOffField = (arg0 == 1); LED_A_ON(); LED_B_OFF(); LED_C_OFF(); - clear_trace(); iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); - if(!iso14443a_select_card(uid, NULL, &cuid)) { + if(!iso14443a_select_card(NULL, NULL, NULL)) { if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Can't select card"); OnError(0); return; }; - if(mifare_ultra_auth1(dataoutbuf)){ - if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Authentication part1: Fail."); + if(mifare_ultra_auth(keybytes) == 1){ + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Authentication failed"); OnError(1); return; } + cmd_send(CMD_ACK,1,0,0,0,0); - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) DbpString("AUTH 1 FINISHED"); - - cmd_send(CMD_ACK,1,cuid,0,dataoutbuf,11); - LEDsoff(); -} -void MifareUC_Auth2(uint8_t arg0, uint8_t *datain){ - - uint8_t key[16] = {0x00}; - byte_t dataoutbuf[16] = {0x00}; - - memcpy(key, datain, 16); - - LED_A_ON(); LED_B_OFF(); LED_C_OFF(); - - if(mifare_ultra_auth2(key, dataoutbuf)){ - if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Authentication part2: Fail..."); - OnError(1); - return; - } - - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) DbpString("AUTH 2 FINISHED"); - - cmd_send(CMD_ACK,1,0,0,dataoutbuf,11); - if (arg0) { + if (turnOffField) { FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LEDsoff(); } @@ -152,125 +126,56 @@ void MifareUReadBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain) { uint8_t blockNo = arg0; byte_t dataout[16] = {0x00}; - uint8_t uid[10] = {0x00}; - uint8_t key[16] = {0x00}; - bool usePwd = (arg1 == 1); + bool useKey = (arg1 == 1); //UL_C + bool usePwd = (arg1 == 2); //UL_EV1/NTAG LEDsoff(); LED_A_ON(); clear_trace(); iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); - int len = iso14443a_select_card(uid, NULL, NULL); + int len = iso14443a_select_card(NULL, NULL, NULL); if(!len) { if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Can't select card (RC:%02X)",len); OnError(1); return; } - // authenticate here. - if ( usePwd ) { + // UL-C authentication + if ( useKey ) { + uint8_t key[16] = {0x00}; + memcpy(key, datain, sizeof(key) ); - memcpy(key, datain, 16); - - // Dbprintf("KEY: %02x %02x %02x %02x %02x %02x %02x %02x", key[0],key[1],key[2],key[3],key[4],key[5],key[6],key[7] ); - // Dbprintf("KEY: %02x %02x %02x %02x %02x %02x %02x %02x", key[8],key[9],key[10],key[11],key[12],key[13],key[14],key[15] ); - - uint8_t random_a[8] = {1,1,1,1,1,1,1,1 }; - uint8_t random_b[8] = {0x00}; - uint8_t enc_random_b[8] = {0x00}; - uint8_t rnd_ab[16] = {0x00}; - uint8_t IV[8] = {0x00}; - - uint16_t len; - uint8_t receivedAnswer[MAX_FRAME_SIZE]; - uint8_t receivedAnswerPar[MAX_PARITY_SIZE]; - - len = mifare_sendcmd_short(NULL, 1, 0x1A, 0x00, receivedAnswer,receivedAnswerPar ,NULL); - if (len != 11) { - if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x", receivedAnswer[0]); + if ( mifare_ultra_auth(key) == 1 ) { OnError(1); return; } - - // tag nonce. - memcpy(enc_random_b,receivedAnswer+1,8); - - // decrypt nonce. - tdes_2key_dec(random_b, enc_random_b, sizeof(random_b), key, IV ); - rol(random_b,8); - memcpy(rnd_ab ,random_a,8); - memcpy(rnd_ab+8,random_b,8); - - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) { - Dbprintf("enc_B: %02x %02x %02x %02x %02x %02x %02x %02x", - enc_random_b[0],enc_random_b[1],enc_random_b[2],enc_random_b[3], - enc_random_b[4],enc_random_b[5],enc_random_b[6],enc_random_b[7]); - - Dbprintf(" B: %02x %02x %02x %02x %02x %02x %02x %02x", - random_b[0],random_b[1],random_b[2],random_b[3], - random_b[4],random_b[5],random_b[6],random_b[7]); - - Dbprintf("rnd_ab: %02x %02x %02x %02x %02x %02x %02x %02x", - rnd_ab[0],rnd_ab[1],rnd_ab[2],rnd_ab[3], - rnd_ab[4],rnd_ab[5],rnd_ab[6],rnd_ab[7]); - - Dbprintf("rnd_ab: %02x %02x %02x %02x %02x %02x %02x %02x", - rnd_ab[8],rnd_ab[9],rnd_ab[10],rnd_ab[11], - rnd_ab[12],rnd_ab[13],rnd_ab[14],rnd_ab[15] ); - } - - // encrypt out, in, length, key, iv - tdes_2key_enc(rnd_ab, rnd_ab, sizeof(rnd_ab), key, enc_random_b); - - len = mifare_sendcmd_short_mfucauth(NULL, 1, 0xAF, rnd_ab, receivedAnswer, receivedAnswerPar, NULL); - if (len != 11) { - if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x", receivedAnswer[0]); - OnError(1); - return; - } - - uint8_t enc_resp[8] = { 0 }; - uint8_t resp_random_a[8] = { 0 }; - memcpy(enc_resp, receivedAnswer+1, 8); - - // decrypt out, in, length, key, iv - tdes_2key_dec(resp_random_a, enc_resp, 8, key, enc_random_b); - if ( memcmp(resp_random_a, random_a, 8) != 0 ) - Dbprintf("failed authentication"); - - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) { - Dbprintf("e_AB: %02x %02x %02x %02x %02x %02x %02x %02x", - rnd_ab[0],rnd_ab[1],rnd_ab[2],rnd_ab[3], - rnd_ab[4],rnd_ab[5],rnd_ab[6],rnd_ab[7]); - - Dbprintf("e_AB: %02x %02x %02x %02x %02x %02x %02x %02x", - rnd_ab[8],rnd_ab[9],rnd_ab[10],rnd_ab[11], - rnd_ab[12],rnd_ab[13],rnd_ab[14],rnd_ab[15]); - - Dbprintf("a: %02x %02x %02x %02x %02x %02x %02x %02x", - random_a[0],random_a[1],random_a[2],random_a[3], - random_a[4],random_a[5],random_a[6],random_a[7]); - - Dbprintf("b: %02x %02x %02x %02x %02x %02x %02x %02x", - resp_random_a[0],resp_random_a[1],resp_random_a[2],resp_random_a[3], - resp_random_a[4],resp_random_a[5],resp_random_a[6],resp_random_a[7]); - } } - + + // UL-EV1 / NTAG authentication + if ( usePwd ) { + uint8_t pwd[4] = {0x00}; + memcpy(pwd, datain, 4); + uint8_t pack[4] = {0,0,0,0}; + if (mifare_ul_ev1_auth(pwd, pack) == 1) { + OnError(1); + return; + } + } + if( mifare_ultra_readblock(blockNo, dataout) ) { if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Read block error"); OnError(2); return; } - + if( mifare_ultra_halt() ) { if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Halt error"); OnError(3); return; } - - cmd_send(CMD_ACK,1,0,0,dataout,16); + + cmd_send(CMD_ACK,1,0,0,dataout,16); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LEDsoff(); } @@ -365,64 +270,25 @@ void MifareUReadCard(uint8_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain) return; } - // authenticate + // UL-C authentication if ( useKey ) { uint8_t key[16] = {0x00}; - memcpy(key, datain, 16); + memcpy(key, datain, sizeof(key) ); - uint8_t random_a[8] = {1,1,1,1,1,1,1,1 }; - uint8_t random_b[8] = {0x00}; - uint8_t enc_random_b[8] = {0x00}; - uint8_t rnd_ab[16] = {0x00}; - uint8_t IV[8] = {0x00}; - - uint16_t len2; - uint8_t receivedAnswer[MAX_FRAME_SIZE]; - uint8_t receivedAnswerPar[MAX_PARITY_SIZE]; - - len2 = mifare_sendcmd_short(NULL, 1, 0x1A, 0x00, receivedAnswer,receivedAnswerPar ,NULL); - if (len2 != 11) { - if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x", receivedAnswer[0]); + if ( mifare_ultra_auth(key) == 1 ) { OnError(1); return; } - - // tag nonce. - memcpy(enc_random_b,receivedAnswer+1,8); - - // decrypt nonce. - tdes_2key_dec(random_b, enc_random_b, sizeof(random_b), key, IV ); - rol(random_b,8); - memcpy(rnd_ab ,random_a,8); - memcpy(rnd_ab+8,random_b,8); - - // encrypt out, in, length, key, iv - tdes_2key_enc(rnd_ab, rnd_ab, sizeof(rnd_ab), key, enc_random_b); - - len2 = mifare_sendcmd_short_mfucauth(NULL, 1, 0xAF, rnd_ab, receivedAnswer, receivedAnswerPar, NULL); - if (len2 != 11) { - OnError(1); - return; - } - - uint8_t enc_resp[8] = { 0 }; - uint8_t resp_random_a[8] = { 0 }; - memcpy(enc_resp, receivedAnswer+1, 8); - - // decrypt out, in, length, key, iv - tdes_2key_dec(resp_random_a, enc_resp, 8, key, enc_random_b); - if ( memcmp(resp_random_a, random_a, 8) != 0 ) - Dbprintf("failed authentication"); } - if (usePwd) { //ev1 or ntag auth - uint8_t Pwd[4] = {0x00}; - memcpy(Pwd, datain, 4); + // UL-EV1 / NTAG authentication + if (usePwd) { + uint8_t pwd[4] = {0x00}; + memcpy(pwd, datain, sizeof(pwd)); uint8_t pack[4] = {0,0,0,0}; - if (mifare_ul_ev1_auth(Pwd, pack)){ + if (mifare_ul_ev1_auth(pwd, pack) == 1){ OnError(1); - Dbprintf("failed authentication"); return; } } @@ -569,16 +435,15 @@ void MifareUWriteBlock_Special(uint8_t arg0, uint8_t *datain) { uint8_t blockNo = arg0; byte_t blockdata[4] = {0x00}; - - memcpy(blockdata, datain,4); - uint8_t uid[10] = {0x00}; + memcpy(blockdata, datain,4); - LED_A_ON(); LED_B_OFF(); LED_C_OFF(); + LEDsoff(); + LED_A_ON(); clear_trace(); iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); - if(!iso14443a_select_card(uid, NULL, NULL)) { + if(!iso14443a_select_card(NULL, NULL, NULL)) { if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card"); OnError(0); return; @@ -1320,21 +1185,18 @@ void Mifare_DES_Auth1(uint8_t arg0, uint8_t *datain){ int len = iso14443a_select_card(uid, NULL, &cuid); if(!len) { - if (MF_DBGLEVEL >= MF_DBG_ERROR) - Dbprintf("Can't select card"); - //OnError(1); + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Can't select card"); + OnError(1); return; }; if(mifare_desfire_des_auth1(cuid, dataout)){ - if (MF_DBGLEVEL >= MF_DBG_ERROR) - Dbprintf("Authentication part1: Fail."); - //OnError(4); + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Authentication part1: Fail."); + OnError(4); return; } if (MF_DBGLEVEL >= MF_DBG_EXTENDED) DbpString("AUTH 1 FINISHED"); - cmd_send(CMD_ACK,1,cuid,0,dataout, sizeof(dataout)); } diff --git a/armsrc/mifareutil.c b/armsrc/mifareutil.c index cc54b7402..0469364c3 100644 --- a/armsrc/mifareutil.c +++ b/armsrc/mifareutil.c @@ -18,6 +18,7 @@ #include "iso14443a.h" #include "crapto1.h" #include "mifareutil.h" +#include "des.h" int MF_DBGLEVEL = MF_DBG_ALL; @@ -110,6 +111,27 @@ int mifare_sendcmd_short_mfucauth(struct Crypto1State *pcs, uint8_t crypted, uin return len; } +int mifare_sendcmd_short_mfuev1auth(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t *data, uint8_t *answer, uint8_t *answer_parity, uint32_t *timing) +{ + uint8_t dcmd[7]; + int len; + dcmd[0] = cmd; + memcpy(dcmd+1,data,4); + AppendCrc14443a(dcmd, 5); + + ReaderTransmit(dcmd, sizeof(dcmd), timing); + len = ReaderReceive(answer, answer_parity); + if(!len) { + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Authentication failed. Card timeout."); + len = ReaderReceive(answer,answer_parity); + } + if(len==1) { + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("NAK - Authentication failed."); + return 1; + } + return len; +} + int mifare_sendcmd_shortex(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t data, uint8_t *answer, uint8_t *answer_parity, uint32_t *timing) { uint8_t dcmd[4], ecmd[4]; @@ -288,67 +310,114 @@ int mifare_classic_readblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blo } // mifare ultralight commands -int mifare_ul_ev1_auth(uint8_t *key, uint8_t *pack){ +int mifare_ul_ev1_auth(uint8_t *keybytes, uint8_t *pack){ uint16_t len; - uint8_t receivedAnswer[MAX_FRAME_SIZE]; - uint8_t receivedAnswerPar[MAX_PARITY_SIZE]; - - len = mifare_sendcmd_short_mfucauth(NULL, 0, 0x1B, key, receivedAnswer, receivedAnswerPar, NULL); + uint8_t resp[4]; + uint8_t respPar[1]; + uint8_t key[4] = {0x00}; + memcpy(key, keybytes, 4); + + Dbprintf("EV1 Auth : %02x%02x%02x%02x", key[0], key[1], key[2], key[3]); + 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", receivedAnswer[0], len); + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x %u", resp[0], len); + OnError(1); return 1; } - - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) { - Dbprintf("Auth Resp: %02x%02x%02x%02x", - receivedAnswer[0],receivedAnswer[1],receivedAnswer[2],receivedAnswer[3]); - } - memcpy(pack, receivedAnswer, 4); + + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) + Dbprintf("Auth Resp: %02x%02x%02x%02x", resp[0],resp[1],resp[2],resp[3]); + + memcpy(pack, resp, 4); return 0; } -int mifare_ultra_auth1(uint8_t *blockData){ +int mifare_ultra_auth(uint8_t *keybytes){ + + /// 3des2k + + uint8_t random_a[8] = {1,1,1,1,1,1,1,1}; + uint8_t random_b[8] = {0x00}; + uint8_t enc_random_b[8] = {0x00}; + uint8_t rnd_ab[16] = {0x00}; + uint8_t IV[8] = {0x00}; + uint8_t key[16] = {0x00}; + memcpy(key, keybytes, 16); uint16_t len; - uint8_t receivedAnswer[MAX_FRAME_SIZE]; - uint8_t receivedAnswerPar[MAX_PARITY_SIZE]; - - len = mifare_sendcmd_short(NULL, 1, 0x1A, 0x00, receivedAnswer,receivedAnswerPar ,NULL); + uint8_t resp[19] = {0x00}; + uint8_t respPar[3] = {0,0,0}; + + // REQUEST AUTHENTICATION + len = mifare_sendcmd_short(NULL, 1, 0x1A, 0x00, resp, respPar ,NULL); if (len != 11) { - if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x", receivedAnswer[0]); + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x", resp[0]); + OnError(1); + return 1; + } + + // tag nonce. + memcpy(enc_random_b,resp+1,8); + + // decrypt nonce. + tdes_2key_dec(random_b, enc_random_b, sizeof(random_b), key, IV ); + rol(random_b,8); + memcpy(rnd_ab ,random_a,8); + memcpy(rnd_ab+8,random_b,8); + + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) { + Dbprintf("enc_B: %02x %02x %02x %02x %02x %02x %02x %02x", + enc_random_b[0],enc_random_b[1],enc_random_b[2],enc_random_b[3],enc_random_b[4],enc_random_b[5],enc_random_b[6],enc_random_b[7]); + + Dbprintf(" B: %02x %02x %02x %02x %02x %02x %02x %02x", + random_b[0],random_b[1],random_b[2],random_b[3],random_b[4],random_b[5],random_b[6],random_b[7]); + + Dbprintf("rnd_ab: %02x %02x %02x %02x %02x %02x %02x %02x", + rnd_ab[0],rnd_ab[1],rnd_ab[2],rnd_ab[3],rnd_ab[4],rnd_ab[5],rnd_ab[6],rnd_ab[7]); + + Dbprintf("rnd_ab: %02x %02x %02x %02x %02x %02x %02x %02x", + rnd_ab[8],rnd_ab[9],rnd_ab[10],rnd_ab[11],rnd_ab[12],rnd_ab[13],rnd_ab[14],rnd_ab[15] ); + } + + // encrypt out, in, length, key, iv + tdes_2key_enc(rnd_ab, rnd_ab, sizeof(rnd_ab), key, enc_random_b); + + len = mifare_sendcmd_short_mfucauth(NULL, 1, 0xAF, rnd_ab, resp, respPar, NULL); + if (len != 11) { + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x", resp[0]); + OnError(1); + return 1; + } + + uint8_t enc_resp[8] = { 0,0,0,0,0,0,0,0 }; + uint8_t resp_random_a[8] = { 0,0,0,0,0,0,0,0 }; + memcpy(enc_resp, resp+1, 8); + + // decrypt out, in, length, key, iv + tdes_2key_dec(resp_random_a, enc_resp, 8, key, enc_random_b); + if ( memcmp(resp_random_a, random_a, 8) != 0 ) { + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("failed authentication"); return 1; } if (MF_DBGLEVEL >= MF_DBG_EXTENDED) { - Dbprintf("Auth1 Resp: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", - receivedAnswer[0],receivedAnswer[1],receivedAnswer[2],receivedAnswer[3],receivedAnswer[4], - receivedAnswer[5],receivedAnswer[6],receivedAnswer[7],receivedAnswer[8],receivedAnswer[9], - receivedAnswer[10]); - } - memcpy(blockData, receivedAnswer, 11); - return 0; -} + Dbprintf("e_AB: %02x %02x %02x %02x %02x %02x %02x %02x", + rnd_ab[0],rnd_ab[1],rnd_ab[2],rnd_ab[3], + rnd_ab[4],rnd_ab[5],rnd_ab[6],rnd_ab[7]); -int mifare_ultra_auth2(uint8_t *key, uint8_t *blockData){ + Dbprintf("e_AB: %02x %02x %02x %02x %02x %02x %02x %02x", + rnd_ab[8],rnd_ab[9],rnd_ab[10],rnd_ab[11], + rnd_ab[12],rnd_ab[13],rnd_ab[14],rnd_ab[15]); - uint16_t len; - uint8_t receivedAnswer[MAX_FRAME_SIZE]; - uint8_t receivedAnswerPar[MAX_PARITY_SIZE]; - - len = mifare_sendcmd_short_mfucauth(NULL, 1, 0xAF, key, receivedAnswer, receivedAnswerPar, NULL); - if (len != 11) { - if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x", receivedAnswer[0]); - return 1; + Dbprintf("a: %02x %02x %02x %02x %02x %02x %02x %02x", + random_a[0],random_a[1],random_a[2],random_a[3], + random_a[4],random_a[5],random_a[6],random_a[7]); + + Dbprintf("b: %02x %02x %02x %02x %02x %02x %02x %02x", + resp_random_a[0],resp_random_a[1],resp_random_a[2],resp_random_a[3], + resp_random_a[4],resp_random_a[5],resp_random_a[6],resp_random_a[7]); } - - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) { - Dbprintf("Auth2 Resp: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", - receivedAnswer[0],receivedAnswer[1],receivedAnswer[2],receivedAnswer[3],receivedAnswer[4], - receivedAnswer[5],receivedAnswer[6],receivedAnswer[7],receivedAnswer[8],receivedAnswer[9], - receivedAnswer[10]); - } - memcpy(blockData, receivedAnswer, 11); return 0; } @@ -380,8 +449,6 @@ int mifare_ultra_readblock(uint8_t blockNo, uint8_t *blockData) return 0; } - - int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData) { // variables diff --git a/armsrc/mifareutil.h b/armsrc/mifareutil.h index 03a545b48..d4fcd8189 100644 --- a/armsrc/mifareutil.h +++ b/armsrc/mifareutil.h @@ -57,14 +57,14 @@ int mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, int mifare_sendcmd_short_special(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t *data, uint8_t* answer, uint8_t *answer_parity, uint32_t *timing); int mifare_sendcmd_short_mfucauth(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t *data, uint8_t *answer, uint8_t *answer_parity, uint32_t *timing); +int mifare_sendcmd_short_mfuev1auth(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t *data, uint8_t *answer, uint8_t *answer_parity, uint32_t *timing); int mifare_sendcmd_shortex(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t data, uint8_t* answer, uint8_t *answer_parity, uint32_t *timing); int mifare_classic_auth(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested); int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested, uint32_t * ntptr, uint32_t *timing); int mifare_classic_readblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData); int mifare_ul_ev1_auth(uint8_t *key, uint8_t *pack); -int mifare_ultra_auth1(uint8_t *blockData); -int mifare_ultra_auth2(uint8_t *key, uint8_t *blockData); +int mifare_ultra_auth(uint8_t *key); int mifare_ultra_readblock(uint8_t blockNo, uint8_t *blockData); int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData); int mifare_ultra_writeblock(uint8_t blockNo, uint8_t *blockData); diff --git a/client/cmdhfmfu.c b/client/cmdhfmfu.c index a502a23d9..a22ff8597 100644 --- a/client/cmdhfmfu.c +++ b/client/cmdhfmfu.c @@ -34,12 +34,16 @@ uint8_t default_3des_keys[KEYS_3DES_COUNT][16] = { { 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xAA,0xBB,0xCC,0xDD,0xEE,0xFF } // 11 22 33 }; -#define KEYS_PWD_COUNT 8 +#define KEYS_PWD_COUNT 10 uint8_t default_pwd_pack[KEYS_PWD_COUNT][4] = { {0xFF,0xFF,0xFF,0xFF}, // PACK 0x00,0x00 -- factory default + {0x4A,0xF8,0x4B,0x19}, // PACK 0xE5,0xBE -- italian bus (sniffed) {0x33,0x6B,0xA1,0x19}, // PACK 0x9c,0x2d -- italian bus (sniffed) {0xFF,0x90,0x6C,0xB2}, // PACK 0x12,0x9e -- italian bus (sniffed) + {0x46,0x1c,0xA3,0x19}, // PACK 0xE9,0x5A -- italian bus (sniffed) + {0x35,0x1C,0xD0,0x19}, // PACK 0x9A,0x5a -- italian bus (sniffed) + {0x05,0x22,0xE6,0xB4}, // PACK 0x80,0x80 -- Amiiboo (sniffed) pikachu-b UID: {0x7E,0x22,0xE6,0xB4}, // PACK 0x80,0x80 -- AMiiboo (sniffed) {0x02,0xE1,0xEE,0x36}, // PACK 0x80,0x80 -- AMiiboo (sniffed) sonic UID: 04d257 7ae33e8027 @@ -56,20 +60,20 @@ uint8_t UL_MEMORY_ARRAY[MAX_UL_TYPES] = {MAX_UL_BLOCKS, MAX_UL_BLOCKS, MAX_ULC_B static int CmdHelp(const char *Cmd); -char* getProductTypeStr( uint8_t id){ +char *getProductTypeStr( uint8_t id){ static char buf[20]; char *retStr = buf; switch(id) { case 3: - sprintf(retStr, "0x%02X %s", id, "(Ultralight)"); + sprintf(retStr, "%02X %s", id, "(Ultralight)"); break; case 4: - sprintf(retStr, "0x%02X %s", id, "(NTAG)"); + sprintf(retStr, "%02X %s", id, "(NTAG)"); break; default: - sprintf(retStr, "0x%02X %s", id, "(unknown)"); + sprintf(retStr, "%02X %s", id, "(unknown)"); break; } return buf; @@ -80,7 +84,7 @@ char* getProductTypeStr( uint8_t id){ the LSBit is set to '0' if the size is exactly 2^n and set to '1' if the storage size is between 2^n and 2^(n+1). */ -char* getUlev1CardSizeStr( uint8_t fsize ){ +char *getUlev1CardSizeStr( uint8_t fsize ){ static char buf[40]; char *retStr = buf; @@ -153,8 +157,6 @@ static int ul_read( uint8_t page, uint8_t *response, uint16_t responseLength ){ uint8_t cmd[] = {ISO14443A_CMD_READBLOCK, page}; int len = ul_send_cmd_raw(cmd, sizeof(cmd), response, responseLength); - if ( len == -1 ) - ul_switch_off_field(); return len; } @@ -169,9 +171,7 @@ static int ul_comp_write( uint8_t page, uint8_t *data, uint8_t datalen ){ memcpy(cmd+2, data, datalen); uint8_t response[1] = {0xff}; - int len = ul_send_cmd_raw(cmd, 2+datalen, response, sizeof(response)); - if ( len == -1 ) - ul_switch_off_field(); + ul_send_cmd_raw(cmd, 2+datalen, response, sizeof(response)); // ACK if ( response[0] == 0x0a ) return 0; // NACK @@ -182,17 +182,25 @@ static int ulc_requestAuthentication( uint8_t *nonce, uint16_t nonceLength ){ uint8_t cmd[] = {MIFARE_ULC_AUTH_1, 0x00}; int len = ul_send_cmd_raw(cmd, sizeof(cmd), nonce, nonceLength); - if ( len == -1 ) - ul_switch_off_field(); return len; } +static int ulc_authentication( uint8_t *key, bool switch_off_field ){ + + UsbCommand c = {CMD_MIFAREUC_AUTH, {switch_off_field}}; + memcpy(c.d.asBytes, key, 16); + SendCommand(&c); + UsbCommand resp; + if ( !WaitForResponseTimeout(CMD_ACK, &resp, 1500) ) return -1; + if ( resp.arg[0] == 1 ) return 0; + + return -2; +} + static int ulev1_requestAuthentication( uint8_t *pwd, uint8_t *pack, uint16_t packLength ){ uint8_t cmd[] = {MIFARE_ULEV1_AUTH, pwd[0], pwd[1], pwd[2], pwd[3]}; int len = ul_send_cmd_raw(cmd, sizeof(cmd), pack, packLength); - if ( len == -1) - ul_switch_off_field(); return len; } @@ -200,8 +208,6 @@ static int ulev1_getVersion( uint8_t *response, uint16_t responseLength ){ uint8_t cmd[] = {MIFARE_ULEV1_VERSION}; int len = ul_send_cmd_raw(cmd, sizeof(cmd), response, responseLength); - if ( len == -1 ) - ul_switch_off_field(); return len; } @@ -210,7 +216,6 @@ static int ulev1_getVersion( uint8_t *response, uint16_t responseLength ){ // uint8_t cmd[] = {MIFARE_ULEV1_FASTREAD, startblock, endblock}; // if ( !ul_send_cmd_raw(cmd, sizeof(cmd), response)){ - // ul_switch_off_field(); // return -1; // } // return 0; @@ -220,8 +225,6 @@ static int ulev1_readCounter( uint8_t counter, uint8_t *response, uint16_t respo uint8_t cmd[] = {MIFARE_ULEV1_READ_CNT, counter}; int len = ul_send_cmd_raw(cmd, sizeof(cmd), response, responseLength); - if (len == -1) - ul_switch_off_field(); return len; } @@ -229,8 +232,6 @@ static int ulev1_readTearing( uint8_t counter, uint8_t *response, uint16_t respo uint8_t cmd[] = {MIFARE_ULEV1_CHECKTEAR, counter}; int len = ul_send_cmd_raw(cmd, sizeof(cmd), response, responseLength); - if (len == -1) - ul_switch_off_field(); return len; } @@ -238,15 +239,12 @@ static int ulev1_readSignature( uint8_t *response, uint16_t responseLength ){ uint8_t cmd[] = {MIFARE_ULEV1_READSIG, 0x00}; int len = ul_send_cmd_raw(cmd, sizeof(cmd), response, responseLength); - if (len == -1) - ul_switch_off_field(); return len; } static int ul_print_default( uint8_t *data){ uint8_t uid[7]; - uid[0] = data[0]; uid[1] = data[1]; uid[2] = data[2]; @@ -504,7 +502,7 @@ uint16_t GetHF14AMfU_Type(void){ status = ul_select(&card); if ( status < 1 ){ - PrintAndLog("Error: couldn't select"); + PrintAndLog("iso14443a card select failed"); ul_switch_off_field(); return UL_ERROR; } @@ -518,7 +516,7 @@ uint16_t GetHF14AMfU_Type(void){ if ( card.uid[0] != 0x05) { len = ulev1_getVersion(version, sizeof(version)); - if (len > -1) ul_switch_off_field(); //if -1 it is already off + ul_switch_off_field(); switch (len) { case 0x0A: { @@ -551,11 +549,11 @@ uint16_t GetHF14AMfU_Type(void){ ul_switch_off_field(); return UL_ERROR; } - uint8_t nonce1[11] = {0x00}; - status = ulc_requestAuthentication(nonce1, sizeof(nonce1)); + uint8_t nonce[11] = {0x00}; + status = ulc_requestAuthentication(nonce, sizeof(nonce)); tagtype = ( status > 0 ) ? UL_C : UL; - if (status != -1) ul_switch_off_field(); + ul_switch_off_field(); } } else { // Infinition MY-D tests Exam high nibble @@ -642,9 +640,8 @@ int CmdHF14AMfUInfo(const char *Cmd){ if ( hasAuthKey ) { if ((tagtype & UL_C)) { - ul_switch_off_field(); //will select card automatically - if (try3DesAuthentication(authenticationkey, false) != 1) { + if (ulc_authentication(authenticationkey, false) != 0) { ul_switch_off_field(); PrintAndLog("Error: Authentication Failed UL-C"); return 0; @@ -652,7 +649,7 @@ int CmdHF14AMfUInfo(const char *Cmd){ } else { len = ulev1_requestAuthentication(authenticationkey, pack, sizeof(pack)); if (len < 1) { - if (!len) ul_switch_off_field(); + ul_switch_off_field(); PrintAndLog("Error: Authentication Failed UL-EV1/NTAG"); return 0; } @@ -663,6 +660,7 @@ int CmdHF14AMfUInfo(const char *Cmd){ // read pages 0,1,2,4 (should read 4pages) status = ul_read(0, data, sizeof(data)); if ( status == -1 ){ + ul_switch_off_field(); PrintAndLog("Error: tag didn't answer to READ"); return status; } @@ -685,6 +683,7 @@ int CmdHF14AMfUInfo(const char *Cmd){ uint8_t ulc_deskey[16] = {0x00}; status = ul_read(0x2C, ulc_deskey, sizeof(ulc_deskey)); if ( status == -1 ){ + ul_switch_off_field(); PrintAndLog("Error: tag didn't answer to READ magic"); return status; } @@ -695,17 +694,18 @@ int CmdHF14AMfUInfo(const char *Cmd){ if ( hasAuthKey ) return 1; PrintAndLog("Trying some default 3des keys"); - ul_switch_off_field(); //will select again in try3DesAuth... for (uint8_t i = 0; i < KEYS_3DES_COUNT; ++i ){ key = default_3des_keys[i]; - if (try3DesAuthentication(key, true) == 1){ + if (ulc_authentication(key, true) == 0){ PrintAndLog("Found default 3des key: "); //%s", sprint_hex(key,16)); uint8_t keySwap[16]; memcpy(keySwap, SwapEndian64(key,16,8), 16); ulc_print_3deskey(keySwap); + ul_switch_off_field(); return 1; } } + ul_switch_off_field(); return 1; //return even if key not found (UL_C is done) } } @@ -718,6 +718,7 @@ int CmdHF14AMfUInfo(const char *Cmd){ status = ulev1_readSignature( ulev1_signature, sizeof(ulev1_signature)); if ( status == -1 ){ PrintAndLog("Error: tag didn't answer to READ SIGNATURE"); + ul_switch_off_field(); return status; } ulev1_print_signature( ulev1_signature, sizeof(ulev1_signature)); @@ -727,6 +728,7 @@ int CmdHF14AMfUInfo(const char *Cmd){ status = ul_read(startconfigblock, ulev1_conf, sizeof(ulev1_conf)); if ( status == -1 ){ PrintAndLog("Error: tag didn't answer to READ EV1"); + ul_switch_off_field(); return status; } // save AUTHENTICATION LIMITS for later: @@ -745,12 +747,16 @@ int CmdHF14AMfUInfo(const char *Cmd){ status = ulev1_getVersion(version, sizeof(version)); if ( status == -1 ){ PrintAndLog("Error: tag didn't answer to GETVERSION"); + ul_switch_off_field(); return status; } ulev1_print_version(version); // if we called info with key, just return - if ( hasAuthKey ) return 1; + if ( hasAuthKey ) { + ul_switch_off_field(); + return 1; + } // AUTHLIMIT, (number of failed authentications) // 0 = limitless. @@ -768,7 +774,6 @@ int CmdHF14AMfUInfo(const char *Cmd){ } } } - if (len > -1) ul_switch_off_field(); } } @@ -985,9 +990,6 @@ int CmdHF14AMfUDump(const char *Cmd){ errors = param_gethex(tempStr, 0, key, dataLen); else errors = true; - - if (!errors) - memcpy(key, data, dataLen/2); cmdp += 2; hasPwd = true; @@ -1087,11 +1089,10 @@ int CmdHF14AMfUDump(const char *Cmd){ } // add keys - if (hasPwd && dataLen == 32){ //UL_C - memcpy(data + Pages*4, key, 16); + if (hasPwd){ //UL_C + memcpy(data + Pages*4, key, dataLen/2); Pages += 4; } - //TODO add key MEM location for other tags for (i = 0; i < Pages; ++i) { if ( i < 3 ) { @@ -1165,6 +1166,7 @@ int CmdHF14AMfUDump(const char *Cmd){ return 0; } +/* // Needed to Authenticate to Ultralight C tags void rol (uint8_t *data, const size_t len){ uint8_t first = data[0]; @@ -1173,6 +1175,7 @@ void rol (uint8_t *data, const size_t len){ } data[len-1] = first; } +*/ //------------------------------------------------------------------------------- // Ultralight C Methods @@ -1191,7 +1194,7 @@ int CmdHF14AMfucAuth(const char *Cmd){ //Change key to user defined one if (cmdp == 'k' || cmdp == 'K'){ keyNo = param_get8(Cmd, 1); - if(keyNo > 6) + if(keyNo > KEYS_3DES_COUNT) errors = true; } @@ -1213,7 +1216,7 @@ int CmdHF14AMfucAuth(const char *Cmd){ } uint8_t *key = default_3des_keys[keyNo]; - if (try3DesAuthentication(key, true) > 0) + if (ulc_authentication(key, true) == 0) PrintAndLog("Authentication successful. 3des key: %s",sprint_hex(key, 16)); else PrintAndLog("Authentication failed"); @@ -1221,68 +1224,6 @@ int CmdHF14AMfucAuth(const char *Cmd){ return 0; } -int try3DesAuthentication( uint8_t *key, bool switch_off_field ){ - - //uint32_t cuid = 0; - - des3_context ctx = { 0 }; - - uint8_t random_a[8] = { 1,1,1,1,1,1,1,1 }; - uint8_t random_b[8] = { 0 }; - uint8_t enc_random_b[8] = { 0 }; - uint8_t rnd_ab[16] = { 0 }; - uint8_t iv[8] = { 0 }; - - UsbCommand c = {CMD_MIFAREUC_AUTH1, {0x00}}; - SendCommand(&c); - UsbCommand resp; - if ( !WaitForResponseTimeout(CMD_ACK, &resp, 1500) ) return -1; - if ( !(resp.arg[0] & 0xff) ) return -2; - - //cuid = resp.arg[1]; - memcpy(enc_random_b,resp.d.asBytes+1,8); - - des3_set2key_dec(&ctx, key); - // context, mode, length, IV, input, output - des3_crypt_cbc( &ctx, DES_DECRYPT, sizeof(random_b), iv , enc_random_b , random_b); - - rol(random_b,8); - memcpy(rnd_ab ,random_a,8); - memcpy(rnd_ab+8,random_b,8); - - des3_set2key_enc(&ctx, key); - // context, mode, length, IV, input, output - des3_crypt_cbc(&ctx, DES_ENCRYPT, sizeof(rnd_ab), enc_random_b, rnd_ab, rnd_ab); - - //Auth2 - c.cmd = CMD_MIFAREUC_AUTH2; - c.arg[0] = switch_off_field; - memcpy(c.d.asBytes, rnd_ab, 16); - SendCommand(&c); - - if ( !WaitForResponseTimeout(CMD_ACK, &resp, 1500)) return -1; - if ( !(resp.arg[0] & 0xff)) return -2; - - uint8_t enc_resp[8] = { 0 }; - uint8_t resp_random_a[8] = { 0 }; - memcpy(enc_resp, resp.d.asBytes+1, 8); - - des3_set2key_dec(&ctx, key); - // context, mode, length, IV, input, output - des3_crypt_cbc( &ctx, DES_DECRYPT, 8, enc_random_b, enc_resp, resp_random_a); - - if ( !memcmp(resp_random_a, random_a, 8)) - return 1; - return 0; - - //PrintAndLog(" RndA :%s", sprint_hex(random_a, 8)); - //PrintAndLog(" enc(RndB) :%s", sprint_hex(enc_random_b, 8)); - //PrintAndLog(" RndB :%s", sprint_hex(random_b, 8)); - //PrintAndLog(" A+B :%s", sprint_hex(random_a_and_b, 16)); - //PrintAndLog(" enc(A+B) :%s", sprint_hex(random_a_and_b, 16)); - //PrintAndLog(" enc(RndA') :%s", sprint_hex(data2+1, 8)); -} - /** A test function to validate that the polarssl-function works the same was as the openssl-implementation. @@ -1419,7 +1360,6 @@ int CmdHF14AMfUCRdBl(const char *Cmd) hasPwd = TRUE; } } - //uint8_t *key2 = SwapEndian64(key, 16, 8); //Read Block UsbCommand c = {CMD_MIFAREU_READBL, {blockNo}}; From 9d87eb66500080f76d81b8d453f3f5340717c001 Mon Sep 17 00:00:00 2001 From: marshmellow42 Date: Mon, 18 May 2015 13:11:00 -0400 Subject: [PATCH 35/49] MF ultralight code cleanup --- armsrc/appmain.c | 1 - armsrc/mifarecmd.c | 38 +++++++++----- armsrc/mifareutil.c | 15 +++--- client/cmdhfmfu.c | 102 ++++++++++++++++++++---------------- client/lualibs/commands.lua | 8 ++- include/usb_cmd.h | 5 +- 6 files changed, 93 insertions(+), 76 deletions(-) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 7b94f8a3c..96644b9a0 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -830,7 +830,6 @@ void UsbPacketReceived(uint8_t *packet, int len) MifareUC_Auth(c->arg[0],c->d.asBytes); break; case CMD_MIFAREU_READCARD: - case CMD_MIFAREUC_READCARD: MifareUReadCard(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); break; case CMD_MIFAREUC_SETPWD: diff --git a/armsrc/mifarecmd.c b/armsrc/mifarecmd.c index 1f8f4ee8e..23652070e 100644 --- a/armsrc/mifarecmd.c +++ b/armsrc/mifarecmd.c @@ -106,17 +106,17 @@ void MifareUC_Auth(uint8_t arg0, uint8_t *keybytes){ return; }; - if(mifare_ultra_auth(keybytes) == 1){ + if(!mifare_ultra_auth(keybytes)){ if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Authentication failed"); OnError(1); return; } - cmd_send(CMD_ACK,1,0,0,0,0); if (turnOffField) { FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LEDsoff(); } + cmd_send(CMD_ACK,1,0,0,0,0); } // Arg0 = BlockNo, @@ -146,7 +146,7 @@ void MifareUReadBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain) uint8_t key[16] = {0x00}; memcpy(key, datain, sizeof(key) ); - if ( mifare_ultra_auth(key) == 1 ) { + if ( !mifare_ultra_auth(key) ) { OnError(1); return; } @@ -157,7 +157,7 @@ void MifareUReadBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain) uint8_t pwd[4] = {0x00}; memcpy(pwd, datain, 4); uint8_t pack[4] = {0,0,0,0}; - if (mifare_ul_ev1_auth(pwd, pack) == 1) { + if (!mifare_ul_ev1_auth(pwd, pack)) { OnError(1); return; } @@ -255,8 +255,8 @@ void MifareUReadCard(uint8_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain) uint16_t blocks = arg1; bool useKey = (arg2 == 1); //UL_C bool usePwd = (arg2 == 2); //UL_EV1/NTAG - int countblocks = 0; - uint8_t dataout[176] = {0x00}; + uint32_t countblocks = 0; + uint8_t *dataout = BigBuf_get_addr(); LEDsoff(); LED_A_ON(); @@ -275,7 +275,7 @@ void MifareUReadCard(uint8_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain) uint8_t key[16] = {0x00}; memcpy(key, datain, sizeof(key) ); - if ( mifare_ultra_auth(key) == 1 ) { + if ( !mifare_ultra_auth(key) ) { OnError(1); return; } @@ -287,19 +287,30 @@ void MifareUReadCard(uint8_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain) memcpy(pwd, datain, sizeof(pwd)); uint8_t pack[4] = {0,0,0,0}; - if (mifare_ul_ev1_auth(pwd, pack) == 1){ + if (!mifare_ul_ev1_auth(pwd, pack)){ OnError(1); return; } } for (int i = 0; i < blocks; i++){ - len = mifare_ultra_readblock(blockNo * 4 + i, dataout + 4 * i); + if ((i*4) + 4 > BigBuf_get_traceLen()) { + Dbprintf("Data exceeds buffer!!"); + break; + } + + len = mifare_ultra_readblock(blockNo + i, dataout + 4 * i); if (len) { if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Read block %d error",i); - OnError(2); - return; + // if no blocks read - error out + if (i==0){ + OnError(2); + return; + } else { + //stop at last successful read block and return what we got + break; + } } else { countblocks++; } @@ -314,9 +325,8 @@ void MifareUReadCard(uint8_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain) if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("Blocks read %d", countblocks); - len = blocks * 4; - - cmd_send(CMD_ACK, 1, len, 0, dataout, len); + countblocks *= 4; + cmd_send(CMD_ACK, 1, countblocks, countblocks, 0, 0); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LEDsoff(); } diff --git a/armsrc/mifareutil.c b/armsrc/mifareutil.c index 0469364c3..77169a363 100644 --- a/armsrc/mifareutil.c +++ b/armsrc/mifareutil.c @@ -322,15 +322,14 @@ int mifare_ul_ev1_auth(uint8_t *keybytes, uint8_t *pack){ 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); - OnError(1); - return 1; + return 0; } if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("Auth Resp: %02x%02x%02x%02x", resp[0],resp[1],resp[2],resp[3]); memcpy(pack, resp, 4); - return 0; + return 1; } int mifare_ultra_auth(uint8_t *keybytes){ @@ -353,8 +352,7 @@ int mifare_ultra_auth(uint8_t *keybytes){ len = mifare_sendcmd_short(NULL, 1, 0x1A, 0x00, resp, respPar ,NULL); if (len != 11) { if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x", resp[0]); - OnError(1); - return 1; + return 0; } // tag nonce. @@ -386,8 +384,7 @@ int mifare_ultra_auth(uint8_t *keybytes){ len = mifare_sendcmd_short_mfucauth(NULL, 1, 0xAF, rnd_ab, resp, respPar, NULL); if (len != 11) { if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x", resp[0]); - OnError(1); - return 1; + return 0; } uint8_t enc_resp[8] = { 0,0,0,0,0,0,0,0 }; @@ -398,7 +395,7 @@ int mifare_ultra_auth(uint8_t *keybytes){ tdes_2key_dec(resp_random_a, enc_resp, 8, key, enc_random_b); if ( memcmp(resp_random_a, random_a, 8) != 0 ) { if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("failed authentication"); - return 1; + return 0; } if (MF_DBGLEVEL >= MF_DBG_EXTENDED) { @@ -418,7 +415,7 @@ int mifare_ultra_auth(uint8_t *keybytes){ resp_random_a[0],resp_random_a[1],resp_random_a[2],resp_random_a[3], resp_random_a[4],resp_random_a[5],resp_random_a[6],resp_random_a[7]); } - return 0; + return 1; } int mifare_ultra_readblock(uint8_t blockNo, uint8_t *blockData) diff --git a/client/cmdhfmfu.c b/client/cmdhfmfu.c index a22ff8597..15fa8e428 100644 --- a/client/cmdhfmfu.c +++ b/client/cmdhfmfu.c @@ -14,9 +14,10 @@ #include "mifare.h" #include "util.h" #include "protocols.h" +#include "data.h" #define MAX_UL_BLOCKS 0x0f -#define MAX_ULC_BLOCKS 0x2f +#define MAX_ULC_BLOCKS 0x2b #define MAX_ULEV1a_BLOCKS 0x12 #define MAX_ULEV1b_BLOCKS 0x20 #define MAX_NTAG_213 0x2c @@ -191,10 +192,10 @@ static int ulc_authentication( uint8_t *key, bool switch_off_field ){ memcpy(c.d.asBytes, key, 16); SendCommand(&c); UsbCommand resp; - if ( !WaitForResponseTimeout(CMD_ACK, &resp, 1500) ) return -1; - if ( resp.arg[0] == 1 ) return 0; + if ( !WaitForResponseTimeout(CMD_ACK, &resp, 1500) ) return 0; + if ( resp.arg[0] == 1 ) return 1; - return -2; + return 0; } static int ulev1_requestAuthentication( uint8_t *pwd, uint8_t *pack, uint16_t packLength ){ @@ -631,22 +632,20 @@ int CmdHF14AMfUInfo(const char *Cmd){ PrintAndLog("-------------------------------------------------------------"); ul_print_type(tagtype, 6); - status = ul_select(&card); - if ( status < 1 ){ - PrintAndLog("iso14443a card select failed"); - ul_switch_off_field(); - return status; - } - - if ( hasAuthKey ) { - if ((tagtype & UL_C)) { - //will select card automatically - if (ulc_authentication(authenticationkey, false) != 0) { - ul_switch_off_field(); - PrintAndLog("Error: Authentication Failed UL-C"); - return 0; - } - } else { + if ( hasAuthKey && (tagtype & UL_C)) { + //will select card automatically and close connection on error + if (!ulc_authentication(authenticationkey, false)) { + PrintAndLog("Error: Authentication Failed UL-C"); + return 0; + } + } else { + status = ul_select(&card); + if ( status < 1 ){ + PrintAndLog("iso14443a card select failed"); + ul_switch_off_field(); + return status; + } + if (hasAuthKey) { len = ulev1_requestAuthentication(authenticationkey, pack, sizeof(pack)); if (len < 1) { ul_switch_off_field(); @@ -674,6 +673,7 @@ int CmdHF14AMfUInfo(const char *Cmd){ status = ul_read(0x28, ulc_conf, sizeof(ulc_conf)); if ( status == -1 ){ PrintAndLog("Error: tag didn't answer to READ UL-C"); + ul_switch_off_field(); return status; } ulc_print_configuration(ulc_conf); @@ -690,22 +690,21 @@ int CmdHF14AMfUInfo(const char *Cmd){ ulc_print_3deskey(ulc_deskey); } else { + ul_switch_off_field(); // if we called info with key, just return if ( hasAuthKey ) return 1; PrintAndLog("Trying some default 3des keys"); for (uint8_t i = 0; i < KEYS_3DES_COUNT; ++i ){ key = default_3des_keys[i]; - if (ulc_authentication(key, true) == 0){ + if (ulc_authentication(key, true)){ PrintAndLog("Found default 3des key: "); //%s", sprint_hex(key,16)); uint8_t keySwap[16]; memcpy(keySwap, SwapEndian64(key,16,8), 16); ulc_print_3deskey(keySwap); - ul_switch_off_field(); return 1; } } - ul_switch_off_field(); return 1; //return even if key not found (UL_C is done) } } @@ -763,14 +762,19 @@ int CmdHF14AMfUInfo(const char *Cmd){ // 1-7 = ... should we even try then? if ( authlim == 0 ){ PrintAndLog("\n--- Known EV1/NTAG passwords."); - - for (uint8_t i = 0; i < 3; ++i ){ + len = 0; + for (uint8_t i = 0; i < KEYS_PWD_COUNT; ++i ){ key = default_pwd_pack[i]; - if ( len > -1 ){ - len = ulev1_requestAuthentication(key, pack, sizeof(pack)); - if (len == 1) { - PrintAndLog("Found a default password: %s || Pack: %02X %02X",sprint_hex(key, 4), pack[0], pack[1]); - break; + len = ulev1_requestAuthentication(key, pack, sizeof(pack)); + if (len >= 1) { + PrintAndLog("Found a default password: %s || Pack: %02X %02X",sprint_hex(key, 4), pack[0], pack[1]); + break; + } else { + status = ul_select(&card); + if ( status < 1 ){ + PrintAndLog("iso14443a card select failed - ev1 auth"); + ul_switch_off_field(); + return status; } } } @@ -783,6 +787,7 @@ int CmdHF14AMfUInfo(const char *Cmd){ status = ul_read(3, cc, sizeof(cc)); if ( status == -1 ){ PrintAndLog("Error: tag didn't answer to READ ntag"); + ul_switch_off_field(); return status; } ntag_print_CC(cc); @@ -988,8 +993,10 @@ int CmdHF14AMfUDump(const char *Cmd){ errors = param_gethex(tempStr, 0, key, dataLen); else if (dataLen == 8) //ev1/ntag errors = param_gethex(tempStr, 0, key, dataLen); - else + else{ + PrintAndLog("\nERROR: Key is incorrect length\n"); errors = true; + } cmdp += 2; hasPwd = true; @@ -1042,8 +1049,7 @@ int CmdHF14AMfUDump(const char *Cmd){ ul_print_type(tagtype, 0); PrintAndLog("Reading tag memory..."); - - UsbCommand c = {CMD_MIFAREUC_READCARD, {startPage,Pages}}; + UsbCommand c = {CMD_MIFAREU_READCARD, {startPage,Pages}}; if ( hasPwd ) { if (tagtype & UL_C) c.arg[2] = 1; //UL_C auth @@ -1058,15 +1064,20 @@ int CmdHF14AMfUDump(const char *Cmd){ PrintAndLog("Command execute time-out"); return 1; } - PrintAndLog ("%u,%u",resp.arg[0],resp.arg[1]); - uint8_t isOK = resp.arg[0] & 0xff; - if (isOK) { - memcpy(data, resp.d.asBytes, resp.arg[1]); - } else { + if (resp.arg[0] != 1) { PrintAndLog("Failed reading block: (%02x)", i); return 1; } + uint32_t bufferSize = resp.arg[1]; + if (bufferSize > sizeof(data)) { + PrintAndLog("Data exceeded Buffer size!"); + bufferSize = sizeof(data); + } + GetFromBigBuf(data, bufferSize, 0); + WaitForResponse(CMD_ACK,NULL); + + Pages = bufferSize/4; // Load lock bytes. int j = 0; @@ -1088,11 +1099,14 @@ int CmdHF14AMfUDump(const char *Cmd){ } } - // add keys - if (hasPwd){ //UL_C + // add keys to block dump + if (hasPwd && (tagtype & UL_C)){ //UL_C memcpy(data + Pages*4, key, dataLen/2); Pages += 4; - } + } else if (hasPwd) { //not sure output is in correct location. + memcpy(data + Pages*4, key, dataLen/2); + Pages += 1; + } for (i = 0; i < Pages; ++i) { if ( i < 3 ) { @@ -1186,7 +1200,7 @@ void rol (uint8_t *data, const size_t len){ // int CmdHF14AMfucAuth(const char *Cmd){ - uint8_t keyNo = 0; + uint8_t keyNo = 3; bool errors = false; char cmdp = param_getchar(Cmd, 0); @@ -1216,11 +1230,11 @@ int CmdHF14AMfucAuth(const char *Cmd){ } uint8_t *key = default_3des_keys[keyNo]; - if (ulc_authentication(key, true) == 0) + if (ulc_authentication(key, true)) PrintAndLog("Authentication successful. 3des key: %s",sprint_hex(key, 16)); else PrintAndLog("Authentication failed"); - + return 0; } diff --git a/client/lualibs/commands.lua b/client/lualibs/commands.lua index b0257ef0e..678c745ec 100644 --- a/client/lualibs/commands.lua +++ b/client/lualibs/commands.lua @@ -135,11 +135,9 @@ local _commands = { CMD_MIFARE_SNIFFER = 0x0630, --//ultralightC - CMD_MIFAREUC_AUTH1 = 0x0724, - CMD_MIFAREUC_AUTH2 = 0x0725, - CMD_MIFAREUC_READCARD = 0x0726, - CMD_MIFAREUC_SETPWD = 0x0727, - CMD_MIFAREU_SETUID = 0x0728, + CMD_MIFAREUC_AUTH = 0x0724, + CMD_MIFAREUC_SETPWD = 0x0727, + CMD_MIFAREU_SETUID = 0x0728, --// mifare desfire CMD_MIFARE_DESFIRE_READBL = 0x0728, diff --git a/include/usb_cmd.h b/include/usb_cmd.h index f67eac580..357395d43 100644 --- a/include/usb_cmd.h +++ b/include/usb_cmd.h @@ -174,9 +174,8 @@ typedef struct{ #define CMD_MIFARE_SNIFFER 0x0630 //ultralightC -#define CMD_MIFAREUC_AUTH1 0x0724 -#define CMD_MIFAREUC_AUTH2 0x0725 -#define CMD_MIFAREUC_READCARD 0x0726 +#define CMD_MIFAREUC_AUTH 0x0724 +//0x0725 and 0x0726 no longer used #define CMD_MIFAREUC_SETPWD 0x0727 From 29250969b0e2762fca3cbfa24e0648f29b21407d Mon Sep 17 00:00:00 2001 From: marshmellow42 Date: Mon, 18 May 2015 22:07:11 -0400 Subject: [PATCH 36/49] @iceman1001 s comments/updates mfu cmds --- armsrc/mifareutil.c | 4 ++-- client/cmdhfmfu.c | 27 ++++++++------------------- client/cmdhfmfu.h | 4 ---- 3 files changed, 10 insertions(+), 25 deletions(-) diff --git a/armsrc/mifareutil.c b/armsrc/mifareutil.c index 77169a363..2f84797b9 100644 --- a/armsrc/mifareutil.c +++ b/armsrc/mifareutil.c @@ -728,8 +728,8 @@ int mifare_desfire_des_auth1(uint32_t uid, uint8_t *blockData){ int len; // load key, keynumber uint8_t data[2]={0x0a, 0x00}; - uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE]; - uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE]; + uint8_t receivedAnswer[MAX_FRAME_SIZE]; + uint8_t receivedAnswerPar[MAX_PARITY_SIZE]; len = mifare_sendcmd_special(NULL, 1, 0x02, data, receivedAnswer,receivedAnswerPar,NULL); if (len == 1) { diff --git a/client/cmdhfmfu.c b/client/cmdhfmfu.c index 15fa8e428..d087ff6d2 100644 --- a/client/cmdhfmfu.c +++ b/client/cmdhfmfu.c @@ -278,14 +278,17 @@ static int ul_print_default( uint8_t *data){ PrintAndLog(" BCC1 : %02X - crc should be %02X", data[8], crc1 ); PrintAndLog(" Internal : %02X - %s default", data[9], (data[9]==0x48)?"":"not" ); + PrintAndLog(" Lock : %s - %s", sprint_hex(data+10, 2), printBits(2, data+10) ); + PrintAndLog("OneTimePad : %s - %s\n", sprint_hex(data + 12, 4), printBits(4, data+12) ); + return 0; } @@ -364,7 +367,7 @@ static int ulc_print_configuration( uint8_t *data){ bool validAuth = (data[8] >= 0x03 && data[8] <= 0x30); if ( validAuth ) - PrintAndLog(" Auth0 [42/0x2A]: %s Page %d and above need authentication", sprint_hex(data+8, 4), data[8] ); + PrintAndLog(" Auth0 [42/0x2A]: %s page %d/0x%02X and above need authentication", sprint_hex(data+8, 4), data[8], data[8]); else{ if ( data[8] == 0){ PrintAndLog(" Auth0 [42/0x2A]: %s default", sprint_hex(data+8, 4) ); @@ -539,7 +542,7 @@ uint16_t GetHF14AMfU_Type(void){ } case 0x01: tagtype = UL_C; break; case 0x00: tagtype = UL; break; - case -1 : tagtype = (UL | UL_C); break; //when does this happen? + case -1 : tagtype = (UL | UL_C); break; //when does this happen? -- if getversion fails, it assumes it is either UL/ULC -- but why? magic tags? default : tagtype = UNKNOWN; break; } // UL-C test @@ -698,7 +701,7 @@ int CmdHF14AMfUInfo(const char *Cmd){ for (uint8_t i = 0; i < KEYS_3DES_COUNT; ++i ){ key = default_3des_keys[i]; if (ulc_authentication(key, true)){ - PrintAndLog("Found default 3des key: "); //%s", sprint_hex(key,16)); + PrintAndLog("Found default 3des key: "); uint8_t keySwap[16]; memcpy(keySwap, SwapEndian64(key,16,8), 16); ulc_print_3deskey(keySwap); @@ -931,7 +934,7 @@ int usage_hf_mfu_dump(void) PrintAndLog("Reads all pages from Ultralight, Ultralight-C, Ultralight EV1"); PrintAndLog("and saves binary dump into the file `filename.bin` or `cardUID.bin`"); PrintAndLog("It autodetects card type.\n"); - PrintAndLog("Usage: hf mfu dump s k n "); + PrintAndLog("Usage: hf mfu dump l k n "); PrintAndLog(" Options : "); PrintAndLog(" k : key for authentication [UL-C 16bytes, EV1/NTAG 4bytes]"); PrintAndLog(" l : swap entered key's endianness for auth"); @@ -949,14 +952,11 @@ int usage_hf_mfu_dump(void) // // Mifare Ultralight / Ultralight-C / Ultralight-EV1 // Read and Dump Card Contents, using auto detection of tag size. -// -// TODO: take a password to read UL-C / UL-EV1 tags. int CmdHF14AMfUDump(const char *Cmd){ FILE *fout; char filename[FILE_PATH_SIZE] = {0x00}; char *fnameptr = filename; - //char *str = "Dumping Ultralight%s%s Card Data..."; uint8_t *lockbytes_t = NULL; uint8_t lockbytes[2] = {0x00}; uint8_t *lockbytes_t2 = NULL; @@ -1089,7 +1089,7 @@ int CmdHF14AMfUDump(const char *Cmd){ } // Load bottom lockbytes if available - // HOW DOES THIS APPLY TO EV1 and/or NTAG??? + // TODO -- FIGURE OUT LOCK BYTES FOR TO EV1 and/or NTAG if ( Pages == 44 ) { lockbytes_t2 = data + (40*4); lockbytes2[0] = lockbytes_t2[2]; @@ -1180,17 +1180,6 @@ int CmdHF14AMfUDump(const char *Cmd){ return 0; } -/* -// Needed to Authenticate to Ultralight C tags -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; -} -*/ - //------------------------------------------------------------------------------- // Ultralight C Methods //------------------------------------------------------------------------------- diff --git a/client/cmdhfmfu.h b/client/cmdhfmfu.h index 806c27d34..533422190 100644 --- a/client/cmdhfmfu.h +++ b/client/cmdhfmfu.h @@ -13,15 +13,11 @@ int CmdHF14AMfUCRdBl(const char *Cmd); int CmdHF14AMfUCRdCard(const char *Cmd); int CmdHF14AMfucAuth(const char *Cmd); -uint8_t requestAuthentication( uint8_t *nonce); -int try3DesAuthentication( uint8_t *key, bool switch_off_field); - //general stuff int CmdHF14AMfUDump(const char *Cmd); int CmdHF14AMfUInfo(const char *Cmd); uint16_t GetHF14AMfU_Type(void); -void rol (uint8_t *data, const size_t len); int ul_print_type(uint16_t tagtype, uint8_t spacer); void ul_switch_off_field(void); From d7acc6403ed1e1a138c8d8fb662ee995442f209b Mon Sep 17 00:00:00 2001 From: marshmellow42 Date: Tue, 19 May 2015 11:30:50 -0400 Subject: [PATCH 37/49] hf mfu dump - bigbuf allocation fix some larger nfc tags can get large so set the allocation to the 4k CARD_MEMORY_SIZE buffersize. --- armsrc/mifarecmd.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/armsrc/mifarecmd.c b/armsrc/mifarecmd.c index 23652070e..0586a25db 100644 --- a/armsrc/mifarecmd.c +++ b/armsrc/mifarecmd.c @@ -250,17 +250,26 @@ void MifareReadSector(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) void MifareUReadCard(uint8_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain) { + // free eventually allocated BigBuf memory + BigBuf_free(); + // clear trace + clear_trace(); + // params uint8_t blockNo = arg0; uint16_t blocks = arg1; bool useKey = (arg2 == 1); //UL_C bool usePwd = (arg2 == 2); //UL_EV1/NTAG uint32_t countblocks = 0; - uint8_t *dataout = BigBuf_get_addr(); + uint8_t *dataout = BigBuf_malloc(CARD_MEMORY_SIZE); + if (dataout == NULL){ + Dbprintf("out of memory"); + OnError(1); + return; + } LEDsoff(); LED_A_ON(); - clear_trace(); iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); int len = iso14443a_select_card(NULL, NULL, NULL); @@ -294,7 +303,7 @@ void MifareUReadCard(uint8_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain) } for (int i = 0; i < blocks; i++){ - if ((i*4) + 4 > BigBuf_get_traceLen()) { + if ((i*4) + 4 > CARD_MEMORY_SIZE) { Dbprintf("Data exceeds buffer!!"); break; } From a98b05b71df1acf84aab0e70e721fe9901301494 Mon Sep 17 00:00:00 2001 From: marshmellow42 Date: Tue, 19 May 2015 15:03:35 -0400 Subject: [PATCH 38/49] missed file in previous commit... duh... --- common/protocols.h | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/common/protocols.h b/common/protocols.h index 01b738c2b..580342728 100644 --- a/common/protocols.h +++ b/common/protocols.h @@ -123,9 +123,21 @@ NXP/Philips CUSTOM COMMANDS #define MIFARE_CMD_RESTORE 0xC2 #define MIFARE_CMD_TRANSFER 0xB0 -#define MIFARE_ULC_WRITE 0xA0 +#define MIFARE_ULC_WRITE 0xA2 +//#define MIFARE_ULC__COMP_WRITE 0xA0 #define MIFARE_ULC_AUTH_1 0x1A -#define MIFARE_ULC_AUTH_2 0xAF +#define MIFARE_ULC_AUTH_2 0xAF + +#define MIFARE_ULEV1_AUTH 0x1B +#define MIFARE_ULEV1_VERSION 0x60 +#define MIFARE_ULEV1_FASTREAD 0x3A +//#define MIFARE_ULEV1_WRITE 0xA2 +//#define MIFARE_ULEV1_COMP_WRITE 0xA0 +#define MIFARE_ULEV1_READ_CNT 0x39 +#define MIFARE_ULEV1_INCR_CNT 0xA5 +#define MIFARE_ULEV1_READSIG 0x3C +#define MIFARE_ULEV1_CHECKTEAR 0x3E +#define MIFARE_ULEV1_VCSL 0x4B /** 06 00 = INITIATE From a383f4b708f818894a67636857e28d62efd22cdd Mon Sep 17 00:00:00 2001 From: marshmellow42 Date: Wed, 20 May 2015 11:27:44 -0400 Subject: [PATCH 39/49] Add ntag 210, 212, 203 and bug fix --- client/cmdhfmfu.c | 219 +++++++++++++++++++++++++++------------------- client/cmdhfmfu.h | 19 ++-- 2 files changed, 141 insertions(+), 97 deletions(-) diff --git a/client/cmdhfmfu.c b/client/cmdhfmfu.c index d087ff6d2..88d502b80 100644 --- a/client/cmdhfmfu.c +++ b/client/cmdhfmfu.c @@ -19,7 +19,10 @@ #define MAX_UL_BLOCKS 0x0f #define MAX_ULC_BLOCKS 0x2b #define MAX_ULEV1a_BLOCKS 0x12 -#define MAX_ULEV1b_BLOCKS 0x20 +#define MAX_ULEV1b_BLOCKS 0x28 +#define MAX_NTAG_203 0x29 +#define MAX_NTAG_210 0x13 +#define MAX_NTAG_212 0x28 #define MAX_NTAG_213 0x2c #define MAX_NTAG_215 0x86 #define MAX_NTAG_216 0xe6 @@ -51,12 +54,13 @@ uint8_t default_pwd_pack[KEYS_PWD_COUNT][4] = { {0x32,0x0C,0x16,0x17}, // PACK 0x80,0x80 -- AMiiboo (sniffed) }; -#define MAX_UL_TYPES 13 -uint16_t UL_TYPES_ARRAY[MAX_UL_TYPES] = {UNKNOWN, UL, UL_C, UL_EV1_48, UL_EV1_128, - NTAG, NTAG_213, NTAG_215, NTAG_216, MY_D, MY_D_NFC, MY_D_MOVE, MY_D_MOVE_NFC}; -uint8_t UL_MEMORY_ARRAY[MAX_UL_TYPES] = {MAX_UL_BLOCKS, MAX_UL_BLOCKS, MAX_ULC_BLOCKS, - MAX_ULEV1a_BLOCKS, MAX_ULEV1b_BLOCKS, MAX_NTAG_213, MAX_NTAG_213, MAX_NTAG_215, - MAX_NTAG_216, MAX_UL_BLOCKS, MAX_UL_BLOCKS, MAX_UL_BLOCKS, MAX_UL_BLOCKS}; +#define MAX_UL_TYPES 16 +uint16_t UL_TYPES_ARRAY[MAX_UL_TYPES] = {UNKNOWN, UL, UL_C, UL_EV1_48, UL_EV1_128, NTAG, NTAG_203, + NTAG_210, NTAG_212, NTAG_213, NTAG_215, NTAG_216, MY_D, MY_D_NFC, MY_D_MOVE, MY_D_MOVE_NFC}; + +uint8_t UL_MEMORY_ARRAY[MAX_UL_TYPES] = {MAX_UL_BLOCKS, MAX_UL_BLOCKS, MAX_ULC_BLOCKS, MAX_ULEV1a_BLOCKS, + MAX_ULEV1b_BLOCKS, MAX_NTAG_203, MAX_NTAG_203, MAX_NTAG_210, MAX_NTAG_212, MAX_NTAG_213, + MAX_NTAG_215, MAX_NTAG_216, MAX_UL_BLOCKS, MAX_UL_BLOCKS, MAX_UL_BLOCKS, MAX_UL_BLOCKS}; static int CmdHelp(const char *Cmd); @@ -292,15 +296,14 @@ static int ul_print_default( uint8_t *data){ return 0; } -static int ntag_print_CC(uint8_t *data) { - - PrintAndLog("\n--- NTAG NDEF Message"); +static int ndef_print_CC(uint8_t *data) { if(data[0] != 0xe1) { - PrintAndLog("no NDEF message"); + //PrintAndLog("no NDEF message"); return -1; // no NDEF message } + PrintAndLog("--- NDEF Message"); PrintAndLog("Capability Container: %s", sprint_hex(data,4) ); PrintAndLog(" %02X: NDEF Magic Number", data[0]); PrintAndLog(" %02X: version %d.%d supported by tag", data[1], (data[1] & 0xF0) >> 4, data[1] & 0x0f); @@ -331,12 +334,20 @@ int ul_print_type(uint16_t tagtype, uint8_t spaces){ PrintAndLog("%sTYPE : MIFARE Ultralight EV1 48bytes (MF0UL1101)", spacer); else if ( tagtype & UL_EV1_128) PrintAndLog("%sTYPE : MIFARE Ultralight EV1 128bytes (MF0UL2101)", spacer); + else if ( tagtype & NTAG ) + PrintAndLog("%sTYPE : NTAG UNKNOWN", spacer); + else if ( tagtype & NTAG_203 ) + PrintAndLog("%sTYPE : NTAG 203 144bytes (NT2H0301F0DT)", spacer); else if ( tagtype & NTAG_213 ) - PrintAndLog("%sTYPE : MIFARE NTAG 213 144bytes (NT2H1311G0DU)", spacer); + PrintAndLog("%sTYPE : NTAG 210 48bytes (NT2L1011G0DU)", spacer); + else if ( tagtype & NTAG_213 ) + PrintAndLog("%sTYPE : NTAG 212 128bytes (NT2L1211G0DU)", spacer); + else if ( tagtype & NTAG_213 ) + PrintAndLog("%sTYPE : NTAG 213 144bytes (NT2H1311G0DU)", spacer); else if ( tagtype & NTAG_215 ) - PrintAndLog("%sTYPE : MIFARE NTAG 215 504bytes (NT2H1511G0DU)", spacer); + PrintAndLog("%sTYPE : NTAG 215 504bytes (NT2H1511G0DU)", spacer); else if ( tagtype & NTAG_216 ) - PrintAndLog("%sTYPE : MIFARE NTAG 216 888bytes (NT2H1611G0DU)", spacer); + PrintAndLog("%sTYPE : NTAG 216 888bytes (NT2H1611G0DU)", spacer); else if ( tagtype & MY_D ) PrintAndLog("%sTYPE : INFINEON my-d\x99", spacer); else if ( tagtype & MY_D_NFC ) @@ -384,7 +395,7 @@ static int ulc_print_configuration( uint8_t *data){ static int ulev1_print_configuration( uint8_t *data){ - PrintAndLog("\n--- UL-EV1 Configuration"); + PrintAndLog("\n--- Tag Configuration"); bool strg_mod_en = (data[0] & 2); uint8_t authlim = (data[4] & 0x07); @@ -412,7 +423,7 @@ static int ulev1_print_configuration( uint8_t *data){ } static int ulev1_print_counters(){ - PrintAndLog("--- UL-EV1 Counters"); + PrintAndLog("--- Tag Counters"); uint8_t tear[1] = {0}; uint8_t counter[3] = {0,0,0}; for ( uint8_t i = 0; i<3; ++i) { @@ -425,7 +436,7 @@ static int ulev1_print_counters(){ } static int ulev1_print_signature( uint8_t *data, uint8_t len){ - PrintAndLog("\n--- UL-EV1 Signature"); + PrintAndLog("\n--- Tag Signature"); PrintAndLog("IC signature public key name : NXP NTAG21x 2013"); PrintAndLog("IC signature public key value : 04494e1a386d3d3cfe3dc10e5de68a499b1c202db5b132393e89ed19fe5be8bc61"); PrintAndLog(" Elliptic curve parameters : secp128r1"); @@ -436,7 +447,7 @@ static int ulev1_print_signature( uint8_t *data, uint8_t len){ } static int ulev1_print_version(uint8_t *data){ - PrintAndLog("\n--- UL-EV1 / NTAG Version"); + PrintAndLog("\n--- Tag Version"); PrintAndLog(" Raw bytes : %s", sprint_hex(data, 8) ); PrintAndLog(" Vendor ID : %02X, Manufacturer: %s", data[1], getTagInfo(data[1])); PrintAndLog(" Product type : %s", getProductTypeStr(data[2])); @@ -529,11 +540,15 @@ uint16_t GetHF14AMfU_Type(void){ tagtype = UL_EV1_48; else if ( version[2] == 0x03 && version[6] != 0x0B ) tagtype = UL_EV1_128; - else if ( version[2] == 0x04 && version[6] == 0x0F ) + else if ( version[2] == 0x04 && version[3] == 0x01 && version[6] == 0x0B ) + tagtype = NTAG_210; + else if ( version[2] == 0x04 && version[3] == 0x01 && version[6] == 0x0E ) + tagtype = NTAG_212; + else if ( version[2] == 0x04 && version[3] == 0x02 && version[6] == 0x0F ) tagtype = NTAG_213; - else if ( version[2] == 0x04 && version[6] == 0x11 ) + else if ( version[2] == 0x04 && version[3] == 0x02 && version[6] == 0x11 ) tagtype = NTAG_215; - else if ( version[2] == 0x04 && version[6] == 0x13 ) + else if ( version[2] == 0x04 && version[3] == 0x02 && version[6] == 0x13 ) tagtype = NTAG_216; else if ( version[2] == 0x04 ) tagtype = NTAG; @@ -542,35 +557,60 @@ uint16_t GetHF14AMfU_Type(void){ } case 0x01: tagtype = UL_C; break; case 0x00: tagtype = UL; break; - case -1 : tagtype = (UL | UL_C); break; //when does this happen? -- if getversion fails, it assumes it is either UL/ULC -- but why? magic tags? + case -1 : tagtype = (UL | UL_C | NTAG_203); break; //when does this happen? -- if getversion fails, it assumes it is either UL/ULC -- but why? magic tags? default : tagtype = UNKNOWN; break; } - // UL-C test - if (tagtype == (UL | UL_C)) { + // UL vs UL-C vs ntag203 test + if (tagtype & (UL | UL_C | NTAG_203)) { status = ul_select(&card); if ( status < 1 ){ PrintAndLog("iso14443a card select failed (UL-C)"); ul_switch_off_field(); return UL_ERROR; } + + // do UL_C check first... uint8_t nonce[11] = {0x00}; status = ulc_requestAuthentication(nonce, sizeof(nonce)); - tagtype = ( status > 0 ) ? UL_C : UL; - ul_switch_off_field(); + if (status > 1) { + tagtype = UL_C; + } else { + // need to re-select after authentication error + status = ul_select(&card); + if ( status < 1 ){ + PrintAndLog("iso14443a card select failed (UL-C)"); + ul_switch_off_field(); + return UL_ERROR; + } + uint8_t data[16] = {0x00}; + // read page 0x26-0x29 (last valid ntag203 page) + status = ul_read(0x26, data, sizeof(data)); + if ( status <= 1 ) { + tagtype = UL; + } else { + // read page 0x30 (should error if it is a ntag203) + status = ul_read(30, data, sizeof(data)); + if ( status <= 1 ){ + tagtype = NTAG_203; + } else { + tagtype = UNKNOWN; + } + } + ul_switch_off_field(); + } } } else { // Infinition MY-D tests Exam high nibble uint8_t nib = (card.uid[1] & 0xf0) >> 4; switch ( nib ){ case 1: tagtype = MY_D; break; - case 2: tagtype = (MY_D | MY_D_NFC); break; - case 3: tagtype = (MY_D_MOVE | MY_D_MOVE_NFC); break; + case 2: tagtype = (MY_D | MY_D_NFC); break; //notice: we can not currently distinguish between these two + case 3: tagtype = (MY_D_MOVE | MY_D_MOVE_NFC); break; //notice: we can not currently distinguish between these two } } tagtype = (ul_magic_test() == UL_MAGIC) ? (tagtype | MAGIC) : tagtype; - //if ((tagtype & UL)) tagtype = ul_magic_test(); return tagtype; } @@ -584,6 +624,7 @@ int CmdHF14AMfUInfo(const char *Cmd){ int status; bool errors = false; bool hasAuthKey = false; + bool locked = false; uint8_t cmdp = 0; uint8_t datalen = 0; uint8_t authenticationkey[16] = {0x00}; @@ -658,18 +699,21 @@ int CmdHF14AMfUInfo(const char *Cmd){ } } - - // read pages 0,1,2,4 (should read 4pages) + // read pages 0,1,2,3 (should read 4pages) status = ul_read(0, data, sizeof(data)); - if ( status == -1 ){ + if ( status == -1 ) { ul_switch_off_field(); PrintAndLog("Error: tag didn't answer to READ"); return status; } + if (status == 16) { + ul_print_default(data); + ndef_print_CC(data+12); - ul_print_default(data); + } else locked = true; - if ((tagtype & UL_C)){ + // UL_C Specific + if ((tagtype & UL_C)) { // read pages 0x28, 0x29, 0x2A, 0x2B uint8_t ulc_conf[16] = {0x00}; @@ -679,18 +723,19 @@ int CmdHF14AMfUInfo(const char *Cmd){ ul_switch_off_field(); return status; } - ulc_print_configuration(ulc_conf); - - if ((tagtype & MAGIC)){ + if (status == 16) ulc_print_configuration(ulc_conf); + else locked = true; + if ((tagtype & MAGIC)) { + //just read key uint8_t ulc_deskey[16] = {0x00}; status = ul_read(0x2C, ulc_deskey, sizeof(ulc_deskey)); - if ( status == -1 ){ + if ( status == -1 ) { ul_switch_off_field(); PrintAndLog("Error: tag didn't answer to READ magic"); return status; } - ulc_print_3deskey(ulc_deskey); + if (status == 16) ulc_print_3deskey(ulc_deskey); } else { ul_switch_off_field(); @@ -698,75 +743,81 @@ int CmdHF14AMfUInfo(const char *Cmd){ if ( hasAuthKey ) return 1; PrintAndLog("Trying some default 3des keys"); - for (uint8_t i = 0; i < KEYS_3DES_COUNT; ++i ){ + for (uint8_t i = 0; i < KEYS_3DES_COUNT; ++i ) { key = default_3des_keys[i]; - if (ulc_authentication(key, true)){ + if (ulc_authentication(key, true)) { PrintAndLog("Found default 3des key: "); uint8_t keySwap[16]; memcpy(keySwap, SwapEndian64(key,16,8), 16); ulc_print_3deskey(keySwap); - return 1; + break; } } - return 1; //return even if key not found (UL_C is done) + // reselect for future tests (ntag test) + status = ul_select(&card); + if ( status < 1 ){ + PrintAndLog("iso14443a card select failed"); + ul_switch_off_field(); + return status; + } } } - if ((tagtype & (UL_EV1_48 | UL_EV1_128))) { - //do counters and signature first (don't neet auth) - ulev1_print_counters(); + // do counters and signature first (don't neet auth) + // ul counters are different than ntag counters + if ((tagtype & (UL_EV1_48 | UL_EV1_128))) ulev1_print_counters(); + + if ((tagtype & (UL_EV1_48 | UL_EV1_128 | NTAG_213 | NTAG_215 | NTAG_216 ))) { uint8_t ulev1_signature[32] = {0x00}; status = ulev1_readSignature( ulev1_signature, sizeof(ulev1_signature)); - if ( status == -1 ){ + if ( status == -1 ) { PrintAndLog("Error: tag didn't answer to READ SIGNATURE"); ul_switch_off_field(); return status; - } - ulev1_print_signature( ulev1_signature, sizeof(ulev1_signature)); - - uint8_t startconfigblock = (tagtype & UL_EV1_48) ? 0x10 : 0x25; - uint8_t ulev1_conf[16] = {0x00}; - status = ul_read(startconfigblock, ulev1_conf, sizeof(ulev1_conf)); - if ( status == -1 ){ - PrintAndLog("Error: tag didn't answer to READ EV1"); - ul_switch_off_field(); - return status; } - // save AUTHENTICATION LIMITS for later: - authlim = (ulev1_conf[4] & 0x07); - bool allZeros = true; - for (uint8_t idx=0; idx<8; idx++) - if (ulev1_conf[idx]) allZeros = false; - - if (allZeros) authlim=7; - ulev1_print_configuration(ulev1_conf); + if (status == 32) ulev1_print_signature( ulev1_signature, sizeof(ulev1_signature)); } - if ((tagtype & (UL_EV1_48 | UL_EV1_128 | NTAG_213 | NTAG_215 | NTAG_216))) { - + if ((tagtype & (UL_EV1_48 | UL_EV1_128 | NTAG_210 | NTAG_212 | NTAG_213 | NTAG_215 | NTAG_216))) { uint8_t version[10] = {0x00}; status = ulev1_getVersion(version, sizeof(version)); - if ( status == -1 ){ + if ( status == -1 ) { PrintAndLog("Error: tag didn't answer to GETVERSION"); ul_switch_off_field(); return status; } - ulev1_print_version(version); + if (status == 10) ulev1_print_version(version); + else locked = true; - // if we called info with key, just return - if ( hasAuthKey ) { + uint8_t startconfigblock = 0; + uint8_t ulev1_conf[16] = {0x00}; + // config blocks always are last 4 pages + for (uint8_t idx = 0; idx < MAX_UL_TYPES; idx++) + if (tagtype & UL_TYPES_ARRAY[idx]) + startconfigblock = UL_MEMORY_ARRAY[idx]-3; + + status = ul_read(startconfigblock, ulev1_conf, sizeof(ulev1_conf)); + if ( status == -1 ) { + PrintAndLog("Error: tag didn't answer to READ EV1"); ul_switch_off_field(); - return 1; + return status; + } else if (status == 16) { + // save AUTHENTICATION LIMITS for later: + authlim = (ulev1_conf[4] & 0x07); + ulev1_print_configuration(ulev1_conf); + } else { + authlim=7; } // AUTHLIMIT, (number of failed authentications) // 0 = limitless. - // 1-7 = ... should we even try then? - if ( authlim == 0 ){ + // 1-7 = limit. No automatic tries then. + // hasAuthKey, if we was called with key, skip test. + if ( !authlim && !hasAuthKey ) { PrintAndLog("\n--- Known EV1/NTAG passwords."); len = 0; - for (uint8_t i = 0; i < KEYS_PWD_COUNT; ++i ){ + for (uint8_t i = 0; i < KEYS_PWD_COUNT; ++i ) { key = default_pwd_pack[i]; len = ulev1_requestAuthentication(key, pack, sizeof(pack)); if (len >= 1) { @@ -774,29 +825,19 @@ int CmdHF14AMfUInfo(const char *Cmd){ break; } else { status = ul_select(&card); - if ( status < 1 ){ + if ( status < 1 ) { PrintAndLog("iso14443a card select failed - ev1 auth"); ul_switch_off_field(); return status; } } } + if (len < 1) PrintAndLog("password not known"); } } - if ((tagtype & (NTAG_213 | NTAG_215 | NTAG_216))){ - - uint8_t cc[16] = {0x00}; - status = ul_read(3, cc, sizeof(cc)); - if ( status == -1 ){ - PrintAndLog("Error: tag didn't answer to READ ntag"); - ul_switch_off_field(); - return status; - } - ntag_print_CC(cc); - } - ul_switch_off_field(); + if (locked) PrintAndLog("\nTag appears to be locked, try using the key to get more info"); PrintAndLog(""); return 1; } @@ -1100,7 +1141,7 @@ int CmdHF14AMfUDump(const char *Cmd){ } // add keys to block dump - if (hasPwd && (tagtype & UL_C)){ //UL_C + if (hasPwd && (tagtype & UL_C)) { //UL_C memcpy(data + Pages*4, key, dataLen/2); Pages += 4; } else if (hasPwd) { //not sure output is in correct location. diff --git a/client/cmdhfmfu.h b/client/cmdhfmfu.h index 533422190..4087b3114 100644 --- a/client/cmdhfmfu.h +++ b/client/cmdhfmfu.h @@ -33,14 +33,17 @@ typedef enum TAGTYPE_UL { UL_EV1_48 = 0x0004, UL_EV1_128 = 0x0008, NTAG = 0x0010, - NTAG_213 = 0x0020, - NTAG_215 = 0x0040, - NTAG_216 = 0x0080, - MY_D = 0x0100, - MY_D_NFC = 0x0200, - MY_D_MOVE = 0x0400, - MY_D_MOVE_NFC = 0x0800, - MAGIC = 0x1000, + NTAG_203 = 0x0020, + NTAG_210 = 0x0040, + NTAG_212 = 0x0080, + NTAG_213 = 0x0100, + NTAG_215 = 0x0200, + NTAG_216 = 0x0400, + MY_D = 0x0800, + MY_D_NFC = 0x1000, + MY_D_MOVE = 0x2000, + MY_D_MOVE_NFC = 0x4000, + MAGIC = 0x8000, UL_MAGIC = UL | MAGIC, UL_C_MAGIC = UL_C | MAGIC, UL_ERROR = 0xFFFF, From c7442b76732e1dbc31fdd8a996142e34534ef5fb Mon Sep 17 00:00:00 2001 From: marshmellow42 Date: Wed, 20 May 2015 14:06:46 -0400 Subject: [PATCH 40/49] Add NTAG i2c and bug fix also streamlined select tag code --- client/cmdhf14a.c | 2 +- client/cmdhfmfu.c | 106 +++++++++++++++++++++------------------------- client/cmdhfmfu.h | 42 +++++++++--------- 3 files changed, 71 insertions(+), 79 deletions(-) diff --git a/client/cmdhf14a.c b/client/cmdhf14a.c index 1973ff222..9a761864b 100644 --- a/client/cmdhf14a.c +++ b/client/cmdhf14a.c @@ -178,7 +178,7 @@ int CmdHF14AReader(const char *Cmd) c.arg[2] = 0; SendCommand(&c); - uint16_t tagT = GetHF14AMfU_Type(); + uint32_t tagT = GetHF14AMfU_Type(); ul_print_type(tagT, 0); //reconnect for further tests diff --git a/client/cmdhfmfu.c b/client/cmdhfmfu.c index 88d502b80..e3ea9378a 100644 --- a/client/cmdhfmfu.c +++ b/client/cmdhfmfu.c @@ -150,11 +150,16 @@ static int ul_select( iso14a_card_select_t *card ){ ul_switch_on_field(); UsbCommand resp; - if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) return -1; - if (resp.arg[0] < 1) return -1; + bool ans = false; + ans = WaitForResponseTimeout(CMD_ACK, &resp, 1500); + if (resp.arg[0] < 1 || !ans) { + PrintAndLog("iso14443a card select failed"); + ul_switch_off_field(); + return 0; + } memcpy(card, resp.d.asBytes, sizeof(iso14a_card_select_t)); - return resp.arg[0]; + return 1; } // This read command will at least return 16bytes. @@ -321,7 +326,7 @@ static int ndef_print_CC(uint8_t *data) { return 0; } -int ul_print_type(uint16_t tagtype, uint8_t spaces){ +int ul_print_type(uint32_t tagtype, uint8_t spaces){ char spc[11] = " "; spc[10]=0x00; char *spacer = spc + (10-spaces); @@ -338,9 +343,9 @@ int ul_print_type(uint16_t tagtype, uint8_t spaces){ PrintAndLog("%sTYPE : NTAG UNKNOWN", spacer); else if ( tagtype & NTAG_203 ) PrintAndLog("%sTYPE : NTAG 203 144bytes (NT2H0301F0DT)", spacer); - else if ( tagtype & NTAG_213 ) + else if ( tagtype & NTAG_210 ) PrintAndLog("%sTYPE : NTAG 210 48bytes (NT2L1011G0DU)", spacer); - else if ( tagtype & NTAG_213 ) + else if ( tagtype & NTAG_212 ) PrintAndLog("%sTYPE : NTAG 212 128bytes (NT2L1211G0DU)", spacer); else if ( tagtype & NTAG_213 ) PrintAndLog("%sTYPE : NTAG 213 144bytes (NT2H1311G0DU)", spacer); @@ -357,7 +362,7 @@ int ul_print_type(uint16_t tagtype, uint8_t spaces){ else if ( tagtype & MY_D_MOVE_NFC ) PrintAndLog("%sTYPE : INFINEON my-d\x99 move NFC", spacer); else - PrintAndLog("%sTYPE : Unknown %04x", spacer, tagtype); + PrintAndLog("%sTYPE : Unknown %06x", spacer, tagtype); return 0; } @@ -426,13 +431,16 @@ static int ulev1_print_counters(){ PrintAndLog("--- Tag Counters"); uint8_t tear[1] = {0}; uint8_t counter[3] = {0,0,0}; + uint16_t len = 0; for ( uint8_t i = 0; i<3; ++i) { ulev1_readTearing(i,tear,sizeof(tear)); - ulev1_readCounter(i,counter, sizeof(counter) ); - PrintAndLog(" [%0d] : %s", i, sprint_hex(counter,3)); - PrintAndLog(" - %02X tearing %s", tear[0], ( tear[0]==0xBD)?"Ok":"failure"); + len = ulev1_readCounter(i,counter, sizeof(counter) ); + if (len == 3) { + PrintAndLog(" [%0d] : %s", i, sprint_hex(counter,3)); + PrintAndLog(" - %02X tearing %s", tear[0], ( tear[0]==0xBD)?"Ok":"failure"); + } } - return 0; + return len; } static int ulev1_print_signature( uint8_t *data, uint8_t len){ @@ -472,9 +480,7 @@ static int ulc_magic_test(){ uint8_t nonce1[11] = {0x00}; uint8_t nonce2[11] = {0x00}; int status = ul_select(&card); - if ( status < 1 ){ - PrintAndLog("Error: couldn't select ulc_magic_test"); - ul_switch_off_field(); + if ( !status ){ return UL_ERROR; } status = ulc_requestAuthentication(nonce1, sizeof(nonce1)); @@ -494,12 +500,9 @@ static int ul_magic_test(){ // 1) take present UID, and try to write it back. OBSOLETE // 2) make a wrong length write to page0, and see if tag answers with ACK/NACK: iso14a_card_select_t card; - int status = ul_select(&card); - if ( status < 1 ){ - PrintAndLog("iso14443a card select failed"); - ul_switch_off_field(); + int status; + if ( !ul_select(&card) ) return UL_ERROR; - } status = ul_comp_write(0, NULL, 0); ul_switch_off_field(); if ( status == 0 ) @@ -507,7 +510,7 @@ static int ul_magic_test(){ return UL; } -uint16_t GetHF14AMfU_Type(void){ +uint32_t GetHF14AMfU_Type(void){ TagTypeUL_t tagtype = UNKNOWN; iso14a_card_select_t card; @@ -515,12 +518,8 @@ uint16_t GetHF14AMfU_Type(void){ int status = 0; int len; - status = ul_select(&card); - if ( status < 1 ){ - PrintAndLog("iso14443a card select failed"); - ul_switch_off_field(); - return UL_ERROR; - } + if (!ul_select(&card)) return UL_ERROR; + // Ultralight - ATQA / SAK if ( card.atqa[1] != 0x00 || card.atqa[0] != 0x44 || card.sak != 0x00 ) { PrintAndLog("Tag is not Ultralight | NTAG | MY-D [ATQA: %02X %02X SAK: %02X]\n", card.atqa[1], card.atqa[0], card.sak); @@ -550,6 +549,11 @@ uint16_t GetHF14AMfU_Type(void){ tagtype = NTAG_215; else if ( version[2] == 0x04 && version[3] == 0x02 && version[6] == 0x13 ) tagtype = NTAG_216; + else if ( version[2] == 0x04 && version[3] == 0x05 && version[6] == 0x13 ) + tagtype = NTAG_I2C_1K; + else if ( version[2] == 0x04 && version[3] == 0x05 && version[6] == 0x15 ) + tagtype = NTAG_I2C_2K; + else if ( version[2] == 0x04 ) tagtype = NTAG; @@ -562,12 +566,7 @@ uint16_t GetHF14AMfU_Type(void){ } // UL vs UL-C vs ntag203 test if (tagtype & (UL | UL_C | NTAG_203)) { - status = ul_select(&card); - if ( status < 1 ){ - PrintAndLog("iso14443a card select failed (UL-C)"); - ul_switch_off_field(); - return UL_ERROR; - } + if ( !ul_select(&card) ) return UL_ERROR; // do UL_C check first... uint8_t nonce[11] = {0x00}; @@ -577,12 +576,8 @@ uint16_t GetHF14AMfU_Type(void){ tagtype = UL_C; } else { // need to re-select after authentication error - status = ul_select(&card); - if ( status < 1 ){ - PrintAndLog("iso14443a card select failed (UL-C)"); - ul_switch_off_field(); - return UL_ERROR; - } + if ( !ul_select(&card) ) return UL_ERROR; + uint8_t data[16] = {0x00}; // read page 0x26-0x29 (last valid ntag203 page) status = ul_read(0x26, data, sizeof(data)); @@ -611,7 +606,7 @@ uint16_t GetHF14AMfU_Type(void){ } tagtype = (ul_magic_test() == UL_MAGIC) ? (tagtype | MAGIC) : tagtype; - + if (tagtype == (UNKNOWN | MAGIC)) tagtype = (UL | MAGIC); return tagtype; } @@ -683,12 +678,8 @@ int CmdHF14AMfUInfo(const char *Cmd){ return 0; } } else { - status = ul_select(&card); - if ( status < 1 ){ - PrintAndLog("iso14443a card select failed"); - ul_switch_off_field(); - return status; - } + if ( !ul_select(&card) ) return 0; + if (hasAuthKey) { len = ulev1_requestAuthentication(authenticationkey, pack, sizeof(pack)); if (len < 1) { @@ -754,19 +745,19 @@ int CmdHF14AMfUInfo(const char *Cmd){ } } // reselect for future tests (ntag test) - status = ul_select(&card); - if ( status < 1 ){ - PrintAndLog("iso14443a card select failed"); - ul_switch_off_field(); - return status; - } + if ( !ul_select(&card) ) return 0; } } // do counters and signature first (don't neet auth) // ul counters are different than ntag counters - if ((tagtype & (UL_EV1_48 | UL_EV1_128))) ulev1_print_counters(); + if ((tagtype & (UL_EV1_48 | UL_EV1_128))) { + if (ulev1_print_counters() != 3) { + // failed - re-select + if ( !ul_select(&card) ) return 0; + } + } if ((tagtype & (UL_EV1_48 | UL_EV1_128 | NTAG_213 | NTAG_215 | NTAG_216 ))) { uint8_t ulev1_signature[32] = {0x00}; @@ -777,6 +768,10 @@ int CmdHF14AMfUInfo(const char *Cmd){ return status; } if (status == 32) ulev1_print_signature( ulev1_signature, sizeof(ulev1_signature)); + else { + // re-select + if ( !ul_select(&card) ) return 0; + } } if ((tagtype & (UL_EV1_48 | UL_EV1_128 | NTAG_210 | NTAG_212 | NTAG_213 | NTAG_215 | NTAG_216))) { @@ -824,12 +819,7 @@ int CmdHF14AMfUInfo(const char *Cmd){ PrintAndLog("Found a default password: %s || Pack: %02X %02X",sprint_hex(key, 4), pack[0], pack[1]); break; } else { - status = ul_select(&card); - if ( status < 1 ) { - PrintAndLog("iso14443a card select failed - ev1 auth"); - ul_switch_off_field(); - return status; - } + if ( !ul_select(&card) ) return 0; } } if (len < 1) PrintAndLog("password not known"); diff --git a/client/cmdhfmfu.h b/client/cmdhfmfu.h index 4087b3114..83f284031 100644 --- a/client/cmdhfmfu.h +++ b/client/cmdhfmfu.h @@ -16,9 +16,9 @@ int CmdHF14AMfucAuth(const char *Cmd); //general stuff int CmdHF14AMfUDump(const char *Cmd); int CmdHF14AMfUInfo(const char *Cmd); -uint16_t GetHF14AMfU_Type(void); +uint32_t GetHF14AMfU_Type(void); -int ul_print_type(uint16_t tagtype, uint8_t spacer); +int ul_print_type(uint32_t tagtype, uint8_t spacer); void ul_switch_off_field(void); int usage_hf_mfu_dump(void); @@ -27,26 +27,28 @@ int usage_hf_mfu_info(void); int CmdHFMFUltra(const char *Cmd); typedef enum TAGTYPE_UL { - UNKNOWN = 0x0000, - UL = 0x0001, - UL_C = 0x0002, - UL_EV1_48 = 0x0004, - UL_EV1_128 = 0x0008, - NTAG = 0x0010, - NTAG_203 = 0x0020, - NTAG_210 = 0x0040, - NTAG_212 = 0x0080, - NTAG_213 = 0x0100, - NTAG_215 = 0x0200, - NTAG_216 = 0x0400, - MY_D = 0x0800, - MY_D_NFC = 0x1000, - MY_D_MOVE = 0x2000, - MY_D_MOVE_NFC = 0x4000, - MAGIC = 0x8000, + UNKNOWN = 0x000000, + UL = 0x000001, + UL_C = 0x000002, + UL_EV1_48 = 0x000004, + UL_EV1_128 = 0x000008, + NTAG = 0x000010, + NTAG_203 = 0x000020, + NTAG_210 = 0x000040, + NTAG_212 = 0x000080, + NTAG_213 = 0x000100, + NTAG_215 = 0x000200, + NTAG_216 = 0x000400, + MY_D = 0x000800, + MY_D_NFC = 0x001000, + MY_D_MOVE = 0x002000, + MY_D_MOVE_NFC = 0x004000, + NTAG_I2C_1K = 0x008000, + NTAG_I2C_2K = 0x010000, + MAGIC = 0x020000, UL_MAGIC = UL | MAGIC, UL_C_MAGIC = UL_C | MAGIC, - UL_ERROR = 0xFFFF, + UL_ERROR = 0xFFFFFF, } TagTypeUL_t; #endif From ea11861793628ce153926ffe9b60068d83e9aa9f Mon Sep 17 00:00:00 2001 From: marshmellow42 Date: Wed, 20 May 2015 14:17:43 -0400 Subject: [PATCH 41/49] minor adjustments to hf mfu --- client/cmdhfmfu.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/client/cmdhfmfu.c b/client/cmdhfmfu.c index e3ea9378a..9826a5921 100644 --- a/client/cmdhfmfu.c +++ b/client/cmdhfmfu.c @@ -152,7 +152,7 @@ static int ul_select( iso14a_card_select_t *card ){ UsbCommand resp; bool ans = false; ans = WaitForResponseTimeout(CMD_ACK, &resp, 1500); - if (resp.arg[0] < 1 || !ans) { + if (!ans || resp.arg[0] < 1) { PrintAndLog("iso14443a card select failed"); ul_switch_off_field(); return 0; @@ -408,22 +408,22 @@ static int ulev1_print_configuration( uint8_t *data){ bool prot = (data[4] & 0x80); uint8_t vctid = data[5]; - PrintAndLog(" cfg0 [16/0x10]: %s", sprint_hex(data, 4)); + PrintAndLog(" cfg0 [16/0x10]: %s", sprint_hex(data, 4)); if ( data[3] < 0xff ) PrintAndLog(" - page %d and above need authentication",data[3]); else PrintAndLog(" - pages don't need authentication"); PrintAndLog(" - strong modulation mode %s", (strg_mod_en) ? "enabled":"disabled"); - PrintAndLog(" cfg1 [17/0x11]: %s", sprint_hex(data+4, 4) ); + PrintAndLog(" cfg1 [17/0x11]: %s", sprint_hex(data+4, 4) ); if ( authlim == 0) PrintAndLog(" - Unlimited password attempts"); else PrintAndLog(" - Max number of password attempts is %d", authlim); PrintAndLog(" - user configuration %s", cfglck ? "permanently locked":"writeable"); PrintAndLog(" - %s access is protected with password", prot ? "read and write":"write"); - PrintAndLog(" %02X - Virtual Card Type Identifier is %s default", vctid, (vctid==0x05)? "":"not"); - PrintAndLog(" PWD [18/0x12]: %s", sprint_hex(data+8, 4)); - PrintAndLog(" PACK [19/0x13]: %s", sprint_hex(data+12, 4)); + PrintAndLog(" %02X - Virtual Card Type Identifier is %s default", vctid, (vctid==0x05)? "":"not"); + PrintAndLog(" PWD [18/0x12]: %s", sprint_hex(data+8, 4)); + PrintAndLog(" PACK [19/0x13]: %s", sprint_hex(data+12, 4)); return 0; } From 8241872c4702766159594eae0ef7ab4292d37d40 Mon Sep 17 00:00:00 2001 From: marshmellow42 Date: Wed, 20 May 2015 14:22:26 -0400 Subject: [PATCH 42/49] ULEV1_48 had the wrong max block --- client/cmdhfmfu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/cmdhfmfu.c b/client/cmdhfmfu.c index 9826a5921..c0fd136a5 100644 --- a/client/cmdhfmfu.c +++ b/client/cmdhfmfu.c @@ -18,7 +18,7 @@ #define MAX_UL_BLOCKS 0x0f #define MAX_ULC_BLOCKS 0x2b -#define MAX_ULEV1a_BLOCKS 0x12 +#define MAX_ULEV1a_BLOCKS 0x13 #define MAX_ULEV1b_BLOCKS 0x28 #define MAX_NTAG_203 0x29 #define MAX_NTAG_210 0x13 From 46fcd738e02bb4e3c5159e6848121666160de7a5 Mon Sep 17 00:00:00 2001 From: marshmellow42 Date: Wed, 20 May 2015 15:41:48 -0400 Subject: [PATCH 43/49] finish NTAG i2c +... thanks @iceman1001 --- client/cmdhfmfu.c | 55 ++++++++++++++++++++++++----------------------- 1 file changed, 28 insertions(+), 27 deletions(-) diff --git a/client/cmdhfmfu.c b/client/cmdhfmfu.c index c0fd136a5..68ed11d50 100644 --- a/client/cmdhfmfu.c +++ b/client/cmdhfmfu.c @@ -72,13 +72,13 @@ char *getProductTypeStr( uint8_t id){ switch(id) { case 3: - sprintf(retStr, "%02X %s", id, "(Ultralight)"); + sprintf(retStr, "%02X %s", id, "Ultralight"); break; case 4: - sprintf(retStr, "%02X %s", id, "(NTAG)"); + sprintf(retStr, "%02X %s", id, "NTAG"); break; default: - sprintf(retStr, "%02X %s", id, "(unknown)"); + sprintf(retStr, "%02X %s", id, "unknown"); break; } return buf; @@ -264,7 +264,7 @@ static int ul_print_default( uint8_t *data){ uid[6] = data[7]; PrintAndLog(" UID : %s ", sprint_hex(uid, 7)); - PrintAndLog(" UID[0] : %02X, Manufacturer: %s", uid[0], getTagInfo(uid[0]) ); + PrintAndLog(" UID[0] : %02X Manufacturer: %s", uid[0], getTagInfo(uid[0]) ); if ( uid[0] == 0x05 ) { uint8_t chip = (data[8] & 0xC7); // 11000111 mask, bit 3,4,5 RFU switch (chip){ @@ -353,6 +353,8 @@ int ul_print_type(uint32_t tagtype, uint8_t spaces){ PrintAndLog("%sTYPE : NTAG 215 504bytes (NT2H1511G0DU)", spacer); else if ( tagtype & NTAG_216 ) PrintAndLog("%sTYPE : NTAG 216 888bytes (NT2H1611G0DU)", spacer); + else if ( tagtype & NTAG_I2C_1K ) + else if ( tagtype & NTAG_I2C_2K ) else if ( tagtype & MY_D ) PrintAndLog("%sTYPE : INFINEON my-d\x99", spacer); else if ( tagtype & MY_D_NFC ) @@ -445,7 +447,7 @@ static int ulev1_print_counters(){ static int ulev1_print_signature( uint8_t *data, uint8_t len){ PrintAndLog("\n--- Tag Signature"); - PrintAndLog("IC signature public key name : NXP NTAG21x 2013"); + PrintAndLog("IC signature public key name : NXP NTAG21x 2013"); // don't know if there is other NXP public keys.. :( PrintAndLog("IC signature public key value : 04494e1a386d3d3cfe3dc10e5de68a499b1c202db5b132393e89ed19fe5be8bc61"); PrintAndLog(" Elliptic curve parameters : secp128r1"); PrintAndLog(" Tag ECC Signature : %s", sprint_hex(data, len)); @@ -457,7 +459,7 @@ static int ulev1_print_signature( uint8_t *data, uint8_t len){ static int ulev1_print_version(uint8_t *data){ PrintAndLog("\n--- Tag Version"); PrintAndLog(" Raw bytes : %s", sprint_hex(data, 8) ); - PrintAndLog(" Vendor ID : %02X, Manufacturer: %s", data[1], getTagInfo(data[1])); + PrintAndLog(" Vendor ID : %02X %s", data[1], getTagInfo(data[1])); PrintAndLog(" Product type : %s", getProductTypeStr(data[2])); PrintAndLog(" Product subtype : %02X %s", data[3], (data[3]==1) ?"17 pF":"50pF"); PrintAndLog(" Major version : %02X", data[4]); @@ -500,14 +502,13 @@ static int ul_magic_test(){ // 1) take present UID, and try to write it back. OBSOLETE // 2) make a wrong length write to page0, and see if tag answers with ACK/NACK: iso14a_card_select_t card; - int status; if ( !ul_select(&card) ) return UL_ERROR; - status = ul_comp_write(0, NULL, 0); + int status = ul_comp_write(0, NULL, 0); ul_switch_off_field(); if ( status == 0 ) - return UL_MAGIC; - return UL; + return MAGIC; + return 0; } uint32_t GetHF14AMfU_Type(void){ @@ -561,7 +562,7 @@ uint32_t GetHF14AMfU_Type(void){ } case 0x01: tagtype = UL_C; break; case 0x00: tagtype = UL; break; - case -1 : tagtype = (UL | UL_C | NTAG_203); break; //when does this happen? -- if getversion fails, it assumes it is either UL/ULC -- but why? magic tags? + case -1 : tagtype = (UL | UL_C | NTAG_203); break; // could be UL | UL_C magic tags default : tagtype = UNKNOWN; break; } // UL vs UL-C vs ntag203 test @@ -605,8 +606,9 @@ uint32_t GetHF14AMfU_Type(void){ } } - tagtype = (ul_magic_test() == UL_MAGIC) ? (tagtype | MAGIC) : tagtype; - if (tagtype == (UNKNOWN | MAGIC)) tagtype = (UL | MAGIC); + + tagtype |= ul_magic_test(); + if (tagtype == (UNKNOWN | MAGIC)) tagtype = (UL_MAGIC); return tagtype; } @@ -700,7 +702,6 @@ int CmdHF14AMfUInfo(const char *Cmd){ if (status == 16) { ul_print_default(data); ndef_print_CC(data+12); - } else locked = true; // UL_C Specific @@ -759,7 +760,7 @@ int CmdHF14AMfUInfo(const char *Cmd){ } } - if ((tagtype & (UL_EV1_48 | UL_EV1_128 | NTAG_213 | NTAG_215 | NTAG_216 ))) { + if ((tagtype & (UL_EV1_48 | UL_EV1_128 | NTAG_213 | NTAG_215 | NTAG_216 | NTAG_I2C_1K | NTAG_I2C_2K ))) { uint8_t ulev1_signature[32] = {0x00}; status = ulev1_readSignature( ulev1_signature, sizeof(ulev1_signature)); if ( status == -1 ) { @@ -774,7 +775,7 @@ int CmdHF14AMfUInfo(const char *Cmd){ } } - if ((tagtype & (UL_EV1_48 | UL_EV1_128 | NTAG_210 | NTAG_212 | NTAG_213 | NTAG_215 | NTAG_216))) { + if ((tagtype & (UL_EV1_48 | UL_EV1_128 | NTAG_210 | NTAG_212 | NTAG_213 | NTAG_215 | NTAG_216 | NTAG_I2C_1K | NTAG_I2C_2K))) { uint8_t version[10] = {0x00}; status = ulev1_getVersion(version, sizeof(version)); if ( status == -1 ) { @@ -792,17 +793,17 @@ int CmdHF14AMfUInfo(const char *Cmd){ if (tagtype & UL_TYPES_ARRAY[idx]) startconfigblock = UL_MEMORY_ARRAY[idx]-3; - status = ul_read(startconfigblock, ulev1_conf, sizeof(ulev1_conf)); - if ( status == -1 ) { - PrintAndLog("Error: tag didn't answer to READ EV1"); - ul_switch_off_field(); - return status; - } else if (status == 16) { - // save AUTHENTICATION LIMITS for later: - authlim = (ulev1_conf[4] & 0x07); - ulev1_print_configuration(ulev1_conf); - } else { - authlim=7; + if (startconfigblock){ // if we know where the config block is... + status = ul_read(startconfigblock, ulev1_conf, sizeof(ulev1_conf)); + if ( status == -1 ) { + PrintAndLog("Error: tag didn't answer to READ EV1"); + ul_switch_off_field(); + return status; + } else if (status == 16) { + // save AUTHENTICATION LIMITS for later: + authlim = (ulev1_conf[4] & 0x07); + ulev1_print_configuration(ulev1_conf); + } } // AUTHLIMIT, (number of failed authentications) From cd87ee9133bf4b12e7b8a250e44e2924f515a617 Mon Sep 17 00:00:00 2001 From: marshmellow42 Date: Wed, 20 May 2015 15:42:58 -0400 Subject: [PATCH 44/49] finish NTAG i2c +... thanks iceman --- client/cmdhfmfu.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/client/cmdhfmfu.c b/client/cmdhfmfu.c index 68ed11d50..aebde8338 100644 --- a/client/cmdhfmfu.c +++ b/client/cmdhfmfu.c @@ -354,7 +354,9 @@ int ul_print_type(uint32_t tagtype, uint8_t spaces){ else if ( tagtype & NTAG_216 ) PrintAndLog("%sTYPE : NTAG 216 888bytes (NT2H1611G0DU)", spacer); else if ( tagtype & NTAG_I2C_1K ) + PrintAndLog("%sTYPE : NTAG I%sC 888bytes (NT3H1101FHK)", spacer, "\xFD"); else if ( tagtype & NTAG_I2C_2K ) + PrintAndLog("%sTYPE : NTAG I%sC 1904bytes (NT3H1201FHK)", spacer, "\xFD"); else if ( tagtype & MY_D ) PrintAndLog("%sTYPE : INFINEON my-d\x99", spacer); else if ( tagtype & MY_D_NFC ) From 1c429594a13155b464c9ccf618067c29339d7fff Mon Sep 17 00:00:00 2001 From: marshmellow42 Date: Wed, 20 May 2015 16:47:40 -0400 Subject: [PATCH 45/49] further mfu info updates needed to auth select when a command failed for locked tags. some output cleanups from @iceman1001 --- client/cmdhfmfu.c | 155 +++++++++++++++++++++++----------------------- 1 file changed, 77 insertions(+), 78 deletions(-) diff --git a/client/cmdhfmfu.c b/client/cmdhfmfu.c index aebde8338..7f0e8fc56 100644 --- a/client/cmdhfmfu.c +++ b/client/cmdhfmfu.c @@ -71,15 +71,9 @@ char *getProductTypeStr( uint8_t id){ char *retStr = buf; switch(id) { - case 3: - sprintf(retStr, "%02X %s", id, "Ultralight"); - break; - case 4: - sprintf(retStr, "%02X %s", id, "NTAG"); - break; - default: - sprintf(retStr, "%02X %s", id, "unknown"); - break; + case 3: sprintf(retStr, "%02X, Ultralight", id); break; + case 4: sprintf(retStr, "%02X, NTAG", id); break; + default: sprintf(retStr, "%02X, unknown", id); break; } return buf; } @@ -214,6 +208,27 @@ static int ulev1_requestAuthentication( uint8_t *pwd, uint8_t *pack, uint16_t pa return len; } +static int ul_auth_select( iso14a_card_select_t *card, TagTypeUL_t tagtype, bool hasAuthKey, uint8_t *authenticationkey, uint8_t *pack, uint8_t packSize){ + if ( hasAuthKey && (tagtype & UL_C)) { + //will select card automatically and close connection on error + if (!ulc_authentication(authenticationkey, false)) { + PrintAndLog("Error: Authentication Failed UL-C"); + return 0; + } + } else { + if ( !ul_select(card) ) return 0; + + if (hasAuthKey) { + if (ulev1_requestAuthentication(authenticationkey, pack, packSize) < 1) { + ul_switch_off_field(); + PrintAndLog("Error: Authentication Failed UL-EV1/NTAG"); + return 0; + } + } + } + return 1; +} + static int ulev1_getVersion( uint8_t *response, uint16_t responseLength ){ uint8_t cmd[] = {MIFARE_ULEV1_VERSION}; @@ -264,7 +279,7 @@ static int ul_print_default( uint8_t *data){ uid[6] = data[7]; PrintAndLog(" UID : %s ", sprint_hex(uid, 7)); - PrintAndLog(" UID[0] : %02X Manufacturer: %s", uid[0], getTagInfo(uid[0]) ); + PrintAndLog(" UID[0] : %02X, Manufacturer: %s", uid[0], getTagInfo(uid[0]) ); if ( uid[0] == 0x05 ) { uint8_t chip = (data[8] & 0xC7); // 11000111 mask, bit 3,4,5 RFU switch (chip){ @@ -276,17 +291,17 @@ static int ul_print_default( uint8_t *data){ // CT (cascade tag byte) 0x88 xor SN0 xor SN1 xor SN2 int crc0 = 0x88 ^ data[0] ^ data[1] ^data[2]; if ( data[3] == crc0 ) - PrintAndLog(" BCC0 : %02X - Ok", data[3]); + PrintAndLog(" BCC0 : %02X, Ok", data[3]); else - PrintAndLog(" BCC0 : %02X - crc should be %02X", data[3], crc0); + PrintAndLog(" BCC0 : %02X, crc should be %02X", data[3], crc0); int crc1 = data[4] ^ data[5] ^ data[6] ^data[7]; if ( data[8] == crc1 ) - PrintAndLog(" BCC1 : %02X - Ok", data[8]); + PrintAndLog(" BCC1 : %02X, Ok", data[8]); else - PrintAndLog(" BCC1 : %02X - crc should be %02X", data[8], crc1 ); + PrintAndLog(" BCC1 : %02X, crc should be %02X", data[8], crc1 ); - PrintAndLog(" Internal : %02X - %s default", data[9], (data[9]==0x48)?"":"not" ); + PrintAndLog(" Internal : %02X, %sdefault", data[9], (data[9]==0x48)?"":"not " ); PrintAndLog(" Lock : %s - %s", sprint_hex(data+10, 2), @@ -302,25 +317,23 @@ static int ul_print_default( uint8_t *data){ } static int ndef_print_CC(uint8_t *data) { - - if(data[0] != 0xe1) { - //PrintAndLog("no NDEF message"); - return -1; // no NDEF message - } + // no NDEF message + if(data[0] != 0xe1) + return -1; PrintAndLog("--- NDEF Message"); PrintAndLog("Capability Container: %s", sprint_hex(data,4) ); - PrintAndLog(" %02X: NDEF Magic Number", data[0]); - PrintAndLog(" %02X: version %d.%d supported by tag", data[1], (data[1] & 0xF0) >> 4, data[1] & 0x0f); - PrintAndLog(" %02X: Physical Memory Size: %d bytes", data[2], (data[2] + 1) * 8); + PrintAndLog(" %02X : NDEF Magic Number", data[0]); + PrintAndLog(" %02X : version %d.%d supported by tag", data[1], (data[1] & 0xF0) >> 4, data[1] & 0x0f); + PrintAndLog(" %02X : Physical Memory Size: %d bytes", data[2], (data[2] + 1) * 8); if ( data[2] == 0x12 ) - PrintAndLog(" %02X: NDEF Memory Size: %d bytes", data[2], 144); + PrintAndLog(" %02X : NDEF Memory Size: %d bytes", data[2], 144); else if ( data[2] == 0x3e ) - PrintAndLog(" %02X: NDEF Memory Size: %d bytes", data[2], 496); + PrintAndLog(" %02X : NDEF Memory Size: %d bytes", data[2], 496); else if ( data[2] == 0x6d ) - PrintAndLog(" %02X: NDEF Memory Size: %d bytes", data[2], 872); - - PrintAndLog(" %02X: %s / %s", data[3], + PrintAndLog(" %02X : NDEF Memory Size: %d bytes", data[2], 872); + + PrintAndLog(" %02X : %s / %s", data[3], (data[3] & 0xF0) ? "(RFU)" : "Read access granted without any security", (data[3] & 0x0F)==0 ? "Write access granted without any security" : (data[3] & 0x0F)==0x0F ? "No write access granted at all" : "(RFU)"); return 0; @@ -332,19 +345,19 @@ int ul_print_type(uint32_t tagtype, uint8_t spaces){ char *spacer = spc + (10-spaces); if ( tagtype & UL ) - PrintAndLog("%sTYPE : MIFARE Ultralight (MF0ICU1) %s [%x]", spacer, (tagtype & MAGIC)?"":"", tagtype); + PrintAndLog("%sTYPE : MIFARE Ultralight (MF0ICU1) %s", spacer, (tagtype & MAGIC) ? "" : "" ); else if ( tagtype & UL_C) - PrintAndLog("%sTYPE : MIFARE Ultralight C (MF0ULC) %s [%x]", spacer, (tagtype & MAGIC)?"":"", tagtype ); + PrintAndLog("%sTYPE : MIFARE Ultralight C (MF0ULC) %s", spacer, (tagtype & MAGIC) ? "" : "" ); else if ( tagtype & UL_EV1_48) PrintAndLog("%sTYPE : MIFARE Ultralight EV1 48bytes (MF0UL1101)", spacer); - else if ( tagtype & UL_EV1_128) + else if ( tagtype & UL_EV1_128) PrintAndLog("%sTYPE : MIFARE Ultralight EV1 128bytes (MF0UL2101)", spacer); else if ( tagtype & NTAG ) PrintAndLog("%sTYPE : NTAG UNKNOWN", spacer); else if ( tagtype & NTAG_203 ) PrintAndLog("%sTYPE : NTAG 203 144bytes (NT2H0301F0DT)", spacer); else if ( tagtype & NTAG_210 ) - PrintAndLog("%sTYPE : NTAG 210 48bytes (NT2L1011G0DU)", spacer); + PrintAndLog("%sTYPE : NTAG 210 48bytes (NT2L1011G0DU)", spacer); else if ( tagtype & NTAG_212 ) PrintAndLog("%sTYPE : NTAG 212 128bytes (NT2L1211G0DU)", spacer); else if ( tagtype & NTAG_213 ) @@ -371,10 +384,10 @@ int ul_print_type(uint32_t tagtype, uint8_t spaces){ } static int ulc_print_3deskey( uint8_t *data){ - PrintAndLog(" deskey1 [44/0x2C]: %s [%.4s]", sprint_hex(data ,4),data); - PrintAndLog(" deskey1 [45/0x2D]: %s [%.4s]", sprint_hex(data+4 ,4),data+4); - PrintAndLog(" deskey2 [46/0x2E]: %s [%.4s]", sprint_hex(data+8 ,4),data+8); - PrintAndLog(" deskey2 [47/0x2F]: %s [%.4s]", sprint_hex(data+12,4),data+12); + PrintAndLog(" deskey1 [44/0x2C] : %s [%.4s]", sprint_hex(data ,4),data); + PrintAndLog(" deskey1 [45/0x2D] : %s [%.4s]", sprint_hex(data+4 ,4),data+4); + PrintAndLog(" deskey2 [46/0x2E] : %s [%.4s]", sprint_hex(data+8 ,4),data+8); + PrintAndLog(" deskey2 [47/0x2F] : %s [%.4s]", sprint_hex(data+12,4),data+12); PrintAndLog("\n 3des key : %s", sprint_hex(SwapEndian64(data, 16, 8), 16)); return 0; } @@ -382,20 +395,20 @@ static int ulc_print_3deskey( uint8_t *data){ static int ulc_print_configuration( uint8_t *data){ PrintAndLog("--- UL-C Configuration"); - PrintAndLog(" Higher Lockbits [40/0x28]: %s - %s", sprint_hex(data, 4), printBits(2, data)); - PrintAndLog(" Counter [41/0x29]: %s - %s", sprint_hex(data+4, 4), printBits(2, data+4)); + PrintAndLog(" Higher Lockbits [40/0x28] : %s - %s", sprint_hex(data, 4), printBits(2, data)); + PrintAndLog(" Counter [41/0x29] : %s - %s", sprint_hex(data+4, 4), printBits(2, data+4)); bool validAuth = (data[8] >= 0x03 && data[8] <= 0x30); if ( validAuth ) - PrintAndLog(" Auth0 [42/0x2A]: %s page %d/0x%02X and above need authentication", sprint_hex(data+8, 4), data[8], data[8]); + PrintAndLog(" Auth0 [42/0x2A] : %s page %d/0x%02X and above need authentication", sprint_hex(data+8, 4), data[8],data[8] ); else{ if ( data[8] == 0){ - PrintAndLog(" Auth0 [42/0x2A]: %s default", sprint_hex(data+8, 4) ); + PrintAndLog(" Auth0 [42/0x2A] : %s default", sprint_hex(data+8, 4) ); } else { - PrintAndLog(" Auth0 [42/0x2A]: %s auth byte is out-of-range", sprint_hex(data+8, 4) ); + PrintAndLog(" Auth0 [42/0x2A] : %s auth byte is out-of-range", sprint_hex(data+8, 4) ); } } - PrintAndLog(" Auth1 [43/0x2B]: %s %s", + PrintAndLog(" Auth1 [43/0x2B] : %s %s", sprint_hex(data+12, 4), (data[12] & 1) ? "write access restricted": "read and write access restricted" ); @@ -412,22 +425,22 @@ static int ulev1_print_configuration( uint8_t *data){ bool prot = (data[4] & 0x80); uint8_t vctid = data[5]; - PrintAndLog(" cfg0 [16/0x10]: %s", sprint_hex(data, 4)); + PrintAndLog(" cfg0 [16/0x10] : %s", sprint_hex(data, 4)); if ( data[3] < 0xff ) PrintAndLog(" - page %d and above need authentication",data[3]); else PrintAndLog(" - pages don't need authentication"); PrintAndLog(" - strong modulation mode %s", (strg_mod_en) ? "enabled":"disabled"); - PrintAndLog(" cfg1 [17/0x11]: %s", sprint_hex(data+4, 4) ); + PrintAndLog(" cfg1 [17/0x11] : %s", sprint_hex(data+4, 4) ); if ( authlim == 0) PrintAndLog(" - Unlimited password attempts"); else PrintAndLog(" - Max number of password attempts is %d", authlim); PrintAndLog(" - user configuration %s", cfglck ? "permanently locked":"writeable"); PrintAndLog(" - %s access is protected with password", prot ? "read and write":"write"); - PrintAndLog(" %02X - Virtual Card Type Identifier is %s default", vctid, (vctid==0x05)? "":"not"); - PrintAndLog(" PWD [18/0x12]: %s", sprint_hex(data+8, 4)); - PrintAndLog(" PACK [19/0x13]: %s", sprint_hex(data+12, 4)); + PrintAndLog(" - %02X, Virtual Card Type Identifier is %s default", vctid, (vctid==0x05)? "":"not"); + PrintAndLog(" PWD [18/0x12] : %s", sprint_hex(data+8, 4)); + PrintAndLog(" PACK [19/0x13] : %s", sprint_hex(data+12, 4)); return 0; } @@ -460,10 +473,10 @@ static int ulev1_print_signature( uint8_t *data, uint8_t len){ static int ulev1_print_version(uint8_t *data){ PrintAndLog("\n--- Tag Version"); - PrintAndLog(" Raw bytes : %s", sprint_hex(data, 8) ); - PrintAndLog(" Vendor ID : %02X %s", data[1], getTagInfo(data[1])); + PrintAndLog(" Raw bytes : %s",sprint_hex(data, 8) ); + PrintAndLog(" Vendor ID : %02X, %s", data[1], getTagInfo(data[1])); PrintAndLog(" Product type : %s", getProductTypeStr(data[2])); - PrintAndLog(" Product subtype : %02X %s", data[3], (data[3]==1) ?"17 pF":"50pF"); + PrintAndLog(" Product subtype : %02X, %s", data[3], (data[3]==1) ?"17 pF":"50pF"); PrintAndLog(" Major version : %02X", data[4]); PrintAndLog(" Minor version : %02X", data[5]); PrintAndLog(" Size : %s", getUlev1CardSizeStr(data[6])); @@ -556,7 +569,6 @@ uint32_t GetHF14AMfU_Type(void){ tagtype = NTAG_I2C_1K; else if ( version[2] == 0x04 && version[3] == 0x05 && version[6] == 0x15 ) tagtype = NTAG_I2C_2K; - else if ( version[2] == 0x04 ) tagtype = NTAG; @@ -675,24 +687,7 @@ int CmdHF14AMfUInfo(const char *Cmd){ PrintAndLog("-------------------------------------------------------------"); ul_print_type(tagtype, 6); - if ( hasAuthKey && (tagtype & UL_C)) { - //will select card automatically and close connection on error - if (!ulc_authentication(authenticationkey, false)) { - PrintAndLog("Error: Authentication Failed UL-C"); - return 0; - } - } else { - if ( !ul_select(&card) ) return 0; - - if (hasAuthKey) { - len = ulev1_requestAuthentication(authenticationkey, pack, sizeof(pack)); - if (len < 1) { - ul_switch_off_field(); - PrintAndLog("Error: Authentication Failed UL-EV1/NTAG"); - return 0; - } - } - } + if (!ul_auth_select( &card, tagtype, hasAuthKey, authenticationkey, pack, sizeof(pack))) return -1; // read pages 0,1,2,3 (should read 4pages) status = ul_read(0, data, sizeof(data)); @@ -700,11 +695,12 @@ int CmdHF14AMfUInfo(const char *Cmd){ ul_switch_off_field(); PrintAndLog("Error: tag didn't answer to READ"); return status; - } - if (status == 16) { + } else if (status == 16) { ul_print_default(data); ndef_print_CC(data+12); - } else locked = true; + } else { + locked = true; + } // UL_C Specific if ((tagtype & UL_C)) { @@ -748,7 +744,7 @@ int CmdHF14AMfUInfo(const char *Cmd){ } } // reselect for future tests (ntag test) - if ( !ul_select(&card) ) return 0; + if (!ul_auth_select( &card, tagtype, hasAuthKey, authenticationkey, pack, sizeof(pack))) return -1; } } @@ -758,7 +754,7 @@ int CmdHF14AMfUInfo(const char *Cmd){ if ((tagtype & (UL_EV1_48 | UL_EV1_128))) { if (ulev1_print_counters() != 3) { // failed - re-select - if ( !ul_select(&card) ) return 0; + if (!ul_auth_select( &card, tagtype, hasAuthKey, authenticationkey, pack, sizeof(pack))) return -1; } } @@ -773,7 +769,7 @@ int CmdHF14AMfUInfo(const char *Cmd){ if (status == 32) ulev1_print_signature( ulev1_signature, sizeof(ulev1_signature)); else { // re-select - if ( !ul_select(&card) ) return 0; + if (!ul_auth_select( &card, tagtype, hasAuthKey, authenticationkey, pack, sizeof(pack))) return -1; } } @@ -784,9 +780,12 @@ int CmdHF14AMfUInfo(const char *Cmd){ PrintAndLog("Error: tag didn't answer to GETVERSION"); ul_switch_off_field(); return status; + } else if (status == 10) { + ulev1_print_version(version); + } else { + locked = true; + if (!ul_auth_select( &card, tagtype, hasAuthKey, authenticationkey, pack, sizeof(pack))) return -1; } - if (status == 10) ulev1_print_version(version); - else locked = true; uint8_t startconfigblock = 0; uint8_t ulev1_conf[16] = {0x00}; @@ -822,7 +821,7 @@ int CmdHF14AMfUInfo(const char *Cmd){ PrintAndLog("Found a default password: %s || Pack: %02X %02X",sprint_hex(key, 4), pack[0], pack[1]); break; } else { - if ( !ul_select(&card) ) return 0; + if (!ul_auth_select( &card, tagtype, hasAuthKey, authenticationkey, pack, sizeof(pack))) return -1; } } if (len < 1) PrintAndLog("password not known"); From efd193519c5e4613a16b7a13dd69a9962df0b218 Mon Sep 17 00:00:00 2001 From: marshmellow42 Date: Thu, 21 May 2015 11:17:01 -0400 Subject: [PATCH 46/49] hf mfu bug fixes, and help text fixes --- client/cmdhfmfu.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/client/cmdhfmfu.c b/client/cmdhfmfu.c index 7f0e8fc56..b3304f163 100644 --- a/client/cmdhfmfu.c +++ b/client/cmdhfmfu.c @@ -600,7 +600,7 @@ uint32_t GetHF14AMfU_Type(void){ tagtype = UL; } else { // read page 0x30 (should error if it is a ntag203) - status = ul_read(30, data, sizeof(data)); + status = ul_read(0x30, data, sizeof(data)); if ( status <= 1 ){ tagtype = NTAG_203; } else { @@ -679,7 +679,7 @@ int CmdHF14AMfUInfo(const char *Cmd){ //Validations if(errors) return usage_hf_mfu_info(); - + TagTypeUL_t tagtype = GetHF14AMfU_Type(); if (tagtype == UL_ERROR) return -1; @@ -698,7 +698,7 @@ int CmdHF14AMfUInfo(const char *Cmd){ } else if (status == 16) { ul_print_default(data); ndef_print_CC(data+12); - } else { + } else { locked = true; } @@ -740,11 +740,10 @@ int CmdHF14AMfUInfo(const char *Cmd){ uint8_t keySwap[16]; memcpy(keySwap, SwapEndian64(key,16,8), 16); ulc_print_3deskey(keySwap); - break; + return 1; } } - // reselect for future tests (ntag test) - if (!ul_auth_select( &card, tagtype, hasAuthKey, authenticationkey, pack, sizeof(pack))) return -1; + return 1; } } @@ -950,8 +949,8 @@ int usage_hf_mfu_info(void) PrintAndLog("It gathers information about the tag and tries to detect what kind it is."); PrintAndLog("Sometimes the tags are locked down, and you may need a key to be able to read the information"); PrintAndLog("The following tags can be identified:\n"); - PrintAndLog("Ultralight, Ultralight-C, Ultralight EV1"); - PrintAndLog("NTAG 213, NTAG 215, NTAG 216"); + PrintAndLog("Ultralight, Ultralight-C, Ultralight EV1, NTAG 203, NTAG 210,"); + PrintAndLog("NTAG 212, NTAG 213, NTAG 215, NTAG 216, NTAG I2C 1K & 2K"); PrintAndLog("my-d, my-d NFC, my-d move, my-d move NFC\n"); PrintAndLog("Usage: hf mfu info k "); PrintAndLog(" Options : "); @@ -965,6 +964,7 @@ int usage_hf_mfu_info(void) int usage_hf_mfu_dump(void) { PrintAndLog("Reads all pages from Ultralight, Ultralight-C, Ultralight EV1"); + PrintAndLog("NTAG 203, NTAG 210, NTAG 212, NTAG 213, NTAG 215, NTAG 216"); PrintAndLog("and saves binary dump into the file `filename.bin` or `cardUID.bin`"); PrintAndLog("It autodetects card type.\n"); PrintAndLog("Usage: hf mfu dump l k n "); From 06561c34efdb6c0aaaf1008cca3ac8cb82065df9 Mon Sep 17 00:00:00 2001 From: marshmellow42 Date: Fri, 22 May 2015 00:15:57 -0400 Subject: [PATCH 47/49] fix to dump cmd print keys. add l option to info cmd. add ascii print to dump (screen only) other minor clean up --- client/cmdhfmfu.c | 135 ++++++++++++++++++++++++---------------------- 1 file changed, 70 insertions(+), 65 deletions(-) diff --git a/client/cmdhfmfu.c b/client/cmdhfmfu.c index b3304f163..c5f061b1f 100644 --- a/client/cmdhfmfu.c +++ b/client/cmdhfmfu.c @@ -94,9 +94,9 @@ char *getUlev1CardSizeStr( uint8_t fsize ){ // is LSB set? if ( fsize & 1 ) - sprintf(retStr, "%02X (%u <-> %u bytes)",fsize, usize, lsize); + sprintf(retStr, "%02X, (%u <-> %u bytes)",fsize, usize, lsize); else - sprintf(retStr, "%02X (%u bytes)", fsize, lsize); + sprintf(retStr, "%02X, (%u bytes)", fsize, lsize); return buf; } @@ -462,7 +462,7 @@ static int ulev1_print_counters(){ static int ulev1_print_signature( uint8_t *data, uint8_t len){ PrintAndLog("\n--- Tag Signature"); - PrintAndLog("IC signature public key name : NXP NTAG21x 2013"); // don't know if there is other NXP public keys.. :( + //PrintAndLog("IC signature public key name : NXP NTAG21x 2013"); // don't know if there is other NXP public keys.. :( PrintAndLog("IC signature public key value : 04494e1a386d3d3cfe3dc10e5de68a499b1c202db5b132393e89ed19fe5be8bc61"); PrintAndLog(" Elliptic curve parameters : secp128r1"); PrintAndLog(" Tag ECC Signature : %s", sprint_hex(data, len)); @@ -620,7 +620,6 @@ uint32_t GetHF14AMfU_Type(void){ } } - tagtype |= ul_magic_test(); if (tagtype == (UNKNOWN | MAGIC)) tagtype = (UL_MAGIC); return tagtype; @@ -631,16 +630,19 @@ int CmdHF14AMfUInfo(const char *Cmd){ uint8_t authlim = 0xff; uint8_t data[16] = {0x00}; iso14a_card_select_t card; - uint8_t *key; int status; bool errors = false; bool hasAuthKey = false; bool locked = false; + bool swapEndian = false; uint8_t cmdp = 0; - uint8_t datalen = 0; + uint8_t dataLen = 0; uint8_t authenticationkey[16] = {0x00}; + uint8_t *authkeyptr = authenticationkey; + uint8_t *key; uint8_t pack[4] = {0,0,0,0}; - int len=0; + int len = 0; + char tempStr[50]; while(param_getchar(Cmd, cmdp) != 0x00) { @@ -651,23 +653,21 @@ int CmdHF14AMfUInfo(const char *Cmd){ return usage_hf_mfu_info(); case 'k': case 'K': - // EV1/NTAG size key - datalen = param_gethex(Cmd, cmdp+1, data, 8); - if ( !datalen ) { - memcpy(authenticationkey, data, 4); - cmdp += 2; - hasAuthKey = true; - break; + dataLen = param_getstr(Cmd, cmdp+1, tempStr); + if (dataLen == 32 || dataLen == 8) { //ul-c or ev1/ntag key length + errors = param_gethex(tempStr, 0, authenticationkey, dataLen); + dataLen /= 2; // handled as bytes from now on + } else { + PrintAndLog("\nERROR: Key is incorrect length\n"); + errors = true; } - // UL-C size key - datalen = param_gethex(Cmd, cmdp+1, data, 32); - if (!datalen){ - memcpy(authenticationkey, data, 16); - cmdp += 2; - hasAuthKey = true; - break; - } - errors = true; + cmdp += 2; + hasAuthKey = true; + break; + case 'l': + case 'L': + swapEndian = true; + cmdp++; break; default: PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp)); @@ -687,7 +687,10 @@ int CmdHF14AMfUInfo(const char *Cmd){ PrintAndLog("-------------------------------------------------------------"); ul_print_type(tagtype, 6); - if (!ul_auth_select( &card, tagtype, hasAuthKey, authenticationkey, pack, sizeof(pack))) return -1; + // Swap endianness + if (swapEndian && hasAuthKey) authkeyptr = SwapEndian64(authenticationkey, dataLen, (dataLen == 16) ? 8 : 4 ); + + if (!ul_auth_select( &card, tagtype, hasAuthKey, authkeyptr, pack, sizeof(pack))) return -1; // read pages 0,1,2,3 (should read 4pages) status = ul_read(0, data, sizeof(data)); @@ -732,6 +735,7 @@ int CmdHF14AMfUInfo(const char *Cmd){ // if we called info with key, just return if ( hasAuthKey ) return 1; + // also try to diversify default keys.. look into CmdHF14AMfuGenDiverseKeys PrintAndLog("Trying some default 3des keys"); for (uint8_t i = 0; i < KEYS_3DES_COUNT; ++i ) { key = default_3des_keys[i]; @@ -944,33 +948,33 @@ int CmdHF14AMfURdBl(const char *Cmd){ return 0; } -int usage_hf_mfu_info(void) -{ +int usage_hf_mfu_info(void) { PrintAndLog("It gathers information about the tag and tries to detect what kind it is."); PrintAndLog("Sometimes the tags are locked down, and you may need a key to be able to read the information"); PrintAndLog("The following tags can be identified:\n"); PrintAndLog("Ultralight, Ultralight-C, Ultralight EV1, NTAG 203, NTAG 210,"); PrintAndLog("NTAG 212, NTAG 213, NTAG 215, NTAG 216, NTAG I2C 1K & 2K"); PrintAndLog("my-d, my-d NFC, my-d move, my-d move NFC\n"); - PrintAndLog("Usage: hf mfu info k "); + PrintAndLog("Usage: hf mfu info k l"); PrintAndLog(" Options : "); - PrintAndLog(" k : key for authentication [UL-C 16bytes, EV1/NTAG 4bytes]"); + PrintAndLog(" k : (optional) key for authentication [UL-C 16bytes, EV1/NTAG 4bytes]"); + PrintAndLog(" l : (optional) swap entered key's endianness"); PrintAndLog(""); PrintAndLog(" sample : hf mfu info"); - PrintAndLog(" : hf mfu info k 11223344"); + PrintAndLog(" : hf mfu info k 00112233445566778899AABBCCDDEEFF"); + PrintAndLog(" : hf mfu info k AABBCCDDD"); return 0; } -int usage_hf_mfu_dump(void) -{ +int usage_hf_mfu_dump(void) { PrintAndLog("Reads all pages from Ultralight, Ultralight-C, Ultralight EV1"); PrintAndLog("NTAG 203, NTAG 210, NTAG 212, NTAG 213, NTAG 215, NTAG 216"); PrintAndLog("and saves binary dump into the file `filename.bin` or `cardUID.bin`"); PrintAndLog("It autodetects card type.\n"); - PrintAndLog("Usage: hf mfu dump l k n "); + PrintAndLog("Usage: hf mfu dump k l n "); PrintAndLog(" Options : "); - PrintAndLog(" k : key for authentication [UL-C 16bytes, EV1/NTAG 4bytes]"); - PrintAndLog(" l : swap entered key's endianness for auth"); + PrintAndLog(" k : (optional) key for authentication [UL-C 16bytes, EV1/NTAG 4bytes]"); + PrintAndLog(" l : (optional) swap entered key's endianness"); PrintAndLog(" n : filename w/o .bin to save the dump as"); PrintAndLog(" p : starting Page number to manually set a page to start the dump at"); PrintAndLog(" q : number of Pages to manually set how many pages to dump"); @@ -979,6 +983,7 @@ int usage_hf_mfu_dump(void) PrintAndLog(" sample : hf mfu dump"); PrintAndLog(" : hf mfu dump n myfile"); PrintAndLog(" : hf mfu dump k 00112233445566778899AABBCCDDEEFF"); + PrintAndLog(" : hf mfu dump k AABBCCDDD\n"); return 0; } @@ -997,14 +1002,14 @@ int CmdHF14AMfUDump(const char *Cmd){ bool bit[16] = {0x00}; bool bit2[16] = {0x00}; uint8_t data[1024] = {0x00}; - bool hasPwd = false; + bool hasAuthKey = false; int i = 0; int Pages = 16; bool tmplockbit = false; - uint8_t dataLen=0; - uint8_t cmdp =0; - uint8_t key[16] = {0x00}; - uint8_t *keyPtr = key; + uint8_t dataLen = 0; + uint8_t cmdp = 0; + uint8_t authenticationkey[16] = {0x00}; + uint8_t *authKeyPtr = authenticationkey; size_t fileNlen = 0; bool errors = false; bool swapEndian = false; @@ -1022,17 +1027,15 @@ int CmdHF14AMfUDump(const char *Cmd){ case 'k': case 'K': dataLen = param_getstr(Cmd, cmdp+1, tempStr); - if (dataLen == 32) //ul-c - errors = param_gethex(tempStr, 0, key, dataLen); - else if (dataLen == 8) //ev1/ntag - errors = param_gethex(tempStr, 0, key, dataLen); - else{ + if (dataLen == 32 || dataLen == 8) { //ul-c or ev1/ntag key length + errors = param_gethex(tempStr, 0, authenticationkey, dataLen); + dataLen /= 2; + } else { PrintAndLog("\nERROR: Key is incorrect length\n"); errors = true; } - cmdp += 2; - hasPwd = true; + hasAuthKey = true; break; case 'l': case 'L': @@ -1069,8 +1072,8 @@ int CmdHF14AMfUDump(const char *Cmd){ //Validations if(errors) return usage_hf_mfu_dump(); - if (swapEndian && dataLen == 32) - keyPtr = SwapEndian64(data, 16, 8); + if (swapEndian && hasAuthKey) + authKeyPtr = SwapEndian64(authenticationkey, dataLen, (dataLen == 16) ? 8 : 4); TagTypeUL_t tagtype = GetHF14AMfU_Type(); if (tagtype == UL_ERROR) return -1; @@ -1083,13 +1086,13 @@ int CmdHF14AMfUDump(const char *Cmd){ ul_print_type(tagtype, 0); PrintAndLog("Reading tag memory..."); UsbCommand c = {CMD_MIFAREU_READCARD, {startPage,Pages}}; - if ( hasPwd ) { + if ( hasAuthKey ) { if (tagtype & UL_C) c.arg[2] = 1; //UL_C auth else c.arg[2] = 2; //UL_EV1/NTAG auth - memcpy(c.d.asBytes, key, dataLen/2); + memcpy(c.d.asBytes, authKeyPtr, dataLen); } SendCommand(&c); UsbCommand resp; @@ -1133,12 +1136,14 @@ int CmdHF14AMfUDump(const char *Cmd){ } // add keys to block dump - if (hasPwd && (tagtype & UL_C)) { //UL_C - memcpy(data + Pages*4, key, dataLen/2); - Pages += 4; - } else if (hasPwd) { //not sure output is in correct location. - memcpy(data + Pages*4, key, dataLen/2); - Pages += 1; + if (hasAuthKey) { + if (!swapEndian) { + authKeyPtr = SwapEndian64(authenticationkey, dataLen, (dataLen == 16) ? 8 : 4); + memcpy(data + Pages*4, authKeyPtr, dataLen); + } else { + memcpy(data + Pages*4, authenticationkey, dataLen); + } + Pages += dataLen/4; //not sure output is in correct location for all tag types. } for (i = 0; i < Pages; ++i) { @@ -1148,11 +1153,11 @@ int CmdHF14AMfUDump(const char *Cmd){ } switch(i){ case 3: tmplockbit = bit[4]; break; - case 4: tmplockbit = bit[3]; break; - case 5: tmplockbit = bit[2]; break; - case 6: tmplockbit = bit[1]; break; - case 7: tmplockbit = bit[0]; break; - case 8: tmplockbit = bit[15]; break; + case 4: tmplockbit = bit[3]; break; + case 5: tmplockbit = bit[2]; break; + case 6: tmplockbit = bit[1]; break; + case 7: tmplockbit = bit[0]; break; + case 8: tmplockbit = bit[15]; break; case 9: tmplockbit = bit[14]; break; case 10: tmplockbit = bit[13]; break; case 11: tmplockbit = bit[12]; break; @@ -1171,7 +1176,7 @@ int CmdHF14AMfUDump(const char *Cmd){ case 24: case 25: case 26: - case 27: tmplockbit = bit2[4]; break; + case 27: tmplockbit = bit2[4]; break; case 28: case 29: case 30: @@ -1190,8 +1195,8 @@ int CmdHF14AMfUDump(const char *Cmd){ case 43: tmplockbit = bit2[9]; break; //auth1 default: break; } - PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),tmplockbit); - } + PrintAndLog("Block %02x:%s [%d] {%.4s}", i, sprint_hex(data + i * 4, 4), tmplockbit, data+i*4); + } // user supplied filename? if (fileNlen < 1) { @@ -1204,7 +1209,7 @@ int CmdHF14AMfUDump(const char *Cmd){ if ((fout = fopen(filename,"wb")) == NULL) { PrintAndLog("Could not create file name %s", filename); - return 1; + return 1; } fwrite( data, 1, Pages*4, fout ); fclose(fout); From 8f2e50b4c5aad09db70f82bbf6b865e283ad5e5e Mon Sep 17 00:00:00 2001 From: marshmellow42 Date: Fri, 22 May 2015 07:29:18 -0400 Subject: [PATCH 48/49] mfu info authkeyptr fix didn't follow @iceman1001 s l parameter changes fully... fixed now.. :) --- client/cmdhfmfu.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/client/cmdhfmfu.c b/client/cmdhfmfu.c index c5f061b1f..dbe4a7540 100644 --- a/client/cmdhfmfu.c +++ b/client/cmdhfmfu.c @@ -757,7 +757,7 @@ int CmdHF14AMfUInfo(const char *Cmd){ if ((tagtype & (UL_EV1_48 | UL_EV1_128))) { if (ulev1_print_counters() != 3) { // failed - re-select - if (!ul_auth_select( &card, tagtype, hasAuthKey, authenticationkey, pack, sizeof(pack))) return -1; + if (!ul_auth_select( &card, tagtype, hasAuthKey, authkeyptr, pack, sizeof(pack))) return -1; } } @@ -772,7 +772,7 @@ int CmdHF14AMfUInfo(const char *Cmd){ if (status == 32) ulev1_print_signature( ulev1_signature, sizeof(ulev1_signature)); else { // re-select - if (!ul_auth_select( &card, tagtype, hasAuthKey, authenticationkey, pack, sizeof(pack))) return -1; + if (!ul_auth_select( &card, tagtype, hasAuthKey, authkeyptr, pack, sizeof(pack))) return -1; } } @@ -787,7 +787,7 @@ int CmdHF14AMfUInfo(const char *Cmd){ ulev1_print_version(version); } else { locked = true; - if (!ul_auth_select( &card, tagtype, hasAuthKey, authenticationkey, pack, sizeof(pack))) return -1; + if (!ul_auth_select( &card, tagtype, hasAuthKey, authkeyptr, pack, sizeof(pack))) return -1; } uint8_t startconfigblock = 0; @@ -824,7 +824,7 @@ int CmdHF14AMfUInfo(const char *Cmd){ PrintAndLog("Found a default password: %s || Pack: %02X %02X",sprint_hex(key, 4), pack[0], pack[1]); break; } else { - if (!ul_auth_select( &card, tagtype, hasAuthKey, authenticationkey, pack, sizeof(pack))) return -1; + if (!ul_auth_select( &card, tagtype, hasAuthKey, authkeyptr, pack, sizeof(pack))) return -1; } } if (len < 1) PrintAndLog("password not known"); From 012c0761bd69ac3bba5e89ae4347c5e16aa81701 Mon Sep 17 00:00:00 2001 From: marshmellow42 Date: Fri, 22 May 2015 13:17:51 -0400 Subject: [PATCH 49/49] hf mfu minor output adjustments dump key placed properly for EV1 and NTAGs config pages for ntags corrected in printout note on config that PWD and PACK cannot actually be read from memory (probably could just delete them (other than it shows what memory block they are stored in for changing...) --- client/cmdhfmfu.c | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/client/cmdhfmfu.c b/client/cmdhfmfu.c index dbe4a7540..07c379bc0 100644 --- a/client/cmdhfmfu.c +++ b/client/cmdhfmfu.c @@ -415,7 +415,7 @@ static int ulc_print_configuration( uint8_t *data){ return 0; } -static int ulev1_print_configuration( uint8_t *data){ +static int ulev1_print_configuration( uint8_t *data, uint8_t startPage){ PrintAndLog("\n--- Tag Configuration"); @@ -425,13 +425,13 @@ static int ulev1_print_configuration( uint8_t *data){ bool prot = (data[4] & 0x80); uint8_t vctid = data[5]; - PrintAndLog(" cfg0 [16/0x10] : %s", sprint_hex(data, 4)); + PrintAndLog(" cfg0 [%u/0x%02X] : %s", startPage, startPage, sprint_hex(data, 4)); if ( data[3] < 0xff ) PrintAndLog(" - page %d and above need authentication",data[3]); else PrintAndLog(" - pages don't need authentication"); PrintAndLog(" - strong modulation mode %s", (strg_mod_en) ? "enabled":"disabled"); - PrintAndLog(" cfg1 [17/0x11] : %s", sprint_hex(data+4, 4) ); + PrintAndLog(" cfg1 [%u/0x%02X] : %s", startPage + 1, startPage + 1, sprint_hex(data+4, 4) ); if ( authlim == 0) PrintAndLog(" - Unlimited password attempts"); else @@ -439,8 +439,9 @@ static int ulev1_print_configuration( uint8_t *data){ PrintAndLog(" - user configuration %s", cfglck ? "permanently locked":"writeable"); PrintAndLog(" - %s access is protected with password", prot ? "read and write":"write"); PrintAndLog(" - %02X, Virtual Card Type Identifier is %s default", vctid, (vctid==0x05)? "":"not"); - PrintAndLog(" PWD [18/0x12] : %s", sprint_hex(data+8, 4)); - PrintAndLog(" PACK [19/0x13] : %s", sprint_hex(data+12, 4)); + PrintAndLog(" PWD [%u/0x%02X] : %s- (cannot be read)", startPage + 2, startPage + 2, sprint_hex(data+8, 4)); + PrintAndLog(" PACK [%u/0x%02X] : %s - (cannot be read)", startPage + 3, startPage + 3, sprint_hex(data+12, 2)); + PrintAndLog(" RFU [%u/0x%02X] : %s- (cannot be read)", startPage + 3, startPage + 3, sprint_hex(data+12, 2)); return 0; } @@ -806,7 +807,7 @@ int CmdHF14AMfUInfo(const char *Cmd){ } else if (status == 16) { // save AUTHENTICATION LIMITS for later: authlim = (ulev1_conf[4] & 0x07); - ulev1_print_configuration(ulev1_conf); + ulev1_print_configuration(ulev1_conf, startconfigblock); } } @@ -1137,13 +1138,18 @@ int CmdHF14AMfUDump(const char *Cmd){ // add keys to block dump if (hasAuthKey) { - if (!swapEndian) { + if (!swapEndian){ authKeyPtr = SwapEndian64(authenticationkey, dataLen, (dataLen == 16) ? 8 : 4); - memcpy(data + Pages*4, authKeyPtr, dataLen); } else { - memcpy(data + Pages*4, authenticationkey, dataLen); + authKeyPtr = authenticationkey; + } + + if (tagtype & UL_C){ //add 4 pages + memcpy(data + Pages*4, authKeyPtr, dataLen); + Pages += dataLen/4; + } else { // 2nd page from end + memcpy(data + (Pages*4) - 8, authenticationkey, dataLen); } - Pages += dataLen/4; //not sure output is in correct location for all tag types. } for (i = 0; i < Pages; ++i) { @@ -1195,7 +1201,7 @@ int CmdHF14AMfUDump(const char *Cmd){ case 43: tmplockbit = bit2[9]; break; //auth1 default: break; } - PrintAndLog("Block %02x:%s [%d] {%.4s}", i, sprint_hex(data + i * 4, 4), tmplockbit, data+i*4); + PrintAndLog("Block %02X:%s [%d] {%.4s}", i, sprint_hex(data + i * 4, 4), tmplockbit, data+i*4); } // user supplied filename?