pkiutilities/DeviceToken/Src/KeyStore/Server/DevCertKeyStoreConduit.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Tue, 26 Jan 2010 15:20:08 +0200
changeset 0 164170e6151a
permissions -rw-r--r--
Revision: 201004

/*
* Copyright (c) 2006 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:   Implementation of DevCertKeyStoreConduit
*
*/



#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
#include <mctkeystoreuids.h>
#endif
#include "DevCertKeyStoreConduit.h"
#include "DevCertKeyStoreServer.h"
#include "DevCertKeyStoreSession.h"
#include "DevCertOpenedKeysSrv.h"
#include "DevTokenDataTypes.h"
#include "DevTokenMarshaller.h"
#include "DevTokenUtil.h"
#include <asymmetric.h>
#include <mctkeystoremanager.h>


// ======== MEMBER FUNCTIONS ========

// CDevCertKeyStoreConduit

// ---------------------------------------------------------------------------
// CDevCertKeyStoreConduit::NewL()
// ---------------------------------------------------------------------------
// 
CDevCertKeyStoreConduit* CDevCertKeyStoreConduit::NewL(CDevCertKeyStoreServer& aServer)
    {
    CDevCertKeyStoreConduit* self = new (ELeave) CDevCertKeyStoreConduit(aServer);
    CleanupStack::PushL(self);
    self->ConstructL();
    CleanupStack::Pop(self);
    return self;
    }


// ---------------------------------------------------------------------------
// CDevCertKeyStoreConduit::~CDevCertKeyStoreConduit()
// ---------------------------------------------------------------------------
// 
CDevCertKeyStoreConduit::~CDevCertKeyStoreConduit()
    {
    Cancel();
    }


// ---------------------------------------------------------------------------
// CDevCertKeyStoreConduit::CDevCertKeyStoreConduit()
// ---------------------------------------------------------------------------
// 
CDevCertKeyStoreConduit::CDevCertKeyStoreConduit(CDevCertKeyStoreServer& aServer)
  : CActive(EPriorityHigh), iServer(aServer), iCurrentRequest(iStatus)
    {
    }


// ---------------------------------------------------------------------------
// CDevCertKeyStoreConduit::ConstructL()
// ---------------------------------------------------------------------------
//
void CDevCertKeyStoreConduit::ConstructL()
    {
    CActiveScheduler::Add(this);
    }


// ---------------------------------------------------------------------------
// CDevCertKeyStoreConduit::ServiceRequestL()
// ---------------------------------------------------------------------------
//
void CDevCertKeyStoreConduit::ServiceRequestL(const RMessage2& aMessage, CDevCertKeyStoreSession& aSession)
    {
    TDevTokenMessages request = static_cast<TDevTokenMessages>(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!=ECancelRSASign) &&
        (request!=ECancelDSASign) &&
        (request!=ECancelDecrypt) )
            {
            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 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);
            break;         
        case ERepudiableRSASign:
            RepudiableRSASignL(aMessage, aSession);
            break;
        case ECancelRSASign:
            CancelRSASign(aMessage);
            break;         
        case EDecryptText:
            DecryptL(aMessage, aSession);
            break;
        case ECancelDecrypt:
            CancelDecrypt(aMessage);
            break;         
        case EDHPublicKey:
            DHPublicKeyL(aMessage, aSession);
            break;
        case EDHAgree:
            DHAgreeL(aMessage, aSession);
            break;
        case ECancelDH:
            CancelDH(aMessage);
            break;         

        default:  //  Should not reach here
            __ASSERT_DEBUG(EFalse, PanicServer(EPanicInvalidRequest));
            User::Leave(KErrNotSupported);
        }
    }


// ---------------------------------------------------------------------------
// CDevCertKeyStoreConduit::ListL()
// ---------------------------------------------------------------------------
//
void CDevCertKeyStoreConduit::ListL(const RMessage2& aMessage)
    {
    //  p[0] has the filter to use
    RCPointerArray<CDevTokenKeyInfo> keyInfos;
    CleanupClosePushL(keyInfos);

    TPckgBuf<TCTKeyAttributeFilter> filter;
    aMessage.ReadL(0, filter);

    iServer.ListL(filter(), keyInfos);

    TInt bufSize = User::LeaveIfError(aMessage.GetDesMaxLength(2)); 
    TInt reqdSize = DevTokenDataMarshaller::Size(keyInfos);
    if (bufSize >= reqdSize)
        {
        HBufC8* buffer = HBufC8::NewMaxLC(reqdSize);
        TPtr8 thePtr(buffer->Des());
        DevTokenDataMarshaller::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);
    }


