예제 #1
0
파일: beidcard.cpp 프로젝트: taktik/eid-mw
static bool BeidCardSelectApplet(CContext *poContext, SCARDHANDLE hCard)
{
	long lRetVal = 0; 
	unsigned char tucSelectApp[] = {0x00, 0xA4, 0x04, 0x00};
	CByteArray oCmd(40);
	oCmd.Append(tucSelectApp, sizeof(tucSelectApp));
	oCmd.Append((unsigned char) sizeof(APPLET_AID));
	oCmd.Append(APPLET_AID, sizeof(APPLET_AID));
	CByteArray oResp;

	try {
		oResp = poContext->m_oPCSC.Transmit(hCard, oCmd, &lRetVal);
	}
    catch(CMWException e)
    {
		MWLOG(LEV_CRIT, MOD_CAL, L"Failed to select applet: 0x%0x", e.GetError());
        return false;
    }
    catch(...)
    {
        MWLOG(LEV_CRIT, MOD_CAL, L"Failed to select applet");
        return false;
    }

	return (oResp.Size() == 2 && (oResp.GetByte(0) == 0x61 || oResp.GetByte(0) == 0x90));
}
예제 #2
0
static long TestPteidSendApdu(CReader & oReader)
{
	long lErrors = 0;

	printf("\nTesting SendAPDU()\n");

	// Send a Get Card Data APDU
	unsigned char tucGetCardData[] = {0x80, 0xE4, 0x00, 0x00, 0x1C};
	CByteArray oGetCardData(tucGetCardData, sizeof(tucGetCardData));
	CByteArray oData = oReader.SendAPDU(oGetCardData);
	// Serial nr. are the first 16 bytes of the Get Card Data APDU
	std::string csSerialNr = oReader.GetSerialNr();
	if (csSerialNr != oData.ToString(false, true, 0, 16))
		ERR_LOG("SendAPDU(GetCardData) returns wrong data (bad serial nr.)\n", lErrors);

	// Send a Select MF APDU
	unsigned char tucSelectMF[] = {0x00, 0xa4, 0x02, 0x0C, 0x02, 0x3f, 0x00};
	CByteArray oSelectMF(tucSelectMF, sizeof(tucSelectMF));
	oData = oReader.SendAPDU(oSelectMF);
	// Result should be 90 00
	if (oData.Size() != 2 || oData.GetByte(0) != 0x90 || oData.GetByte(1) != 0x00)
	{
		ERR_LOG("SendAPDU(GetCardData) returns wrong data (bad serial nr.)\n", lErrors);
		printf("    (result = %s\n", oData.ToString().c_str());
	}

	return lErrors;
}
예제 #3
0
static long TestPteid(CReader & oReader, const std::string & csPin)
{
	long lErrors = 0;

	CByteArray oCardData = oReader.GetInfo();
	unsigned char ucVersion = oCardData.GetByte(21);

	printf("Card: Belgian eID V%d.%d\n", ucVersion / 16, ucVersion % 16);

	lErrors += TestPteidSendApdu(oReader);

	lErrors += TestPteidCtrl(oReader, ucVersion);

	lErrors += TestCache(oReader, "3F00DF014035");
	lErrors += TestReadShortFile(oReader, "3F002F00");

	lErrors += TestReadLongFile(oReader, "3F00DF005038");

	std::vector <CByteArray> vAIDs;
	vAIDs.push_back(CByteArray("A000000177504B43532D3135", true));
	if (ucVersion >= 0x20)
		vAIDs.push_back(CByteArray("A000000177496446696C6573", true));
	lErrors += TestSelectApplication(oReader, vAIDs);

	lErrors += TestRandom(oReader);

	lErrors += TestPteidP15(oReader, ucVersion);

	lErrors += TestPteidPinStatus(oReader, ucVersion);

	lErrors += TestSignatures(oReader, csPin);

	return lErrors;
}
예제 #4
0
CCard *SISCardGetInstance(unsigned long ulVersion, const char *csReader,
	SCARDHANDLE hCard, CContext *poContext, CPinpad *poPinpad)
{
	CCard *poCard = NULL;
	bool bIsSisCard = false;
	CByteArray oData;

	// Check if it's a SIS card by reading the ATR and serial number
	try
	{
		poContext->m_oPCSC.BeginTransaction(hCard);

#ifndef SWITCH_TO_ASYNC_AFTER_READ
		unsigned long ulReadLen = 26;  // read only the first part
#else
		unsigned long ulReadLen = 404; // read everything
		try {
#endif
		oData = ReadInternal(&poContext->m_oPCSC, hCard, 0, ulReadLen);
		bIsSisCard =
			(oData.Size() >= 26) &&
			(oData.GetByte(21) == 0xA0) && (oData.GetByte(22) == 0x00) &&
			(oData.GetByte(23) == 0x00) && (oData.GetByte(24) == 0x00) && (oData.GetByte(25) == 0x33);
#ifdef SWITCH_TO_ASYNC_AFTER_READ
		} catch (...) {
			// Switch back to asynchronous mode.
			BackToAsyncMode(hCard, &poContext->m_oPCSC, csReader);
			throw;
		}
		// Switch back to asynchronous mode.
		BackToAsyncMode(hCard, &poContext->m_oPCSC, csReader);
#endif

		if (bIsSisCard)
			poCard = new CSISCard(hCard, poContext, poPinpad, oData);

		poContext->m_oPCSC.EndTransaction(hCard);
	}
	catch(...)
	{
		poContext->m_oPCSC.EndTransaction(hCard);
		//printf("Exception in cardPluginSIS.SISCardGetInstance()\n");
	}

	return poCard;
}
예제 #5
0
static long TestPteidCtrl(CReader & oReader, unsigned char ucVersion)
{
	long lErrors = 0;

	printf("\nTesting Ctrl()\n");

	// CTRL_PTEID_GETCARDDATA
	CByteArray oCardInfo = oReader.GetInfo();
	CByteArray oUnsignedCardData = oReader.Ctrl(CTRL_PTEID_GETCARDDATA, CByteArray());
	if (!oCardInfo.Equals(oUnsignedCardData))
		ERR_LOG("ERR: Ctrl(CTRL_PTEID_GETCARDDATA) != GetInfo()\n", lErrors);

	// CTRL_PTEID_GETSIGNEDCARDDATA
	if (ucVersion >= 0x20)
	{
		CByteArray oSignedCardData = oReader.Ctrl(CTRL_PTEID_GETSIGNEDCARDDATA, CByteArray());

		if (oSignedCardData.Size() != oUnsignedCardData.Size() + 128)
			ERR_LOG("ERR: signed and unsigned card data should differ in size by 128 bytes\n", lErrors);

		oSignedCardData.Chop(128);
		if (!oUnsignedCardData.Equals(oSignedCardData))
			ERR_LOG("ERR: start of unsigned card data should be the same as for unsigned card data\n", lErrors);
	}

	// CTRL_PTEID_GETSIGNEDPINSTATUS
	if (ucVersion >= 0x20)
	{
		tPin pin = oReader.GetPin(0);

		CByteArray oData(1);
		oData.Append((unsigned char) pin.ulPinRef);
		CByteArray oSignedPinStatus = oReader.Ctrl(CTRL_PTEID_GETSIGNEDPINSTATUS, oData);

		if (oSignedPinStatus.Size() != 129)
			ERR_LOG("ERR: signed pin status response should be (1 + 128) bytes\n", lErrors);
		else if (oSignedPinStatus.GetByte(0) != oReader.PinStatus(pin))
			ERR_LOG("ERR: signed pin status differs from unsigned PIN status\n", lErrors);
	}

	// CTRL_PTEID_INTERNAL_AUTH
	CByteArray oData(21); // Key ref (1 byte) + challenge(20 bytes)
	oData.Append(0x81);
	for (int i = 0; i < 20; i++)
		oData.Append((unsigned char) rand());
	CByteArray oResp1 = oReader.Ctrl(CTRL_PTEID_INTERNAL_AUTH, oData);
	if (oResp1.Size() != 128)
		ERR_LOG("ERR: Internal Auth. didn't return 128 bytes\n", lErrors);
	CByteArray oResp2 = oReader.Ctrl(CTRL_PTEID_INTERNAL_AUTH, oData);
	if (!oResp1.Equals(oResp2))
		ERR_LOG("ERR: Internal Auth. on the same data returns a different result\n", lErrors);
	oData.SetByte(oData.GetByte(5) + 0x01, 5);
	CByteArray oResp3 = oReader.Ctrl(CTRL_PTEID_INTERNAL_AUTH, oData);
	if (oResp1.Equals(oResp3))
		ERR_LOG("ERR: Internal Auth. on the different data returns the same result\n", lErrors);

	return lErrors;
}
예제 #6
0
파일: beidcard.cpp 프로젝트: taktik/eid-mw
unsigned long CBeidCard::PinStatus(const tPin & Pin)
{
    // This command isn't supported on V1 cards
    if (m_oCardData.GetByte(21) < 0x20)
        return PIN_STATUS_UNKNOWN;

    try
    {
        m_ucCLA = 0x80;
        CByteArray oResp = SendAPDU(0xEA, 0x00, (unsigned char) Pin.ulPinRef, 1);
        m_ucCLA = 0x00;

        getSW12(oResp, 0x9000);

        return oResp.GetByte(0);
    }
    catch(...)
    {
        m_ucCLA = 0x00;
        throw;
    }
}
예제 #7
0
CByteArray CPinpadLibOldBeid::PinCmd(SCARDHANDLE hCard, unsigned long ulControl,
	CByteArray oCmd, unsigned char ucPintype, unsigned char ucOperation)
{
	if (ulControl == CCID_IOCTL_GET_FEATURE_REQUEST)
	{
		unsigned char tucFeatures[] = {0x06, 0x04, 0x00, 0x31, 0x32, 0x33, 0x07, 0x04, 0x00 ,0x31, 0x32, 0x33};
		return CByteArray(tucFeatures, sizeof(tucFeatures));
	}

	SCR_Card xCard = {
		hCard,
		tcsLangs[m_iLangIdx],
		{NULL, 0},
		NULL
	};
	unsigned char tucStatus[2];
	long lRet = SCARD_F_INTERNAL_ERROR;

	if (ucOperation == EIDMW_PP_OP_VERIFY)
	{
		SCR_PinUsage xPinUsage = {
			ucPintype == EIDMW_PP_TYPE_SIGN ? SCR_USAGE_SIGN: SCR_USAGE_AUTH,
			ucPintype == EIDMW_PP_TYPE_SIGN ? "SIG" : "AUT",
			ucPintype == EIDMW_PP_TYPE_SIGN ? tcsUsageSig[m_iLangIdx] : tcsUsageAuth[m_iLangIdx]
		};

		lRet = m_pVerifyPin(&xCard, oCmd.GetByte(22), &xPinUsage, &xApp, tucStatus);
	}
	else if (ucOperation == EIDMW_PP_OP_CHANGE)
	{
		lRet = m_pChangePin(&xCard, oCmd.GetByte(27), &xApp, tucStatus);	
	}
	else
		throw CMWEXCEPTION(EIDMW_ERR_PIN_OPERATION);

	CByteArray oResp(2);
	switch(lRet)
	{
	case SCARD_S_SUCCESS:
		if (tucStatus[0] == 0xEC && tucStatus[1] == 0xD2)
			oResp.Append(tucErrTimeout, sizeof(tucErrTimeout));
		else if (tucStatus[0] == 0xEC && tucStatus[1] == 0xD6)
			oResp.Append(tucErrCancel, sizeof(tucErrCancel));
		else
			oResp.Append(tucStatus, 2);
		break;
	case SCARD_E_CANCELLED:
		oResp.Append(tucErrCancel, sizeof(tucErrCancel));
		break;
	case SCARD_W_REMOVED_CARD:
		throw CMWEXCEPTION(EIDMW_ERR_NO_CARD);
		break;
	case SCR_I_PIN_CHECK_FAILED:
		oResp.Append(tucErrPinsDiffer, sizeof(tucErrPinsDiffer));
		break;
	default:
		oResp.Append(tucErrGeneral, sizeof(tucErrGeneral));
	}

	return oResp;
}
예제 #8
0
파일: beidcard.cpp 프로젝트: taktik/eid-mw
CCard *BeidCardGetInstance(unsigned long ulVersion, const char *csReader,
	SCARDHANDLE hCard, CContext *poContext, CPinpad *poPinpad)
{
	CCard *poCard = NULL;

	if ((ulVersion % 100) == (PLUGIN_VERSION % 100))
	{
		unsigned long ulLockCount = 1;
		try {
			bool bNeedToSelectApplet = false;
			CByteArray oData;
			CByteArray oCmd(40);
			unsigned char tucSelectApp[] = {0x00, 0xA4, 0x04, 0x0C};
			oCmd.Append(tucSelectApp, sizeof(tucSelectApp));
			oCmd.Append((unsigned char) sizeof(BELPIC_AID));
			oCmd.Append(BELPIC_AID, sizeof(BELPIC_AID));
			long lRetVal;
			// Don't remove these brackets, CAutoLock dtor must be called!
			//{
			//don't use autolock when card might be reset
				//CAutoLock oAutLock(&poContext->m_oPCSC, hCard);
				
				poContext->m_oPCSC.BeginTransaction(hCard);
				oData = poContext->m_oPCSC.Transmit(hCard, oCmd, &lRetVal);
				if (lRetVal == SCARD_E_COMM_DATA_LOST || lRetVal == SCARD_E_NOT_TRANSACTED)
				{
					poContext->m_oPCSC.Recover(hCard, &ulLockCount);
					
					bNeedToSelectApplet = BeidCardSelectApplet(poContext, hCard);
					if (bNeedToSelectApplet)// try again to select the belpic app
						oData = poContext->m_oPCSC.Transmit(hCard, oCmd,&lRetVal);
				}
				if (oData.Size() == 2 && oData.GetByte(0) == 0x6A &&
					(oData.GetByte(1) == 0x82 || oData.GetByte(1) == 0x86))
				{
					// Perhaps the applet is no longer selected; so try to select it
					// first; and if successfull then try to select the Belpic AID again
					bNeedToSelectApplet = BeidCardSelectApplet(poContext, hCard);
					if (bNeedToSelectApplet)
						oData = poContext->m_oPCSC.Transmit(hCard, oCmd,&lRetVal);
				}

				bool bIsBeidCard = oData.Size() == 2 && oData.GetByte(0) == 0x90 && oData.GetByte(1) == 0x00;

				if (bIsBeidCard)
					poCard = new CBeidCard(hCard, poContext, poPinpad, oData,
					bNeedToSelectApplet ? ALW_SELECT_APPLET : TRY_SELECT_APPLET);
#ifdef __APPLE__
				else {
					// On Mac, if an unknown asynchronous card is inserted,
					// we don't return NULL but a CUnknownCard instance.
					// Reason: if we return NULL then the SISCardPlugin who
					// will be consulted next in card of a ACR38U reader
					// causes the reader/driver to get in a strange state
					// (if no SIS card is present) and if then a CUnknownCard
					// is instantiated, it will throw an exception if e.g.
					// SCardStatus() is called.
					// Remark: this trick won't work if synchronous card
					// (other then the SIS card is inserted).
					if(ulLockCount)
					{
						poContext->m_oPCSC.EndTransaction(hCard);
					}
					return new CUnknownCard(hCard, poContext, poPinpad, CByteArray());
				}
#endif
			//}
			if(ulLockCount)
			{
				poContext->m_oPCSC.EndTransaction(hCard);
			}
		}
		catch(...)
		{
			if(ulLockCount)
			{
				poContext->m_oPCSC.EndTransaction(hCard);
			}
			//printf("Exception in cardPluginBeid.CardGetInstance()\n");
		}
	}

	return poCard;
}
예제 #9
0
파일: beidcard.cpp 프로젝트: taktik/eid-mw
CByteArray CBeidCard::Ctrl(long ctrl, const CByteArray & oCmdData)
{
	CAutoLock oAutoLock(this);

	switch(ctrl)
    {
    case CTRL_BEID_GETCARDDATA:
        return m_oCardData;
    case CTRL_BEID_GETSIGNEDCARDDATA:
		if (m_ucAppletVersion < 0x17)
			throw CMWEXCEPTION(EIDMW_ERR_NOT_SUPPORTED);
		else
		{
			if (m_selectAppletMode == ALW_SELECT_APPLET)
				SelectApplet();
			m_ucCLA = 0x80;
			CByteArray oRet = SendAPDU(0xE4, 0x02, 0x00, 0x9C);
			m_ucCLA = 0;
			getSW12(oRet, 0x9000);
			oRet.Chop(2);
			return oRet;
		}
    case CTRL_BEID_GETSIGNEDPINSTATUS:
		// oCmdData must contain:
		// - the pin reference (1 byte)
		if (m_ucAppletVersion < 0x17)
			throw CMWEXCEPTION(EIDMW_ERR_NOT_SUPPORTED);
		else
		{
			if (m_selectAppletMode == ALW_SELECT_APPLET)
				SelectApplet();
			unsigned char ucPinRef = oCmdData.GetByte(0);
			m_ucCLA = 0x80;
			CByteArray oRet = SendAPDU(0xEA, 0x02, ucPinRef, 0x81);
			m_ucCLA = 0;
			if (ShouldSelectApplet(0xEA, getSW12(oRet)))
			{
				if (SelectApplet())
				{
					m_selectAppletMode = ALW_SELECT_APPLET;
					m_ucCLA = 0x80;
					CByteArray oRet = SendAPDU(0xEA, 0x02, ucPinRef, 0x81);
					m_ucCLA = 0;
				}
			}
			getSW12(oRet, 0x9000);
			oRet.Chop(2);
			return oRet;
		}
	case CTRL_BEID_INTERNAL_AUTH:
		// oCmdData must contain:
		// - the key reference (1 byte)
		// - the challenge to be signed (20 bytes)
		if (oCmdData.Size() != 21)
			throw CMWEXCEPTION(EIDMW_ERR_PARAM_BAD);
		else
		{
			if (m_selectAppletMode == ALW_SELECT_APPLET)
				SelectApplet();
			unsigned char ucKeyRef = oCmdData.GetByte(0);
			CByteArray oData(22);
			oData.Append(0x94);
			oData.Append(0x14);
			oData.Append(oCmdData.GetBytes() + 1, 20);
			CByteArray oRet = SendAPDU(0x88, 0x02, ucKeyRef, oData);
			if (ShouldSelectApplet(0x88, getSW12(oRet)))
			{
				if (SelectApplet())
				{
					m_selectAppletMode = ALW_SELECT_APPLET;
					CByteArray oRet = SendAPDU(0x88, 0x02, ucKeyRef, oData);
				}
			}
			getSW12(oRet, 0x9000);
			oRet.Chop(2);
			return oRet;
		}
    default:
        MWLOG(LEV_WARN, MOD_CAL, L"Ctrl(): Unknown CRTL code %d (0x%0x) specified", ctrl, ctrl);
		throw CMWEXCEPTION(EIDMW_ERR_PARAM_BAD);
    }
}