CByteArray CBeidCard::SignInternal(const tPrivKey & key, unsigned long algo, const CByteArray & oData, const tPin *pPin) { CAutoLock autolock(this); // For V1.7 cards, the Belpic dir has to be selected if (m_ucAppletVersion >= 0x17) SelectFile(key.csPath); else if (m_selectAppletMode == ALW_SELECT_APPLET) SelectApplet(); SetSecurityEnv(key, algo, oData.Size()); // Pretty unique for smart cards: first MSE SET, then verify PIN // (needed for the nonrep key/pin, but also usable for the auth key/pin) if (pPin != NULL) { //unsigned long ulRemaining = 0; bool bOK = PinCmd(PIN_OP_VERIFY, *pPin, "", "", m_ulRemaining, &key); if (!bOK) throw CMWEXCEPTION(m_ulRemaining == 0 ? EIDMW_ERR_PIN_BLOCKED : EIDMW_ERR_PIN_BAD); } // PSO: Compute Digital Signature CByteArray oResp = SendAPDU(0x2A, 0x9E, 0x9A, oData); unsigned long ulSW12 = getSW12(oResp); if (ulSW12 != 0x9000) throw CMWEXCEPTION(m_poContext->m_oPCSC.SW12ToErr(ulSW12)); // Remove SW1-SW2 from the response oResp.Chop(2); return oResp; }
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; }
static CByteArray ReadInternal(CPCSC *poPCSC, SCARDHANDLE hCard, unsigned long ulOffset, unsigned long ulMaxLen) { unsigned long ulLen = ulMaxLen > 252 ? 252 : ulMaxLen; long lretVal = 0; unsigned char tucReadDat[5] = {0xFF, 0xB2}; tucReadDat[2] = (unsigned char)(ulOffset/256); tucReadDat[3] = (unsigned char)(ulOffset%256); tucReadDat[4] = (unsigned char)(ulLen); CByteArray oCmd(tucReadDat, sizeof(tucReadDat)); CByteArray oData = poPCSC->Transmit(hCard, oCmd, &lretVal); oData.Chop(2); // remove SW12 // If we read enough, or there isn't more to read, return if (ulMaxLen == ulLen || oData.Size() < ulLen) { MWLOG(LEV_INFO, MOD_CAL, L" Read %d bytes from the SIS card", oData.Size()); return oData; } ulLen = oData.Size(); ulOffset += ulLen; ulMaxLen -= ulLen; ulLen = ulMaxLen > 252 ? 252 : ulMaxLen; tucReadDat[2] = (unsigned char)(ulOffset/256); tucReadDat[3] = (unsigned char)(ulOffset%256); tucReadDat[4] = (unsigned char)(ulLen); oCmd = CByteArray(tucReadDat, sizeof(tucReadDat)); CByteArray oData2 = poPCSC->Transmit(hCard, oCmd,&lretVal); oData2.Chop(2); // remove SW12 oData.Append(oData2); MWLOG(LEV_INFO, MOD_CAL, L" Read %d bytes from the SIS card", oData.Size()); return oData; }
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); } }