Example #1
0
vector<RAPDU> ePACard::transceive(const vector<CAPDU> &cmds)
{
	vector<RAPDU> resps;

	if (!m_kEnc.empty() && !m_kMac.empty()) {
		unsigned long long start_ssc = m_ssc;
		size_t i;
		bool sm = true;
		vector<CAPDU> sm_cmds;
		for (i = 0; i < cmds.size(); i++) {
			if (cmds[i].isSecure())
				sm = false;

			if (sm) {
				sm_cmds.push_back(applySM(cmds[i]));
				/* increment SSC, to simulate decryption of the APDU */
				m_ssc++;
			} else
				sm_cmds.push_back(cmds[i]);
		}

		vector<RAPDU> sm_resps = ICard::transceive(sm_cmds);
		if (cmds.size() > sm_resps.size()) {
			eCardCore_warn(DEBUG_LEVEL_APDU, "Received too few APDUs");
		}

		m_ssc = start_ssc;
		sm = true;
		for (i = 0; i < sm_resps.size() && i < cmds.size(); i++) {
			if (cmds[i].isSecure())
				sm = false;
			if (sm) {
				/* increment SSC, to simulate encryption of the APDU */
				m_ssc++;
				resps.push_back(removeSM(sm_resps[i]));
			} else
				resps.push_back(sm_resps[i]);
		}

		for (i = 0; i < (cmds.size() - sm_resps.size()); i++) {
			resps.push_back(RAPDU(vector<unsigned char> (), 0x6d00));
		}

		if (!sm) {
			m_kEnc.clear();
			m_kMac.clear();
			m_ssc = 0;
		}
	} else {
		resps = ICard::transceive(cmds);
	}

	return resps;
}
bool ExternalReader::m_libload(void)
{
	bool r = false;

	if (!m_hLib) {
#if defined(WIN32)
#if defined(_DEBUG) || defined(DEBUG)
		m_hLib = LOAD_LIBRARY("externalReaderd.dll");
#else
		m_hLib = LOAD_LIBRARY("externalReader.dll");
#endif
#elif defined(__APPLE__)
		m_hLib = LOAD_LIBRARY("libexternalReader.dylib");
#else
		m_hLib = LOAD_LIBRARY("libexternalReader.so");
#endif

		if (m_hLib) {
			m_hOpen = (CardReaderOpen_t) GET_FUNCTION(m_hLib, CardReaderOpen);
			m_hSend = (CardReaderSend_t) GET_FUNCTION(m_hLib, CardReaderSend);
			m_hGetATR = (CardReaderGetATR_t) GET_FUNCTION(m_hLib, CardReaderGetATR);
			m_hSupportsPACE = (CardReaderSupportsPACE_t) GET_FUNCTION(m_hLib, CardReaderSupportsPACE);
			m_hDoPACE = (CardReaderDoPACE_t) GET_FUNCTION(m_hLib, CardReaderDoPACE);
			m_hClose = (CardReaderClose_t) GET_FUNCTION(m_hLib, CardReaderClose);
		} else {
			eCardCore_warn(DEBUG_LEVEL_CARD, "could not load external reader library");
		}
	}

	if (!m_hLib || !m_hOpen || !m_hSend || !m_hGetATR || !m_hSupportsPACE || !m_hDoPACE || !m_hClose) {
		eCardCore_warn(DEBUG_LEVEL_CARD, "could not load external reader library functions");
		m_libcleanup();
	} else {
		r = true;
	}

	return r;
}
std::vector<unsigned char> ExternalReader::transceive(const std::vector<unsigned char>& cmd)
{
    std::vector<unsigned char> response;
	
	unsigned long	nLengthResult = MAX_BUFFER_SIZE;

	if (ECARD_SUCCESS == m_hSend(m_hCardReader, DATA(cmd), cmd.size(), buffer, &nLengthResult)) {
		response.clear();
		response.insert(response.end(), buffer, buffer+nLengthResult);
	} else
		eCardCore_warn(DEBUG_LEVEL_CARD, "external send failed");
  
	return response;
}
bool ExternalReader::open(void)
{
	bool r = false;

	if (!m_hOpen)
		goto err;

	if (ECARD_SUCCESS == m_hOpen(&m_hCardReader, "ExternalCardReader"))
		r = true;
	else
		eCardCore_warn(DEBUG_LEVEL_CARD, "external open failed");

err:
	return r;
}
std::vector<unsigned char> ExternalReader::getATRForPresentCard(void)
{
    std::vector<unsigned char> atr;
	unsigned long	nLengthResult = MAX_BUFFER_SIZE;

	if (!m_hGetATR)
		goto err;

	if (ECARD_SUCCESS == m_hGetATR(m_hCardReader, buffer, &nLengthResult))
		atr.insert(atr.end(), buffer, buffer+nLengthResult);
	else
		eCardCore_warn(DEBUG_LEVEL_CARD, "external get atr failed");

err:
	return atr;
}
Example #6
0
PCSCReader::PCSCReader(
	const string &readerName,
	vector<ICardDetector *>& detector) : IReader(readerName, detector),
	m_hCard(0x0),
