void MifareCommands::setSectorToMAD(long aid, unsigned int sector, std::shared_ptr<MifareKey> madKeyA, std::shared_ptr<MifareKey> madKeyB) { MifareAccessInfo::SectorAccessBits sab; if (!madKeyA->isEmpty()) { getMifareChip()->getMifareProfile()->setKey(0, KT_KEY_A, madKeyA); getMifareChip()->getMifareProfile()->setKey(16, KT_KEY_A, madKeyA); } if (madKeyB->isEmpty()) { sab.setTransportConfiguration(); } else { getMifareChip()->getMifareProfile()->setKey(0, KT_KEY_B, madKeyB); getMifareChip()->getMifareProfile()->setKey(16, KT_KEY_B, madKeyB); sab.setAReadBWriteConfiguration(); } if (sector < 16) { if (sector == 0) { THROW_EXCEPTION_WITH_LOG(LibLogicalAccessException, "Can't make reference to the MAD itself."); } std::vector<unsigned char> madbuf = readSector(0, 1, sab); if (!madbuf.size()) { THROW_EXCEPTION_WITH_LOG(LibLogicalAccessException, "Can't read the MAD."); } madbuf[(sector * 2)] = aid & 0xff; madbuf[sector * 2 + 1] = (aid & 0xff00) >> 8; if (madbuf[1] == 0x00) { // BCD Nibble representation madbuf[1] = static_cast<unsigned char>(sector % 10); if (sector >= 10) { madbuf[1] |= 0x10; } } madbuf[0] = calculateMADCrc(&madbuf[0], madbuf.size()); writeSector(0, 1, madbuf, sab); } else { if (sector == 16)
void MifareCommands::setSectorToMAD(long aid, unsigned int sector, boost::shared_ptr<MifareKey> madKeyA, boost::shared_ptr<MifareKey> madKeyB) { MifareAccessInfo::SectorAccessBits sab; if (!madKeyA->isEmpty()) { getMifareChip()->getMifareProfile()->setKey(0, KT_KEY_A, madKeyA); getMifareChip()->getMifareProfile()->setKey(16, KT_KEY_A, madKeyA); } if (madKeyB->isEmpty()) { sab.setTransportConfiguration(); } else { getMifareChip()->getMifareProfile()->setKey(0, KT_KEY_B, madKeyB); getMifareChip()->getMifareProfile()->setKey(16, KT_KEY_B, madKeyB); sab.setAReadBWriteConfiguration(); } if (sector < 16) { if (sector == 0) { THROW_EXCEPTION_WITH_LOG(LibLogicalAccessException, "Can't make reference to the MAD itself."); } unsigned char madbuf[32]; memset(madbuf, 0x00, sizeof(madbuf)); if (readSector(0, 1, madbuf, sizeof(madbuf), sab) != sizeof(madbuf)) { THROW_EXCEPTION_WITH_LOG(LibLogicalAccessException, "Can't read the MAD."); } madbuf[(sector*2)] = aid & 0xff; madbuf[sector*2 + 1] = (aid & 0xff00) >> 8; if (madbuf[1] == 0x00) { madbuf[1] = static_cast<unsigned char>(sector); } madbuf[0] = calculateMADCrc(madbuf, sizeof(madbuf)); if (!writeSector(0, 1, madbuf, sizeof(madbuf), sab)) { THROW_EXCEPTION_WITH_LOG(LibLogicalAccessException, "Can't write the MAD."); } } else { if (sector == 16)
void MifareStorageCardService::writeData(std::shared_ptr<Location> location, std::shared_ptr<AccessInfo> aiToUse, std::shared_ptr<AccessInfo> aiToWrite, const std::vector<unsigned char>& data, CardBehavior behaviorFlags) { EXCEPTION_ASSERT_WITH_LOG(location, std::invalid_argument, "location cannot be null."); std::shared_ptr<MifareLocation> mLocation = std::dynamic_pointer_cast<MifareLocation>(location); std::shared_ptr<MifareAccessInfo> mAiToUse = std::dynamic_pointer_cast<MifareAccessInfo>(aiToUse); EXCEPTION_ASSERT_WITH_LOG(mLocation, std::invalid_argument, "location must be a MifareLocation."); if (aiToUse) { EXCEPTION_ASSERT_WITH_LOG(mAiToUse, std::invalid_argument, "aiToUse must be a MifareAccessInfo."); } else { mAiToUse = std::dynamic_pointer_cast<MifareAccessInfo>(getChip()->getProfile()->createAccessInfo()); } bool writeAidToMad = false; getChip()->getProfile()->clearKeys(); if (mLocation->useMAD) { if (mLocation->sector == 0) { mLocation->sector = getMifareChip()->getMifareCommands()->getSectorFromMAD(mLocation->aid, mAiToUse->madKeyA); } else { writeAidToMad = true; } } size_t totaldatalen = data.size() + (mLocation->block * 16) + mLocation->byte; int nbSectors = 0; size_t totalbuflen = 0; while (totalbuflen < totaldatalen) { totalbuflen += getMifareChip()->getMifareCommands()->getNbBlocks(mLocation->sector + nbSectors) * 16; nbSectors++; // user data on sector trailer ? if (nbSectors == 1 && (totaldatalen - totalbuflen) == 1) { totalbuflen++; } } if (nbSectors >= 1) { size_t buflen = totalbuflen - (mLocation->block * 16); std::vector<unsigned char> dataSectors; dataSectors.resize(buflen, 0x00); std::copy(data.begin(), data.end(), dataSectors.begin() + mLocation->byte); if (writeAidToMad) { for (int i = mLocation->sector; i < (mLocation->sector + nbSectors); ++i) { getMifareChip()->getMifareCommands()->setSectorToMAD(mLocation->aid, i, mAiToUse->madKeyA, mAiToUse->madKeyB); } } for (int i = 0; i < nbSectors; ++i) { if (!mAiToUse->keyA->isEmpty()) { getMifareChip()->getMifareProfile()->setKey(mLocation->sector + i, KT_KEY_A, mAiToUse->keyA); } if (!mAiToUse->keyB->isEmpty()) { getMifareChip()->getMifareProfile()->setKey(mLocation->sector + i, KT_KEY_B, mAiToUse->keyB); } } std::shared_ptr<MifareAccessInfo> mAiToWrite; // Write access informations too if (aiToWrite) { // Sector keys will be changed after writing mAiToWrite = std::dynamic_pointer_cast<MifareAccessInfo>(aiToWrite); EXCEPTION_ASSERT_WITH_LOG(mAiToWrite, std::invalid_argument, "mAiToWrite must be a MifareAccessInfo."); // MAD keys are changed now if (writeAidToMad && mAiToWrite->useMAD) { unsigned int madsector = (mLocation->sector <= 16) ? 0 : 16; MifareAccessInfo::SectorAccessBits sab; getMifareChip()->getMifareProfile()->setKey(madsector, KT_KEY_A, mAiToUse->madKeyA); if (mAiToUse->madKeyB->isEmpty()) { sab.setTransportConfiguration(); } else { sab.setAReadBWriteConfiguration(); getMifareChip()->getMifareProfile()->setKey(madsector, KT_KEY_B, mAiToUse->madKeyB); } MifareAccessInfo::SectorAccessBits newsab; if (mAiToWrite->madKeyB->isEmpty()) { newsab.setTransportConfiguration(); } else { newsab.setAReadBWriteConfiguration(); } if (!mAiToWrite->madKeyA->isEmpty()) { getMifareChip()->getMifareProfile()->setKey(getMifareChip()->getNbSectors(), KT_KEY_A, mAiToWrite->madKeyA); } if (!mAiToWrite->madKeyB->isEmpty()) { getMifareChip()->getMifareProfile()->setKey(getMifareChip()->getNbSectors(), KT_KEY_B, mAiToWrite->madKeyB); } getMifareChip()->getMifareCommands()->changeKey(mAiToWrite->madKeyA, mAiToWrite->madKeyB, madsector, sab, &newsab, mAiToWrite->madGPB); } if (!mAiToWrite->keyA->isEmpty()) { getMifareChip()->getMifareProfile()->setKey(getMifareChip()->getNbSectors(), KT_KEY_A, mAiToWrite->keyA); } if (!mAiToWrite->keyB->isEmpty()) { getMifareChip()->getMifareProfile()->setKey(getMifareChip()->getNbSectors(), KT_KEY_B, mAiToWrite->keyB); } // No key change, set to null (to not change sab, ...) if (mAiToWrite->keyA->isEmpty() && mAiToWrite->keyB->isEmpty()) { mAiToWrite.reset(); } } if (behaviorFlags & CB_AUTOSWITCHAREA) { getMifareChip()->getMifareCommands()->writeSectors(mLocation->sector, mLocation->sector + nbSectors - 1, mLocation->block, dataSectors, mAiToUse->sab, mAiToUse->gpb, (mAiToWrite) ? &(mAiToWrite->sab) : NULL); } else { getMifareChip()->getMifareCommands()->writeSector(mLocation->sector, mLocation->block, dataSectors, mAiToUse->sab, mAiToUse->gpb, (mAiToWrite) ? &(mAiToWrite->sab) : NULL); } getMifareChip()->getMifareProfile()->setKeyUsage(getMifareChip()->getNbSectors(), KT_KEY_A, false); getMifareChip()->getMifareProfile()->setKeyUsage(getMifareChip()->getNbSectors(), KT_KEY_B, false); } }