cryptoservices/certificateandkeymgmt/pkixcertbase/pkixcertchainao.cpp
changeset 8 35751d3474b7
parent 0 2c201484c85f
child 19 ece3df019add
--- a/cryptoservices/certificateandkeymgmt/pkixcertbase/pkixcertchainao.cpp	Tue Jul 21 01:04:32 2009 +0100
+++ b/cryptoservices/certificateandkeymgmt/pkixcertbase/pkixcertchainao.cpp	Thu Sep 10 14:01:51 2009 +0300
@@ -1,613 +1,613 @@
-/*
-* Copyright (c) 1998-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 "pkixcertchainao.h"
-#include "pkixCons.h"
-#include <x509keys.h>
-#include <pkixcertchain.h>
-#include <x509constraintext.h>
-
-CPKIXCertChainAO* CPKIXCertChainAO::NewL(MCertStore& aCertStore,
-										 CPKIXCertChainBase &aPKIXCertChain,
-										 const RPointerArray<CX509Certificate>& aRootCerts)
-	{
-	CPKIXCertChainAO* self = new(ELeave) CPKIXCertChainAO(aCertStore, aPKIXCertChain);
-	CleanupStack::PushL(self);
-	self->ConstructL(aRootCerts);
-	CleanupStack::Pop(self);
-	return self;
-	}
-
-CPKIXCertChainAO* CPKIXCertChainAO::NewL(MCertStore& aCertStore, 
-										 CPKIXCertChainBase &aPKIXCertChain,
-										 const TUid aClient)
-	{
-	return new(ELeave) CPKIXCertChainAO(aCertStore, aPKIXCertChain, aClient);
-	}
-
-CPKIXCertChainAO::~CPKIXCertChainAO()
-	{
-	Cancel();
-
-	delete iRoots;
-	delete iBuilder;
-	delete iCertsFromStoreRoots;
-	}
-
-CPKIXCertChainAO::CPKIXCertChainAO(MCertStore& aCertStore,
-								   CPKIXCertChainBase &aPKIXCertChain)
-	: CActive(EPriorityNormal), iCertStore(&aCertStore), iPKIXCertChain(aPKIXCertChain)
-	{
-	CActiveScheduler::Add(this);
-	}
-
-CPKIXCertChainAO::CPKIXCertChainAO(MCertStore& aCertStore, 
-								   CPKIXCertChainBase &aPKIXCertChain,
-								   const TUid aClient)
-	: CActive(EPriorityNormal), iCertStore(&aCertStore),
-	  iPKIXCertChain(aPKIXCertChain), iClient(aClient)
-	{
-	CActiveScheduler::Add(this);
-	}
-
-void CPKIXCertChainAO::ConstructL(const RPointerArray<CX509Certificate>& aRootCerts)
-	{
-	CPKIXCertsFromClient* roots = CPKIXCertsFromClient::NewLC(aRootCerts);
-	iRoots = CPKIXChainBuilder::NewL();
-	iRoots->AddSourceL(roots);
-	CleanupStack::Pop(roots);
-	}
-
-void CPKIXCertChainAO::RunL()
-	{
-	User::LeaveIfError(iStatus.Int());
-
-	switch (iState)
-		{
-		case EAddRoots:
-			HandleEAddRootsL();
-			break;
-
-		case ERootsInitialized:
-			HandleERootsInitializedL();
-			break;
-
-		case EBuildChainStart:
-			HandleEBuildChainStartL();
-			break;
-
-		case EBuildChainAddCandidateEnd:
-			HandleEBuildChainAddCandidateEndL();
-			break;
-
-		case EBuildChainCertsFromStoreBegin:
-			HandleEBuildChainCertsFromStoreBeginL();
-			break;
-
-		case EBuildChainCertsFromStoreEnd:
-			HandleEBuildChainCertsFromStoreEndL();
-			break;
-
-		case EAddCandidateIntermediateCertsEnd:
-			HandleEAddCandidateIntermediateCertsEndL();
-			break;
-
-		case EValidateEnd:
-			HandleEValidateEndL();
-			break;
-
-		default:
-			User::Panic(_L("CPKIXCertChainAO"), 1);
-			break;
-		}
-	}
-
-TInt CPKIXCertChainAO::RunError(TInt aError)
-{
-	iPKIXCertChain.RemoveLastCerts(iNumberOfAddedCertificates);
-	iNumberOfAddedCertificates = 0;
-
-	delete iRoots;
-	iRoots = 0;
-		
-	delete iBuilder;
-	iBuilder = 0;
-	delete iCertsFromStoreRoots;
-	iCertsFromStoreRoots = 0;
-
-	iValidationResult->RemovePolicies();
-
-	User::RequestComplete(iOriginalRequestStatus, aError);
-	return KErrNone;
-}
-
-/**
- * Creates a list of all the certificates retrieved from the store based on the filter passed.  
- */
-
-void CPKIXCertChainAO::HandleEAddRootsL()
-	{
-	__ASSERT_DEBUG(!iCertsFromStoreRoots, User::Panic(_L("CPKICCertChainAO"), 1));
-	iCertsFromStoreRoots = CPKIXCertsFromStore::NewL(*iCertStore, iClient);
-	iCertsFromStoreRoots->Initialize(iStatus);
-	iState = ERootsInitialized;	
-	SetActive();
-	}
-
-/**
- * Adds the list of certificates retrieved from the store, iRoots (CPKIXChainBuilder)
- * maintains a templatized list of all the certificates in MPKIXCertSource format.
- */
-
-void CPKIXCertChainAO::HandleERootsInitializedL()
-	{
-	iRoots->AddSourceL(iCertsFromStoreRoots);
-	// Ownership has been passed to iRoots
-	iCertsFromStoreRoots = 0;
-	iState = EBuildChainStart;
-	TRequestStatus* status = &iStatus;
-	User::RequestComplete(status, KErrNone);
-	SetActive();
-	}
-
-void CPKIXCertChainAO::HandleEBuildChainStartL()
-	{
-	if ( false == iPKIXCertChain.ChainHasRoot())
-		{
-		if (iPKIXCertChain.Chain().Count() == 0)
-			{
-			iState = EValidateEnd;
-			TRequestStatus* status = &iStatus;
-			User::RequestComplete(status, KErrNone);
-			}
-		else
-			{
-			//1) look for an issuer that's a root
-			iRoots->AddIssuer(iNumberOfAddedCertificates, iAddIssuerResult, iPKIXCertChain.Chain(), iStatus);
-			iState = EBuildChainAddCandidateEnd;
-			}
-		}
-	else
-		{
-		// This is the correct state as at this point the chain of certificate has been build upto a
-		// root certificate.
-		iState = EValidateEnd;
-		TRequestStatus* status = &iStatus;
-		User::RequestComplete(status, KErrNone);
-		}
-	SetActive();
-	}
-
-void CPKIXCertChainAO::HandleEBuildChainAddCandidateEndL()
-	{
-	if (iAddIssuerResult)
-		{
-		iPKIXCertChain.SetChainHasRoot(ETrue);
-		iState = EValidateEnd;
-		}
-	else
-		{
-		//2) look for a non-root issuer in intermediate certs
-		iBuilder = CPKIXChainBuilder::NewL();
-		
-		CPKIXCertsFromClient* serverCerts = CPKIXCertsFromClient::NewLC(iPKIXCertChain.IntermediateCerts());
-		iBuilder->AddSourceL(serverCerts);
-		CleanupStack::Pop(serverCerts);
-
-		iState = EBuildChainCertsFromStoreBegin;
-		}
-
-	TRequestStatus* status = &iStatus;
-	User::RequestComplete(status, KErrNone);
-	SetActive();
-	}
-
-void CPKIXCertChainAO::HandleEBuildChainCertsFromStoreBeginL()
-	{
-	//3) look for a non-root issuer in the store
-	iCertsFromStoreRoots = CPKIXCertsFromStore::NewL(*iCertStore);
-	iCertsFromStoreRoots->Initialize(iStatus);
-	iState = EBuildChainCertsFromStoreEnd;
-	SetActive();
-	}
-
-void CPKIXCertChainAO::HandleEBuildChainCertsFromStoreEndL()
-	{
-	iBuilder->AddSourceL(iCertsFromStoreRoots);
-	iCertsFromStoreRoots = 0;
-
-	iBuilder->AddIssuer(iNumberOfAddedCertificates, iAddIssuerResult, iPKIXCertChain.Chain(), iStatus);
-	iState = EAddCandidateIntermediateCertsEnd;
-	SetActive();
-	}
-
-void CPKIXCertChainAO::HandleEAddCandidateIntermediateCertsEndL()
-	{
-	if (iAddIssuerResult)
-		{
-		// cert is a pointer to something we don't own
-		CX509Certificate* cert = iPKIXCertChain.Chain().At(iPKIXCertChain.Chain().Count() - 1);
-		
-		/* If the issuer is not a self signed certificate then it cannot be trusted anchor for the chain 
-		 * validation process, this means that we restart the certification validation process.
-		 */ 
-		
-		if (!(cert->IsSelfSignedL()))
-			{
-			iState = EBuildChainStart;	
-			}
-		else
-			{
-			iState = EValidateEnd;			
-			}
-		}
-	else
-		{
-		iState = EValidateEnd;	
-		}
-
-	delete iBuilder;
-	iBuilder = 0;
-
-	TRequestStatus* status = &iStatus;
-	User::RequestComplete(status, KErrNone);
-	SetActive();
-	}
-
-void CPKIXCertChainAO::HandleEValidateEndL()
-	{
-	InitParamsL();
-	
-	__ASSERT_DEBUG(iValidationResult, User::Panic(_L("CPKICCertChainAO"), 1));
-	DoValidateL(*iValidationResult, iValidationTime, iInitialPolicies);
-
-	User::RequestComplete(iOriginalRequestStatus, KErrNone);
-	}
-
-void CPKIXCertChainAO::DoCancel()
-	{
-	delete iRoots;
-	iRoots = 0;
-
-	delete iBuilder;
-	iBuilder = 0;
-
-	delete iCertsFromStoreRoots;
-	iCertsFromStoreRoots = 0;
-
-	User::RequestComplete(iOriginalRequestStatus, KErrCancel);
-	}
-
-void CPKIXCertChainAO::ValidateL(CPKIXValidationResultBase& aValidationResult,
-								 const TTime& aValidationTime,								 
-								 const CArrayPtr<HBufC>* aInitialPolicies,
-								 TRequestStatus& aStatus)
-	{
-	aValidationResult.Reset();
-	iValidationResult = &aValidationResult;
-	iValidationTime = aValidationTime;
-	iInitialPolicies = aInitialPolicies;
-	iOriginalRequestStatus = &aStatus;
-	iNumberOfAddedCertificates = 0;
-
-	__ASSERT_ALWAYS(!IsActive(), User::Panic(_L("CPKICCertChainAO"), 1));
-
-	if (!iRoots)
-		{
-		// If iRoots is 0, it means that the caller gave a uid and that
-		// we must retrieve the trusted certificates from the different
-		// stores
-		iRoots = CPKIXChainBuilder::NewL();
-		iState = EAddRoots;
-		}
-	else
-		{
-		// The caller gave a set of certificates it trusts,
-		// so we don't have to retrieve anything from the stores
-		iState = EBuildChainStart;
-		}
-
-	aStatus = KRequestPending;
-	TRequestStatus *status = &iStatus;
-	User::RequestComplete(status, KErrNone);
-	SetActive();
-	}
-
-void CPKIXCertChainAO::CancelValidate()
-	{
-	Cancel();
-	}
-
-void CPKIXCertChainAO::InitParamsL()
-/*
-this function initialises signing key parameters for the certificates
--only DSA needs these at present
--we get the signing key, from the spki of the issuer
--if it's dsa, we look for params here
-	-if we find them we initialise the cert with them
-	-otherwise, we look in the issuer's issuer
-		-if we don't find them there we give up.
-*/
-	{
-	
-	// If the root is DSA signed, set its parameters
-
-	TInt count = iPKIXCertChain.Chain().Count();
-	
-	CX509Certificate* current = iPKIXCertChain.Chain().At(count-1);
-	TAlgorithmId signingAlgorithm = current->SigningAlgorithm().AsymmetricAlgorithm().Algorithm();
-	
-	if (signingAlgorithm == EDSA)
-		{
-		
-		const CSubjectPublicKeyInfo& key = current->PublicKey();
-		SetParamsL(*current, key.EncodedParams());
-		
-		}
-	
-	// Also the rest of the chain
-	
-	for (TInt i = count - 2; i >= 0; i--)
-		{
-		
-		current = iPKIXCertChain.Chain().At(i);
-		TAlgorithmId signingAlgorithm = current->SigningAlgorithm().AsymmetricAlgorithm().Algorithm();
-		
-		if (signingAlgorithm == EDSA)
-			{
-			
-			// Look down the chain for parameters
-			
-			for (TInt j = i+1; j < count; j++)
-				{
-				
-				CX509Certificate* issuer = iPKIXCertChain.Chain().At(j);
-				const CSubjectPublicKeyInfo& key = issuer->PublicKey();
-				if (key.EncodedParams() != KNullDesC8 && key.AlgorithmId() == EDSA)
-					{
-					SetParamsL(*current, key.EncodedParams());
-					break;
-					}
-				
-				}
-			
-			}
-		
-		}
-	}
-
-void CPKIXCertChainAO::SetParamsL(CX509Certificate& aCert, const TPtrC8& aEncodedParams)
-	{
-	TX509KeyFactory factory;
-	CDSAParameters* theDSAParams = factory.DSAParametersL(aEncodedParams);
-	CleanupStack::PushL(theDSAParams);
-	
-	CSigningKeyParameters* params = CSigningKeyParameters::NewLC();
-	params->SetDSAParamsL(*theDSAParams);
-	
-	aCert.SetParametersL(*params);
-
-	CleanupStack::PopAndDestroy(2, theDSAParams);
-	}
-
-void CPKIXCertChainAO::DoValidateL(CPKIXValidationResultBase& aValidationResult,
-								 const TTime& aValidationTime, 
-								 const CArrayPtr<HBufC>* aInitialPolicies)
-	{
-	if (!iPKIXCertChain.ChainHasRoot())
-		{
-		aValidationResult.SetError(EChainHasNoRoot, 0);
-		}
-	else
-		{
-		CPKIXValidationState* state = CPKIXValidationState::NewLC(aValidationTime, iPKIXCertChain.Chain().Count(), aInitialPolicies);
-		TRAPD(err, ProcessCertsL(*state, aValidationResult));
-		//a leave here means either:
-		//	-a validation error, in which case we've set the error field in result, or
-		//	-some other error (e.g. OOM) in which case error is still EChainHasNoRoot
-		if ((err != KErrNone) && ((aValidationResult.Error().iReason) == EChainHasNoRoot))
-			//then we left with a non-validation-related error, so leave again...
-			{
-			User::Leave(err);
-			}
-		CleanupStack::PopAndDestroy(state);
-		}
-	}
-
-// ProcessCertsL: This function validates a complete certificate 
-//                chain. If an error occurs in this function the function
-//                SetErrorAndLeaveL must be called. 
-// 
-// Note Do not use SetErrorAndLeaveL with EChainHasNoRoot (see TRAP code in 
-// CPKIXCertChainAO::DoValidateL )             
-void CPKIXCertChainAO::ProcessCertsL(CPKIXValidationState& aState,
-									 CPKIXValidationResultBase& aResult) const
-	{
-	TPKIXPolicyConstraint policy(aState, aResult);
-	TPKIXNameConstraint name(aState, aResult);
-	TPKIXBasicConstraint basic(aState, aResult);
-	TPKIXKeyUsageConstraint keyUsage(aState, aResult);
-	for (; aState.iPos >= 0; aState.iPos--)
-		{
-		aState.iMaxPathLength--;
-		if (aState.iMaxPathLength < aState.iPos)
-			{
-			aResult.SetErrorAndLeaveL(EPathTooLong, aState.iPos);
-			}
-		const CX509Certificate* current = iPKIXCertChain.Chain().At(aState.iPos);
-		CCertificateValidationWarnings* certWarnings = CCertificateValidationWarnings::NewLC(aState.iPos);
-		aResult.AppendCertificateValidationObjectL(*certWarnings);
-		CleanupStack::Pop(certWarnings);
-		CriticalExtsL(aState, *current);
-		CheckCriticalExtsL(aState, aResult);
-		CheckSignatureAndNameL(*current, aState, aResult);
-		//!!!!NO!!checks for revocation at this time!!
-		
-		if (!(current->ValidityPeriod().Valid(aState.iValidationTime)))
-			{
-			//validity period invalid, now check how to report this
-			if (iPKIXCertChain.ValidityPeriodCheckFatal())
-				{
-				aResult.SetErrorAndLeaveL(EDateOutOfRange, aState.iPos);
-				}
-			else
-				{
-				aResult.AppendWarningL(TValidationStatus(EDateOutOfRange, aState.iPos));
-				}
-			}
-		
-		policy.CheckCertPoliciesL(*current);
-		name.CheckNameConstraintsL(*current);
-		keyUsage.CheckKeyUsageL(*current);
-		if (aState.iPos < (iPKIXCertChain.Chain().Count() - 1))
-			{
-			basic.CheckCertSubjectTypeL(*current);
-			}
-		basic.UpdatePathLengthConstraintsL(*current);
-		name.UpdateNameConstraintsL(*current);
-		policy.UpdatePolicyConstraintsL(*current);
-		aState.iCriticalExts->Reset();
-		}
-	policy.FinishPolicyCheckL();
-	//*copy* all policies from aState.iAuthorityConstrainedPolicies into aResult.iPolicies
-	TInt policyCount = aState.iAuthorityConstrainedPolicies->Count();
-	for (TInt i = 0; i < policyCount; i ++)
-		{
-		CX509CertPolicyInfo* policyInfo = CX509CertPolicyInfo::NewLC(*(aState.iAuthorityConstrainedPolicies->At(i)));
-		aResult.AppendPolicyL(*policyInfo);
-		CleanupStack::Pop(policyInfo);
-		}
-
-	aResult.SetError(EValidatedOK, 0);
-	}
-
-void CPKIXCertChainAO::CriticalExtsL(CPKIXValidationState& aState, 
-									 const CX509Certificate& aCert) const
-	{
-	const CArrayPtrFlat<CX509CertExtension>& exts = aCert.Extensions();
-	TInt count = exts.Count();
-	for (TInt i = 0; i < count; i++)
-		{
-		CX509CertExtension* ext = exts.At(i);
-		if (ext->Critical())
-			{
-			aState.iCriticalExts->AppendL(ext);
-			}
-		}	 
-	}
-
-void CPKIXCertChainAO::CheckSignatureAndNameL(const CX509Certificate& aCert, CPKIXValidationState& aState, 
-											CPKIXValidationResultBase& aResult) const
-	{
-	TInt issuerPos = aState.iPos + 1;
-	if (issuerPos == iPKIXCertChain.Chain().Count())
-		//then it's the root
-		{
-		if (aCert.IssuerName().ExactMatchL(aCert.SubjectName()))
-			//then it claims to be self signed, sig must verify
-			{
-			if (!(aCert.VerifySignatureL(aCert.PublicKey().KeyData())))
-				{
-				aResult.SetErrorAndLeaveL(ESignatureInvalid, aState.iPos);
-				}
-			}
-		else
-			//we generate a warning
-			{
-			aResult.AppendWarningL(TValidationStatus(ERootCertNotSelfSigned, aState.iPos));
-			}
-		}
-	else
-		//then it isn't the root: so names must chain & sigs must verify
-		{
-		const CX509Certificate* issuer = iPKIXCertChain.Chain().At(issuerPos);
-		if (!(aCert.IssuerName().ExactMatchL(issuer->SubjectName())))
-			{
-			aResult.SetErrorAndLeaveL(ENamesDontChain, aState.iPos);
-			}
-		if (!(aCert.VerifySignatureL(issuer->PublicKey().KeyData())))
-			{
-			aResult.SetErrorAndLeaveL(ESignatureInvalid, aState.iPos);
-			}
-		}
-	}
-
-void CPKIXCertChainAO::CheckCriticalExtsL(CPKIXValidationState& aState, CPKIXValidationResultBase& aResult) const
-	{
-	TBool foundUnrecognisedCritExt;
-	
-	// retrieve the supported list of critical extensions. If a critical extension is found whose OID matches an 
-	// element in this set then certificate validation shall treat this as a warning instead of an error.
-	const RPointerArray<TDesC>& supportedCritExt = iPKIXCertChain.SupportedCriticalExtensions();
-	
-	TInt count = aState.iCriticalExts->Count();
-	TInt supportedCount = supportedCritExt.Count();
-	for (TInt i = 0; i < count; i++)
-		{
-		foundUnrecognisedCritExt = ETrue;
-		const CX509CertExtension* ext = aState.iCriticalExts->At(i);
-		const TPtrC& extName = ext->Id();
-		
-		for (TInt j = 0; j < supportedCount; ++j)
-			{
-			if (extName == *supportedCritExt[j])
-				{
-				foundUnrecognisedCritExt = EFalse;
-				HBufC* oid = extName.AllocLC();
-				aResult.AppendCriticalExtensionWarningL(*oid);
-				CleanupStack::Pop(oid);
-				break;
-				}
-			}			
-		
-		if (extName == KExtendedKeyUsage)
-			{
-			aResult.AppendWarningL(TValidationStatus(ECriticalExtendedKeyUsage, aState.iPos));
-			}
-		else if (extName == KPolicyMapping)
-			{
-			aResult.AppendWarningL(TValidationStatus(ECriticalPolicyMapping, aState.iPos));
-			}
-		else if (extName == KInhibitAnyPolicy)
-			{
-			//ignore this in the same way
-			}
-		else if (extName == KDeviceIdListConstraint)
-			{
-			aResult.AppendWarningL(TValidationStatus(ECriticalDeviceId, aState.iPos));
-			}
-		else if(extName == KSidListConstraint)
-			{
-			aResult.AppendWarningL(TValidationStatus(ECriticalSid, aState.iPos));
-			}
-		else if(extName == KVidListConstraint)
-			{
-			aResult.AppendWarningL(TValidationStatus(ECriticalVid, aState.iPos));
-			}
-		else if(extName == KCapabilitiesConstraint)
-			{
-			aResult.AppendWarningL(TValidationStatus(ECriticalCapabilities, aState.iPos));
-			}
-		
-		if (foundUnrecognisedCritExt)
-			{
-			aResult.SetErrorAndLeaveL(EUnrecognizedCriticalExtension, aState.iPos);
-			}			
-		
-		}
-	}
+/*
+* Copyright (c) 1998-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 "pkixcertchainao.h"
+#include "pkixCons.h"
+#include <x509keys.h>
+#include <pkixcertchain.h>
+#include <x509constraintext.h>
+
+CPKIXCertChainAO* CPKIXCertChainAO::NewL(MCertStore& aCertStore,
+										 CPKIXCertChainBase &aPKIXCertChain,
+										 const RPointerArray<CX509Certificate>& aRootCerts)
+	{
+	CPKIXCertChainAO* self = new(ELeave) CPKIXCertChainAO(aCertStore, aPKIXCertChain);
+	CleanupStack::PushL(self);
+	self->ConstructL(aRootCerts);
+	CleanupStack::Pop(self);
+	return self;
+	}
+
+CPKIXCertChainAO* CPKIXCertChainAO::NewL(MCertStore& aCertStore, 
+										 CPKIXCertChainBase &aPKIXCertChain,
+										 const TUid aClient)
+	{
+	return new(ELeave) CPKIXCertChainAO(aCertStore, aPKIXCertChain, aClient);
+	}
+
+CPKIXCertChainAO::~CPKIXCertChainAO()
+	{
+	Cancel();
+
+	delete iRoots;
+	delete iBuilder;
+	delete iCertsFromStoreRoots;
+	}
+
+CPKIXCertChainAO::CPKIXCertChainAO(MCertStore& aCertStore,
+								   CPKIXCertChainBase &aPKIXCertChain)
+	: CActive(EPriorityNormal), iCertStore(&aCertStore), iPKIXCertChain(aPKIXCertChain)
+	{
+	CActiveScheduler::Add(this);
+	}
+
+CPKIXCertChainAO::CPKIXCertChainAO(MCertStore& aCertStore, 
+								   CPKIXCertChainBase &aPKIXCertChain,
+								   const TUid aClient)
+	: CActive(EPriorityNormal), iCertStore(&aCertStore),
+	  iPKIXCertChain(aPKIXCertChain), iClient(aClient)
+	{
+	CActiveScheduler::Add(this);
+	}
+
+void CPKIXCertChainAO::ConstructL(const RPointerArray<CX509Certificate>& aRootCerts)
+	{
+	CPKIXCertsFromClient* roots = CPKIXCertsFromClient::NewLC(aRootCerts);
+	iRoots = CPKIXChainBuilder::NewL();
+	iRoots->AddSourceL(roots);
+	CleanupStack::Pop(roots);
+	}
+
+void CPKIXCertChainAO::RunL()
+	{
+	User::LeaveIfError(iStatus.Int());
+
+	switch (iState)
+		{
+		case EAddRoots:
+			HandleEAddRootsL();
+			break;
+
+		case ERootsInitialized:
+			HandleERootsInitializedL();
+			break;
+
+		case EBuildChainStart:
+			HandleEBuildChainStartL();
+			break;
+
+		case EBuildChainAddCandidateEnd:
+			HandleEBuildChainAddCandidateEndL();
+			break;
+
+		case EBuildChainCertsFromStoreBegin:
+			HandleEBuildChainCertsFromStoreBeginL();
+			break;
+
+		case EBuildChainCertsFromStoreEnd:
+			HandleEBuildChainCertsFromStoreEndL();
+			break;
+
+		case EAddCandidateIntermediateCertsEnd:
+			HandleEAddCandidateIntermediateCertsEndL();
+			break;
+
+		case EValidateEnd:
+			HandleEValidateEndL();
+			break;
+
+		default:
+			User::Panic(_L("CPKIXCertChainAO"), 1);
+			break;
+		}
+	}
+
+TInt CPKIXCertChainAO::RunError(TInt aError)
+{
+	iPKIXCertChain.RemoveLastCerts(iNumberOfAddedCertificates);
+	iNumberOfAddedCertificates = 0;
+
+	delete iRoots;
+	iRoots = 0;
+		
+	delete iBuilder;
+	iBuilder = 0;
+	delete iCertsFromStoreRoots;
+	iCertsFromStoreRoots = 0;
+
+	iValidationResult->RemovePolicies();
+
+	User::RequestComplete(iOriginalRequestStatus, aError);
+	return KErrNone;
+}
+
+/**
+ * Creates a list of all the certificates retrieved from the store based on the filter passed.  
+ */
+
+void CPKIXCertChainAO::HandleEAddRootsL()
+	{
+	__ASSERT_DEBUG(!iCertsFromStoreRoots, User::Panic(_L("CPKICCertChainAO"), 1));
+	iCertsFromStoreRoots = CPKIXCertsFromStore::NewL(*iCertStore, iClient);
+	iCertsFromStoreRoots->Initialize(iStatus);
+	iState = ERootsInitialized;	
+	SetActive();
+	}
+
+/**
+ * Adds the list of certificates retrieved from the store, iRoots (CPKIXChainBuilder)
+ * maintains a templatized list of all the certificates in MPKIXCertSource format.
+ */
+
+void CPKIXCertChainAO::HandleERootsInitializedL()
+	{
+	iRoots->AddSourceL(iCertsFromStoreRoots);
+	// Ownership has been passed to iRoots
+	iCertsFromStoreRoots = 0;
+	iState = EBuildChainStart;
+	TRequestStatus* status = &iStatus;
+	User::RequestComplete(status, KErrNone);
+	SetActive();
+	}
+
+void CPKIXCertChainAO::HandleEBuildChainStartL()
+	{
+	if ( false == iPKIXCertChain.ChainHasRoot())
+		{
+		if (iPKIXCertChain.Chain().Count() == 0)
+			{
+			iState = EValidateEnd;
+			TRequestStatus* status = &iStatus;
+			User::RequestComplete(status, KErrNone);
+			}
+		else
+			{
+			//1) look for an issuer that's a root
+			iRoots->AddIssuer(iNumberOfAddedCertificates, iAddIssuerResult, iPKIXCertChain.Chain(), iStatus);
+			iState = EBuildChainAddCandidateEnd;
+			}
+		}
+	else
+		{
+		// This is the correct state as at this point the chain of certificate has been build upto a
+		// root certificate.
+		iState = EValidateEnd;
+		TRequestStatus* status = &iStatus;
+		User::RequestComplete(status, KErrNone);
+		}
+	SetActive();
+	}
+
+void CPKIXCertChainAO::HandleEBuildChainAddCandidateEndL()
+	{
+	if (iAddIssuerResult)
+		{
+		iPKIXCertChain.SetChainHasRoot(ETrue);
+		iState = EValidateEnd;
+		}
+	else
+		{
+		//2) look for a non-root issuer in intermediate certs
+		iBuilder = CPKIXChainBuilder::NewL();
+		
+		CPKIXCertsFromClient* serverCerts = CPKIXCertsFromClient::NewLC(iPKIXCertChain.IntermediateCerts());
+		iBuilder->AddSourceL(serverCerts);
+		CleanupStack::Pop(serverCerts);
+
+		iState = EBuildChainCertsFromStoreBegin;
+		}
+
+	TRequestStatus* status = &iStatus;
+	User::RequestComplete(status, KErrNone);
+	SetActive();
+	}
+
+void CPKIXCertChainAO::HandleEBuildChainCertsFromStoreBeginL()
+	{
+	//3) look for a non-root issuer in the store
+	iCertsFromStoreRoots = CPKIXCertsFromStore::NewL(*iCertStore);
+	iCertsFromStoreRoots->Initialize(iStatus);
+	iState = EBuildChainCertsFromStoreEnd;
+	SetActive();
+	}
+
+void CPKIXCertChainAO::HandleEBuildChainCertsFromStoreEndL()
+	{
+	iBuilder->AddSourceL(iCertsFromStoreRoots);
+	iCertsFromStoreRoots = 0;
+
+	iBuilder->AddIssuer(iNumberOfAddedCertificates, iAddIssuerResult, iPKIXCertChain.Chain(), iStatus);
+	iState = EAddCandidateIntermediateCertsEnd;
+	SetActive();
+	}
+
+void CPKIXCertChainAO::HandleEAddCandidateIntermediateCertsEndL()
+	{
+	if (iAddIssuerResult)
+		{
+		// cert is a pointer to something we don't own
+		CX509Certificate* cert = iPKIXCertChain.Chain().At(iPKIXCertChain.Chain().Count() - 1);
+		
+		/* If the issuer is not a self signed certificate then it cannot be trusted anchor for the chain 
+		 * validation process, this means that we restart the certification validation process.
+		 */ 
+		
+		if (!(cert->IsSelfSignedL()))
+			{
+			iState = EBuildChainStart;	
+			}
+		else
+			{
+			iState = EValidateEnd;			
+			}
+		}
+	else
+		{
+		iState = EValidateEnd;	
+		}
+
+	delete iBuilder;
+	iBuilder = 0;
+
+	TRequestStatus* status = &iStatus;
+	User::RequestComplete(status, KErrNone);
+	SetActive();
+	}
+
+void CPKIXCertChainAO::HandleEValidateEndL()
+	{
+	InitParamsL();
+	
+	__ASSERT_DEBUG(iValidationResult, User::Panic(_L("CPKICCertChainAO"), 1));
+	DoValidateL(*iValidationResult, iValidationTime, iInitialPolicies);
+
+	User::RequestComplete(iOriginalRequestStatus, KErrNone);
+	}
+
+void CPKIXCertChainAO::DoCancel()
+	{
+	delete iRoots;
+	iRoots = 0;
+
+	delete iBuilder;
+	iBuilder = 0;
+
+	delete iCertsFromStoreRoots;
+	iCertsFromStoreRoots = 0;
+
+	User::RequestComplete(iOriginalRequestStatus, KErrCancel);
+	}
+
+void CPKIXCertChainAO::ValidateL(CPKIXValidationResultBase& aValidationResult,
+								 const TTime& aValidationTime,								 
+								 const CArrayPtr<HBufC>* aInitialPolicies,
+								 TRequestStatus& aStatus)
+	{
+	aValidationResult.Reset();
+	iValidationResult = &aValidationResult;
+	iValidationTime = aValidationTime;
+	iInitialPolicies = aInitialPolicies;
+	iOriginalRequestStatus = &aStatus;
+	iNumberOfAddedCertificates = 0;
+
+	__ASSERT_ALWAYS(!IsActive(), User::Panic(_L("CPKICCertChainAO"), 1));
+
+	if (!iRoots)
+		{
+		// If iRoots is 0, it means that the caller gave a uid and that
+		// we must retrieve the trusted certificates from the different
+		// stores
+		iRoots = CPKIXChainBuilder::NewL();
+		iState = EAddRoots;
+		}
+	else
+		{
+		// The caller gave a set of certificates it trusts,
+		// so we don't have to retrieve anything from the stores
+		iState = EBuildChainStart;
+		}
+
+	aStatus = KRequestPending;
+	TRequestStatus *status = &iStatus;
+	User::RequestComplete(status, KErrNone);
+	SetActive();
+	}
+
+void CPKIXCertChainAO::CancelValidate()
+	{
+	Cancel();
+	}
+
+void CPKIXCertChainAO::InitParamsL()
+/*
+this function initialises signing key parameters for the certificates
+-only DSA needs these at present
+-we get the signing key, from the spki of the issuer
+-if it's dsa, we look for params here
+	-if we find them we initialise the cert with them
+	-otherwise, we look in the issuer's issuer
+		-if we don't find them there we give up.
+*/
+	{
+	
+	// If the root is DSA signed, set its parameters
+
+	TInt count = iPKIXCertChain.Chain().Count();
+	
+	CX509Certificate* current = iPKIXCertChain.Chain().At(count-1);
+	TAlgorithmId signingAlgorithm = current->SigningAlgorithm().AsymmetricAlgorithm().Algorithm();
+	
+	if (signingAlgorithm == EDSA)
+		{
+		
+		const CSubjectPublicKeyInfo& key = current->PublicKey();
+		SetParamsL(*current, key.EncodedParams());
+		
+		}
+	
+	// Also the rest of the chain
+	
+	for (TInt i = count - 2; i >= 0; i--)
+		{
+		
+		current = iPKIXCertChain.Chain().At(i);
+		TAlgorithmId signingAlgorithm = current->SigningAlgorithm().AsymmetricAlgorithm().Algorithm();
+		
+		if (signingAlgorithm == EDSA)
+			{
+			
+			// Look down the chain for parameters
+			
+			for (TInt j = i+1; j < count; j++)
+				{
+				
+				CX509Certificate* issuer = iPKIXCertChain.Chain().At(j);
+				const CSubjectPublicKeyInfo& key = issuer->PublicKey();
+				if (key.EncodedParams() != KNullDesC8 && key.AlgorithmId() == EDSA)
+					{
+					SetParamsL(*current, key.EncodedParams());
+					break;
+					}
+				
+				}
+			
+			}
+		
+		}
+	}
+
+void CPKIXCertChainAO::SetParamsL(CX509Certificate& aCert, const TPtrC8& aEncodedParams)
+	{
+	TX509KeyFactory factory;
+	CDSAParameters* theDSAParams = factory.DSAParametersL(aEncodedParams);
+	CleanupStack::PushL(theDSAParams);
+	
+	CSigningKeyParameters* params = CSigningKeyParameters::NewLC();
+	params->SetDSAParamsL(*theDSAParams);
+	
+	aCert.SetParametersL(*params);
+
+	CleanupStack::PopAndDestroy(2, theDSAParams);
+	}
+
+void CPKIXCertChainAO::DoValidateL(CPKIXValidationResultBase& aValidationResult,
+								 const TTime& aValidationTime, 
+								 const CArrayPtr<HBufC>* aInitialPolicies)
+	{
+	if (!iPKIXCertChain.ChainHasRoot())
+		{
+		aValidationResult.SetError(EChainHasNoRoot, 0);
+		}
+	else
+		{
+		CPKIXValidationState* state = CPKIXValidationState::NewLC(aValidationTime, iPKIXCertChain.Chain().Count(), aInitialPolicies);
+		TRAPD(err, ProcessCertsL(*state, aValidationResult));
+		//a leave here means either:
+		//	-a validation error, in which case we've set the error field in result, or
+		//	-some other error (e.g. OOM) in which case error is still EChainHasNoRoot
+		if ((err != KErrNone) && ((aValidationResult.Error().iReason) == EChainHasNoRoot))
+			//then we left with a non-validation-related error, so leave again...
+			{
+			User::Leave(err);
+			}
+		CleanupStack::PopAndDestroy(state);
+		}
+	}
+
+// ProcessCertsL: This function validates a complete certificate 
+//                chain. If an error occurs in this function the function
+//                SetErrorAndLeaveL must be called. 
+// 
+// Note Do not use SetErrorAndLeaveL with EChainHasNoRoot (see TRAP code in 
+// CPKIXCertChainAO::DoValidateL )             
+void CPKIXCertChainAO::ProcessCertsL(CPKIXValidationState& aState,
+									 CPKIXValidationResultBase& aResult) const
+	{
+	TPKIXPolicyConstraint policy(aState, aResult);
+	TPKIXNameConstraint name(aState, aResult);
+	TPKIXBasicConstraint basic(aState, aResult);
+	TPKIXKeyUsageConstraint keyUsage(aState, aResult);
+	for (; aState.iPos >= 0; aState.iPos--)
+		{
+		aState.iMaxPathLength--;
+		if (aState.iMaxPathLength < aState.iPos)
+			{
+			aResult.SetErrorAndLeaveL(EPathTooLong, aState.iPos);
+			}
+		const CX509Certificate* current = iPKIXCertChain.Chain().At(aState.iPos);
+		CCertificateValidationWarnings* certWarnings = CCertificateValidationWarnings::NewLC(aState.iPos);
+		aResult.AppendCertificateValidationObjectL(*certWarnings);
+		CleanupStack::Pop(certWarnings);
+		CriticalExtsL(aState, *current);
+		CheckCriticalExtsL(aState, aResult);
+		CheckSignatureAndNameL(*current, aState, aResult);
+		//!!!!NO!!checks for revocation at this time!!
+		
+		if (!(current->ValidityPeriod().Valid(aState.iValidationTime)))
+			{
+			//validity period invalid, now check how to report this
+			if (iPKIXCertChain.ValidityPeriodCheckFatal())
+				{
+				aResult.SetErrorAndLeaveL(EDateOutOfRange, aState.iPos);
+				}
+			else
+				{
+				aResult.AppendWarningL(TValidationStatus(EDateOutOfRange, aState.iPos));
+				}
+			}
+		
+		policy.CheckCertPoliciesL(*current);
+		name.CheckNameConstraintsL(*current);
+		keyUsage.CheckKeyUsageL(*current);
+		if (aState.iPos < (iPKIXCertChain.Chain().Count() - 1))
+			{
+			basic.CheckCertSubjectTypeL(*current);
+			}
+		basic.UpdatePathLengthConstraintsL(*current);
+		name.UpdateNameConstraintsL(*current);
+		policy.UpdatePolicyConstraintsL(*current);
+		aState.iCriticalExts->Reset();
+		}
+	policy.FinishPolicyCheckL();
+	//*copy* all policies from aState.iAuthorityConstrainedPolicies into aResult.iPolicies
+	TInt policyCount = aState.iAuthorityConstrainedPolicies->Count();
+	for (TInt i = 0; i < policyCount; i ++)
+		{
+		CX509CertPolicyInfo* policyInfo = CX509CertPolicyInfo::NewLC(*(aState.iAuthorityConstrainedPolicies->At(i)));
+		aResult.AppendPolicyL(*policyInfo);
+		CleanupStack::Pop(policyInfo);
+		}
+
+	aResult.SetError(EValidatedOK, 0);
+	}
+
+void CPKIXCertChainAO::CriticalExtsL(CPKIXValidationState& aState, 
+									 const CX509Certificate& aCert) const
+	{
+	const CArrayPtrFlat<CX509CertExtension>& exts = aCert.Extensions();
+	TInt count = exts.Count();
+	for (TInt i = 0; i < count; i++)
+		{
+		CX509CertExtension* ext = exts.At(i);
+		if (ext->Critical())
+			{
+			aState.iCriticalExts->AppendL(ext);
+			}
+		}	 
+	}
+
+void CPKIXCertChainAO::CheckSignatureAndNameL(const CX509Certificate& aCert, CPKIXValidationState& aState, 
+											CPKIXValidationResultBase& aResult) const
+	{
+	TInt issuerPos = aState.iPos + 1;
+	if (issuerPos == iPKIXCertChain.Chain().Count())
+		//then it's the root
+		{
+		if (aCert.IssuerName().ExactMatchL(aCert.SubjectName()))
+			//then it claims to be self signed, sig must verify
+			{
+			if (!(aCert.VerifySignatureL(aCert.PublicKey().KeyData())))
+				{
+				aResult.SetErrorAndLeaveL(ESignatureInvalid, aState.iPos);
+				}
+			}
+		else
+			//we generate a warning
+			{
+			aResult.AppendWarningL(TValidationStatus(ERootCertNotSelfSigned, aState.iPos));
+			}
+		}
+	else
+		//then it isn't the root: so names must chain & sigs must verify
+		{
+		const CX509Certificate* issuer = iPKIXCertChain.Chain().At(issuerPos);
+		if (!(aCert.IssuerName().ExactMatchL(issuer->SubjectName())))
+			{
+			aResult.SetErrorAndLeaveL(ENamesDontChain, aState.iPos);
+			}
+		if (!(aCert.VerifySignatureL(issuer->PublicKey().KeyData())))
+			{
+			aResult.SetErrorAndLeaveL(ESignatureInvalid, aState.iPos);
+			}
+		}
+	}
+
+void CPKIXCertChainAO::CheckCriticalExtsL(CPKIXValidationState& aState, CPKIXValidationResultBase& aResult) const
+	{
+	TBool foundUnrecognisedCritExt;
+	
+	// retrieve the supported list of critical extensions. If a critical extension is found whose OID matches an 
+	// element in this set then certificate validation shall treat this as a warning instead of an error.
+	const RPointerArray<TDesC>& supportedCritExt = iPKIXCertChain.SupportedCriticalExtensions();
+	
+	TInt count = aState.iCriticalExts->Count();
+	TInt supportedCount = supportedCritExt.Count();
+	for (TInt i = 0; i < count; i++)
+		{
+		foundUnrecognisedCritExt = ETrue;
+		const CX509CertExtension* ext = aState.iCriticalExts->At(i);
+		const TPtrC& extName = ext->Id();
+		
+		for (TInt j = 0; j < supportedCount; ++j)
+			{
+			if (extName == *supportedCritExt[j])
+				{
+				foundUnrecognisedCritExt = EFalse;
+				HBufC* oid = extName.AllocLC();
+				aResult.AppendCriticalExtensionWarningL(*oid);
+				CleanupStack::Pop(oid);
+				break;
+				}
+			}			
+		
+		if (extName == KExtendedKeyUsage)
+			{
+			aResult.AppendWarningL(TValidationStatus(ECriticalExtendedKeyUsage, aState.iPos));
+			}
+		else if (extName == KPolicyMapping)
+			{
+			aResult.AppendWarningL(TValidationStatus(ECriticalPolicyMapping, aState.iPos));
+			}
+		else if (extName == KInhibitAnyPolicy)
+			{
+			//ignore this in the same way
+			}
+		else if (extName == KDeviceIdListConstraint)
+			{
+			aResult.AppendWarningL(TValidationStatus(ECriticalDeviceId, aState.iPos));
+			}
+		else if(extName == KSidListConstraint)
+			{
+			aResult.AppendWarningL(TValidationStatus(ECriticalSid, aState.iPos));
+			}
+		else if(extName == KVidListConstraint)
+			{
+			aResult.AppendWarningL(TValidationStatus(ECriticalVid, aState.iPos));
+			}
+		else if(extName == KCapabilitiesConstraint)
+			{
+			aResult.AppendWarningL(TValidationStatus(ECriticalCapabilities, aState.iPos));
+			}
+		
+		if (foundUnrecognisedCritExt)
+			{
+			aResult.SetErrorAndLeaveL(EUnrecognizedCriticalExtension, aState.iPos);
+			}			
+		
+		}
+	}