--- /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 <secdlg.h>
+
+#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<TKeySignParameters> 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<KKeyIdLen> keyIdBuf = signPckg().iKeyId;
+ TPtr8 keyIdHash( const_cast<TUint8*>( 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