+ PrintAndLogEx(NORMAL, " Auth0 [42/0x2A] : %s auth byte is out-of-range", sprint_hex(data+8, 4) );
+ }
+ }
+ PrintAndLogEx(NORMAL, " 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) {
+
+ PrintAndLogEx(NORMAL, "\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];
+
+ PrintAndLogEx(NORMAL, " cfg0 [%u/0x%02X] : %s", startPage, startPage, sprint_hex(data, 4));
+ if (data[3] < 0xff)
+ PrintAndLogEx(NORMAL, " - page %d and above need authentication", data[3]);
+ else
+ PrintAndLogEx(NORMAL, " - pages don't need authentication");
+ PrintAndLogEx(NORMAL, " - strong modulation mode %s", (strg_mod_en) ? "enabled" : "disabled");
+ PrintAndLogEx(NORMAL, " cfg1 [%u/0x%02X] : %s", startPage + 1, startPage + 1, sprint_hex(data+4, 4) );
+ if (authlim == 0)
+ PrintAndLogEx(NORMAL, " - Unlimited password attempts");
+ else
+ PrintAndLogEx(NORMAL, " - Max number of password attempts is %d", authlim);
+ PrintAndLogEx(NORMAL, " - user configuration %s", cfglck ? "permanently locked":"writeable");
+ PrintAndLogEx(NORMAL, " - %s access is protected with password", prot ? "read and write":"write");
+ PrintAndLogEx(NORMAL, " - %02X, Virtual Card Type Identifier is %s default", vctid, (vctid==0x05)? "":"not");
+ PrintAndLogEx(NORMAL, " PWD [%u/0x%02X] : %s- (cannot be read)", startPage + 2, startPage + 2, sprint_hex(data+8, 4));
+ PrintAndLogEx(NORMAL, " PACK [%u/0x%02X] : %s - (cannot be read)", startPage + 3, startPage + 3, sprint_hex(data+12, 2));
+ PrintAndLogEx(NORMAL, " RFU [%u/0x%02X] : %s- (cannot be read)", startPage + 3, startPage + 3, sprint_hex(data+14, 2));
+ return 0;
+}
+
+
+static int ulev1_print_counters(void) {
+ PrintAndLogEx(NORMAL, "--- 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) {
+ PrintAndLogEx(NORMAL, " [%0d] : %s", i, sprint_hex(counter,3));
+ PrintAndLogEx(NORMAL, " - %02X tearing %s", tear[0], ( tear[0]==0xBD)?"Ok":"failure");
+ }
+ }
+ return len;
+}
+
+
+static int ulev1_print_signature( uint8_t *data, uint8_t len){
+ PrintAndLogEx(NORMAL, "\n--- Tag Signature");
+ PrintAndLogEx(NORMAL, "IC signature public key name : NXP NTAG21x (2013)");
+ PrintAndLogEx(NORMAL, "IC signature public key value : %s", sprint_hex(public_ecda_key, PUBLIC_ECDA_KEYLEN));
+ PrintAndLogEx(NORMAL, " Elliptic curve parameters : secp128r1");
+ PrintAndLogEx(NORMAL, " Tag ECC Signature : %s", sprint_hex(data, len));
+ //to do: verify if signature is valid
+ //PrintAndLogEx(NORMAL, "IC signature status: %s valid", (iseccvalid() )?"":"not");
+ return 0;
+}
+
+
+static int ulev1_print_version(uint8_t *data){
+ PrintAndLogEx(NORMAL, "\n--- Tag Version");
+ PrintAndLogEx(NORMAL, " Raw bytes : %s", sprint_hex(data, 8) );
+ PrintAndLogEx(NORMAL, " Vendor ID : %02X, %s", data[1], getManufacturerName(data[1]));
+ PrintAndLogEx(NORMAL, " Product type : %s", getProductTypeStr(data[2]));
+ PrintAndLogEx(NORMAL, " Product subtype : %02X, %s", data[3], (data[3]==1) ?"17 pF":"50pF");
+ PrintAndLogEx(NORMAL, " Major version : %02X", data[4]);
+ PrintAndLogEx(NORMAL, " Minor version : %02X", data[5]);
+ PrintAndLogEx(NORMAL, " Size : %s", getUlev1CardSizeStr(data[6]));
+ PrintAndLogEx(NORMAL, " Protocol type : %02X", data[7]);
+ return 0;
+}
+
+
+static int ul_magic_test(void) {
+ // try a compatibility write to page0, and see if tag answers with ACK/NACK to the first part of the command
+ iso14a_card_select_t card;
+ if (!ul_select(&card, false))
+ return UL_ERROR;
+ int status = ul_comp_write_ex(0, NULL, 0, true);
+ if (status == 0) {
+ return MAGIC;
+ }
+ return 0;
+}
+
+
+uint32_t GetHF14AMfU_Type(void){
+
+ TagTypeUL_t tagtype = UNKNOWN;
+ iso14a_card_select_t card;
+ uint8_t version[10] = {0x00};
+ int len;
+
+ if (!ul_select(&card, true)) {
+ DropField();
+ msleep(200);
+ return UL_ERROR;
+ }
+
+ // Check for Ultralight Family
+ if (card.uidlen != 7 || (card.sak & 0x38) != 0x00) {
+ DropField();
+ PrintAndLogEx(NORMAL, "Tag is not Ultralight | NTAG | MY-D [ATQA: %02X %02X SAK: %02X]\n", card.atqa[1], card.atqa[0], card.sak);
+ return UL_ERROR;
+ }
+
+ if (card.uid[0] != 0x05) {
+ len = ulev1_getVersion(version, sizeof(version));
+ if (len == 10) {
+ 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[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[3] == 0x02 && version[6] == 0x11)
+ 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;
+ }
+
+ // UL vs UL-C vs ntag203 test
+ if (tagtype == UNKNOWN) {
+ ul_halt();
+ if (!ul_select(&card, false)) {
+ DropField();
+ msleep(200);
+ return UL_ERROR;
+ }
+
+ // do UL_C check first...
+ uint8_t nonce[11] = {0x00};
+ len = ulc_requestAuthentication(nonce, sizeof(nonce));
+ ul_halt();
+ if (len == 11) {
+ tagtype = UL_C;