diff --git a/client/src/fileutils.c b/client/src/fileutils.c index 14b596c6d..9da6dc923 100644 --- a/client/src/fileutils.c +++ b/client/src/fileutils.c @@ -288,7 +288,7 @@ int saveFileJSONex(const char *preferredName, JSONFileType ftype, uint8_t *data, break; } case jsfMfc_v2: { - iso14a_mf_extdump_t *xdump = (iso14a_mf_extdump_t *)(void *) data; + iso14a_mf_extdump_t *xdump = (iso14a_mf_extdump_t *)data; JsonSaveStr(root, "FileType", "mfc v2"); JsonSaveBufAsHexCompact(root, "$.Card.UID", xdump->card_info.uid, xdump->card_info.uidlen); JsonSaveBufAsHexCompact(root, "$.Card.ATQA", xdump->card_info.atqa, 2); @@ -326,6 +326,48 @@ int saveFileJSONex(const char *preferredName, JSONFileType ftype, uint8_t *data, } break; } + case jsfMfc_v3: { + iso14a_mf_dump_ev1_t *xdump = (iso14a_mf_dump_ev1_t *)data; + JsonSaveStr(root, "FileType", "mfc v3"); + JsonSaveBufAsHexCompact(root, "$.Card.UID", xdump->card.ev1.uid, xdump->card.ev1.uidlen); + JsonSaveBufAsHexCompact(root, "$.Card.ATQA", xdump->card.ev1.atqa, 2); + JsonSaveBufAsHexCompact(root, "$.Card.SAK", &(xdump->card.ev1.sak), 1); + JsonSaveBufAsHexCompact(root, "$.Card.ATS", xdump->card.ev1.ats, sizeof(xdump->card.ev1.ats_len)); + JsonSaveBufAsHexCompact(root, "$.Card.SIGNATURE", xdump->card.ev1.signature, sizeof(xdump->card.ev1.signature)); + + for (size_t i = 0; i < (xdump->dumplen / MFBLOCK_SIZE); i++) { + + snprintf(path, sizeof(path), "$.blocks.%zu", i); + JsonSaveBufAsHexCompact(root, path, &xdump->dump[i * MFBLOCK_SIZE], MFBLOCK_SIZE); + if (mfIsSectorTrailer(i)) { + snprintf(path, sizeof(path), "$.SectorKeys.%d.KeyA", mfSectorNum(i)); + JsonSaveBufAsHexCompact(root, path, &xdump->dump[i * MFBLOCK_SIZE], 6); + + snprintf(path, sizeof(path), "$.SectorKeys.%d.KeyB", mfSectorNum(i)); + JsonSaveBufAsHexCompact(root, path, &xdump->dump[i * MFBLOCK_SIZE + 10], 6); + + uint8_t *adata = &xdump->dump[i * MFBLOCK_SIZE + 6]; + snprintf(path, sizeof(path), "$.SectorKeys.%d.AccessConditions", mfSectorNum(i)); + JsonSaveBufAsHexCompact(root, path, &xdump->dump[i * MFBLOCK_SIZE + 6], 4); + + snprintf(path, sizeof(path), "$.SectorKeys.%d.AccessConditionsText.block%zu", mfSectorNum(i), i - 3); + JsonSaveStr(root, path, mfGetAccessConditionsDesc(0, adata)); + + snprintf(path, sizeof(path), "$.SectorKeys.%d.AccessConditionsText.block%zu", mfSectorNum(i), i - 2); + JsonSaveStr(root, path, mfGetAccessConditionsDesc(1, adata)); + + snprintf(path, sizeof(path), "$.SectorKeys.%d.AccessConditionsText.block%zu", mfSectorNum(i), i - 1); + JsonSaveStr(root, path, mfGetAccessConditionsDesc(2, adata)); + + snprintf(path, sizeof(path), "$.SectorKeys.%d.AccessConditionsText.block%zu", mfSectorNum(i), i); + JsonSaveStr(root, path, mfGetAccessConditionsDesc(3, adata)); + + snprintf(path, sizeof(path), "$.SectorKeys.%d.AccessConditionsText.UserData", mfSectorNum(i)); + JsonSaveBufAsHexCompact(root, path, &adata[3], 1); + } + } + break; + } case jsfFudan: { iso14a_mf_extdump_t *xdump = (iso14a_mf_extdump_t *)(void *) data; JsonSaveStr(root, "FileType", "fudan"); @@ -1123,6 +1165,38 @@ int loadFileJSONex(const char *preferredName, void *data, size_t maxdatalen, siz goto out; } + if (!strcmp(ctype, "mfc v3")) { + + JsonLoadBufAsHex(root, "$.Card.UID", udata.mfc_ev1->card.ev1.uid, udata.mfc_ev1->card.ev1.uidlen, datalen); + JsonLoadBufAsHex(root, "$.Card.ATQA", udata.mfc_ev1->card.ev1.atqa, 2, datalen); + JsonLoadBufAsHex(root, "$.Card.SAK", &(udata.mfc_ev1->card.ev1.sak), 1, datalen); + JsonLoadBufAsHex(root, "$.Card.ATS", udata.mfc_ev1->card.ev1.ats, sizeof(udata.mfc_ev1->card.ev1.ats_len), datalen); + JsonLoadBufAsHex(root, "$.Card.SIGNATURE", udata.mfc_ev1->card.ev1.signature, sizeof(udata.mfc_ev1->card.ev1.signature), datalen); + + *datalen = MFU_DUMP_PREFIX_LENGTH; + + size_t sptr = 0; + for (int i = 0; i < maxdatalen; i++) { + + if (sptr + MFBLOCK_SIZE > maxdatalen) { + retval = PM3_EMALLOC; + goto out; + } + + snprintf(blocks, sizeof(blocks), "$.blocks.%d", i); + uint8_t block[MFBLOCK_SIZE]; + JsonLoadBufAsHex(root, blocks, block, MFBLOCK_SIZE, &len); + if (!len) + break; + + memcpy(&udata.bytes[sptr], block, MFBLOCK_SIZE); + sptr += len; + } + + *datalen = sptr; + goto out; + } + if (!strcmp(ctype, "fudan")) { size_t sptr = 0; for (int i = 0; i < maxdatalen; i++) { diff --git a/client/src/fileutils.h b/client/src/fileutils.h index 88d624788..0552ed5f3 100644 --- a/client/src/fileutils.h +++ b/client/src/fileutils.h @@ -39,12 +39,14 @@ typedef union { mfu_dump_t *mfu; topaz_tag_t *topaz; iso14a_mf_extdump_t *mfc; + iso14a_mf_dump_ev1_t *mfc_ev1; } udata_t; typedef enum { jsfRaw, jsfCardMemory, jsfMfc_v2, + jsfMfc_v3, jsfMfuMemory, jsfHitag, jsfIclass,