deviceencryption/DevEncUi/src/DevEncUiEncryptionOperator.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Mon, 18 Jan 2010 20:09:41 +0200
changeset 0 6a9f87576119
child 5 1e73d2d04cbc
permissions -rw-r--r--
Revision: 201001 Kit: 201003

/*
* Copyright (c) 2005 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:  Implementation of CDevEncUiEncryptionOperator.
*
*/

// INCLUDE FILES
#include <DevEncExternalCRKeys.h>
// Class includes
#include "DevEncLog.h"
#include "DevEncUids.hrh"
#include "DevEncUiEncryptionOperator.h"

#include "DevEncUiFileManager.h"

//System includes
#include <aknmessagequerydialog.h>
#include <aknViewAppUi.h>
#include <AknWaitNoteWrapper.h>
#include <aknnotewrappers.h> // for CAknErrorNote
#include <bautils.h> // For BAFL, localized resource files
#include <centralrepository.h>
#include <coemain.h>
#include <data_caging_path_literals.hrh> // for resource files dir
#include <DevEncUi.rsg>
#include <eikenv.h>
#include <e32property.h>
#include <etelmm.h>
#include <f32file.h>
#include <gsfwviewuids.h> // For general settings view UIDs (autolock)
#include <hwrmpowerstatesdkpskeys.h> // For power state
#include <SecUiSecuritySettings.h> // for autolock
#include <SettingsInternalCRKeys.h>
#include <StringLoader.h>
#include <utf.h> // For character conversion
#include <TerminalControl3rdPartyAPI.h>

#include <DevEncKeyUtils.h>

//User includes
#include "DevEncLog.h"
#include "DevEnc.hrh"
#include "DevEncUiCreateKeyProcess.h"
#include "DevEncDef.h"
#include "DevEncUiMemoryEntity.h"
#include "DevEncUiSecretMinMaxCodeQuery.h"
//for KMaxAutolockPeriod = 20;
#include "DevEncSession.h"

// --------------------------------------------------------------------------
// CDevEncUiEncryptionOperator::~CDevEncUiEncryptionOperator
//
// --------------------------------------------------------------------------
//
CDevEncUiEncryptionOperator::~CDevEncUiEncryptionOperator()
    {
    }

// --------------------------------------------------------------------------
// CDevEncUiEncryptionOperator::NewL
//
// --------------------------------------------------------------------------
//
CDevEncUiEncryptionOperator* CDevEncUiEncryptionOperator::NewL( CEikonEnv& aEikonEnv,
                                                                CAknViewAppUi& aAppUi,
                                                                CRepository*& aCrSettings )
    {
    CDevEncUiEncryptionOperator* self =
        CDevEncUiEncryptionOperator::NewLC( aEikonEnv,
                                            aAppUi,
                                            aCrSettings );
    CleanupStack::Pop( self );
    return self;
    }

// --------------------------------------------------------------------------
// CDevEncUiEncryptionOperator::NewLC
//
// --------------------------------------------------------------------------
//
CDevEncUiEncryptionOperator* CDevEncUiEncryptionOperator::NewLC( CEikonEnv& aEikonEnv,
                                                                 CAknViewAppUi& aAppUi,
                                                                 CRepository*& aCrSettings )
    {
    CDevEncUiEncryptionOperator* self =
        new ( ELeave ) CDevEncUiEncryptionOperator( aEikonEnv,
                                                    aAppUi,
                                                    aCrSettings );
    CleanupStack::PushL( self );
    self->ConstructL();
    return self;
    }

// --------------------------------------------------------------------------
// CDevEncUiEncryptionOperator::CDevEncUiEncryptionOperator
//
// --------------------------------------------------------------------------
//
CDevEncUiEncryptionOperator::CDevEncUiEncryptionOperator( CEikonEnv& aEikonEnv,
                                                          CAknViewAppUi& aAppUi,
                                                          CRepository*& aCrSettings )
    : iEikEnv( aEikonEnv ),
    iAppUi( aAppUi ),
    iCrSettings( aCrSettings )
    {
    }

// --------------------------------------------------------------------------
// CDevEncUiEncryptionOperator::ConstructL
//
// --------------------------------------------------------------------------
//
void CDevEncUiEncryptionOperator::ConstructL()
    {
    }

// --------------------------------------------------------------------------
// CDevEncUiEncryptionOperator::HandlePhoneMemEncryptRequestL()
// --------------------------------------------------------------------------
//
void CDevEncUiEncryptionOperator::HandlePhoneMemEncryptRequestL( CDevEncUiMemoryEntity* aMem, CDevEncUiMemoryEntity* aPrimaryMem )
    {
    // Check the battery level first
    if ( ! CheckBatteryL() )
        {
        // The battery level is too low and no charger is connected.
        // Show a note to the user.
        ErrorNoteL( R_DEVENCUI_TEXT_BATTERY_LOW );
        User::Leave( KErrNotReady );
        }

    if ( (aMem->State() == EDecrypted) || (aPrimaryMem && (aPrimaryMem->State() == EDecrypted)) )
        {
        // Encryption is off -> encrypt
        if ( PrepareEncryptionL() )
            {
            if ( aMem->State() == EDecrypted )
            	{
            	DFLOG( "Starting Mass Storage encryption" );
            	aMem->StartEncryptionL();
            	}
            if( aPrimaryMem && (aPrimaryMem->State() == EDecrypted) )
            	{
            	DFLOG( "Starting phone memory encryption" );
            	aPrimaryMem->StartEncryptionL();
                }
            }
        else
            {
            DFLOG( "Encryption cancelled" );
            }
        }
    else if ( (aMem->State() == EEncrypted) || (aPrimaryMem && (aPrimaryMem->State() == EEncrypted)) )
        {
        if ( PrepareDecryptionL() )
            {
            if ( aMem->State() == EEncrypted )
            	{
            	DFLOG( "Starting Mass Storage decryption" );
            	aMem->StartDecryptionL();
            	}
            if( aPrimaryMem && (aPrimaryMem->State() == EEncrypted) )
                {
                DFLOG( "Starting phone memory decryption" );
                aPrimaryMem->StartDecryptionL();
                }
            }
        else
            {
            DFLOG( "Decryption cancelled" );
            }
        }
    else
        {
        DFLOG2( "Phone memory busy, state = %d, no action", aMem->State() );
        }

    // Depending on the user's selection, the memory may be in the same
    // state as before or in a new state. This call will let all observers
    // know what state the memory ended up in.
    aMem->UpdateMemoryInfo();
    }

