--- /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 <asymmetric.h>
+
+#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<TKeyListEntry>* 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<TKeyListEntry>* CKeyPairOperationProvider::MakeKeyEntryListL(RMPointerArray<CCTKeyInfo> aKeysList,
+ TInt aUsedKeyStore) const
+ {
+ CArrayFixFlat<TKeyListEntry>* list = new (ELeave) CArrayFixFlat<TKeyListEntry>(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();
+ }
+
+