cpsecplugins/cpadvancedsecplugin/src/advsecsettingscertmover_symbian.cpp
author hgs
Thu, 14 Oct 2010 13:56:11 +0300
changeset 63 989397f9511c
permissions -rw-r--r--
201039_03

/*
* Copyright (c) 2010 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:  Helper class to move certificates
*
*/

#include "advsecsettingscertmover_symbian.h"
#include "advsecsettingsstoreuids.h"
#include <unifiedcertstore.h>           // CUnifiedCertStore
#include <unifiedkeystore.h>            // CUnifiedKeyStore
#include <cctcertinfo.h>                // CCTCertInfo
#include <mctwritablecertstore.h>       // MCTWritableCertStore
#include <mctkeystoremanager.h>         // MCTKeyStoreManager

const TInt KMaxBufferLength = 0x3000;   // 12kB, for keys and certificates
_LIT_SECURITY_POLICY_C1( KKeyStoreUsePolicy, ECapabilityReadUserData );

// TODO: replace with proper logging
#ifdef _DEBUG
#define TRACE(x)        RDebug::Printf(x)
#define TRACE1(x, y)    RDebug::Printf((x), (y))
#define TRACE2(x, y, z) RDebug::Printf((x), (y), (z))
#else
#define TRACE(x)
#define TRACE1(x, y)
#define TRACE2(x, y, z)
#endif


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

// ---------------------------------------------------------------------------
// CAdvSecSettingsCertMover::NewL()
// ---------------------------------------------------------------------------
//
CAdvSecSettingsCertMover *CAdvSecSettingsCertMover::NewL(RFs &aFs)
{
    TRACE("CAdvSecSettingsCertMover::NewL()");
    CAdvSecSettingsCertMover* self = new( ELeave ) CAdvSecSettingsCertMover(aFs);
    CleanupStack::PushL(self);
    self->ConstructL();
    CleanupStack::Pop(self);
    return self;
}

// ---------------------------------------------------------------------------
// CAdvSecSettingsCertMover::~CAdvSecSettingsCertMover()
// ---------------------------------------------------------------------------
//
CAdvSecSettingsCertMover::~CAdvSecSettingsCertMover()
{
    TRACE("CAdvSecSettingsCertMover::~CAdvSecSettingsCertMover()");
    Cancel();
    delete iCertStore;
    iTargetCertStore = NULL;
    delete iCertFilter;
    iCerts.Close();

    delete iKeyStore;
    iSourceKeyStore = NULL;
    iTargetKeyStore = NULL;
    delete iKeyFilter;
    iKeys.Close();
    if (iSavedKeyInfo) {
        iSavedKeyInfo->Release();
    }

    delete iDataBuffer;
    iClientStatus = NULL;
    iCertInfo = NULL;
}

// ---------------------------------------------------------------------------
// CAdvSecSettingsCertMover::Move()
// ---------------------------------------------------------------------------
//
void CAdvSecSettingsCertMover::Move(const CCTCertInfo &aCert,
    TInt aSourceCertStoreTokenId, TInt aTargetCertStoreTokenId,
    TRequestStatus &aStatus)
{
    TRACE("CAdvSecSettingsCertMover::Move()");
    aStatus = KRequestPending;
    if (!iClientStatus) {
        iClientStatus = &aStatus;

        iCertInfo = &aCert;
        iSourceCertStoreTokenId = aSourceCertStoreTokenId;
        iTargetCertStoreTokenId = aTargetCertStoreTokenId;

        if (iState <= EIdle) {
            // Start move operation if initializations are complete.
            if (iState == EIdle) {
                TRAPD(err, StartMoveOperationL());
                if (err) {
                    TRACE1("CAdvSecSettingsCertMover::Move(), error %d", err);
                    User::RequestComplete(iClientStatus, err);
                    iClientStatus = NULL;
                }
            }
            // If initializations are not complete yet, then moving
            // starts in RunL() after initializations are completed.
        } else {
            // Possibly initializations have failed.
            TRACE("CAdvSecSettingsCertMover::Move(), RequestComplete KErrGeneral");
            User::RequestComplete(iClientStatus, KErrGeneral);
            iClientStatus = NULL;
        }
    } else {
        TRACE("CAdvSecSettingsCertMover::Move(), RequestComplete KErrInUse");
        TRequestStatus* status = &aStatus;
        User::RequestComplete(status, KErrInUse);
    }
}

