--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/cryptoservices/filebasedcertificateandkeystores/source/keystore/Server/Ckeystoreconduit.cpp Wed Jul 08 11:25:26 2009 +0100
@@ -0,0 +1,1013 @@
+/*
+* Copyright (c) 2004-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 "CKeyStoreConduit.h"
+#include "cfskeystoreserver.h"
+#include "CKeyStoreSession.h"
+#include "OpenedKeys.h"
+#include "fsdatatypes.h"
+#include "fsmarshaller.h"
+#include "fstokenutil.h"
+#include <asymmetric.h>
+#include <pbedata.h>
+#include <mctkeystoremanager.h>
+
+// CKeyStoreConduit ////////////////////////////////////////////////////////////
+
+// can keep pointer to session as member
+// also, do we need to pass the RMessage everywhere?
+
+/*static*/ CKeyStoreConduit* CKeyStoreConduit::NewL(CFSKeyStoreServer& aServer)
+{
+ CKeyStoreConduit* self = new (ELeave) CKeyStoreConduit(aServer);
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop(self);
+ return self;
+}
+
+CKeyStoreConduit::~CKeyStoreConduit()
+ {
+ Cancel();
+ }
+
+CKeyStoreConduit::CKeyStoreConduit(CFSKeyStoreServer& aServer)
+ : CActive(EPriorityHigh), iServer(aServer), iCurrentRequest(iStatus)
+ {
+ }
+
+void CKeyStoreConduit::ConstructL()
+ {
+ CActiveScheduler::Add(this);
+ }
+
+void CKeyStoreConduit::ServiceRequestL(const RMessage2& aMessage, CKeyStoreSession& aSession)
+ {
+ TFSTokenMessages request = static_cast<TFSTokenMessages>(aMessage.Function());
+
+ if (iCurrentRequest.OutstandingRequest()!=EIdle)
+ {
+ // There is currently a request outstanding, only allow this one if it's a cancel
+ if ( (request!=ECancelCreateKey) &&
+ (request!=ECancelImportKey) &&
+ (request!=ECancelImportEncryptedKey) &&
+ (request!=ECancelExportKey) &&
+ (request!=ECancelExportEncryptedKey) &&
+ (request!=ECancelRSASign) &&
+ (request!=ECancelDSASign) &&
+ (request!=ECancelDecrypt) &&
+ (request!=ECancelChangePassphrase) &&
+ (request!=ECancelAuthOpen))
+ {
+ User::Leave(KErrServerBusy);
+ }
+ }
+
+ switch (request)
+ {
+ case EListKeys:
+ ListL(aMessage);
+ break;
+ case EGetKeyInfo:
+ GetKeyInfoL(aMessage);
+ break;
+ case ECreateKey:
+ CreateKeyL(aMessage);
+ break;
+ case ECancelCreateKey:
+ CancelCreateKey(aMessage);
+ break;
+ case EImportKey:
+ case EImportEncryptedKey:
+ ImportKeyL(aMessage);
+ break;
+ case ECancelImportKey:
+ case ECancelImportEncryptedKey:
+ CancelImportKey(aMessage);
+ break;
+ case EExportKey:
+ ExportKeyL(aMessage);
+ break;
+ case ECancelExportKey:
+ CancelExportKey(aMessage);
+ break;
+ case EExportEncryptedKey:
+ ExportKeyL(aMessage);
+ break;
+ case ECancelExportEncryptedKey:
+ CancelExportEncryptedKey(aMessage);
+ break;
+ case EExportPublic:
+ ExportPublicL(aMessage);
+ break;
+ case EGetKeyLength:
+ GetKeyLengthL(aMessage);
+ break;
+ case EDeleteKey:
+ DeleteKeyL(aMessage);
+ break;
+ case ESetUsePolicy:
+ SetUsePolicyL(aMessage);
+ break;
+ case ESetManagementPolicy:
+ SetManagementPolicyL(aMessage);
+ break;
+ case EOpenKeyRepudiableRSASign:
+ OpenKeyL(aMessage, aSession, KRSARepudiableSignerUID);
+ break;
+ case EOpenKeyRepudiableDSASign:
+ OpenKeyL(aMessage, aSession, KDSARepudiableSignerUID);
+ break;
+ case EOpenKeyDecrypt:
+ OpenKeyL(aMessage, aSession, KPrivateDecryptorUID);
+ break;
+ case EOpenKeyAgree:
+ OpenKeyL(aMessage, aSession, KKeyAgreementUID);
+ break;
+ case ECloseObject:
+ CloseObjectL(aMessage, aSession);
+ break;
+ case ERepudiableDSASign:
+ RepudiableDSASignL(aMessage, aSession);
+ break;
+ case ECancelDSASign:
+ CancelDSASign(aMessage, aSession);
+ break;
+ case ERepudiableRSASign:
+ RepudiableRSASignL(aMessage, aSession);
+ break;
+ case ECancelRSASign:
+ CancelRSASign(aMessage, aSession);
+ break;
+ case EDecryptText:
+ DecryptL(aMessage, aSession);
+ break;
+ case ECancelDecrypt:
+ CancelDecrypt(aMessage, aSession);
+ break;
+ case EDHPublicKey:
+ DHPublicKeyL(aMessage, aSession);
+ break;
+ case EDHAgree:
+ DHAgreeL(aMessage, aSession);
+ break;
+ case ECancelDH:
+ CancelDH(aMessage, aSession);
+ break;
+ case EChangePassphrase:
+ ChangePassphrase(aMessage);
+ break;
+ case ECancelChangePassphrase:
+ CancelChangePassphrase(aMessage);
+ break;
+ case EAuthOpen:
+ AuthOpen(aMessage);
+ break;
+ case ECancelAuthOpen:
+ CancelAuthOpen(aMessage);
+ break;
+ case EAuthClose:
+ AuthClose(aMessage);
+ break;
+ case EAuthTimeRemaining:
+ GetTimeRemaining(aMessage);
+ break;
+ case ESetTimeout:
+ SetTimeout(aMessage);
+ break;
+ case EGetTimeout:
+ GetTimeout(aMessage);
+ break;
+ case ERelock:
+ Relock(aMessage);
+ break;
+ default: // Should not reach here
+ PanicClient(aMessage,EPanicIllegalFunction);
+ break;
+ }
+ }
+
+void CKeyStoreConduit::ListL(const RMessage2& aMessage)
+ {
+ // p[0] has the filter to use
+ RCPointerArray<CKeyInfo> keyInfos;
+ CleanupClosePushL(keyInfos);
+
+ TPckgBuf<TCTKeyAttributeFilter> filter;
+ aMessage.ReadL(0, filter);
+
+ iServer.ListL(filter(), keyInfos);
+
+ TInt bufSize = User::LeaveIfError(aMessage.GetDesMaxLength(2));
+ TInt reqdSize = TokenDataMarshaller::Size(keyInfos);
+ if (bufSize >= reqdSize)
+ {
+ HBufC8* buffer = HBufC8::NewMaxLC(reqdSize);
+ TPtr8 thePtr(buffer->Des());
+ TokenDataMarshaller::Write(keyInfos, thePtr);
+ aMessage.WriteL(2, thePtr);
+ CleanupStack::PopAndDestroy(buffer);
+ }
+ else
+ {
+ TPckg<TInt> sizePckg(reqdSize);
+ aMessage.WriteL(2, sizePckg);
+ User::Leave(KErrOverflow);
+ }
+
+ CleanupStack::PopAndDestroy(&keyInfos); // keyInfos
+ aMessage.Complete(KErrNone);
+ }
+
+void CKeyStoreConduit::GetKeyInfoL(const RMessage2& aMessage)
+ {
+ // Token object to delete is in p[0]
+ TInt objectId = aMessage.Int0();
+ CKeyInfo* info = NULL;
+ iServer.GetKeyInfoL(objectId, info);
+ info->CleanupPushL();
+
+ TInt bufferSize = User::LeaveIfError(aMessage.GetDesMaxLength(2));
+ TInt requiredSize = TokenDataMarshaller::Size(*info);
+
+ if (bufferSize >= requiredSize)
+ {
+ HBufC8* buffer = HBufC8::NewMaxLC(requiredSize);
+ TPtr8 thePtr(buffer->Des());
+ TokenDataMarshaller::Write(*info, thePtr);
+ aMessage.WriteL(2, thePtr);
+ CleanupStack::PopAndDestroy(buffer);
+ }
+ else
+ {
+ TPckg<TInt> theSize(requiredSize);
+ aMessage.WriteL(2, theSize);
+ User::Leave(KErrOverflow);
+ }
+
+ CleanupStack::PopAndDestroy(info);
+ aMessage.Complete(KErrNone);
+ }
+
+/** Work out the UID of the client process. */
+TUid CKeyStoreConduit::GetClientUidL(const RMessage2& aMessage) const
+ {
+ RThread clientThread;
+ User::LeaveIfError(aMessage.Client(clientThread));
+ CleanupClosePushL(clientThread);
+ RProcess clientProcess;
+ User::LeaveIfError(clientThread.Process(clientProcess));
+ CleanupClosePushL(clientProcess);
+ TUid uid = clientProcess.Type()[2];
+ CleanupStack::PopAndDestroy(2); // clientProcess, clientThread
+ return uid;
+ }
+
+void CKeyStoreConduit::CreateKeyL(const RMessage2& aMessage)
+ {
+ ASSERT(!iKeyInfo);
+
+ // p[0] has the length of the buffer. Check our buffer is big
+ // enough, to cope with requests for keys with very long labels.
+
+ TInt bufLength = User::LeaveIfError(aMessage.GetDesLength(1));
+ HBufC8* keyInfoBuf = HBufC8::NewMaxLC(bufLength);
+
+ // p[1] has the CKeyInfo structure required to create a key
+ // Read it and convert from descriptor back to a CKeyInfo
+ TPtr8 thePtr(keyInfoBuf->Des());
+ thePtr.FillZ();
+
+ aMessage.ReadL(1, thePtr);
+ TokenDataMarshaller::ReadL(*keyInfoBuf, iKeyInfo);
+ CleanupStack::PopAndDestroy(keyInfoBuf);
+
+ iCurrentRequest.Set(ECreateKey, aMessage);
+ iStatus = KRequestPending;
+ SetActive();
+ iServer.CreateKey(*iKeyInfo, iStatus);
+ }
+
+void CKeyStoreConduit::CancelCreateKey(const RMessage2& aMessage)
+ {
+ if (iCurrentRequest.OutstandingRequest() == ECreateKey)
+ {
+ Cancel();
+ }
+ aMessage.Complete(KErrNone);
+ }
+
+void CKeyStoreConduit::ImportKeyL(const RMessage2& aMessage)
+ {
+ ASSERT(!iImportKey);
+ ASSERT(!iKeyInfo);
+
+ // p[0] has the descriptor containing the PKCS8 object (may or may not be encrypted)
+ TInt keyLen = User::LeaveIfError(aMessage.GetDesLength(0));
+
+ HBufC8* importBuf = HBufC8::NewMaxLC(keyLen);
+ TPtr8 theKeyData(importBuf->Des());
+ theKeyData.FillZ();
+ aMessage.ReadL(0, theKeyData);
+
+ TInt bufLen = User::LeaveIfError(aMessage.GetDesLength(1));
+ HBufC8* keyInfoBuf = HBufC8::NewMaxLC(bufLen);
+
+ // p[1] has the CKeyInfo structure required to create a key
+ // Read it and convert from descriptor back to a CKeyInfo
+ TPtr8 thePtr(keyInfoBuf->Des());
+ thePtr.FillZ();
+ aMessage.ReadL(1, thePtr);
+
+ TokenDataMarshaller::ReadL(*keyInfoBuf, iKeyInfo);
+ CleanupStack::PopAndDestroy(keyInfoBuf);
+
+ iImportKey = importBuf;
+ CleanupStack::Pop(importBuf);
+
+ iCurrentRequest.Set(static_cast<TFSTokenMessages>(aMessage.Function()), aMessage);
+ iStatus = KRequestPending;
+ SetActive();
+
+ TBool isEncrypted = (aMessage.Function() == EImportEncryptedKey);
+ iServer.ImportKey(*iImportKey, *iKeyInfo, isEncrypted, iStatus);
+}
+
+void CKeyStoreConduit::CancelImportKey(const RMessage2& aMessage)
+ {
+ if (iCurrentRequest.OutstandingRequest() == EImportKey ||
+ iCurrentRequest.OutstandingRequest() == EImportEncryptedKey)
+ {
+ Cancel();
+ }
+ aMessage.Complete(KErrNone);
+ }
+
+void CKeyStoreConduit::GetKeyLengthL(const RMessage2& aMessage)
+ {
+ TInt length = iServer.GetKeyLengthL(aMessage.Int0());
+ ASSERT(length > 0);
+ aMessage.Complete(length);
+ }
+
+void CKeyStoreConduit::CancelExportKey(const RMessage2& aMessage)
+ {
+ if (iCurrentRequest.OutstandingRequest() == EExportKey)
+ {
+ Cancel();
+ }
+ aMessage.Complete(KErrNone);
+ }
+
+void CKeyStoreConduit::CancelExportEncryptedKey(const RMessage2& aMessage)
+ {
+ if (iCurrentRequest.OutstandingRequest() == EExportEncryptedKey)
+ {
+ Cancel();
+ }
+ aMessage.Complete(KErrNone);
+ }
+
+void CKeyStoreConduit::ExportKeyL(const RMessage2& aMessage)
+ {
+ ASSERT(!iExportBuf);
+ ASSERT(!iPbeParams);
+
+ TInt objectId = aMessage.Int0();
+ TInt bufLen = User::LeaveIfError(aMessage.GetDesMaxLength(1)); // #1 IPC argument is the request Ptr
+
+ HBufC8* exportBuf = HBufC8::NewMaxLC(bufLen);
+ TPtr8 temp(exportBuf->Des());
+ temp.FillZ();
+
+ if (aMessage.Function() == EExportEncryptedKey)
+ {
+ TInt paramsLen = User::LeaveIfError(aMessage.GetDesLength(2));
+ HBufC8* pbeParamsBuf = HBufC8::NewMaxLC(paramsLen);
+ TPtr8 thePtr(pbeParamsBuf->Des());
+ thePtr.FillZ();
+ aMessage.ReadL(2, thePtr);
+
+ TokenDataMarshaller::ReadL(*pbeParamsBuf, iPbeParams);
+ CleanupStack::PopAndDestroy(pbeParamsBuf);
+ }
+
+ // No more leaves
+
+ iExportBuf = exportBuf;
+ CleanupStack::Pop(exportBuf);
+
+ iCurrentRequest.Set(static_cast<TFSTokenMessages>(aMessage.Function()), aMessage);
+ iStatus = KRequestPending;
+ SetActive();
+
+ if (aMessage.Function() == EExportKey)
+ {
+ iServer.ExportKey(objectId, temp, iStatus);
+ }
+ else if (aMessage.Function() == EExportEncryptedKey)
+ {
+ iServer.ExportEncryptedKey(objectId, temp, *iPbeParams, iStatus);
+ }
+ }
+
+void CKeyStoreConduit::ExportPublicL(const RMessage2& aMessage)
+ {
+ TInt objectId = aMessage.Int0();
+ TInt bufLen = User::LeaveIfError(aMessage.GetDesMaxLength(1));
+
+ HBufC8* exportBuf = HBufC8::NewMaxLC(bufLen);
+ TPtr8 ptr(exportBuf->Des());
+ ptr.FillZ();
+ iServer.ExportPublicL(objectId, ptr);
+ aMessage.WriteL(1, ptr);
+
+ CleanupStack::PopAndDestroy(exportBuf);
+ aMessage.Complete(KErrNone);
+ }
+
+void CKeyStoreConduit::DeleteKeyL(const RMessage2& aMessage)
+ {
+ TInt objectId = aMessage.Int0();
+ iServer.DeleteKeyL(objectId);
+ aMessage.Complete(KErrNone);
+ }
+
+void CKeyStoreConduit::SetUsePolicyL(const RMessage2& aMessage)
+ {
+ TInt objectId = aMessage.Int0();
+ TSecurityPolicyBuf policyBuf;
+
+ aMessage.ReadL(1, policyBuf);
+
+ iServer.SetUsePolicyL(objectId, policyBuf());
+ aMessage.Complete(KErrNone);
+ }
+
+void CKeyStoreConduit::SetManagementPolicyL(const RMessage2& aMessage)
+ {
+ TInt objectId = aMessage.Int0();
+ TSecurityPolicyBuf policyBuf;
+
+ aMessage.ReadL(1, policyBuf);
+
+ iServer.SetManagementPolicyL(objectId, policyBuf());
+ aMessage.Complete(KErrNone);
+ }
+
+void CKeyStoreConduit::OpenKeyL(const RMessage2& aMessage, CKeyStoreSession& aSession, TUid aType)
+ {
+ COpenedKey* openedKey = iServer.OpenKeyL(aMessage.Int0(), aType);
+ CleanupStack::PushL(openedKey);
+
+ const TDesC& label = openedKey->Label();
+
+ TInt writeBufLen = User::LeaveIfError(aMessage.GetDesMaxLength(3));
+ TInt reqdLength = label.Length();
+ if (writeBufLen < reqdLength)
+ {
+ // We're writing into a TDes16 so we can't use TPckg<TInt>
+ TPtrC sizePtr(reinterpret_cast<TUint16*>(&reqdLength), 2);
+ aMessage.WriteL(3, sizePtr);
+ User::Leave(KErrOverflow);
+ }
+
+ aMessage.WriteL(3, label);
+
+ TInt handle = aSession.AddOpenedKeyL(*openedKey);
+
+ TPckg<TInt> handlePckg(handle);
+ TRAPD(err, aMessage.WriteL(1, handlePckg));
+
+ if (err != KErrNone)
+ {
+ aSession.RemoveOpenedKeyL(handle);
+ User::Leave(err);
+ }
+
+ CleanupStack::Pop(openedKey); // now owned by session
+ aMessage.Complete(KErrNone);
+ }
+
+void CKeyStoreConduit::RepudiableRSASignL(const RMessage2& aMessage, CKeyStoreSession& aSession)
+ {
+ ASSERT(iOpenedKey == NULL);
+ TPtr8 thePtr(0,0);
+ iOpenedKey = ProcessL(aMessage, aSession, KRSARepudiableSignerUID, ERepudiableRSASign, thePtr);
+ static_cast<CRSARepudiableSigner*>(iOpenedKey)->Sign(thePtr, iRSASignature, iStatus);
+ }
+
+void CKeyStoreConduit::CancelRSASign(const RMessage2& aMessage, CKeyStoreSession& aSession)
+ {
+ if (iCurrentRequest.OutstandingRequest() == ERepudiableRSASign)
+ {
+ aSession.PassphraseManager().Cancel();
+ Cancel();
+ }
+ aMessage.Complete(KErrNone);
+ }
+
+void CKeyStoreConduit::RepudiableDSASignL(const RMessage2& aMessage, CKeyStoreSession& aSession)
+ {
+ ASSERT(iOpenedKey == NULL);
+ TPtr8 thePtr(0,0);
+ iOpenedKey = ProcessL(aMessage, aSession, KDSARepudiableSignerUID, ERepudiableDSASign, thePtr);
+ static_cast<CDSARepudiableSigner*>(iOpenedKey)->Sign(thePtr, iDSASignature, iStatus);
+ }
+
+void CKeyStoreConduit::CancelDSASign(const RMessage2& aMessage, CKeyStoreSession& aSession)
+ {
+ if (iCurrentRequest.OutstandingRequest() == ERepudiableDSASign)
+ {
+ aSession.PassphraseManager().Cancel();
+ Cancel();
+ }
+ aMessage.Complete(KErrNone);
+ }
+
+void CKeyStoreConduit::DecryptL(const RMessage2& aMessage, CKeyStoreSession& aSession)
+ {
+ ASSERT(iOpenedKey == NULL);
+ TPtr8 thePtr(0,0);
+ iOpenedKey = ProcessL(aMessage, aSession, KPrivateDecryptorUID, EDecryptText, thePtr);
+ static_cast<CFSRSADecryptor*>(iOpenedKey)->Decrypt(thePtr, iPlaintext, iStatus);
+ }
+
+void CKeyStoreConduit::CancelDecrypt(const RMessage2& aMessage, CKeyStoreSession& aSession)
+ {
+ if (iCurrentRequest.OutstandingRequest() == EDecryptText)
+ {
+ aSession.PassphraseManager().Cancel();
+ Cancel();
+ }
+ aMessage.Complete(KErrNone);
+ }
+
+COpenedKey* CKeyStoreConduit::ProcessL(const RMessage2& aMessage,
+ CKeyStoreSession& aSession,
+ const TUid& aCKeyInfoID,
+ const TFSTokenMessages& aState,
+ TPtr8& aTextPtr)
+ {
+ COpenedKey* object = aSession.OpenedKey(aMessage.Int0());
+ if (!object)
+ {
+ User::Leave(KErrNotFound);
+ }
+
+ if (aCKeyInfoID != object->Type())
+ {
+ User::Leave(KErrAccessDenied);
+ }
+
+ TInt length = User::LeaveIfError(aMessage.GetDesLength(1));
+ iText = HBufC8::NewL(length);
+ aTextPtr.Set(iText->Des());
+ aMessage.ReadL(1, aTextPtr);
+
+ iCurrentRequest.Set(aState, aMessage);
+ iStatus=KRequestPending;
+ SetActive();
+
+ return object;
+ }
+
+void CKeyStoreConduit::DHPublicKeyL(const RMessage2& aMessage, CKeyStoreSession& aSession)
+ {
+ // 0: Object id
+ // 1: DH paramters
+
+ ASSERT(iDHParams == NULL);
+ ASSERT(iOpenedKey == NULL);
+ TRAPD(err, DoDHPublicKeyL(aMessage, aSession));
+ if (err != KErrNone)
+ {
+ iOpenedKey = NULL;
+ delete iDHParams;
+ iDHParams = NULL;
+ User::Leave(err);
+ }
+ }
+
+void CKeyStoreConduit::DoDHPublicKeyL(const RMessage2& aMessage, CKeyStoreSession& aSession)
+ {
+ iOpenedKey = aSession.OpenedKey(aMessage.Int0());
+ if (!iOpenedKey)
+ {
+ User::Leave(KErrNotFound);
+ }
+
+ //Check that this is a DH object
+ if (KKeyAgreementUID != iOpenedKey->Type())
+ {
+ iOpenedKey = NULL;
+ User::Leave(KErrAccessDenied);
+ }
+
+ HBufC8* clientBuf = HBufC8::NewMaxLC(User::LeaveIfError(aMessage.GetDesLength(1)));
+ TPtr8 clientPtr = clientBuf->Des();
+ aMessage.ReadL(1, clientPtr);
+ TokenDataMarshaller::ReadL(*clientBuf, iDHParams);
+ CleanupStack::PopAndDestroy(clientBuf);
+
+ static_cast<CDHAgreement*>(iOpenedKey)->PublicKey(*iDHParams, iDHPublicKeyOut, iStatus);
+
+ iCurrentRequest.Set(EDHPublicKey, aMessage);
+ iStatus=KRequestPending;
+ SetActive();
+ }
+
+void CKeyStoreConduit::FinishDHPublicKeyL()
+ {
+ // Client buffer must be big enough for result because it had the DH
+ // parameters in it
+ TInt reqdSize = TokenDataMarshaller::Size(iDHPublicKeyOut);
+ ASSERT(reqdSize <= iCurrentRequest.Message().GetDesMaxLength(1));
+
+ HBufC8* clientBuf = HBufC8::NewMaxLC(reqdSize);
+ TPtr8 clientPtr = clientBuf->Des();
+ TokenDataMarshaller::WriteL(iDHPublicKeyOut, clientPtr);
+ iCurrentRequest.Message().WriteL(1, clientPtr);
+ CleanupStack::PopAndDestroy(clientBuf);
+ }
+
+void CKeyStoreConduit::DHAgreeL(const RMessage2& aMessage, CKeyStoreSession& aSession)
+ {
+ // 0: Object id
+ // 1: DH public key
+
+ ASSERT(iOpenedKey == NULL);
+ ASSERT(iDHPublicKey == NULL);
+ TRAPD(err, DoDHAgreeL(aMessage, aSession));
+ if (err != KErrNone)
+ {
+ iOpenedKey = NULL;
+ delete iDHPublicKey;
+ iDHPublicKey = NULL;
+ User::Leave(err);
+ }
+ }
+
+void CKeyStoreConduit::DoDHAgreeL(const RMessage2& aMessage, CKeyStoreSession& aSession)
+ {
+ COpenedKey* iOpenedKey = aSession.OpenedKey(aMessage.Int0());
+ if (!iOpenedKey)
+ {
+ User::Leave(KErrNotFound);
+ }
+
+ //Check that this is a DH object
+ if (KKeyAgreementUID != iOpenedKey->Type())
+ {
+ iOpenedKey = NULL;
+ User::Leave(KErrAccessDenied);
+ }
+
+ HBufC8* clientBuf = HBufC8::NewMaxLC(User::LeaveIfError(aMessage.GetDesLength(1)));
+ TPtr8 clientPtr = clientBuf->Des();
+ aMessage.ReadL(1, clientPtr);
+ TokenDataMarshaller::ReadL(*clientBuf, iDHPublicKey);
+ CleanupStack::PopAndDestroy(clientBuf);
+
+ static_cast<CDHAgreement*>(iOpenedKey)->Agree(*iDHPublicKey, iDHAgreedKeyOut, iStatus);
+
+ iCurrentRequest.Set(EDHAgree, aMessage);
+ iStatus=KRequestPending;
+ SetActive();
+ }
+
+void CKeyStoreConduit::FinishDHAgreeL()
+ {
+ // Client buffer must be big enough for result because it had the DH
+ // public key in it
+ ASSERT(iDHAgreedKeyOut->Length() <= iCurrentRequest.Message().GetDesMaxLength(1));
+
+ iCurrentRequest.Message().WriteL(1, *iDHAgreedKeyOut);
+ }
+
+void CKeyStoreConduit::CancelDH(const RMessage2& aMessage, CKeyStoreSession& aSession)
+ {
+ if (iCurrentRequest.OutstandingRequest() == EDHPublicKey ||
+ iCurrentRequest.OutstandingRequest() == EDHAgree)
+ {
+ aSession.PassphraseManager().Cancel();
+ Cancel();
+ }
+ aMessage.Complete(KErrNone);
+ }
+
+void CKeyStoreConduit::CloseObjectL(const RMessage2& aMessage, CKeyStoreSession& aSession)
+ {
+ aSession.RemoveOpenedKeyL(aMessage.Int0());
+ aMessage.Complete(KErrNone);
+ }
+
+void CKeyStoreConduit::ChangePassphrase(const RMessage2& aMessage)
+ {
+ iCurrentRequest.Set(EChangePassphrase, aMessage);
+ iStatus=KRequestPending;
+ SetActive();
+ iServer.ChangePassphrase(iStatus);
+ }
+
+void CKeyStoreConduit::CancelChangePassphrase(const RMessage2& aMessage)
+ {
+ if (iCurrentRequest.OutstandingRequest() == EChangePassphrase)
+ {
+ Cancel();
+ }
+ aMessage.Complete(KErrNone);
+ }
+
+void CKeyStoreConduit::AuthOpen(const RMessage2& aMessage)
+ {
+ iCurrentRequest.Set(EAuthOpen, aMessage);
+ iStatus=KRequestPending;
+ SetActive();
+ iServer.AuthOpen(iStatus);
+ }
+
+void CKeyStoreConduit::CancelAuthOpen(const RMessage2& aMessage)
+ {
+ if (iCurrentRequest.OutstandingRequest() == EAuthOpen)
+ {
+ Cancel();
+ }
+ aMessage.Complete(KErrNone);
+ }
+
+void CKeyStoreConduit::AuthClose(const RMessage2& aMessage)
+ {
+ iServer.AuthClose();
+ aMessage.Complete(KErrNone);
+ }
+
+void CKeyStoreConduit::GetTimeRemaining(const RMessage2& aMessage)
+ {
+ TInt result = 0;
+ TRAPD(err, result = iServer.GetTimeRemainingL());
+ if (err != KErrNone)
+ {
+ result = err;
+ }
+ aMessage.Complete(result);
+ }
+
+void CKeyStoreConduit::SetTimeout(const RMessage2& aMessage)
+ {
+ // p[1] is new timeout
+ TInt timeout = aMessage.Int1();
+ TRAPD(err, iServer.SetTimeoutL(timeout));
+ aMessage.Complete(err);
+ }
+
+void CKeyStoreConduit::GetTimeout(const RMessage2& aMessage)
+ {
+ TInt result = 0;
+ TRAPD(err, result = iServer.GetTimeoutL());
+ if (err != KErrNone)
+ {
+ result = err;
+ }
+ aMessage.Complete(result);
+ }
+
+void CKeyStoreConduit::Relock(const RMessage2& aMessage)
+ {
+ iServer.Relock();
+ aMessage.Complete(KErrNone);
+ }
+
+//
+// CActive functions
+//
+void CKeyStoreConduit::DoCancel()
+ {
+ switch (iCurrentRequest.OutstandingRequest())
+ {
+ case ECreateKey:
+ iServer.CancelCreateKey();
+ break;
+
+ case ERepudiableRSASign:
+ case ERepudiableDSASign:
+ case EDecryptText:
+ case EDHAgree:
+ case EDHPublicKey:
+ if (iOpenedKey)
+ {
+ iOpenedKey->Cancel();
+ }
+ break;
+
+ case EImportKey:
+ case EImportEncryptedKey:
+ iServer.CancelImportKey();
+ break;
+
+ case EExportKey:
+ iServer.CancelExportKey();
+ break;
+
+ case EExportEncryptedKey:
+ iServer.CancelExportEncryptedKey();
+ break;
+
+ case EChangePassphrase:
+ iServer.CancelChangePassphrase();
+ break;
+
+ case EAuthOpen:
+ iServer.CancelAuthOpen();
+ break;
+
+ default:
+ // Nothing to do
+ break;
+ }
+
+ Cleanup();
+ iCurrentRequest.Cancel();
+ }
+
+
+/**
+ * The token interface has completed the request - munge any return parameters
+ * and write back to client.
+ */
+void CKeyStoreConduit::RunL()
+ {
+ // Handle errors from server
+ User::LeaveIfError(iStatus.Int());
+
+ switch (iCurrentRequest.OutstandingRequest())
+ {
+ case ECreateKey:
+ case EImportKey:
+ case EImportEncryptedKey:
+ {
+ // Marshal TKeyUpdate to client - the client's buffer will be large
+ // enough as it passed us a CCTKeyInfo in the first place
+ ASSERT(iKeyInfo);
+ TKeyUpdate update;
+ update.iReference = iKeyInfo->HandleID();
+ update.iId = iKeyInfo->ID();
+ update.iSize = iKeyInfo->Size();
+ update.iAlgorithm = iKeyInfo->Algorithm();
+ TPckg<TKeyUpdate> pckg(update);
+ iCurrentRequest.Message().WriteL(1, pckg);
+ break;
+ }
+ case EExportKey:
+ case EExportEncryptedKey:
+ {
+ ASSERT(iExportBuf);
+ TPtr8 clientPtr(iExportBuf->Des());
+ iCurrentRequest.Message().WriteL(1, clientPtr);
+ break;
+ }
+ case ERepudiableDSASign:
+ {
+ ASSERT(iDSASignature);
+
+ TInt length = User::LeaveIfError(iCurrentRequest.Message().GetDesMaxLength(2));
+ TInt reqdLength = TokenDataMarshaller::Size(*iDSASignature);
+ if (length < reqdLength)
+ {
+ User::Leave(KErrOverflow);
+ }
+
+ HBufC8* clientBuffer = HBufC8::NewLC(reqdLength);
+ TPtr8 ptr(clientBuffer->Des());
+ TokenDataMarshaller::WriteL(*iDSASignature, ptr);
+ iCurrentRequest.Message().WriteL(2, ptr);
+ CleanupStack::PopAndDestroy(clientBuffer);
+ break;
+ }
+ case ERepudiableRSASign:
+ {
+ ASSERT(iRSASignature);
+ TInt length = User::LeaveIfError(iCurrentRequest.Message().GetDesMaxLength(2));
+ TInt reqdLength = TokenDataMarshaller::Size(*iRSASignature);
+ if (length < reqdLength)
+ {
+ User::Leave(KErrOverflow);
+ }
+
+ HBufC8* clientBuffer = HBufC8::NewLC(reqdLength);
+ TPtr8 ptr(clientBuffer->Des());
+ TokenDataMarshaller::WriteL(*iRSASignature, ptr);
+ iCurrentRequest.Message().WriteL(2, ptr);
+ CleanupStack::PopAndDestroy(clientBuffer);
+ break;
+ }
+ case EDecryptText:
+ {
+ ASSERT(iPlaintext);
+ TInt length = User::LeaveIfError(iCurrentRequest.Message().GetDesMaxLength(2));
+ if (length < iPlaintext->Length())
+ {
+ User::Leave(KErrOverflow);
+ }
+ iCurrentRequest.Message().WriteL(2, *iPlaintext);
+ break;
+ }
+
+ case EDHPublicKey:
+ FinishDHPublicKeyL();
+ break;
+ case EDHAgree:
+ FinishDHAgreeL();
+ break;
+ case EChangePassphrase:
+ case EAuthOpen:
+ // Nothing to do
+ break;
+ default:
+ __ASSERT_DEBUG(EFalse, PanicServer(EPanicInvalidRequest));
+ User::Leave(KErrNotSupported);
+ }
+
+ Cleanup();
+ iCurrentRequest.Complete(KErrNone);
+ }
+
+/**
+ * Cleans up data members used in processing a client request. Called whenenver a
+ * request is completed, either from RunL, RunError or indirectly from DoCancel.
+ */
+
+void CKeyStoreConduit::Cleanup()
+ {
+ delete iKeyInfo; iKeyInfo = NULL;
+ delete iImportKey; iImportKey = NULL;
+ delete iText; iText = NULL;
+ delete iDSASignature; iDSASignature = NULL;
+ delete iRSASignature; iRSASignature = NULL;
+ delete iExportBuf; iExportBuf = NULL;
+ delete iPbeParams; iPbeParams = NULL;
+ delete iDHParams; iDHParams = NULL;
+ iDHPublicKeyOut.Close();
+ delete iDHPublicKey; iDHPublicKey = NULL;
+ delete iDHAgreedKeyOut; iDHAgreedKeyOut = NULL;
+ delete iPlaintext; iPlaintext = NULL;
+ iOpenedKey = NULL;
+ }
+
+TInt CKeyStoreConduit::RunError(TInt aError)
+ {
+ Cleanup();
+
+ // Handle error by completing client appropriately
+ iCurrentRequest.Complete(aError);
+
+ return (KErrNone);
+ }
+
+// CKeyStoreConduit::TAsyncRequest /////////////////////////////////////////////
+
+CKeyStoreConduit::TAsyncRequest::TAsyncRequest(TRequestStatus& aStatus) :
+ iOwnerStatus(aStatus)
+ {
+ }
+
+CKeyStoreConduit::TAsyncRequest::~TAsyncRequest()
+ {
+ __ASSERT_DEBUG(EIdle==iRequest, PanicServer(EPanicRequestOutstanding));
+ }
+
+void CKeyStoreConduit::TAsyncRequest::Set(TFSTokenMessages aRequest, const RMessage2& aMessage)
+ {
+ __ASSERT_DEBUG(EIdle==iRequest, PanicServer(EPanicRequestOutstanding));
+
+ iOwnerStatus = KRequestPending;
+ iRequest = aRequest;
+ iMessage = aMessage;
+ }
+
+void CKeyStoreConduit::TAsyncRequest::Complete(TInt aResult)
+ {
+ iMessage.Complete(aResult);
+ iRequest = EIdle;
+ }
+
+void CKeyStoreConduit::TAsyncRequest::Cancel()
+ {// Complete outstanding request with KErrCancel
+ iMessage.Complete(KErrCancel);
+ iRequest = EIdle;
+ }