diff -r 000000000000 -r 33413c0669b9 vpnengine/pkiservice/src/keyoperationprovider.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vpnengine/pkiservice/src/keyoperationprovider.cpp Thu Dec 17 09:14:51 2009 +0200 @@ -0,0 +1,532 @@ +/* +* Copyright (c) 2008 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: Class, which provides keypair operations. +* +*/ + + +#include + +#include "keyoperationprovider.h" +#include "pkiservicesigner.h" +#include "pkiservicedecryptor.h" +#include "pkisession.h" +#include "pkidefs.h" +#include "logonservices.h" +#include "keymanager.h" +#include "pkiserviceassert.h" +#include "keyoperationqueue.h" + +static const TInt KTimeoutNever = -1; + +CKeyPairOperationProvider* CKeyPairOperationProvider::NewL(CKeyOperationQueue& aKeyOperationQueue) + { + CKeyPairOperationProvider* self = new (ELeave)CKeyPairOperationProvider(aKeyOperationQueue); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + + return self; + } + + +CKeyPairOperationProvider::CKeyPairOperationProvider(CKeyOperationQueue& aKeyOperationQueue) +:CActive(EPriorityStandard), iKeyOperationQueue(aKeyOperationQueue), iOutputDataPtr(NULL, 0) + { + CActiveScheduler::Add(this); + } + + +void CKeyPairOperationProvider::ConstructL() + { + User::LeaveIfError(iFileServer.Connect()); + iUnifiedKeyStore = CUnifiedKeyStore::NewL(iFileServer); + iLogonService = CLogonServices::NewL(*iUnifiedKeyStore); + iKeyManager = CKeyManager::NewL(*iLogonService); + iPkiSigner = CPkiServiceSigner::NewL(*iLogonService); + iPkiDecryptor = CPkiServiceDecryptor::NewL(*iLogonService); + } + + +CKeyPairOperationProvider::~CKeyPairOperationProvider() + { + Cancel(); + + delete iPkiDecryptor; + delete iPkiSigner; + delete iKeyManager; + delete iLogonService; + delete iUnifiedKeyStore; + iFileServer.Close(); + } + + +void CKeyPairOperationProvider::Initialize() + { + PKISERVICE_ASSERT(!IsActive()); + PKISERVICE_ASSERT(iKeyOperation == EKeyOperationIdle); + + iKeyOperation = EKeyOperationInitialize; + if (!iIsInitialized) + { + iUnifiedKeyStore->Initialize(iStatus); + SetActive(); + } + else + { + TRequestStatus* ownStatus = &iStatus; + *ownStatus = KRequestPending; + SetActive(); + User::RequestComplete(ownStatus, KErrNone); + } + } + + +void CKeyPairOperationProvider::GetKeyPairList(const TPKIKeyIdentifier& aKeyId, TInt aUsedKeyStore) + { + PKISERVICE_ASSERT(iIsInitialized); + PKISERVICE_ASSERT(!IsActive()); + PKISERVICE_ASSERT(iKeyOperation == EKeyOperationIdle); + + iKeyOperation = EKeyOperationGetKeyList; + iUsedKeyStore = aUsedKeyStore; + + TCTKeyAttributeFilter filter; + if (aKeyId.Length() > 0) + { + filter.iKeyId = aKeyId; + } + + iUnifiedKeyStore->List(iKeysList, filter, iStatus); + SetActive(); + } + + +void CKeyPairOperationProvider::Decrypt(const TPKIKeyIdentifier& aKeyId, + TInt aUsedKeyStore, + HBufC8* aEncryptedData, + TInt aOutputLength) + { + PKISERVICE_ASSERT(iIsInitialized); + PKISERVICE_ASSERT(!IsActive()); + PKISERVICE_ASSERT(iKeyOperation == EKeyOperationIdle); + PKISERVICE_ASSERT(aKeyId.Length() > 0); + + iKeyOperation = EKeyOperationDecrypting; + TRAPD(err, DecryptL(aKeyId, aUsedKeyStore, aEncryptedData, aOutputLength)); + if (err != KErrNone) + { + iStatus = KRequestPending; + TRequestStatus* ownStatus = &iStatus; + SetActive(); + + User::RequestComplete(ownStatus, err); + } + } + + +void CKeyPairOperationProvider::DecryptL(const TPKIKeyIdentifier& aKeyId, + TInt aUsedKeyStore, + HBufC8* aEncryptedData, + TInt aOutputLength) + { + PKISERVICE_ASSERT(iKeysList.Count() == 0); + PKISERVICE_ASSERT(iInputData == NULL); + PKISERVICE_ASSERT(iKeyOperation == EKeyOperationDecrypting); + + iInputData = aEncryptedData; + iOutputData = HBufC8::NewL(aOutputLength); + iOutputDataPtr.Set(iOutputData->Des()); + + iPkiDecryptor->Decrypt(aKeyId, + *iInputData, + iOutputDataPtr, + *iUnifiedKeyStore, + aUsedKeyStore, + iStatus); + + SetActive(); + } + + +void CKeyPairOperationProvider::Sign(const TPKIKeyIdentifier& aKeyId, + TInt aUsedKeyStore, + HBufC8* aDataToBeSigned) + { + PKISERVICE_ASSERT(iIsInitialized); + PKISERVICE_ASSERT(!IsActive()); + PKISERVICE_ASSERT(iKeyOperation == EKeyOperationIdle); + PKISERVICE_ASSERT(aKeyId.Length() > 0); + PKISERVICE_ASSERT(iKeysList.Count() == 0); + PKISERVICE_ASSERT(iInputData == NULL); + + + iKeyOperation = EKeyOperationSigning; + iInputData = aDataToBeSigned; + + iPkiSigner->Sign(aKeyId, + *iInputData, + iOutputData, + *iUnifiedKeyStore, + aUsedKeyStore, + iStatus); + SetActive(); + } + + +void CKeyPairOperationProvider::Logon() + { + PKISERVICE_ASSERT(iIsInitialized); + PKISERVICE_ASSERT(!IsActive()); + PKISERVICE_ASSERT(iKeyOperation == EKeyOperationIdle); + + iKeyOperation = EKeyOperationLogon; + iLogonService->Logon(iStatus); + SetActive(); + } + + +void CKeyPairOperationProvider::Logoff() + { + PKISERVICE_ASSERT(iIsInitialized); + PKISERVICE_ASSERT(!IsActive()); + PKISERVICE_ASSERT(iKeyOperation == EKeyOperationIdle); + + iKeyOperation = EKeyOperationLogoff; + iLogonService->Logoff(iStatus); + SetActive(); + } + + +void CKeyPairOperationProvider::ChangePassword() + { + PKISERVICE_ASSERT(iIsInitialized); + PKISERVICE_ASSERT(!IsActive()); + PKISERVICE_ASSERT(iKeyOperation == EKeyOperationIdle); + + if (iLogonService->LogonCompleted()) + { + iKeyOperation = EKeyOperationChangingPassword; + iLogonService->ChangePassword(iStatus); + } + else + { + iKeyOperation = EKeyOperationLogonForChangePassword; + iLogonService->Logon(iStatus); + } + + SetActive(); + } + + +void CKeyPairOperationProvider::RemoveKeyPair(const TPKIKeyIdentifier& aKeyId, TInt aUsedKeyStore) + { + PKISERVICE_ASSERT(iIsInitialized); + PKISERVICE_ASSERT(!IsActive()); + PKISERVICE_ASSERT(iKeyOperation == EKeyOperationIdle); + + iKeyOperation = EKeyOperationRemoveKeyPair; + + iKeyManager->RemoveKeyPair(aKeyId, *iUnifiedKeyStore, aUsedKeyStore, iStatus); + SetActive(); + } + + +void CKeyPairOperationProvider::GenerateKeyPair(const TUint aKeySize, + TPKIKeyAlgorithm aKeyAlgorithm, + TInt aUsedKeyStore) + { + PKISERVICE_ASSERT(iIsInitialized); + PKISERVICE_ASSERT(!IsActive()); + PKISERVICE_ASSERT(iKeyOperation == EKeyOperationIdle); + + iKeyOperation = EKeyOperationGeneratingKeyPair; + + iKeyManager->GenerateKeyPair(*iUnifiedKeyStore, aUsedKeyStore, aKeySize, + aKeyAlgorithm, iKeyId, iStatus); + SetActive(); + } + + +void CKeyPairOperationProvider::ImportKeyPair(HBufC8* aKeyData, TInt aUsedKeyStore) + { + PKISERVICE_ASSERT(iIsInitialized); + PKISERVICE_ASSERT(!IsActive()); + PKISERVICE_ASSERT(iKeyOperation == EKeyOperationIdle); + + iKeyOperation = EKeyOperationImportingKeyPair; + iInputData = aKeyData; + + iKeyManager->ImportKeyPair(*iUnifiedKeyStore, aUsedKeyStore, *iInputData, iKeyId, iStatus); + SetActive(); + } + + +void CKeyPairOperationProvider::GetPublicKey(const TPKIKeyIdentifier& aKeyId, TInt aUsedKeyStore) + { + PKISERVICE_ASSERT(iIsInitialized); + PKISERVICE_ASSERT(!IsActive()); + PKISERVICE_ASSERT(iKeyOperation == EKeyOperationIdle); + + iKeyOperation = EKeyOperationPublicKeyExport; + + iKeyManager->ExportPublicKey(*iUnifiedKeyStore, aUsedKeyStore, aKeyId, iOutputData, iStatus); + SetActive(); + } + + + +void CKeyPairOperationProvider::RunL() + { + switch(iKeyOperation) + { + case EKeyOperationInitialize: + { + iKeyOperation = EKeyOperationIdle; + TInt err = iStatus.Int(); + if (err == KErrNone) + { + if (!iIsInitialized) + { + iKeyOperation = EKeyOperationSetPassPhraseTimeout; + iUnifiedKeyStore->SetPassphraseTimeout(KTimeoutNever, iStatus); + SetActive(); + } + else + {//keystore is already initialized + iKeyOperationQueue.KeyStoreInitComplete(err); + } + } + else + { + iKeyOperationQueue.KeyStoreInitComplete(err); + } + } + break; + case EKeyOperationSetPassPhraseTimeout: + iKeyOperation = EKeyOperationIdle; + if (iStatus.Int() == KErrNone) + { + iIsInitialized = ETrue; + } + iKeyOperationQueue.KeyStoreInitComplete(iStatus.Int()); + break; + case EKeyOperationGetKeyList: + { + PKISERVICE_ASSERT(iIsInitialized); + iKeyOperation = EKeyOperationIdle; + + CArrayFixFlat* list = NULL; + TInt err = iStatus.Int(); + if (err == KErrNone) + { + TRAP(err, list = MakeKeyEntryListL(iKeysList, iUsedKeyStore)); + } + CleanupCryptoOperation(); + iKeyOperationQueue.KeyPairListComplete(err, list); + } + break; + case EKeyOperationDecrypting: + { + PKISERVICE_ASSERT(iIsInitialized); + iKeyOperation = EKeyOperationIdle; + HBufC8* plainTextData = NULL; + if (iStatus.Int() == KErrNone) + { + plainTextData = iOutputData; + iOutputData = NULL; + } + CleanupCryptoOperation(); + iKeyOperationQueue.DecryptComplete(iStatus.Int(), plainTextData); + } + break; + case EKeyOperationSigning: + { + PKISERVICE_ASSERT(iIsInitialized); + iKeyOperation = EKeyOperationIdle; + HBufC8* data = iOutputData; + iOutputData = NULL; + CleanupCryptoOperation(); + iKeyOperationQueue.SignComplete(iStatus.Int(), data); + } + break; + case EKeyOperationPublicKeyExport: + { + PKISERVICE_ASSERT(iIsInitialized); + iKeyOperation = EKeyOperationIdle; + + PKISERVICE_ASSERT((iStatus.Int() == KErrNone && iOutputData != NULL) || + (iStatus.Int() != KErrNone && iOutputData == NULL)); + + HBufC8* publicKeyData = iOutputData; + iOutputData = NULL; + CleanupCryptoOperation(); + iKeyOperationQueue.GetPublicKeyCompleted(iStatus.Int(), publicKeyData); + } + break; + case EKeyOperationLogon: + iKeyOperation = EKeyOperationIdle; + iKeyOperationQueue.LogonCompleted(iStatus.Int()); + break; + case EKeyOperationLogoff: + iKeyOperation = EKeyOperationIdle; + iKeyOperationQueue.LogoffCompleted(iStatus.Int()); + break; + case EKeyOperationLogonForChangePassword: + iKeyOperation = EKeyOperationIdle; + if (iStatus.Int() == KErrNone) + { + iKeyOperation = EKeyOperationChangingPassword; + iLogonService->ChangePassword(iStatus); + SetActive(); + } + else + { + iKeyOperationQueue.PasswordChangeCompleted(iStatus.Int()); + } + break; + case EKeyOperationChangingPassword: + iKeyOperation = EKeyOperationIdle; + iKeyOperationQueue.PasswordChangeCompleted(iStatus.Int()); + break; + case EKeyOperationRemoveKeyPair: + iKeyOperation = EKeyOperationIdle; + iKeyOperationQueue.KeyPairRemoveCompleted(iStatus.Int()); + break; + case EKeyOperationGeneratingKeyPair: + { + iKeyOperation = EKeyOperationIdle; + TPKIKeyIdentifier keyId = iKeyId; + iKeyId.Zero(); + iKeyOperationQueue.KeyGenerationCompleted(iStatus.Int(), keyId); + } + break; + case EKeyOperationImportingKeyPair: + { + delete iInputData; + iInputData = NULL; + iKeyOperation = EKeyOperationIdle; + TPKIKeyIdentifier keyId = iKeyId; + iKeyId.Zero(); + iKeyOperationQueue.StoreKeyPairCompleted(iStatus.Int(), keyId); + } + break; + default: + PKISERVICE_INVARIANT(); + } + } + + +void CKeyPairOperationProvider::DoCancel() + { + switch(iKeyOperation) + { + case EKeyOperationInitialize: + PKISERVICE_ASSERT(!iIsInitialized); + iUnifiedKeyStore->CancelInitialize(); + break; + case EKeyOperationSetPassPhraseTimeout: + iUnifiedKeyStore->CancelSetPassphraseTimeout(); + break; + case EKeyOperationGetKeyList: + PKISERVICE_ASSERT(iIsInitialized); + iUnifiedKeyStore->CancelList(); + break; + case EKeyOperationDecrypting: + //Deletes and cancels the decryptor also + CleanupCryptoOperation(); + break; + case EKeyOperationSigning: + //Deletes and cancels the signer also. + CleanupCryptoOperation(); + break; + case EKeyOperationLogon: //falls through + case EKeyOperationLogoff: //falls through + case EKeyOperationLogonForChangePassword: //falls through + case EKeyOperationChangingPassword: + iLogonService->Cancel(); + break; + case EKeyOperationRemoveKeyPair: //falls through + case EKeyOperationGeneratingKeyPair://falls through + case EKeyOperationImportingKeyPair://falls through + case EKeyOperationPublicKeyExport: + iKeyManager->Cancel(); + break; + default: + PKISERVICE_INVARIANT(); + } + iKeyOperation = EKeyOperationIdle; + } + + +TInt CKeyPairOperationProvider::RunError(TInt aError) + { + //This is not be called, because the RunL doesn't + //leave. + PKISERVICE_INVARIANT(); + return aError; + } + + +CArrayFixFlat* CKeyPairOperationProvider::MakeKeyEntryListL(RMPointerArray aKeysList, + TInt aUsedKeyStore) const + { + CArrayFixFlat* list = new (ELeave) CArrayFixFlat(2); + CleanupStack::PushL(list); + + for (TInt i = 0; i < aKeysList.Count(); ++i) + { + const CCTKeyInfo* info = aKeysList[i]; + if (aUsedKeyStore == 0 || + aUsedKeyStore == aKeysList[i]->Token().TokenType().Type().iUid) + { + TKeyListEntry keyInfo; + keyInfo.iObjectName = info->Label(); + keyInfo.iSubjectKeyId = info->ID(); + keyInfo.iKeySize = info->Size(); // Key size + switch(info->Algorithm()) + { + case CCTKeyInfo::ERSA: + keyInfo.iKeyAlgorithm = EPKIRSA; + break; + case CCTKeyInfo::EDSA: + keyInfo.iKeyAlgorithm = EPKIDSA; + break; + case CCTKeyInfo::EDH: + keyInfo.iKeyAlgorithm = EPKIDH; + break; + default: + keyInfo.iKeyAlgorithm = EPKIInvalidAlgorithm; + break; + } + list->AppendL(keyInfo); + } + } + CleanupStack::Pop(list); + return list; + } + + + +void CKeyPairOperationProvider::CleanupCryptoOperation() + { + delete iInputData; + iInputData = NULL; + + delete iOutputData; + iOutputData = NULL; + iKeysList.Close(); + } + +