+ // base4 conversion and left shift twice
+ i = 3;
+ uint8_t base4[] = {0,0,0,0};
+ while( chksum !=0 ){
+ base4[i--] = (chksum % 4 << 2);
+ chksum /= 4;
+ }
+
+ // merge scambled and chksum parts
+ uint32_t encvalue =
+ ( NIBBLE_LOW ( base4[0]) << 28 ) |
+ ( NIBBLE_HIGH( temp[0]) << 24 ) |
+
+ ( NIBBLE_LOW ( base4[1]) << 20 ) |
+ ( NIBBLE_LOW ( temp[0]) << 16 ) |
+
+ ( NIBBLE_LOW ( base4[2]) << 12 ) |
+ ( NIBBLE_HIGH( temp[1]) << 8 ) |
+
+ ( NIBBLE_LOW ( base4[3]) << 4 ) |
+ NIBBLE_LOW ( temp[1] );
+
+ PrintAndLog("ICE encoded | %08X -> %08X", value, encvalue);
+ return encvalue;
+}
+uint32_t srix4kDecode(uint32_t value) {
+ switch(value) {
+ case 0xC04F42C5: return 0x003139;
+ case 0xC1484807: return 0x002943;
+ case 0xC0C60848: return 0x001A20;
+ }
+ return 0;
+}
+uint32_t srix4kDecodeCounter(uint32_t num) {
+ uint32_t value = ~num;
+ ++value;
+ return value;
+}
+
+uint32_t srix4kGetMagicbytes( uint64_t uid, uint32_t block6, uint32_t block18, uint32_t block19 ){
+#define MASK 0xFFFFFFFF;
+ uint32_t uid32 = uid & MASK;
+ uint32_t counter = srix4kDecodeCounter(block6);
+ uint32_t decodedBlock18 = srix4kDecode(block18);
+ uint32_t decodedBlock19 = srix4kDecode(block19);
+ uint32_t doubleBlock = (decodedBlock18 << 16 | decodedBlock19) + 1;
+
+ uint32_t result = (uid32 * doubleBlock * counter) & MASK;
+ PrintAndLog("Magic bytes | %08X", result);
+ return result;
+}
+int srix4kValid(const char *Cmd){
+
+ uint64_t uid = 0xD00202501A4532F9;
+ uint32_t block6 = 0xFFFFFFFF;
+ uint32_t block18 = 0xC04F42C5;
+ uint32_t block19 = 0xC1484807;
+ uint32_t block21 = 0xD1BCABA4;
+
+ uint32_t test_b18 = 0x00313918;
+ uint32_t test_b18_enc = srix4kEncode(test_b18);
+ //uint32_t test_b18_dec = srix4kDecode(test_b18_enc);
+ PrintAndLog("ENCODE & CHECKSUM | %08X -> %08X (%s)", test_b18, test_b18_enc , "");
+
+ uint32_t magic = srix4kGetMagicbytes(uid, block6, block18, block19);
+ PrintAndLog("BLOCK 21 | %08X -> %08X (no XOR)", block21, magic ^ block21);
+ return 0;
+}
+
+bool waitCmd(bool verbose) {
+
+ bool crc = FALSE;
+ uint8_t b1 = 0, b2 = 0;
+ uint8_t data[USB_CMD_DATA_SIZE] = {0x00};
+ uint8_t status = 0;
+ uint16_t len = 0;
+ UsbCommand resp;
+
+ if (WaitForResponseTimeout(CMD_ACK, &resp, TIMEOUT)) {
+
+ status = (resp.arg[0] & 0xFF);
+ if ( status > 0 ) return FALSE;
+
+ len = (resp.arg[1] & 0xFFFF);
+
+ memcpy(data, resp.d.asBytes, len);
+
+ if (verbose) {
+ if ( len >= 3 ) {
+ ComputeCrc14443(CRC_14443_B, data, len-2, &b1, &b2);
+ crc = ( data[len-2] == b1 && data[len-1] == b2);
+
+ PrintAndLog("[LEN %u] %s[%02X %02X] %s",
+ len,
+ sprint_hex(data, len-2),
+ data[len-2],
+ data[len-1],
+ (crc) ? "OK" : "FAIL"
+ );
+ } else {
+ PrintAndLog("[LEN %u] %s", len, sprint_hex(data, len) );
+ }
+ }
+ return TRUE;
+ } else {
+ PrintAndLog("timeout while waiting for reply.");
+ return FALSE;
+ }
+}
+
+static command_t CommandTable[] = {
+ {"help", CmdHelp, 1, "This help"},
+ {"info", CmdHF14Binfo, 0, "Find and print details about a 14443B tag"},
+ {"list", CmdHF14BList, 0, "[Deprecated] List ISO 14443B history"},