// --------------------------------------------------------------------------
// CDevEncUiEncryptionOperator::PrepareEncryptionL()
// --------------------------------------------------------------------------
//
TBool CDevEncUiEncryptionOperator::PrepareEncryptionL()
    {
    TBool result( EFalse );

    // Show the confirmation query about autolock
    CAknMessageQueryDialog* yesNoQuery = new ( ELeave ) CAknMessageQueryDialog;
    if ( ! yesNoQuery->ExecuteLD( R_DEVENCUI_ENCRYPT_CONFIRMATION_QUERY_DIALOG ) )
        {
        // User answered no. Do nothing
        DFLOG( "User cancelled after autolock warning. No action." );
        return result;
        }

    // Autolock must be on before encryption can be enabled.
    // Get the current autolock status and the current max autolock period
    TInt lockTime = 0;
    TBuf8<21> autoLockPeriodBuf;
    
    RTerminalControl terminalCtrl;
    TInt ctrlConnect = terminalCtrl.Connect();
    DFLOG2( "DEVENC: terminal control connected %d", ctrlConnect );
    
    RTerminalControl3rdPartySession session;
    TInt retValue = session.Open( terminalCtrl );
    DFLOG2( "DEVENC: terminal control session open %d", retValue );

    TInt err2 = session.GetDeviceLockParameter( RTerminalControl3rdPartySession::ETimeout, autoLockPeriodBuf );
    DFLOG2( "DEVENC: max value get returned value %d", err2 );
    
    TLex8 lexAutolock( autoLockPeriodBuf );          
    lexAutolock.Val( lockTime );
    DFLOG2( "lockTime = %d", lockTime );
    
    //Get current max autolock period
    TBuf8<21> oldMaxPeriodBuf;
    TInt maxperioderr = session.GetDeviceLockParameter( RTerminalControl3rdPartySession::EMaxTimeout, oldMaxPeriodBuf );
    DFLOG2( "DEVENC: max value set returned value %d", maxperioderr );

#ifndef __WINS__
    // Setting the autolock works only in target

    if ( lockTime == 0 )
        {
        // Autolock disabled. Go to the autolock settings
        DFLOG( "Autolock currently disabled, going to settings" );

        // Create the filename of the SecUi resource file
        _LIT( KFileDrive, "z:" );
        _LIT( KSecUiResourceFileName, "SecUi.rsc" );
        TFileName filename;
        filename += KFileDrive;
        filename += KDC_RESOURCE_FILES_DIR;
        filename += KSecUiResourceFileName;

        // Convert to a localized resource filename if possible
        RFs fs;
        User::LeaveIfError( fs.Connect() );
        BaflUtils::NearestLanguageFile( fs, filename );

        // Load the SecUi resource file
        TInt rfileOffset( 0 );
        TRAPD( err, rfileOffset = iEikEnv.AddResourceFileL( filename ) );
        if ( err )
            {
            DFLOG2( "Add resource file error %d", err );
            }
        User::LeaveIfError( err );
        
        // Set maximum autolock period
        
        TBuf8<21> maxPeriodBuf;
        maxPeriodBuf.AppendNum( KMaxAutolockPeriod );
        TInt err3 = session.SetDeviceLockParameter( RTerminalControl3rdPartySession::EMaxTimeout, maxPeriodBuf );
        DFLOG2( "DEVENC: max value set returned value %d", err3 );

        // Let the user set an autolock period
        CSecuritySettings* secSett = CSecuritySettings::NewL();
        CleanupStack::PushL( secSett );
        TInt newLockTime = secSett->ChangeAutoLockPeriodL( lockTime );
        CleanupStack::PopAndDestroy( secSett );

        iEikEnv.DeleteResourceFile( rfileOffset );
        
        if ( newLockTime == 0 )
            {
            // User cancelled or set autolock off -> do nothing
            DFLOG( "User selected not to enable autolock. No action." );
            
            //restore the old maximum period value
            TInt err3 = session.SetDeviceLockParameter( RTerminalControl3rdPartySession::EMaxTimeout, oldMaxPeriodBuf );
            DFLOG2( "DEVENC: max value set returned value %d", err3 );
            
            //the autolock period is now at KMaxAutolockPeriod( =20 ) so we have to set it as it was previously
            err3 = session.SetDeviceLockParameter( RTerminalControl3rdPartySession::ETimeout, autoLockPeriodBuf );
            DFLOG2( "DEVENC: max value set returned value %d", err3 );
            
            session.Close();
            terminalCtrl.Close();
            return result;
            }
        
        TBuf8<21> newLockTimeBuf;
        newLockTimeBuf.AppendNum( newLockTime );
        
        TInt setResult = session.SetDeviceLockParameter( RTerminalControl3rdPartySession::ETimeout, newLockTimeBuf );
        if ( setResult )
            {
            // TBI: Log the failure and leave with error
            DFLOG2( "ERROR: session.SetDeviceLockParameter( RTerminalControl3rdPartySession::ETimeout, .. ) returned %d", setResult );
            session.Close();
            terminalCtrl.Close();
            return result;
            }
        lockTime = newLockTime;
        }
    else
    	{    	
    	DFLOG( "Autolock already enabled. Set only the current maximum period" );
    	
    	//By setting the max autolock period the autolock period is set to max if it was greater than that
    	TBuf8<21> maxPeriodBuf;
        maxPeriodBuf.AppendNum( KMaxAutolockPeriod );
        TInt err3 = session.SetDeviceLockParameter( RTerminalControl3rdPartySession::EMaxTimeout, maxPeriodBuf );
        DFLOG2( "DEVENC: max value set returned value %d", err3 );
        }
#endif // __WINS__

    DFLOG2( "Autolock time is %d", lockTime );

    // Autolock is now enabled, so we can proceed with the encryption
    // Warn the user about the long encryption process
    if ( MessageQueryL( R_DEVENCUI_TEXT_NOTE_ENCRYPTING ) )
        {
        result = ETrue;
        DFLOG( "Starting encryption" );
        }
    else
        {
        DFLOG( "Encryption cancelled" );
        //the encryption was cancelled. Let's set the old autolock values
        //restore the old maximum period value
        TInt err3 = session.SetDeviceLockParameter( RTerminalControl3rdPartySession::EMaxTimeout, oldMaxPeriodBuf );
        DFLOG2( "DEVENC: max value set returned value %d", err3 );
        
        //the autolock period is now at KMaxAutolockPeriod( =20 ) so we have to set it as it was previously
        err3 = session.SetDeviceLockParameter( RTerminalControl3rdPartySession::ETimeout, autoLockPeriodBuf );
        DFLOG2( "DEVENC: max value set returned value %d", err3 );
        }
    
    session.Close();
    terminalCtrl.Close();
    
    return result;
    }

