diff -r 491b3ed49290 -r 65326cf895ed deviceencryption/DevEncUi/src/DevEncUiEncryptionOperator.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/deviceencryption/DevEncUi/src/DevEncUiEncryptionOperator.cpp Wed Sep 01 12:31:07 2010 +0100 @@ -0,0 +1,1349 @@ +/* +* 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 +// Class includes +#include "DevEncLog.h" +#include "DevEncUids.hrh" +#include "DevEncUiEncryptionOperator.h" + +#include "DevEncUiFileManager.h" + +//System includes +#include +#include +#include +#include // for CAknErrorNote +#include // For BAFL, localized resource files +#include +#include +#include // for resource files dir +#include +#include +#include +#include +#include +#include // For general settings view UIDs (autolock) +#include // For power state +#include // for autolock +#include +#include +#include // For character conversion +#include + +#include + +//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 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 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 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 password; + TBuf8 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