void MifareSTidSTRCommands::loadKey(boost::shared_ptr<Location> location, boost::shared_ptr<Key> key, MifareKeyType keytype)
	{
		INFO_("Loading key... location {%s} key type {0x%x(%d)}", location->serialize().c_str(), keytype, keytype);

		EXCEPTION_ASSERT_WITH_LOG(location, std::invalid_argument, "location cannot be null.");
		EXCEPTION_ASSERT_WITH_LOG(key, std::invalid_argument, "key cannot be null.");

		boost::shared_ptr<MifareLocation> mLocation = boost::dynamic_pointer_cast<MifareLocation>(location);
		boost::shared_ptr<MifareKey> mKey = boost::dynamic_pointer_cast<MifareKey>(key);

		EXCEPTION_ASSERT_WITH_LOG(mLocation, std::invalid_argument, "location must be a MifareLocation.");
		EXCEPTION_ASSERT_WITH_LOG(mKey, std::invalid_argument, "key must be a MifareKey.");

		boost::shared_ptr<KeyStorage> key_storage = key->getKeyStorage();

		if (boost::dynamic_pointer_cast<ComputerMemoryKeyStorage>(key_storage))
		{
			INFO_SIMPLE_("Using computer memory key storage !");
			loadKey(static_cast<unsigned char>(mLocation->sector), keytype, key->getData(), key->getLength(), true);
		}
		else if (boost::dynamic_pointer_cast<ReaderMemoryKeyStorage>(key_storage))
		{
			INFO_SIMPLE_("Using reader memory key storage !");
			// Don't load the key when reader memory, except if specified
			if (!key->isEmpty())
			{
				THROW_EXCEPTION_WITH_LOG(LibLogicalAccessException, "It's not possible to change a key at specific index through host/reader connection. Please use SKB configuration card instead.");
			}
		}
		else
		{
			THROW_EXCEPTION_WITH_LOG(LibLogicalAccessException, "The key storage type is not supported for this card/reader.");
		}
	}
    void SAMAV1ISO7816Commands::changeKUCEntry(unsigned char kucno, std::shared_ptr<SAMKucEntry> kucentry, std::shared_ptr<DESFireKey> key)
    {
        if (d_crypto->d_sessionKey.size() == 0)
            THROW_EXCEPTION_WITH_LOG(LibLogicalAccessException, "Failed: AuthentificationHost have to be done before use such command.");

        unsigned char data[6] = {};
        memcpy(data, &kucentry->getKucEntryStruct(), 6);
        std::vector<unsigned char> vectordata(data, data + 6);
        std::vector<unsigned char> encdatalittle;

        if (key->getKeyType() == DF_KEY_DES)
            encdatalittle = d_crypto->sam_encrypt(d_crypto->d_sessionKey, vectordata);
        else
            encdatalittle = d_crypto->sam_crc_encrypt(d_crypto->d_sessionKey, vectordata, key);

        unsigned char proMas = kucentry->getUpdateMask();

        unsigned char cmd[] = { d_cla, 0xcc, kucno, proMas, 0x08 };
        std::vector<unsigned char> cmd_vector(cmd, cmd + 5), result;
        cmd_vector.insert(cmd_vector.end(), encdatalittle.begin(), encdatalittle.end());
        result = transmit(cmd_vector);

        if (result.size() >= 2 && (result[result.size() - 2] != 0x90 || result[result.size() - 1] != 0x00))
            THROW_EXCEPTION_WITH_LOG(LibLogicalAccessException, "changeKUCEntry failed.");
    }
    void SAMAV1ISO7816Commands::changeKeyEntry(unsigned char keyno, std::shared_ptr<SAMKeyEntry<KeyEntryAV1Information, SETAV1> > keyentry, std::shared_ptr<DESFireKey> key)
    {
        if (d_crypto->d_sessionKey.size() == 0)
            THROW_EXCEPTION_WITH_LOG(LibLogicalAccessException, "Failed: AuthentificationHost have to be done before use such command.");

        unsigned char proMas = keyentry->getUpdateMask();

        size_t buffer_size = keyentry->getLength() + sizeof(KeyEntryAV1Information);
        unsigned char *data = new unsigned char[buffer_size]();

        memcpy(data, &*(keyentry->getData()), keyentry->getLength());
        memcpy(data + 48, &keyentry->getKeyEntryInformation(), sizeof(KeyEntryAV1Information));

        std::vector<unsigned char> iv;
        iv.resize(16, 0x00);

        std::vector<unsigned char> vectordata(data, data + buffer_size);
        delete[] data;

        std::vector<unsigned char> encdatalittle;

        if (key->getKeyType() == DF_KEY_DES)
            encdatalittle = d_crypto->sam_encrypt(d_crypto->d_sessionKey, vectordata);
        else
            encdatalittle = d_crypto->sam_crc_encrypt(d_crypto->d_sessionKey, vectordata, key);

        unsigned char cmd[] = { d_cla, 0xc1, keyno, proMas, (unsigned char)(encdatalittle.size()) };
        std::vector<unsigned char> cmd_vector(cmd, cmd + 5), result;
        cmd_vector.insert(cmd_vector.end(), encdatalittle.begin(), encdatalittle.end());

        result = transmit(cmd_vector);

        if (result.size() >= 2 && (result[result.size() - 2] != 0x90 || result[result.size() - 1] != 0x00))
            THROW_EXCEPTION_WITH_LOG(LibLogicalAccessException, "changeKeyEntry failed.");
    }
        void OpenSSLSymmetricCipher::update(OpenSSLSymmetricCipherContext& context, const std::vector<unsigned char>& src)
        {
            int r = 0;
            int outlen = 0;

            unsigned char* buf = new unsigned char[src.size() + context.blockSize()];

            switch (context.method())
            {
            case M_ENCRYPT:
            {
                r = EVP_EncryptUpdate(context.ctx(), buf, &outlen, &src[0], static_cast<int>(src.size()));
                break;
            }
            case M_DECRYPT:
            {
                r = EVP_DecryptUpdate(context.ctx(), buf, &outlen, &src[0], static_cast<int>(src.size()));
                break;
            }
            default:
            {
                THROW_EXCEPTION_WITH_LOG(std::runtime_error, "Unhandled method");
            }
            }

            if (r != 1)
            {
                delete[] buf;
                THROW_EXCEPTION_WITH_LOG(OpenSSLException, "");
            }

            context.data().insert(context.data().end(), buf, buf + outlen);
            delete[] buf;
        }
    void SAMAV1ISO7816Commands::authenticateHost_AES_3K3DES(std::shared_ptr<DESFireKey> key, unsigned char keyno)
    {
        std::vector<unsigned char> data;
        unsigned char authMode = 0x00;

        data.push_back(keyno);
        data.push_back(key->getKeyVersion());

        unsigned char cmdp1[] = { d_cla, 0xa4, authMode, 0x00, 0x02, 0x00 };
        std::vector<unsigned char> cmd_vector(cmdp1, cmdp1 + 6), result;
        cmd_vector.insert(cmd_vector.end() - 1, data.begin(), data.end());

        result = transmit(cmd_vector);
        if (result.size() >= 2 && (result[result.size() - 2] != 0x90 || result[result.size() - 1] != 0xaf))
            THROW_EXCEPTION_WITH_LOG(LibLogicalAccessException, "authenticateHost_AES_3K3DES P1 failed.");

        std::vector<unsigned char> encRndB(result.begin(), result.end() - 2);
        std::vector<unsigned char> encRndAB = d_crypto->authenticateHostP1(key, encRndB, keyno);

        unsigned char cmdp2[] = { d_cla, 0xa4, 0x00, 0x00, (unsigned char)(encRndAB.size()), 0x00 };
        cmd_vector.assign(cmdp2, cmdp2 + 6);
        cmd_vector.insert(cmd_vector.end() - 1, encRndAB.begin(), encRndAB.end());

        result = transmit(cmd_vector);
        if (result.size() >= 2 && (result[result.size() - 2] != 0x90 || result[result.size() - 1] != 0x00))
            THROW_EXCEPTION_WITH_LOG(LibLogicalAccessException, "authenticateHost_AES_3K3DES P2 failed.");

        std::vector<unsigned char> encRndA1(result.begin(), result.end() - 2);
        d_crypto->authenticateHostP2(keyno, encRndA1, key);
    }
	bool DESFireStorageCardService::erase()
	{
		bool r = false;
		boost::shared_ptr<DESFireCommands> cmd = getDESFireChip()->getDESFireCommands();
		if (cmd->selectApplication(0))
		{
			if (cmd->authenticate(0))
			{
				if (cmd->erase())
				{
					r = cmd->changeKey(0, boost::shared_ptr<DESFireKey>(new DESFireKey(string("00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00"))));
				}
			}
			else
			{
				THROW_EXCEPTION_WITH_LOG(CardException, EXCEPTION_MSG_AUTHENTICATE);
			}
		}
		else
		{
			THROW_EXCEPTION_WITH_LOG(CardException, EXCEPTION_MSG_SELECTAPPLICATION);
		}
		
		return r;
	}
	bool ISO7816StorageCardService::readData(boost::shared_ptr<Location> location, boost::shared_ptr<AccessInfo> /*aiToUse*/, void* data, size_t dataLength, CardBehavior /*behaviorFlags*/)
	{
		bool ret = false;

		EXCEPTION_ASSERT_WITH_LOG(location, std::invalid_argument, "location cannot be null.");
		EXCEPTION_ASSERT_WITH_LOG(data, std::invalid_argument, "data cannot be null.");

		boost::shared_ptr<ISO7816Location> icLocation = boost::dynamic_pointer_cast<ISO7816Location>(location);

		EXCEPTION_ASSERT_WITH_LOG(icLocation, std::invalid_argument, "location must be a ISO7816Location.");

		
		if (icLocation->fileid != 0)
		{
			getISO7816Chip()->getISO7816Commands()->selectFile(icLocation->fileid);
		}
		else
		{
			unsigned char defaultdf[16];
			memset(defaultdf, 0x00, sizeof(defaultdf));
			if (memcmp(icLocation->dfname, defaultdf, sizeof(defaultdf)))
			{
				getISO7816Chip()->getISO7816Commands()->selectFile(icLocation->dfname, icLocation->dfnamelen);
			}
		}

		switch (icLocation->fileType)
		{
		case IFT_MASTER:
		case IFT_DIRECTORY:
			if (icLocation->dataObject > 0)
			{
				ret = getISO7816Chip()->getISO7816Commands()->getData(data, dataLength, icLocation->dataObject);
			}
			else
			{
				THROW_EXCEPTION_WITH_LOG(LibLogicalAccessException, "Please specify a data object.");
			}
			break;

		case IFT_TRANSPARENT:
			ret = getISO7816Chip()->getISO7816Commands()->readBinay(data, dataLength, 0);
			break;

		case IFT_LINEAR_FIXED:
		case IFT_LINEAR_VARIABLE:
		case IFT_CYCLIC:
			THROW_EXCEPTION_WITH_LOG(LibLogicalAccessException, "Not implemented yet.");
			break;

		default:
			THROW_EXCEPTION_WITH_LOG(LibLogicalAccessException, "Doesn't know how to read on this file.");
			break;
		}

		return ret;
	}
    void ISO7816StorageCardService::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<ISO7816Location> icLocation = std::dynamic_pointer_cast<ISO7816Location>(location);

        EXCEPTION_ASSERT_WITH_LOG(icLocation, std::invalid_argument, "location must be a ISO7816Location.");

        if (icLocation->fileid != 0)
        {
            getISO7816Chip()->getISO7816Commands()->selectFile(icLocation->fileid);
        }
        else
        {
            unsigned char defaultdf[16];
            memset(defaultdf, 0x00, sizeof(defaultdf));
            if (memcmp(icLocation->dfname, defaultdf, sizeof(defaultdf)))
            {
                getISO7816Chip()->getISO7816Commands()->selectFile(icLocation->dfname, icLocation->dfnamelen);
            }
        }

        switch (icLocation->fileType)
        {
        case IFT_MASTER:
        case IFT_DIRECTORY:
        {
            if (icLocation->dataObject > 0)
            {
                getISO7816Chip()->getISO7816Commands()->putData(data, icLocation->dataObject);
            }
            else
            {
                THROW_EXCEPTION_WITH_LOG(LibLogicalAccessException, "Please specify a data object.");
            }
        }
            break;

        case IFT_TRANSPARENT:
        {
            getISO7816Chip()->getISO7816Commands()->writeBinary(data, 0);
        }
            break;

        case IFT_LINEAR_FIXED:
        case IFT_LINEAR_VARIABLE:
        case IFT_CYCLIC:
            THROW_EXCEPTION_WITH_LOG(LibLogicalAccessException, "Not implemented yet.");
            break;

        default:
            THROW_EXCEPTION_WITH_LOG(LibLogicalAccessException, "Doesn't know how to write on this file.");
            break;
        }
    }
