cryptoservices/filebasedcertificateandkeystores/source/keystore/Server/Ckeystoreconduit.cpp
changeset 0 2c201484c85f
child 8 35751d3474b7
--- /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;
+	}