// ---------------------------------------------------------------------------
// CAdvSecSettingsCertMover::DoCancel()
// ---------------------------------------------------------------------------
//
void CAdvSecSettingsCertMover::DoCancel()
{
    TRACE("CAdvSecSettingsCertMover::DoCancel()");
    switch (iState) {
    case EInitializingCertStore:
        iCertStore->CancelInitialize();
        iState = ENotInitialized;
        break;
    case EInitializingKeyStore:
        iKeyStore->CancelInitialize();
        iState = ENotInitialized;
        break;
    case EMovingKeyListingKeys:
        iKeyStore->CancelList();
        iState = EIdle;
        break;
    case EMovingKeyExportingKeys:
        iSourceKeyStore->CancelExportKey();
        iState = EIdle;
        break;
    case EMovingKeyImportingKeys:
        iTargetKeyStore->CancelImportKey();
        iState = EIdle;
        break;
    case EMovingKeyDeletingOriginal:
        iSourceKeyStore->CancelDeleteKey();
        iState = EIdle;
        break;
    case EMovingCertListingCerts:
        iCertStore->CancelList();
        iState = EIdle;
        break;
    case EMovingCertRetrievingCerts:
        iSourceCertStore->CancelRetrieve();
        iState = EIdle;
        break;
    case EMovingCertAddingCerts:
        iTargetCertStore->CancelAdd();
        iState = EIdle;
        break;
    case EMovingCertDeletingOriginal:
        iSourceCertStore->CancelRemove();
        iState = EIdle;
        break;
    default:
        break;
    }

    if (iClientStatus) {
        TRACE("CAdvSecSettingsCertMover::DoCancel(), RequestComplete KErrCancel");
        User::RequestComplete(iClientStatus, KErrCancel);
        iClientStatus = NULL;
    }
}

// ---------------------------------------------------------------------------
// CAdvSecSettingsCertMover::RunL()
// ---------------------------------------------------------------------------
//
void CAdvSecSettingsCertMover::RunL()
{
    TRACE2("CAdvSecSettingsCertMover::RunL(), iState=%d, iStatus.Int()=%d", iState, iStatus.Int());
    User::LeaveIfError(iStatus.Int());

    switch (iState) {
    case EInitializingCertStore:
        iKeyStore->Initialize(iStatus);
        iState = EInitializingKeyStore;
        SetActive();
        break;
    case EInitializingKeyStore:
        iState = EIdle;
        if (iClientStatus) {
            StartMoveOperationL();
        }
        break;
    case EMovingKeyListingKeys:
        ExportFirstKeyL();
        break;
    case EMovingKeyExportingKeys:
        SaveExportedKeyL();
        break;
    case EMovingKeyImportingKeys:
        DeleteOriginalKeyL();
        break;
    case EMovingKeyDeletingOriginal:
        ExportNextKeyL();
        break;
    case EMovingCertListingCerts:
        RetrieveFirstCertL();
        break;
    case EMovingCertRetrievingCerts:
        SaveRetrievedCertL();
        break;
    case EMovingCertAddingCerts:
        DeleteOriginalCertL();
        break;
    case EMovingCertDeletingOriginal:
        RetrieveNextCertL();
        break;
    default:
        ASSERT(EFalse);
        break;
    }
}

// ---------------------------------------------------------------------------
// CAdvSecSettingsCertMover::RunError()
// ---------------------------------------------------------------------------
//
TInt CAdvSecSettingsCertMover::RunError(TInt aError)
{
    TRACE1("CAdvSecSettingsCertMover::RunError(), aError=%d", aError);
    if (iClientStatus) {
        TRACE1("CAdvSecSettingsCertMover::RunError(), RequestComplete %d", aError);
        User::RequestComplete(iClientStatus, aError);
        iClientStatus = NULL;
    }
    if (iState < EIdle) {
        iState = EFailed;
    } else {
        iState = EIdle;
    }
    return KErrNone;
}

// ---------------------------------------------------------------------------
// CAdvSecSettingsCertMover::CAdvSecSettingsCertMover()
// ---------------------------------------------------------------------------
//
CAdvSecSettingsCertMover::CAdvSecSettingsCertMover(RFs &aFs) :
    CActive(CActive::EPriorityLow), iFs(aFs), iDataPtr(0,0)
{
    CActiveScheduler::Add(this);
}