Пример #9
0
    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)
Пример #10
0
	unsigned int MifareCommands::getSectorFromMAD(long aid, boost::shared_ptr<MifareKey> madKeyA)
	{
		unsigned int sector = static_cast<unsigned int>(-1);
		MifareAccessInfo::SectorAccessBits sab;
		
		if (!madKeyA->isEmpty())
		{
			getMifareChip()->getMifareProfile()->setKey(0, KT_KEY_A, madKeyA);
		}

		unsigned char madbuf[32];
		memset(madbuf, 0x00, sizeof(madbuf));

		if (!readSector(0, 1, madbuf, sizeof(madbuf), sab))
		{
			THROW_EXCEPTION_WITH_LOG(LibLogicalAccessException, "Can't read the MAD.");
		}
		
		unsigned char madcrc = calculateMADCrc(madbuf, sizeof(madbuf));
		if (madcrc != madbuf[0])
		{
			THROW_EXCEPTION_WITH_LOG(LibLogicalAccessException, "Bad MAD CRC.");
		}
		
		sector = findReferencedSector(aid, madbuf, sizeof(madbuf));

		if ((sector == static_cast<unsigned int>(-1)) && getChip()->getCardType() == "Mifare4K")
		{
			unsigned char madbuf2[48];
			memset(madbuf2, 0x00, sizeof(madbuf2));

			if (readSector(16, 0, madbuf2, sizeof(madbuf2), sab) != sizeof(madbuf2))
			{
				THROW_EXCEPTION_WITH_LOG(LibLogicalAccessException, "Can't read the MAD2.");
			}

			unsigned char mad2crc = calculateMADCrc(madbuf2, sizeof(madbuf2));
			if (mad2crc != madbuf2[0])
			{
				THROW_EXCEPTION_WITH_LOG(LibLogicalAccessException, "Bad MAD2 CRC.");
			}

			sector = findReferencedSector(aid, madbuf2, sizeof(madbuf2));

			if (sector != static_cast<unsigned int>(-1))
			{
				sector += 16;
			}
		}

		return sector;
	}
