Example #1
0
static int testCardFunctionality(SCARDCONTEXT ctx, const char *readerName)
{
	SCARDHANDLE hCard;
	DWORD       protocol;
	int         errCount = 0;

	printf("Using reader \"%s\"\n\n", readerName);

	long ret = SCardConnectA(ctx, readerName,
		SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0, &hCard, &protocol);

	CHECK_PCSC_RET("SCardConnect", ret);
	if (SCARD_S_SUCCESS == ret)
	{
		delayMS(200);

		printf("--- Get Response tests ---\n");
		errCount += testGetResponse(hCard);

		printf("\n--- Get Response tests within a transaction ---\n");
		ret = SCardBeginTransaction(hCard);
		CHECK_PCSC_RET("SCardBeginTransaction", ret);
		errCount += testGetResponse(hCard);
		ret       = SCardEndTransaction(hCard, SCARD_LEAVE_CARD);
		CHECK_PCSC_RET("SCardBeginTransaction", ret);

		printf("\n--- Test reading a long file ---\n");
		errCount += testLongFileRead(hCard);

		printf("\n--- Test reading a long file within a transaction ---\n");
		ret = SCardBeginTransaction(hCard);
		CHECK_PCSC_RET("SCardBeginTransaction", ret);
		errCount += testLongFileRead(hCard);
		ret       = SCardEndTransaction(hCard, SCARD_LEAVE_CARD);
		CHECK_PCSC_RET("SCardBeginTransaction", ret);

		printf("\n--- Misc tests ---\n");
		errCount += testMisc(hCard);

		ret = SCardDisconnect(hCard, SCARD_LEAVE_CARD);
		CHECK_PCSC_RET("SCardDisconnect", ret);
	}

	if (errCount == 0)
		printf("\nFunctional tests done, no errors\n");
	else
		printf("\nFunctional tests done, %d errors\n", errCount);

	return 0;
}
Example #2
0
/*
 * Begin transaction.
 */
