Exemplo n.º 1
0
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());
}
Exemplo n.º 2
0
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());
}
Exemplo n.º 3
0
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		
	}
Exemplo n.º 5
0
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());
}
Exemplo n.º 6
0
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());
}
Exemplo n.º 7
0
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());
}
Exemplo n.º 8
0
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());
}
Exemplo n.º 9
0
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());
}
Exemplo n.º 10
0
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());
}
Exemplo n.º 11
0
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());
}
Exemplo n.º 12
0
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());
}
Exemplo n.º 13
0
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());
}
Exemplo n.º 14
0
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