// --------------------------------------------------------------------------
// CDevEncUiEncryptionOperator::PrepareDecryptionL()
// --------------------------------------------------------------------------
//
TBool CDevEncUiEncryptionOperator::PrepareDecryptionL()
    {
    // Warn the user about the long decryption process
    return MessageQueryL( R_DEVENCUI_TEXT_NOTE_PHONE_DECRYPTING );
    }

// --------------------------------------------------------------------------
// CDevEncUiEncryptionOperator::MessageQueryL()
// --------------------------------------------------------------------------
//
TBool CDevEncUiEncryptionOperator::MessageQueryL( TInt aResourceId,
                                                  TInt aSoftKeysId )
    {
    TBool result( EFalse );

    // Show a message query with OK and Cancel buttons and the specified text
    CAknMessageQueryDialog* query =
        new ( ELeave ) CAknMessageQueryDialog;
    query->PrepareLC( R_DEVENCUI_ENCRYPT_CONFIRMATION_QUERY_DIALOG );
    query->ButtonGroupContainer().SetCommandSetL( aSoftKeysId );
    HBufC* prompt = StringLoader::LoadLC( aResourceId, &iEikEnv );
    query->SetMessageTextL( *prompt );
    CleanupStack::PopAndDestroy( prompt );
    if ( query->RunLD() )
        {
        result = ETrue;
        }
    return result;
    }

// --------------------------------------------------------------------------
// CDevEncUiEncryptionOperator::QueryDialog()
// --------------------------------------------------------------------------
//
TBool CDevEncUiEncryptionOperator::QueryDialogL( TInt aResourceId,
                                                 TInt aSoftKeysId )
    {
    TBool result( EFalse );
    CAknQueryDialog* query = CAknQueryDialog::NewL();
    query->PrepareLC( R_DEVENCUI_CONFIRMATION_QUERY ); // CleanupStack OK
    HBufC* prompt = StringLoader::LoadLC( aResourceId, &iEikEnv );
    query->SetPromptL( *prompt );
    query->ButtonGroupContainer().SetCommandSetL( aSoftKeysId );
    
    CleanupStack::PopAndDestroy( prompt );
    if ( query->RunLD() )
        {
        result = ETrue;
        }
    return result;
    }

// --------------------------------------------------------------------------
// CDevEncUiEncryptionOperator::DataQueryDialogL()
// --------------------------------------------------------------------------
//
TBool CDevEncUiEncryptionOperator::DataQueryDialogL( TDes& aResult,
                                                     TInt aPromptResourceId,
                                                     TInt aMaxLength )
    {
    // The descriptor contained the prompt text for the query. The prompt
    // text can also be defined in the resource structure of the query
    HBufC* prompt = StringLoader::LoadLC( aPromptResourceId, &iEikEnv );

    // create dialog instance
    CAknTextQueryDialog* dlg =
        new( ELeave ) CAknTextQueryDialog( aResult, *prompt );

    CleanupStack::PopAndDestroy( prompt );

    // Sets the maximum length of the text editor
    dlg->SetMaxLength( aMaxLength );

    // Prepares the dialog, constructing it from the specified resource
    dlg->PrepareLC( R_DEVENCUI_DATA_QUERY );

    // Launch the dialog
    return dlg->RunLD();
    }