#if defined(_WIN32)
	m_dwProtocol(SCARD_PROTOCOL_UNDEFINED),
#else
	m_dwProtocol(SCARD_PROTOCOL_UNSET),
#endif
	m_hScardContext(0x0)
{
	DWORD retValue = SCARD_S_SUCCESS;
	BYTE sendbuf[] = {
		FUNCTION_GetReadersPACECapabilities,
		0x00,              /* lengthInputData */
		0x00,              /* lengthInputData */
	};

	if ((retValue = SCardEstablishContext(/*SCARD_SCOPE_USER*/ SCARD_SCOPE_SYSTEM,
					0x0, 0x0, &m_hScardContext)) != SCARD_S_SUCCESS)
		eCardCore_warn(DEBUG_LEVEL_CARD,  "SCardEstablishContext failed. 0x%08X (%s:%d)", retValue,
					   __FILE__, __LINE__);

#if defined(UNICODE) || defined(_UNICODE)
	WCHAR *_readerName = new WCHAR[m_readerName.size() + 1];
	mbstowcs(_readerName, m_readerName.c_str(), m_readerName.size());
	_readerName[m_readerName.size()] = 0;
	retValue = SCardConnect(m_hScardContext, _readerName, SCARD_SHARE_DIRECT,
							m_dwProtocol, &m_hCard, &m_dwProtocol);
	delete [] _readerName;
#else
	retValue = SCardConnect(m_hScardContext, m_readerName.c_str(), SCARD_SHARE_DIRECT,
							m_dwProtocol, &m_hCard, &m_dwProtocol);
#endif

	if (retValue != SCARD_S_SUCCESS) {
		eCardCore_warn(DEBUG_LEVEL_CARD,  "SCardConnect for %s failed. 0x%08X (%s:%d)",
					   m_readerName.c_str(), retValue,  __FILE__, __LINE__);
	}

	/* does the reader support PACE? */
	m_ioctl_pace = 0;
#if ENABLE_PACE
	BYTE recvbuf[1024];
	DWORD recvlen = sizeof(recvbuf);
	retValue = SCardControl(m_hCard, CM_IOCTL_GET_FEATURE_REQUEST, NULL, 0,
							recvbuf, sizeof(recvbuf), &recvlen);

	if (retValue != SCARD_S_SUCCESS) {
		eCardCore_warn(DEBUG_LEVEL_CARD,  "SCardControl for the reader's features failed. 0x%08X (%s:%d)",
					   retValue,  __FILE__, __LINE__);

	} else {
		for (size_t i = 0; i + PCSC_TLV_ELEMENT_SIZE <= recvlen; i += PCSC_TLV_ELEMENT_SIZE)
			if (recvbuf[i] == FEATURE_EXECUTE_PACE)
				memcpy(&m_ioctl_pace, recvbuf + i + 2, 4);
	}

	if (0 == m_ioctl_pace) {
		eCardCore_info(DEBUG_LEVEL_CARD, "Reader does not support PACE");

	} else {
		/* convert to host byte order to use for SCardControl */
		m_ioctl_pace = ntohl(m_ioctl_pace);
		hexdump(DEBUG_LEVEL_CARD, "Execute PACE Input Data (FUNCTION=GetReadersPACECapabilities)", sendbuf, sizeof sendbuf);
		recvlen = sizeof(recvbuf);
		retValue = SCardControl(m_hCard, m_ioctl_pace, sendbuf, sizeof sendbuf,
								recvbuf, sizeof(recvbuf), &recvlen);
		hexdump(DEBUG_LEVEL_CARD, "Execute PACE Output Data (FUNCTION=GetReadersPACECapabilities)", recvbuf, recvlen);

		if (retValue == SCARD_S_SUCCESS
			&& recvlen == 7
			&& recvbuf[0] == 0 && recvbuf[1] == 0
			&& recvbuf[2] == 0 && recvbuf[3] == 0) {
			if (recvbuf[6] & BITMAP_Qualified_Signature)
				eCardCore_info(DEBUG_LEVEL_CARD, "Reader supports qualified signature");

			if (recvbuf[6] & BITMAP_German_eID)
				eCardCore_info(DEBUG_LEVEL_CARD, "Reader supports German eID");

			if (recvbuf[6] & BITMAP_PACE) {
				eCardCore_info(DEBUG_LEVEL_CARD, "Reader supports PACE");

			} else
				m_ioctl_pace = 0;

			if (recvbuf[6] & BITMAP_DestroyPACEChannel)
				eCardCore_info(DEBUG_LEVEL_CARD, "Reader supports DestroyPACEChannel");

		} else {
			eCardCore_warn(DEBUG_LEVEL_CARD, "Error executing GetReadersPACECapabilities");
			m_ioctl_pace = 0;
		}
	}

#endif
}
Example #7
0
static PaceOutput
parse_EstablishPACEChannel_OutputData(BYTE *output, size_t output_length)
{
	size_t parsed = 0;
	uint8_t lengthCAR, lengthCARprev;
	uint16_t lengthOutputData, lengthEF_CardAccess, length_IDicc, mse_setat;
	vector<BYTE> CAR, CARprev, EF_CardAccess, IDicc;
	uint32_t result;
	PaceOutput paceoutput;

	/* Output Data */
	if (parsed + sizeof result > output_length) {
		eCardCore_warn(DEBUG_LEVEL_CARD, "Malformed Establish PACE Channel output data.");
		throw PACEException();
	}

	memcpy(&result, output + parsed, sizeof result);

	switch (result) {
		case 0x00000000:
			break;
		case 0xD0000001:
			eCardCore_warn(DEBUG_LEVEL_CARD, "Längen im Input sind inkonsistent");
			throw PACEException();
		case 0xD0000002:
			eCardCore_warn(DEBUG_LEVEL_CARD, "Unerwartete Daten im Input");
			throw PACEException();
		case 0xD0000003:
			eCardCore_warn(DEBUG_LEVEL_CARD, "Unerwartete Kombination von Daten im Input");
			throw PACEException();
		case 0xE0000001:
			eCardCore_warn(DEBUG_LEVEL_CARD, "Syntaxfehler im Aufbau der TLV-Antwortdaten");
			throw PACEException();
		case 0xE0000002:
			eCardCore_warn(DEBUG_LEVEL_CARD, "Unerwartete/fehlende Objekte in den TLV-Antwortdaten");
			throw PACEException();
		case 0xE0000003:
			eCardCore_warn(DEBUG_LEVEL_CARD, "Der Kartenleser kennt die PIN-ID nicht.");
			throw PACEException();
		case 0xE0000006:
			eCardCore_warn(DEBUG_LEVEL_CARD, "Fehlerhaftes PACE-Token");
			throw PACEException();
		case 0xE0000007:
			eCardCore_warn(DEBUG_LEVEL_CARD, "Zertifikatskette für Terminalauthentisierung kann nicht gebildet werden");
			throw PACEException();
		case 0xE0000008:
			eCardCore_warn(DEBUG_LEVEL_CARD, "Unerwartete Datenstruktur in Rückgabe der Chipauthentisierung");
			throw PACEException();
		case 0xE0000009:
			eCardCore_warn(DEBUG_LEVEL_CARD, "Passive Authentisierung fehlgeschlagen");
			throw PACEException();
		case 0xE000000A:
			eCardCore_warn(DEBUG_LEVEL_CARD, "Fehlerhaftes Chipauthentisierung-Token");
			throw PACEException();
		case 0xF0100001:
			eCardCore_warn(DEBUG_LEVEL_CARD, "Kommunikationsabbruch mit Karte.");
			throw PACEException();
		default:
			eCardCore_warn(DEBUG_LEVEL_CARD, "Reader reported some error: %0X.", result);
			throw PACEException();
	}

	paceoutput.set_result(result);
	parsed += sizeof result;

	/* Output Data */
	if (parsed + sizeof lengthOutputData > output_length) {
		eCardCore_warn(DEBUG_LEVEL_CARD, "Malformed Establish PACE Channel output data.");
		throw PACEException();
	}

	memcpy(&lengthOutputData, output + parsed, sizeof lengthOutputData);
	parsed += sizeof lengthOutputData;

	if (lengthOutputData != output_length - parsed) {
		eCardCore_warn(DEBUG_LEVEL_CARD, "Malformed Establish PACE Channel output data.");
		throw PACEException();
	}

	/* MSE:Set AT */
	if (parsed + sizeof mse_setat > output_length) {
		eCardCore_warn(DEBUG_LEVEL_CARD, "Malformed Establish PACE Channel output data.");
		throw PACEException();
	}

	memcpy(&mse_setat, output + parsed, sizeof mse_setat);
	paceoutput.set_status_mse_set_at(mse_setat);
	parsed += sizeof mse_setat;

	/* lengthEF_CardAccess */
	if (parsed + 2 > output_length) {
		eCardCore_warn(DEBUG_LEVEL_CARD, "Malformed Establish PACE Channel output data.");
		throw PACEException();
	}

	memcpy(&lengthEF_CardAccess, output + parsed, sizeof lengthEF_CardAccess);
	parsed += sizeof lengthEF_CardAccess;

	/* EF.CardAccess */
	if (parsed + lengthEF_CardAccess > output_length) {
		eCardCore_warn(DEBUG_LEVEL_CARD, "Malformed Establish PACE Channel output data.");
		throw PACEException();
	}

	EF_CardAccess.assign(output + parsed, output + parsed + lengthEF_CardAccess);
	paceoutput.set_ef_cardaccess(EF_CardAccess);
	parsed += lengthEF_CardAccess;

	/* lengthCAR */
	if (parsed + sizeof lengthCAR > output_length) {
		eCardCore_warn(DEBUG_LEVEL_CARD, "Malformed Establish PACE Channel output data.");
		throw PACEException();
	}

	memcpy(&lengthCAR, output + parsed, sizeof lengthCAR);
	parsed += sizeof lengthCAR;

	/* CAR */
	if (parsed + lengthCAR > output_length) {
		eCardCore_warn(DEBUG_LEVEL_CARD, "Malformed Establish PACE Channel output data.");
		throw PACEException();
	}

	CAR.assign(output + parsed, output + parsed + lengthCAR);
	paceoutput.set_car_curr(CAR);
	parsed += lengthCAR;

	/* lengthCARprev */
	if (parsed + sizeof lengthCARprev > output_length) {
		eCardCore_warn(DEBUG_LEVEL_CARD, "Malformed Establish PACE Channel output data.");
		throw PACEException();
	}

	memcpy(&lengthCARprev, output + parsed, sizeof lengthCARprev);
	parsed += sizeof lengthCARprev;

	/* CARprev */
	if (parsed + lengthCARprev > output_length) {
		eCardCore_warn(DEBUG_LEVEL_CARD, "Malformed Establish PACE Channel output data.");
		throw PACEException();
	}

	CARprev.assign(output + parsed, output + parsed + lengthCARprev);
	paceoutput.set_car_prev(CARprev);
	parsed += lengthCARprev;

	/* lengthIDicc */
	if (parsed + sizeof length_IDicc > output_length) {
		eCardCore_warn(DEBUG_LEVEL_CARD, "Malformed Establish PACE Channel output data.");
		throw PACEException();
	}

	memcpy(&length_IDicc , output + parsed, sizeof length_IDicc);
	parsed += sizeof length_IDicc;

	/* IDicc */
	if (parsed + length_IDicc > output_length) {
		eCardCore_warn(DEBUG_LEVEL_CARD, "Malformed Establish PACE Channel output data.");
		throw PACEException();
	}

	IDicc.assign(output + parsed, output + parsed + length_IDicc);
	paceoutput.set_id_icc(IDicc);
	parsed += length_IDicc;

	if (parsed != output_length) {
		eCardCore_warn(DEBUG_LEVEL_CARD, "Overrun by %d bytes", output_length - parsed);
		throw PACEException();
	}

	return paceoutput;
}
Example #8
0
void PCSCManager::findReaders(
	void)
{
	long retValue = SCARD_S_SUCCESS;
	SCARDCONTEXT hScardContext = 0x0;

	if ((retValue = SCardEstablishContext(SCARD_SCOPE_SYSTEM, 0x0,
										  0x0, &hScardContext)) != SCARD_S_SUCCESS) {
		eCardCore_warn(DEBUG_LEVEL_CARD, "SCardEstablishContext failed. 0x%08X (%s:%d)",
					   retValue, __FILE__, __LINE__);
		return;
	}

	DWORD dwSize = 0;

	if ((retValue = SCardListReaders(hScardContext, NULL,
									 NULL, &dwSize)) != SCARD_S_SUCCESS) {
		eCardCore_warn(DEBUG_LEVEL_CARD, "SCardListReaders failed. 0x%08X (%s:%d)",
					   retValue, __FILE__, __LINE__);
		return;
	}

#if defined(WIN32) || defined(WINCE)
	LPTSTR readers = new TCHAR[dwSize];
#else
	char *readers = new char[dwSize];
#endif

	if ((retValue = SCardListReaders(hScardContext, NULL,
									 readers, &dwSize)) != SCARD_S_SUCCESS) {
		eCardCore_warn(DEBUG_LEVEL_CARD, "SCardListReaders failed. 0x%08X (%s:%d)",
					   retValue, __FILE__, __LINE__);
		return;
	}

	if (0x00 == readers) {
		eCardCore_warn(DEBUG_LEVEL_CARD, "No readers available. (%s:%d)",
					   __FILE__, __LINE__);
		return;
	}

#if defined(WIN32) || defined(WINCE)
	LPTSTR pReader = readers;
#else
	char *pReader = readers;
#endif

	while ('\0' != *pReader) {
#if defined(UNICODE) || defined(_UNICODE)
		int size = wcslen(pReader) + 1;
		char *pMBBuffer = new char[size];
		memset(pMBBuffer, 0, size);
		wcstombs(pMBBuffer, pReader, wcslen(pReader));
		IReader *newReader = new PCSCReader(pMBBuffer, m_cardDetectors);
		m_readerList.push_back(newReader);
		delete [] pMBBuffer;
		pReader = pReader + wcslen(pReader) + 1;
#else
		m_readerList.push_back(new PCSCReader(pReader, m_cardDetectors));
		pReader = pReader + strlen(pReader) + 1;
#endif
	}

	delete [] readers;
	SCardReleaseContext(hScardContext);
}
PaceOutput ExternalReader::establishPACEChannelNative(const PaceInput &input)
{
	PaceOutput paceoutput;

	if (m_hDoPACE) {
		enum PinID pinid = PI_UNDEF;
		switch (input.get_pin_id()) {
			case PaceInput::pin:
				pinid = PI_PIN;
				break;
			case PaceInput::can:
				pinid = PI_CAN;
				break;
			case PaceInput::mrz:
				pinid = PI_MRZ;
				break;
			case PaceInput::puk:
				pinid = PI_PUK;
				break;
			default:
				eCardCore_warn(DEBUG_LEVEL_CARD, "Unknown type of secret");
				break;
		}
		const nPADataBuffer_t pin = {
			(unsigned char *) DATA(input.get_pin()),
			input.get_pin().size()};
		const nPADataBuffer_t chat = {
			(unsigned char *) DATA(input.get_chat()),
			input.get_chat().size()};
		const nPADataBuffer_t chat_required = {
			(unsigned char *) DATA(input.get_chat_required()),
			input.get_chat_required().size()};
		const nPADataBuffer_t chat_optional = {
			(unsigned char *) DATA(input.get_chat_optional()),
			input.get_chat_optional().size()};
		const nPADataBuffer_t certificate_description = {
			(unsigned char *) DATA(input.get_certificate_description()),
			input.get_certificate_description().size()};
		const nPADataBuffer_t transaction_info_hidden = {
			(unsigned char *) DATA(input.get_transaction_info_hidden()),
			input.get_transaction_info_hidden().size()};
		unsigned int result;
		unsigned short status_mse_set_at;
		nPADataBuffer_t ef_cardaccess = {NULL, 0};
		nPADataBuffer_t car_curr = {NULL, 0};
		nPADataBuffer_t car_prev = {NULL, 0};
		nPADataBuffer_t id_icc = {NULL, 0};
		nPADataBuffer_t chat_used = {NULL, 0};

		if (ECARD_SUCCESS == m_hDoPACE(m_hCardReader, pinid, &pin, &chat,
					&chat_required, &chat_optional, &certificate_description,
					&transaction_info_hidden, &result, &status_mse_set_at,
					&ef_cardaccess, &car_curr, &car_prev, &id_icc, &chat_used)) {
			paceoutput.set_result(result);
			paceoutput.set_status_mse_set_at(status_mse_set_at);
			paceoutput.set_ef_cardaccess(buffer2vector(&ef_cardaccess));
			paceoutput.set_car_curr(buffer2vector(&car_curr));
			paceoutput.set_car_prev(buffer2vector(&car_prev));
			paceoutput.set_id_icc(buffer2vector(&id_icc));
			paceoutput.set_chat(buffer2vector(&chat_used));

			free(car_curr.pDataBuffer);
			free(car_prev.pDataBuffer);
			free(ef_cardaccess.pDataBuffer);
			free(id_icc.pDataBuffer);
			free(chat_used.pDataBuffer);
		} else
			eCardCore_warn(DEBUG_LEVEL_CARD, "external PACE failed");
	}

    return paceoutput;
}