pkiutilities/ocsp/test/engine.cpp
changeset 0 164170e6151a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pkiutilities/ocsp/test/engine.cpp	Tue Jan 26 15:20:08 2010 +0200
@@ -0,0 +1,1123 @@
+// Copyright (c) 2001-2009 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:
+//
+
+#include "engine.h"
+#include "transport.h"
+#include "panic.h"
+#include "logger.h"
+#include "main.h"
+#include "requestlogger.h"
+#include "testfilterparameters.h"
+#include <miscutil.h>
+
+#include <ocsp.h>
+#include <x509cert.h>
+
+#include <ocsptransport.h>
+
+#include "ocspsupporttransport.h"
+
+// Log file created by the transport filter
+_LIT(KFilterLogFileName, "\\tocsphttpfilter.log");
+
+const TInt KTimeMilliToMicro = 1000;
+
+CTOCSPEngine* CTOCSPEngine::NewL(CTOCSPLogger& aLog)
+	{
+	CTOCSPEngine* self = new (ELeave) CTOCSPEngine(aLog);
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	CleanupStack::Pop(self);
+	return self;
+	}
+
+
+CTOCSPEngine::CTOCSPEngine(CTOCSPLogger& aLog) :
+	CActive(EPriorityNormal),
+	iLog(aLog)
+	{
+	CActiveScheduler::Add(this);
+	}
+
+
+void CTOCSPEngine::ConstructL()
+	{
+	// Open file server session
+	User::LeaveIfError(iFs.Connect());
+	iCertUtils = CCertUtils::NewL(iFs);
+
+	// Create cancellation timer
+	iTimer = CCallbackTimer::NewL(*this);
+	}
+
+CTOCSPEngine::~CTOCSPEngine()
+	{
+    Cancel(); // Calls Reset along the way
+	Destroy();
+	delete iTimer;
+	delete iCertUtils;
+	delete iUnifiedCertStore;
+	iFs.Close();
+	}
+
+// Common code between destructor and ResetL()
+void CTOCSPEngine::Destroy()
+	{
+	delete iParams;
+	iParams = NULL;
+	
+	delete iClient;
+	iClient = NULL;
+	
+	iSubjectCerts.ResetAndDestroy();
+	iIssuerCerts.ResetAndDestroy();
+	iSigningCerts.ResetAndDestroy();
+	iTransportLog.Close();
+
+	delete iRequestLog;
+	iRequestLog = NULL;
+
+	// Not owned
+	iTransport = NULL;
+	}
+
+void CTOCSPEngine::Reset()
+	{
+	Destroy();
+
+	// Delete and reset all the filter parameters
+	DeleteFilterParameters();
+
+	iUseDirectAuthorisation = EFalse;
+	iUseCADelegateAuthorisation = EFalse;
+	iUseCADirectAuthorisation = EFalse;
+	iUseAllSchemes = EFalse;
+
+	iCancelTime = 0;
+	}
+
+
+void CTOCSPEngine::StartL(TRequestStatus& aStatus)
+	{	
+	iParams = COCSPParameters::NewL();	
+	InitDirectAuthL();
+
+	// Delete the transport filter log file
+	TInt err = iFs.Delete(KFilterLogFileName);
+	if ((err != KErrNone) && (err != KErrNotFound))
+		{
+		if (iVerbose)
+			{
+			iLog.LogL(_L("Failed to delete transport filter log file ("), ETrue);
+			iLog.LogL(KFilterLogFileName);
+			iLog.LogL(_L("). Error: "), ETrue);
+			iLog.LogL(err);
+			}
+		User::Leave(err);
+		}
+
+	iState = EInitCertStore;
+	aStatus = KRequestPending;
+	iOriginalRequestStatus = &aStatus;
+	SetActive();
+		
+	// Initialise unified cert store here if it doesn't already exist
+	if (!iUnifiedCertStore)
+		{
+		iUnifiedCertStore = CUnifiedCertStore::NewL(iFs, ETrue);
+		iUnifiedCertStore->Initialize(iStatus);
+		}
+	else
+		{
+		TRequestStatus* status = &iStatus;
+		User::RequestComplete(status, KErrNone);
+		}
+	}
+
+void CTOCSPEngine::EndL(TRequestStatus& aStatus)
+	{
+	Reset();
+	CleanUpDirectAuthL(aStatus);
+	}
+
+
+void CTOCSPEngine::SetURIL(const TDesC8& aURI, TBool aUseAIA)
+	{
+	iParams->SetURIL(aURI, aUseAIA);
+	}
+
+
+void CTOCSPEngine::SetDefaultTransportL()
+	{
+	iIap = 0;
+	MOCSPTransport* trans = COCSPTransportDefault::NewL(iIap);
+	CleanupStack::PushL(trans);
+	SetTransportL(trans);
+	CleanupStack::Pop(trans);
+	}
+
+
+void CTOCSPEngine::SetTestTransportL(const TDesC& aResponseFile, const TDesC* aRequestFile)
+	{
+	CTOCSPTransport* trans = CTOCSPTransport::NewL(aResponseFile, aRequestFile);
+	CleanupStack::PushL(trans);
+	SetTransportL(trans);
+	CleanupStack::Pop(trans);
+	}
+
+void CTOCSPEngine::SetOcspSupportTransportL()
+	{
+	iIap = 0;
+	Swi::COcspSupportTransport* trans = Swi::COcspSupportTransport::NewL(iIap);
+
+	CleanupStack::PushL(trans);
+	SetTransportL(trans);
+	CleanupStack::Pop(trans);
+	}
+
+void CTOCSPEngine::SetTransportRetryCount(TUint aRetryCount)
+	{
+	__ASSERT_DEBUG(iTransport != NULL, Panic(KErrTOCSPScriptParameterError));
+	iParams->SetRetryCount(aRetryCount);
+	}
+
+void CTOCSPEngine::SetTransportTimeout(TInt aTimeout)
+	{
+	__ASSERT_DEBUG(iTransport != NULL, Panic(KErrTOCSPScriptParameterError));
+	iParams->SetTimeout(aTimeout);
+	}
+
+void CTOCSPEngine::SetTransportL(MOCSPTransport* aTransport)
+	{
+	// To log the request, we wrap the transport in our request logger transport
+	if (iRequestLog)
+		{
+		aTransport = CTOCSPRequestLogger::NewL(*iRequestLog, aTransport);
+		}
+	iTransport = aTransport;
+	iParams->SetTransport(aTransport);
+	}
+
+void CTOCSPEngine::SetFilterParameters(TInt aNumDelayResp, TInt aCountDropResp,
+			TInt countCorruptHTTPDataHeader, TInt countCorruptHTTPDataBodySizeLarge, TInt countCorruptHTTPDataBodySizeSmall, 
+			TInt aCountCorruptOCSPData, 
+			TInt aCountInternalErrorResp, TInt aCountTryLaterResp,
+			TInt aCountSigValidateFailure)
+	{
+	iNumDelayResp = aNumDelayResp;
+	iCountDropResp = aCountDropResp;
+	iCountCorruptHTTPDataHeader = countCorruptHTTPDataHeader;
+	iCountCorruptHTTPDataBodySizeLarge = countCorruptHTTPDataBodySizeLarge;
+	iCountCorruptHTTPDataBodySizeSmall = countCorruptHTTPDataBodySizeSmall;
+	iCountCorruptOCSPData = aCountCorruptOCSPData;
+	iCountInternalErrorResp = aCountInternalErrorResp;
+	iCountTryLaterResp = aCountTryLaterResp;
+	iCountSigValidateFailure = aCountSigValidateFailure;
+	}
+
+void CTOCSPEngine::AddCertL(const TDesC8& aSubject, const TDesC8& aIssuer)
+	{
+	// Create certificate objects and keep hold of them - these are added
+	// to the client later
+
+	CX509Certificate* subject = CX509Certificate::NewLC(aSubject);
+	User::LeaveIfError(iSubjectCerts.Append(subject));
+	CleanupStack::Pop(subject);  // Now owned through iCerts
+
+	CX509Certificate* issuer = CX509Certificate::NewLC(aIssuer);
+	User::LeaveIfError(iIssuerCerts.Append(issuer));
+	CleanupStack::Pop(issuer);  // Now owned through iCerts
+	
+	// Add certificates to parameter
+	iParams->AddCertificateL(*subject, *issuer);
+	}
+
+void CTOCSPEngine::ReadTransportLogL()
+	{
+	// Read and process the transport filter log (if it exists)
+	RFile file;
+	TInt size;
+	if (file.Open(iFs, KFilterLogFileName, EFileShareAny | EFileRead) != KErrNone)
+		{
+		return;
+		}
+
+	CleanupClosePushL(file);
+	file.Size(size);
+	RFileReadStream fileStream(file);
+	CleanupClosePushL(fileStream);
+	RBuf8 logBuffer;
+	logBuffer.CreateL(size);
+	CleanupClosePushL(logBuffer);
+	fileStream.ReadL(logBuffer, size);
+	TInt readPos = 0;
+	TPtrC8 currentLine;
+	while (MiscUtil::ReadNonEmptyLineL(logBuffer, readPos, currentLine))
+		{
+		TLex8 lex(currentLine);
+		TPtrC8 methodName = lex.NextToken();
+
+		// Validate and store the entry
+		TTransportLog logEntry;
+		if (methodName.Length() <= 4)
+			{
+			logEntry.iHttpMethod.Copy(methodName);
+			logEntry.iHttpMethod.UpperCase();
+			}
+
+		// Get the timestamps and calculate transaction duration
+		TInt64 startTime = 0;
+		TInt64 endTime = 0;
+		lex.SkipSpaceAndMark(); User::LeaveIfError(lex.Val(startTime));
+		lex.SkipSpaceAndMark(); User::LeaveIfError(lex.Val(endTime));
+		logEntry.iTransDurationMs = static_cast<TInt64>((endTime - startTime) / KTimeMilliToMicro);
+
+		iTransportLog.AppendL(logEntry);
+		}
+	CleanupStack::PopAndDestroy(3, &file); // fileStream, logBuffer
+	}
+
+TBool CTOCSPEngine::ReadLineL(const TDesC8& aBuffer, TInt& aPos, TPtrC8& aLine) const
+	{
+	TBool endOfBuffer = EFalse;	
+	aLine.Set(NULL, 0);
+
+	TInt bufferLength = aBuffer.Length();	
+	__ASSERT_ALWAYS(aPos >=0 && aPos <= bufferLength, User::Leave(KErrArgument));
+
+	// Skip blank lines
+	while (aPos < bufferLength) 
+		{
+		TChar  c = aBuffer[aPos];
+		if (c != '\r' && c != '\n')
+			{
+			break;
+			}
+		aPos++;
+		}
+
+	// Find the position of the next delimter		
+	TInt endPos = aPos;	
+	while (endPos < bufferLength)
+		{
+		TChar c = aBuffer[endPos];
+		if (c == '\n' || c == '\r') 
+			{
+			break;
+			}	
+		++endPos;
+		}
+
+	if (endPos != aPos)	
+		{
+		TInt tokenLen = endPos - aPos;
+		aLine.Set(&aBuffer[aPos], tokenLen);
+		}
+	else 
+		{
+		return ETrue; // End of buffer
+		}			
+
+	aPos = endPos;
+	return endOfBuffer;
+	}
+
+void CTOCSPEngine::LogResponseDetailsL()
+	{
+	if (iVerbose)
+		{
+		_LIT(KDateFormat, "%F%H:%T %D/%M/%Y");
+		TBuf<32> timeString;
+
+		iLog.LogL(_L("Response details:\n"));
+
+		TTime timeNow;
+		timeNow.UniversalTime();
+		timeNow.FormatL(timeString, KDateFormat);
+		iLog.LogL(_L("  Response generation time == "));
+		iLog.LogL(timeString);
+		iLog.LogL(_L("\n"));
+
+		TBuf<10> indexText;
+
+		for (int i = 0 ; i < iClient->TransactionCount() ; ++i)
+			{
+			const COCSPResponse* response = iClient->Response(i);
+
+			iLog.LogL(_L("  Response "));
+			indexText.Zero();
+			indexText.Num(i);
+			iLog.LogL(indexText);
+			iLog.LogL(_L(":\n"));
+
+			if (response)
+				{
+				response->ProducedAt().FormatL(timeString, KDateFormat);
+				iLog.LogL(_L("    producedAt == "));
+				iLog.LogL(timeString);
+				iLog.NewLineL();
+	
+				TInt count = response->CertCount();
+				for (TInt index = 0; index < count; ++index)
+					{
+					const COCSPResponseCertInfo& certInfo = response->CertInfo(index);
+
+					iLog.LogL(_L("    Cert "));
+					indexText.Zero();
+					indexText.Num(index);
+					iLog.LogL(indexText);
+					iLog.LogL(_L(" Results:"));
+			
+					iLog.LogL(_L("\n      status == "));
+					iLog.LogL(TranslateResultL(certInfo.Status()));
+
+					certInfo.ThisUpdate().FormatL(timeString, KDateFormat);
+					iLog.LogL(_L("\n      thisUpdate == "));
+					iLog.LogL(timeString);
+					iLog.NewLineL();
+
+					if (certInfo.NextUpdate())
+						{
+						timeString.Zero();
+						certInfo.NextUpdate()->FormatL(timeString, KDateFormat);
+						iLog.LogL(_L("      nextUpdate == "));
+						iLog.LogL(timeString);
+						iLog.NewLineL();
+						}
+
+					if (certInfo.RevocationTime())
+						{
+						timeString.Zero();
+						certInfo.RevocationTime()->FormatL(timeString, KDateFormat);
+						iLog.LogL(_L("      revocationTime == "));
+						iLog.LogL(timeString);
+						iLog.NewLineL();
+						}
+					}
+				}
+			else
+				{
+				iLog.LogL(_L("    missing"));			
+				iLog.NewLineL();
+				}
+
+			const TOCSPOutcome& outcome = iClient->Outcome(i);
+			iLog.LogL(_L("    Validation outcome:"));
+			iLog.NewLineL();
+			iLog.LogL(_L("      status == "));
+			iLog.LogL(TranslateStatusL(outcome.iStatus));
+			iLog.NewLineL();
+			iLog.LogL(_L("      result == "));
+			iLog.LogL(TranslateResultL(outcome.iResult));
+			iLog.NewLineL();
+			}
+
+		iLog.LogL(_L("  OCSP Summary result == "));
+		iLog.LogL(TranslateResultL(iClient->SummaryResult()));
+		iLog.NewLineL();
+		}
+	}
+
+
+void CTOCSPEngine::RunL()
+	{
+	TInt err = iStatus.Int();
+	if( KErrNotFound != err && KErrNone != err )
+		{
+		iLog.LogL(_L("Client request completed with code:"));  
+		iLog.LogL(err);
+		iLog.NewLineL();
+		User::LeaveIfError(err);
+		}
+
+	if( KErrNotFound == err )
+		{
+		iLog.LogL(_L("Item not found leave code"));
+		iLog.NewLineL();
+		// Handle error
+		User::Leave(err);
+		}
+
+	switch (iState)
+		{
+		case EInitCertStore:
+			// Remove all certificates so we always start from the same state 
+			iCertUtils->RemoveCertsL(*iUnifiedCertStore, iStatus);
+			iState = ERemovingCerts;
+			SetActive();
+			break;
+			
+		case EAddingCert:
+		case ERemovingCerts:
+			User::RequestComplete(iOriginalRequestStatus, KErrNone);
+			break;
+
+		case EChecking:
+			// Cancel the timer
+			iTimer->Cancel();
+			ReadTransportLogL();
+			LogResponseDetailsL();
+			User::RequestComplete(iOriginalRequestStatus, KErrNone);
+			break;
+
+		default:
+            User::Panic(_L("TOCSP"), 1);
+			break;
+		}
+	}
+
+TInt CTOCSPEngine::RunError(TInt aError)
+    {
+    User::RequestComplete(iOriginalRequestStatus, aError);
+    return KErrNone;
+    }
+
+void CTOCSPEngine::DoCancel()
+	{
+    switch (iState)
+        {
+		case EInitCertStore:
+			if (iUnifiedCertStore)
+				{
+				iUnifiedCertStore->CancelInitialize();
+				}
+			break;
+			
+		case EAddingCert:
+		case ERemovingCerts:
+            iCertUtils->Cancel();
+            break;
+
+		case EChecking:
+            iClient->CancelCheck();
+            break;
+
+		default:
+            User::Panic(_L("TOCSP"), 1);
+			break;
+        }
+
+	Reset();
+    User::RequestComplete(iOriginalRequestStatus, KErrCancel);
+	}
+
+// Implementation of MTimerRun
+void CTOCSPEngine::TimerRun(TInt /*aError*/)
+	{
+	// Cancellation timer expired
+	this->Cancel();
+	}
+
+void CTOCSPEngine::SetValidationTimeL(const TTime& aWhen)
+	{
+	iParams->SetValidationTimeL(aWhen);
+	}
+
+
+void CTOCSPEngine::SetNonce(const TBool aNonce)
+	{
+	iParams->SetUseNonce(aNonce);
+	}
+
+
+void CTOCSPEngine::SetMaxStatusAgeL(TUint aMaxAge)
+	{
+	iParams->SetMaxStatusAgeL(aMaxAge);
+	}
+
+void CTOCSPEngine::InitDirectAuthL()
+	{
+	// Add OCSP test harness to cert store client list
+	TName name(_L("TOCSP"));
+	iCertUtils->AddApplicationL(name, TUid::Uid(KTOCSP_UID));
+	}
+
+void CTOCSPEngine::CleanUpDirectAuthL(TRequestStatus& aStatus)
+	{
+	iOriginalRequestStatus = &aStatus;
+	aStatus = KRequestPending;
+
+	// Should always succeed, as called after InitDirectAuthL
+	iCertUtils->RemoveApplicationL(TUid::Uid(KTOCSP_UID));
+
+	//This should remove the X509Certs, which is the only certificate type used by the test.
+	iCertUtils->RemoveCertsL(*iUnifiedCertStore, iStatus);
+	iState = ERemovingCerts;
+	SetActive();
+	}
+
+void CTOCSPEngine::AddDirectAuthorisationCert(const TDesC& aCert,
+                                              const TDesC& aLabel,
+                                              TRequestStatus& aStatus)
+	{
+    TRAPD(err, DoAddDirectAuthorisationCertL(aCert, aLabel, aStatus));
+    if (err != KErrNone)
+        {
+        Cancel();
+        TRequestStatus* status = &aStatus;
+        User::RequestComplete(status, err);
+        }
+    }
+
+void CTOCSPEngine::DoAddDirectAuthorisationCertL(const TDesC& aCert,
+												 const TDesC& aLabel,
+												 TRequestStatus& aStatus)
+	{
+	TPtrC cert = aCert;
+	HBufC8* certData = ReadDataL(iFs, cert);
+	CleanupStack::PushL(certData);
+
+	// Make and store the certificate
+	CX509Certificate* cert2 = CX509Certificate::NewLC(*certData);
+	User::LeaveIfError(iSigningCerts.Append(cert2));
+	CleanupStack::Pop(cert2);  // Now owned through iCerts
+	CleanupStack::PopAndDestroy(certData);
+	
+	iUseDirectAuthorisation = ETrue;
+
+	iCert = aCert;
+	iLabel = aLabel;	
+
+	iOriginalRequestStatus = &aStatus;
+	aStatus = KRequestPending;
+	iState = EAddingCert;
+
+	iCertUtils->AddCert(iLabel, EX509Certificate, ECACertificate, KTOCSP_UID,
+						KNullDesC, iCert, *iUnifiedCertStore, iStatus);
+	SetActive();
+	}
+
+
+/**
+	Called when "AUTHORISATIONCERT AUTHCERTNONE" is parsed.
+	Sets a flag so an instance of COCSPDirectAuthorisationScheme
+	is allocated in PrepareAuthorisationSchemeL().
+	
+	This function should be used to test direct authorisation
+	without supplying a cert.  When a cert is supplied, use
+	AddDirectAuthorisationCert().
+	
+	@see AddDirectAuthorisationCert
+	@see UseCADelegateAuthorisation
+ */
+void CTOCSPEngine::UseDirectAuthorisation()
+	{
+	iUseDirectAuthorisation = ETrue;	
+	}
+
+/**
+	Called when a "CADELEGATE" command is parsed.  It sets
+	a flag so that an instance of COCSPDelegateAuthorisationScheme
+	is allocated in PrepareAuthorisationSchemeL().
+
+	@see AddDirectAuthorisationCert
+	@see UseCADirectAuthorisation
+ */
+void CTOCSPEngine::UseCADelegateAuthorisation()
+	{
+	iUseCADelegateAuthorisation = ETrue;
+	}
+
+/**
+	Called when "CADIRECT" command is parsed.  It sets
+	a flag so that an instance of COCSPCaDirectAuthorisationScheme
+	is allocated in PrepareAuthorisationSchemeL().
+
+	@see AddDirectAuthorisationCert
+	@see UseCADelegateAuthorisation
+ 	@see UseDirectAuthorisation
+*/
+void CTOCSPEngine::UseCADirectAuthorisation()
+	{
+	iUseCADirectAuthorisation = ETrue;
+	}
+
+/**
+	Called when "ALLSCHEMES" command is parsed.  It sets
+	a flag so that all schemes are allocated in 
+	PrepareAuthorisationSchemeL().
+
+	@see AddDirectAuthorisationCert
+	@see UseCADelegateAuthorisation
+	@see UseCADirectAuthorisation
+*/
+void CTOCSPEngine::UseAllAuthorisationSchemes()
+	{
+	iUseAllSchemes = ETrue;
+	}
+
+void CTOCSPEngine::PrepareAuthorisationL()
+	{
+	if (iUseAllSchemes)
+		{
+		// iUseDirectAuthorisation may also be set because
+		// "AUTHORISATIONCERT" commands have been parsed.
+		ASSERT(!(iUseCADelegateAuthorisation || iUseCADirectAuthorisation));
+
+		// This assumes __SECURITY_PLATSEC_ARCH__ is defined.  This
+		// is the case because AddAllAuthorisationSchemesL() is added
+		// to 9.1 onwards.
+		iParams->AddAllAuthorisationSchemesL(TUid::Uid(KTOCSP_UID), *iUnifiedCertStore);
+		return;
+		}
+
+	if (iUseDirectAuthorisation)
+		{
+		// Register direct authorisation object with OCSP validator
+		COCSPDirectAuthorisationScheme* scheme =  
+			COCSPDirectAuthorisationScheme::NewLC(TUid::Uid(KTOCSP_UID), *iUnifiedCertStore);
+		iParams->AddAuthorisationSchemeL(scheme);
+		CleanupStack::Pop(); // scheme, now owned by client
+		}
+	
+	if (iUseCADelegateAuthorisation)
+		{
+		COCSPDelegateAuthorisationScheme* schemeDel =
+			COCSPDelegateAuthorisationScheme::NewLC(*iUnifiedCertStore);
+		iParams->AddAuthorisationSchemeL(schemeDel);
+		CleanupStack::Pop(schemeDel); // scheme, now owned by client		
+		}
+	
+	if (iUseCADirectAuthorisation)
+		{
+		COCSPCaDirectAuthorisationScheme* schemeCad =
+			COCSPCaDirectAuthorisationScheme::NewLC();
+		iParams->AddAuthorisationSchemeL(schemeCad);
+		CleanupStack::Pop(schemeCad); // scheme, now owned by client		
+		}
+	}
+
+// Set filter parameters
+void CTOCSPEngine::DefineAndSetFilterParametersL()
+	{
+	TUid categoryUid = TUid::Uid(KFilterParametersCategoryUID);
+
+	// Define the parameters
+	RProperty::Define(categoryUid, KFilterParameterNumDelayResp, RProperty::EInt);
+	RProperty::Define(categoryUid, KFilterParameterCountDropResp, RProperty::EInt);
+	RProperty::Define(categoryUid, KFilterParameterCountCorruptHTTPDataHeader, RProperty::EInt);
+	RProperty::Define(categoryUid, KFilterParameterCountCorruptHTTPDataBodySizeLarge, RProperty::EInt);
+	RProperty::Define(categoryUid, KFilterParameterCountCorruptHTTPDataBodySizeSmall, RProperty::EInt);
+	RProperty::Define(categoryUid, KFilterParameterCountCorruptOCSPData, RProperty::EInt);
+	RProperty::Define(categoryUid, KFilterParameterCountInternalErrorResp, RProperty::EInt);
+	RProperty::Define(categoryUid, KFilterParameterCountTryLaterResp, RProperty::EInt);
+	RProperty::Define(categoryUid, KFilterParameterCountSigValidateFailure, RProperty::EInt);
+
+	// and Set them
+	User::LeaveIfError(RProperty::Set(categoryUid, KFilterParameterNumDelayResp, iNumDelayResp));
+	User::LeaveIfError(RProperty::Set(categoryUid, KFilterParameterCountDropResp, iCountDropResp));
+	User::LeaveIfError(RProperty::Set(categoryUid, KFilterParameterCountCorruptHTTPDataHeader, iCountCorruptHTTPDataHeader));
+	User::LeaveIfError(RProperty::Set(categoryUid, KFilterParameterCountCorruptHTTPDataBodySizeLarge, iCountCorruptHTTPDataBodySizeLarge));
+	User::LeaveIfError(RProperty::Set(categoryUid, KFilterParameterCountCorruptHTTPDataBodySizeSmall, iCountCorruptHTTPDataBodySizeSmall));
+	User::LeaveIfError(RProperty::Set(categoryUid, KFilterParameterCountCorruptOCSPData, iCountCorruptOCSPData));
+	User::LeaveIfError(RProperty::Set(categoryUid, KFilterParameterCountInternalErrorResp, iCountInternalErrorResp));
+	User::LeaveIfError(RProperty::Set(categoryUid, KFilterParameterCountTryLaterResp, iCountTryLaterResp));
+	User::LeaveIfError(RProperty::Set(categoryUid, KFilterParameterCountSigValidateFailure, iCountSigValidateFailure));
+	}
+
+void CTOCSPEngine::DeleteFilterParameters()
+	{
+	TUid categoryUid = TUid::Uid(KFilterParametersCategoryUID);
+	RProperty::Delete(categoryUid, KFilterParameterNumDelayResp);
+	RProperty::Delete(categoryUid, KFilterParameterCountDropResp);
+	RProperty::Delete(categoryUid, KFilterParameterCountCorruptHTTPDataHeader);
+	RProperty::Delete(categoryUid, KFilterParameterCountCorruptHTTPDataBodySizeLarge);
+	RProperty::Delete(categoryUid, KFilterParameterCountCorruptHTTPDataBodySizeSmall);
+	RProperty::Delete(categoryUid, KFilterParameterCountCorruptOCSPData);
+	RProperty::Delete(categoryUid, KFilterParameterCountInternalErrorResp);
+	RProperty::Delete(categoryUid, KFilterParameterCountTryLaterResp);
+	RProperty::Delete(categoryUid, KFilterParameterCountSigValidateFailure);
+	// Reset the params
+	iNumDelayResp = iCountDropResp = iCountCorruptHTTPDataHeader = iCountCorruptHTTPDataBodySizeLarge = 
+		iCountCorruptHTTPDataBodySizeSmall = iCountCorruptOCSPData = iCountInternalErrorResp = 
+		iCountTryLaterResp = iCountSigValidateFailure = 0;
+	}
+
+void CTOCSPEngine::SetCancelTime(TInt aTime)
+	{
+	iCancelTime = aTime;
+	}
+
+void CTOCSPEngine::Check(TRequestStatus& aStatus)
+	{
+    TRAPD(err, DoCheckL(aStatus));
+    if (err != KErrNone)
+        {
+        Cancel();
+        TRequestStatus* status = &aStatus;
+        User::RequestComplete(status, err);
+        }
+    }
+
+void CTOCSPEngine::DoCheckL(TRequestStatus& aStatus)
+ 	{
+	iOriginalRequestStatus = &aStatus;
+	aStatus = KRequestPending;
+	iState = EChecking;
+
+	PrepareAuthorisationL();
+
+	// Set filter parameters
+	DefineAndSetFilterParametersL();
+
+	if (iVerbose)
+		{
+		iLog.LogL(_L("Checking...\n"), ETrue);
+		}
+
+	iClient = COCSPClient::NewL(iParams);
+	iParams = NULL; // Client takes ownership
+
+	// Setup cancellation timer
+	if (iCancelTime)
+		{
+		iTimer->After(iCancelTime * KTimeMilliToMicro);
+		}
+	iClient->Check(iStatus);
+	SetActive();
+ 	}
+
+void CTOCSPEngine::LogValidationL(const TOCSPOutcome& aOutcome) const
+	{
+	if (iVerbose)
+		{
+		iLog.LogL(_L("Validation complete:\n  status == "));
+		iLog.LogL(TranslateStatusL(aOutcome.iStatus));
+	
+		// Output summary result
+		iLog.LogL(_L("\n  summary result == "));
+		iLog.LogL(TranslateResultL(aOutcome.iResult));
+		iLog.NewLineL();
+		}
+	}
+
+
+TPtrC CTOCSPEngine::TranslateStatusL(OCSP::TStatus aStatus)
+	{
+	switch ((TInt) aStatus)
+		{
+		case OCSP::ETransportError:
+			return _L("Transport error");
+		case OCSP::ETimeOut:
+			return _L("Request timedout");
+		case OCSP::EClientInternalError:
+			return _L("Client internal error");
+		case OCSP::ENoServerSpecified:
+			return _L("No server specified");
+		case OCSP::EInvalidURI:
+			return _L("Invalid URI");
+		case OCSP::EMalformedResponse:
+			return _L("Malformed response");
+		case OCSP::EUnknownResponseType:
+			return _L("Unknown response type");
+		case OCSP::EUnknownCriticalExtension:
+			return _L("Unknown critical extension");
+		case OCSP::EMalformedRequest:
+			return _L("Server: Malformed request");
+		case OCSP::EServerInternalError:
+			return _L("Server: Internal error");
+		case OCSP::ETryLater:
+			return _L("Server: Try later");
+		case OCSP::ESignatureRequired:
+			return _L("Server: Signature required");
+		case OCSP::EClientUnauthorised:
+			return _L("Server: Client unauthorised");
+		case OCSP::EMissingCertificates:
+			return _L("Missing certificates");
+		case OCSP::EResponseSignatureValidationFailure:
+			return _L("Response signature validation failure");
+		case OCSP::EThisUpdateTooLate:
+			return _L("Time error: This update too late");
+		case OCSP::EThisUpdateTooEarly:
+			return _L("Time error: This update too early");
+		case OCSP::ENextUpdateTooEarly:
+			return _L("Time error: Next update too early");
+		case OCSP::ECertificateNotValidAtValidationTime:
+			return _L("Time error: Not valid at validation time");
+		case OCSP::ENonceMismatch:
+			return _L("Nonce mismatch");			
+		case OCSP::EMissingNonce:
+			return _L("Missing nonce");
+		case OCSP::EValid:
+			return _L("Valid");
+		case TOCSP::ETooManyTransactions:
+			return _L("(test) Too many transactions");
+		case TOCSP::EURIMismatch:
+			return _L("(test) URI mismatch");
+		case TOCSP::ERequestMismatch:
+			return _L("(test) Request mismatch");
+		default:
+			return _L("Unknown");
+		}
+	}
+
+
+TPtrC CTOCSPEngine::TranslateResultL(OCSP::TResult aResult)
+	{
+	switch (aResult)
+		{
+		case OCSP::EGood:
+			return _L("Good");
+		case OCSP::ERevoked:
+			return _L("Revoked");
+		case OCSP::EUnknown:
+			return _L("Unknown");
+		default:
+			return _L("Unknown");
+		}
+	}
+
+
+HBufC8* CTOCSPEngine::ReadDataL(RFs& session, const TDesC& aFileName) const
+	{
+	RFile file;
+	User::LeaveIfError(file.Open(session, aFileName, EFileRead | EFileShareReadersOnly));
+	CleanupClosePushL(file);
+
+	TInt size = 0;
+	User::LeaveIfError(file.Size(size));
+
+	HBufC8* data = HBufC8::NewLC(size);
+	TPtr8 dataPtr = data->Des();
+	User::LeaveIfError(file.Read(dataPtr));
+
+	CleanupStack::Pop(data);
+	CleanupStack::PopAndDestroy(); // Close file;
+	
+	return data;
+	}
+
+
+void CTOCSPEngine::LogRequestL(const TDesC& aFilename)
+    {
+	delete iRequestLog;
+	iRequestLog = NULL;
+
+	iRequestLog = aFilename.AllocL();
+	}
+
+
+void CTOCSPEngine::LogResponseL(const TDesC& aFilename)
+    {
+	RFs fs;
+	User::LeaveIfError(fs.Connect());
+	CleanupClosePushL(fs);
+
+	TInt err = fs.MkDirAll(aFilename);
+	if (err != KErrAlreadyExists)
+		{
+		User::LeaveIfError(err);
+		}
+
+	RFile file;
+	User::LeaveIfError(file.Replace(fs, aFilename, EFileWrite));
+	CleanupClosePushL(file);
+
+	RFileWriteStream writeStream(file);
+	CleanupClosePushL(writeStream);
+
+	writeStream.WriteUint32L(iClient->TransactionCount());
+
+	for (int i = 0 ; i < iClient->TransactionCount() ; ++i)
+		{
+		const COCSPResponse* response = iClient->Response(i);
+		if (response)
+			{
+			const TPtrC8 data = response->Encoding();
+			writeStream.WriteUint32L(data.Length());
+			writeStream.WriteL(data);
+			}
+		else
+			{
+			writeStream.WriteUint32L(0);
+			}
+		}
+
+	CleanupStack::PopAndDestroy(3); // writeStream, file, fs
+    }
+
+
+void CTOCSPEngine::SetVerbose(TBool aVerbose)
+	{
+	iVerbose = aVerbose;
+	}
+
+TBool CTOCSPEngine::TestSummaryL(OCSP::TResult aExpected)
+	{
+	TBool result = iClient->SummaryResult() == aExpected;
+
+	if (iVerbose && !result)
+		{
+		iLog.LogL(_L("Summary result fail: expected "));
+		iLog.LogL(aExpected);
+		iLog.NewLineL();
+		}
+
+	return result;
+	}
+
+TBool CTOCSPEngine::TestOutcomeL(TInt aIndex, const TOCSPOutcome& aExpected)
+	{
+	TBool result = EFalse;
+	// This assumes one-transaction-per-certificate behaviour
+	if(iClient)
+		{
+		result = iClient->Outcome(aIndex) == aExpected;
+		}
+
+	if (iVerbose && !result)
+		{
+		iLog.LogL(_L("Outcome result fail for cert "));
+		iLog.LogL(aIndex);
+		iLog.LogL(_L(":\n"));
+		//iLog.LogL(_L("Expected Result:\n"));
+		iLog.LogL(_L("Expected Status == "));
+		iLog.LogL(TranslateStatusL(aExpected.iStatus));
+		iLog.NewLineL();
+		iLog.LogL(_L("Expected Result == "));
+		iLog.LogL(TranslateResultL(aExpected.iResult));
+		iLog.NewLineL();
+		}
+
+	return result;
+	}
+
+void CTOCSPEngine::SetReponderCertCheck()
+	{
+	iParams->SetOCSPCheckForResponderCert(ETrue);
+	}
+
+void CTOCSPEngine::AddCertToStore(const TDesC& aCertFileName, const TDesC& aLabel, TCertificateOwnerType aCertType, TRequestStatus& aStatus)
+	{
+	iOriginalRequestStatus = &aStatus;
+	aStatus = KRequestPending;
+	iState = EAddingCert;
+	
+	iCert = aCertFileName;
+	iLabel = aLabel;	
+	
+	iCertUtils->AddCert(iLabel, EX509Certificate, aCertType, KTOCSP_UID,
+						KNullDesC, iCert, *iUnifiedCertStore, iStatus);		
+	
+	SetActive();
+	}
+
+TBool CTOCSPEngine::TestTransportL(TInt aRetryCountNum, const TDesC& aExpectedHttpMethod, 
+		TInt aExpectedRespTimeMin, TInt aExpectedRespTimeMax)
+	{
+	// This assumes one-tranaction-per-certificate behaviour
+	// This also assumes test case includes only certificate revocation check request (which 
+	// means CHECKRESPONDERCERT command cannot be used with this)
+	// Ensure we have read the entry from the transport log
+	TBool result = ETrue;
+	if (iTransportLog.Count() < (aRetryCountNum + 1))
+		{
+		if (iVerbose)
+			{
+			iLog.LogL(_L("Transport filter log contains insufficient entries: "));
+			iLog.LogL(_L("\n  Expected number of entries: "));
+			iLog.LogL(aRetryCountNum + 1);
+			iLog.LogL(_L("\n  Actual entries: "));
+			iLog.LogL(iTransportLog.Count());
+			iLog.NewLineL();
+			}
+		result = EFalse;
+		}
+
+	TTransportLog& logEntry = iTransportLog[aRetryCountNum];
+	// Convert to 8-bit
+	RBuf8 expectedMethod;
+	expectedMethod.CreateL(aExpectedHttpMethod.Length());
+	CleanupClosePushL(expectedMethod);
+	expectedMethod.Copy(aExpectedHttpMethod);
+	expectedMethod.UpperCase();
+	if (expectedMethod != logEntry.iHttpMethod)
+		{
+		if (iVerbose)
+			{
+			iLog.LogL(_L("Transport outcome result failed for send number: "));
+			iLog.LogL(aRetryCountNum);
+			iLog.LogL(_L("\n  Expected method: "));
+			iLog.LogL(expectedMethod);
+			iLog.LogL(_L("\n  Got method: "));
+			iLog.LogL(logEntry.iHttpMethod);
+			iLog.NewLineL();
+			}
+		result = EFalse;
+		}
+	CleanupStack::PopAndDestroy(&expectedMethod);
+
+	// Test the range of response time
+	if (aExpectedRespTimeMin > logEntry.iTransDurationMs || aExpectedRespTimeMax < logEntry.iTransDurationMs)
+		{
+		if (iVerbose)
+			{
+			iLog.LogL(_L("Transport outcome result failed for send number: "));
+			iLog.LogL(aRetryCountNum);
+			iLog.LogL(_L("\n  Expected response time range (ms): "));
+			iLog.LogL(aExpectedRespTimeMin);
+			iLog.LogL(_L(" to "));
+			iLog.LogL(aExpectedRespTimeMax);
+			iLog.LogL(_L("\n  Actual response time (ms): "));
+			iLog.LogL(logEntry.iTransDurationMs);
+			iLog.NewLineL();
+			}
+		result = EFalse;
+		}
+	else if (iVerbose)
+		{
+		iLog.LogL(_L("Send number: "));
+		iLog.LogL(aRetryCountNum);
+		iLog.LogL(_L(" Response duration(ms): "));
+		iLog.LogL(logEntry.iTransDurationMs);
+		iLog.NewLineL();
+		}
+
+	return result;
+	}
+
+TBool CTOCSPEngine::TestTransportRetryL(TInt aRetryCount)
+	{
+	// This assumes one-tranaction-per-certificate behaviour
+	// This also assumes test case includes only certificate revocation check request (which means 
+	// CHECKRESPONDERCERT command cannot be used with this)
+	// Check the number of retries
+	TBool result = ETrue;
+	if (iTransportLog.Count() != aRetryCount)
+		{
+		if (iVerbose)
+			{
+			iLog.LogL(_L("Transport retry outcome result failed:"));
+			iLog.LogL(_L("\n  Expected number of retries: "));
+			iLog.LogL(aRetryCount);
+			iLog.LogL(_L("\n  Actual retries: "));
+			iLog.LogL(iTransportLog.Count());
+			iLog.NewLineL();
+			}
+		result = EFalse;
+		}
+
+	return result;
+	}
+
+void CTOCSPEngine::SetCheckCertsWithAiaOnly(TBool aCheckCertsWithAiaOnly)
+	{
+	iParams->SetCheckCertsWithAiaOnly(aCheckCertsWithAiaOnly);
+	}
+
+void CTOCSPEngine::SetUseAIA(TBool aUseAIA)
+	{
+	iParams->SetUseAIA(aUseAIA);
+	}