// --------------------------------------------------------------------------
// CDevEncUiEncryptionOperator::HandleMmcEncryptRequestL()
// --------------------------------------------------------------------------
//
void CDevEncUiEncryptionOperator::HandleMmcEncryptRequestL( CDevEncUiMemoryEntity* aMem,
                                                            TInt aCommand )
    {
    // Check the battery level first
    if ( ! CheckBatteryL() )
        {
        // The battery level is too low and no charger is connected.
        // Show a note to the user.
        ErrorNoteL( R_DEVENCUI_TEXT_BATTERY_LOW );
        User::Leave( KErrNotReady );
        }

    TBool proceed( EFalse );
    switch ( aCommand )
        {
        case EDevEncUiCommandEncryptWithRestoredKey:
            {
            DFLOG( "Encrypt with restored key selected" );
            proceed = LoadAndSetKeyL(); // No cleanup stack needed
            break;
            }

        case EDevEncUiCommandEncryptAndSaveKey:
            {
            DFLOG( "Encrypt and save key selected" );
            proceed = CreateAndSaveKeyL(); // No cleanup stack needed
            if( proceed )
                {
                InfoNoteL( R_DEVENCUI_TEXT_NOTE_SAVEINFO, ETrue );
                DFLOG( "Key saved succesfully" );
                }
            break;
            }

        case EDevEncUiCommandEncryptWithoutSavingKey:
            {
            DFLOG( "Encrypt without saving key selected" );
            // Create an encryption key and take it in use
            // The key will remain in the driver until the next key is set,
            // and it can not be retrieved.
            proceed = CreateKeyL(); // No cleanup stack needed
            break;
            }

        case EDevEncUiCommandEncryptWithCurrentKey:
            {
            DFLOG( "Encrypt with current key selected" );
            proceed = ETrue;
            }
            
        default:
            {
            DFLOG( "Invalid command" );
            break;
            }
        }

    if ( aMem->State() == EUnmounted )
        {
        if( !proceed )
        	{
            // The encryption operation was cancelled, just go back to encryption view
            DFLOG( "No Mmc present and operation was cancelled -> no encryption" );
            }
        else
        	{
        	// The encryption operation was succesfull, go back to main view
            iAppUi.ActivateLocalViewL( TUid::Uid( EDevEncUiMainViewId ) );
        	proceed = EFalse;
            DFLOG( "No Mmc present -> no encryption" );
            }
        }

    if ( aMem->State() == ECorrupted )
        {
        if( !proceed )
        	{
        	DFLOG( "Mmc probably enc with another key -> wait for remount" );
            }
        else
        	{
        	// Mmc was probably encrypted with another key. We have just set a
            // new key, so now we have to wait until the state changes and hope
            // that the card is readable. If it is, a note will be shown to the
            // user. (See UI spec 2.7)
            InfoNoteL( R_DEVENCUI_TEXT_NOTE_MEMORYCARD_ENCRYPTED, ETrue );
            iAppUi.ActivateLocalViewL( TUid::Uid( EDevEncUiMainViewId ) );
            proceed = EFalse;
            DFLOG( "Mmc probably enc with another key -> wait for remount" );
            RemountMmcL();
            }
        }
    
    if ( proceed )
        {
        TInt encrypt( 0 );
        
        // Check DM admin status
        TInt dmControlSetting( 0 );
        iCrSettings->Get( KDevEncUiDmControl, dmControlSetting );
        
        if( ( dmControlSetting & KDmControlsMemoryCard ) && ( aCommand == EDevEncUiCommandEncryptWithCurrentKey ) )
        	{
        	//if the DM admin is controlling the encryption, encrypt straight away
        	encrypt = ETrue;
        	}
        else
        	{
        	encrypt = MessageQueryL( R_DEVENCUI_TEXT_NOTE_ENCRYPTING );
            }
        
        // Warn the user about the long encryption process
        if ( encrypt )
            {
            // Start the encryption
            DFLOG( "Starting encryption" );
            aMem->StartEncryptionL();
            // Go back to main view
            iAppUi.ActivateLocalViewL( TUid::Uid( EDevEncUiMainViewId ) );
            }
        else
            {
            DFLOG( "Encryption cancelled" );
            // Stay in the Encryption view
            // Show a note to the user about that the new key is in use,
            // but the card is still decrypted (UI spec 2.3)
            InfoNoteL( R_DEVENCUI_TEXT_NOTE_ENCRYPTIONINTERRUPT, ETrue );
            iAppUi.ActivateLocalViewL( TUid::Uid( EDevEncUiMainViewId ) );
            }
        }

    // Depending on the user's selection, the memory may be in the same
    // state as before or in a new state. This call will let all observers
    // know what state the memory ended up in.
    aMem->UpdateMemoryInfo();
    }

// --------------------------------------------------------------------------
// CDevEncUiEncryptionOperator::CreateKeyL()
// --------------------------------------------------------------------------
//
TBool CDevEncUiEncryptionOperator::CreateKeyL()
    {
    TBool proceed( EFalse );
    CDevEncKeyUtils* utils = new ( ELeave ) CDevEncKeyUtils;
    CleanupStack::PushL( utils );
//    User::LeaveIfError(utils->Connect());
    TRequestStatus status;
    utils->CreateSetKey( status, KEncryptionKeyLength );
    User::WaitForRequest( status );
//    utils->Close();
    CleanupStack::PopAndDestroy( utils );
    if ( ! status.Int() )
        {
        // Save the Mmc encryption key status
        User::LeaveIfError( iCrSettings->Set( KDevEncUserSettingMemoryCard,
                                              ETrue ) );
        proceed = ETrue;
        }
    return proceed;
    }

