cryptoservices/certificateandkeymgmt/certstore/unifiedkeystore.cpp
changeset 0 2c201484c85f
child 8 35751d3474b7
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cryptoservices/certificateandkeymgmt/certstore/unifiedkeystore.cpp	Wed Jul 08 11:25:26 2009 +0100
@@ -0,0 +1,1121 @@
+/*
+* Copyright (c) 2001-2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the License "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: 
+*
+*/
+
+
+#include "unifiedkeystore.h"
+#include <ecom.h>
+#include <random.h>
+#include <pbedata.h>
+#include <asnpkcs.h>
+
+_LIT(KUnifiedKeyStore, "UnifiedKeyStore");
+
+/////////////////////////////////////////////////////////////////////////////////////
+//CUnifiedKeyStore
+/////////////////////////////////////////////////////////////////////////////////////
+
+EXPORT_C CUnifiedKeyStore* CUnifiedKeyStore::NewL(RFs& aFs)
+	{
+	CUnifiedKeyStore* self = CUnifiedKeyStore::NewLC(aFs);
+	CleanupStack::Pop(self);
+	return self;
+	}
+
+EXPORT_C CUnifiedKeyStore* CUnifiedKeyStore::NewLC(RFs& aFs)
+	{
+	CUnifiedKeyStore* self = new(ELeave) CUnifiedKeyStore(aFs);
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	return self;
+	}
+
+EXPORT_C CUnifiedKeyStore::~CUnifiedKeyStore()
+	{
+	Cancel();
+	Cleanup();
+
+	iKeyStoresHolder.ResetAndDestroy();
+	iKeyStoresHolder.Close();
+
+	REComSession::FinalClose();
+	}
+
+void CUnifiedKeyStore::DoInitializeL()
+{//	We want the list of all token types that support a keystore interface
+	RArray<TUid> uidArray;
+	CleanupClosePushL(uidArray);
+	
+	User::LeaveIfError(uidArray.Append(TUid::Uid(KInterfaceKeyStore)));
+
+	TCTFindTokenTypesByInterface filter(uidArray.Array());
+	CCTTokenTypeInfo::ListL(iTokenTypes, filter);
+	
+	CleanupStack::PopAndDestroy();	// uidArray
+}
+
+EXPORT_C void CUnifiedKeyStore::Initialize(TRequestStatus& aStatus)
+{// The following assertion checks that we didn't call Initialize twice
+	__ASSERT_DEBUG((iKeyStoresHolder.Count()==0), User::Panic(KUnifiedKeyStore, EUnexpectedInitialise));
+
+	TRAPD(err, DoInitializeL());
+	if (err != KErrNone)
+		{
+		TRequestStatus* status = &aStatus;
+		User::RequestComplete(status, err);
+		return;
+		}
+	
+	iIndexTokenTypes = -1;
+	StartAsyncOperation(EInitializeGetTokenList, aStatus);
+
+	SetActive();
+	TRequestStatus* status = &iStatus;
+	User::RequestComplete(status, KErrNone);
+}
+
+EXPORT_C void CUnifiedKeyStore::CancelInitialize()
+	{
+	if (iState == EInitializeGetTokenList ||
+		iState == EInitializeGetToken ||
+		iState == EInitialiseGetKeyManagerInterface ||
+		iState == EInitializeGetKeyUserInterface ||
+		iState == EInitializeGetKeyUserInterfaceFinished ||
+		iState == EInitializeFinished)
+		{
+		Cancel();
+		}
+	}
+
+EXPORT_C void CUnifiedKeyStore::CreateKey(TInt aKeyStoreIndex, TKeyUsagePKCS15 aUsage,TUint aSize, 
+										  const TDesC& aLabel, CCTKeyInfo::EKeyAlgorithm aAlgorithm, 
+										  TInt aAccessType, TTime aStartDate, TTime aEndDate, 
+										  CCTKeyInfo*& aKeyInfoOut, TRequestStatus& aStatus)
+	{
+	StartAsyncOperation(ECreateKey, aStatus);
+	TRAPD(err, PrepareToCreateKeyL(aKeyStoreIndex, aUsage, aSize, aLabel, aAlgorithm, aAccessType,
+								   aStartDate, aEndDate, aStatus));
+	if (KErrNone != err)
+		{
+		Complete(err);
+		return;
+		}
+	
+	iKeyInfoOut = &aKeyInfoOut;
+	aKeyInfoOut = NULL;
+	iKeyStoreManager->CreateKey(iKeyInfo, iStatus);
+	SetActive();
+	}
+
+EXPORT_C void CUnifiedKeyStore::CancelCreateKey()
+	{
+	if (iState == ECreateKey)
+		{			
+		Cancel();
+		}
+	}
+
+EXPORT_C void CUnifiedKeyStore::ImportKey(TInt aKeyStoreIndex, const TDesC8& aKeyData,
+										  TKeyUsagePKCS15 aUsage, const TDesC& aLabel, 
+										  TInt aAccessType, TTime aStartDate, TTime aEndDate, 
+										  CCTKeyInfo*& aKeyInfoOut, TRequestStatus& aStatus)
+	{
+	TBool isEncrypted = TASN1DecPKCS8::IsEncryptedPKCS8Data(aKeyData);
+	StartAsyncOperation(isEncrypted ? EImportKeyEncrypted : EImportKey, aStatus);
+
+	ASSERT(!iKeyData);
+	iKeyData = aKeyData.Alloc();
+	if (!iKeyData)	//	OOM or some other catastrophe
+		{
+		Complete(KErrNoMemory);
+		return;
+		}
+	
+	TRAPD(err, PrepareToCreateKeyL(aKeyStoreIndex, aUsage, 0, aLabel, CCTKeyInfo::EInvalidAlgorithm, aAccessType,
+								   aStartDate, aEndDate, aStatus));
+	if (KErrNone != err)
+		{
+		Complete(err);
+		return;
+		}
+
+	iKeyInfoOut = &aKeyInfoOut;
+	aKeyInfoOut = NULL;
+
+	if (isEncrypted)
+		{
+		iKeyStoreManager->ImportEncryptedKey(*iKeyData, iKeyInfo, iStatus);
+		}
+	else
+		{
+		iKeyStoreManager->ImportKey(*iKeyData, iKeyInfo, iStatus);
+		}
+	SetActive();
+	}
+
+EXPORT_C void CUnifiedKeyStore::CancelImportKey()
+	{
+	if (iState == EImportKey ||
+		iState == EImportKeyEncrypted)
+		{
+		Cancel();
+		}
+	}
+
+void CUnifiedKeyStore::PrepareToCreateKeyL(	TInt aKeyStoreIndex,
+											TKeyUsagePKCS15 aUsage, TUint aSize, 
+											const TDesC& aLabel, 
+											CCTKeyInfo::EKeyAlgorithm aAlgorithm,
+											TInt aAccessType, 
+											TTime aStartTime, TTime aEndTime,
+											TRequestStatus& aStatus)
+	{
+	ASSERT(!iKeyStoreManager);
+	
+	//	These values are filled in by the server when the key is created
+	TKeyIdentifier keyID;
+	keyID.MaxSize();
+	keyID.FillZ(keyID.MaxSize());
+	TInt keyHandle = 0;
+
+	// Get the secure ID of the current process
+	RProcess thisProcess;
+	User::LeaveIfError(thisProcess.Open(thisProcess.Id()));
+	TSecureId creatorId = thisProcess.SecureId();
+	thisProcess.Close();
+
+	// Default management policy: resict to creating process
+	TSecurityPolicy managementPolicy(creatorId);
+
+	// Default use policy: also resict to creating process
+	TSecurityPolicy usePolicy(creatorId);
+
+	HBufC* label = aLabel.AllocLC();
+
+	// Panics if keystore manager index invalid
+	MCTKeyStoreManager& keystore = KeyStoreManager(aKeyStoreIndex);
+
+	iKeyInfo = CCTKeyInfo::NewL(keyID, aUsage, aSize, NULL, label, keystore.Token(),
+								keyHandle, usePolicy, managementPolicy, aAlgorithm,
+								aAccessType, ETrue, aStartTime, aEndTime);
+	CleanupStack::Pop(label);
+
+	iKeyStoreManager = &keystore;
+	iOriginalRequestStatus = &aStatus;
+	aStatus = KRequestPending;
+	}
+
+//	************************************************************************
+//	MKeyStore
+//	************************************************************************
+
+void CUnifiedKeyStore::List(RMPointerArray<CCTKeyInfo>& aKeys, 
+							const TCTKeyAttributeFilter& aFilter, 
+							TRequestStatus& aStatus)
+	{
+	StartAsyncOperation(EList, aStatus);
+
+	iKeyInfos = &aKeys;
+
+	delete iFilter;
+	iFilter = new TCTKeyAttributeFilter(aFilter);
+	if (!iFilter)
+		{
+		Complete(KErrNoMemory);
+		return;
+		}
+	
+	iIndex = -1;
+
+	SetActive();
+	TRequestStatus* status = &iStatus;
+	User::RequestComplete(status, KErrNone);
+}
+
+void CUnifiedKeyStore::CancelList()
+	{
+	if (iState == EList)
+		{
+		Cancel();
+		}
+	}
+
+void CUnifiedKeyStore::GetKeyInfo(TCTTokenObjectHandle aHandle, 
+										   CCTKeyInfo*& aKeyInfo,
+										   TRequestStatus& aStatus)
+	{
+	StartAsyncOperation(EGetKeyInfo, aStatus);
+	
+	ASSERT(!iKeyStore);	
+	iKeyStore = FindKeyStore(aHandle);
+	if (!iKeyStore)
+		{
+		Complete(KErrNotFound);
+		return;
+		}
+
+	iKeyStore->GetKeyInfo(aHandle, aKeyInfo, iStatus);
+	SetActive();
+	}
+
+void CUnifiedKeyStore::CancelGetKeyInfo()
+	{
+	if (iState == EGetKeyInfo)
+		{
+		Cancel();
+		}
+	}
+
+// Implementation for most of the Open() method
+TBool CUnifiedKeyStore::DoOpen(const TCTTokenObjectHandle& aHandle, 
+							   TRequestStatus& aStatus)
+	{
+	StartAsyncOperation(EOpen, aStatus);
+	
+	ASSERT(!iKeyStore);	
+	iKeyStore = FindKeyStore(aHandle);
+	if (!iKeyStore)
+		{
+		Complete(KErrNotFound);
+		return EFalse;
+		} 
+
+	SetActive();
+	return ETrue;
+	}
+
+void CUnifiedKeyStore::Open(const TCTTokenObjectHandle& aHandle, 
+							MRSASigner*& aSigner,
+							TRequestStatus& aStatus)
+	{
+	if (DoOpen(aHandle, aStatus))
+		{
+		iKeyStore->Open(aHandle, aSigner, iStatus);
+		}
+	}
+
+void CUnifiedKeyStore::Open(const TCTTokenObjectHandle& aHandle, 
+							MDSASigner*& aSigner, 
+							TRequestStatus& aStatus)
+	{
+	if (DoOpen(aHandle, aStatus))
+		{			
+		iKeyStore->Open(aHandle, aSigner, iStatus);
+		}
+	}
+
+void CUnifiedKeyStore::Open(const TCTTokenObjectHandle& aHandle, 
+							MCTDecryptor*& aDecryptor,
+							TRequestStatus& aStatus)
+	{
+	if (DoOpen(aHandle, aStatus))
+		{
+		iKeyStore->Open(aHandle, aDecryptor, iStatus);
+		}
+	}
+
+void CUnifiedKeyStore::Open(const TCTTokenObjectHandle& aHandle, 
+							MCTDH*& aDH, TRequestStatus& aStatus)
+	{	
+	if (DoOpen(aHandle, aStatus))
+		{
+		iKeyStore->Open(aHandle, aDH, iStatus);
+		}
+	}
+
+void CUnifiedKeyStore::CancelOpen()
+	{
+	if (iState == EOpen)
+		{
+		Cancel();
+		}
+	}
+
+/** Returns the public key in DER-encoded ASN-1 */
+void CUnifiedKeyStore::ExportPublic(const TCTTokenObjectHandle& aHandle,
+									HBufC8*& aPublicKey,
+									TRequestStatus& aStatus)
+	{
+	StartAsyncOperation(EExportPublic, aStatus);
+
+	iKeyStore = FindKeyStore(aHandle);
+	if (!iKeyStore)
+		{
+		Complete(KErrNotFound);
+		return;
+		}
+		
+	iKeyStore->ExportPublic(aHandle, aPublicKey, iStatus);
+	SetActive();
+	}
+
+void CUnifiedKeyStore::CancelExportPublic()
+	{
+	if (iState == EExportPublic)
+		{
+		Cancel();
+		}
+	}
+
+//	************************************************************************
+//	MKeyStoreManager
+//	************************************************************************
+	
+EXPORT_C void CUnifiedKeyStore::ExportKey(TCTTokenObjectHandle aHandle, 
+										  HBufC8*& aKey, TRequestStatus& aStatus)
+	{
+	StartAsyncOperation(EExportKey, aStatus);
+
+	ASSERT(!iKeyStoreManager);
+	iKeyStoreManager = FindKeyStoreManager(aHandle);
+	if (!iKeyStoreManager)
+		{
+		Complete(KErrNotFound);
+		return;
+		} 
+
+	iKeyStoreManager->ExportKey(aHandle, aKey, iStatus);
+	SetActive();
+	}
+
+EXPORT_C void CUnifiedKeyStore::CancelExportKey()
+	{
+	if (iState == EExportKey)
+		{
+		Cancel();
+		}
+	} 
+
+EXPORT_C void CUnifiedKeyStore::ExportEncryptedKey(TCTTokenObjectHandle aHandle, 
+												   const CPBEncryptParms& aEncryptParams,
+												   HBufC8*& aKey, TRequestStatus& aStatus)
+	{
+	StartAsyncOperation(EExportEncryptedKey, aStatus);
+	
+	ASSERT(!iKeyStoreManager);	
+	iKeyStoreManager = FindKeyStoreManager(aHandle);
+	if (!iKeyStoreManager)
+		{
+		Complete(KErrNotFound);
+		return;
+		} 
+		
+	iKeyStoreManager->ExportEncryptedKey(aHandle, aEncryptParams, aKey, iStatus);
+	SetActive();
+	}
+
+EXPORT_C void CUnifiedKeyStore::CancelExportEncryptedKey()
+	{
+	if (iState == EExportEncryptedKey)
+		{
+		Cancel();
+		}	
+	}
+
+EXPORT_C void CUnifiedKeyStore::DeleteKey(TCTTokenObjectHandle aHandle, 
+										  TRequestStatus& aStatus)
+	{
+	StartAsyncOperation(EDeleteKey, aStatus);
+
+	iKeyStoreManager = FindKeyStoreManager(aHandle);
+	if (!iKeyStoreManager)
+		{
+		Complete(KErrNotFound);
+		return;
+		}
+	
+	iKeyStoreManager->DeleteKey(aHandle, iStatus);
+	SetActive();
+	}
+
+EXPORT_C void CUnifiedKeyStore::CancelDeleteKey()
+	{
+	if (iState == EDeleteKey)
+		{
+		Cancel();
+		}
+	}
+
+EXPORT_C void CUnifiedKeyStore::SetUsePolicy(TCTTokenObjectHandle aHandle, 
+											 const TSecurityPolicy& aPolicy,
+											 TRequestStatus& aStatus)
+	{
+	StartAsyncOperation(ESetUsePolicy, aStatus);
+
+	iKeyStoreManager = FindKeyStoreManager(aHandle);
+	if (!iKeyStoreManager)
+		{
+		Complete(KErrNotFound);
+		return;
+		}
+	
+	iKeyStoreManager->SetUsePolicy(aHandle, aPolicy, iStatus);
+	SetActive();
+	}
+
+EXPORT_C void CUnifiedKeyStore::CancelSetUsePolicy()
+	{
+	if (iState == ESetUsePolicy)
+		{
+		Cancel();
+		}
+	}
+
+EXPORT_C void CUnifiedKeyStore::SetManagementPolicy(TCTTokenObjectHandle aHandle, 
+													const TSecurityPolicy& aPolicy,
+													TRequestStatus& aStatus)
+	{
+	StartAsyncOperation(ESetManagementPolicy, aStatus);
+
+	iKeyStoreManager = FindKeyStoreManager(aHandle);
+	if (!iKeyStoreManager)
+		{
+		Complete(KErrNotFound);
+		return;
+		}
+	
+	iKeyStoreManager->SetManagementPolicy(aHandle, aPolicy, iStatus);
+	SetActive();
+	}
+
+EXPORT_C void CUnifiedKeyStore::CancelSetManagementPolicy()
+	{
+	if (iState == ESetManagementPolicy)
+		{
+		Cancel();
+		}
+	}
+
+EXPORT_C void CUnifiedKeyStore::SetPassphraseTimeout(TInt aTimeout, 
+													 TRequestStatus& aStatus)
+	{
+	StartAsyncOperation(ESetPassphraseTimeout, aStatus);
+
+	iIndex = -1;
+	iNewTimeout = aTimeout;
+	SetActive();
+	
+	TRequestStatus* status = &iStatus;
+	User::RequestComplete(status, KErrNone);
+	}
+
+EXPORT_C void CUnifiedKeyStore::CancelSetPassphraseTimeout()
+	{
+	if (iState == ESetPassphraseTimeout)
+		{
+		Cancel();
+		}
+	}
+
+EXPORT_C void CUnifiedKeyStore::Relock(TRequestStatus& aStatus)
+	{
+	StartAsyncOperation(ERelock, aStatus);
+
+	iIndex = -1;
+	SetActive();
+	
+	TRequestStatus* status = &iStatus;
+	User::RequestComplete(status, KErrNone);
+	}
+
+EXPORT_C void CUnifiedKeyStore::CancelRelock()
+	{
+	if (iState == ERelock)
+		{
+		Cancel();
+		}
+	}
+
+//	************************************************************************
+//	Other exports
+//	************************************************************************
+
+EXPORT_C TInt CUnifiedKeyStore::KeyStoreCount() const
+{
+	return (iKeyStoresHolder.Count());
+}
+
+EXPORT_C MCTKeyStore& CUnifiedKeyStore::KeyStore(TInt aIndex)
+{
+	__ASSERT_ALWAYS(aIndex >= 0 && aIndex < iKeyStoresHolder.Count(),
+					User::Panic(KUnifiedKeyStore, EArrayAccessOutOfBounds));
+	
+	MCTKeyStore* keyStore = static_cast<MCTKeyStore*>(iKeyStoresHolder[aIndex]->KeyStore());
+	return (*keyStore);
+}
+
+EXPORT_C TInt CUnifiedKeyStore::KeyStoreManagerCount() const
+	{
+	TInt result = 0;
+	for (TInt i = 0 ; i < iKeyStoresHolder.Count() ; ++i)
+		{
+		if (iKeyStoresHolder[i]->IsKeyManager())
+			{
+			++result;
+			}
+		}
+	return result;
+	}
+
+EXPORT_C MCTKeyStoreManager& CUnifiedKeyStore::KeyStoreManager(TInt aIndex)
+	{
+	__ASSERT_ALWAYS(aIndex >= 0, User::Panic(KUnifiedKeyStore, EArrayAccessOutOfBounds));
+	TInt managerIndex = 0;
+	MCTKeyStoreManager* result = NULL;
+	for (TInt i = 0 ; i < iKeyStoresHolder.Count() ; ++i)
+		{
+		if (iKeyStoresHolder[i]->IsKeyManager())
+			{
+			if (managerIndex == aIndex)
+				{
+				result = static_cast<MCTKeyStoreManager*>(iKeyStoresHolder[i]->KeyStore());
+				break;
+				}
+			++managerIndex;
+			}
+		}
+	__ASSERT_ALWAYS(result != NULL, User::Panic(KUnifiedKeyStore, EArrayAccessOutOfBounds));
+	return *result;
+	}
+
+CUnifiedKeyStore::CUnifiedKeyStore(RFs& aFs)
+	:	CActive(EPriorityNormal), iFs(aFs), iState(EIdle)
+{//	Currently defaults to always try for key store manager interface
+//	This may change (add parameter to NewL for required interface)
+	iRequestUid.iUid = KInterfaceKeyStoreManager;
+	CActiveScheduler::Add(this);
+}
+
+void CUnifiedKeyStore::ConstructL()
+{}
+
+void CUnifiedKeyStore::StartAsyncOperation(TState aState, TRequestStatus& aStatus)
+	{
+	ASSERT(iState == EIdle);
+	ASSERT(iOriginalRequestStatus == NULL);
+	iState = aState;
+	iOriginalRequestStatus = &aStatus;
+	aStatus = KRequestPending;
+	}
+
+MCTKeyStore* CUnifiedKeyStore::FindKeyStore(const TCTTokenObjectHandle& aHandle)
+	{
+	for (TInt index = 0 ; index < iKeyStoresHolder.Count() ; ++index)
+		{
+		MCTTokenInterface* store = iKeyStoresHolder[index]->KeyStore();
+		ASSERT(store);
+		if (store->Token().Handle() == aHandle.iTokenHandle)
+			{
+			return static_cast<MCTKeyStoreManager*>(store);
+			}
+		}
+	return NULL;
+	}
+	
+MCTKeyStoreManager* CUnifiedKeyStore::FindKeyStoreManager(const TCTTokenObjectHandle& aHandle)
+	{
+	for (TInt index = 0 ; index < iKeyStoresHolder.Count() ; ++index)
+		{
+		MCTTokenInterface* store = iKeyStoresHolder[index]->KeyStore();
+		ASSERT(store);
+		if (store->Token().Handle() == aHandle.iTokenHandle && iKeyStoresHolder[index]->IsKeyManager())
+			{
+			return static_cast<MCTKeyStoreManager*>(store);
+			}
+		}
+	return NULL;
+	}
+	
+void CUnifiedKeyStore::RunL()
+{
+	if (EInitializeGetKeyUserInterfaceFinished != iState &&
+		EInitializeGetKeyUserInterface != iState && 
+		EInitializeGetToken != iState)
+	{
+		User::LeaveIfError(iStatus.Int());
+	}
+
+	switch (iState)
+	{
+		case EInitializeGetTokenList:
+		{//	Try to get a list of Tokens for each of the Token Types
+			iIndexTokenTypes++;
+			if (iIndexTokenTypes < iTokenTypes.Count())
+			{
+				__ASSERT_DEBUG(!iTokenType, User::Panic(KUnifiedKeyStore, EArrayAccessOutOfBounds));
+				iTokenType = MCTTokenType::NewL(*iTokenTypes[iIndexTokenTypes], iFs);
+				__ASSERT_DEBUG(iTokens.Count()==0, User::Panic(KUnifiedKeyStore, ETokensArrayAlreadyInUse));
+				iTokenType->List(iTokens, iStatus);
+				iIndexTokens = -1;
+				iState = EInitializeGetToken;
+			}
+			else
+			{// We don't need the list of Token Types anymore
+				iTokenTypes.ResetAndDestroy();
+				iTokenTypes.Close();
+				iState = EInitializeFinished;
+				TRequestStatus* status = &iStatus;
+				User::RequestComplete(status, KErrNone);
+			}
+			SetActive();
+			break;
+		}
+		case EInitializeGetToken:
+		{
+			if (iStatus.Int() == KErrHardwareNotAvailable)
+				{
+				// If the hardware corresponding to this
+				// TokenType has been removed then just skip it
+				// but DO NOT leave!
+				++iIndexTokens;
+				iState = EInitializeGetToken;
+				TRequestStatus* status = &iStatus;
+				User::RequestComplete(status, KErrNone);
+				}
+            else
+				{
+				User::LeaveIfError(iStatus.Int());
+    			iIndexTokens++;		
+		
+				if (iIndexTokens < iTokens.Count())
+					{
+					iTokenType->OpenToken(*iTokens[iIndexTokens], iToken, iStatus);
+					iRequestUid.iUid = KInterfaceKeyStoreManager;
+					iState = EInitialiseGetKeyManagerInterface;
+					}
+				else
+					{// Don't need the iTokenType anymore
+					iTokenType->Release();
+					iTokenType = 0;
+
+					iTokens.Close();	// Don't need the list of Tokens anymore
+					iState = EInitializeGetTokenList;
+					TRequestStatus* status = &iStatus;
+					User::RequestComplete(status, KErrNone);
+					}
+				}
+			SetActive();
+			break;
+		}
+		case EInitialiseGetKeyManagerInterface:
+		{// First try to get a manager interface to the store, if
+		//	unsuccessful, try once to get a user interface
+			if (iToken)
+			{
+				iRequestUid.iUid = KInterfaceKeyStoreManager;			
+				iToken->GetInterface(iRequestUid, iTokenInterface, iStatus);
+				iState = EInitializeGetKeyUserInterface;
+				SetActive();			
+			}
+			else
+			{//	No token
+				User::Leave(KErrNotReady);
+			}
+			break;
+		}
+		case EInitializeGetKeyUserInterface:
+		{//	Did we get a manager interface?
+			if (iStatus==KErrNoMemory)
+			{
+				User::Leave(KErrNoMemory);
+			}
+
+			if (iRequestUid.iUid==KInterfaceKeyStoreManager)
+			{
+				if (KErrNone==iStatus.Int())
+				{//	Success! Store it and finish up
+					CKeyStoreIF* keyStore = new (ELeave) CKeyStoreIF(iTokenInterface, ETrue);
+					CleanupStack::PushL(keyStore);
+					User::LeaveIfError(iKeyStoresHolder.Append(keyStore));
+					CleanupStack::Pop(keyStore);
+
+					iTokenInterface = 0;
+					iToken->Release();
+					iToken = 0;
+					iState = EInitializeGetToken;
+					TRequestStatus* status = &iStatus;
+					User::RequestComplete(status, KErrNone);
+				}
+				else
+				{//	No luck getting a manager, so try getting a user
+					iRequestUid.iUid = KInterfaceKeyStore;			
+					iToken->GetInterface(iRequestUid, iTokenInterface, iStatus);
+					iState = EInitializeGetKeyUserInterfaceFinished;					
+				}
+			}
+			else if (iRequestUid.iUid==KInterfaceKeyStore) 
+			{//	We were trying for user IF								
+				if (iStatus==KErrNone)
+				{
+					if (iToken)
+					{
+						iRequestUid.iUid = KInterfaceKeyStore;			
+						iToken->GetInterface(iRequestUid, iTokenInterface, iStatus);
+						iState = EInitializeGetKeyUserInterfaceFinished;	
+					}
+					else
+					{
+						User::Leave(KErrNotReady);
+					}
+				}
+				else
+				{//	Couldn't even get a user IF
+					User::Leave(iStatus.Int());
+				}				
+			}
+
+			SetActive();
+			break;
+		}
+		case EInitializeGetKeyUserInterfaceFinished:
+		{
+			if (iStatus==KErrNone)
+			{
+				CKeyStoreIF* keyStore = new (ELeave) CKeyStoreIF(iTokenInterface, EFalse);
+				CleanupStack::PushL(keyStore);
+				User::LeaveIfError(iKeyStoresHolder.Append(keyStore));
+				CleanupStack::Pop(keyStore);
+
+				iTokenInterface = 0;
+				iToken->Release();
+				iToken = 0;
+				iState = EInitializeGetToken;
+				TRequestStatus* status = &iStatus;
+				User::RequestComplete(status, KErrNone);
+			}
+			else if (iStatus == KErrNoMemory)
+			{
+				User::Leave(KErrNoMemory);
+			}
+			else
+			{
+				iState = EInitializeGetToken;
+				TRequestStatus* status = &iStatus;
+				User::RequestComplete(status,iStatus.Int());
+			}
+			
+			SetActive();
+			break;
+		}
+		case EInitializeFinished:
+			Complete(KErrNone);
+			break;
+			
+		case EList:
+		{//	iIndex has been initialized in List function
+			++iIndex;
+			if (iIndex < iKeyStoresHolder.Count())
+				{
+				iKeyStore = static_cast<MCTKeyStore*>(iKeyStoresHolder[iIndex]->KeyStore());
+				ASSERT(iKeyStore);
+				iKeyStore->List(*iKeyInfos, *iFilter, iStatus);
+				SetActive();
+				}
+			else
+				{
+				Complete(KErrNone);
+				}
+			break;
+		}
+		
+	    case EGetKeyInfo:
+			Complete(KErrNone);
+			break;
+			
+		case ECreateKey:
+			*iKeyInfoOut = iKeyInfo;
+			iKeyInfo = NULL; // Release ownership
+			Complete(KErrNone);
+			break;
+			
+		case EImportKey:
+		case EImportKeyEncrypted:
+			*iKeyInfoOut = iKeyInfo;
+			iKeyInfo = NULL; // Release ownership
+			Complete(KErrNone);
+			break;
+			
+		case EExportKey:
+		case EExportEncryptedKey:
+			Complete(KErrNone);
+			break;		
+
+	    case ERelock:
+			++iIndex;
+			
+			// Find next key store manager
+			while (iIndex < iKeyStoresHolder.Count() && !iKeyStoresHolder[iIndex]->IsKeyManager())
+				++iIndex;
+			
+			if (iIndex < iKeyStoresHolder.Count())
+				{
+				iKeyStoreManager = static_cast<MCTKeyStoreManager*>(iKeyStoresHolder[iIndex]->KeyStore());
+				ASSERT(iKeyStoreManager);
+				iKeyStoreManager->Relock(iStatus);
+				SetActive();
+				}
+			else
+				{
+				Complete(KErrNone);
+				}
+			break;
+
+	    case ESetPassphraseTimeout:
+			++iIndex;
+			
+			// Find next key store manager
+			while (iIndex < iKeyStoresHolder.Count() && !iKeyStoresHolder[iIndex]->IsKeyManager())
+				++iIndex;
+			
+			if (iIndex < iKeyStoresHolder.Count())
+				{
+				iKeyStoreManager = static_cast<MCTKeyStoreManager*>(iKeyStoresHolder[iIndex]->KeyStore());
+				ASSERT(iKeyStoreManager);
+				iKeyStoreManager->SetPassphraseTimeout(iNewTimeout, iStatus);
+				SetActive();
+				}
+			else
+				{
+				Complete(KErrNone);
+				}
+			break;
+
+	    case EOpen:
+		case EExportPublic:
+	    case EDeleteKey:
+	    case ESetUsePolicy:
+	    case ESetManagementPolicy:
+			Complete(KErrNone);
+			break;
+		default:
+			User::Panic(KUnifiedKeyStore, EUnrecognisedState);
+			break;
+	}
+}
+
+TInt CUnifiedKeyStore::RunError(TInt aError)
+	{
+	Complete(aError); 
+	return KErrNone;
+	}
+
+void CUnifiedKeyStore::DoCancel()
+	{
+	// If the current state is the last state involved in handling a request, we
+	// check to see if we have already been completed - in this case we can
+	// simply complete the client with iStatus (this may be KErrNone).  If we
+	// have not we cancel the outstanding request and pass the resulting iStatus
+	// back to the client - this too may indicate a successful completion if the
+	// cancel arrived after the request was executed.
+	//
+	// For more complex cases, where there are more states to go through before
+	// we finish servicing the client request, we cancel any outstanding
+	// request, and return KErrCancel to the client.
+
+	switch (iState)
+		{
+		case EInitializeFinished:
+		case EGetKeyInfo:
+		case ECreateKey:
+		case EImportKey:
+		case EImportKeyEncrypted:
+		case EExportKey:
+		case EExportEncryptedKey:
+	    case EOpen:
+		case EExportPublic:
+	    case EDeleteKey:
+	    case ESetUsePolicy:
+	    case ESetManagementPolicy:
+			if (iStatus == KRequestPending)
+				{
+				// Attempt to cancel outstanding request and pass status back to
+				// client
+				CancelOutstandingRequest();
+				Complete(iStatus.Int());
+				}
+			else
+				{
+				// We've already been completed - call RunL() to process results
+				// and complete client
+				TRAPD(err, RunL());
+				if (err != KErrNone)
+					{
+					RunError(err);
+					}
+				}
+			break;
+
+		default:
+			CancelOutstandingRequest();
+			Complete(KErrCancel);
+			break;
+		}
+	}
+
+void CUnifiedKeyStore::CancelOutstandingRequest()
+	{
+	switch (iState)
+		{
+		case EInitializeGetTokenList:
+		case EInitializeGetToken:
+		case EInitialiseGetKeyManagerInterface:
+		case EInitializeGetKeyUserInterface:
+		case EInitializeGetKeyUserInterfaceFinished:
+		case EInitializeFinished:
+			// Don't have to cancel initialisation stuff - this happens when we
+			// release the objects in Cleanup().
+			iStatus = KErrCancel;
+			break;
+
+		case EList:
+			if (iKeyStore)
+				{
+				iKeyStore->CancelList();
+				}
+			break;
+
+		case EGetKeyInfo:
+			ASSERT(iKeyStore);
+			iKeyStore->CancelGetKeyInfo();
+			break;
+
+		case EOpen:
+			ASSERT(iKeyStore);
+			iKeyStore->CancelOpen();
+			break;
+
+		case EExportPublic:
+			ASSERT(iKeyStore);
+			iKeyStore->CancelExportPublic();
+			break;			
+
+		case ECreateKey:
+			ASSERT(iKeyStoreManager);
+			iKeyStoreManager->CancelCreateKey();
+			break;
+
+		case EImportKey:
+		case EImportKeyEncrypted:
+			ASSERT(iKeyStoreManager);
+			iKeyStoreManager->CancelImportKey();
+			break;
+			
+		case EExportKey:
+		case EExportEncryptedKey:
+			ASSERT(iKeyStoreManager);
+			iKeyStoreManager->CancelExportKey();
+			break;
+			
+		case EDeleteKey:
+			ASSERT(iKeyStoreManager);
+			iKeyStoreManager->CancelDeleteKey();
+			break;
+
+		case ERelock:
+			ASSERT(iKeyStoreManager);
+			iKeyStoreManager->CancelRelock();
+			break;
+
+		case ESetPassphraseTimeout:
+			ASSERT(iKeyStoreManager);
+			iKeyStoreManager->CancelSetPassphraseTimeout();
+			break;
+		
+	    case ESetUsePolicy:
+			ASSERT(iKeyStoreManager);
+			iKeyStoreManager->CancelSetUsePolicy();
+			break;
+
+	    case ESetManagementPolicy:
+			ASSERT(iKeyStoreManager);
+			iKeyStoreManager->CancelSetManagementPolicy();
+			break;
+
+		default:
+			User::Panic(KUnifiedKeyStore, EUnrecognisedState);
+			break;
+		}
+	}
+
+
+void CUnifiedKeyStore::Complete(TInt aError)
+	{
+	Cleanup();
+	if (iOriginalRequestStatus)
+		{
+		User::RequestComplete(iOriginalRequestStatus, aError);
+		}
+	}
+
+void CUnifiedKeyStore::Cleanup()
+	{
+	// If we have a key info, we want to release it
+	if (iKeyInfo)
+	{
+		iKeyInfo->Release();
+		iKeyInfo = NULL;
+	}
+
+	delete iKeyData;
+	iKeyData = NULL;
+
+	delete iFilter;
+	iFilter = NULL;
+
+	delete iPbeParams;
+	iPbeParams = NULL;
+
+	iTokenTypes.Close();
+
+	if (iTokenType)
+		{
+		iTokenType->Release();
+		iTokenType = 0;
+		}
+
+	iTokens.Close();
+
+	if (iToken)
+		{
+		iToken->Release();
+		iToken = 0;
+		}
+
+	if (iTokenInterface)
+		{
+		iTokenInterface->Release();
+		iTokenInterface = 0;
+		}
+	
+	iKeyInfoOut = NULL;
+	iKeyStore = NULL;
+	iKeyStoreManager = NULL;
+	
+	iState = EIdle;
+	}
+
+CUnifiedKeyStore::CKeyStoreIF::CKeyStoreIF(MCTTokenInterface* aKeyStore, TBool aIsKeyManager)
+:	iKeyStore(aKeyStore), iIsKeyManager(aIsKeyManager)
+{}
+
+CUnifiedKeyStore::CKeyStoreIF::~CKeyStoreIF()
+{
+	if (iKeyStore)
+	{
+		iKeyStore->Release();
+		iKeyStore = NULL;
+	}
+}