// ---------------------------------------------------------------------------
// CDevCertKeyStoreConduit::GetKeyInfoL()
// ---------------------------------------------------------------------------
//
void CDevCertKeyStoreConduit::GetKeyInfoL(const RMessage2& aMessage)
    {
    //  Token object to delete is in p[0]
    TInt objectId = aMessage.Int0();
    CDevTokenKeyInfo* info = NULL;
    iServer.GetKeyInfoL(objectId, info);
    info->CleanupPushL();

    TInt bufferSize = User::LeaveIfError(aMessage.GetDesMaxLength(2));
    TInt requiredSize = DevTokenDataMarshaller::Size(*info);

    if (bufferSize >= requiredSize)
        {
        HBufC8* buffer = HBufC8::NewMaxLC(requiredSize);
        TPtr8 thePtr(buffer->Des());
        DevTokenDataMarshaller::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);
    }


// ---------------------------------------------------------------------------
// CDevCertKeyStoreConduit::GetClientUidL()
// Work out the UID of the client process.
// ---------------------------------------------------------------------------
//
TUid CDevCertKeyStoreConduit::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;
    }


// ---------------------------------------------------------------------------
// CDevCertKeyStoreConduit::CreateKeyL()
// ---------------------------------------------------------------------------
//
void CDevCertKeyStoreConduit::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 CDevTokenKeyInfo structure required to create a key
    //  Read it and convert from descriptor back to a CDevTokenKeyInfo
    TPtr8 thePtr(keyInfoBuf->Des());
    thePtr.FillZ();

    aMessage.ReadL(1, thePtr);
    DevTokenDataMarshaller::ReadL(*keyInfoBuf, iKeyInfo);
    CleanupStack::PopAndDestroy(keyInfoBuf);

    iCurrentRequest.Set(ECreateKey, aMessage);
    iStatus = KRequestPending;
    SetActive();
    iServer.CreateKey(*iKeyInfo, iStatus);
    }


// ---------------------------------------------------------------------------
// CDevCertKeyStoreConduit::CancelCreateKey()
// ---------------------------------------------------------------------------
//
void CDevCertKeyStoreConduit::CancelCreateKey(const RMessage2& aMessage)
    {
    if (iCurrentRequest.OutstandingRequest() == ECreateKey)
        {
        Cancel();
        }
    aMessage.Complete(KErrNone);
    }


// ---------------------------------------------------------------------------
// CDevCertKeyStoreConduit::ImportKeyL()
// ---------------------------------------------------------------------------
//
void CDevCertKeyStoreConduit::ImportKeyL(const RMessage2& aMessage)
    {
    ASSERT(!iImportKey);
    ASSERT(!iKeyInfo);

    // p[0] has the descriptor containing the PKCS8 object (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 CDevTokenKeyInfo structure required to create a key
    // Read it and convert from descriptor back to a CDevTokenKeyInfo
    TPtr8 thePtr(keyInfoBuf->Des());
    thePtr.FillZ();
    aMessage.ReadL(1, thePtr);

    DevTokenDataMarshaller::ReadL(*keyInfoBuf, iKeyInfo);
    CleanupStack::PopAndDestroy(keyInfoBuf);

    iImportKey = importBuf;
    CleanupStack::Pop(importBuf);

    iCurrentRequest.Set(static_cast<TDevTokenMessages>(aMessage.Function()), aMessage);
    iStatus = KRequestPending;
    SetActive();
    
    TBool isEncrypted = (aMessage.Function() == EImportEncryptedKey);
	iServer.ImportKey(*iImportKey, *iKeyInfo, isEncrypted, iStatus);
    }


