diff -r 000000000000 -r 2c201484c85f cryptoservices/certificateandkeymgmt/certstore/unifiedkeystore.cpp --- /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 +#include +#include +#include + +_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 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& 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(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(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(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(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(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(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(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; + } +}