// --------------------------------------------------------------------------
// CDevEncUiEncryptionOperator::CreateAndSaveKeyL()
// --------------------------------------------------------------------------
//
TBool CDevEncUiEncryptionOperator::CreateAndSaveKeyL()
    {
    TBool proceed( EFalse );
    
    TBool passwordOk( EFalse );
    TBool keyFileNameOk( EFalse );
    TBool keyCreated( EFalse );
    TBool keySaved( EFalse );
    CFileStore* file( NULL );
    HBufC* keyFileName = HBufC::NewLC( KMaxFilenameLength );
    
    // Get the key password from the user
    HBufC8* password = HBufC8::NewLC( KMaxPasswordLength );
    TPtr8 passwordPtr = password->Des();
    passwordOk = PasswordQueryL( R_DEVENCUI_TEXT_PASSPHRASE_PROTECT,
                                 passwordPtr );

    CDevEncUiFileManager* fm = new ( ELeave ) CDevEncUiFileManager;
    CleanupStack::PushL( fm );
    fm->ConstructL();

    HBufC8* pkcs5Key( NULL );

    if ( passwordOk )
        {
        DFLOG( "Password entered" );
        // The user entered the correct password

        // Construct file path
        _LIT( KDevEncKeyFileExtension, ".pk5");
        TBuf<KMaxFileName> filePath;
        User::LeaveIfError( fm->KeyFolder( filePath ) );
        TInt pathLen( filePath.Length() );

        // Get the key file name from the user
        TBool filenameEntered( EFalse );
        TBool cancelPressed( EFalse );
        TPtr16 keyFileNamePtr = keyFileName->Des();
        while ( ( ! cancelPressed ) && ( ! file ) )
            {
            filenameEntered = DataQueryDialogL( keyFileNamePtr,
                    R_DEVENCUI_TEXT_FILENAME,
                    KMaxFilenameLength );
            if ( !filenameEntered )
                {
                // User pressed cancel, stop here
                cancelPressed = ETrue;
                }
            else
                {
                // User entered a file name. Try to open a file store
                filePath.Append( keyFileNamePtr );
                filePath.Append( KDevEncKeyFileExtension );
                TInt openError = fm->OpenFileStore( filePath,
                                                    file );
                if ( openError )
                    {
                    DFLOG2( "Error opening file: %d", openError );

                    // Notify the user that something went wrong
                    if ( openError == KErrAlreadyExists )
                        {
                        ErrorNoteL( R_DEVENCUI_TEXT_FILE_EXISTS );
                        }
                    else
                        {
                        ErrorNoteL( R_DEVENCUI_TEXT_BAD_NAME );
                        }
                    
                    // Remove the file name from the path and try again
                    filePath.Delete( pathLen, filePath.Length() - pathLen );
                    }
                else
                    {
                    DFLOG( "File opened:" );
                    DFLOGBUF( filePath );
                    keyFileNameOk = ETrue;
                    CleanupStack::PushL( file );
                    }
                }
            } // end of while
        }
    else
        {
        DFLOG( "Password incorrect" );
        }
    
    if ( keyFileNameOk )
        {
        // Create the encryption key
        CDevEncKeyUtils* utils = new ( ELeave ) CDevEncKeyUtils;
        CleanupStack::PushL( utils );
//        User::LeaveIfError(utils->Connect());

        TRequestStatus status;
        utils->CreateSetKey( status, pkcs5Key, *password, KEncryptionKeyLength );
        User::WaitForRequest( status );
//        utils->Close();
        CleanupStack::PopAndDestroy( utils );
        
        if ( status.Int() )
            {
            DFLOG2( "Error creating key: %d", status.Int() );
            }
        else
            {
            keyCreated = ETrue;
            CleanupStack::PushL( pkcs5Key );
            // Save the Mmc encryption key status
            User::LeaveIfError( iCrSettings->Set( KDevEncUserSettingMemoryCard,
                                                  ETrue ) );
            }
        }

    if ( keyCreated )
        {
        // Save the key
        fm->SaveKeyL( file, *pkcs5Key );
        CleanupStack::PopAndDestroy( pkcs5Key );
        keySaved = ETrue;
        }

    if ( keySaved )
        {
        // Finally, start the encryption
        proceed = ETrue;
        }

    // Cleanup on demand
    if ( file )
        {
        CleanupStack::PopAndDestroy( file );
        }
    if ( fm )
        {
        CleanupStack::PopAndDestroy( fm );
        }
    if ( password )
        {
        CleanupStack::PopAndDestroy( password );
        }
    if ( keyFileName )
        {
        CleanupStack::PopAndDestroy( keyFileName );
        }
    
    return proceed;
    }

// --------------------------------------------------------------------------
// CDevEncUiEncryptionOperator::LoadAndSetKeyL()
// --------------------------------------------------------------------------
//
TBool CDevEncUiEncryptionOperator::LoadAndSetKeyL()
    {
    TBool proceed( EFalse );

    TBool keySelected( EFalse );
    TBool passwordOk( EFalse );
    TBool askPassword( ETrue );
    HBufC8* pkcs5Key( NULL );
    TBuf8<KMaxPasswordLength> password8;

    // Get a list of existing keys in the private directory
    CDevEncUiFileManager* fm = new ( ELeave ) CDevEncUiFileManager;
    CleanupStack::PushL( fm );
    fm->ConstructL();
    CDir* dir( NULL );
    fm->GetKeyListL( dir );

    DFLOG2( "Found %d keys", dir->Count() );
    
    if ( dir->Count() <= 0 )
        {
        ErrorNoteL( R_DEVENCUI_TEXT_NO_KEYS_FOUND );
        User::Leave( KErrNotReady );
        }
    
    // Create a list for the query
    iListQueryItemArray = new ( ELeave ) CDesCArrayFlat( dir->Count() );
    for ( TInt i = 0; i < dir->Count(); i++ )
        {
        TEntry entry( (*dir)[i] );
        HBufC* tmpFileName = entry.iName.AllocLC();
        iListQueryItemArray->AppendL( entry.iName );
        CleanupStack::PopAndDestroy( tmpFileName );
        }

    // Let the user select which key to load
    TInt index( 0 ); // the index of the selected item
    CAknListQueryDialog* query =
        new ( ELeave ) CAknListQueryDialog( &index );
    query->PrepareLC( R_DEVENCUI_LIST_QUERY );
    query->ButtonGroupContainer().SetCommandSetL( R_AVKON_SOFTKEYS_OK_BACK );
    query->SetItemTextArray( iListQueryItemArray );
    // Keep ownership of the item array
    query->SetOwnershipType( ELbmDoesNotOwnItemArray );
    if ( query->RunLD() )
        {
        DFLOG2( "User selected key %d", index );
        DFLOGBUF( ( *dir )[index].iName );
        // Load the key file.

        // Construct file path
        TBuf<KMaxFileName> filePath;
        DFLOG("Start find key folder");
        User::LeaveIfError( fm->KeyFolder( filePath ) );
        DFLOG("Stop find key folder");
    
        TFileName filename;
        filename.Append( filePath );
        filename.Append( ( *dir )[index].iName );
        fm->LoadKeyL( filename,
                      pkcs5Key );
        CleanupStack::PushL( pkcs5Key );
        keySelected = ETrue;
        DFLOG( "Key loaded" );
        }
    else
        {
        // User cancelled the query
        DFLOG( "Key file query cancelled by user, stopping here" );
        }
    
    while ( askPassword )
    	{
        if ( keySelected )
            {
            // Get the key password from the user
            passwordOk = PasswordQueryL( R_DEVENCUI_TEXT_PASSPHRASE_ASK,
                                         password8 );
            }
        else
        	{
        	//The user pressed back. Do not ask the password
        	askPassword = EFalse;
        	}

        if ( passwordOk )
            {
            DFLOG( "Password ok, setting key" );
            CDevEncKeyUtils* utils = new ( ELeave ) CDevEncKeyUtils;
            CleanupStack::PushL( utils );
//            User::LeaveIfError(utils->Connect());

            TRequestStatus status;
            utils->SetKey( status, *pkcs5Key, password8 );
            User::WaitForRequest( status );
//            utils->Close();
            CleanupStack::PopAndDestroy( utils );
            if ( status.Int() )
                {
                const TInt KErrBadPassphrase( -11000 );
                DFLOG2( "Error taking key in use: %d", status.Int() );
                if ( status.Int() == KErrBadPassphrase )
                    {
                    DFLOG( "Invalid password" );
                    ErrorNoteL( R_DEVENCUI_TEXT_INVALID_PASSWORD );
                    }
                else
                    {
                    DFLOG2( "Key read error %d", status.Int() );
                    ErrorNoteL( R_DEVENCUI_TEXT_KEY_ERROR );
                    askPassword = EFalse;
                    }
                }
            else
                {
                DFLOG( "New key is now in use" );
                // Save the Mmc encryption key status
                User::LeaveIfError( iCrSettings->Set( KDevEncUserSettingMemoryCard,
                                                      ETrue ) );
                proceed = ETrue;
                askPassword = EFalse;
                }
            }
        else
            {
            askPassword = EFalse;
            }
        }
    // Cleanup on demand
    if ( pkcs5Key )
        {
        CleanupStack::PopAndDestroy( pkcs5Key );
        }
    if ( fm )
        {
        CleanupStack::PopAndDestroy( fm );
        }

    return proceed;
    }
    

