// // Created by robin on 7/22/16. // #include "FreeFareTagBusiness.h" FreeFareTagBusiness::FreeFareTagBusiness(std::shared_ptr tag) : _tag(tag) { } ResultBool FreeFareTagBusiness::authenticate(int sector, std::string key, int keyType) { return _tag->authenticate(sector, key, keyType); } ResultString FreeFareTagBusiness::readBlock(int sector, int block, std::string key, int keyType) { return _tag->readBlock(sector, block, key, keyType); } Result FreeFareTagBusiness::readSector(int sector, std::string key, int keyType) { std::string res; int lastBlock = _tag->getSectorBlockCount(sector); for (int i = 0; i < lastBlock; ++i) { auto data = readBlock(sector, i, key, keyType); if (data) { res += data.getData(); } else { return Result::error(data); } } return Result::ok(SectorDbo(res)); } const std::string &FreeFareTagBusiness::getUid() const { return _tag->getUid(); } freefare_tag_type FreeFareTagBusiness::getType() const { return _tag->getType(); } std::shared_ptr FreeFareTagBusiness::getTag() const { return _tag; } Result FreeFareTagBusiness::mapKeys(std::vector keys, std::function cb) { MappedKeys mappedKeys; for (int i = 0; i < 16; ++i) { std::pair blockKeys; for (int k = 0; k < keys.size(); ++k) { auto key = keys[k]; if (authenticate(i, key, MFC_KEY_A)) { blockKeys.first = key; } if (authenticate(i, key, MFC_KEY_B)) { blockKeys.second = key; } if (cb != 0) { cb((i * keys.size()) + k + 1, 16 * keys.size()); } if (!blockKeys.first.empty() && !blockKeys.second.empty()) { break; } } mappedKeys.push_back(blockKeys); } if (cb != 0) { cb(16 * keys.size(), 16 * keys.size()); } return Result::ok(mappedKeys); } Result> FreeFareTagBusiness::dump(MappedKeys keys, std::function cb) { if (keys.size() != 16) { return Result>::error("Must have 16 sectors"); } std::vector sectors; for (int s = 0; s < keys.size(); ++s) { auto sectorKey = keys[s]; SectorDbo sector; bool keyA = false; bool keyB = false; for (int b = 0; b < 3; ++b) { std::string data = ""; if (!sectorKey.first.empty()) { auto blockResult = readBlock(s, b, sectorKey.first, MFC_KEY_A); if (blockResult) { data = blockResult.getData(); keyA = true; } } if (!sectorKey.second.empty()) { auto blockResult = readBlock(s, b, sectorKey.second, MFC_KEY_B); if (blockResult) { if (data.empty()) { data = blockResult.getData(); } keyB = true; } } sector.setBlock(b, data); if (cb != 0) { cb((s * 4) + b + 1, keys.size() * 4); } } int b = 3; std::string dataA = ""; std::string dataB = ""; if (!sectorKey.first.empty()) { auto blockResult = readBlock(s, b, sectorKey.first, MFC_KEY_A); if (blockResult) { dataA = blockResult.getData(); keyA = true; } } if (!sectorKey.second.empty()) { auto blockResult = readBlock(s, b, sectorKey.second, MFC_KEY_B); if (blockResult) { dataB = blockResult.getData(); keyB = true; } } if (cb != 0) { cb((s * 4) + b + 1, keys.size() * 4); } sector.setBlock(b, dataA); AccessBitsDbo accessBitsDboA = sector.getAccessBitsDbo(); sector.setBlock(b, dataB); AccessBitsDbo accessBitsDboB = sector.getAccessBitsDbo(); sector.setKeyA(keyA ? sectorKey.first : ""); sector.setKeyB(keyB ? sectorKey.second : ""); std::string accessBits; if (keyA && accessBitsDboA.canKeyAReadAccessBitsTrailer()) { accessBits = accessBitsDboA.getBits(); } else if (keyB && accessBitsDboB.canKeyBReadAccessBitsTrailer()) { accessBits = accessBitsDboB.getBits(); } sector.setAccessBits(accessBits); sectors.push_back(sector); } return Result>::ok(sectors); } Result> FreeFareTagBusiness::dump(std::vector keys, std::function mapCb, std::function dumpCb) { auto mappedKeysResult = mapKeys(keys, mapCb); if (!mappedKeysResult) { return Result>::error(mappedKeysResult); } return dump(mappedKeysResult.getData(), dumpCb); }