Пример #11
0
	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)
bool logicalaccess::MifarePlusISO7816ResultChecker::checkByte(uint8_t t)
{
    switch (t)
    {
        case 0x06:
        THROW_EXCEPTION_WITH_LOG(CardException, "Access conditions not fulfilled.");
            break;
        case 0x07:
        THROW_EXCEPTION_WITH_LOG(CardException, "Too many read or write commands in the session or in the transaction");
            break;
        case 0x08:
            THROW_EXCEPTION_WITH_LOG(CardException, "Invalid MAC in command or response");
            break;
        case 0x09:
        THROW_EXCEPTION_WITH_LOG(CardException, "Block number is not valid");
            break;
        case 0x0A:
        THROW_EXCEPTION_WITH_LOG(CardException, "Block number is not valid / not existing");
            break;
        case 0x0B:
        THROW_EXCEPTION_WITH_LOG(CardException, "The current command code is not available at the current card state");
            break;
        case 0x0C:
        THROW_EXCEPTION_WITH_LOG(CardException, "Length error");
            break;
        case 0x0F:
        THROW_EXCEPTION_WITH_LOG(CardException, "General Manipulation Error: Failure in the operation of the PICC");
            break;
        case 0x90:
            return true;
    }
    return false;
}
	size_t MifareSTidSTRCommands::updateBinary(unsigned char blockno, const void* buf, size_t buflen)
	{
		INFO_("Update binary block {0x%x(%u)} [in] buffer len {%d}", blockno, blockno, buflen);

		if ((buflen >= 256) || (!buf))
		{
			THROW_EXCEPTION_WITH_LOG(std::invalid_argument, "Bad buffer parameter.");
		}

		if (d_useSKB)
		{
			INFO_SIMPLE_("Need to use reader memory key storage (SKB) !");
			return updateBinaryIndex(d_skbIndex, blockno, buf, buflen);
		}

		INFO_SIMPLE_(" => Rescanning card to avoid bad authentication");
		scanMifare();
		INFO_SIMPLE_("Scan done ! Continue to update binary block.");

		if (blockno != 0)
		{
			std::vector<unsigned char> command;
			command.push_back(static_cast<unsigned char>(d_lastKeyType));
			command.push_back(blockno);
			command.insert(command.end(), (unsigned char*)buf, (unsigned char*)buf + buflen);

			getSTidSTRReaderCardAdapter()->sendCommand(0x00D2, command);
		}

		INFO_("Returns final [out] buffer len {%d}", buflen);
		return buflen;
	}	