// --------------------------------------------------------------------------
// CDevEncUiEncryptionOperator::PasswordQueryL()
// --------------------------------------------------------------------------
//
TBool CDevEncUiEncryptionOperator::PasswordQueryL( TInt aPromptResourceId,
                                                   TDes8& aResult )
    {
    TBool passwordOk( EFalse );
    TBuf<KMaxPasswordLength> password;
    TBuf8<KMaxPasswordLength> password8;
    CDevEncUiSecretMinMaxCodeQuery* query =
        new ( ELeave ) CDevEncUiSecretMinMaxCodeQuery( password,
                                                   KMinPasswordLength,
                                                   KMaxPasswordLength );

    HBufC* prompt = StringLoader::LoadLC( aPromptResourceId, &iEikEnv );
    query->SetPromptL( *prompt );
    CleanupStack::PopAndDestroy( prompt );

    // Prompt the user for the key password
    if ( ( query->ExecuteLD( R_DEVENCUI_CODE_QUERY ) ) )
        {
        // This indicates that the user filled in some password and
        // pressed OK.
        passwordOk = ETrue;
        }
    else
        {
        DFLOG( "Key password dialog cancelled" );
        }

    if ( passwordOk )
        {
        // Convert the password to UTF-8
        if ( CnvUtfConverter::ConvertFromUnicodeToUtf8( password8,
                                                        password ) )
            {
            DFLOG( "Password conversion failed" );
            passwordOk = EFalse;
            }
        else
            {
            aResult.Copy( password8 );
            }
        }
    
    return passwordOk;
    }

// --------------------------------------------------------------------------
// CDevEncUiEncryptionOperator::HandleMmcDecryptRequestL()
// --------------------------------------------------------------------------
//
void CDevEncUiEncryptionOperator::HandleMmcDecryptRequestL( CDevEncUiMemoryEntity* aMem,
                                                            TInt aCommand )
    {
    // Check the battery level first
    if ( ! CheckBatteryL() )
        {
        // The battery level is too low and no charger is connected.
        // Show a note to the user.
        ErrorNoteL( R_DEVENCUI_TEXT_BATTERY_LOW );
        User::Leave( KErrNotReady );
        }

    TBool proceed( EFalse );
    switch ( aCommand )
        {
        case EDevEncUiCommandDecrypt:
            {
            DFLOG( "Decrypt selected" );
            // Warn the user about the long decryption process
            proceed = MessageQueryL( R_DEVENCUI_TEXT_NOTE_DECRYPTING );
            break;
            }
        case EDevEncUiCommandDecryptAndTurnOffEncryption:
            {
            DFLOG( "Decrypt and turn off selected" );
            // Warn the user about the long decryption process,
            // and that the key will be destroyed
            proceed = MessageQueryL( R_DEVENCUI_TEXT_NOTE_DECRYPTINGDESTROY );
            // Save the Mmc encryption key status
            User::LeaveIfError( iCrSettings->Set( KDevEncUserSettingMemoryCard,
                                                  EFalse ) );
            // The key will actually be destroyed in the DevEncStarter
            // component, because the user may exit from the UI at any time.
            // By saving the encryption key status in the central repository,
            // we ensure that the Starter knows that it's supposed to destroy
            // the key when the operation is complete
            // TBI: Destroy the key in Starter after decryption is complete.
            break;
            }
        default:
            {
            break;
            }
        }

    if ( aMem->State() == EUnmounted )
        {
        // Just go back to main view, no decryption operation
        iAppUi.ActivateLocalViewL( TUid::Uid( EDevEncUiMainViewId ) );
        proceed = EFalse;
        DFLOG( "No Mmc present -> no decryption" );
        }
    
    if ( proceed )
        {
        // Start the decryption
        DFLOG( "Starting decryption" );
        aMem->StartDecryptionL();
        // Go back to main view
        iAppUi.ActivateLocalViewL( TUid::Uid( EDevEncUiMainViewId ) );
        }
    else
        {
        DFLOG( "Decryption cancelled" );
        // Stay in the decryption view
        }

    // Depending on the user's selection, the memory may be in the same
    // state as before or in a new state. This call will let all observers
    // know what state the memory ended up in.
    aMem->UpdateMemoryInfo();
    }