// ---------------------------------------------------------------------------
// CDevCertKeyStoreConduit::CancelImportKey()
// ---------------------------------------------------------------------------
//
void CDevCertKeyStoreConduit::CancelImportKey(const RMessage2& aMessage)
    {
    if (iCurrentRequest.OutstandingRequest() == EImportKey ||
		iCurrentRequest.OutstandingRequest() == EImportEncryptedKey)
        {
        Cancel();
        }
    aMessage.Complete(KErrNone); 
    }


// ---------------------------------------------------------------------------
// CDevCertKeyStoreConduit::GetKeyLengthL()
// ---------------------------------------------------------------------------
//
void CDevCertKeyStoreConduit::GetKeyLengthL(const RMessage2& aMessage)
    {
    TInt length = iServer.GetKeyLengthL(aMessage.Int0());
    ASSERT(length > 0);
    aMessage.Complete(length);    
    }


// ---------------------------------------------------------------------------
// CDevCertKeyStoreConduit::CancelExportKey()
// ---------------------------------------------------------------------------
//
void CDevCertKeyStoreConduit::CancelExportKey(const RMessage2& aMessage)
    {
    if (iCurrentRequest.OutstandingRequest() == EExportKey ||
        iCurrentRequest.OutstandingRequest() == EImportEncryptedKey)
        {
        Cancel();
        }
    aMessage.Complete(KErrNone);
    }


// ---------------------------------------------------------------------------
// CDevCertKeyStoreConduit::ExportKeyL()
// ---------------------------------------------------------------------------
//
void CDevCertKeyStoreConduit::ExportKeyL(const RMessage2& aMessage)
    {
    ASSERT(!iExportBuf);

    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();

    // No more leaves
    iExportBuf = exportBuf;
    CleanupStack::Pop(exportBuf);

    iCurrentRequest.Set(static_cast<TDevTokenMessages>(aMessage.Function()), aMessage); 
    iStatus = KRequestPending;
    SetActive();    

    if (aMessage.Function() == EExportKey) 
        {
        iServer.ExportKey(objectId, temp, iStatus);
        }    
    }


// ---------------------------------------------------------------------------
// CDevCertKeyStoreConduit::ExportPublicL()
// ---------------------------------------------------------------------------
//
void CDevCertKeyStoreConduit::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);
    }


// ---------------------------------------------------------------------------
// CDevCertKeyStoreConduit::DeleteKeyL()
// ---------------------------------------------------------------------------
//
void CDevCertKeyStoreConduit::DeleteKeyL(const RMessage2& aMessage)
    {
    TInt objectId = aMessage.Int0();
    iServer.DeleteKeyL(objectId);
    aMessage.Complete(KErrNone);
    }


// ---------------------------------------------------------------------------
// CDevCertKeyStoreConduit::SetUsePolicyL()
// ---------------------------------------------------------------------------
//
void CDevCertKeyStoreConduit::SetUsePolicyL(const RMessage2& aMessage)
    {
    TInt objectId = aMessage.Int0();
    TSecurityPolicyBuf policyBuf;

    aMessage.ReadL(1, policyBuf);

    iServer.SetUsePolicyL(objectId, policyBuf());
    aMessage.Complete(KErrNone);
    }


// ---------------------------------------------------------------------------
// CDevCertKeyStoreConduit::SetManagementPolicyL()
// ---------------------------------------------------------------------------
//
void CDevCertKeyStoreConduit::SetManagementPolicyL(const RMessage2& aMessage)
    {
    TInt objectId = aMessage.Int0();
    TSecurityPolicyBuf policyBuf;

    aMessage.ReadL(1, policyBuf);

    iServer.SetManagementPolicyL(objectId, policyBuf());
    aMessage.Complete(KErrNone);
    }


// ---------------------------------------------------------------------------
// CDevCertKeyStoreConduit::OpenKeyL()
// ---------------------------------------------------------------------------
//
void CDevCertKeyStoreConduit::OpenKeyL(const RMessage2& aMessage, 
                                       CDevCertKeyStoreSession& aSession, 
                                       TUid aType)
    { 
    CDevCertOpenedKeySrv* 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);
    }