// ---------------------------------------------------------------------------
// CAdvSecSettingsCertMover::ConstructL()
// ---------------------------------------------------------------------------
//
void CAdvSecSettingsCertMover::ConstructL()
{
    TRACE("CAdvSecSettingsCertMover::ConstructL()");
    const TBool KWriteMode = ETrue;
    iCertStore = CUnifiedCertStore::NewL(iFs, KWriteMode);
    iKeyStore = CUnifiedKeyStore::NewL(iFs);

    iDataBuffer = HBufC8::New(KMaxBufferLength);
    iDataPtr.Set(iDataBuffer->Des());

    iCertStore->Initialize(iStatus);
    iState = EInitializingCertStore;
    SetActive();
}

// ---------------------------------------------------------------------------
// CAdvSecSettingsCertMover::StartMoveOperationL()
// ---------------------------------------------------------------------------
//
void CAdvSecSettingsCertMover::StartMoveOperationL()
{
    TRACE("CAdvSecSettingsCertMover::StartMoveOperationL()");
    FindSourceAndTargetKeyStoresL();
    FindSourceAndTargetCertStoreL();
    StartMovingKeysL();
}

// ---------------------------------------------------------------------------
// CAdvSecSettingsCertMover::FindSourceAndTargetKeyStoresL()
// ---------------------------------------------------------------------------
//
void CAdvSecSettingsCertMover::FindSourceAndTargetKeyStoresL()
{
    TRACE("CAdvSecSettingsCertMover::FindSourceAndTargetKeyStoresL()");
    TInt keyStoreSourceTokenId = CorrespondingKeyStoreTokenId(iSourceCertStoreTokenId);
    TInt keyStoreTargetTokenId = CorrespondingKeyStoreTokenId(iTargetCertStoreTokenId);
    TInt keyStoreSourceIndex = KErrNotFound;
    TInt keyStoreTargetIndex = KErrNotFound;

    TInt count = iKeyStore->KeyStoreManagerCount();
    for (TInt index = 0; index < count; index++) {
        MCTKeyStoreManager& keystoremanager = iKeyStore->KeyStoreManager(index);
        MCTToken& token = keystoremanager.Token();
        TUid tokenTypeUid = token.Handle().iTokenTypeUid;
        if (tokenTypeUid.iUid == keyStoreSourceTokenId) {
            keyStoreSourceIndex = index;
        }
        if (tokenTypeUid.iUid == keyStoreTargetTokenId) {
            keyStoreTargetIndex = index;
        }
    }

    if (keyStoreSourceIndex == KErrNotFound || keyStoreTargetIndex == KErrNotFound) {
        User::Leave(KErrNotFound);
    }

    iSourceKeyStore = &( iKeyStore->KeyStoreManager(keyStoreSourceIndex) );
    iTargetKeyStore = &( iKeyStore->KeyStoreManager(keyStoreTargetIndex) );
}

// ---------------------------------------------------------------------------
// CAdvSecSettingsCertMover::FindSourceAndTargetCertStoreL()
// ---------------------------------------------------------------------------
//
void CAdvSecSettingsCertMover::FindSourceAndTargetCertStoreL()
{
    TRACE("CAdvSecSettingsCertMover::FindSourceAndTargetCertStoreL()");
    TInt certStoreSourceIndex = KErrNotFound;
    TInt certStoreTargetIndex = KErrNotFound;

    TInt count = iCertStore->WritableCertStoreCount();
    for (TInt index = 0; index < count; index++) {
        MCTWritableCertStore& writablestore = iCertStore->WritableCertStore(index);
        MCTToken& token = writablestore.Token();
        TUid tokenTypeUid = token.Handle().iTokenTypeUid;
        if (tokenTypeUid.iUid == iSourceCertStoreTokenId) {
            certStoreSourceIndex = index;
        }
        if (tokenTypeUid.iUid == iTargetCertStoreTokenId) {
            certStoreTargetIndex = index;
        }
    }

    if (certStoreSourceIndex == KErrNotFound || certStoreTargetIndex == KErrNotFound) {
        User::Leave(KErrNotFound);
    }

    iSourceCertStore = &( iCertStore->WritableCertStore(certStoreSourceIndex) );
    iTargetCertStore = &( iCertStore->WritableCertStore(certStoreTargetIndex) );
}