// ---------------------------------------------------------------------------
// CDevEncUiEncryptionOperator::CheckBatteryL()
// Checks if there's enough battery power to update
// ---------------------------------------------------------------------------
//
TBool CDevEncUiEncryptionOperator::CheckBatteryL()
    {
#ifdef __WINS__

    // In the emulator, the battery level is always 0 and the charger is never
    // connected, so just return ETrue.
    return ETrue;

#else // __WINS__

    // Running on target. Check the real battery and charger status

    TInt chargingstatus( EChargingStatusError );
    TInt batterylevel( 1 );
    TBool enoughPower( EFalse );

    // Read battery
    DFLOG( "CDevEncUiEncryptionOperator::CheckBatteryL" );
    RProperty pw;
    User::LeaveIfError( pw.Attach( KPSUidHWRMPowerState, KHWRMBatteryLevel ) );
    User::LeaveIfError( pw.Get( batterylevel ) );
    pw.Close();

    User::LeaveIfError( pw.Attach( KPSUidHWRMPowerState, KHWRMChargingStatus ) );
    User::LeaveIfError( pw.Get( chargingstatus ));
    pw.Close();

    // Too low battery, power insufficient
    if ( batterylevel >= EBatteryLevelLevel4 )
        {
        enoughPower = ETrue;
        }
    // But charger is connected, power sufficient
    if ( ( chargingstatus != EChargingStatusError ) &&
         ( chargingstatus != EChargingStatusNotConnected ) )
        {
        enoughPower = ETrue;
        }

    DFLOG3( "Battery level: %d  (0..7), chargingstatus %d",
           batterylevel, chargingstatus );
    DFLOG2( "CheckBatteryL %d", ( enoughPower ? 1 : 0 ) );
    return enoughPower;

#endif // __WINS__
    }

// --------------------------------------------------------------------------
// CDevEncUiEncryptionOperator::ErrorNoteL()
// --------------------------------------------------------------------------
//
void CDevEncUiEncryptionOperator::ErrorNoteL( TInt aResourceId,
                                              TBool aWaitingNote )
    {
    HBufC* message = StringLoader::LoadLC( aResourceId );
    CAknErrorNote* errorNote = new ( ELeave ) CAknErrorNote( aWaitingNote );
    errorNote->ExecuteLD( *message );
    CleanupStack::PopAndDestroy( message );
    }

// --------------------------------------------------------------------------
// CDevEncUiEncryptionOperator::InfoNoteL()
// --------------------------------------------------------------------------
//
void CDevEncUiEncryptionOperator::InfoNoteL( TInt aResourceId,
                                             TBool aWaitingNote )
    {
    HBufC* message = StringLoader::LoadLC( aResourceId );
    CAknInformationNote* note = new ( ELeave ) CAknInformationNote( aWaitingNote );
    note->ExecuteLD( *message );
    CleanupStack::PopAndDestroy( message );
    }

// --------------------------------------------------------------------------
// CDevEncUiEncryptionOperator::DestroyKeyQueryL()
//
// --------------------------------------------------------------------------
void CDevEncUiEncryptionOperator::DestroyKeyQueryL( TBool aShowMmcNote )
    {
    TBool destroy = QueryDialogL( R_DEVENCUI_TEXT_NOTE_DECRYPT_NOMEMRYCARD, R_AVKON_SOFTKEYS_YES_NO );
    if ( destroy )
        {
        DestroyKeyL();
        if ( aShowMmcNote )
            {
            InfoNoteL( R_DEVENCUI_TEXT_NOTE_MEMORYCARD_UNENCRYPTED );
            }
        }
    else
        {
        DFLOG( "User cancelled destroy key query" );
        }
    }

// --------------------------------------------------------------------------
// CDevEncUiEncryptionOperator::DestroyKeyL()
//
// --------------------------------------------------------------------------
void CDevEncUiEncryptionOperator::DestroyKeyL()
    {
    DFLOG( "CDevEncUiEncryptionOperator::DestroyKeyL" );
    CDevEncKeyUtils* utils = new ( ELeave ) CDevEncKeyUtils;
    CleanupStack::PushL( utils );
//    User::LeaveIfError(utils->Connect());

    TRequestStatus status;
    utils->ResetKey( status );
    User::WaitForRequest( status );
//    utils->Close();
    CleanupStack::PopAndDestroy( utils );
    if ( status.Int() )
        {
        DFLOG2( "DestroyKeyL error %d", status.Int() );
        }
    else
        {
        DFLOG( "DestroyKeyL done" );
        // We no longer have a key in the driver. Update the user setting.
        iCrSettings->Set( KDevEncUserSettingMemoryCard, 0 );
        }
    User::LeaveIfError( status.Int() );
    }

// --------------------------------------------------------------------------
// CDevEncUiEncryptionOperator::SuggestMmcEncryptionL()
//
// --------------------------------------------------------------------------
void CDevEncUiEncryptionOperator::SuggestMmcEncryptionL(
                                                CDevEncUiMemoryEntity* aMem )
    {
    TInt encrypt( 0 );
    
    // Check DM admin status
    TInt dmControlSetting( 0 );
    iCrSettings->Get( KDevEncUiDmControl, dmControlSetting );
    
    if( dmControlSetting & KDmControlsMemoryCard )
    	{
    	//The admin is controlling the encryption, encrypt straight away without questions
    	encrypt = ETrue;
    	}
    else
    	{
    	encrypt = MessageQueryL( R_DEVENCUI_TEXT_NOTE_INSERTUNENCRYPTED,
                R_AVKON_SOFTKEYS_YES_NO );
        }
    
    if ( encrypt )
        {
        HandleMmcEncryptRequestL( aMem,
                                  EDevEncUiCommandEncryptWithCurrentKey );
        }
    else
        {
        DFLOG( "User selected not to encrypt the card" );
        }
    }

// --------------------------------------------------------------------------
// CDevEncUiEncryptionOperator::SuggestMmcDecryptionL()
//
// --------------------------------------------------------------------------
void CDevEncUiEncryptionOperator::SuggestMmcDecryptionL( CDevEncUiMemoryEntity* aMem )
    {
    TBool decrypt = MessageQueryL( R_DEVENCUI_TEXT_NOTE_INSERTENCRYPTED,
                                   R_AVKON_SOFTKEYS_YES_NO );
    if ( decrypt )
        {
        SuggestMmcImportKeyL( aMem, ETrue );
        }
    else
        {
        ErrorNoteL( R_DEVENCUI_TEXT_NOTE_INSERTOFF_UNUSEDMEMORYCARD );
        }
    }