Пример #14
0
	void MifareProfile::setKeyUsage(int index, MifareKeyType keytype, bool used)
	{
		if (index > static_cast<int>(getNbSectors()))
		{
			THROW_EXCEPTION_WITH_LOG(std::invalid_argument, "Index is greater than max sector number.");
		}

		boost::shared_ptr<MifareKey> key;
		if (used)
		{
			key.reset(new MifareKey());
		}

		switch (keytype)
		{
			case KT_KEY_A:
				{
					d_key[index * 2] = key;
				}
			case KT_KEY_B:
				{
					d_key[index * 2 + 1] = key;
				}
		}
	}
Пример #15
0
    std::vector<unsigned char> OK5553ReaderUnit::rats()
    {
        std::vector<unsigned char> answer;

        // Sending two RATS is not supported without a new Select. Doesn't send another one if the first successed.
        if (d_successedRATS.size() == 0)
        {
            LOG(LogLevel::INFOS) << "Sending a RATS";
            answer = getDefaultOK5553ReaderCardAdapter()->sendAsciiCommand("t020FE020");
            answer = asciiToHex(answer);
            if (answer.size() > 1)
            {
                if (answer[0] == answer.size() - 1)
                {
                    answer.erase(answer.begin());
                }
                else
                    answer.clear();
            }
            else
            {
                answer.clear();
                THROW_EXCEPTION_WITH_LOG(std::invalid_argument, "No tag present in rfid field");
            }

            d_successedRATS = answer;
        }
        else
        {
            answer = d_successedRATS;
        }

        return answer;
    }
Пример #16
0
	bool OSDPReaderUnit::connectToReader()
	{
		bool ret = getDataTransport()->connect();
		if (ret)
		{
			m_commands->initCommands(getOSDPConfiguration()->getRS485Address());

			//Test if can read
			m_commands->poll();
			
			//Start Secure Channel
			std::shared_ptr<OSDPChannel> challenge = m_commands->challenge();
			checkPDAuthentication(challenge);
			std::shared_ptr<OSDPChannel> crypt = m_commands->sCrypt();
			//Successful Authentication
			crypt->isSCB = true;

			std::shared_ptr<OSDPChannel> result = m_commands->getProfile();
			if (result->getCommandsType() == OSDPCommandsType::XRD)
			{
                std::vector<unsigned char>& data = result->getData();
                if (data.size() > 2 && data[0x03] != 0x01)
                {
                    std::shared_ptr<OSDPChannel> result = m_commands->setProfile(0x01);
                    if (result->getCommandsType() != OSDPCommandsType::ACK)
                        THROW_EXCEPTION_WITH_LOG(LibLogicalAccessException, "Impossible to set Profile 0x01");
                }
			}
		}

		return ret;
	}
	size_t MifareSTidSTRCommands::readBinary(unsigned char blockno, size_t len, void* buf, size_t buflen)
	{
		INFO_("Read binary block {0x%x(%u)} len {%d} [out] buffer len {%d}", blockno, blockno, len, buflen);
		
		if ((len >= 256) || (len > buflen) || (!buf))
		{
			THROW_EXCEPTION_WITH_LOG(std::invalid_argument, "Bad buffer parameter.");
		}

		if (d_useSKB)
		{
			INFO_SIMPLE_("Need to use reader memory key storage (SKB) !");
			return readBinaryIndex(d_skbIndex, blockno, len, buf, buflen);
		}

		INFO_SIMPLE_(" => Rescanning card to avoid bad authentication");
		scanMifare();
		INFO_SIMPLE_("Scan done ! Continue to read binary block.");

		std::vector<unsigned char> command;
		command.push_back(static_cast<unsigned char>(d_lastKeyType));
		command.push_back(blockno);

		std::vector<unsigned char> sbuf = getSTidSTRReaderCardAdapter()->sendCommand(0x00B2, command);

		INFO_("Read binary buffer returned %s len {%d}", BufferHelper::getHex(sbuf).c_str(), sbuf.size());
		EXCEPTION_ASSERT_WITH_LOG(sbuf.size() == 16, LibLogicalAccessException, "The read value should always be 16 bytes long");
		EXCEPTION_ASSERT_WITH_LOG(sbuf.size() <= buflen, LibLogicalAccessException, "Buffer is too small to get all response value");

		memcpy(buf, &sbuf[0], sbuf.size());

		return sbuf.size();
	}
