wim/WimServer/src/WimSignTextHandler.cpp
changeset 0 164170e6151a
--- /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