// --------------------------------------------------------------------------
// CDevEncUiEncryptionOperator::SuggestMmcImportKeyL()
//
// --------------------------------------------------------------------------
void CDevEncUiEncryptionOperator::SuggestMmcImportKeyL(
                                                CDevEncUiMemoryEntity* /*aMem*/,
                                                TBool aFirstAttempt )
    {
    DFLOG( "CDevEncUiEncryptionOperator::SuggestMmcImportKeyL" );
    TBool import( ETrue );
    if ( aFirstAttempt )
        {
        DFLOG( "CDevEncUiEncryptionOperator::SuggestMmcImportKeyL => firstAttempt" );
        import = MessageQueryL( R_DEVENCUI_TEXT_NOTE_DECRYPT_LOADKEY,
                                R_AVKON_SOFTKEYS_YES_NO );
        }
    
    if ( import )
        {
        TBool reloadKey = ETrue; 
        // Loop while user chooses correct key or cancels operation 
        while ( reloadKey ) 
            { 
            TBool keySet = LoadAndSetKeyL(); 
            if ( !keySet ) 
                { 
                ErrorNoteL( R_DEVENCUI_TEXT_NOTE_UNUSEDMEMORYCARD ); 
                reloadKey = EFalse; 
                } 
            else 
                { 
                // New key is in use, now we need to remount the mmc 
                RemountMmcL(); 
                
                // Check that key is valid 
                TInt err = CheckMMCStatus();              

                if( err == KErrCorrupt )
                	{
                	ErrorNoteL( R_DEVENCUI_TEXT_NOTE_WRONGKEYFILE );
                	reloadKey = ETrue;
                	}
                else
                	{
                	reloadKey = EFalse;
                	}
                } 
            }
        }
    }

// --------------------------------------------------------------------------
// CDevEncUiEncryptionOperator::CheckMMCStatus()
//
// --------------------------------------------------------------------------
TInt CDevEncUiEncryptionOperator::CheckMMCStatus()
    {
    TVolumeInfo volInfo; 
    RFs fs; 
    TInt err =  fs.Connect(); 
    if (err == KErrNone)
        {
        fs.Volume( volInfo, EDriveF );
        fs.Close();
        }
    return err;
    }

// --------------------------------------------------------------------------
// CDevEncUiEncryptionOperator::RemountMmc()
//
// --------------------------------------------------------------------------
void CDevEncUiEncryptionOperator::RemountMmcL()
    {
    CDevEncUiFileManager* fm = new ( ELeave ) CDevEncUiFileManager;
    CleanupStack::PushL( fm );
    fm->ConstructL();
    TInt error = fm->RemountMmc();
    CleanupStack::PopAndDestroy( fm );
    if ( error )
        {
        DFLOG2( "Mmc remount failed, error %d", error );
        User::Leave( error );
        }
    else
        {
        DFLOG( "Mmc remounted" );
        }
    }

// --------------------------------------------------------------------------
// CDevEncUiEncryptionOperator::ShowWrongKeyNoteL()
//
// --------------------------------------------------------------------------
void CDevEncUiEncryptionOperator::ShowWrongKeyNoteL()
    {
    ErrorNoteL( R_DEVENCUI_TEXT_NOTE_INSERTON_UNUSEDMEMORYCARD );
    }

// --------------------------------------------------------------------------
// CDevEncUiEncryptionOperator::CheckNotesWithHeaderL()
//
// --------------------------------------------------------------------------
void CDevEncUiEncryptionOperator::CheckNotesWithHeaderL()
    {
    MessageQueryL( R_DEVENCUI_TEXT_NOTE_DECRYPT_LOADKEY );
    MessageQueryL( R_DEVENCUI_TEXT_NOTE_DECRYPT_NOMEMRYCARD );
    MessageQueryL( R_DEVENCUI_TEXT_NOTE_DECRYPTING );
    MessageQueryL( R_DEVENCUI_TEXT_NOTE_DECRYPTINGDESTROY );
    MessageQueryL( R_DEVENCUI_TEXT_NOTE_ENCRYPTING );
    MessageQueryL( R_DEVENCUI_TEXT_NOTE_ENCRYPTIONINTERRUPT );
    MessageQueryL( R_DEVENCUI_TEXT_NOTE_INSERTENCRYPTED );
    MessageQueryL( R_DEVENCUI_TEXT_NOTE_INSERTOFF_UNUSEDMEMORYCARD );
    MessageQueryL( R_DEVENCUI_TEXT_NOTE_INSERTON_UNUSEDMEMORYCARD );
    MessageQueryL( R_DEVENCUI_TEXT_NOTE_INSERTUNENCRYPTED );
    MessageQueryL( R_DEVENCUI_TEXT_NOTE_LOCK );
    MessageQueryL( R_DEVENCUI_TEXT_NOTE_PHONE_DECRYPTING );
    }

// --------------------------------------------------------------------------
// CDevEncUiEncryptionOperator::CheckNotesL()
// --------------------------------------------------------------------------
//
void CDevEncUiEncryptionOperator::CheckNotesL()
    {
    QueryDialogL( R_DEVENCUI_TEXT_NOTE_DECRYPT_LOADKEY );
    QueryDialogL( R_DEVENCUI_TEXT_NOTE_DECRYPT_NOMEMRYCARD );
    QueryDialogL( R_DEVENCUI_TEXT_NOTE_DECRYPTING );
    QueryDialogL( R_DEVENCUI_TEXT_NOTE_DECRYPTINGDESTROY );
    QueryDialogL( R_DEVENCUI_TEXT_NOTE_ENCRYPTING );
    QueryDialogL( R_DEVENCUI_TEXT_NOTE_ENCRYPTIONINTERRUPT );
    QueryDialogL( R_DEVENCUI_TEXT_NOTE_INSERTENCRYPTED );
    QueryDialogL( R_DEVENCUI_TEXT_NOTE_INSERTOFF_UNUSEDMEMORYCARD );
    QueryDialogL( R_DEVENCUI_TEXT_NOTE_INSERTON_UNUSEDMEMORYCARD );
    QueryDialogL( R_DEVENCUI_TEXT_NOTE_INSERTUNENCRYPTED );
    QueryDialogL( R_DEVENCUI_TEXT_NOTE_LOCK );
    QueryDialogL( R_DEVENCUI_TEXT_NOTE_PHONE_DECRYPTING );
    }

// END OF FILE