Пример #18
0
    void ValueDataField::revertBinaryData(const void* data, size_t dataLengthBytes, unsigned int* pos, unsigned int fieldlen, void* revertedData, size_t revertedDataLengthBytes) const
    {
        unsigned int readSizeBits = fieldlen;
        size_t extractedSizeBytes = (readSizeBits + 7) / 8;
        unsigned int revertedSizeBits = readSizeBits;
        size_t revertedTemporarySizeBytes = (revertedSizeBits + 7) / 8;

        unsigned char* extractData = new unsigned char[extractedSizeBytes];
        unsigned char* revertedTemporaryData = new unsigned char[revertedTemporarySizeBytes];
        memset(extractData, 0x00, extractedSizeBytes);
        memset(revertedTemporaryData, 0x00, revertedTemporarySizeBytes);

        unsigned int tmp = 0;
        if ((tmp = BitHelper::extract(extractData, extractedSizeBytes, data, dataLengthBytes, static_cast<unsigned int>(dataLengthBytes * 8), *pos, readSizeBits)) > 0)
        {
            if ((tmp = d_dataRepresentation->revertBinary(extractData, extractedSizeBytes, tmp, revertedTemporaryData, revertedTemporarySizeBytes)) > 0)
            {

#if defined(UNIX)
              if (revertedDataLengthBytes < revertedTemporarySizeBytes)
                THROW_EXCEPTION_WITH_LOG(LibLogicalAccessException, "The size of the dest buffer is too small for memcpy");
              memcpy(revertedData, revertedTemporaryData, revertedTemporarySizeBytes);
#else
              memcpy_s(revertedData, revertedDataLengthBytes, revertedTemporaryData, revertedTemporarySizeBytes);
#endif
            }
        }

        delete[] extractData;
        delete[] revertedTemporaryData;

        (*pos) += readSizeBits;
    }