// ---------------------------------------------------------------------------
// CDevCertKeyStoreConduit::RepudiableRSASignL()
// ---------------------------------------------------------------------------
//
void CDevCertKeyStoreConduit::RepudiableRSASignL(const RMessage2& aMessage, 
                                         CDevCertKeyStoreSession& aSession)
    {
    ASSERT( iOpenedKey == NULL );
    TPtr8 thePtr(0,0);
    iOpenedKey = ProcessL(aMessage, aSession, KRSARepudiableSignerUID, ERepudiableRSASign, thePtr);
    static_cast<CDevCertRSARepudiableSignerSrv*>(iOpenedKey)->Sign(thePtr, iRSASignature, iStatus);
    }


// ---------------------------------------------------------------------------
// CDevCertKeyStoreConduit::CancelRSASign()
// ---------------------------------------------------------------------------
//
void CDevCertKeyStoreConduit::CancelRSASign(const RMessage2& aMessage)
    {
    if (iCurrentRequest.OutstandingRequest() == ERepudiableRSASign)
        {
        Cancel();
        }
    aMessage.Complete(KErrNone);
    }


// ---------------------------------------------------------------------------
// CDevCertKeyStoreConduit::RepudiableDSASignL()
// ---------------------------------------------------------------------------
//
void CDevCertKeyStoreConduit::RepudiableDSASignL(const RMessage2& aMessage, 
                                          CDevCertKeyStoreSession& aSession)
    {
    ASSERT( iOpenedKey == NULL );
    TPtr8 thePtr(0,0);
    iOpenedKey = ProcessL(aMessage, aSession, KDSARepudiableSignerUID, ERepudiableDSASign, thePtr);
    static_cast<CDevCertDSARepudiableSignerSrv*>(iOpenedKey)->Sign(thePtr, iDSASignature, iStatus);
    }


// ---------------------------------------------------------------------------
// CDevCertKeyStoreConduit::CancelDSASign()
// ---------------------------------------------------------------------------
//
void CDevCertKeyStoreConduit::CancelDSASign(const RMessage2& aMessage)
    {
    if (iCurrentRequest.OutstandingRequest() == ERepudiableDSASign)
        {
        Cancel();
        }
    aMessage.Complete(KErrNone);
    }


// ---------------------------------------------------------------------------
// CDevCertKeyStoreConduit::DecryptL()
// ---------------------------------------------------------------------------
//
void CDevCertKeyStoreConduit::DecryptL(const RMessage2& aMessage, 
                                       CDevCertKeyStoreSession& aSession)
    {
    ASSERT( iOpenedKey == NULL );
    TPtr8 thePtr(0,0);
    iOpenedKey = ProcessL(aMessage, aSession, KPrivateDecryptorUID, EDecryptText, thePtr);
    static_cast<CDevCertRSADecryptorSrv*>(iOpenedKey)->Decrypt(thePtr, iPlaintext, iStatus);
    }


// ---------------------------------------------------------------------------
// CDevCertKeyStoreConduit::CancelDecrypt()
// ---------------------------------------------------------------------------
//
void CDevCertKeyStoreConduit::CancelDecrypt(const RMessage2& aMessage)
    {
    if (iCurrentRequest.OutstandingRequest() == EDecryptText)
        {
        Cancel();
        }
    aMessage.Complete(KErrNone);
    }


// ---------------------------------------------------------------------------
// CDevCertKeyStoreConduit::ProcessL()
// ---------------------------------------------------------------------------
//
CDevCertOpenedKeySrv* CDevCertKeyStoreConduit::ProcessL(
                     const RMessage2& aMessage,
                     CDevCertKeyStoreSession& aSession,
                     const TUid& aCKeyInfoID,
                     const TDevTokenMessages& aState,
                     TPtr8& aTextPtr)
    {
    CDevCertOpenedKeySrv* 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;
    }


// ---------------------------------------------------------------------------
// CDevCertKeyStoreConduit::DHPublicKeyL()
// ---------------------------------------------------------------------------
//
void CDevCertKeyStoreConduit::DHPublicKeyL(const RMessage2& aMessage, 
                                      CDevCertKeyStoreSession& 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);
        }
    }


