bool CPkiCard::AskPinRetry(tPinOperation operation, const tPin & Pin, unsigned long ulRemaining, const tPrivKey *pKey) { bool bRetry = false; bool bUsePinpad = m_poPinpad->UsePinpad(operation); // Bad PIN: show a dialog to ask the user to try again // PIN blocked: show a dialog to tell the user if (!bUsePinpad) { DlgPinUsage usage = PinUsage2Dlg(Pin, pKey); DlgRet dlgret = DlgBadPin(usage, utilStringWiden(Pin.csLabel).c_str(), ulRemaining); if (0 != ulRemaining && DLG_RETRY == dlgret) bRetry = true; } return bRetry; }
unsigned char CPkiCard::PinUsage2Pinpad(const tPin & Pin, const tPrivKey *pKey) { DlgPinUsage dlgUsage = PinUsage2Dlg(Pin, pKey); unsigned char ucPinpadUsage = EIDMW_PP_TYPE_UNKNOWN; switch(dlgUsage) { case DLG_PIN_AUTH: ucPinpadUsage = EIDMW_PP_TYPE_AUTH; break; case DLG_PIN_SIGN: ucPinpadUsage = EIDMW_PP_TYPE_SIGN; break; case DLG_PIN_ADDRESS: ucPinpadUsage = EIDMW_PP_TYPE_ADDR; break; default: break; } return ucPinpadUsage; }
bool CPkiCard::PinCmd(tPinOperation operation, const tPin & Pin, const std::string & csPin1, const std::string & csPin2, unsigned long & ulRemaining, const tPrivKey *pKey) { // No standard for Logoff, so each card has to implement // it's own command here. if (operation == PIN_OP_LOGOFF ) return LogOff(Pin); bool bRet = false; std::string csReadPin1, csReadPin2; const std::string *pcsPin1 = &csPin1; const std::string *pcsPin2 = &csPin2; bool bAskPIN = csPin1.empty(); bool bUsePinpad = bAskPIN ? m_poPinpad->UsePinpad(operation) : false; bad_pin: //If no Pin(s) provided and it's no Pinpad reader -> ask Pins if (bAskPIN && !bUsePinpad) { showPinDialog(operation, Pin, csReadPin1, csReadPin2, pKey); pcsPin1 = &csReadPin1; pcsPin2 = &csReadPin2; } CByteArray oPinBuf = MakePinBuf(Pin, *pcsPin1, bUsePinpad); if (operation != PIN_OP_VERIFY) oPinBuf.Append(MakePinBuf(Pin, *pcsPin2, bUsePinpad)); CByteArray oAPDU = MakePinCmd(operation, Pin); // add CLA, INS, P1, P2 oAPDU.Append((unsigned char) oPinBuf.Size()); // add P3 oAPDU.Append(oPinBuf); CByteArray oResp; bool bSelected = false; // Don't remove these brackets!! { CAutoLock autolock(this); // Select the path where the Pin is, if necessary if (!Pin.csPath.empty() && !bSelected && Pin.csPath != "3F00") { SelectFile(Pin.csPath); bSelected = true; } // Send the command if (csPin1.empty() && bUsePinpad) oResp = m_poPinpad->PinCmd(operation, Pin, PinUsage2Pinpad(Pin, pKey), oAPDU, ulRemaining); else oResp = SendAPDU(oAPDU); } unsigned long ulSW12 = getSW12(oResp); if (ulSW12 == 0x9000) bRet = true; else if (ulSW12 == 0x6983) ulRemaining = 0; else if (ulSW12 / 16 == 0x63C) ulRemaining = ulSW12 % 16; else throw CMWEXCEPTION(m_poContext->m_oPCSC.SW12ToErr(ulSW12)); #ifndef NO_DIALOGS // Bad PIN: show a dialog to ask the user to try again // PIN blocked: show a dialog to tell the user if (bAskPIN && !bRet) { DlgPinUsage usage = PinUsage2Dlg(Pin, pKey); DlgRet dlgret = DlgBadPin(usage, utilStringWiden(Pin.csLabel).c_str(), ulRemaining); if (0 != ulRemaining && DLG_RETRY == dlgret) goto bad_pin; } #endif // If PIN command OK and no SSO, then state that we have now // verified this PIN, this info is needed in the Sign() method if (bRet && !m_poContext->m_bSSO) { bool bFound = false; for (size_t i = 0; i < m_verifiedPINs.size() && !bFound; i++) bFound = (m_verifiedPINs[i] == Pin.ulID); if (!bFound) m_verifiedPINs.push_back(Pin.ulID); } return bRet; }