installationservices/swi/source/securitymanager/securitymanager.cpp
changeset 0 ba25891c3a9e
child 17 741e5bba2bd1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/installationservices/swi/source/securitymanager/securitymanager.cpp	Thu Dec 17 08:51:10 2009 +0200
@@ -0,0 +1,1212 @@
+/*
+* Copyright (c) 1997-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: 
+*
+*/
+
+
+/**
+ @file 
+ @released
+ @internalTechnology
+*/
+ 
+#include <f32file.h>
+
+#include "securitymanager.h"
+#include "swi/sishash.h"
+#include "swi/sisdataprovider.h"
+#include "swi/sissignaturealgorithm.h"
+#include "swi/sissignaturecertificatechain.h"
+#include "swi/siscertificatechain.h"
+#include "swi/sisinfo.h"
+#include "swi/sissupportedoptions.h"
+#include "swi/sissupportedlanguages.h"
+#include "swi/sisprerequisites.h"
+#include "swi/sislogo.h"
+#include "swi/sisproperties.h"
+#include "swi/sisinstallblock.h"
+#include "swi/sistruststatus.h"
+#include "hashcontainer.h"
+#include "certchainconstraints.h"
+#include "devinfosupportclient.h"
+
+#include "log.h"
+
+// PKIX dependencies
+#include <pkixcertchain.h>
+#include <x509keys.h> 
+#include <ocsp.h>
+#include <securitydefsconst.h>
+
+#include <ccertattributefilter.h>
+#include <ct/mcttoken.h>
+//#include <mctcertstore.h>
+#include "cfstokentypeclient.h"
+
+// Crypto dependencies
+#include <hash.h>
+#include <swicertstore.h>
+
+// SecMan includes
+#include "chainvalidator.h"
+#include "certificateretriever.h"
+#include "signatureverifier.h"
+#include "securitypolicy.h"
+#include "revocationhandler.h"
+
+const TInt KFileBufferSize = 1024;  // 1k buffer used to read the data to be hashed
+_LIT(KSecurityManagerName, "_Security_Manager_");
+
+
+using namespace Swi;
+
+//
+// Life Cycle methods
+//
+
+EXPORT_C CSecurityManager* CSecurityManager::NewL()
+	{
+	CSecurityManager* self = CSecurityManager::NewLC();
+	CleanupStack::Pop(self);
+	return self;
+	}
+ 
+EXPORT_C CSecurityManager* CSecurityManager::NewLC()
+	{
+	CSecurityManager* self = new(ELeave) CSecurityManager();
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	return self;
+	}
+
+EXPORT_C CSecurityPolicy& CSecurityManager::SecurityPolicy() const
+	{
+	return *iSecPolicy;
+	}
+
+CSecurityManager::CSecurityManager() : CActive(EPriorityNormal) 
+	{
+	CActiveScheduler::Add(this);	
+	}
+
+CSecurityManager::~CSecurityManager()
+	{	
+	Deque();
+
+	if (iCurrentPkixChain)
+		{
+		delete iCurrentPkixChain;
+		}
+
+	if (iCertStore)
+		{
+		iCertStore->Release();
+		}
+	
+	if (iCertificateRetriever)
+		{
+		delete iCertificateRetriever;
+		}
+		
+	if (iChainValidator)
+		{
+		delete iChainValidator;
+		}
+		
+	if (iRevocationHandler)
+		{
+		delete iRevocationHandler;
+		}
+		
+	iValidPkixChains.ResetAndDestroy();
+	iUntrustedRoots.ResetAndDestroy();
+	iDeviceIDs.ResetAndDestroy();
+	TInt count = iTrustedRoots.Count();
+	// Release certificates from the list
+	for (TInt i = 0; i < count; ++i)
+		{
+		iTrustedRoots[0]->Release(); 
+		iTrustedRoots.Remove(0);
+		}
+	iTrustedRoots.Close();	
+	iCertMetaInfo.Reset();
+	iFs.Close();
+	}
+
+
+void CSecurityManager::ConstructL()
+	{	
+	User::LeaveIfError(iFs.Connect());
+	iSecPolicy = CSecurityPolicy::GetSecurityPolicyL();	
+	iCertStore=CSWICertStore::NewL(iFs);
+	}
+	
+	
+//
+// Active Objects methods
+//
+
+void CSecurityManager::RunL()
+	{
+	DEBUG_PRINTF3(_L8("Security Manager - RunL(). State: %d, Status: %d."),
+		iState, iStatus.Int());
+	
+	if (iStatus.Int() != KErrNone)
+		{
+		User::Leave(iStatus.Int());     // Hop into RunError()
+		}
+		
+	switch (iState)
+		{ 			
+		case ERetrievedTrustedRoots:
+			{
+			iCertMetaInfo.Reset();
+			TInt trustedCertCount = iTrustedRoots.Count();
+			for (TInt i = 0; i < trustedCertCount; ++i)
+				{
+				CCTCertInfo& certInfo=*iTrustedRoots[i];
+				DEBUG_CODE_SECTION(			
+					DEBUG_PRINTF2(_L("Security Manager - SWI certstore contains trust anchor certificate '%S'"),
+						&(certInfo.Label()));
+						);
+				TCertMetaInfo metaInfo = iCertStore->CertMetaInfoL(certInfo);
+				iCertMetaInfo.AppendL(metaInfo);
+				if (metaInfo.iIsMandatory)		
+					{
+					iMandatoryCertDNCount++;
+					DEBUG_CODE_SECTION(			
+					DEBUG_PRINTF2(_L("Security Manager - SWI certstore contains mandatory certificate '%S'"),
+						&(certInfo.Label()));
+						);
+					}
+				if (metaInfo.iIsSystemUpgrade)		
+					{
+					DEBUG_CODE_SECTION(			
+					DEBUG_PRINTF2(_L("Security Manager - SWI certstore contains system upgrade certificate '%S'"),
+						&(certInfo.Label()));
+						);
+					}
+				}
+			// After we get here, we have retrieved mandatory certificates
+			// We may have an unsigned sis file in which case we do not want to verify the block
+			// since there isn't one, so bail here with the correct error
+			if (iChains.Count() == 0)
+					{
+					if (iMandatoryCertDNCount == 0)
+						{
+						*iResult = ESignatureNotPresent; // No mandatory certs, so just say unsigned
+						}
+					else
+						{
+						*iResult = EMandatorySignatureMissing; // more important error code overrides
+						}
+					
+					User::RequestComplete(iClientStatus, KErrNone);							
+					break;
+					}
+	
+		
+			VerifyBlockL(iCurrentChain);			
+			}
+			break;
+			
+		case EValidatingChain :
+			{
+			CPKIXValidationResultBase* result = (*iValidationResultsOut)[iCurrentChain];
+			::TValidationStatus resultStatus = result->Error(); 	
+
+			DEBUG_PRINTF3(_L8("Security Manager - Certificate validation result was %d. (If applicable, error on certificate %d.)"),
+				resultStatus.iReason, resultStatus.iCert);
+
+			iCurrentChain++; // Next chain to validate
+
+			if (resultStatus.iReason != EValidatedOK)
+				{
+				// we can discard the invalid cert chain
+				delete iCurrentPkixChain;
+				iCurrentPkixChain = NULL;
+				
+				// ooops
+				if (iChains.Count() > iCurrentChain)   // This is the ValidateANY policy
+					{
+					VerifyBlockL(iCurrentChain);
+					break;						
+					}
+				}
+			else
+				{
+				iHasValidated = ETrue; // At least one chain has been validated! Hurrah!
+				
+				// check if a chain has validated that is not self signed
+				if (*iResult != ESignatureSelfSigned)
+					{
+					iHasValidatedTrusted = ETrue;
+					}
+				
+			    // From here on the chain has been validated successfully
+						
+			    iTotalCapabilitiesOut->Union(iCurrentCapabilities); // Update the total capabilities
+			
+			    // Reduce the count from the list of mandatory certs
+			    UpdateListOfMissingRequiredCertsL(iCurrentPkixChain->Cert(iCurrentPkixChain->Count()-1));
+				
+				// Updage the System Upgrade status of the Certificate
+				UpdateSystemUpgradeCertStatusL(iCurrentPkixChain->Cert(iCurrentPkixChain->Count()-1));
+				
+			    User::LeaveIfError(iValidPkixChains.Append(iCurrentPkixChain));
+			    // this chain will be used for OCSP checking if required, so record it.
+			    iController->AddChainIndex(iCurrentChain-1);
+			    
+			    iCurrentPkixChain = NULL;
+				}
+
+			if (iCurrentChain == iChains.Count())
+				{
+				if (iMandatoryCertDNCount == 0)
+					{
+					// Mandatory certs prerequisites met				
+
+					if (iHasValidated)
+						{
+						//Build the certificate chain constraints
+						CCertChainConstraints* certChainConstraints(0);
+						TRAPD(err, certChainConstraints=CCertChainConstraints::NewL(iValidPkixChains));
+						if (err)
+							{
+							*iResult = ECertificateValidationError;
+							User::RequestComplete(iClientStatus, KErrNone);
+							return;
+							}
+
+						*iResult = iHasValidatedTrusted ? EValidationSucceeded : ESignatureSelfSigned;
+						
+						//Pass the certificate chain constraints ownership to controller
+						Sis::CController* controller=const_cast<Sis::CController*>(iController);
+						controller->SetCertChainConstraints(certChainConstraints);
+
+						//Set the dev cert found flag if dev cert first time found
+						if (iDevCertWarningState==ENoDevCerts && 
+							(certChainConstraints->SIDsAreConstrained() 
+							||certChainConstraints->VIDsAreConstrained()
+							||certChainConstraints->DeviceIDsAreConstrained()
+							||certChainConstraints->CapabilitiesAreConstrained()))
+							{
+							DEBUG_PRINTF(_L("Security Manager - At least one certificate chain contains a devcert."));
+							iDevCertWarningState=EFoundDevCerts;
+							}
+
+						//Check if the device id is contrained and the device Id has been retrieved
+						if (certChainConstraints->DeviceIDsAreConstrained() && iDeviceIDs.Count()==0)
+							{
+				 			//Retrieve and Save the device ID list then complete
+				 			RDeviceInfo deviceInfo;
+				 			User::LeaveIfError(deviceInfo.Connect());
+				 			CleanupClosePushL(deviceInfo);
+ 							const RPointerArray<HBufC>& tempbuf=deviceInfo.DeviceIdsL();
+				 			for (TInt i=0;i<tempbuf.Count();i++)
+					 			{
+					 			HBufC* element=tempbuf[i]->AllocLC();
+				  				iDeviceIDs.AppendL(element);
+				  				CleanupStack::Pop(element);	 				
+					 			}
+					 		CleanupStack::PopAndDestroy(&deviceInfo);					
+							}						
+						iState = EChecksDone;
+						TRequestStatus* status = &iStatus;
+						User::RequestComplete(status, KErrNone);
+						SetActive();
+						return;
+						}
+					}
+
+				if (iMandatoryCertDNCount != 0)
+					{
+					*iResult = EMandatorySignatureMissing;  // We did not meet mandatory cert requirements!
+					}
+				else
+					{
+					if (!iHasValidated) 
+						{
+						*iResult = ECertificateValidationError; // No chain ever validated 
+						}
+					}
+	
+				User::RequestComplete(iClientStatus, KErrNone);							
+				}
+			else
+				{
+				VerifyBlockL(iCurrentChain);
+				return;					
+				}
+			}
+			break;
+
+		case ERevalidatingChain:
+			{
+			TInt chainIndex = (*iChainListIndices)[iCurrentChain];
+			
+			CPKIXValidationResultBase* result = (*iValidationResultsOut)[iCurrentChain];
+			::TValidationStatus resultStatus = result->Error(); 	
+
+			DEBUG_PRINTF3(_L8("Security Manager - Certificate validation result was %d. (If applicable, error on certificate %d.)"),
+				resultStatus.iReason, resultStatus.iCert);
+				
+			iCurrentChain++; // Next chain to validate
+
+			if (resultStatus.iReason != EValidatedOK)
+				{
+				// We can discard the invalid chain.
+				delete iCurrentPkixChain;
+				iCurrentPkixChain = NULL;
+				
+				// ooops
+				if (iChains.Count() > chainIndex)  	
+					{ // This is the ValidateANY policy
+					VerifyBlockL(chainIndex);
+					break;						
+					}
+				}
+			else
+				{
+				iHasValidated = ETrue; // At least one chain has been validated! Hurrah!
+				
+				// check if a chain has validated that is not self signed
+				if (*iResult != ESignatureSelfSigned)
+					{
+					iHasValidatedTrusted = ETrue;
+					}
+				
+				// From here on the chain has been validated successfully
+						
+				iTotalCapabilitiesOut->Union(iCurrentCapabilities); // Update the total capabilities
+			
+				// Reduce the count from the list of mandatory certs
+				UpdateListOfMissingRequiredCertsL(iCurrentPkixChain->Cert(iCurrentPkixChain->Count()-1));
+			
+				// Updage the System Upgrade status of the Certificate
+				UpdateSystemUpgradeCertStatusL(iCurrentPkixChain->Cert(iCurrentPkixChain->Count()-1));
+				
+				iValidPkixChains.AppendL(iCurrentPkixChain);
+					
+				iCurrentPkixChain = NULL;
+				}
+
+			if (chainIndex == iChains.Count())
+				{
+				if (iHasValidated)
+					{
+					//Build the certificate chain constraints
+					CCertChainConstraints* certChainConstraints(0);
+					TRAPD(err, certChainConstraints=CCertChainConstraints::NewL(iValidPkixChains));
+					if (err)
+						{
+						*iResult = ECertificateValidationError;
+						User::RequestComplete(iClientStatus, KErrNone);
+						return;
+						}
+					else
+						{
+						*iResult = iHasValidatedTrusted ? EValidationSucceeded : ESignatureSelfSigned;								
+						}
+
+					//Pass the certificate chain constraints ownership to controller
+					Sis::CController* controller=const_cast<Sis::CController*>(iController);
+					controller->SetCertChainConstraints(certChainConstraints);
+					
+					//Check if the device id is contrained and the device Id has been retrieved
+					if (certChainConstraints->DeviceIDsAreConstrained() && iDeviceIDs.Count()==0)
+						{
+				 		//Retrieve and Save the device ID list then complete
+				 		RDeviceInfo deviceInfo;
+				 		User::LeaveIfError(deviceInfo.Connect());
+				 		CleanupClosePushL(deviceInfo);
+ 						const RPointerArray<HBufC>& tempbuf=deviceInfo.DeviceIdsL();
+				 		for (TInt i=0;i<tempbuf.Count();i++)
+					 		{
+							HBufC* element=tempbuf[i]->AllocLC();
+			  				iDeviceIDs.AppendL(element);
+			  				CleanupStack::Pop(element);	 				
+					 		}
+					 	CleanupStack::PopAndDestroy(&deviceInfo);					
+						}						
+					iState = EChecksDone;
+					TRequestStatus* status = &iStatus;
+					User::RequestComplete(status, KErrNone);
+					SetActive();
+					return;
+					}
+
+				else
+					{
+					*iResult = ECertificateValidationError; // No chain ever validated 
+					}
+
+				User::RequestComplete(iClientStatus, KErrNone);							
+				}
+			else
+				{
+				VerifyBlockL(chainIndex);
+				return;					
+				}
+			}
+			break;
+
+		case EOCSPCheck:
+			{
+			iState = EChecksDone;
+			ProcessOcspOutcomesL();
+			
+			TRequestStatus* status = &iStatus;
+			User::RequestComplete(status, KErrNone);
+			SetActive();			
+			}
+			break;
+			
+		case EChecksDone:
+			{
+			// If the validation is done by certs passed by third party(API user)
+			// instead of cert-store then even on successful validation
+			// the result of validation is ESignatureSelfSigned. 
+			// But if iUntrustedRoots count is not zero then the result is
+			// really ESignatureSelfSigned.
+			if (NULL != iRootCerts && iHasValidated)
+				{
+				*iResult = EValidationSucceeded;
+				}
+			// Complete the client and be happy
+			User::RequestComplete(iClientStatus, KErrNone);			
+			}
+			break;
+			
+		default:
+			{
+			User::Panic(KSecurityManagerName, 1); 		
+			}
+		}
+	}
+
+
+void CSecurityManager::ProcessOcspOutcomesL() 
+	{
+	
+	 // Identify the worst outcome overall, and the worst in each chain.
+ 	// The OCSP outcomes are in the same order as the valid chains and
+ 	// certificates within them, with the number of outcomes per chain
+ 	// one fewer than the number of certs in the chain.
+ 
+
+	TInt numOutcomes=iRevocationHandler->TransactionCount();
+	TInt currentChain = 0;
+ 	TInt chainErrorLevel = 0;
+ 
+ 	// Since the number of outcomes is 1 fewer than the number of certs in the
+ 	// PkixChain, the index for the last outcome of the first chain will be
+ 	// 2 lower than the number of certs in the chain.
+ 	TInt chainLastOutcomeIndex = iValidPkixChains[0]->Count() - 2;
+ 	TInt chainWorstOutcome = 0;
+ 	
+	// This variable is used to record the most serious error condition.
+	TInt errorLevel = 0;
+
+	DEBUG_PRINTF2(_L8("Security Manager - OCSP check complete. %d OCSP outcomes."), numOutcomes);
+
+	for (TInt i=0; i<numOutcomes; i++)
+		{
+		const TOCSPOutcome& outcome=iRevocationHandler->Outcome(i);
+		
+		DEBUG_PRINTF4(_L8("Security Manager - OCSP outcome %d; Status: %d, Result: %d."),
+			i, outcome.iStatus, outcome.iResult);
+		
+		if (outcome.iResult == OCSP::ERevoked)
+			{
+			// If any certificate is revoked then installation must be aborted
+ 			// but we still want to identify the worst case for each chain for
+ 			// the purposes of the error dialog.
+
+			*iRevocationMessage = ECertificateStatusIsRevoked;
+			errorLevel = 6;
+ 			chainWorstOutcome = i;
+ 			
+ 			// Skip the rest of the outcomes for this chain.
+ 			i = chainLastOutcomeIndex;
+			}
+		else if (outcome.iResult != OCSP::EGood)
+			{			
+			switch (outcome.iStatus)			
+				{
+				// permanent errors, no user interaction is required
+				case OCSP::ENoServerSpecified:
+				case OCSP::EClientInternalError:
+				case OCSP::EMalformedRequest:
+				case OCSP::EUnknownResponseType:
+				case OCSP::EClientUnauthorised:
+				case OCSP::EUnknownCriticalExtension:
+				case OCSP::EMissingCertificates:
+				case OCSP::ESignatureRequired:				
+				case OCSP::EThisUpdateTooLate:
+				case OCSP::EThisUpdateTooEarly:
+				case OCSP::ENextUpdateTooEarly:
+				case OCSP::ECertificateNotValidAtValidationTime:				
+				case OCSP::ENonceMismatch:
+					if (errorLevel < 5)
+						{
+						errorLevel = 5;
+						*iRevocationMessage = EInvalidCertificateStatusInformation;
+						}
+					if (chainErrorLevel < 5)
+ 						{
+ 						chainErrorLevel = 5;
+ 						chainWorstOutcome = i;
+ 						}
+					break;
+				case OCSP::EResponseSignatureValidationFailure:
+					if (errorLevel < 4)
+						{
+						errorLevel = 4;
+						*iRevocationMessage = EResponseSignatureValidationFailure;			
+						}	
+					if (chainErrorLevel < 4)
+ 						{
+ 						chainErrorLevel = 4;
+ 						chainWorstOutcome = i;
+						}
+					break;
+				// permanent errors, ask the user	
+				case OCSP::EValid:
+					if (errorLevel < 3)
+						{
+						errorLevel = 3;
+						*iRevocationMessage = ECertificateStatusIsUnknown;
+						}	
+					if (chainErrorLevel < 3)
+ 						{
+ 						chainErrorLevel = 3;
+ 						chainWorstOutcome = i;
+ 						}
+					break;					
+				// transient errors - user can retry
+				case OCSP::EInvalidURI:					
+					if (errorLevel < 2)
+						{
+						errorLevel = 2;
+						*iRevocationMessage = EInvalidRevocationServerUrl;
+						}
+					if (chainErrorLevel < 2)
+ 						{
+ 						chainErrorLevel = 2;
+ 						chainWorstOutcome = i;
+						}
+					break;
+				case OCSP::ETryLater:
+				case OCSP::ETransportError:
+				case OCSP::EServerInternalError:
+				case OCSP::EMissingNonce:
+					if (errorLevel < 1)
+						{
+						errorLevel = 1;
+						*iRevocationMessage = EUnableToObtainCertificateStatus;
+						}	
+ 					if (chainErrorLevel < 1)
+ 						{
+ 						chainErrorLevel = 1;
+ 						chainWorstOutcome = i;
+ 						}
+
+					break;	
+				default:
+					// All possible OCSP responses should be checked
+					__ASSERT_ALWAYS(EFalse, User::Leave(KErrArgument));
+					break;
+				}	
+			}
+
+ 		// If this is the end of the chain, store the worst outcome for the
+ 		// chain in the output outcome array.
+ 		if (i == chainLastOutcomeIndex)
+ 			{
+ 			TOCSPOutcome* chainOutcome=new(ELeave) TOCSPOutcome(iRevocationHandler->Outcome(chainWorstOutcome));
+ 			CleanupStack::PushL(chainOutcome);
+ 			iOcspOutcomeOut->AppendL(chainOutcome);
+ 			CleanupStack::Pop(chainOutcome);
+ 
+ 			// If there are more chains to consider, get set to identify the
+ 			// worst outcome in the next chain.
+ 			if (++currentChain < iValidPkixChains.Count())
+ 				{
+ 				chainErrorLevel = 0;
+ 				chainWorstOutcome = i + 1;
+ 				chainLastOutcomeIndex += iValidPkixChains[currentChain]->Count() - 1;
+ 				}
+ 			}
+
+		}
+	}
+
+void CSecurityManager::DoCancel()
+	{
+	DEBUG_PRINTF2(_L8("Security Manager - Cancelling in state %d."), iState);
+	
+	switch (iState)
+		{
+		case ERetrievedTrustedRoots:
+			{
+			iCertificateRetriever->Cancel();
+			}
+			break;
+			
+		case EValidatingChain:
+		case ERevalidatingChain:
+			{
+			iChainValidator->Cancel();		
+			}
+			break;
+			
+		case EOCSPCheck:
+			{
+			iRevocationHandler->Cancel();
+			}
+			break;
+			
+		case EChecksDone:	
+		default: 
+			{
+			// Do nothing
+			}
+		}
+	if(iClientStatus)
+		{
+		User::RequestComplete(iClientStatus,KErrCancel);		
+		}
+	}
+
+TInt CSecurityManager::RunError(TInt aError)
+	{
+	DEBUG_PRINTF2(_L8("Security Manager - RunError(). Error code %d."), aError);
+	
+	User::RequestComplete(iClientStatus, aError);			
+	return KErrNone; 
+	}
+
+
+//
+// Business methods
+//
+
+EXPORT_C void CSecurityManager::PerformOcspL(const TDesC8& aOcspUri, 
+											 TUint32& aIap,
+											 TRevocationDialogMessage* aRevocationMessageOut, 
+											 RPointerArray<TOCSPOutcome>& aOcspOutcomeOut, 
+											 RPointerArray<CX509Certificate>& aCertOut,
+											 TRequestStatus& aStatus)
+	{	
+	Cancel();
+	
+	DEBUG_PRINTF2(_L8("Security Manager - Performing OCSP with revocation server at %S."),
+		&aOcspUri);
+
+	// Reset and re-populate certificate list to contain only end certificates
+ 	// from valid chains, so that the end cert list can be correlated with the
+ 	// list of outcomes.
+ 	aCertOut.ResetAndDestroy();
+ 	TInt numChains = iValidPkixChains.Count();
+ 	for (TInt index = 0; index < numChains; index++)
+ 		{
+ 		CX509Certificate* certOut = CX509Certificate::NewLC(iValidPkixChains[index]->Cert(0));
+ 		aCertOut.AppendL(certOut);
+ 		CleanupStack::Pop(certOut);
+ 		}
+ 		
+ 	DEBUG_PRINTF2(_L8("Security Manager - Validating %d certificate chains for this controller."), numChains);
+
+	iClientStatus = &aStatus;
+	*iClientStatus = KRequestPending;
+
+	iOcspOutcomeOut = &aOcspOutcomeOut;
+	iRevocationMessage = aRevocationMessageOut;
+	
+	// Make sure to delete earlier object
+	if (iRevocationHandler)
+		{
+		delete iRevocationHandler;
+		iRevocationHandler = NULL;
+		}	
+	iRevocationHandler = CRevocationHandler::NewL(*iCertStore);
+	iRevocationHandler->SetDefaultURIL(aOcspUri);
+	iState = EOCSPCheck;
+	
+	iRevocationHandler->SendRequestL(iValidPkixChains, aIap, iStatus);
+	
+	SetActive();
+	}
+
+EXPORT_C void CSecurityManager::VerifyControllerL(
+				TDesC8& aRawController,
+				const Sis::CController& aController, 
+				TSignatureValidationResult* aResultOut, 
+				RPointerArray<CPKIXValidationResultBase>& aPkixResultsOut,
+				RPointerArray<CX509Certificate>& aCertsOut,
+				TCapabilitySet* aCapabilitySetOut,
+				TBool& aAllowUnsigned,
+				TBool& aIsEmbeddedController,
+				TRequestStatus& aStatus,
+				TBool aCheckDateAndTime)
+	{
+	DEBUG_PRINTF(_L8("Security Manager - Validating Controller"));
+	
+	iResult = aResultOut;
+	iChains = aController.SignatureCertificateChains();	
+	iController = &aController;
+	iEndCertificatesOut = &aCertsOut;
+	iValidationResultsOut = &aPkixResultsOut;
+	iTotalCapabilitiesOut = aCapabilitySetOut;
+	iIsEmbeddedController = aIsEmbeddedController;
+	iCheckDateAndTime = aCheckDateAndTime;
+	
+	// Initialy assume that the chain is not validated
+	iHasValidated = EFalse;
+	iHasValidatedTrusted = EFalse;
+	
+	*iResult = ESignatureNotPresent;
+	aAllowUnsigned=iSecPolicy->AllowUnsigned();
+	
+	
+	iClientStatus = &aStatus;  // Store caller's request status
+	*iClientStatus = KRequestPending;
+		
+	if (iChains.Count() == 0)
+		{
+		User::RequestComplete(iClientStatus, KErrNone);	
+		return;	
+		}
+	
+	iRawController.Set(aRawController);
+	iCurrentChain = 0;
+	
+	// First retrieve all CA certificates
+
+	delete iCertificateRetriever;
+	iCertificateRetriever = NULL;
+	iCertificateRetriever = CCertificateRetriever::NewL(*iCertStore);
+	
+	delete iChainValidator;
+	iChainValidator = NULL;
+	iChainValidator = CChainValidator::NewL(*iCertStore, *iSecPolicy);
+	
+	iState = ERetrievedTrustedRoots;
+	SetActive();
+
+	// No need to fetch certificates from the certstore if the root certs
+	// are already provided by the caller. or
+	// The root Certificates already fetched from certstore in case of embedded packages
+
+	if(NULL == iRootCerts && iTrustedRoots.Count() == 0)
+		{
+		iCertificateRetriever->RetrieveCACertificates(
+			iTrustedRoots, iStatus);
+		}
+	else
+		{
+		TRequestStatus* tempStatus = &iStatus;
+		User::RequestComplete(tempStatus, KErrNone);
+		}
+	}
+	
+EXPORT_C void CSecurityManager::ReverifyControllerL(
+				TDesC8& aRawController,
+				const Sis::CController& aController, 
+				const RArray<TInt>& aChainListIndices,
+				TSignatureValidationResult* aResultOut, 
+				RPointerArray<CPKIXValidationResultBase>& aPkixResultsOut,
+				RPointerArray<CX509Certificate>& aCertsOut,
+				TCapabilitySet* aCapabilitySetOut,
+				TBool& aAllowUnsigned,
+				TRequestStatus& aStatus)
+	{
+	DEBUG_PRINTF(_L8("Security Manager - Re-Verifying Controller"));
+	
+	iResult = aResultOut;
+	iChains = aController.SignatureCertificateChains();	
+	iController = &aController;
+	iChainListIndices = &aChainListIndices;
+	iEndCertificatesOut = &aCertsOut;
+	iValidationResultsOut = &aPkixResultsOut;
+	iTotalCapabilitiesOut = aCapabilitySetOut;
+	iIsEmbeddedController = ETrue;
+	
+
+	*iResult = ESignatureNotPresent;
+	aAllowUnsigned = iSecPolicy->AllowUnsigned();
+	
+	iClientStatus = &aStatus;  // Store caller's request status
+	*iClientStatus = KRequestPending;
+		
+	if (iChains.Count() == 0)
+		{
+		// This is an unsigned SISX file
+		User::RequestComplete(iClientStatus, KErrNone);	
+		return;	
+		}
+	
+	iRawController.Set(aRawController);
+    iCurrentChain = 0;
+    
+    delete iCertificateRetriever;
+    iCertificateRetriever = NULL;
+    iCertificateRetriever = CCertificateRetriever::NewL(*iCertStore);
+    
+    delete iChainValidator;
+    iChainValidator = NULL;
+	iChainValidator = CChainValidator::NewL(*iCertStore, *iSecPolicy);
+
+	// We may have an unsigned sis file in which case we do not want to verify the block
+	// since there isn't one, so bail here with the correct error
+	if (iChains.Count() == 0)
+		{
+		User::RequestComplete(iClientStatus, KErrNone);							
+		}
+	else 
+		{
+		TInt currentChain = (*iChainListIndices)[iCurrentChain];
+		VerifyBlockL(currentChain);		
+		}	
+	}
+		
+TInt CSecurityManager::SignedSize(TInt iChainsToAdd) const
+	{
+	TInt64 size = 0;
+
+	const Sis::CInfo& info = iController->Info();	
+	size += info.Length() + info.HeaderSize() + info.PaddingSize();
+
+	const Sis::CSupportedOptions& options = iController->SupportedOptions();
+	size += options.Length() + options.HeaderSize() + options.PaddingSize();
+
+	const Sis::CSupportedLanguages& languages = iController->SupportedLanguages();
+	size += languages.Length() + languages.HeaderSize() + languages.PaddingSize();
+
+	const Sis::CPrerequisites& prerequisites = iController->Prerequisites();
+	size += prerequisites.Length() + prerequisites.HeaderSize() + prerequisites.PaddingSize();
+
+	const Sis::CProperties& props = iController->Properties();
+	size += props.Length() + props.HeaderSize() + props.PaddingSize();
+
+	const Sis::CLogo* logo = iController->Logo();
+	if (logo != NULL)
+		{
+		size += logo->Length() + logo->HeaderSize() + logo->PaddingSize();		
+		}
+		
+	const Sis::CInstallBlock& installblock = iController->InstallBlock();
+	size += installblock.Length() + installblock.HeaderSize() + installblock.PaddingSize();
+
+	for (TInt k = 0; k < iChainsToAdd; k++)
+		{
+		size += iChains[k]->Length() + iChains[k]->HeaderSize() + iChains[k]->PaddingSize();
+		}
+
+	return I64INT(size);	
+	}
+
+void CSecurityManager::VerifyBlockL(TInt aChainIndex)
+	{		
+	DEBUG_PRINTF2(_L8("Security Manager - Validating certificate chain %d."), aChainIndex);
+
+	Sis::CSignatureCertificateChain& chain = *iChains[aChainIndex];	
+	
+	// First verify the signature
+	const RPointerArray<Sis::CSignature> signatures = chain.Signatures();
+	
+	// Determine the size of the controller data which was signed
+	TInt size = SignedSize(aChainIndex);
+
+	const Sis::CCertificateChain& certChain = chain.CertificateChain();
+	const TPtrC8 data = certChain.Data();
+	
+	TInt pos = 0;
+	TInt end = data.Length();
+	iUntrustedRoots.ResetAndDestroy();
+	
+	// Find all the self-signed certificates in the chain as possible root candidates
+	
+	while (pos < end)
+		{
+		CX509Certificate* decoded = CX509Certificate::NewLC(data, pos);
+		if (decoded->IsSelfSignedL())
+			{
+			// If the root isn't in the trusted list, append it to the untrusted roots
+			TBool found = EFalse;
+			if(NULL == iRootCerts)
+				{
+				for (TInt i = 0; i < iTrustedRoots.Count(); i++)
+					{
+					CCTCertInfo* root = iTrustedRoots[i];
+					if (root->SubjectKeyId() == decoded->KeyIdentifierL()) 
+						{
+						found = ETrue;
+						break;
+						}
+					}
+				}
+			else
+				{
+				for (TInt i = iRootCerts->Count() - 1; i >= 0; --i)
+					{
+					CX509Certificate* root = (*iRootCerts)[i];
+					if (root->KeyIdentifierL() == decoded->KeyIdentifierL()) 
+						{
+						found = ETrue;
+						break;
+						}
+					}
+				}
+			
+			if (!found)
+				{
+				iUntrustedRoots.AppendL(decoded);
+				CleanupStack::Pop(decoded);
+				}
+			else
+				{
+				CleanupStack::PopAndDestroy(decoded);	
+				}
+			}
+		else
+			{
+			CleanupStack::PopAndDestroy(decoded);
+			}	
+		}
+	
+	DEBUG_PRINTF2(_L8("Security Manager - Found %d non-trusted candidate root certificates"), iUntrustedRoots.Count());
+		
+	// If we have self signed roots, don't look in the certstore for a further root
+	
+	TBool hasUntrustedRoot = (iUntrustedRoots.Count() > 0);
+	
+	if (NULL != iRootCerts)
+		{
+		DEBUG_PRINTF(_L8("Security Manager - Validating chain using user provided roots"));
+		iCurrentPkixChain = CPKIXCertChainBase::NewL(*iCertStore, data, *iRootCerts);
+		hasUntrustedRoot = ETrue; // These root certs are considered untrusted.
+		}
+	else if(hasUntrustedRoot)
+		{
+		DEBUG_PRINTF(_L8("Security Manager - Validating chain using untrusted roots"));
+		iCurrentPkixChain = CPKIXCertChainBase::NewL(*iCertStore, data, iUntrustedRoots);
+		}
+	else
+		{
+		DEBUG_PRINTF(_L8("Security Manager - Validating chain using trusted roots from store"));
+		iCurrentPkixChain = CPKIXCertChainBase::NewL(*iCertStore, data, KSwiApplicabilityUid);	
+		}
+	
+
+	DEBUG_PRINTF2(_L8("Security Manager - Certificate chain contains %d certificates."), iCurrentPkixChain->Count());
+
+	const CX509Certificate& clientCert = iCurrentPkixChain->Cert(0); // This is the ee certificate
+	CX509Certificate* endCertOut = CX509Certificate::NewLC(clientCert);
+	iEndCertificatesOut->AppendL(endCertOut);
+	CleanupStack::Pop(endCertOut);
+	
+	DEBUG_CODE_SECTION(HBufC* issuer = clientCert.IssuerL(); DEBUG_PRINTF2(_L("Security Manager - End Entity Certificate Issuer: '%S'."), issuer); delete issuer;);
+	DEBUG_CODE_SECTION(HBufC* subject = clientCert.SubjectL(); DEBUG_PRINTF2(_L("Security Manager - End Entity Certificate Subject: '%S'."), subject); delete subject;);
+	
+	const CSubjectPublicKeyInfo& publicKey=  clientCert.PublicKey();
+	
+	DEBUG_PRINTF2(_L8("Security Manager - SIS file signed %d times with this certificate."), signatures.Count());
+	
+	CSignatureVerifier* verifier = CSignatureVerifier::NewLC();
+	TBool result = EFalse;
+	for (TInt k = 0; k < signatures.Count(); k++)
+		{
+		const TDesC& algorithmOID = signatures[k]->Algorithm().AlgorithmIdentifier().Data();
+		TRAP_IGNORE(result = verifier->VerifySignatureL(algorithmOID, publicKey, iRawController.Mid((iIsEmbeddedController ? 4 : iController->HeaderSize()), size), signatures[k]->Data()));
+		if (result) 
+ 			{
+			// We have a verify any policy on signatures (inside a given SISSignatureCertificateChain)
+			// Cf. SGL.GT0188.251 Section 4.3
+			break;   
+			}
+		}
+
+	CleanupStack::PopAndDestroy(verifier);
+
+	if (!result) // Signature not verified: something is WRONG. Abort.
+		{
+		DEBUG_PRINTF(_L8("Security Manager - No signature validated."));
+		
+		*iResult = ESignatureCouldNotBeValidated;
+		User::RequestComplete(iClientStatus, KErrNone);	
+		return;			
+		}
+			
+	// The signature is good, validate the certificate chain
+	
+	CPKIXValidationResultBase* validationResult = CPKIXValidationResultBase::NewLC();
+	iValidationResultsOut->Append(validationResult);
+	CleanupStack::Pop(validationResult);
+	
+	iState = EValidatingChain;
+	iCurrentPkixChain->SetValidityPeriodCheckFatal(iCheckDateAndTime);
+	iChainValidator->ValidateChainL(*iCurrentPkixChain, *iResult, *validationResult, 
+									iCurrentCapabilities, hasUntrustedRoot, iStatus);
+	SetActive();	
+	}
+
+EXPORT_C HBufC8* CSecurityManager::CalculateHashLC(MSisDataProvider& aDataProvider, CMessageDigest::THashId aAlgorithm)
+	{
+	CMessageDigest* digest = CMessageDigestFactory::NewDigestLC(aAlgorithm);
+		
+	HBufC8* aBuffer = HBufC8::NewMaxLC(KFileBufferSize); 
+	TPtr8 aBufferPtr(aBuffer->Des());
+
+	User::LeaveIfError(aDataProvider.Read(aBufferPtr));
+
+	while (aBuffer->Length() != 0)
+		{
+		digest->Update(*aBuffer);
+		User::LeaveIfError(aDataProvider.Read(aBufferPtr));		
+		}
+	TPtrC8 hash = digest->Final();
+	HBufC8* hashBuffer = hash.AllocL();
+	CleanupStack::PopAndDestroy(2, digest); // aBuffer, digest
+	
+	CleanupStack::PushL(hashBuffer);
+	return hashBuffer;
+	}
+
+EXPORT_C TBool CSecurityManager::VerifyFileHashL(MSisDataProvider& aDataProvider, const CHashContainer& aDigest)
+	{
+	HBufC8* hashBuffer = CalculateHashLC(aDataProvider, aDigest.Algorithm());
+
+	TBool result = EFalse;
+
+	TPtrC8 hash = hashBuffer->Des();
+	if (hash.Compare(aDigest.Data()) == 0)
+		{
+		result = ETrue;
+		}
+
+	CleanupStack::PopAndDestroy(hashBuffer);
+	return result;
+	}
+	
+void CSecurityManager::UpdateListOfMissingRequiredCertsL(const CCertificate& aCertificate) 
+	{
+	// Find aCertificate in iTrustedRoots and marked as nonmandatory for temporary!
+	TInt count = iTrustedRoots.Count();
+	for (TInt k = 0; k < count; k++)
+		{
+		CCTCertInfo* certInfo = iTrustedRoots[k];
+		if (iCertMetaInfo[k].iIsMandatory && !certInfo->SubjectKeyId().Compare(aCertificate.KeyIdentifierL()))
+			{
+			DEBUG_PRINTF2(_L("Security Manager - Mandatory certificate '%S' satisfied."), &(certInfo->Label()));
+			// set the Mandatory is false so that next time this certificate won't be compared
+			iCertMetaInfo[k].iIsMandatory = 0;
+			iMandatoryCertDNCount--;
+			break;
+			}
+		}
+	}
+
+void CSecurityManager::UpdateSystemUpgradeCertStatusL(const CCertificate& aCertificate)
+	{	
+	// Find aCertificate in iTrustedRoots and update the system upgrade trust status
+	TInt count = iTrustedRoots.Count();
+	for (TInt k = 0; k < count; k++)
+		{
+		CCTCertInfo* certInfo = iTrustedRoots[k];
+		if (iCertMetaInfo[k].iIsSystemUpgrade && certInfo->SubjectKeyId() == aCertificate.KeyIdentifierL())
+			{
+			DEBUG_PRINTF2(_L("Security Manager - System upgrade certificate '%S' satisfied."), &(certInfo->Label()));
+			// create a modifyable reference to the current controller
+			Sis::CController& controller = const_cast <Sis::CController&>(*iController);
+			// set the SuCert validation status
+			controller.SetSignedBySuCert(ETrue);
+			break;
+			}
+		}
+	
+	}
+
+EXPORT_C void CSecurityManager::GetCertificatesFromControllerL(
+	const Sis::CController& aController,
+	RPointerArray<CX509Certificate>& aCerts)
+	{
+	// Go through all SIS chains and extract end certificates from them.
+	const RPointerArray<Sis::CSignatureCertificateChain>& chains=
+		aController.SignatureCertificateChains();
+	for (TInt i=0; i<chains.Count(); i++)
+		{
+		Sis::CSignatureCertificateChain& sigCertChain=*chains[i];
+		const Sis::CCertificateChain& certChain=
+			sigCertChain.CertificateChain();
+		// Construct PKIX cert chain from raw data in the controller.
+		CPKIXCertChainBase* pkixChain=CPKIXCertChainBase::NewLC(*iCertStore,
+			certChain.Data(), KSwiApplicabilityUid);
+		
+		// Extract end entity certificate and store it in the member array.
+		const CX509Certificate& endCert=pkixChain->Cert(0);
+		CX509Certificate* endCertCopy=CX509Certificate::NewLC(endCert);
+		User::LeaveIfError(aCerts.Append(endCertCopy));
+		CleanupStack::Pop(endCertCopy);
+		
+		// Cleanup.
+		CleanupStack::PopAndDestroy(pkixChain);
+		}
+	}
+
+EXPORT_C void CSecurityManager::FillCertInfoArrayL(
+	const RPointerArray<CX509Certificate>& aCertificates,
+	RPointerArray<CCertificateInfo>& aCertInfos)
+	{
+	for (TInt i=0; i<aCertificates.Count(); i++)
+		{
+		CCertificateInfo* certInfo=CCertificateInfo::NewLC(*aCertificates[i]);
+		aCertInfos.AppendL(certInfo);
+		CleanupStack::Pop(certInfo);
+		}
+	}
+
+EXPORT_C const RPointerArray<HBufC>& CSecurityManager::DeviceIDsInfo() const
+ 	{
+ 	return iDeviceIDs;
+ 	}
+
+EXPORT_C void CSecurityManager::ResetValidCertChains() 
+	{
+	iValidPkixChains.ResetAndDestroy();
+	}
+	
+EXPORT_C void CSecurityManager::SetDevCertWarningState(TInt aDevCertWarningState)
+	{
+	iDevCertWarningState=static_cast<TDevCertWarningState>(aDevCertWarningState);	
+	}
+
+EXPORT_C TInt CSecurityManager::GetDevCertWarningState()
+	{
+	return iDevCertWarningState;
+	}
+
+
+EXPORT_C void CSecurityManager::SetRootCerts(RPointerArray<CX509Certificate>* aX509CertArray)
+	{
+	iRootCerts = aX509CertArray;
+	}
+
+	
+	
+
+
+