123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335 |
- //
- // Created by robin on 7/22/16.
- //
-
- #include "libnfc_cpptools/FreeFareTag.h"
- #include "libnfc_cpptools/StringUtils.h"
- #include "FreeFareTagInternal.h"
-
- namespace LibNfc
- {
- namespace FreeFare
- {
-
- std::string FreeFareTag::getTagTypeString(FreeFareTag::FreeFareTagType type)
- {
- if (type == FreeFareTagType::FELICA)
- {
- return "FELICA";
- }
- if (type == FreeFareTagType::MIFARE_MINI)
- {
- return "MIFARE_MINI";
- }
- if (type == FreeFareTagType::MIFARE_CLASSIC_1K)
- {
- return "MIFARE_CLASSIC_1K";
- }
- if (type == FreeFareTagType::MIFARE_CLASSIC_4K)
- {
- return "MIFARE_CLASSIC_4K";
- }
- if (type == FreeFareTagType::MIFARE_DESFIRE)
- {
- return "MIFARE_DESFIRE";
- }
- if (type == FreeFareTagType::MIFARE_ULTRALIGHT)
- {
- return "MIFARE_ULTRALIGHT";
- }
- if (type == FreeFareTagType::MIFARE_ULTRALIGHT_C)
- {
- return "MIFARE_ULTRALIGHT_C";
- }
- return "UNKNOWN";
- }
-
- FreeFareTag::FreeFareTag(std::shared_ptr<FreeFareTagInternal> tag)
- : _tag(tag)
- {
- }
-
- LibNfc::Utils::ResultBool FreeFareTag::authenticate(int sector, std::string key, int keyType)
- {
- return _tag->authenticate(sector, key, keyType);
- }
-
- LibNfc::Utils::Result<MappedKeys> FreeFareTag::mapKeys(std::vector<std::string> keys, std::function<void(int, int)> cb)
- {
- MappedKeys mappedKeys;
- int done = 0;
- int total = 16 * keys.size();
-
- for (int i = 0; i < 16; ++i) {
- std::pair<std::string, std::string> 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(++done, total);
- }
- if (!blockKeys.first.empty() && !blockKeys.second.empty()) {
- break;
- }
- }
- mappedKeys.push_back(blockKeys);
- }
- if (cb != 0 && done < total) {
- cb(total, total);
- }
-
- return LibNfc::Utils::Result<MappedKeys>::ok(mappedKeys);
- }
-
- LibNfc::Utils::ResultString FreeFareTag::readBlock(int sector, int block, std::string key, int keyType)
- {
- return _tag->readBlock(sector, block, key, keyType);
- }
-
- LibNfc::Utils::Result<FreeFareSector> FreeFareTag::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 LibNfc::Utils::Result<FreeFareSector>::error(data);
- }
- }
- return LibNfc::Utils::Result<FreeFareSector>::ok(FreeFareSector(res));
- }
-
- LibNfc::Utils::Result<std::vector<FreeFareSector>> FreeFareTag::read(MappedKeys keys, std::function<void(int, int)> cb)
- {
- if (keys.size() != 16) {
- return LibNfc::Utils::Result<std::vector<FreeFareSector>>::error("Must have 16 sectors keys");
- }
- int done = 0;
- int total = 4 * keys.size();
- std::vector<FreeFareSector> sectors;
- for (int s = 0; s < keys.size(); ++s) {
- auto sectorKey = keys[s];
- FreeFareSector 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(++done, total);
- }
- }
- 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(++done, total);
- }
-
- sector.setBlock(b, dataA);
- FreeFareAccessBits accessBitsDboA = sector.getAccessBitsDbo();
- sector.setBlock(b, dataB);
- FreeFareAccessBits 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);
- }
- if (cb != 0 && done < total) {
- cb(total, total);
- }
-
- return LibNfc::Utils::Result<std::vector<FreeFareSector>>::ok(sectors);
- }
-
- LibNfc::Utils::Result<std::vector<FreeFareSector>> FreeFareTag::read(std::vector<std::string> keys, std::function<void(int, int)> mapCb,
- std::function<void(int, int)> readCb)
- {
- auto mappedKeysResult = mapKeys(keys, mapCb);
- if (!mappedKeysResult) {
- return LibNfc::Utils::Result<std::vector<FreeFareSector>>::error(mappedKeysResult);
- }
- return read(mappedKeysResult.getData(), readCb);
- }
-
- LibNfc::Utils::ResultBool FreeFareTag::writeBlock(int sector, int block, std::string key, int keyType, const std::string &data)
- {
- return _tag->writeBlock(sector, block, key, keyType, LibNfc::Utils::StringUtils::ensureSize(data, 16));
- }
-
- LibNfc::Utils::ResultBool FreeFareTag::writeSector(int sector, std::string key, int keyType, const std::string &data)
- {
- std::string d = LibNfc::Utils::StringUtils::ensureSize(data, 64);
- std::string errors;
- for (int b = 0; b < 4; ++b) {
- auto result = writeBlock(sector, b, key, keyType, d.substr(b * 16, 16));
- if (!result) {
- errors += std::string(errors.empty() ? "" : "\n") + "Failed to write sector " + std::to_string(sector) +
- " block " + std::to_string(b) + " with key " + (keyType == MFC_KEY_A ? "A" : "B") + ": " + result.getError();
- }
- }
- if (errors.empty()) {
- return LibNfc::Utils::ResultBool::ok(true);
- }
- return LibNfc::Utils::ResultBool::error(errors);
- }
-
- LibNfc::Utils::ResultBool FreeFareTag::write(MappedKeys keys, const std::string &data, bool writeSector0, std::function<void(int, int)> cb)
- {
- if (keys.size() != 16) {
- return LibNfc::Utils::ResultBool::error("Must have 16 sectors keys");
- }
- std::string d = LibNfc::Utils::StringUtils::ensureSize(data, 1024);
- std::string errors;
- int done = 0;
- int total = 4 * keys.size();
- for (int s = 0; s < keys.size(); ++s) {
- auto sectorKey = keys[s];
- for (int b = 0; b < 4; ++b) {
- if (s == 0 && b == 0 && !writeSector0) {
- continue;
- }
- std::string blockData = d.substr((s * 64) + (b * 16), 16);
- if (cb != 0 && done < total) {
- bool keyA = false;
- bool keyB = false;
- std::string sectorErrors;
- if (!sectorKey.first.empty()) {
- auto resultA = writeBlock(s, b, sectorKey.first, MFC_KEY_A, blockData);
- if (resultA) {
- keyA = true;
- }
- else {
- sectorErrors = "Failed to write sector " + std::to_string(s) +
- " block " + std::to_string(b) + " with key A: " + resultA.getError();
- }
- }
- if (!keyA && !sectorKey.second.empty()) {
- auto resultB = writeBlock(s, b, sectorKey.first, MFC_KEY_A, blockData);
- if (resultB) {
- keyB = true;
- }
- else {
- sectorErrors = std::string(sectorErrors.empty() ? "" : "\n") + "Failed to write sector " + std::to_string(s) +
- " block " + std::to_string(b) + " with key B: " + resultB.getError();
- }
- }
- if (!keyA && !keyB) {
- errors += std::string(errors.empty() ? "" : "\n") + sectorErrors;
- }
- cb(++done, total);
- }
- }
- }
- if (cb != 0 && done < total) {
- cb(total, total);
- }
- if (errors.empty()) {
- return LibNfc::Utils::ResultBool::ok(true);
- }
- return LibNfc::Utils::ResultBool::error(errors);
- }
-
- LibNfc::Utils::ResultBool FreeFareTag::write(std::vector<std::string> keys, const std::string &data, bool writeSector0,
- std::function<void(int, int)> mapCb, std::function<void(int, int)> writeCb)
- {
- auto mappedKeysResult = mapKeys(keys, mapCb);
- if (!mappedKeysResult) {
- return LibNfc::Utils::ResultBool::error(mappedKeysResult);
- }
- return write(mappedKeysResult.getData(), data, writeSector0, writeCb);
- }
-
- const std::string &FreeFareTag::getUid() const
- {
- return _tag->getUid();
- }
-
- FreeFareTag::FreeFareTagType FreeFareTag::getType() const
- {
- auto type = _tag->getType();
- if (type == freefare_tag_type::FELICA)
- {
- return FreeFareTagType::FELICA;
- }
- if (type == freefare_tag_type::MIFARE_MINI)
- {
- return FreeFareTagType::MIFARE_MINI;
- }
- if (type == freefare_tag_type::MIFARE_CLASSIC_1K)
- {
- return FreeFareTagType::MIFARE_CLASSIC_1K;
- }
- if (type == freefare_tag_type::MIFARE_CLASSIC_4K)
- {
- return FreeFareTagType::MIFARE_CLASSIC_4K;
- }
- if (type == freefare_tag_type::MIFARE_DESFIRE)
- {
- return FreeFareTagType::MIFARE_DESFIRE;
- }
- if (type == freefare_tag_type::MIFARE_ULTRALIGHT)
- {
- return FreeFareTagType::MIFARE_ULTRALIGHT;
- }
- if (type == freefare_tag_type::MIFARE_ULTRALIGHT_C)
- {
- return FreeFareTagType::MIFARE_ULTRALIGHT_C;
- }
- return FreeFareTagType::UNKNOWN;
- }
-
- std::shared_ptr<FreeFareTagInternal> FreeFareTag::getTag() const
- {
- return _tag;
- }
-
- }; // FreeFare
- }; // LibNfc
|