// ---------------------------------------------------------------------------
// CAdvSecSettingsCertMover::CorrespondingKeyStoreTokenId()
// ---------------------------------------------------------------------------
//
TInt CAdvSecSettingsCertMover::CorrespondingKeyStoreTokenId(TInt aCertStoreTokenId)
{
    TInt keyStoreTokenId = KErrNotFound;
    switch (aCertStoreTokenId) {
    case KAdvSecSettingsFileCertStore:
        keyStoreTokenId = KAdvSecSettingsFileKeyStore;
        break;
    case KAdvSecSettingsDeviceCertStore:
        keyStoreTokenId = KAdvSecSettingsDeviceKeyStore;
        break;
    default:
        ASSERT(EFalse);     // Unsupported cert store token id used
        break;
    }
    return keyStoreTokenId;
}

// ---------------------------------------------------------------------------
// CAdvSecSettingsCertMover::StartMovingKeysL()
// ---------------------------------------------------------------------------
//
void CAdvSecSettingsCertMover::StartMovingKeysL()
{
    TRACE("CAdvSecSettingsCertMover::StartMovingKeysL()");
    if (iKeyFilter) {
        delete iKeyFilter;
        iKeyFilter = NULL;
    }
    iKeyFilter = new( ELeave ) TCTKeyAttributeFilter;
    iKeyFilter->iKeyId = iCertInfo->SubjectKeyId();
    iKeyFilter->iPolicyFilter =  TCTKeyAttributeFilter::EAllKeys;
    iKeyStore->List(iKeys, *iKeyFilter, iStatus);
    iState = EMovingKeyListingKeys;
    SetActive();
}

// ---------------------------------------------------------------------------
// CAdvSecSettingsCertMover::ExportFirstKeyL()
// ---------------------------------------------------------------------------
//
void CAdvSecSettingsCertMover::ExportFirstKeyL()
{
    TRACE1("CAdvSecSettingsCertMover::ExportFirstKeyL(), iKeys.Count()=%d", iKeys.Count());
    iKeyIndex = 0;
    ExportOneKeyL();
}

// ---------------------------------------------------------------------------
// CAdvSecSettingsCertMover::ExportOneKeyL()
// ---------------------------------------------------------------------------
//
void CAdvSecSettingsCertMover::ExportOneKeyL()
{
    TRACE("CAdvSecSettingsCertMover::ExportOneKeyL()");
    if (iKeyIndex < iKeys.Count()) {
        const CCTKeyInfo& keyInfo = *(iKeys[iKeyIndex]);
        iSourceKeyStore->ExportKey(keyInfo.Handle(), iDataBuffer, iStatus);
        iState = EMovingKeyExportingKeys;
        SetActive();
    } else {
        TRACE("CAdvSecSettingsCertMover::ExportOneKeyL(), all done");
        StartMovingCertificatesL();
    }
}

// ---------------------------------------------------------------------------
// CAdvSecSettingsCertMover::ExportNextKeyL()
// ---------------------------------------------------------------------------
//
void CAdvSecSettingsCertMover::ExportNextKeyL()
{
    TRACE("CAdvSecSettingsCertMover::ExportNextKeyL()");
    ++iKeyIndex;
    ExportOneKeyL();
}

// ---------------------------------------------------------------------------
// CAdvSecSettingsCertMover::SaveExportedKeyL()
// ---------------------------------------------------------------------------
//
void CAdvSecSettingsCertMover::SaveExportedKeyL()
{
    TRACE("CAdvSecSettingsCertMover::SaveExportedKeyL()");
    const CCTKeyInfo& keyInfo = *(iKeys[iKeyIndex]);
    iSourceKeyHandle = keyInfo.Handle();

    // TODO: is this needed? should iSavedKeyInfo be always used?
    // Keys having CCTKeyInfo::ELocal access type cannot be imported.
    // Workaround is to create almost identical copy of CCTKeyInfo without
    // ELocal access type flag. UsePolicy is also updated.
    TInt accessType = keyInfo.AccessType();
    if (accessType & CCTKeyInfo::ELocal) {
        accessType ^= CCTKeyInfo::ELocal;

        HBufC* label = keyInfo.Label().AllocLC();
        if (iSavedKeyInfo) {
            iSavedKeyInfo->Release();
            iSavedKeyInfo = NULL;
        }
        iSavedKeyInfo = CCTKeyInfo::NewL( keyInfo.ID(), keyInfo.Usage(),
            keyInfo.Size(), NULL, label, keyInfo.Token(), keyInfo.HandleID(),
            KKeyStoreUsePolicy, keyInfo.ManagementPolicy(),keyInfo.Algorithm(),
            keyInfo.AccessType(), keyInfo.Native(), keyInfo.StartDate(),
            keyInfo.EndDate() );
        CleanupStack::Pop(label);

        iTargetKeyStore->ImportKey(*iDataBuffer, iSavedKeyInfo, iStatus);
    } else {
        iTargetKeyStore->ImportKey(*iDataBuffer, iKeys[iKeyIndex], iStatus);
    }
    iState = EMovingKeyImportingKeys;
    SetActive();
}