Пример #19
0
void MifarePCSCCommands::loadKey(boost::shared_ptr<Location> location, boost::shared_ptr<Key> key, MifareKeyType keytype)
{
    EXCEPTION_ASSERT_WITH_LOG(location, std::invalid_argument, "location cannot be null.");
    EXCEPTION_ASSERT_WITH_LOG(key, std::invalid_argument, "key cannot be null.");

    boost::shared_ptr<MifareLocation> mLocation = boost::dynamic_pointer_cast<MifareLocation>(location);
    boost::shared_ptr<MifareKey> mKey = boost::dynamic_pointer_cast<MifareKey>(key);

    EXCEPTION_ASSERT_WITH_LOG(mLocation, std::invalid_argument, "location must be a MifareLocation.");
    EXCEPTION_ASSERT_WITH_LOG(mKey, std::invalid_argument, "key must be a MifareKey.");

    boost::shared_ptr<KeyStorage> key_storage = key->getKeyStorage();

    if (boost::dynamic_pointer_cast<ComputerMemoryKeyStorage>(key_storage))
    {
        loadKey(0, keytype, key->getData(), key->getLength());
    }
    else if (boost::dynamic_pointer_cast<ReaderMemoryKeyStorage>(key_storage))
    {
        // Don't load the key when reader memory, except if specified
        if (!key->isEmpty())
        {
            boost::shared_ptr<ReaderMemoryKeyStorage> rmKs = boost::dynamic_pointer_cast<ReaderMemoryKeyStorage>(key_storage);
            loadKey(rmKs->getKeySlot(), keytype, key->getData(), key->getLength(), rmKs->getVolatile());
        }
    }
    else
    {
        THROW_EXCEPTION_WITH_LOG(LibLogicalAccessException, "The key storage type is not supported for this card/reader.");
    }
}
	bool MifarePlusSL3Profile::getKeyUsage(int index, MifarePlusKeyType keytype) const
	{
		if (index > static_cast<int>(getNbSectors()) && (keytype == KT_KEY_AES_A || keytype == KT_KEY_AES_B))
		{
			THROW_EXCEPTION_WITH_LOG(std::invalid_argument, "Index is greater than max sector number.");
		}

		switch (keytype)
		{
			case KT_KEY_AES_A:
				{
					return bool(d_sectorKeys[index * 2]);
				}
			case KT_KEY_AES_B:
				{
					return bool(d_sectorKeys[index * 2 + 1]);
				}
			case KT_KEY_ORIGINALITY:
				{
					return bool(d_originalityKey);
				}
			case KT_KEY_MASTERCARD:
				{
					return bool(d_masterCardKey);
				}
			case KT_KEY_CONFIGURATION:
				{
					return bool(d_configurationKey);
				}
			default:
				{
					return false;
				}
		}
	}
	bool AccessControlCardService::writeFormat(boost::shared_ptr<Format> format, boost::shared_ptr<Location> location, boost::shared_ptr<AccessInfo> aiToUse, boost::shared_ptr<AccessInfo> aiToWrite)
	{
		bool ret = false;

		EXCEPTION_ASSERT_WITH_LOG(format, std::invalid_argument, "format to write can't be null.");
		EXCEPTION_ASSERT_WITH_LOG(location, std::invalid_argument, "location parameter can't be null.");

		boost::shared_ptr<StorageCardService> storage = boost::dynamic_pointer_cast<StorageCardService>(d_chip->getService(CST_STORAGE));
		if (storage)
		{
			size_t length = (format->getDataLength() + 7) / 8;
			unsigned char *formatBuf = new unsigned char[length];
			memset(formatBuf, 0x00, length);
			format->getLinearData(formatBuf, length);
			try
			{
				if (!storage->writeData(location, aiToUse, aiToWrite, formatBuf, length, CB_AUTOSWITCHAREA))
				{				
					THROW_EXCEPTION_WITH_LOG(CardException, EXCEPTION_MSG_WRITE);
				}
			}
			catch(std::exception&)
			{
				delete[] formatBuf;
				throw;
			}

			ret = true;
			delete[] formatBuf;
		}
		
		return ret;
	}
	bool DESFireStorageCardService::readData(boost::shared_ptr<Location> location, boost::shared_ptr<AccessInfo> aiToUse, void* data, size_t dataLength, CardBehavior /*behaviorFlags*/)
	{
		bool ret = false;

		EXCEPTION_ASSERT_WITH_LOG(location, std::invalid_argument, "location cannot be null.");
		EXCEPTION_ASSERT_WITH_LOG(data, std::invalid_argument, "location cannot be null.");

		boost::shared_ptr<DESFireLocation> dfLocation = boost::dynamic_pointer_cast<DESFireLocation>(location);
		boost::shared_ptr<DESFireAccessInfo> dfAiToUse = boost::dynamic_pointer_cast<DESFireAccessInfo>(aiToUse);

		EXCEPTION_ASSERT_WITH_LOG(dfLocation, std::invalid_argument, "location must be a DESFireLocation.");
		if (aiToUse)
		{
			EXCEPTION_ASSERT_WITH_LOG(dfAiToUse, std::invalid_argument, "aiToUse must be a DESFireAccessInfo.");
		}
		else
		{
			dfAiToUse = boost::dynamic_pointer_cast<DESFireAccessInfo>(getChip()->getProfile()->createAccessInfo());
		}

		getChip()->getProfile()->clearKeys();		

		getDESFireChip()->getDESFireCommands()->selectApplication(dfLocation);

		
		bool needLoadKey = true;
		EncryptionMode encMode = dfLocation->securityLevel;
		if (encMode == CM_UNKNOWN)
		{
			encMode = getDESFireChip()->getDESFireCommands()->getEncryptionMode(aiToUse, static_cast<unsigned char>(dfLocation->file), true, &needLoadKey);
		}

		if (needLoadKey)
		{
			if (!dfAiToUse->readKey->isEmpty())
			{
				getDESFireChip()->getDESFireProfile()->setKey(dfLocation->aid, dfAiToUse->readKeyno, dfAiToUse->readKey);
			}

			if (!getDESFireChip()->getDESFireCommands()->authenticate(dfAiToUse->readKeyno))
			{
				THROW_EXCEPTION_WITH_LOG(CardException, EXCEPTION_MSG_AUTHENTICATE);
			}
		}


		size_t reallen = getDESFireChip()->getDESFireCommands()->readData(dfLocation->file,
			dfLocation->byte,
			dataLength,
			data,
			encMode);

		if (dataLength <= static_cast<size_t>(reallen))
		{
			ret = true;
		}

		return ret;
	}
