cryptoservices/certificateandkeymgmt/tcertcommon/tcertutils.cpp
changeset 0 2c201484c85f
child 8 35751d3474b7
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cryptoservices/certificateandkeymgmt/tcertcommon/tcertutils.cpp	Wed Jul 08 11:25:26 2009 +0100
@@ -0,0 +1,769 @@
+/*
+* Copyright (c) 2005-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: 
+* tcertuils.cpp
+*
+*/
+
+
+#include "tcertutils.h"
+#include <wtlscert.h>
+#include <certificateapps.h>
+#include <t_input.h>
+#include <ccertattributefilter.h>
+#include <cctcertinfo.h>
+#include <mctwritablecertstore.h>
+
+
+EXPORT_C CCertUtils* CCertUtils::NewL(RFs& aFs)
+	{
+	CCertUtils* self = CCertUtils::NewLC(aFs);
+	CleanupStack::Pop(self);
+	return self;
+	}
+
+EXPORT_C CCertUtils* CCertUtils::NewLC(RFs& aFs)
+	{
+	CCertUtils* self = new(ELeave) CCertUtils(aFs);
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	return self;
+	}
+
+CCertUtils::CCertUtils(RFs& aFs)
+: CActive(EPriorityNormal), iFs(aFs)
+	{
+	CActiveScheduler::Add(this);
+	}
+
+EXPORT_C CCertUtils::~CCertUtils()
+	{
+	Cancel();
+
+	delete iCertificate;
+	delete iCreatedUnifiedCertStore;
+	
+	delete iCertData;
+	delete iLabelData;
+	delete iSecondCertUtils;
+
+	delete iCAFilter;
+	delete iUserFilter;
+
+	iCACertStoreEntries.Close();		// The entries are owned by us
+	iUserCertStoreEntries.Close();		// The entries are owned by us
+	iTrusters.Close();
+	}
+
+/**
+This function handles all the asynchronous calls. There is at least 
+one state for each of the functions of CCertUtils that requires 
+asynchronicity.
+*/
+void CCertUtils::RunL()
+	{
+	if (iStatus != KErrNone)
+        {
+        User::RequestComplete(iOriginalRequestStatus, iStatus.Int());
+        return;
+        }
+
+	switch (iState)
+		{
+		// Used for AddCACerts
+		case EAddCACerts:
+			HandleEAddCACertsL();
+			break;
+
+		// Used for AddCert
+		case EAddCert:
+			TRAPD(err, HandleEAddCACertL());
+			if (err != KErrNone)
+				{
+				iDiagnosticState = EAddCert;
+                User::RequestComplete(iOriginalRequestStatus, err);
+				}
+			break;
+		case EAddCACertGetCAEntry:
+			HandleEAddCACertGetCAEntry();
+			break;
+		case EAddCACertSetApplications:
+			HandleEAddCACertSetApplicationsL();
+			break;
+		case EAddCACertSetTrust:
+			HandleEAddCACertSetTrust();
+			break;
+		case EAddCACertFinished:
+			HandleEAddCACertFinishedL();
+			delete iCreatedUnifiedCertStore;
+			iCreatedUnifiedCertStore = 0;
+			break;
+
+		// Used for RemoveCerts
+		case ERemoveCertsGetCACerts:
+			HandleERemoveCertsGetCACerts();
+			break;
+		case ERemoveCertsCACertsRetrieved:
+			HandleERemoveCertsCACertsRetrieved();
+			break;
+		case ERemoveCertsRemoveCACerts:
+			HandleERemoveCertsRemoveCACerts();
+			break;
+		case ERemoveCertsGetUserCerts:
+			HandleERemoveCertsGetUserCerts();
+			break;
+		case ERemoveCertsUserCertsRetrieved:
+			HandleERemoveCertsUserCertsRetrieved();
+			break;
+		case ERemoveCertsRemoveUserCerts:
+			HandleERemoveCertsRemoveUserCerts();
+			break;
+		case ERemoveCertsFinished:
+			HandleERemoveCertsFinished();
+			delete iCreatedUnifiedCertStore;
+			iCreatedUnifiedCertStore = 0;
+			break;
+
+		default:
+			break;
+		}
+	}
+
+TInt CCertUtils::RunError(TInt aError)
+    {
+	User::RequestComplete(iOriginalRequestStatus, aError);
+    return KErrNone;
+    }
+
+void CCertUtils::DoCancel()
+	{
+	if (iSecondCertUtils)
+		iSecondCertUtils->Cancel();
+
+	if (iUnifiedCertStore)
+		{
+		iUnifiedCertStore->Cancel();
+		if (iUnifiedCertStore->WritableCertStoreCount() != 0)
+			{
+			MCTWritableCertStore *store;
+			store = &iUnifiedCertStore->WritableCertStore(0);
+			store->CancelRemove();
+			store->CancelSetApplicability();
+			}
+		}
+
+	if (iStore)
+		iStore->CancelAdd();
+	}
+
+EXPORT_C CCertificate* CCertUtils::CertFromFileLC(const TDesC& aFilename, 
+												  const TDesC& aPathname, 
+												  RFs& aFs,
+												  TCertificateFormat aFormat)
+	{
+	TFileName fullname;
+	fullname.Append(aPathname);
+	fullname.Append(aFilename);
+	HBufC8* certBuf = Input::ReadFileLC(fullname, aFs);
+	CCertificate* cert = 0;
+	if (aFormat == EX509Certificate)
+		{
+		cert = CX509Certificate::NewLC(*certBuf);
+		}
+	else if (aFormat == EWTLSCertificate)
+		{
+		cert = CWTLSCertificate::NewLC(*certBuf);
+		}
+	CleanupStack::Pop();//cert
+	CleanupStack::PopAndDestroy();//buf
+	CleanupStack::PushL(cert);
+	return cert;
+	}
+
+EXPORT_C CCertificate* CCertUtils::CertFromFileL(const TDesC& aFilename,
+												 const TDesC& aPathname,
+												 RFs& aFs,
+												 TCertificateFormat aFormat)
+	{
+	CCertificate* cert = CertFromFileLC(aFilename, aPathname, aFs, aFormat);
+	CleanupStack::Pop();
+	return cert;
+	}
+
+EXPORT_C void CCertUtils::AddCertL(const TDesC& aLabel,
+								  TCertificateFormat aFormat,
+								  TCertificateOwnerType aCertificateOwnerType, 
+								  TInt aTrustedUsage, 
+								  const TDesC& aCertificatePath, 
+								  const TDesC& aCertificateFileName,
+								  TRequestStatus& aStatus)
+	{
+	iOriginalRequestStatus = &aStatus;
+	aStatus = KRequestPending;
+
+	// We set up the member variable as required for this function
+	iCertificateFileName = &aCertificateFileName;
+	iLabel = &aLabel;
+	iFormat = aFormat;
+	iTrustedUsage = aTrustedUsage;
+	iPath = &aCertificatePath;
+	iCertificateOwnerType = aCertificateOwnerType;
+
+	if (iCreatedUnifiedCertStore)
+		{
+		delete iCreatedUnifiedCertStore;
+		}
+
+	iCreatedUnifiedCertStore = CUnifiedCertStore::NewL(iFs, ETrue);	// We want to open it for 
+																	// writing
+	iUnifiedCertStore = iCreatedUnifiedCertStore;
+	iCreatedUnifiedCertStore->Initialize(iStatus);
+	iState = EAddCert;
+	SetActive();
+	}
+
+EXPORT_C void CCertUtils::AddCert(const TDesC& aLabel,
+								  TCertificateFormat aFormat,
+								  TCertificateOwnerType aCertificateOwnerType, 
+								  TInt aTrustedUsage, 
+								  const TDesC& aCertificatePath, 
+								  const TDesC& aCertificateFileName,
+								  CUnifiedCertStore& aUnifiedCertStore,
+								  TRequestStatus& aStatus)
+	{
+	iOriginalRequestStatus = &aStatus;
+	aStatus = KRequestPending;
+
+	// We set up the member variable as required for this function
+	iCertificateFileName = &aCertificateFileName;
+	iLabel = &aLabel;
+	iFormat = aFormat;
+	iTrustedUsage = aTrustedUsage;
+	iPath = &aCertificatePath;
+	iCertificateOwnerType = aCertificateOwnerType;
+	iUnifiedCertStore = &aUnifiedCertStore;
+	
+	iState = EAddCert;
+	SetActive();
+	TRequestStatus* status = &iStatus;
+	User::RequestComplete(status, KErrNone);
+	}
+
+EXPORT_C void CCertUtils::AddCACertsL(const CDesCArray& aRoots,
+									  const CDesCArray& aLabels,
+									  TCertificateFormat aFormat,
+									  TInt aTrustedUsage, 									
+									  const TDesC& aPath,
+									  TRequestStatus& aStatus)
+	{
+	iOriginalRequestStatus = &aStatus;
+	aStatus = KRequestPending;
+
+	// We set up the member variable as required for this function
+	iRoots = &aRoots;
+	iFormat = aFormat;
+	iLabels = &aLabels;	
+	iTrustedUsage = aTrustedUsage;
+	iPath = &aPath;
+	
+	iIndex = -1;	// -1 because it will be incremented before its first use
+	if (!iSecondCertUtils)
+		{
+		iSecondCertUtils = CCertUtils::NewL(iFs);
+		}
+
+	if (iCreatedUnifiedCertStore)
+		{
+		delete iCreatedUnifiedCertStore;
+		}
+
+	iCreatedUnifiedCertStore = CUnifiedCertStore::NewL(iFs, ETrue);	// We want to open it for 
+																	// writing
+	iUnifiedCertStore = iCreatedUnifiedCertStore;
+	iCreatedUnifiedCertStore->Initialize(iStatus);
+
+	iState = EAddCACerts;
+	SetActive();
+	}
+
+EXPORT_C void CCertUtils::AddCACertsL(const CDesCArray& aRoots,
+									  const CDesCArray& aLabels,
+									  TCertificateFormat aFormat,
+									  TInt aTrustedUsage, 									
+									  const TDesC& aPath,
+									  CUnifiedCertStore& aUnifiedCertStore, 
+									  TRequestStatus& aStatus)
+	{
+	iOriginalRequestStatus = &aStatus;
+	aStatus = KRequestPending;
+
+	// We set up the member variable as required for this function
+	iRoots = &aRoots;
+	iFormat = aFormat;
+	iLabels = &aLabels;
+	iTrustedUsage = aTrustedUsage;
+	iPath = &aPath;
+	iUnifiedCertStore = &aUnifiedCertStore;
+
+	iIndex = -1;	// -1 because it will be incremented before its first use
+	if (!iSecondCertUtils)
+		{
+		iSecondCertUtils = CCertUtils::NewL(iFs);
+		}
+
+	iState = EAddCACerts;
+	SetActive();
+	TRequestStatus* status = &iStatus;
+	User::RequestComplete(status, KErrNone);
+	}
+
+EXPORT_C void CCertUtils::RemoveCertsL(CUnifiedCertStore& aUnifiedCertStore,
+									   TRequestStatus& aStatus)
+	{
+	iOriginalRequestStatus = &aStatus;
+	aStatus = KRequestPending;	
+	iUnifiedCertStore = &aUnifiedCertStore;
+
+	iState = ERemoveCertsGetCACerts;
+	TRequestStatus* status = &iStatus;
+	User::RequestComplete(status, KErrNone);
+	SetActive();
+	}
+
+EXPORT_C void CCertUtils::RemoveCertsL(TRequestStatus& aStatus)
+	{
+	iOriginalRequestStatus = &aStatus;
+	aStatus = KRequestPending;	
+	iState = ERemoveCertsGetCACerts;
+	
+	if (iCreatedUnifiedCertStore)
+		{
+		delete iCreatedUnifiedCertStore;
+		}
+	
+	iCreatedUnifiedCertStore = CUnifiedCertStore::NewL(iFs, ETrue);	// We want to open it for 
+																	// writing
+	iUnifiedCertStore = iCreatedUnifiedCertStore;
+	iCreatedUnifiedCertStore->Initialize(iStatus);
+	SetActive();
+	}
+
+EXPORT_C void CCertUtils::WriteError(TValidationError aError, Output& aOut)
+	{
+	aOut.writeString(CCertUtils::MapError(aError));
+	}
+
+EXPORT_C TPtrC CCertUtils::MapError(TValidationError aError)
+	{
+
+	switch(aError)
+		{
+		//errors
+		case EValidatedOK:
+			{
+			return (_L("Validated OK"));
+			}
+		case EChainHasNoRoot:
+			{
+			return(_L("Chain has no root"));
+			}
+		case ESignatureInvalid:
+			{
+			return(_L("Signature invalid"));
+			}
+		case EDateOutOfRange:
+			{
+			return(_L("Date out of range"));
+			}
+		case ENameIsExcluded:
+			{
+			return(_L("Name is excluded"));
+			}
+		case ENameNotPermitted:
+			{
+			return(_L("Name is not permitted"));
+			}
+		case ECertificateRevoked:
+			{
+			return(_L("Certificate revoked"));
+			}
+		case EUnrecognizedCriticalExtension:
+			{
+			return(_L("Unrecognized Critical Extension"));
+			}
+		case ENoBasicConstraintInCACert:
+			{
+			return(_L("CA cert with no Basic Constraint"));
+			}
+		case ENoAcceptablePolicy:
+			{
+			return(_L("No acceptable policy"));
+			}
+		case EPathTooLong:
+			{
+			return(_L("Path too long"));
+			}
+		case ENegativePathLengthSpecified:
+			{
+			return(_L("Negative path length specified"));
+			}
+		case ENamesDontChain:
+			{
+			return(_L("Names don't chain"));
+			}
+		case ERequiredPolicyNotFound:
+			{
+			return(_L("Required policy not found"));
+			}
+		case EBadKeyUsage:
+			{
+			return(_L("Bad key usage"));
+			}
+		case ENotCACert:
+			{
+			return(_L("Non-CA cert used as CA cert"));
+			}
+		//warnings
+		case ERootCertNotSelfSigned:
+			{
+			return(_L("Root cert not self-signed"));
+			}
+		case ECriticalExtendedKeyUsage:
+			{
+			return(_L("Critical extended key usage"));
+			}
+		case ECriticalCertPoliciesWithQualifiers:
+			{
+			return(_L("Critical cert policies with qualifiers"));
+			}
+		case ECriticalPolicyMapping:
+			{
+			return(_L("Critical policy mapping"));
+			}
+		case ECriticalDeviceId:
+			{
+			return(_L("Critical Device Id"));
+			}
+		case ECriticalSid:
+			{
+			return(_L("Critical Sid"));
+			}
+		case ECriticalVid:
+			{
+			return(_L("Critical Vid"));
+			}
+		case ECriticalCapabilities:
+			{
+			return(_L("Critical Capabilities"));
+			}
+		}
+	return (_L("Unknown Error"));
+	}
+
+
+EXPORT_C HBufC* CCertUtils::DiagnosticLC() const
+	{
+	HBufC* result = HBufC::NewLC(600);
+	switch (iDiagnosticState)
+		{
+		case EAddCert:
+			result->Des().Append(_L("EAddCACert"));
+			result->Des().Append(_L(" : "));
+			result->Des().Append(iDiagnosticMessage);
+			break;
+
+		default:
+			break;
+		}
+
+	return result;
+	}
+
+EXPORT_C void CCertUtils::AddApplicationL(const TDesC& aName, TUid aUid) const
+	{
+	CCertificateAppInfoManager* appManager = CCertificateAppInfoManager::NewL(iFs, ETrue);
+	CleanupStack::PushL(appManager);
+
+	// Only add the application if it doesn't exist already
+	const RArray<TCertificateAppInfo>& apps = appManager->Applications();
+	TInt i;
+	for (i = 0 ; i < apps.Count() ; ++i)
+		{
+		if (apps[i].Id() == aUid && apps[i].Name() == aName)
+			break;
+		}
+
+	if (i == apps.Count())
+		{
+		appManager->AddL(TCertificateAppInfo(aUid, aName));
+		}
+	
+	CleanupStack::PopAndDestroy(appManager);
+	}
+
+EXPORT_C void CCertUtils::RemoveApplicationL(TUid aUid) const
+	{
+	CCertificateAppInfoManager* appManager = CCertificateAppInfoManager::NewL(iFs, ETrue);
+	CleanupStack::PushL(appManager);
+	appManager->RemoveL(aUid);
+	CleanupStack::PopAndDestroy(appManager);
+	}
+
+
+void CCertUtils::ConstructL()
+	{
+	iCAFilter = CCertAttributeFilter::NewL();
+	iCAFilter->SetOwnerType(ECACertificate);
+	iUserFilter = CCertAttributeFilter::NewL();
+	iUserFilter->SetOwnerType(EUserCertificate);
+	}
+
+void CCertUtils::HandleEAddCACertsL()
+	{
+	iIndex++;
+	if (iIndex < iRoots->Count())
+		{
+		// We still have some certificates to add
+		if (iCertData)
+			{	
+			delete iCertData;
+			iCertData = 0;
+			}
+		iCertData = iRoots->MdcaPoint(iIndex).AllocL();
+		if (iLabelData)
+			{
+			delete iLabelData;
+			iLabelData = 0;
+			}
+		iLabelData = iLabels->MdcaPoint(iIndex).AllocL();
+		iSecondCertUtils->AddCert(*iLabelData, iFormat, ECACertificate,
+			iTrustedUsage, *iPath, *iCertData, *iUnifiedCertStore, iStatus);
+		SetActive();
+		}
+	else
+		{
+		// We have finished adding all the certificates
+		delete iSecondCertUtils;
+		iSecondCertUtils = 0;
+		delete iCreatedUnifiedCertStore;
+		iCreatedUnifiedCertStore = 0;
+		User::RequestComplete(iOriginalRequestStatus, KErrNone);
+		}
+	}
+
+void CCertUtils::HandleEAddCACertL()
+	{
+	// At this stage we should always have an initialized iStoreManager
+	__ASSERT_DEBUG(iUnifiedCertStore, User::Panic(_L("TCertUtils"), 1));
+	
+	// We use the first writable certstore
+	iStore = &iUnifiedCertStore->WritableCertStore(0);
+		
+	__ASSERT_DEBUG(!iCertificate, User::Panic(_L("TCertUtils"), 1));
+	iCertificate = 0;
+	TRAPD(err, iCertificate =
+		CCertUtils::CertFromFileL(*iCertificateFileName, *iPath, iFs, iFormat));
+	if (err != KErrNone)
+		{
+		if (err != KErrNoMemory)
+			{
+			iDiagnosticMessage.Zero();
+			iDiagnosticMessage.Append(_L("CertFromFileL failed ("));
+			iDiagnosticMessage.Append(*iCertificateFileName);
+			iDiagnosticMessage.Append(_L(")"));
+			}
+		User::Leave(err);
+		}
+	iEncoding.Set(iCertificate->Encoding());
+	iStore->Add(*iLabel, iFormat, iCertificateOwnerType, 0, 0, iEncoding, iStatus);
+	iState = EAddCACertGetCAEntry;
+	SetActive();
+	}
+
+void CCertUtils::HandleEAddCACertGetCAEntry()
+	{
+	delete iCertificate;
+	iCertificate = 0;
+	iCACertStoreEntries.Close();
+	iUnifiedCertStore->List(iCACertStoreEntries, *iCAFilter, iStatus);
+	iState = EAddCACertSetApplications;
+	SetActive();
+	}
+
+void CCertUtils::HandleEAddCACertSetApplicationsL()
+	{
+	CCTCertInfo* entry = 0;
+	TInt iEnd = iCACertStoreEntries.Count();
+	for (TInt i = 0; i < iEnd; i++)
+		{
+		if (iCACertStoreEntries[i]->Label() == *iLabel)
+			{
+			entry = iCACertStoreEntries[i];
+			}
+		}
+
+	__ASSERT_ALWAYS(entry, User::Panic(_L("TCertUtils"), 1));
+
+	iTrusters.Reset();
+	TUid truster = { iTrustedUsage };
+	User::LeaveIfError(iTrusters.Append(truster));
+	
+	iUnifiedCertStore->SetApplicability(*entry, iTrusters, iStatus);
+	iState = EAddCACertSetTrust;
+	SetActive();
+	}
+
+void CCertUtils::HandleEAddCACertSetTrust()
+	{
+	CCTCertInfo* entry = 0;
+	TInt iEnd = iCACertStoreEntries.Count();
+	for (TInt i = 0; i < iEnd; i++)
+		{
+		if (iCACertStoreEntries[i]->Label() == *iLabel)
+			{
+			entry = iCACertStoreEntries[i];
+			}
+		}
+
+	__ASSERT_ALWAYS(entry, User::Panic(_L("TCertUtils"), 1));
+
+	iUnifiedCertStore->SetTrust(*entry, ETrue, iStatus);
+	iState = EAddCACertFinished;
+	SetActive();
+	}
+
+void CCertUtils::HandleEAddCACertFinishedL()
+	{
+	User::RequestComplete(iOriginalRequestStatus, iStatus.Int());
+	}
+
+void CCertUtils::HandleERemoveCertsGetCACerts()
+	{
+	// At this stage we should always have an initialized iStoreManager
+	__ASSERT_DEBUG(iUnifiedCertStore, User::Panic(_L("TCertUtils"), 1));
+
+	iCACertStoreEntries.Close();
+	iUnifiedCertStore->List(iCACertStoreEntries, *iCAFilter, iStatus);
+
+	iState = ERemoveCertsCACertsRetrieved;
+	SetActive();
+	}
+
+void CCertUtils::HandleERemoveCertsCACertsRetrieved()
+	{
+	// This index will be used to keep track of the current entry
+	iIndex = -1;
+
+	iState = ERemoveCertsRemoveCACerts;
+	TRequestStatus* status = &iStatus;
+	SetActive();
+	User::RequestComplete(status, KErrNone);
+	}
+
+void CCertUtils::HandleERemoveCertsRemoveCACerts()
+	{
+	iIndex++;
+	if (iIndex < iCACertStoreEntries.Count())
+		{
+		// Remove this certificate if it can be deleted.
+		
+		CCTCertInfo& cert = *iCACertStoreEntries[iIndex];
+		
+		// Unfortunately, certs in non-writable stores can still be
+		// marked as deletable, so need to check if cert is also in a
+		// writable store.
+		
+		TBool isDeletable = cert.IsDeletable();
+		
+		TBool inWritableStore = EFalse;
+		
+		TCTTokenObjectHandle certHandle(cert.Handle());
+		TInt writeStoreCount = iUnifiedCertStore->WritableCertStoreCount();
+		for (TInt i = 0; i < writeStoreCount; ++i)
+			{
+			MCTWritableCertStore& wcs = iUnifiedCertStore->WritableCertStore(i);
+			if (wcs.Token().Handle() == certHandle.iTokenHandle)
+				{
+				inWritableStore = ETrue;
+				break;
+				}
+			}
+		
+		if (isDeletable && inWritableStore)
+			{
+			iUnifiedCertStore->Remove(cert, iStatus);
+			SetActive();
+			}
+		else
+			{
+			TRequestStatus* status = &iStatus;
+			SetActive();
+			User::RequestComplete(status, KErrNone);
+			}
+		}
+	else
+		{
+		iState = ERemoveCertsGetUserCerts;
+		TRequestStatus* status = &iStatus;
+		SetActive();
+		User::RequestComplete(status, KErrNone);
+		}
+	}
+
+void CCertUtils::HandleERemoveCertsGetUserCerts()
+	{
+	// At this stage we should always have an initialized iStoreManager
+	__ASSERT_DEBUG(iUnifiedCertStore, User::Panic(_L("TCertUtils"), 1));
+
+	iUserCertStoreEntries.Close();
+	iUnifiedCertStore->List(iUserCertStoreEntries, *iUserFilter, iStatus);
+
+	iState = ERemoveCertsUserCertsRetrieved;
+	SetActive();
+	}
+
+void CCertUtils::HandleERemoveCertsUserCertsRetrieved()
+	{
+	iIndex = -1;
+
+	iState = ERemoveCertsRemoveUserCerts;
+	TRequestStatus* status = &iStatus;
+	SetActive();
+	User::RequestComplete(status, KErrNone);
+	}
+
+void CCertUtils::HandleERemoveCertsRemoveUserCerts()
+	{
+	// At this stage we should always have an initialized iStoreManager
+	__ASSERT_DEBUG(iUnifiedCertStore, User::Panic(_L("TCertUtils"), 1));
+
+	iIndex++;
+	if (iIndex < iUserCertStoreEntries.Count())
+		{
+		iUnifiedCertStore->Remove(*iUserCertStoreEntries[iIndex], iStatus);
+		SetActive();
+		}
+	else
+		{
+		iState = ERemoveCertsFinished;
+		TRequestStatus* status = &iStatus;
+		SetActive();
+		User::RequestComplete(status, KErrNone);
+		}
+	}
+
+void CCertUtils::HandleERemoveCertsFinished()
+	{
+	User::RequestComplete(iOriginalRequestStatus, KErrNone);
+	}