X-Git-Url: https://git.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/blobdiff_plain/623db3559bd3da895035f61cf1f1a7374f2365cf..329f5cf2a5aba57b396e4070067d5de9dc22e157:/client/cmdhfmfu.c diff --git a/client/cmdhfmfu.c b/client/cmdhfmfu.c index 13928915..482d14ba 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 @@ -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; } @@ -100,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; } @@ -150,11 +144,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 (!ans || resp.arg[0] < 1) { + 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. @@ -259,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, %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){ @@ -303,23 +302,23 @@ static int ndef_print_CC(uint8_t *data) { 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 : NDEF Memory Size: %d bytes", data[2], 872); - PrintAndLog(" %02X: %s / %s", data[3], + 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; } -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); @@ -347,9 +346,9 @@ int ul_print_type(uint16_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 i2c 888bytes (NT3H1101FHK )", spacer); + PrintAndLog("%sTYPE : NTAG I%sC 888bytes (NT3H1101FHK)", spacer, "\xFD"); else if ( tagtype & NTAG_I2C_2K ) - PrintAndLog("%sTYPE : NTAG i2c 1904bytes (NT3H1201FHK )", spacer); + 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 ) @@ -364,10 +363,10 @@ int ul_print_type(uint16_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; } @@ -375,20 +374,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" ); @@ -428,13 +427,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) ); + 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){ @@ -451,7 +453,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]); @@ -474,9 +476,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)); @@ -496,17 +496,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 = ul_select(&card); - if ( status < 1 ){ - PrintAndLog("iso14443a card select failed"); - ul_switch_off_field(); + 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 MAGIC; - return UNKNOWN; + return 0; } uint32_t GetHF14AMfU_Type(void){ @@ -517,12 +513,8 @@ uint32_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); @@ -568,12 +560,7 @@ uint32_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}; @@ -583,12 +570,8 @@ uint32_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)); @@ -616,8 +599,9 @@ uint32_t GetHF14AMfU_Type(void){ } } - tagtype = (ul_magic_test() == MAGIC) ? (tagtype | MAGIC) : tagtype; + tagtype |= ul_magic_test(); + if (tagtype == (UNKNOWN | MAGIC)) tagtype = (UL_MAGIC); return tagtype; } @@ -630,12 +614,13 @@ int CmdHF14AMfUInfo(const char *Cmd){ int status; bool errors = false; bool hasAuthKey = false; + bool hasPwdKey = false; bool locked = false; uint8_t cmdp = 0; uint8_t datalen = 0; uint8_t authenticationkey[16] = {0x00}; uint8_t pack[4] = {0,0,0,0}; - int len=0; + int len = 0; while(param_getchar(Cmd, cmdp) != 0x00) { @@ -651,7 +636,7 @@ int CmdHF14AMfUInfo(const char *Cmd){ if ( !datalen ) { memcpy(authenticationkey, data, 4); cmdp += 2; - hasAuthKey = true; + hasPwdKey = true; break; } // UL-C size key @@ -682,28 +667,24 @@ int CmdHF14AMfUInfo(const char *Cmd){ PrintAndLog("-------------------------------------------------------------"); ul_print_type(tagtype, 6); + if (!ul_select(&card)) return 0; + 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(); - PrintAndLog("Error: Authentication Failed UL-EV1/NTAG"); - return 0; - } + PrintAndLog("Error: Authentication Failed UL-C"); + return 0; } } + + if ( hasPwdKey ) { + len = ulev1_requestAuthentication(authenticationkey, pack, sizeof(pack)); + if (len < 1) { + ul_switch_off_field(); + PrintAndLog("Error: Authentication Failed UL-EV1/NTAG"); + return 0; + } + } // read pages 0,1,2,3 (should read 4pages) status = ul_read(0, data, sizeof(data)); @@ -712,6 +693,7 @@ int CmdHF14AMfUInfo(const char *Cmd){ PrintAndLog("Error: tag didn't answer to READ"); return status; } + if (status == 16) { ul_print_default(data); ndef_print_CC(data+12); @@ -763,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 | NTAG_I2C_1K | NTAG_I2C_2K ))) { uint8_t ulev1_signature[32] = {0x00}; @@ -786,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 | NTAG_I2C_1K | NTAG_I2C_2K))) { @@ -806,6 +792,7 @@ int CmdHF14AMfUInfo(const char *Cmd){ if (tagtype & UL_TYPES_ARRAY[idx]) startconfigblock = UL_MEMORY_ARRAY[idx]-3; + 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"); @@ -815,8 +802,7 @@ int CmdHF14AMfUInfo(const char *Cmd){ // save AUTHENTICATION LIMITS for later: authlim = (ulev1_conf[4] & 0x07); ulev1_print_configuration(ulev1_conf); - } else { - authlim=7; + } } // AUTHLIMIT, (number of failed authentications) @@ -833,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");