// ---------------------------------------------------------------------------
// CAdvSecSettingsCertMover::DeleteOriginalKeyL()
// ---------------------------------------------------------------------------
//
void CAdvSecSettingsCertMover::DeleteOriginalKeyL()
{
    TRACE("CAdvSecSettingsCertMover::DeleteOriginalKeyL()");
    iSourceKeyStore->DeleteKey(iSourceKeyHandle, iStatus);
    iState = EMovingKeyDeletingOriginal;
    SetActive();
}

// ---------------------------------------------------------------------------
// CAdvSecSettingsCertMover::StartMovingCertificatesL()
// ---------------------------------------------------------------------------
//
void CAdvSecSettingsCertMover::StartMovingCertificatesL()
{
    TRACE("CAdvSecSettingsCertMover::StartMovingCertificatesL()");
    if (iCertFilter) {
        delete iCertFilter;
        iCertFilter = NULL;
    }
    iCertFilter = CCertAttributeFilter::NewL();
    iCertFilter->SetOwnerType(EUserCertificate);
    iCertFilter->SetSubjectKeyId(iCertInfo->SubjectKeyId());
    iCertStore->List(iCerts, *iCertFilter, iStatus);
    iState = EMovingCertListingCerts;
    SetActive();
}

// ---------------------------------------------------------------------------
// CAdvSecSettingsCertMover::RetrieveFirstCertL()
// ---------------------------------------------------------------------------
//
void CAdvSecSettingsCertMover::RetrieveFirstCertL()
{
    TRACE1("CAdvSecSettingsCertMover::RetrieveFirstCertL(), iCerts.Count()=%d", iCerts.Count());
    iCertIndex = 0;
    RetrieveOneCertL();
}

// ---------------------------------------------------------------------------
// CAdvSecSettingsCertMover::RetrieveOneCertL()
// ---------------------------------------------------------------------------
//
void CAdvSecSettingsCertMover::RetrieveOneCertL()
{
    TRACE("CAdvSecSettingsCertMover::RetrieveOneCertL()");
    if (iCertIndex < iCerts.Count()) {
        const CCTCertInfo& certInfo = *(iCerts[iCertIndex]);
        iSourceCertStore->Retrieve(certInfo, iDataPtr, iStatus);
        iState = EMovingCertRetrievingCerts;
        SetActive();
    } else {
        TRACE("CAdvSecSettingsCertMover::RetrieveOneCertL(), all done");
        iState = EIdle;
        User::RequestComplete(iClientStatus, KErrNone);
        iClientStatus = NULL;
    }
}

// ---------------------------------------------------------------------------
// CAdvSecSettingsCertMover::RetrieveNextCertL()
// ---------------------------------------------------------------------------
//
void CAdvSecSettingsCertMover::RetrieveNextCertL()
{
    TRACE("CAdvSecSettingsCertMover::RetrieveNextCertL()");
    ++iCertIndex;
    RetrieveOneCertL();
}

// ---------------------------------------------------------------------------
// CAdvSecSettingsCertMover::SaveRetrievedCertL()
// ---------------------------------------------------------------------------
//
void CAdvSecSettingsCertMover::SaveRetrievedCertL()
{
    TRACE("CAdvSecSettingsCertMover::SaveRetrievedCertL()");
    const CCTCertInfo& certInfo = *(iCerts[iCertIndex]);
    iTargetCertStore->Add(certInfo.Label(), EX509Certificate, EUserCertificate,
        &(certInfo.SubjectKeyId()), &(certInfo.IssuerKeyId()), *iDataBuffer, iStatus);
    iState = EMovingCertAddingCerts;
    SetActive();
}

// ---------------------------------------------------------------------------
// CAdvSecSettingsCertMover::DeleteOriginalCertL()
// ---------------------------------------------------------------------------
//
void CAdvSecSettingsCertMover::DeleteOriginalCertL()
{
    TRACE("CAdvSecSettingsCertMover::DeleteOriginalCertL()");
    const CCTCertInfo& certInfo = *(iCerts[iCertIndex]);
    iSourceCertStore->Remove(certInfo, iStatus);
    iState = EMovingCertDeletingOriginal;
    SetActive();
}