// ---------------------------------------------------------------------------
// CDevCertKeyStoreConduit::DoDHPublicKeyL()
// ---------------------------------------------------------------------------
//
void CDevCertKeyStoreConduit::DoDHPublicKeyL(const RMessage2& aMessage, 
                                      CDevCertKeyStoreSession& 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);
    DevTokenDataMarshaller::ReadL(*clientBuf, iDHParams);
    CleanupStack::PopAndDestroy(clientBuf);

    static_cast<CDevCertDHAgreementSrv*>(iOpenedKey)->PublicKey(*iDHParams, iDHPublicKeyOut, iStatus);

    iCurrentRequest.Set(EDHPublicKey, aMessage);
    iStatus=KRequestPending;
    SetActive();
    }


// ---------------------------------------------------------------------------
// CDevCertKeyStoreConduit::FinishDHPublicKeyL()
// ---------------------------------------------------------------------------
//
void CDevCertKeyStoreConduit::FinishDHPublicKeyL()
    {
    // Client buffer must be big enough for result because it had the DH
    // parameters in it
    TInt reqdSize = DevTokenDataMarshaller::Size(iDHPublicKeyOut);
    ASSERT(reqdSize <= iCurrentRequest.Message().GetDesMaxLength(1));

    HBufC8* clientBuf = HBufC8::NewMaxLC(reqdSize);
    TPtr8 clientPtr = clientBuf->Des();
    DevTokenDataMarshaller::WriteL(iDHPublicKeyOut, clientPtr);
    iCurrentRequest.Message().WriteL(1, clientPtr);
    CleanupStack::PopAndDestroy(clientBuf);
    }


// ---------------------------------------------------------------------------
// CDevCertKeyStoreConduit::DHAgreeL()
// ---------------------------------------------------------------------------
//
void CDevCertKeyStoreConduit::DHAgreeL(const RMessage2& aMessage, CDevCertKeyStoreSession& 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);
        }
    }


// ---------------------------------------------------------------------------
// CDevCertKeyStoreConduit::DoDHAgreeL()
// ---------------------------------------------------------------------------
//
void CDevCertKeyStoreConduit::DoDHAgreeL(const RMessage2& aMessage, CDevCertKeyStoreSession& aSession)
    {
    CDevCertOpenedKeySrv* 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);
    DevTokenDataMarshaller::ReadL(*clientBuf, iDHPublicKey);
    CleanupStack::PopAndDestroy(clientBuf);

    static_cast<CDevCertDHAgreementSrv*>(iOpenedKey)->Agree(*iDHPublicKey, iDHAgreedKeyOut, iStatus);

    iCurrentRequest.Set(EDHAgree, aMessage);
    iStatus=KRequestPending;
    SetActive();
    }


// ---------------------------------------------------------------------------
// CDevCertKeyStoreConduit::FinishDHAgreeL()
// ---------------------------------------------------------------------------
//
void CDevCertKeyStoreConduit::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);
    }


// ---------------------------------------------------------------------------
// CDevCertKeyStoreConduit::CancelDH()
// ---------------------------------------------------------------------------
//
void CDevCertKeyStoreConduit::CancelDH(const RMessage2& aMessage)
    {
    if (iCurrentRequest.OutstandingRequest() == EDHPublicKey ||
    iCurrentRequest.OutstandingRequest() == EDHAgree)
        {
        Cancel();
        }
    aMessage.Complete(KErrNone);
    }


// ---------------------------------------------------------------------------
// CDevCertKeyStoreConduit::CloseObjectL()
// ---------------------------------------------------------------------------
//
void CDevCertKeyStoreConduit::CloseObjectL(const RMessage2& aMessage, CDevCertKeyStoreSession& aSession)
    {
    aSession.RemoveOpenedKeyL(aMessage.Int0());
    aMessage.Complete(KErrNone);
    }


// ---------------------------------------------------------------------------
// CDevCertKeyStoreConduit::DoCancel()
// ---------------------------------------------------------------------------
//
void CDevCertKeyStoreConduit::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:
            iServer.CancelImportKey();
            break;

        case EExportKey:
            iServer.CancelExportKey();
            break;

        default:
            // Nothing to do
            break;
        }

    Cleanup();
    iCurrentRequest.Cancel();
    }