JNIEXPORT jint JNICALL GEN_FUNCNAME(Card_NativeEndTransaction)
(JNIEnv *env, jobject _this, jint dispo)
{
    SCARDHANDLE card;

    card = (SCARDHANDLE) (*env)->GetLongField(env, _this, CardField);

    return SCardEndTransaction(card, dispo);
}
Example #3
0
static int testTransaction(SCARDCONTEXT ctx, const char *readerName)
{
	int         returnValue = 0;
	SCARDHANDLE hCard;
	DWORD       protocol;

	long        ret = SCardConnectA(ctx, readerName,
		SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0, &hCard, &protocol);
	CHECK_PCSC_RET_PASS(0x1) //-------1
	if (SCARD_S_SUCCESS == ret)
	{
		delayMS(200);

		ret = SCardBeginTransaction(hCard);
		CHECK_PCSC_RET_PASS(0x2) //------1-
		ret = SCardEndTransaction(hCard, SCARD_LEAVE_CARD);
		CHECK_PCSC_RET_PASS(0x2) //-----1--
		ret = SCardEndTransaction(1111, SCARD_LEAVE_CARD);
		CHECK_PCSC_RET_FAIL(0x2) //-----1--
	}
static UINT32 smartcard_EndTransaction_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPERATION* operation, HCardAndDisposition_Call* call)
{
	LONG status;
	Long_Return ret;

	status = ret.ReturnCode = SCardEndTransaction(operation->hCard, call->dwDisposition);

	smartcard_trace_long_return(smartcard, &ret, "EndTransaction");

	return ret.ReturnCode;
}
Example #5
0
int Token::dump_primary(vector<BYTE> &res, DWORD id){

	LONG lReturn;
	BYTE cont_number = 0;
	BYTE *pbSend, *pbRecv;
	DWORD dwRecv;
	const DWORD  cdwRecv = 1024;
	const DWORD cdwSend = 128;

	// need to login
	if (0 != this->et72k_Login()) return 11;

	res.clear();

	pbSend = new BYTE[cdwSend];
	pbRecv = new BYTE[cdwRecv];

	//begin transaction
	lReturn = SCardBeginTransaction(this->hCardHandle);
	if (SCARD_S_SUCCESS != lReturn){
		cout << "[*] ERROR: Failed SCardBeginTransaction: " << lReturn << endl;
		return 20;
	}

	memset(pbSend, 0, cdwSend);
	memcpy(pbSend, s11, ls11);
	pbSend[14] = id;
	dwRecv = cdwRecv;
	SCardTransmit(this->hCardHandle, SCARD_PCI_T1, pbSend, ls11, NULL, pbRecv, &dwRecv); //send s11 with container id
	if (memcmp(pbRecv, noFile, 2) == 0){ //file not found
		delete[] pbRecv;
		delete[] pbSend;

		return 10; //no such container id
	}
	//cout << ">>>(s11) "; showarr(pbSend, ls11, ':'); //DEBUG
	//cout << "<<< "; showarr(pbRecv, dwRecv, ':'); //DEBUG


	dwRecv = cdwRecv;
	SCardTransmit(this->hCardHandle, SCARD_PCI_T1, cmdGET_PRIMARY, lcmdGET_PRIMARY, NULL, pbRecv, &dwRecv); //claim primary.key
	for (int i = 0; i < dwRecv - 2; i++) res.push_back(pbRecv[i]);
	//cout << ">>> "; showarr(cmdGET_MASKS, lcmdGET_MASKS, ':'); //DEBUG
	//cout << "<<< "; showarr(pbRecv, dwRecv, ':'); //DEBUG

	//End transaction
	SCardEndTransaction(this->hCardHandle, SCARD_LEAVE_CARD);

	delete[] pbRecv;
	delete[] pbSend;

	return 0;
}
Example #6
0
int Token::dump_name(vector<BYTE> &res, DWORD id){
	
	LONG lReturn;
	BYTE cont_number = 0;
	BYTE *pbSend, *pbRecv;
	DWORD dwRecv;
	const DWORD  cdwRecv = 1024;
	const DWORD cdwSend = 128;

	res.clear();

	pbSend = new BYTE[cdwSend];
	pbRecv = new BYTE[cdwRecv];

	//begin transaction
	lReturn = SCardBeginTransaction(this->hCardHandle);
	if (SCARD_S_SUCCESS != lReturn){
		cout << "[*] ERROR: Failed SCardBeginTransaction: " << lReturn << endl;
		return 20;
	}

	this->sendPreambula();

	memset(pbSend, 0, cdwSend);
	memcpy(pbSend, s5, ls5);
	pbSend[14] = id;
	dwRecv = cdwRecv;
	SCardTransmit(this->hCardHandle, SCARD_PCI_T1, pbSend, ls6, NULL, pbRecv, &dwRecv); //send s6 with container id
	if (memcmp(pbRecv, noFile, 2) == 0){ //file not found
		delete[] pbRecv;
		delete[] pbSend;

		return 10; //no such container id
	}
	//cout << ">>>(s5) "; showarr(pbSend, ls5, ':'); //DEBUG
	//cout << "<<< "; showarr(pbRecv, dwRecv, ':'); //DEBUG

	dwRecv = cdwRecv;
	SCardTransmit(this->hCardHandle, SCARD_PCI_T1, cmdGIVE_ALL_name, lcmdGIVE_ALL_name, NULL, pbRecv, &dwRecv); //claim first 10 bytes of header.key
	for (int i = 0; i < dwRecv - 2 && pbRecv[i] != 0x00; i++) res.push_back(pbRecv[i]);
	//cout << ">>>(1st 10) "; showarr(cmdGIVE_ALL_name, lcmdGIVE_ALL_name, ':'); //DEBUG
	//cout << "<<< "; showarr(pbRecv, dwRecv, ':'); //DEBUG

	//End transaction
	SCardEndTransaction(this->hCardHandle, SCARD_LEAVE_CARD);

	delete[] pbRecv;
	delete[] pbSend;

	return 0;
}
Example #7
0
bool CPCSCClass::EndTransaction(DWORD EndDisposition)
{
	
	RetCode = SCardEndTransaction(hCard,EndDisposition);
	
	if (RetCode != SCARD_S_SUCCESS)
	{	
		mylog.AddToLogs(m_logobj,"error: SCardEndTransaction failed");
		mylog.AddToLogs(m_logobj,TranslatePCSCError());
		return false;
	}
	
	mylog.AddToLogs(m_logobj,"SCardEndTransaction Success");
	return true;
}
Example #8
0
//
// FUNCTION NAME: SIM_End_Transaction
//
// DESCRIPTION: this is a wrapper for pcsclite SCardEndTransaction function.
//              Its job is to call that function and manage error messages
//              eventually returned.
//
// INPUT PARAMETERS: 
//   SCARDHANDLE  hCard    connection handler for this card.
//
// OUTPUT PARAMETERS:
//   None.
//
// NOTES:
//   -  Possible extension will require additional parameters to be chosen by
//      the caller.
//
void SIM_End_Transaction(SCARDHANDLE hCard) {
  LONG rv;

  rv = SCardEndTransaction(hCard, SCARD_LEAVE_CARD);
  switch(rv) {
    case SCARD_E_READER_UNAVAILABLE: {
      bail(EXIT_FAILURE, "SIM_End_Transaction:",ERR_READER_REMOVED);
    }
    case SCARD_E_SHARING_VIOLATION: {
      bail(EXIT_FAILURE, "SIM_End_Transaction:",ERR_SHARING_VIOLATION);
    }
    case SCARD_E_INVALID_HANDLE: {
      bail(EXIT_FAILURE, "SIM_End_Transaction:",ERR_INVALID_CONTEXT_HANDLER);
    }
    case SCARD_S_SUCCESS: {
      printf("TRANSACTION SUCCESSFULLY CLOSED.\n");
      break;
    }
    default: {
      bail(EXIT_FAILURE, "SIM_End_Transaction:",ERR_WRONG_RETURN_VALUE);
    }
  }
}
Example #9
0
static UINT32 handle_EndTransaction(IRP* irp)
{
	LONG status;
	SCARDCONTEXT hCard;
	DWORD dwDisposition = 0;

	stream_seek(irp->input, 0x20);
	stream_read_UINT32(irp->input, dwDisposition);

	stream_seek(irp->input, 0x0C);
	stream_read_UINT32(irp->input, hCard);

	status = SCardEndTransaction(hCard, dwDisposition);

	if (status != SCARD_S_SUCCESS)
		DEBUG_SCARD("Failure: %s (0x%08x)", pcsc_stringify_error(status), (unsigned) status);
	else
		DEBUG_SCARD("Success hcard: 0x%08x", (unsigned) hCard);

	smartcard_output_alignment(irp, 8);

	return status;
}
Example #10
0
static uint32 handle_EndTransaction(IRP* irp)
{
	LONG rv;
	SCARDCONTEXT hCard;
	DWORD dwDisposition = 0;

	stream_seek(irp->input, 0x20);
	stream_read_uint32(irp->input, dwDisposition);

	stream_seek(irp->input, 0x0C);
	stream_read_uint32(irp->input, hCard);

	rv = SCardEndTransaction(hCard, dwDisposition);

	if (rv != SCARD_S_SUCCESS)
		DEBUG_SCARD("Failure: %s (0x%08x)", pcsc_stringify_error(rv), (unsigned) rv);
	else
		DEBUG_SCARD("Success hcard: 0x%08x", (unsigned) hCard);

	sc_output_alignment(irp, 8);

	return rv;
}
Example #11
0
bool QPCSCReader::endTransaction( Reset reset )
{
	return SCardEndTransaction( d->card, reset ) == SCARD_S_SUCCESS;
}
Example #12
0
void Token::list_containers(vector<string> &res){
	LONG lReturn;
	BYTE cont_number = 0;
	BYTE *pbSend, *pbRecv;
	DWORD dwRecv;
	const DWORD  cdwRecv = 1024;
	const DWORD cdwSend = 128;

	res.clear();

	pbSend = new BYTE[cdwSend];
	pbRecv = new BYTE[cdwRecv];

	//begin transaction
	lReturn = SCardBeginTransaction(this->hCardHandle);
	if (SCARD_S_SUCCESS != lReturn){
		cout << "[*] ERROR: Failed SCardBeginTransaction: " << lReturn << endl;
		return;
	}

	while (true){
		this->sendPreambula();

		memset(pbSend, 0, cdwSend);
		memcpy(pbSend, s4, 16);
		pbSend[14] = cont_number;
		dwRecv = cdwRecv;
		SCardTransmit(this->hCardHandle, SCARD_PCI_T1, pbSend, 16, NULL, pbRecv, &dwRecv); //send s4 with container number
		if (memcmp(pbRecv, noFile, 2) == 0) //file not found
			break;

		memset(pbSend, 0, cdwSend);
		memcpy(pbSend, s5, 18);
		pbSend[14] = cont_number;
		dwRecv = cdwRecv;
		SCardTransmit(this->hCardHandle, SCARD_PCI_T1, pbSend, 18, NULL, pbRecv, &dwRecv); //send s5 with container number

		dwRecv = cdwRecv;
		SCardTransmit(this->hCardHandle, SCARD_PCI_T1, cmdGIVE_10, 10, NULL, pbRecv, &dwRecv); //claim first 10 bytes of container name
		DWORD container_name_len = pbRecv[3];
		string container_name;
		int i = 4;
		while (pbRecv[i] != 0x00 && pbRecv[i] != 0x90){
			container_name.append((char *)(pbRecv + i), 1);
			i++;
		}

		if (container_name_len > 6){ //received 10b without header with length in 4th byte
			memset(pbSend, 0, cdwSend);
			memcpy(pbSend, cmdGIVE_10, 10);
			pbSend[8] = 0x0a; //10b that we received
			pbSend[9] = container_name_len - pbSend[8] + 4; //the rest
			dwRecv = cdwRecv;
			SCardTransmit(this->hCardHandle, SCARD_PCI_T1, pbSend, 10, NULL, pbRecv, &dwRecv);
			container_name.append((char *)pbRecv, dwRecv - 2);
		}

		res.push_back(container_name);

		cont_number++;
	}

	//End transaction
	SCardEndTransaction(this->hCardHandle, SCARD_LEAVE_CARD);
	
	delete[] pbRecv;
	delete[] pbSend;
}
long CardEndTransaction(SCARDHANDLE hCard, DWORD dwDisposition)
{
	return SCardEndTransaction(hCard, dwDisposition);
}
Example #14
0
int Token::dump_header(vector<BYTE> &res, DWORD id){
	
	LONG lReturn;
	BYTE cont_number = 0;
	BYTE *pbSend, *pbRecv;
	DWORD dwRecv;
	const DWORD  cdwRecv = 1024;
	const DWORD cdwSend = 128;

	res.clear();

	pbSend = new BYTE[cdwSend];
	pbRecv = new BYTE[cdwRecv];

	//begin transaction
	lReturn = SCardBeginTransaction(this->hCardHandle);
	if (SCARD_S_SUCCESS != lReturn){
		cout << "[*] ERROR: Failed SCardBeginTransaction: " << lReturn << endl;
		return 20;
	}

	this->sendPreambula();

	memset(pbSend, 0, cdwSend);
	memcpy(pbSend, s6, ls6);
	pbSend[14] = id;
	dwRecv = cdwRecv;
	SCardTransmit(this->hCardHandle, SCARD_PCI_T1, pbSend, ls6, NULL, pbRecv, &dwRecv); //send s6 with container id
	if (memcmp(pbRecv, noFile, 2) == 0){ //file not found
		delete[] pbRecv;
		delete[] pbSend;

		return 10; //no such container id
	}
	//cout << ">>>(s6) "; showarr(pbSend, ls6, ':'); //DEBUG
	//cout << "<<< "; showarr(pbRecv, dwRecv, ':'); //DEBUG


	dwRecv = cdwRecv;
	SCardTransmit(this->hCardHandle, SCARD_PCI_T1, cmdGIVE_10, lcmdGIVE_10, NULL, pbRecv, &dwRecv); //claim first 10 bytes of header.key
	for (int i = 0; i < 0x0a; i++) res.push_back(pbRecv[i]);
	//cout << ">>>(1st 10) "; showarr(cmdGIVE_10, lcmdGIVE_10, ':'); //DEBUG
	//cout << "<<< "; showarr(pbRecv, dwRecv, ':'); //DEBUG

	DWORD header_len = (pbRecv[2] << 8) + pbRecv[3]; //length of header
	DWORD bytes_received = 0x0a; //now received
	const DWORD portion = 0xf5; //bytes claim with one request

	while (bytes_received < header_len){
		memset(pbSend, 0, cdwSend);
		memcpy(pbSend, cmdGIVE_10, lcmdGIVE_10);
		pbSend[7] = bytes_received >> 8;
		pbSend[8] = bytes_received & 0xff;
		pbSend[9] = ((header_len - bytes_received + 4) > portion) ? portion : (header_len - bytes_received + 4);
		dwRecv = cdwRecv;
		SCardTransmit(this->hCardHandle, SCARD_PCI_T1, pbSend, lcmdGIVE_10, NULL, pbRecv, &dwRecv);
		bytes_received += pbSend[9];
		for (int i = 0; i < pbSend[9]; i++) res.push_back(pbRecv[i]);
		//cout << ">>> "; showarr(pbSend, lcmdGIVE_10, ':'); //DEBUG
		//cout << "<<< "; showarr(pbRecv, dwRecv, ':'); //DEBUG
	}

	//End transaction
	SCardEndTransaction(this->hCardHandle, SCARD_LEAVE_CARD);

	delete[] pbRecv;
	delete[] pbSend;

	//cout << res << endl; //DEBUG

	return 0;
}
Example #15
0
static void ContextThread(LPVOID newContext)
{
	SCONTEXT * threadContext = (SCONTEXT *) newContext;
	int32_t filedes = threadContext->dwClientID;

	if (IsClientAuthorized(filedes, "access_pcsc", NULL) == 0)
	{
		Log1(PCSC_LOG_CRITICAL, "Rejected unauthorized PC/SC client");
		goto exit;
	}
	else
	{
		Log1(PCSC_LOG_DEBUG, "Authorized PC/SC client");
	}

	Log3(PCSC_LOG_DEBUG, "Thread is started: dwClientID=%d, threadContext @%p",
		threadContext->dwClientID, threadContext);

	while (1)
	{
		struct rxHeader header;
		int32_t ret = MessageReceive(&header, sizeof(header), filedes);

		if (ret != SCARD_S_SUCCESS)
		{
			/* Clean up the dead client */
			Log2(PCSC_LOG_DEBUG, "Client die: %d", filedes);
			EHTryToUnregisterClientForEvent(filedes);
			goto exit;
		}

		if ((header.command > CMD_ENUM_FIRST)
			&& (header.command < CMD_ENUM_LAST))
			Log3(PCSC_LOG_DEBUG, "Received command: %s from client %d",
				CommandsText[header.command], filedes);

		switch (header.command)
		{
			/* pcsc-lite client/server protocol version */
			case CMD_VERSION:
			{
				struct version_struct veStr;

				READ_BODY(veStr)

				Log3(PCSC_LOG_DEBUG, "Client is protocol version %d:%d",
					veStr.major, veStr.minor);

				veStr.rv = SCARD_S_SUCCESS;

				/* client and server use different protocol */
				if ((veStr.major != PROTOCOL_VERSION_MAJOR)
					|| (veStr.minor != PROTOCOL_VERSION_MINOR))
				{
					Log3(PCSC_LOG_CRITICAL, "Client protocol is %d:%d",
						veStr.major, veStr.minor);
					Log3(PCSC_LOG_CRITICAL, "Server protocol is %d:%d",
						PROTOCOL_VERSION_MAJOR, PROTOCOL_VERSION_MINOR);
					veStr.rv = SCARD_E_NO_SERVICE;
				}

				/* set the server protocol version */
				veStr.major = PROTOCOL_VERSION_MAJOR;
				veStr.minor = PROTOCOL_VERSION_MINOR;

				/* send back the response */
				WRITE_BODY(veStr)
			}
			break;

			case CMD_GET_READERS_STATE:
			{
				/* nothing to read */

#ifdef USE_USB
				/* wait until all readers are ready */
				RFWaitForReaderInit();
#endif

				/* dump the readers state */
				ret = MessageSend(readerStates, sizeof(readerStates), filedes);
			}
			break;

			case CMD_WAIT_READER_STATE_CHANGE:
			{
				struct wait_reader_state_change waStr;

				READ_BODY(waStr)

				/* add the client fd to the list */
				EHRegisterClientForEvent(filedes);

				/* We do not send anything here.
				 * Either the client will timeout or the server will
				 * answer if an event occurs */
			}
			break;

			case CMD_STOP_WAITING_READER_STATE_CHANGE:
			{
				struct wait_reader_state_change waStr;

				READ_BODY(waStr)

				/* add the client fd to the list */
				waStr.rv = EHUnregisterClientForEvent(filedes);

				WRITE_BODY(waStr)
			}
			break;

			case SCARD_ESTABLISH_CONTEXT:
			{
				struct establish_struct esStr;
				SCARDCONTEXT hContext;

				READ_BODY(esStr)

				hContext = esStr.hContext;
				esStr.rv = SCardEstablishContext(esStr.dwScope, 0, 0,
					&hContext);
				esStr.hContext = hContext;

				if (esStr.rv == SCARD_S_SUCCESS)
					esStr.rv = MSGAddContext(esStr.hContext, threadContext);

				WRITE_BODY(esStr)
			}
			break;

			case SCARD_RELEASE_CONTEXT:
			{
				struct release_struct reStr;

				READ_BODY(reStr)

				reStr.rv = SCardReleaseContext(reStr.hContext);

				if (reStr.rv == SCARD_S_SUCCESS)
					reStr.rv = MSGRemoveContext(reStr.hContext, threadContext);

				WRITE_BODY(reStr)
			}
			break;

			case SCARD_CONNECT:
			{
				struct connect_struct coStr;
				SCARDHANDLE hCard;
				DWORD dwActiveProtocol;

				READ_BODY(coStr)

				coStr.szReader[sizeof(coStr.szReader)-1] = 0;
				hCard = coStr.hCard;
				dwActiveProtocol = coStr.dwActiveProtocol;

				if (IsClientAuthorized(filedes, "access_card", coStr.szReader) == 0)
				{
					Log2(PCSC_LOG_CRITICAL, "Rejected unauthorized client for '%s'", coStr.szReader);
					goto exit;
				}
				else
				{
					Log2(PCSC_LOG_DEBUG, "Authorized client for '%s'", coStr.szReader);
				}

				coStr.rv = SCardConnect(coStr.hContext, coStr.szReader,
					coStr.dwShareMode, coStr.dwPreferredProtocols,
					&hCard, &dwActiveProtocol);

				coStr.hCard = hCard;
				coStr.dwActiveProtocol = dwActiveProtocol;

				if (coStr.rv == SCARD_S_SUCCESS)
					coStr.rv = MSGAddHandle(coStr.hContext, coStr.hCard,
						threadContext);

				WRITE_BODY(coStr)
			}
			break;

			case SCARD_RECONNECT:
			{
				struct reconnect_struct rcStr;
				DWORD dwActiveProtocol;

				READ_BODY(rcStr)

				if (MSGCheckHandleAssociation(rcStr.hCard, threadContext))
					goto exit;

				rcStr.rv = SCardReconnect(rcStr.hCard, rcStr.dwShareMode,
					rcStr.dwPreferredProtocols, rcStr.dwInitialization,
					&dwActiveProtocol);
				rcStr.dwActiveProtocol = dwActiveProtocol;

				WRITE_BODY(rcStr)
			}
			break;

			case SCARD_DISCONNECT:
			{
				struct disconnect_struct diStr;

				READ_BODY(diStr)

				if (MSGCheckHandleAssociation(diStr.hCard, threadContext))
					goto exit;

				diStr.rv = SCardDisconnect(diStr.hCard, diStr.dwDisposition);

				if (SCARD_S_SUCCESS == diStr.rv)
					diStr.rv = MSGRemoveHandle(diStr.hCard, threadContext);

				WRITE_BODY(diStr)
			}
			break;

			case SCARD_BEGIN_TRANSACTION:
			{
				struct begin_struct beStr;

				READ_BODY(beStr)

				if (MSGCheckHandleAssociation(beStr.hCard, threadContext))
					goto exit;

				beStr.rv = SCardBeginTransaction(beStr.hCard);

				WRITE_BODY(beStr)
			}
			break;

			case SCARD_END_TRANSACTION:
			{
				struct end_struct enStr;

				READ_BODY(enStr)

				if (MSGCheckHandleAssociation(enStr.hCard, threadContext))
					goto exit;

				enStr.rv = SCardEndTransaction(enStr.hCard,
					enStr.dwDisposition);

				WRITE_BODY(enStr)
			}
			break;

			case SCARD_CANCEL:
			{
				struct cancel_struct caStr;
				SCONTEXT * psTargetContext = NULL;
				READ_BODY(caStr)

				/* find the client */
				(void)pthread_mutex_lock(&contextsList_lock);
				psTargetContext = (SCONTEXT *) list_seek(&contextsList,
					&caStr.hContext);
				(void)pthread_mutex_unlock(&contextsList_lock);
				if (psTargetContext != NULL)
				{
					uint32_t fd = psTargetContext->dwClientID;
					caStr.rv = MSGSignalClient(fd, SCARD_E_CANCELLED);

					/* the client should not receive the event
					 * notification now the waiting has been cancelled */
					EHUnregisterClientForEvent(fd);
				}
				else
					caStr.rv = SCARD_E_INVALID_HANDLE;

				WRITE_BODY(caStr)
			}
			break;

			case SCARD_STATUS:
			{
				struct status_struct stStr;

				READ_BODY(stStr)

				if (MSGCheckHandleAssociation(stStr.hCard, threadContext))
					goto exit;

				/* only hCard and return value are used by the client */
				stStr.rv = SCardStatus(stStr.hCard, NULL, NULL, NULL,
					NULL, 0, NULL);

				WRITE_BODY(stStr)
			}
			break;

			case SCARD_TRANSMIT:
			{
				struct transmit_struct trStr;
				unsigned char pbSendBuffer[MAX_BUFFER_SIZE_EXTENDED];
				unsigned char pbRecvBuffer[MAX_BUFFER_SIZE_EXTENDED];
				SCARD_IO_REQUEST ioSendPci;
				SCARD_IO_REQUEST ioRecvPci;
				DWORD cbRecvLength;

				READ_BODY(trStr)

				if (MSGCheckHandleAssociation(trStr.hCard, threadContext))
					goto exit;

				/* avoids buffer overflow */
				if ((trStr.pcbRecvLength > sizeof(pbRecvBuffer))
					|| (trStr.cbSendLength > sizeof(pbSendBuffer)))
					goto buffer_overflow;

				/* read sent buffer */
				ret = MessageReceive(pbSendBuffer, trStr.cbSendLength, filedes);
				if (ret != SCARD_S_SUCCESS)
				{
					Log2(PCSC_LOG_DEBUG, "Client die: %d", filedes);
					goto exit;
				}

				ioSendPci.dwProtocol = trStr.ioSendPciProtocol;
				ioSendPci.cbPciLength = trStr.ioSendPciLength;
				ioRecvPci.dwProtocol = trStr.ioRecvPciProtocol;
				ioRecvPci.cbPciLength = trStr.ioRecvPciLength;
				cbRecvLength = sizeof pbRecvBuffer;

				trStr.rv = SCardTransmit(trStr.hCard, &ioSendPci,
					pbSendBuffer, trStr.cbSendLength, &ioRecvPci,
					pbRecvBuffer, &cbRecvLength);

				if (cbRecvLength > trStr.pcbRecvLength)
					/* The client buffer is not large enough.
					 * The pbRecvBuffer buffer will NOT be sent a few
					 * lines bellow. So no buffer overflow is expected. */
					trStr.rv = SCARD_E_INSUFFICIENT_BUFFER;

				trStr.ioSendPciProtocol = ioSendPci.dwProtocol;
				trStr.ioSendPciLength = ioSendPci.cbPciLength;
				trStr.ioRecvPciProtocol = ioRecvPci.dwProtocol;
				trStr.ioRecvPciLength = ioRecvPci.cbPciLength;
				trStr.pcbRecvLength = cbRecvLength;

				WRITE_BODY(trStr)

				/* write received buffer */
				if (SCARD_S_SUCCESS == trStr.rv)
					ret = MessageSend(pbRecvBuffer, cbRecvLength, filedes);
			}
			break;

			case SCARD_CONTROL:
			{
				struct control_struct ctStr;
				unsigned char pbSendBuffer[MAX_BUFFER_SIZE_EXTENDED];
				unsigned char pbRecvBuffer[MAX_BUFFER_SIZE_EXTENDED];
				DWORD dwBytesReturned;

				READ_BODY(ctStr)

				if (MSGCheckHandleAssociation(ctStr.hCard, threadContext))
					goto exit;

				/* avoids buffer overflow */
				if ((ctStr.cbRecvLength > sizeof(pbRecvBuffer))
					|| (ctStr.cbSendLength > sizeof(pbSendBuffer)))
				{
					goto buffer_overflow;
				}

				/* read sent buffer */
				ret = MessageReceive(pbSendBuffer, ctStr.cbSendLength, filedes);
				if (ret != SCARD_S_SUCCESS)
				{
					Log2(PCSC_LOG_DEBUG, "Client die: %d", filedes);
					goto exit;
				}

				dwBytesReturned = ctStr.dwBytesReturned;

				ctStr.rv = SCardControl(ctStr.hCard, ctStr.dwControlCode,
					pbSendBuffer, ctStr.cbSendLength,
					pbRecvBuffer, ctStr.cbRecvLength,
					&dwBytesReturned);

				ctStr.dwBytesReturned = dwBytesReturned;

				WRITE_BODY(ctStr)

				/* write received buffer */
				if (SCARD_S_SUCCESS == ctStr.rv)
					ret = MessageSend(pbRecvBuffer, dwBytesReturned, filedes);
			}
			break;

			case SCARD_GET_ATTRIB:
			{
				struct getset_struct gsStr;
				DWORD cbAttrLen;

				READ_BODY(gsStr)

				if (MSGCheckHandleAssociation(gsStr.hCard, threadContext))
					goto exit;

				/* avoids buffer overflow */
				if (gsStr.cbAttrLen > sizeof(gsStr.pbAttr))
					goto buffer_overflow;

				cbAttrLen = gsStr.cbAttrLen;

				gsStr.rv = SCardGetAttrib(gsStr.hCard, gsStr.dwAttrId,
					gsStr.pbAttr, &cbAttrLen);

				gsStr.cbAttrLen = cbAttrLen;

				WRITE_BODY(gsStr)
			}
			break;

			case SCARD_SET_ATTRIB:
			{
				struct getset_struct gsStr;

				READ_BODY(gsStr)

				if (MSGCheckHandleAssociation(gsStr.hCard, threadContext))
					goto exit;

				/* avoids buffer overflow */
				if (gsStr.cbAttrLen > sizeof(gsStr.pbAttr))
					goto buffer_overflow;

				gsStr.rv = SCardSetAttrib(gsStr.hCard, gsStr.dwAttrId,
					gsStr.pbAttr, gsStr.cbAttrLen);

				WRITE_BODY(gsStr)
			}
			break;

			default:
				Log2(PCSC_LOG_CRITICAL, "Unknown command: %d", header.command);
				goto exit;
		}

		/* MessageSend() failed */
		if (ret != SCARD_S_SUCCESS)
		{
			/* Clean up the dead client */
			Log2(PCSC_LOG_DEBUG, "Client die: %d", filedes);
			goto exit;
		}
	}

buffer_overflow:
	Log2(PCSC_LOG_DEBUG, "Buffer overflow detected: %d", filedes);
	goto exit;
wrong_length:
	Log2(PCSC_LOG_DEBUG, "Wrong length: %d", filedes);
exit:
	(void)close(filedes);
	(void)MSGCleanupClient(threadContext);
	(void)pthread_exit((LPVOID) NULL);
}
Example #16
0
static int testCardFunctionality(SCARDCONTEXT ctx, const char *readerName)
{
	SCARDHANDLE hCard;
	DWORD       protocol;
	int         errCount = 0;

	printf("Using reader \"%s\"\n\n", readerName);
	printf("NOTE: make sure no-one else is accessing the card!\n\n");

	long ret = SCardConnectA(ctx, readerName,
		SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0, &hCard, &protocol);

	CHECK_PCSC_RET("SCardConnect", ret);
	if (SCARD_S_SUCCESS == ret)
	{
		delayMS(200);

        printf("--- SCardReconnect tests ---\n");
        errCount += testScardReconnect(hCard, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0);

#ifdef _WIN32
		printf("\n--- SCardState tests ---\n");
		errCount += testSCardState(hCard);
#endif

		printf("\n--- SCardStatus tests ---\n");
		errCount += testSCardStatus(hCard);

#ifndef MAC_OS_X
		printf("\n--- SCardGetAttrib tests ---\n");
		errCount += testSCardGetAttrib(ctx, hCard);
#endif

		printf("\n--- Get Response tests ---\n");
		errCount += testGetResponse(hCard);

		printf("\n--- Get Response tests within a transaction ---\n");
		ret = SCardBeginTransaction(hCard);
		CHECK_PCSC_RET("SCardBeginTransaction", ret);
		errCount += testGetResponse(hCard);
		ret       = SCardEndTransaction(hCard, SCARD_LEAVE_CARD);
		CHECK_PCSC_RET("SCardBeginTransaction", ret);

		printf("\n--- Test reading a long file ---\n");
		errCount += testLongFileRead(hCard);

		printf("\n--- Test reading a long file within a transaction ---\n");
		ret = SCardBeginTransaction(hCard);
		CHECK_PCSC_RET("SCardBeginTransaction", ret);
		errCount += testLongFileRead(hCard);
		ret       = SCardEndTransaction(hCard, SCARD_LEAVE_CARD);
		CHECK_PCSC_RET("SCardBeginTransaction", ret);

		printf("\n--- Misc tests ---\n");
		errCount += testMisc(hCard);

		printf("\n--- Test ListReaders ---\n");
		errCount += testListReaders(ctx);

		ret = SCardDisconnect(hCard, SCARD_LEAVE_CARD);
		CHECK_PCSC_RET("SCardDisconnect", ret);
	}

	if (errCount == 0)
		printf("\nFunctional tests done, no errors\n");
	else
		printf("\nFunctional tests done, %d errors\n", errCount);

	return 0;
}
int
main (int argc, const char *argv[])
{
   char *pin = 0;
   char *chal = 0;
   char *reader = 0;
   char *amount = 0;
   int getid = 0;
   int getotp = 0;
   int readernum = 0;
   int debug = 0;
   int listreader = 0;
   int hyphen = 0;
   int res;
   char c;
   SCARDCONTEXT ctx;
   SCARDHANDLE card;
   BYTE atr[MAX_ATR_SIZE];
   DWORD atrlen;
   DWORD state;
   DWORD proto;
   DWORD temp;
   SCARD_IO_REQUEST recvpci;
   DWORD buflen;
   BYTE buf[256],
     cmd[256];

   poptContext optCon;          // context for parsing command-line options
   const struct poptOption optionsTable[] = {
      {"id", 'i', POPT_ARG_NONE, &getid, 0, "Report card ID", 0},
      {"pin", 'p', POPT_ARG_STRING, &pin, 0, "PIN", "6 to 12 digits"},
      {"otp", 'o', POPT_ARG_NONE, &getotp, 0, "Get OTP", 0},
      {"reference", 'c', POPT_ARG_STRING, &chal, 0, "Challenge/response or account reference", "Up to 8 digit reference/account"},
      {"amount", 'a', POPT_ARG_STRING, &amount, 0, "", "Amount pounds.pence"},
      {"reader", 'r', POPT_ARG_INT, &readernum, 0, "Which reader to use", "Index number"},
      {"list", 'l', POPT_ARG_NONE, &listreader, 0, "List readers", 0},
      {"hyphen", 'h', POPT_ARG_NONE, &hyphen, 0, "Hyphenate OTP or C/R responses", 0},
      {"debug", 'v', POPT_ARG_NONE, &debug, 0, "Debug output", 0},
      POPT_AUTOHELP {NULL, 0, 0, NULL, 0}
   };

   optCon = poptGetContext (NULL, argc, argv, optionsTable, 0);
   //poptSetOtherOptionHelp (optCon, "");

   /* Now do options processing, get portname */
   if ((c = poptGetNextOpt (optCon)) < -1)
   {
      /* an error occurred during option processing */
      fprintf (stderr, "%s: %s\n", poptBadOption (optCon, POPT_BADOPTION_NOALIAS), poptStrerror (c));
      return 1;
   }
   if (poptPeekArg (optCon))
   {
      poptPrintUsage (optCon, stderr, 0);
      return 2;
   }
   if ((res = SCardEstablishContext (SCARD_SCOPE_SYSTEM, NULL, NULL, &ctx)) != SCARD_S_SUCCESS)
      errx (1, "Can't establish context for reading cards (%s)", pcsc_stringify_error (res));

   {                            // list the readers
      int rn = 0;
      char *r,
       *e;
      if ((res = SCardListReaders (ctx, NULL, NULL, &temp)) != SCARD_S_SUCCESS)
         errx (1, "Cannot get reader list (%s)", pcsc_stringify_error (res));
      if (!(r = malloc (temp)))
         errx (1, "Cannot allocated %d bytes for reader list", (int) temp);
      if ((res = SCardListReaders (ctx, NULL, r, &temp)) != SCARD_S_SUCCESS)
         errx (1, "Cannot list readers (%s)", pcsc_stringify_error (res));
      e = r + temp;
      while (*r && r < e)
      {
         if (rn == readernum)
            reader = r;
         if (listreader)
            printf ("%d: %s\n", rn, r);
         r += strlen (r) + 1;
         rn++;
      }
      // not freed as reader is pointer into r.
   }
   if (!reader)
      errx (1, "Reader %d does not exist", readernum);
   if (debug)
      fprintf (stderr, "Reader: %s\n", reader);

   // connect to card
   if ((res =
        SCardConnect (ctx, reader, SCARD_SHARE_EXCLUSIVE, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &card, &proto)) != SCARD_S_SUCCESS)
      errx (1, "Cannot connect to %s (%s)", reader, pcsc_stringify_error (res));
   if (debug)
      fprintf (stderr, "Active protocol %X\n", (int) proto);

   if ((res = SCardBeginTransaction (card)) != SCARD_S_SUCCESS)
      errx (1, "Cannot start transaction (%s)", pcsc_stringify_error (res));

   atrlen = sizeof (atr);
   if ((res = SCardStatus (card, 0, &temp, &state, &proto, atr, &atrlen)) != SCARD_S_SUCCESS)
      errx (1, "Cannot get card status (%s)", pcsc_stringify_error (res));
   if (debug)
      fprintf (stderr, "ATR len %d state %X\n", (int) atrlen, (int) state);

   {                            // get basic data
      BYTE datareq[] = { 0x00, 0xA4, 0x04, 0x00, 0x07, 0xA0, 0x00, 0x00, 0x00, 0x03, 0x80, 0x02 };      // initial data request
      buflen = sizeof (buf);
      if (debug)
         dump ('>', sizeof (datareq), datareq);
      if ((res = SCardTransmit (card, SCARD_PCI_T0, datareq, sizeof (datareq), &recvpci, buf, &buflen)) != SCARD_S_SUCCESS)
         errx (1, "Failed to send initial request for data (%s)", pcsc_stringify_error (res));
      if (debug)
         dump ('<', buflen, buf);
      if (buflen != 2 || buf[0] != 0x61)
         errx (1, "Unexpected response to data request");
   }

   cmd[0] = 0x0;
   cmd[1] = 0xC0;
   cmd[2] = 0;
   cmd[3] = 0;
   cmd[4] = buf[1];
   buflen = sizeof (buf);
   if (debug)
      dump ('>', 5, cmd);
   if ((res = SCardTransmit (card, SCARD_PCI_T0, cmd, 5, &recvpci, buf, &buflen)) != SCARD_S_SUCCESS)
      errx (1, "Failed get initial data (%s)", pcsc_stringify_error (res));
   if (debug)
      dump ('<', buflen, buf);
   if (buflen != cmd[4] + 2)
      errx (1, "Did not get right data length %d!=%d", (int) buflen, cmd[4]);

   cmd[0] = 0x80;
   cmd[1] = 0xA8;
   cmd[2] = 0x00;
   cmd[3] = 0x00;
   cmd[4] = 0x02;
   cmd[5] = 0x83;
   cmd[6] = 0x00;
   buflen = sizeof (buf);
   if (debug)
      dump ('>', 7, cmd);
   if ((res = SCardTransmit (card, SCARD_PCI_T0, cmd, 7, &recvpci, buf, &buflen)) != SCARD_S_SUCCESS)
      errx (1, "Failed get data (%s)", pcsc_stringify_error (res));
   if (debug)
      dump ('<', buflen, buf);
   if (buflen != 2 || buf[0] != 0x61)
      errx (1, "Bad response\n");

   cmd[0] = 0x00;
   cmd[1] = 0xC0;
   cmd[2] = 0x00;
   cmd[3] = 0x00;
   cmd[4] = buf[1];
   buflen = sizeof (buf);
   if (debug)
      dump ('>', 5, cmd);
   if ((res = SCardTransmit (card, SCARD_PCI_T0, cmd, 5, &recvpci, buf, &buflen)) != SCARD_S_SUCCESS)
      errx (1, "Failed to send data (%s)", pcsc_stringify_error (res));
   if (debug)
      dump ('<', buflen, buf);

   if (getid)
   {                            // card number
      int n = 0;
      cmd[0] = 0x00;
      cmd[1] = 0xB2;
      cmd[2] = 0x02;
      cmd[3] = 0x0C;
      cmd[4] = 0x00;
      buflen = sizeof (buf);
      if (debug)
         dump ('>', 5, cmd);
      if ((res = SCardTransmit (card, SCARD_PCI_T0, cmd, 5, &recvpci, buf, &buflen)) != SCARD_S_SUCCESS)
         errx (1, "Failed to send data (%s)", pcsc_stringify_error (res));
      if (debug)
         dump ('<', buflen, buf);
      if (buflen != 2 || buf[0] != 0x6C)
         errx (1, "Unexpected response to data request");
      cmd[4] = buf[1];
      buflen = sizeof (buf);
      if (debug)
         dump ('>', 5, cmd);
      if ((res = SCardTransmit (card, SCARD_PCI_T0, cmd, 5, &recvpci, buf, &buflen)) != SCARD_S_SUCCESS)
         errx (1, "Failed get initial data (%s)", pcsc_stringify_error (res));
      if (debug)
         dump ('<', buflen, buf);
      if (buflen != cmd[4] + 2 || buflen < 12)
         errx (1, "Did not get right data length %d!=%d", (int) buflen, cmd[4]);
      for (n = 4; n < 12; n++)
         printf ("%02X", buf[n]);
      printf ("\n");
   }
   // send PIN if needed
   if (pin && (getotp || chal || amount || debug))
   {                            // send PIN
      char *p = pin;
      int n = 0;
      cmd[0] = 0;
      cmd[1] = 0x20;
      cmd[2] = 0x00;
      cmd[3] = 0x80;
      cmd[4] = 8;
      cmd[5] = 0x24;
      while (*p && n < 14)
      {
         if (isdigit (*p))
         {
            cmd[6 + n / 2] = (cmd[6 + n / 2] << 4) + (*p - '0');
            n++;
         }
         p++;
      }
      while (n < 14)
      {
         cmd[6 + n / 2] = (cmd[6 + n / 2] << 4) + 0xF;
         n++;
      }
      buflen = sizeof (buf);
      if (debug)
         dump ('>', 13, cmd);
      if ((res = SCardTransmit (card, SCARD_PCI_T0, cmd, 13, &recvpci, buf, &buflen)) != SCARD_S_SUCCESS)
         errx (1, "Failed to send PIN (%s)", pcsc_stringify_error (res));
      if (debug)
         dump ('<', buflen, buf);
      if (buflen != 2 || buf[0] != 0x90 || buf[1])
         errx (1, "PIN failed");
   }


   if (getotp || chal || amount)
   {                            // OTP
      unsigned char req[29] = { 0 };
      req[14] = 0x80;
      req[21] = req[22] = req[23] = 1;
      if (chal)
      {
         int n = 0,
            p;
         for (p = 0; chal[p]; p++)
            if (isdigit (chal[p]))
               n++;
         for (p = 0; chal[p] && n; p++)
            if (isdigit (chal[p]))
            {
               n--;
               if (n < 8)
                  req[28 - n / 2] |= ((chal[p] & 0xF) << ((n & 1) ? 4 : 0));
            }
      }
      if (amount)
      {
         int n = 0,
            p;
         for (p = 0; amount[p]; p++)
            if (isdigit (amount[p]))
               n++;
         for (p = 0; amount[p] && n; p++)
            if (isdigit (amount[p]))
            {
               n--;
               if (n < 12)
                  req[5 - n / 2] |= ((amount[p] & 0xF) << ((n & 1) ? 4 : 0));
            }
      }

      buflen = sizeof (buf);
      buf[0] = 0x80;
      buf[1] = 0xAE;
      buf[2] = 0x80;
      buf[3] = 0x00;
      buf[4] = sizeof (req);
      memcpy (buf + 5, req, sizeof (req));
      if (debug)
         dump ('>', sizeof (req) + 5, buf);
      if ((res = SCardTransmit (card, SCARD_PCI_T0, buf, sizeof (req) + 5, &recvpci, buf, &buflen)) != SCARD_S_SUCCESS)
         errx (1, "Failed to send OTP request (%s)", pcsc_stringify_error (res));
      if (debug)
         dump ('<', buflen, buf);
      if (buflen != 2 || buf[0] != 0x61)
         errx (1, "Failed to get OTP");
      cmd[0] = 0x00;
      cmd[1] = 0xC0;
      cmd[2] = 0x00;
      cmd[3] = 0x00;
      cmd[4] = buf[1];
      buflen = sizeof (buf);
      if (debug)
         dump ('>', 5, cmd);
      if ((res = SCardTransmit (card, SCARD_PCI_T0, cmd, 5, &recvpci, buf, &buflen)) != SCARD_S_SUCCESS)
         errx (1, "Failed to send OTP request (%s)", pcsc_stringify_error (res));
      if (debug)
         dump ('<', buflen, buf);
      if (buflen != 22)
         errx (1, "Bad OTP response");
      {
         unsigned long res = ((1 << 25) | (buf[4] << 17) | ((buf[10] & 0x01) << 16) | (buf[11] << 8) | buf[12]);
         printf ("%08lu\n", res);
      }

      // Advance OTP to next number
      buf[0] = 0x80;
      buf[1] = 0xAE;
      buf[2] = 0x00;
      buf[3] = 0x00;
      buf[4] = sizeof (req) + 2;
      buf[5] = 0x5A;
      buf[6] = 0x33;
      memcpy (buf + 7, req, sizeof (req));
      buflen = sizeof (buf);
      if (debug)
         dump ('>', sizeof (req) + 7, buf);
      if ((res = SCardTransmit (card, SCARD_PCI_T0, buf, sizeof (req) + 7, &recvpci, buf, &buflen)) != SCARD_S_SUCCESS)
         errx (1, "Failed to send OTP request (%s)", pcsc_stringify_error (res));
      if (debug)
         dump ('<', buflen, buf);
      if (buflen != 2 || buf[0] != 0x61)
         errx (1, "Failed to get OTP");
      cmd[0] = 0x00;
      cmd[1] = 0xC0;
      cmd[2] = 0x00;
      buflen = sizeof (buf);
      if (debug)
         dump ('>', 5, cmd);
      if ((res = SCardTransmit (card, SCARD_PCI_T0, cmd, 5, &recvpci, buf, &buflen)) != SCARD_S_SUCCESS)
         errx (1, "Failed to send OTP request (%s)", pcsc_stringify_error (res));
      if (debug)
         dump ('<', buflen, buf);
   }
   // Done
   if ((res = SCardEndTransaction (card, SCARD_UNPOWER_CARD)) != SCARD_S_SUCCESS)
      errx (1, "Cannot end transaction (%s)", pcsc_stringify_error (res));

   if ((res = SCardReleaseContext (ctx)) != SCARD_S_SUCCESS)
      errx (1, "Cant release context (%s)", pcsc_stringify_error (res));
   return 0;
}
Example #18
0
int Token::et72k_Login(){
	LONG lReturn;
	const DWORD buff_size = 1024;
	DWORD dwRecv;
	int ret = 1;
	BYTE challenge8[8], rte_data20[20], cmd8011t[15];

	if (strlen(this->upass) == 0){
		if (this->debug) cout << "[*] No user password specified, but have to" << endl;
		return 21;
	}

	//if (this->loggedin) return 0;

	BYTE* pbRecv = new BYTE[buff_size];

	lReturn = SCardBeginTransaction(this->hCardHandle);
	if (SCARD_S_SUCCESS != lReturn){
		cout << "[*] ERROR: Failed SCardBeginTransaction: " << lReturn << endl;
		return 20;
	}

	this->sendPreambula();
	dwRecv = buff_size;
	SCardTransmit(this->hCardHandle, SCARD_PCI_T1, s8, ls8, NULL, pbRecv, &dwRecv); //send s8
	dwRecv = buff_size;
	SCardTransmit(this->hCardHandle, SCARD_PCI_T1, s9, ls9, NULL, pbRecv, &dwRecv); //send s9
	dwRecv = buff_size;
	SCardTransmit(this->hCardHandle, SCARD_PCI_T1, s10, ls10, NULL, pbRecv, &dwRecv); //send s10



	//get 20bytes RTE const
	memset(pbRecv, 0, buff_size);
	dwRecv = buff_size;
	SCardTransmit(this->hCardHandle, SCARD_PCI_T1, cmdGIVE_RTE20, lcmdGIVE_RTE20, NULL, pbRecv, &dwRecv);
	memcpy(rte_data20, pbRecv, 20);
	if (this->debug){ 
		cout << "[*] token RTE data: "; 
		showarr(rte_data20, 20, ':'); }

	//get challenge
	memset(pbRecv, 0, buff_size);
	dwRecv = buff_size;
	SCardTransmit(this->hCardHandle, SCARD_PCI_T1, cmd8017, lcmd8017, NULL, pbRecv, &dwRecv);
	memcpy(challenge8, pbRecv, 8);
	if (this->debug){ 
		cout << "[*] token challenge: "; 
		showarr(challenge8, 8, ':'); 
	}

	//authenticate
	this->coumpute_authcode(challenge8, rte_data20);
	if (this->debug){
		cout << "[*] app response: ";
		showarr(challenge8, 8, ':');
	}
	memcpy(cmd8011t, cmd8011, lcmd8011);
	memcpy(cmd8011t + 7, challenge8, 8);
	memset(pbRecv, 0, buff_size);
	dwRecv = buff_size;
	SCardTransmit(this->hCardHandle, SCARD_PCI_T1, cmd8011t, lcmd8011, NULL, pbRecv, &dwRecv);
	if (this->debug){
		cout << "[*] et72k_Login finished with: ";
		showarr(pbRecv, 2, ':');
	}
	if (memcmp(pbRecv, resOK, 2) == 0){
		ret = 0;
		//this->loggedin = true;
	}

	//End transaction
	SCardEndTransaction(this->hCardHandle, SCARD_LEAVE_CARD);

	delete[] pbRecv;

	return ret;
}