Пример #23
0
    void BinaryDataField::getLinearData(void* data, size_t dataLengthBytes, unsigned int* pos) const
    {
        if ((dataLengthBytes * 8) < (d_length + *pos))
        {
            THROW_EXCEPTION_WITH_LOG(LibLogicalAccessException, "The data length is too short.");
        }

        size_t fieldDataLengthBytes = (d_length + 7) / 8;
        unsigned char* paddedBuffer = new unsigned char[fieldDataLengthBytes];
        memset(paddedBuffer, d_padding, fieldDataLengthBytes);

#if defined(__unix__)
        if (fieldDataLengthBytes < d_value.getLength())
        {
            delete[] paddedBuffer;
            THROW_EXCEPTION_WITH_LOG(LibLogicalAccessException, "The size of the dest buffer is too small for memcpy");
        }
        memcpy(paddedBuffer, d_value.getData(), d_value.getLength());
#else
        memcpy_s(paddedBuffer, fieldDataLengthBytes, d_value.getData(), d_value.getLength());
#endif

        convertBinaryData(paddedBuffer, fieldDataLengthBytes, pos, d_length, data, dataLengthBytes);

        // OLD METHOD WAS NOT HANDLING LSB/MSB CONVERSION
        /*for (size_t i = 0; i < ((d_length + 7) / 8); ++i)
        {
        unsigned char c = d_padding;
        if (i < d_value.getLength())
        {
        c = d_value.getData()[i];
        }

        unsigned int blocklen;
        if ((i+1)*8 > d_length)
        {
        blocklen = d_length % 8;
        }
        else
        {
        blocklen = 8;
        }

        convertNumericData(data, dataLengthBytes, pos, c, blocklen);
        }*/
    }
	bool ISO7816StorageCardService::erase(boost::shared_ptr<Location> location, boost::shared_ptr<AccessInfo> /*aiToUse*/)
	{
		bool ret = false;

		EXCEPTION_ASSERT_WITH_LOG(location, std::invalid_argument, "location cannot be null.");
		boost::shared_ptr<ISO7816Location> icLocation = boost::dynamic_pointer_cast<ISO7816Location>(location);

		EXCEPTION_ASSERT_WITH_LOG(icLocation, std::invalid_argument, "location must be a ISO7816Location.");

		if (icLocation->fileid != 0)
		{
			getISO7816Chip()->getISO7816Commands()->selectFile(icLocation->fileid);
		}
		else
		{
			unsigned char defaultdf[16];
			memset(defaultdf, 0x00, sizeof(defaultdf));
			if (memcmp(icLocation->dfname, defaultdf, sizeof(defaultdf)))
			{
				getISO7816Chip()->getISO7816Commands()->selectFile(icLocation->dfname, icLocation->dfnamelen);
			}
		}

		switch (icLocation->fileType)
		{		
		case IFT_TRANSPARENT:
			{
				getISO7816Chip()->getISO7816Commands()->eraseBinay(0);
				ret = true;
			}
			break;

		case IFT_LINEAR_FIXED:
		case IFT_LINEAR_VARIABLE:
		case IFT_CYCLIC:
			THROW_EXCEPTION_WITH_LOG(LibLogicalAccessException, "Not implemented yet.");
			break;

		default:
			THROW_EXCEPTION_WITH_LOG(LibLogicalAccessException, "Doesn't know how to write on this file.");
			break;
		}

		return ret;
	}
    void MifareStorageCardService::erase()
    {
        std::vector<unsigned char> zeroblock(16, 0x00);
		std::vector<unsigned char> trailerblock(16, 0xFF);

        MifareAccessInfo::SectorAccessBits sab;
        sab.setTransportConfiguration();
        trailerblock[9] = 0x00;

        if (!sab.toArray(&trailerblock[6], 3))
        {
            THROW_EXCEPTION_WITH_LOG(std::invalid_argument, "Bad sector access bits configuration.");
        }

        for (unsigned int i = 0; i < getMifareChip()->getNbSectors(); ++i)
        {
            bool erased = true;
            bool used = false;
            unsigned int firstBlock = (i == 0) ? 1 : 0; // Don't write the first block in sector 0

            std::shared_ptr<MifareLocation> location(new MifareLocation());
            location->sector = i;
            if (getMifareChip()->getMifareProfile()->getKeyUsage(i, KT_KEY_B))
            {
                used = true;

                std::shared_ptr<MifareKey> key = getMifareChip()->getMifareProfile()->getKey(i, KT_KEY_B);

                getMifareChip()->getMifareCommands()->loadKey(location, key, KT_KEY_B);
                getMifareChip()->getMifareCommands()->authenticate(static_cast<unsigned char>(getMifareChip()->getMifareCommands()->getSectorStartBlock(i)), key->getKeyStorage(), KT_KEY_B);

                for (unsigned int j = firstBlock; j < getMifareChip()->getMifareCommands()->getNbBlocks(i); ++j)
                {
                    getMifareChip()->getMifareCommands()->updateBinary(static_cast<unsigned char>(getMifareChip()->getMifareCommands()->getSectorStartBlock(i) + j), zeroblock);
                }

                getMifareChip()->getMifareCommands()->updateBinary(static_cast<unsigned char>(getMifareChip()->getMifareCommands()->getSectorStartBlock(i) + getMifareChip()->getMifareCommands()->getNbBlocks(i)), trailerblock);
            }

            if ((!erased || !used) && getMifareChip()->getMifareProfile()->getKeyUsage(i, KT_KEY_A))
            {
                used = true;

                std::shared_ptr<MifareKey> key = getMifareChip()->getMifareProfile()->getKey(i, KT_KEY_A);

                getMifareChip()->getMifareCommands()->loadKey(location, key, KT_KEY_A);
                getMifareChip()->getMifareCommands()->authenticate(static_cast<unsigned char>(getMifareChip()->getMifareCommands()->getSectorStartBlock(i)), key->getKeyStorage(), KT_KEY_A);

                for (unsigned int j = firstBlock; j < getMifareChip()->getMifareCommands()->getNbBlocks(i); ++j)
                {
                    getMifareChip()->getMifareCommands()->updateBinary(static_cast<unsigned char>(getMifareChip()->getMifareCommands()->getSectorStartBlock(i) + j), zeroblock);
                }

                getMifareChip()->getMifareCommands()->updateBinary(static_cast<unsigned char>(getMifareChip()->getMifareCommands()->getSectorStartBlock(i) + getMifareChip()->getMifareCommands()->getNbBlocks(i)), trailerblock);
            }
        }
    }
    void MifareUltralightPCSCCommands::writePage(int page, const std::vector<unsigned char>& buf)
    {
        if (buf.size() > 16)
        {
            THROW_EXCEPTION_WITH_LOG(std::invalid_argument, "Bad buffer parameter.");
        }

        getPCSCReaderCardAdapter()->sendAPDUCommand(0xFF, 0xD6, 0x00, static_cast<unsigned char>(page), static_cast<unsigned char>(buf.size()), buf);
    }
    bool MifarePlusSpringCardCommandsSL1::SwitchLevel3(std::shared_ptr<MifarePlusKey> key)
    {
        //activate T=Cl mode
        if (!TurnOnTCL())
        {
            THROW_EXCEPTION_WITH_LOG(LibLogicalAccessException, "Error while turning on the TCL mode, or TCL already in use\n");
        }

        return (MifarePlusSpringCardCommands::GenericAESAuthentication(0x9003, key, true, false));
    }
    void NXPAV1KeyDiversification::initDiversification(std::vector<unsigned char> identifier, int AID, std::shared_ptr<Key> key, unsigned char keyno, std::vector<unsigned char>& diversify)
    {
        diversify.push_back(keyno);
        diversify.insert(diversify.end(), identifier.begin(), identifier.end());

        if (diversify.size() != 8)
            THROW_EXCEPTION_WITH_LOG(LibLogicalAccessException, "NXP Diversification AV1 need 8 bytes of DivInput (Keyno + 7-byte UID)");
        if (std::dynamic_pointer_cast<DESFireKey>(key)->getKeyType() == DESFireKeyType::DF_KEY_AES)
            diversify.insert(diversify.end(), diversify.begin(), diversify.end());
    }
	std::vector<unsigned char> OSDPReaderCardAdapter::sendCommand(const std::vector<unsigned char>& command, long timeout)
	{
		std::vector<unsigned char> osdpCommand;
		std::shared_ptr<OSDPChannel> channel = m_commands->getChannel();
		if (channel->isSCB)
		{
			channel->setSecurityBlockData(std::vector<unsigned char>(2));
			channel->setSecurityBlockType(OSDPSecureChannelType::SCS_17); //Enable MAC and Data Security
		}

		channel->setCommandsType(OSDPCommandsType::XWR);
		osdpCommand.push_back(0x01); //XRW_PROFILE 0x01
		osdpCommand.push_back(0x01); //XRW_PCMND 0x01
		osdpCommand.push_back(m_address);
		osdpCommand.insert(osdpCommand.end(), command.begin(), command.end());
		LOG(LogLevel::INFOS) << "OSDP Cmd: " << BufferHelper::getHex(osdpCommand);
		channel->setData(osdpCommand);
		//Transparent Content Send Request
		std::shared_ptr<OSDPChannel> result = m_commands->transmit();

		if (result->getCommandsType() == OSDPCommandsType::NAK)
			THROW_EXCEPTION_WITH_LOG(LibLogicalAccessException, "NAK: Impossible to send Transparent Content");

		if (result->getCommandsType() == OSDPCommandsType::ACK)
		{
			LOG(LogLevel::INFOS) << "OSDP: No XRD recieve, try to send poll";
			result = m_commands->poll();
		}

		std::vector<unsigned char>& data = result->getData();

		if (result->getCommandsType() != OSDPCommandsType::XRD
			|| (result->getCommandsType() == OSDPCommandsType::XRD && data[0x01] != 0x02)) //is Not APDU answer - osdp_PR01SCREP = 0x02
			THROW_EXCEPTION_WITH_LOG(LibLogicalAccessException, "Impossible to send Transparent Content");

		std::vector<unsigned char> res(data.begin() + 4, data.end());

		if (res.size() > 0 && d_resultChecker)
		{
			d_resultChecker->CheckResult(&res[0], res.size());
		}
		return res;
	}
std::shared_ptr<KeyDiversification> KeyDiversification::getKeyDiversificationFromType(std::string kdiv)
{
    std::shared_ptr<KeyDiversification> ret = LibraryManager::getInstance()->getKeyDiversification(kdiv);

    if (!ret)
    {
        THROW_EXCEPTION_WITH_LOG(LibLogicalAccessException, "Key Diversification Type not found on plugins.");
    }
    return ret;
}