cryptoservices/filebasedcertificateandkeystores/source/keystore/Server/Ckeystoreconduit.cpp
/*
* 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>
#include "cfskeystoreserver.h"
#include <mctkeystoreuids.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));
iServer.CheckRangeL(bufSize);
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));
iServer.CheckRangeL(bufferSize);
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));
iServer.CheckRangeL(bufLength);
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));
iServer.CheckRangeL(keyLen);
HBufC8* importBuf = HBufC8::NewMaxLC(keyLen);
TPtr8 theKeyData(importBuf->Des());
theKeyData.FillZ();
aMessage.ReadL(0, theKeyData);
TInt bufLen = User::LeaveIfError(aMessage.GetDesLength(1));
iServer.CheckRangeL(bufLen);
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
iServer.CheckRangeL(bufLen);
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));
iServer.CheckRangeL(bufLen);
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);
}
TInt bufLen = User::LeaveIfError(aMessage.GetDesLength(1));
iServer.CheckRangeL(bufLen);
HBufC8* clientBuf = HBufC8::NewMaxLC(bufLen);
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);
}
TInt bufLen = User::LeaveIfError(aMessage.GetDesLength(1));
iServer.CheckRangeL(bufLen);
HBufC8* clientBuf = HBufC8::NewMaxLC(bufLen);
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 = iServer.GetTimeout();
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;
}