diff --git a/client/src/cmdhflist.c b/client/src/cmdhflist.c index 5534a52ec..2265a3a08 100644 --- a/client/src/cmdhflist.c +++ b/client/src/cmdhflist.c @@ -943,43 +943,83 @@ void annotateIso7816(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize, bool } } +static bool iso14443_4_get_i_block_inf(uint8_t *cmd, uint8_t cmdsize, bool is_response, const uint8_t **inf, size_t *inf_len) { + (void)is_response; + size_t frame_len = cmdsize; + if (frame_len < 1 || (cmd[0] & 0xC0) != 0x00 || (cmd[0] & 0x02) != 0x02) { + return false; + } + + size_t pos = 1; + if ((cmd[0] & 0x08) == 0x08) { + pos++; + } + if ((cmd[0] & 0x04) == 0x04) { + pos++; + } + if (pos >= frame_len) { + return false; + } + + *inf = cmd + pos; + if (inf_len != NULL) { + *inf_len = frame_len - pos; + } + return true; +} + +static bool annotateIso14443_s_r_block(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize, bool is_response, bool show_block_number) { + (void)is_response; + size_t frame_len = cmdsize; + if (frame_len < 1 || frame_len > 4) { + return false; + } + + if ((cmd[0] & 0xC0) == 0xC0) { + switch (cmd[0] & 0x30) { + case 0x00: + snprintf(exp, size, "S-block DESELECT"); + break; + case 0x30: + snprintf(exp, size, "S-block WTX"); + break; + default: + snprintf(exp, size, "S-block"); + break; + } + return true; + } + + if ((cmd[0] & 0xD0) == 0x80) { + if (show_block_number) { + snprintf(exp, size, (cmd[0] & 0x10) ? "R-block NACK(%d)" : "R-block ACK(%d)", cmd[0] & 0x01); + } else { + snprintf(exp, size, (cmd[0] & 0x10) ? "R-block NACK" : "R-block ACK"); + } + return true; + } + + return false; +} + // MIFARE DESFire void annotateMfDesfire(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize) { // it's basically a ISO14443a tag, so try annotation from there if (applyIso14443a(exp, size, cmd, cmdsize, false) != PM3_SUCCESS) { - // S-block 11xxx010 - if ((cmd[0] & 0xC0) && (cmdsize == 3)) { - switch ((cmd[0] & 0x30)) { - case 0x00: - snprintf(exp, size, "S-block DESELECT"); - break; - case 0x30: - snprintf(exp, size, "S-block WTX"); - break; - default: - snprintf(exp, size, "S-block"); - break; - } - } - // R-block (ack) 101xx01x - else if (((cmd[0] & 0xB0) == 0xA0) && (cmdsize > 2)) { - if ((cmd[0] & 0x10) == 0) - snprintf(exp, size, "R-block ACK(%d)", (cmd[0] & 0x01)); - else - snprintf(exp, size, "R-block NACK(%d)", (cmd[0] & 0x01)); + if (annotateIso14443_s_r_block(exp, size, cmd, cmdsize, false, true)) { + return; } // I-block 000xCN1x else if (((cmd[0] & 0xC0) == 0x00) && (cmdsize > 2)) { - // PCB [CID] [NAD] [INF] CRC CRC - int pos = 1; - if ((cmd[0] & 0x08) == 0x08) // cid byte following - pos++; + const uint8_t *inf = NULL; + if (iso14443_4_get_i_block_inf(cmd, cmdsize, false, &inf, NULL) == false) { + return; + } - if ((cmd[0] & 0x04) == 0x04) // nad byte following - pos++; + int pos = inf - cmd; for (uint8_t i = 0; i < 2; i++, pos++) { bool found_annotation = true; @@ -1370,13 +1410,12 @@ void annotateMfPlus(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize) { // ok this part is copy paste from annotateMfDesfire, it seems to work for MIFARE Plus also if (((cmd[0] & 0xC0) == 0x00) && (cmdsize > 2)) { - // PCB [CID] [NAD] [INF] CRC CRC - int pos = 1; - if ((cmd[0] & 0x08) == 0x08) // cid byte following - pos++; + const uint8_t *inf = NULL; + if (iso14443_4_get_i_block_inf(cmd, cmdsize, false, &inf, NULL) == false) { + return; + } - if ((cmd[0] & 0x04) == 0x04) // nad byte following - pos++; + int pos = inf - cmd; for (uint8_t i = 0; i < 2; i++, pos++) { bool found_annotation = true;