diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 2dff491ee..9ceb02310 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -6325,9 +6325,44 @@ static int CmdHF14ADesReadData(const char *Cmd) { } } + // length of record for record file + size_t reclen = 0; + // get file settings if (op == RFTAuto) { - + FileSettingsS fsettings; + res = DesfireGetFileSettingsStruct(&dctx, fnum, &fsettings); + if (res == PM3_SUCCESS) { + switch(fsettings.fileType) { + case 0x00: + case 0x01: { + op = RFTData; + break; + } + case 0x02: { + op = RFTValue; + break; + } + case 0x03: + case 0x04: { + op = RFTRecord; + reclen = fsettings.recordSize; + break; + } + case 0x05: { + op = RFTMAC; + break; + } + default: { + break; + } + } + if (verbose) + PrintAndLogEx(INFO, "Got file type: %s. Option: %s", GetDesfireFileType(fsettings.fileType), CLIGetOptionListStr(DesfireReadFileTypeOpts, op)); + + } else { + PrintAndLogEx(WARNING, "GetFileSettings error. Can't get file type."); + } } PrintAndLogEx(INFO, "-------------- " _CYAN_("File data") " --------------"); @@ -6363,14 +6398,16 @@ static int CmdHF14ADesReadData(const char *Cmd) { } if (op == RFTRecord) { - res = DesfireReadRecords(&dctx, fnum, offset, 1, resp, &resplen); - if (res != PM3_SUCCESS) { - PrintAndLogEx(ERR, "Desfire ReadRecords (len=1) command " _RED_("error") ". Result: %d", res); - DropField(); - return PM3_ESOFT; + if (reclen == 0) { + res = DesfireReadRecords(&dctx, fnum, offset, 1, resp, &resplen); + if (res != PM3_SUCCESS) { + PrintAndLogEx(ERR, "Desfire ReadRecords (len=1) command " _RED_("error") ". Result: %d", res); + DropField(); + return PM3_ESOFT; + } + reclen = resplen; } - size_t reclen = resplen; if (verbose) PrintAndLogEx(INFO, "Record length %zu", reclen); diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index a76921a6a..a0b893e4c 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -1067,6 +1067,16 @@ int DesfireGetFileSettings(DesfireContext *dctx, uint8_t fileid, uint8_t *resp, return DesfireCommand(dctx, MFDES_GET_FILE_SETTINGS, &fileid, 1, resp, resplen, -1); } +int DesfireGetFileSettingsStruct(DesfireContext *dctx, uint8_t fileid, FileSettingsS *fsettings) { + uint8_t resp[250] = {0}; + size_t resplen = 0; + int res = DesfireGetFileSettings(dctx, fileid, resp, &resplen); + if (res == PM3_SUCCESS && resplen > 0 && fsettings != NULL) + DesfireFillFileSettings(resp, resplen, fsettings); + + return res; +} + int DesfireCreateFile(DesfireContext *dctx, uint8_t ftype, uint8_t *fdata, size_t fdatalen, bool checklen) { const DesfireCreateFileCommandsS *rcmd = GetDesfireFileCmdRec(ftype); if (rcmd == NULL) @@ -1355,6 +1365,66 @@ void DesfirePrintAccessRight(uint8_t *data) { PrintAndLogEx(SUCCESS, "change : %s", GetDesfireAccessRightStr(ch)); } +void DesfireFillFileSettings(uint8_t *data, size_t datalen, FileSettingsS *fsettings) { + if (fsettings == NULL) + return; + + memset(fsettings, 0, sizeof(FileSettingsS)); + + if (datalen < 4) + return; + + fsettings->fileType = data[0]; + fsettings->fileOption = data[1]; + fsettings->fileCommMode = data[1] & 0x03; + fsettings->additionalAccessRightsEn = ((data[1] & 0x80) != 0); + fsettings->rawAccessRights = MemLeToUint2byte(&data[2]); + DesfireDecodeFileAcessMode(&data[2], &fsettings->rAccess, &fsettings->wAccess, &fsettings->rwAccess, &fsettings->chAccess); + + int reclen = 0; + switch (fsettings->fileType) { + case 0x00: + case 0x01: { + fsettings->fileSize = MemLeToUint3byte(&data[0]); + reclen = 4 + 3; + break; + } + case 0x02: { + fsettings->lowerLimit = MemLeToUint4byte(&data[0]); + fsettings->upperLimit = MemLeToUint4byte(&data[4]); + fsettings->value = MemLeToUint4byte(&data[8]); + fsettings->limitedCredit = data[12]; + reclen = 4 + 13; + break; + } + case 0x03: + case 0x04: { + fsettings->recordSize = MemLeToUint3byte(&data[0]); + fsettings->maxRecordCount = MemLeToUint3byte(&data[3]); + fsettings->curRecordCount = MemLeToUint3byte(&data[6]); + reclen = 4 + 9; + break; + } + case 0x05: { + fsettings->keyType = data[0]; + fsettings->keyVersion = data[1]; + break; + } + default: { + break; + } + } + + if (fsettings->additionalAccessRightsEn && reclen > 0 && datalen > reclen && datalen == reclen + data[reclen] * 2) { + fsettings->additionalAccessRightsLength = data[reclen]; + + for (int i = 0; i < fsettings->additionalAccessRightsLength; i++) { + fsettings->additionalAccessRights[i] = MemLeToUint2byte(&data[reclen + 1 + i * 2]); + } + } +} + + static void DesfirePrintFileSettDynPart(uint8_t filetype, uint8_t *data, size_t datalen, uint8_t *dynlen, bool create) { switch (filetype) { case 0x00: @@ -1507,7 +1577,6 @@ void DesfirePrintCreateFileSettings(uint8_t filetype, uint8_t *data, size_t len) xlen += reclen; } - int DesfireChangeKey(DesfireContext *dctx, bool change_master_key, uint8_t newkeynum, DesfireCryptoAlgorythm newkeytype, uint32_t newkeyver, uint8_t *newkey, DesfireCryptoAlgorythm oldkeytype, uint8_t *oldkey, bool verbose) { uint8_t okeybuf[DESFIRE_MAX_KEY_SIZE] = {0}; diff --git a/client/src/mifare/desfirecore.h b/client/src/mifare/desfirecore.h index 55abfe5e8..8ff954807 100644 --- a/client/src/mifare/desfirecore.h +++ b/client/src/mifare/desfirecore.h @@ -28,6 +28,43 @@ typedef struct { const bool mayHaveISOfid; } DesfireCreateFileCommandsS; +typedef struct { + // all + uint8_t fileType; + uint8_t fileOption; + uint8_t fileCommMode; + bool additionalAccessRightsEn; + uint16_t rawAccessRights; + uint8_t rAccess; + uint8_t wAccess; + uint8_t rwAccess; + uint8_t chAccess; + + // data + uint32_t fileSize; + + //value + uint32_t lowerLimit; + uint32_t upperLimit; + uint32_t value; + uint8_t limitedCredit; + + // record + uint32_t recordSize; + uint32_t maxRecordCount; + uint32_t curRecordCount; + + //mac + uint8_t keyType; + uint8_t key[16]; + uint8_t keyVersion; + + // additional rights + uint8_t additionalAccessRightsLength; + uint16_t additionalAccessRights[16]; + +} FileSettingsS; + typedef enum { RFTAuto, RFTData, @@ -84,7 +121,9 @@ int DesfireSetConfiguration(DesfireContext *dctx, uint8_t paramid, uint8_t *para int DesfireGetFileIDList(DesfireContext *dctx, uint8_t *resp, size_t *resplen); int DesfireGetFileISOIDList(DesfireContext *dctx, uint8_t *resp, size_t *resplen); +void DesfireFillFileSettings(uint8_t *data, size_t datalen, FileSettingsS *fsettings); int DesfireGetFileSettings(DesfireContext *dctx, uint8_t fileid, uint8_t *resp, size_t *resplen); +int DesfireGetFileSettingsStruct(DesfireContext *dctx, uint8_t fileid, FileSettingsS *fsettings); int DesfireChangeFileSettings(DesfireContext *dctx, uint8_t *data, size_t datalen); const DesfireCreateFileCommandsS *GetDesfireFileCmdRec(uint8_t type);