+int ul_print_type(uint32_t tagtype, uint8_t spaces){
+ char spc[11] = " ";
+ spc[10]=0x00;
+ char *spacer = spc + (10-spaces);
+
+ if ( tagtype & UL )
+ PrintAndLog("%sTYPE : MIFARE Ultralight (MF0ICU1) %s", spacer, (tagtype & MAGIC) ? "<magic>" : "" );
+ else if ( tagtype & UL_C)
+ PrintAndLog("%sTYPE : MIFARE Ultralight C (MF0ULC) %s", spacer, (tagtype & MAGIC) ? "<magic>" : "" );
+ else if ( tagtype & UL_EV1_48)
+ 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_210 )
+ PrintAndLog("%sTYPE : NTAG 210 48bytes (NT2L1011G0DU)", spacer);
+ else if ( tagtype & NTAG_212 )
+ 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 : NTAG 215 504bytes (NT2H1511G0DU)", spacer);
+ 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\0153 (SLE 66RxxS)", spacer);
+ else if ( tagtype & MY_D_NFC )
+ PrintAndLog("%sTYPE : INFINEON my-d\0153 NFC (SLE 66RxxP)", spacer);
+ else if ( tagtype & MY_D_MOVE )
+ PrintAndLog("%sTYPE : INFINEON my-d\0153 move (SLE 66R01P)", spacer);
+ else if ( tagtype & MY_D_MOVE_NFC )
+ PrintAndLog("%sTYPE : INFINEON my-d\0153 move NFC (SLE 66R01P)", spacer);
+ else if ( tagtype & MY_D_MOVE_LEAN )
+ PrintAndLog("%sTYPE : INFINEON my-d\x99 move lean (SLE 66R01L)", spacer);
+ else
+ PrintAndLog("%sTYPE : Unknown %06x", spacer, tagtype);
+ return 0;
+}
+
+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("\n 3des key : %s", sprint_hex(SwapEndian64(data, 16, 8), 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 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) );
+ } 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, uint8_t startPage){
+
+ PrintAndLog("\n--- Tag 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 [%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 [%u/0x%02X] : %s", startPage + 1, startPage + 1, 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 [%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;
+}
+
+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));
+ 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 len;
+}
+
+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 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 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(" 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
+ // 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;