diff -r 000000000000 -r 164170e6151a wim/WimServer/src/WimSignTextHandler.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wim/WimServer/src/WimSignTextHandler.cpp Tue Jan 26 15:20:08 2010 +0200 @@ -0,0 +1,581 @@ +/* +* Copyright (c) 2003 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: Services for Sign Text operation +* +*/ + + + +// INCLUDE FILES +#include "WimServer.h" +#include "Wimi.h" // WIMI definitions +#include "WimClsv.h" +#include "WimSignTextHandler.h" +#include "WimSecurityDlgHandler.h" +#include "WimCallbackImpl.h" +#include "WimTrace.h" +#include "WimCleanup.h" +#include + +#ifdef _DEBUG +_LIT( KWimSignTextPanic, "WimSignText" ); +#endif + +//In secdlg.h Maxlength is defined as 32, which disobeies WIM standard. +//According to WIM standard Pin length should be 4~8 +const TInt KWIMMaxPINLength = 8; +// ============================ MEMBER FUNCTIONS =============================== + +// ----------------------------------------------------------------------------- +// CWimSignTextHandler::CWimSignTextHandler +// C++ default constructor can NOT contain any code, that +// might leave. +// ----------------------------------------------------------------------------- +// +CWimSignTextHandler::CWimSignTextHandler() : CActive( EPriorityStandard ) + { + _WIMTRACE(_L("WIM | WIMServer | CWimSignTextHandler::CWimSignTextHandler | Begin")); + } + +// ----------------------------------------------------------------------------- +// CWimSignTextHandler::ConstructL +// Symbian 2nd phase constructor can leave. +// ----------------------------------------------------------------------------- +// +void CWimSignTextHandler::ConstructL() + { + _WIMTRACE(_L("WIM | WIMServer | CWimSignTextHandler::ConstructL | Begin")); + CActiveScheduler::Add( this ); + iWimUtilFuncs = CWimUtilityFuncs::NewL(); + iWimSecDlg = CWimSecurityDlgHandler::NewL(); + } + +// ----------------------------------------------------------------------------- +// CWimAuthObjHandler::NewL +// Two-phased constructor. +// ----------------------------------------------------------------------------- +// +CWimSignTextHandler* CWimSignTextHandler::NewL() + { + _WIMTRACE(_L("WIM | WIMServer | CWimSignTextHandler::NewL | Begin")); + CWimSignTextHandler* self = new( ELeave ) CWimSignTextHandler; + CleanupStack::PushL( self ); + self->ConstructL(); + CleanupStack::Pop( self ); + return self; + } + +// Destructor +CWimSignTextHandler::~CWimSignTextHandler() + { + _WIMTRACE(_L("WIM | WIMServer | CWimSignTextHandler::~CWimAuthObjHandler | Begin")); + Cancel(); + CleanUp(); // frees iSigningDataBuf, iSigningDataPtr, and iKeyReference + delete iWimUtilFuncs; + delete iWimSecDlg; + // iResponseID and iTrId are deleted in callback functions + } + +// ----------------------------------------------------------------------------- +// CWimSignTextHandler::SignTextL +// Sign given text. Response is handled in CWimCallback if operation is given +// to card. Otherwise message is completed here with error value. +// ----------------------------------------------------------------------------- +// +void CWimSignTextHandler::SignTextL( const RMessage2& aMessage ) + { + _WIMTRACE(_L("WIM | WIMServer | CWimSignTextHandler::SignTextL | Begin")); + + __ASSERT_DEBUG( iResponseID == NULL, User::Panic( KWimSignTextPanic, KErrGeneral ) ); + iResponseID = new( ELeave ) CWimResponse( aMessage ); + iResponseID->iOpcode = ESignTextReq; + + __ASSERT_DEBUG( iTrId == NULL, User::Panic( KWimSignTextPanic, KErrGeneral ) ); + iTrId = iWimUtilFuncs->TrIdLC( iResponseID, EWimMgmtReq ); + CleanupStack::Pop( iTrId ); + + TPckgBuf signPckg; + aMessage.ReadL( 1, signPckg ); + + // Data to be signed + iSigningDataBuf = iWimUtilFuncs->DesLC( 2, aMessage ); + CleanupStack::Pop( iSigningDataBuf ); + + iSigningDataPtr = new( ELeave ) TPtr8( iSigningDataBuf->Des() ); + + // Key ID + TBuf8 keyIdBuf = signPckg().iKeyId; + TPtr8 keyIdHash( const_cast( keyIdBuf.Ptr() ), keyIdBuf.Length() ); + WIMI_Ref_t* keyRef; + WIMI_GetKeyByHash( ( TUint8* )keyIdHash.Ptr(), &keyRef ); + iKeyReference = ( TAny* )keyRef; // Key reference + + iRetry = EFalse; + GetPinParamsL( iPinParams ); // Get PIN parameters + + AskPin(); // Ask PIN + } + +// ----------------------------------------------------------------------------- +// CWimSignTextHandler::AskPin +// Ask PIN from user +// ----------------------------------------------------------------------------- +// +void CWimSignTextHandler::AskPin() + { + TBool IsWIMOpen = EFalse; + iSigningState = EAskPin; + iStatus = KRequestPending; + SetActive(); + + _WIMTRACE(_L("WIM | WIMServer | CWimSignTextHandler::AskPin ")); + WIMI_Ref_pt pWimRefTemp = NULL; + pWimRefTemp = WIMI_GetWIMRef( 0 ); + + if ( pWimRefTemp ) // Close the WIM + { + if ( WIMI_IsWIMOpened( pWimRefTemp ) ) + { + IsWIMOpen = ETrue; + } + free_WIMI_Ref_t( pWimRefTemp ); + } + + if( IsWIMOpen ) + { + TRequestStatus* status = &iStatus; + User::RequestComplete( status, KErrNone ); + } + else + { + iWimSecDlg->EnterPIN( iRetry, + iPinParams, + iSigningPin, + iStatus ); + } + } + +// ----------------------------------------------------------------------------- +// CWimSignTextHandler::GetPinParamsL +// Get parameters for PIN. iKeyReferense has to be set before this function +// is used. +// ----------------------------------------------------------------------------- +// +void CWimSignTextHandler::GetPinParamsL( TPINParams& aPinParams ) const + { + TInt pushed = 0; + TPINLabel pinLabel; // The label that identifies the PIN + TPINLabel tokenLabel; // The label of the token + TUint8 minLength = 0; // The minimum length of the PIN + + WIMI_STAT status = WIMI_Ok; + + // WIMI_GetKeyInfo() + WIMI_Ref_t* pWimRef; + TUint8 keyType; + TUint8 keyNumber; + TUint8 pinNumber; + TUint16 usage; + TUint16 keyLength; + WIMI_BinData_t ptKeyLabel; + WIMI_BinData_t ptKeyId; + // WIMI_GetPINList() + WIMI_Ref_pt pPinRef = NULL; + TUint16 pinNum; + WIMI_RefList_t pinRefLst; + // WIMI_GetPINStatus() + TUint8 flags; + WIMI_BinData_t ptPinLabel; + WIMI_Ref_t* cmeWimRef = NULL; + // WIMI_GetWIMInfo() + TUint16 wimFlags; + TUint8 seSet; + TUint8 version; + WIMI_BinData_t ptWimID; + WIMI_BinData_t ptManufacturerID; + WIMI_BinData_t ptWimLabel; + TUint8 reader = 0; + TBool sim; + + // Get PIN number by Key reference + status = WIMI_GetKeyInfo( iKeyReference, + &pWimRef, + NULL, + &keyType, + &keyNumber, + &pinNumber, + &usage, + &ptKeyId, + &ptKeyLabel, + &keyLength ); + if ( status != WIMI_Ok ) + { + User::Leave( CWimUtilityFuncs::MapWIMError( status ) ); + } + + // TODO: leaving PushL functions should not be used + + CleanupPushWimRefL( pWimRef ); + pushed++; + CleanupPushWimBufL( ptKeyId ); + pushed++; + CleanupPushWimBufL( ptKeyLabel ); + pushed++; + + // Get PIN references + status = WIMI_GetPINList( pWimRef, &pinNum, &pinRefLst ); + if ( status == WIMI_Ok ) + { + // Select right reference by PIN number + pPinRef = pinRefLst[pinNumber]; + } + CleanupPushWimRefListL( pinRefLst ); + pushed++; + + if ( pPinRef ) + { + // Get PIN info (label, min length etc.) + status = WIMI_GetPINStatus( pPinRef, + &cmeWimRef, + &flags, + &minLength, + &pinNumber, + &ptPinLabel ); + if ( status != WIMI_Ok ) + { + User::Leave( CWimUtilityFuncs::MapWIMError( status ) ); + } + CleanupPushWimRefL( cmeWimRef ); + pushed++; + CleanupPushWimBufL( ptPinLabel ); + pushed++; + + HBufC8* pinLabelBuf = HBufC8::NewLC( ptPinLabel.ui_buf_length ); + pushed++; + + TPtr8 pinPtr = pinLabelBuf->Des(); + pinPtr.Copy( ptPinLabel.pb_buf, ptPinLabel.ui_buf_length ); + pinLabel.Copy( pinPtr ); + } + else + { + User::Leave( KErrArgument ); + } + + // Get token label + status = WIMI_GetWIMInfo( cmeWimRef, + &wimFlags, + &seSet, + &ptWimID, + &ptManufacturerID, + &ptWimLabel, + &reader, + &pPinRef, + &sim, + &version ); + if ( status != WIMI_Ok ) + { + User::Leave( CWimUtilityFuncs::MapWIMError( status ) ); + } + CleanupPushWimBufL( ptWimLabel ); + pushed++; + CleanupPushWimBufL( ptWimID ); + pushed++; + CleanupPushWimBufL( ptManufacturerID ); + pushed++; + + HBufC8* wimLabelBuf = HBufC8::NewLC( ptWimID.ui_buf_length ); + pushed++; + + TPtr8 wimLabelPtr( wimLabelBuf->Des() ); + wimLabelPtr.Copy( ptWimLabel.pb_buf, ptWimLabel.ui_buf_length ); + + tokenLabel.Copy( wimLabelPtr ); // Copy token label + + aPinParams.iPINLabel = pinLabel; + aPinParams.iTokenLabel = tokenLabel; + aPinParams.iMinLength = minLength; + aPinParams.iMaxLength = KWIMMaxPINLength; // Use max value + + CleanupStack::PopAndDestroy( pushed, pWimRef ); + } + +// ----------------------------------------------------------------------------- +// CWimSignTextHandler::ContinueSigningL +// Continues signing operation after signing PIN has asked from user. +// Call WIMI and return error code in iStatus in case digital signature +// can not be done e.g. wrong PIN has entered. +// ----------------------------------------------------------------------------- +// +void CWimSignTextHandler::ContinueSigningL() + { + _WIMTRACE(_L("WIM|WIMServer|CWimSignTextHandler::ContinueSigningL|Begin")); + + WIMI_BinData_t pPin; + + // Copy signing PIN to 8 bit buffer + HBufC8* signingPinBuf = HBufC8::NewLC( iSigningPin.Length() ); + TPtr8 signingPin = signingPinBuf->Des(); + signingPin.Copy( iSigningPin ); + pPin.pb_buf = ( TUint8* )signingPin.Ptr(); + pPin.ui_buf_length = ( TUint16 )signingPin.Length(); + + iStatus = KRequestPending; + TRequestStatus* status = &iStatus; + iSigningState = ECallbackResponse; + SetActive(); + + iResponseID->iStatus = WIMI_SignReq( iTrId, + ( TUint8* )iSigningDataPtr->Ptr(), + ( TUint8 )iSigningDataPtr->Length(), + iKeyReference, + &pPin ); + + CleanupStack::PopAndDestroy( signingPinBuf ); + + // Some error in WIMI (no connection to card etc.) + // Request not completed by callback function + if ( iResponseID->iStatus != WIMI_Ok ) + { + iSigningState = EWimiError; + User::RequestComplete( status, iResponseID->iStatus ); + } + } + +// ----------------------------------------------------------------------------- +// CWimSignTextHandler::CleanUp +// Clean up member data +// ----------------------------------------------------------------------------- +// +void CWimSignTextHandler::CleanUp() + { + if( iSigningDataBuf ) + { + delete iSigningDataBuf; + iSigningDataBuf = NULL; + } + + if( iSigningDataPtr ) + { + delete iSigningDataPtr; + iSigningDataPtr = NULL; + } + + WIMI_Ref_t* keyRef = iKeyReference; + free_WIMI_Ref_t( keyRef ); + } + +// ----------------------------------------------------------------------------- +// CWimSignTextHandler::RunL +// Handle digital signature operation as state machine. Handle different +// states here. +// ----------------------------------------------------------------------------- +// +void CWimSignTextHandler::RunL() + { + _WIMTRACE2(_L("WIM|WIMServer|CWimSignTextHandler::RunL|status=%d"), iStatus.Int()); + + switch ( iSigningState ) + { + // PIN asked + case EAskPin: + { + iRetry = ETrue; // Next is retry + + if ( iStatus.Int() != KErrNone ) // Cancelled or other error + { + if( iResponseID ) + { + if( iStatus.Int() == KErrCancel ) + { + iResponseID->iStatus = WIMI_ERR_UserCancelled; + } + else + { + iResponseID->iStatus = ( TUint16 )iStatus.Int(); + } + iResponseID->CompleteMsgAndDelete(); + iResponseID = NULL; + } + + if( iTrId ) + { + delete iTrId; + iTrId = NULL; + } + + CleanUp(); + } + else // User entered PIN without errors + { + CWimCallBack::SetSignTextRequestStatus( &iStatus ); + ContinueSigningL(); // Continue digital signature operation + } + break; + } + + // We come here from CWimCallBack::SignResp() + case ECallbackResponse: + { + CWimCallBack::SetSignTextRequestStatus( NULL ); + + if ( iStatus.Int() == WIMI_ERR_BadPIN ) // Wrong PIN, continue + { + AskPin(); // Ask PIN again and continue + } + // If PIN is blocked show note + else if ( iStatus.Int() == WIMI_ERR_PINBlocked ) + { + iSigningState = EShowPinBlocked; + iWimSecDlg->ShowPINBlocked( iPinParams, iStatus ); + SetActive(); + } + else if ( iStatus.Int() == WIMI_ERR_CardIOError ) + { + iSigningState = EShowCardIsRemoved; + iStatus = KRequestPending; + TRequestStatus* status = &iStatus; + SetActive(); + User::RequestComplete( status, KErrNone ); + } + else // Response completed in callbacks, just finalize operation + { + iStatus = KRequestPending; + iSigningState = ESigningDone; + TRequestStatus* status = &iStatus; + SetActive(); + User::RequestComplete( status, KErrNone ); + } + break; + } + + // PIN Blocked note showed to user + case EShowPinBlocked: + { + // Complete message here with KErrLocked + if( iResponseID ) + { + iResponseID->iStatus = WIMI_ERR_PINBlocked; + iResponseID->CompleteMsgAndDelete(); + iResponseID = NULL; + } + + if( iTrId ) + { + delete iTrId; + iTrId = NULL; + } + + iStatus = KRequestPending; + iSigningState = ESigningDone; + TRequestStatus* status = &iStatus; + SetActive(); + User::RequestComplete( status, KErrNone ); + break; + } + case EShowCardIsRemoved: + { + if( iResponseID ) + { + iResponseID->iStatus = WIMI_ERR_CardIOError; + iResponseID->CompleteMsgAndDelete(); + iResponseID = NULL; + } + if( iTrId ) + { + delete iTrId; + iTrId = NULL; + } + + iStatus = KRequestPending; + iSigningState = ESigningDone; + TRequestStatus* status = &iStatus; + SetActive(); + User::RequestComplete( status, KErrNone ); + break; + } + // WIMI error. Message is not completed in callback function. + // So, complete it here + case EWimiError: + { + CWimCallBack::SetSignTextRequestStatus( NULL ); + + if( iResponseID ) + { + iResponseID->iStatus = ( TUint16 )iStatus.Int(); + iResponseID->CompleteMsgAndDelete(); + iResponseID = NULL; + } + if ( iTrId ) + { + delete iTrId; + iTrId = NULL; + } + + CleanUp(); + break; + } + + // Text is signed, handle response in callback functions + case ESigningDone: + { + CleanUp(); + iResponseID = NULL; + iTrId = NULL; + break; + } + + default: + { + CleanUp(); + break; + } + } + } + +// ----------------------------------------------------------------------------- +// CWimSignTextHandler::DoCancel +// Asyncronous call cancelled. +// ----------------------------------------------------------------------------- +// +void CWimSignTextHandler::DoCancel() + { + _WIMTRACE(_L("WIM|WIMServer|CWimSignTextHandler::DoCancel|Begin")); + } + +// ----------------------------------------------------------------------------- +// CWimSignTextHandler::RunError +// RunL leaved, handle error here. +// ----------------------------------------------------------------------------- +// +TInt CWimSignTextHandler::RunError( TInt aError ) + { + CWimCallBack::SetSignTextRequestStatus( NULL ); + if( iResponseID ) + { + iResponseID->iStatus = ( TUint16 )aError; + iResponseID->CompleteMsgAndDelete(); + iResponseID = NULL; + } + if( iTrId ) + { + delete iTrId; + iTrId = NULL; + } + + CleanUp(); + return KErrNone; + } + +// End of File