std::string KeyStatusResponse( IINField iin, uint8_t seq, uint32_t ksq, uint16_t user, KeyWrapAlgorithm keyWrap, KeyStatus status, HMACType hmacType, const std::string& challenge, const std::string& hmac ) { Buffer buffer(DEFAULT_MAX_APDU_SIZE); APDUResponse apdu(buffer.GetWSlice()); apdu.SetControl(AppControlField(true, true, false, false, seq)); apdu.SetFunction(FunctionCode::AUTH_RESPONSE); apdu.SetIIN(iin); HexSequence challengeBuff(challenge); HexSequence hmacBuff(hmac); Group120Var5 rsp; rsp.keyChangeSeqNum = ksq; rsp.userNum = user; rsp.keyWrapAlgo = keyWrap; rsp.keyStatus = status; rsp.hmacAlgo = hmacType; rsp.challengeData = challengeBuff.ToRSlice(); rsp.hmacValue = hmacBuff.ToRSlice(); apdu.GetWriter().WriteFreeFormat(rsp); return ToHex(apdu.ToRSlice()); }
std::string ChallengeResponse( opendnp3::IINField iin, uint8_t seq, uint32_t csq, uint16_t user, HMACType hmacType, ChallengeReason reason, std::string challengeDataHex ) { Buffer buffer(DEFAULT_MAX_APDU_SIZE); APDUResponse apdu(buffer.GetWSlice()); apdu.SetControl(AppControlField(true, true, false, false, seq)); apdu.SetFunction(FunctionCode::AUTH_RESPONSE); apdu.SetIIN(iin); HexSequence challengeBuff(challengeDataHex); Group120Var1 rsp( csq, user, hmacType, reason, challengeBuff.ToRSlice() ); apdu.GetWriter().WriteFreeFormat(rsp); return ToHex(apdu.ToRSlice()); }
std::string AuthErrorResponse( opendnp3::IINField iin, uint8_t appSeq, uint32_t challengeSeqNum, uint16_t user, uint16_t assocId, opendnp3::AuthErrorCode code, opendnp3::DNPTime timestamp, std::string hexErrorText) { Buffer buffer(DEFAULT_MAX_APDU_SIZE); APDUResponse apdu(buffer.GetWSlice()); apdu.SetControl(AppControlField(true, true, false, false, appSeq)); apdu.SetFunction(FunctionCode::AUTH_RESPONSE); apdu.SetIIN(iin); HexSequence hexErrorTextBuff(hexErrorText); Group120Var7 error( challengeSeqNum, user, assocId, code, timestamp, hexErrorTextBuff.ToRSlice() ); apdu.GetWriter().WriteFreeFormat(error); return ToHex(apdu.ToRSlice()); }
/** * @SYMTestCaseID BA-CTSYD-DIS-SIM-NEGATIVE-UN0016 * @SYMComponent telephony_ctsy * @SYMTestCaseDesc Test handing in CTSY dispatch when the SendAPDUReq API is disabled * @SYMTestPriority High * @SYMTestActions Disable API, call API, check correct error returned * @SYMTestExpectedResults Pass * @SYMTestType CT */ void CCTsySimFUNegative::TestSendAPDUReqL() { TConfig config; config.SetSupportedValue(MLtsyDispatchSimSendApduRequest::KLtsyDispatchSimSendApduRequestApiId, EFalse); config.PushL(); OpenEtelServerL(EUseExtendedError); CleanupStack::PushL(TCleanupItem(Cleanup,this)); OpenPhoneL(); RMmCustomAPI customApi; OpenCustomApiLC(customApi); TBuf8<3> info; info.Append(1); info.Append(1); info.Append(1); RBuf8 dataBuf; CleanupClosePushL(dataBuf); _LIT8(KApduDataExp,"APDU DATA EXP "); dataBuf.CreateL(KApduDataExp); RMmCustomAPI::TApdu apdu(info,dataBuf); TRequestStatus status; customApi.SendAPDUReq(status, apdu); User::WaitForRequest(status); ASSERT_EQUALS(status.Int(), KErrNotSupported); AssertMockLtsyStatusL(); config.Reset(); CleanupStack::PopAndDestroy(4, &config); // dataBuf, customApi, this, config }
std::string Confirm(uint8_t seq, bool unsol) { Buffer buffer(DEFAULT_MAX_APDU_SIZE); APDURequest apdu(buffer.GetWSlice()); apdu.SetControl(AppControlField(true, true, false, unsol, seq)); apdu.SetFunction(FunctionCode::CONFIRM); return ToHex(apdu.ToRSlice()); }
std::string RequestKeyStatus(uint8_t seq, uint16_t user) { Buffer buffer(DEFAULT_MAX_APDU_SIZE); APDURequest apdu(buffer.GetWSlice()); apdu.SetControl(AppControlField(true, true, false, false, seq)); apdu.SetFunction(FunctionCode::AUTH_REQUEST); Group120Var4 status; status.userNum = user; apdu.GetWriter().WriteSingleValue<UInt8>(QualifierCode::UINT8_CNT, status); return ToHex(apdu.ToRSlice()); }
std::string FinishUpdateKeyChangeResponse( uint8_t seq, const std::string& hmac ) { Buffer buffer(DEFAULT_MAX_APDU_SIZE); APDUResponse apdu(buffer.GetWSlice()); apdu.SetControl(AppControlField(true, true, false, false, seq)); apdu.SetFunction(FunctionCode::AUTH_RESPONSE); apdu.SetIIN(IINBit::DEVICE_RESTART); HexSequence hmacBuffer(hmac); apdu.GetWriter().WriteFreeFormat(Group120Var15(hmacBuffer.ToRSlice())); return ToHex(apdu.ToRSlice()); }
std::string BeginUpdateKeyChangeResponse( uint8_t seq, uint32_t ksq, uint16_t user, const std::string& outstationChallenge ) { Buffer buffer(DEFAULT_MAX_APDU_SIZE); APDUResponse apdu(buffer.GetWSlice()); apdu.SetControl(AppControlField(true, true, false, false, seq)); apdu.SetFunction(FunctionCode::AUTH_RESPONSE); apdu.SetIIN(IINBit::DEVICE_RESTART); HexSequence challenge(outstationChallenge); apdu.GetWriter().WriteFreeFormat(Group120Var12(ksq, user, challenge)); return ToHex(apdu.ToRSlice()); }
std::string BeginUpdateKeyChangeRequest( uint8_t seq, opendnp3::KeyChangeMethod method, const std::string& username, const std::string& masterChallenge ) { Buffer buffer(DEFAULT_MAX_APDU_SIZE); APDURequest apdu(buffer.GetWSlice()); apdu.SetControl(AppControlField(true, true, false, false, seq)); apdu.SetFunction(FunctionCode::AUTH_REQUEST); RSlice name(reinterpret_cast<const uint8_t*>(username.c_str()), static_cast<uint32_t>(username.size())); HexSequence challenge(masterChallenge); apdu.GetWriter().WriteFreeFormat(Group120Var11(method, name, challenge)); return ToHex(apdu.ToRSlice()); }
std::string ChallengeReply( uint8_t appSeq, uint32_t challengeSeqNum, uint16_t userNum, std::string hmacHex ) { Buffer buffer(DEFAULT_MAX_APDU_SIZE); APDURequest apdu(buffer.GetWSlice()); apdu.SetControl(AppControlField(true, true, false, false, appSeq)); apdu.SetFunction(FunctionCode::AUTH_REQUEST); HexSequence hmacBuff(hmacHex); Group120Var2 rsp(challengeSeqNum, userNum, hmacBuff.ToRSlice()); apdu.GetWriter().WriteFreeFormat(rsp); return ToHex(apdu.ToRSlice()); }
std::string FinishUpdateKeyChangeRequest( uint8_t seq, uint32_t ksq, uint16_t user, const std::string& encryptedData, const std::string& hmac ) { Buffer buffer(DEFAULT_MAX_APDU_SIZE); APDURequest apdu(buffer.GetWSlice()); apdu.SetControl(AppControlField(true, true, false, false, seq)); apdu.SetFunction(FunctionCode::AUTH_REQUEST); HexSequence encryptedBuffer(encryptedData); HexSequence hmacBuffer(hmac); auto writer = apdu.GetWriter(); writer.WriteFreeFormat(Group120Var13(ksq, user, encryptedBuffer.ToRSlice())); writer.WriteFreeFormat(Group120Var15(hmacBuffer.ToRSlice())); return ToHex(apdu.ToRSlice()); }
std::string KeyChangeRequest( uint8_t seq, uint32_t ksq, uint16_t user, const std::string& keyWrapData ) { Buffer buffer(DEFAULT_MAX_APDU_SIZE); APDURequest apdu(buffer.GetWSlice()); apdu.SetControl(AppControlField(true, true, false, false, seq)); apdu.SetFunction(FunctionCode::AUTH_REQUEST); HexSequence keyBuffer(keyWrapData); Group120Var6 rsp; rsp.keyChangeSeqNum = ksq; rsp.userNum = user; rsp.keyWrapData = keyBuffer.ToRSlice(); apdu.GetWriter().WriteFreeFormat(rsp); return ToHex(apdu.ToRSlice()); }
std::string UserStatusChangeRequest( uint8_t seq, opendnp3::KeyChangeMethod keyChangeMethod, opendnp3::UserOperation userOperation, uint32_t statusChangeSeqNum, uint16_t userRole, uint16_t userRoleExpDays, const std::string& userName, const std::string& userPublicKeyHex, const std::string& certificationDataHex ) { Buffer buffer(DEFAULT_MAX_APDU_SIZE); APDURequest apdu(buffer.GetWSlice()); apdu.SetControl(AppControlField(true, true, false, false, seq)); apdu.SetFunction(FunctionCode::AUTH_REQUEST); RSlice name(reinterpret_cast<const uint8_t*>(userName.c_str()), static_cast<uint32_t>(userName.size())); HexSequence userPublicKeyBuffer(userPublicKeyHex); HexSequence certificationDataBuffer(certificationDataHex); Group120Var10 statusChange( keyChangeMethod, userOperation, statusChangeSeqNum, userRole, userRoleExpDays, name, userPublicKeyBuffer.ToRSlice(), certificationDataBuffer.ToRSlice() ); apdu.GetWriter().WriteFreeFormat(statusChange); return ToHex(apdu.ToRSlice()); }
PCSC::PCSC( std::string& a_stInputReaderName, u2& a_u2PortNumber, std::string& a_stURI, u4& a_NameSpaceHivecode, u2& a_TypeHivecode, u4& a_Index ) { Log::begin( "PCSC::PCSC" ); m_bDoTransact = true; std::string stIdentifiedReaderName = ""; LPTSTR pReaderList = NULL; if( a_stInputReaderName.empty( ) ) { a_stInputReaderName = "selfdiscover"; } m_hContextPCSC = 0; m_hCardPCSC = 0; LONG lReturn = SCardEstablishContext( 0, NULL, NULL, &m_hContextPCSC ); if( SCARD_S_SUCCESS != lReturn ) { std::string msg = ""; Log::toString( msg, "SCardEstablishContext <%#02x>", lReturn ); Log::error( "PCSC::PCSC", msg.c_str( ) ); throw RemotingException((lpCharPtr)"PCSC: SCardEstablishContext error",lReturn); } // self-discovery mechanism #ifdef WIN32 if (_stricmp("selfdiscover", a_stInputReaderName.c_str()) == 0) { #else if (strncasecmp("selfdiscover", a_stInputReaderName.c_str(),a_stInputReaderName.length()) == 0) { #endif // In Windows SCARD_AUTOALLOCATE (-1) as a value of readerListChatLength // would signal the SCardListReaders to determine the size of reader string // This is not available in Linux so we call the SCardListReaders twice. First // to get the length and then the reader names. #ifdef WIN32 DWORD readerListCharLength = SCARD_AUTOALLOCATE; lReturn = SCardListReaders( m_hContextPCSC, NULL, (LPTSTR)&pReaderList, &readerListCharLength); #else DWORD readerListCharLength = 0; lReturn = SCardListReaders(m_hContextPCSC,NULL,NULL,&readerListCharLength); if(lReturn != SCARD_S_SUCCESS) throw RemotingException((lpCharPtr)"PCSC: SCardListReaders error",lReturn); pReaderList = (lpCharPtr)malloc(sizeof(char)*readerListCharLength); lReturn = SCardListReaders(m_hContextPCSC, NULL,pReaderList, &readerListCharLength); #endif if(lReturn != SCARD_S_SUCCESS) { std::string msg = ""; Log::toString( msg, "SCardListReaders <%#02x>", lReturn ); Log::error( "PCSC::PCSC", msg.c_str( ) ); throw RemotingException((lpCharPtr)"PCSC: SCardListReaders error",lReturn); } else { u4 count = 0; u1 foundReader = FALSE; SCARDHANDLE finalCardHandle = 0; try { lpTCharPtr pReader = pReaderList; while ('\0' != *pReader ) { size_t readerNameLen = strlen((const char*)pReader); SCARD_READERSTATE readerStates[1]; readerStates[0].dwCurrentState = SCARD_STATE_UNAWARE; readerStates[0].szReader = pReader; if ( SCardGetStatusChange( m_hContextPCSC, 0, readerStates, 1) == SCARD_S_SUCCESS) { if ((readerStates[0].dwEventState & SCARD_STATE_PRESENT) == SCARD_STATE_PRESENT) { // we found a card in this reader stIdentifiedReaderName = pReader; DWORD activeProtocol; lReturn = SCardConnect( m_hContextPCSC, (LPTSTR)stIdentifiedReaderName.c_str(), SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0, &m_hCardPCSC, &activeProtocol); if (lReturn == SCARD_S_SUCCESS) { // try to identify if we're dealing with a .NetCard u1 answerData[258]; DWORD answerLen = 258; Log::log( "PCSC::PCSC SCardTransmit..." ); lReturn = SCardTransmit( m_hCardPCSC, SCARD_PCI_T0, isNetCardAPDU, sizeof(isNetCardAPDU), NULL, (LPBYTE)answerData, &answerLen); Log::log( "PCSC::PCSC - SCardTransmit <%#02x>", lReturn ); if (lReturn == SCARD_S_SUCCESS) { u1 rethrowException = FALSE; try { if (answerData[answerLen - 2] == 0x61) { if (answerData[answerLen - 1] > 10) { u1Array invokeAPDU(0); invokeAPDU += (u1)0xD8; invokeAPDU += (u2)CARDMANAGER_SERVICE_PORT; invokeAPDU += (u1)0x6F; invokeAPDU += (u4)HIVECODE_NAMESPACE_SMARTCARD; invokeAPDU += (u2)HIVECODE_TYPE_SMARTCARD_CONTENTMANAGER; invokeAPDU += (u2)HIVECODE_METHOD_SMARTCARD_CONTENTMANAGER_GETASSOCIATEDPORT; std::string* cmServicem_stURI = new std::string(CARDMANAGER_SERVICE_NAME); invokeAPDU.Append(cmServicem_stURI); delete cmServicem_stURI; invokeAPDU += (u4)a_NameSpaceHivecode; invokeAPDU += (u2)a_TypeHivecode; invokeAPDU.Append(&a_stURI); // construct call if(invokeAPDU.GetLength() <= (s4)APDU_TO_CARD_MAX_SIZE) { u1Array apdu(5); apdu.GetBuffer()[0] = 0x80; apdu.GetBuffer()[1] = 0xC2; apdu.GetBuffer()[2] = 0x00; apdu.GetBuffer()[3] = 0x00; apdu.GetBuffer()[4] = (u1)invokeAPDU.GetLength(); apdu += invokeAPDU; u1Array answer(0); Log::log( "PCSC::PCSC - ExchangeData..." ); exchangeData(apdu, answer); Log::log( "PCSC::PCSC - ExchangeData ok" ); Log::log( "PCSC::PCSC - CheckForException..." ); u4 protocolOffset = m_MarshallerUtil.CheckForException(answer, HIVECODE_NAMESPACE_SYSTEM, HIVECODE_TYPE_SYSTEM_INT32); Log::log( "PCSC::PCSC - CheckForException ok" ); u4 discoveredPortNumber = m_MarshallerUtil.ComReadU4At(answer, protocolOffset); if ((a_u2PortNumber == 0) || (discoveredPortNumber == a_u2PortNumber)) { a_u2PortNumber = (u2)discoveredPortNumber; if (foundReader == TRUE) { if (a_Index == 0) { // this is the second reader/card/app that matches - we error at this point rethrowException = TRUE; std::string errorMessage( "At least 2 cards posses \""); errorMessage += a_stURI.c_str( ); errorMessage += "\" service\r\nRemove conflicting cards from your system"; Log::error( "PCSC::PCSC", errorMessage.c_str( ) ); throw RemotingException(errorMessage); } } foundReader = TRUE; finalCardHandle = m_hCardPCSC; // Advance to the next value. count++; if (count == a_Index) { // we enumerate one by one the valid readers - so stop here break; } pReader = (lpTCharPtr)((lpTCharPtr)pReader + readerNameLen + 1); continue; } } } } } catch (...) { if (rethrowException == TRUE) { throw; } else { // swallow exception } } SCardDisconnect( m_hCardPCSC, SCARD_LEAVE_CARD); m_hCardPCSC = 0; } // this is not a .NetCard, or the service was not found - let's try another reader/card else { Log::error( "PCSC::PCSC", "SCardTransmit failed" ); } } else { Log::error( "PCSC::PCSC", "SCardConnect failed" ); } } else { Log::error( "PCSC::PCSC", "SCARD_STATE_PRESENT not present" ); } } else { Log::error( "PCSC::PCSC", "SCardGetStatusChange != SCARD_S_SUCCESS" ); } // Advance to the next value. pReader = (lpTCharPtr)((lpTCharPtr)pReader + readerNameLen + 1); } } catch (...) { stIdentifiedReaderName = ""; #ifdef WIN32 /*lReturn = */SCardFreeMemory( m_hContextPCSC, pReaderList); /*if(lReturn != SCARD_S_SUCCESS) { throw RemotingException((lpCharPtr)"PCSC: SCardFreeMemory error",lReturn); }*/ #else if( pReaderList ) { free(pReaderList); } #endif throw; } // have we found anything ? if( !foundReader) { stIdentifiedReaderName = ""; #ifdef WIN32 /*lReturn = */SCardFreeMemory( m_hContextPCSC, pReaderList); //if(lReturn != SCARD_S_SUCCESS) { // throw RemotingException((lpCharPtr)"PCSC: SCardFreeMemory error",lReturn); //} #else if(pReaderList ) { free(pReaderList); } #endif throw RemotingException((lpCharPtr)"Could not find any .NET smart card", SCARD_E_NO_SMARTCARD ); } m_hCardPCSC = finalCardHandle; } m_stReaderName = stIdentifiedReaderName; } else { m_stReaderName = a_stInputReaderName; } Log::end( "PCSC::PCSC" ); } /* */ void PCSC::exchangeData( u1Array &dataIn, u1Array &dataout ) { // check validity of handle if ( SCARD_S_SUCCESS != SCardIsValidContext( m_hContextPCSC ) ) { throw RemotingException( (lpCharPtr)"PCSC: Invalid handle", SCARD_E_INVALID_HANDLE ); } try { if( m_bDoTransact ) { beginTransaction( ); } unsigned char ucRetry = 0; do { ucRetry++; unsigned char answerData[ 258 ]; memset( answerData, 0, sizeof( answerData ) ); DWORD answerLen = sizeof( answerData ); #ifdef __DEBUG_APDU__ Log::logCK_UTF8CHAR_PTR( "PCSC::ExchangeData - Command", dataIn.GetBuffer( ), dataIn.GetLength( ) ); Timer t; t.start( ); #endif LONG lReturn = SCardTransmit( m_hCardPCSC, SCARD_PCI_T0, dataIn.GetBuffer( ), dataIn.GetLength( ), NULL, (lpByte)answerData, &answerLen ); if( SCARD_S_SUCCESS != lReturn ) { std::string msg = ""; Log::toString( msg, "SCardTransmit <%#02x>", lReturn ); Log::error( "PCSC::ExchangeData", msg.c_str( ) ); } if( ( SCARD_W_REMOVED_CARD == lReturn ) || ( SCARD_W_RESET_CARD == lReturn ) ) { DWORD dwActiveProtocol = SCARD_PROTOCOL_T0; lReturn = SCardReconnect( m_hCardPCSC, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0, SCARD_LEAVE_CARD, &dwActiveProtocol ); if( SCARD_S_SUCCESS != lReturn ) { std::string msg = ""; Log::toString( msg, "SCardReconnect <%#02x>", lReturn ); Log::error( "PCSC::ExchangeData", msg.c_str( ) ); throw RemotingException( (lpCharPtr)"PCSC: SCardReconnect error", lReturn ); } lReturn = SCardTransmit( m_hCardPCSC, SCARD_PCI_T0, dataIn.GetBuffer( ), dataIn.GetLength( ), NULL, (lpByte)answerData, &answerLen ); if( SCARD_S_SUCCESS != lReturn ) { Log::log( "PCSC::ExchangeData - SCardTransmit <%#02x>", lReturn ); } } else if( SCARD_S_SUCCESS != lReturn ) { std::string s; Log::toString( s, "SCardTransmit failed <%#02x>", lReturn ); Log::error( "PCSC::ExchangeData", s.c_str( ) ); throw RemotingException( (lpCharPtr)"PCSC: SCardTransmit error", lReturn ); } if (answerLen < 2) { Log::error( "PCSC::ExchangeData", "Incorrect length returned" ); throw RemotingException((lpCharPtr)"PCSC: SCardTransmit error - Incorrect length returned",SCARD_F_COMM_ERROR); } if (answerLen > 2) { u1Array temp(answerLen - 2); temp.SetBuffer(answerData); dataout += temp; } u1 sw1 = answerData[answerLen - 2]; u1 sw2 = answerData[answerLen - 1]; #ifdef __DEBUG_APDU__ Log::log( "PCSC::ExchangeData - Status (1) <%02x%02x>", sw1, sw2 ); Log::logCK_UTF8CHAR_PTR( "PCSC::ExchangeData - Response", answerData, answerLen ); t.stop( "PCSC::ExchangeData - Response" ); #endif while( (sw1 == 0x61 ) || ( sw1 == 0x9F ) ) { memset( answerData, 0, sizeof( answerData ) ); unsigned char GetResponse[ 5 ]; memset( GetResponse, 0, sizeof( GetResponse ) ); if (sw1 == 0x9F) { GetResponse[0] = 0xA0; } else { GetResponse[0] = 0x00; } GetResponse[1] = 0xC0; GetResponse[2] = 0x00; GetResponse[3] = 0x00; GetResponse[4] = sw2; answerLen = 258; #ifdef __DEBUG_APDU__ Log::logCK_UTF8CHAR_PTR( "PCSC::ExchangeData - Command", GetResponse, sizeof( GetResponse ) ); t.start( ); #endif lReturn = SCardTransmit( m_hCardPCSC, SCARD_PCI_T0, (lpCByte)GetResponse, 5, NULL, (lpByte)answerData, &answerLen ); if( ( SCARD_W_REMOVED_CARD == lReturn ) || ( SCARD_W_RESET_CARD == lReturn ) ) { DWORD dwActiveProtocol = SCARD_PROTOCOL_T0; lReturn = SCardReconnect( m_hCardPCSC, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0, SCARD_LEAVE_CARD, &dwActiveProtocol ); lReturn = SCardTransmit( m_hCardPCSC, SCARD_PCI_T0, (lpCByte)GetResponse, 5, NULL, (lpByte)answerData, &answerLen ); } else if( SCARD_S_SUCCESS != lReturn ) { std::string s; Log::toString( s, "SCardTransmit failed <%02x>", lReturn ); Log::error( "PCSC::ExchangeData", s.c_str( ) ); throw RemotingException( (lpCharPtr)"PCSC: SCardTransmit error", lReturn ); } if( answerLen < 2 ) { Log::error( "PCSC::ExchangeData", "Incorrect length returned" ); throw RemotingException( (lpCharPtr)"PCSC: SCardTransmit error - Incorrect length returned", SCARD_F_COMM_ERROR ); } if( answerLen > 2 ) { u1Array temp( answerLen - 2 ); temp.SetBuffer( answerData ); dataout += temp; } sw1 = answerData[ answerLen - 2 ]; sw2 = answerData[ answerLen - 1 ]; #ifdef __DEBUG_APDU__ Log::log( "PCSC::ExchangeData - Status (2) <%02x%02x>", sw1, sw2 ); Log::logCK_UTF8CHAR_PTR( "PCSC::ExchangeData - Response", answerData, answerLen ); t.stop( "PCSC::ExchangeData - Response" ); #endif } // The response is not acceptable. We have to retry the data transmission if( ( 0x63 == sw1 ) || ( ( 0x69 == sw1 ) && ( 0x99 == sw2 ) ) ) { Log::log( "PCSC::ExchangeData - Invalid response. Retry" ); } else { break; } /* if( ( 0x90 == sw1 ) && ( 0x00 == sw2 ) ) { break; }*/ } while ( 3 > ucRetry ); } catch (...) { if( m_bDoTransact ) { endTransaction( ); } throw; } if( m_bDoTransact ) { endTransaction( ); } } /* Cleanup the context and card handle */ PCSC::~PCSC( ) { if( m_hCardPCSC ) { SCardDisconnect( m_hCardPCSC, SCARD_LEAVE_CARD ); m_hCardPCSC = 0; } if( m_hContextPCSC ) { SCardReleaseContext( m_hContextPCSC ); m_hContextPCSC = 0; } } MARSHALLER_NS_END