// ---------------------------------------------------------------------------
// CDevCertKeyStoreConduit::RunL()
// The token interface has completed the request - munge any return parameters
// and write back to client.
// ---------------------------------------------------------------------------
// 
void CDevCertKeyStoreConduit::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);
            TDevTokenKeyUpdate update;
            update.iReference = iKeyInfo->HandleID();
            update.iId = iKeyInfo->ID();
            update.iSize = iKeyInfo->Size();
            update.iAlgorithm = iKeyInfo->Algorithm();
            TPckg<TDevTokenKeyUpdate> pckg(update);
            iCurrentRequest.Message().WriteL(1, pckg);
            break;
            }
        case EExportKey:
            {
            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 = DevTokenDataMarshaller::Size(*iDSASignature);
            if (length < reqdLength)
                {
                User::Leave(KErrOverflow);
                }

            HBufC8* clientBuffer = HBufC8::NewLC(reqdLength);
            TPtr8 ptr(clientBuffer->Des());
            DevTokenDataMarshaller::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 = DevTokenDataMarshaller::Size(*iRSASignature);
            if (length < reqdLength)
                {
                User::Leave(KErrOverflow);
                }

            HBufC8* clientBuffer = HBufC8::NewLC(reqdLength);
            TPtr8 ptr(clientBuffer->Des());
            DevTokenDataMarshaller::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;

        default:
            __ASSERT_DEBUG(EFalse, PanicServer(EPanicInvalidRequest));
            User::Leave(KErrNotSupported);
        }

    Cleanup();
    iCurrentRequest.Complete(KErrNone);
    }


// ---------------------------------------------------------------------------
// CDevCertKeyStoreConduit::Cleanup()
// 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 CDevCertKeyStoreConduit::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 iDHParams;    iDHParams = NULL;
    iDHPublicKeyOut.Close();
    delete iDHPublicKey;   iDHPublicKey = NULL;
    delete iDHAgreedKeyOut;  iDHAgreedKeyOut = NULL;
    delete iPlaintext;     iPlaintext = NULL;
    iOpenedKey = NULL;
    }


// ---------------------------------------------------------------------------
// CDevCertKeyStoreConduit::RunError()
// ---------------------------------------------------------------------------
// 
TInt CDevCertKeyStoreConduit::RunError(TInt aError)
    {
    Cleanup();
    //  Handle error by completing client appropriately
    iCurrentRequest.Complete(aError);
    return (KErrNone);
    }


// CDevCertKeyStoreConduit::TAsyncRequest 

// ---------------------------------------------------------------------------
// CDevCertKeyStoreConduit::TAsyncRequest::TAsyncRequest()
// ---------------------------------------------------------------------------
// 
CDevCertKeyStoreConduit::TAsyncRequest::TAsyncRequest(TRequestStatus& aStatus) :
  iOwnerStatus(aStatus)
    {
    }


// ---------------------------------------------------------------------------
// CDevCertKeyStoreConduit::TAsyncRequest::~TAsyncRequest()
// ---------------------------------------------------------------------------
// 
CDevCertKeyStoreConduit::TAsyncRequest::~TAsyncRequest()
    {
    __ASSERT_DEBUG(EIdle==iRequest, PanicServer(EPanicRequestOutstanding));
    }


// ---------------------------------------------------------------------------
// CDevCertKeyStoreConduit::TAsyncRequest::Set()
// ---------------------------------------------------------------------------
// 
void CDevCertKeyStoreConduit::TAsyncRequest::Set(TDevTokenMessages aRequest, const RMessage2& aMessage)
    {
    __ASSERT_DEBUG(EIdle==iRequest, PanicServer(EPanicRequestOutstanding));

    iOwnerStatus = KRequestPending;
    iRequest = aRequest;
    iMessage = aMessage;
    }


// ---------------------------------------------------------------------------
// CDevCertKeyStoreConduit::TAsyncRequest::Complete()
// ---------------------------------------------------------------------------
//
void CDevCertKeyStoreConduit::TAsyncRequest::Complete(TInt aResult)
    {
    iMessage.Complete(aResult);
    iRequest = EIdle;
    }


// ---------------------------------------------------------------------------
// CDevCertKeyStoreConduit::TAsyncRequest::Cancel()
// ---------------------------------------------------------------------------
//
void CDevCertKeyStoreConduit::TAsyncRequest::Cancel()
    {// Complete outstanding request with KErrCancel
    iMessage.Complete(KErrCancel);
    iRequest = EIdle;
    }
    
//EOF