cryptoservices/certificateandkeymgmt/tx509/extensiontest.cpp
changeset 0 2c201484c85f
child 8 35751d3474b7
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cryptoservices/certificateandkeymgmt/tx509/extensiontest.cpp	Wed Jul 08 11:25:26 2009 +0100
@@ -0,0 +1,434 @@
+/*
+* Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the License "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: 
+*
+*/
+
+
+#include "x509constraintext.h"
+#include "extensiontest.h"
+#include "t_input.h"
+
+_LIT(KFileNameStart, "<filename>");
+_LIT(KExpectedDeviceIdList, "<device_id_list>");
+_LIT(KExpectedDevice, "<device_id>");
+_LIT(KExpectedSidList, "<sid_list>");
+_LIT(KExpectedSid, "<sid>");
+_LIT(KExpectedVidList, "<vid_list>");
+_LIT(KExpectedVid, "<vid>");
+_LIT(KExpectedCapabilities, "<capabilities>");
+_LIT(KCorrupt, "<corrupt>");
+_LIT(KMatch, "<match>");
+
+CTestAction* CExtensionTest::NewL(RFs& aFs, CConsoleBase& aConsole, 
+	Output& aOut, const TTestActionSpec& aTestActionSpec)
+	{
+	CTestAction* self = CExtensionTest::NewLC(aFs, aConsole, aOut, aTestActionSpec);
+	CleanupStack::Pop(self);
+	return self;
+	}
+
+CTestAction* CExtensionTest::NewLC(RFs& aFs, CConsoleBase& aConsole, 
+	Output& aOut, const TTestActionSpec& aTestActionSpec)
+	{
+	CExtensionTest* self = new(ELeave) CExtensionTest(aFs, aConsole, aOut);
+	CleanupStack::PushL(self);
+	self->ConstructL(aTestActionSpec);
+	return self;
+	}
+
+CExtensionTest::CExtensionTest(RFs& aFs, CConsoleBase& aConsole, Output& aOut)
+	: CTestAction(aConsole, aOut), 
+	iFs(aFs)
+	{
+	}
+
+CExtensionTest::~CExtensionTest()
+	{	
+	iExpectedDeviceIdList.ResetAndDestroy();
+	iExpectedDeviceIdList.Close();		
+	iExpectedSidList.Close();
+	iExpectedVidList.Close();
+	}	
+
+void CExtensionTest::ConstructL(const TTestActionSpec& aTestActionSpec)
+	{
+	CTestAction::ConstructL(aTestActionSpec);
+	TInt startPos = 0;
+	TInt err = 0;
+	
+	HBufC* aBody = HBufC::NewLC(aTestActionSpec.iActionBody.Length());	
+	aBody->Des().Copy(aTestActionSpec.iActionBody);
+	
+	// Filename of the certificate file
+	TPtrC fileNameStart = Input::ParseElement(*aBody, KFileNameStart);
+	iCertFileName.Copy(fileNameStart);
+
+	// Whether we expect at least on of the extensions to be corrupt
+	TPtrC corruptStart = Input::ParseElement(*aBody, KCorrupt);	
+	if (corruptStart.CompareF(_L("True")) == 0)
+		{
+		iExpectedCorrupt = ETrue;
+		}				
+		
+	// We expect the certificate to match the constraints
+	TPtrC matchStart = Input::ParseElement(*aBody, KMatch);	
+	if (matchStart.CompareF(_L("True")) == 0)
+		{
+		iExpectedMatch = ETrue;
+		}						
+
+	// Extract the lists of constraints that are expected to be present 		
+	startPos = 0;
+	TPtrC deviceListStart = Input::ParseElement(*aBody, KExpectedDeviceIdList, startPos, err);
+	if (err >= 0)
+		{
+		BuildStringListL(iExpectedDeviceIdList, deviceListStart, KExpectedDevice);
+		iDeviceIdsPresent = ETrue;		
+		}
+
+	startPos = 0;
+	TPtrC sidListStart = Input::ParseElement(*aBody, KExpectedSidList, startPos, err);
+	if (err >= 0)
+		{
+		BuildIntList(iExpectedSidList, sidListStart, KExpectedSid);
+		iSidsPresent = ETrue;
+		}	
+
+	startPos = 0;
+	TPtrC vidListStart = Input::ParseElement(*aBody, KExpectedVidList, startPos, err);
+	if (err >= 0)
+		{
+		BuildIntList(iExpectedVidList, vidListStart, KExpectedVid);
+		iVidsPresent = ETrue;
+		}	
+		
+	startPos = 0;
+	TPtrC capabilities = Input::ParseElement(*aBody, KExpectedCapabilities, startPos, err);
+	if (err >= 0)
+		{
+		BuildCapabilitySet(iExpectedCapabilities, capabilities);
+		iCapabilitiesPresent = ETrue;
+		}	
+	
+	CleanupStack::PopAndDestroy(aBody);
+	}	
+
+void CExtensionTest::BuildStringListL(RPointerArray<HBufC>& aStrings, const TDesC& aBuf, const TDesC& aTag)
+	{
+	TInt pos = 0;
+	TInt err = 0;	
+	do
+		{			
+		// Find next value for the specified tag and add it to the string array
+		// if it exists.
+		TPtrC str = Input::ParseElement(aBuf, aTag, pos, err);
+		if (err >= 0)
+			{			
+			aStrings.Append(str.AllocL());
+			}								
+		}
+	while (err >= 0);	
+	}
+
+void CExtensionTest::BuildIntList(RArray<TInt>& aInts, const TDesC& aBuf, const TDesC& aTag)
+	{	
+	TInt pos = 0;
+	TInt err = 0;	
+	do
+		{			
+		// Attempt to convert the contents of val to an int and store in  
+		// the aInts array if it is a valid integer.
+		TInt n = Input::ParseIntElement(aBuf, aTag, pos, err);
+		if (err >= 0)
+			{
+			aInts.Append(n);
+			}								
+		}
+	while (err >= 0);
+	}
+
+void CExtensionTest::BuildCapabilitySet(TCapabilitySet& aCapabilitySet, const TDesC& aBuf)	
+	{
+	aCapabilitySet.SetEmpty();
+	TUint length = aBuf.Length();
+	for (TUint i = 0; i < length && i < ECapability_Limit; i++) 
+		{
+		if (aBuf[i] == '1')
+			{
+			aCapabilitySet.AddCapability(static_cast<TCapability>(i));
+			}			
+		}
+	}
+			
+void CExtensionTest::PerformAction(TRequestStatus& aStatus)
+	{
+	HBufC8* buf = NULL;
+	TInt err = KErrNone;
+	
+	TRAP(err, buf = Input::ReadFileL(iCertFileName, iFs));
+	if (err == KErrNotFound)
+		{
+		iResult = EFalse;
+		iFinished = ETrue;
+		SetScriptError(EFileNotFound, iCertFileName);
+		TRequestStatus* status = &aStatus;
+		iActionState = EPostrequisite;
+		User::RequestComplete(status, KErrNone);
+		return;
+		}
+	else if (err != KErrNone)
+		{
+		User::Leave(err);
+		}
+		
+	CleanupStack::PushL(buf);
+	CX509Certificate* cert = CX509Certificate::NewLC(buf->Des());
+
+	Print(_L("Checking certificate extensions in file "));
+	PrintLine(iCertFileName);
+	
+	TBool match = EFalse;
+	TBool corrupt = EFalse;
+	CheckExtensionsL(*cert, match, corrupt);
+	if (corrupt)
+		{
+		iResult = iExpectedCorrupt;
+		if (!iResult)
+			{
+			Print(_L("Found unexpected corrupt extension."));
+			}
+		}
+	else 
+		{
+		// no error. test whether the certificate matched the
+		// test script.
+		iResult = (match == iExpectedMatch);
+		}
+	CleanupStack::PopAndDestroy(2, buf); // cert, buf	
+
+	TRequestStatus* status = &aStatus;
+	iActionState = EPostrequisite;
+	User::RequestComplete(status, KErrNone);
+	}	
+	
+void CExtensionTest::CheckExtensionsL(const CX509Certificate& cert, 
+	TBool& match, TBool& corrupt)
+	{
+	TInt err = KErrNone;
+	
+	match = ETrue;
+	corrupt = EFalse;
+
+	TRAP(err, match &= CheckDeviceIdListL(cert));
+	if (err == KErrArgument)
+		{		
+		PrintLine(_L("The device id constraint is corrupt."));
+		corrupt = ETrue;
+		}
+	else if (err != KErrNone) 
+		{
+		User::Leave(err);
+		}	
+				
+	TRAP(err, match &= CheckSidListL(cert));
+	if (err == KErrArgument)
+		{		
+		PrintLine(_L("The secure id constraint is corrupt."));
+		corrupt = ETrue;
+		}
+	else if (err != KErrNone) 
+		{
+		User::Leave(err);
+		}
+		
+	TRAP(err, match &= CheckVidListL(cert));
+	if (err == KErrArgument)
+		{		
+		PrintLine(_L("The vendor id constraint is corrupt."));
+		corrupt = ETrue;
+		}
+	else if (err != KErrNone) 
+		{
+		User::Leave(err);
+		}		
+		
+	TRAP(err, match &= CheckCapabilitiesL(cert));
+	if (err == KErrArgument)
+		{		
+		PrintLine(_L("The capabilities constraint is corrupt."));
+		corrupt = ETrue;
+		}
+	else if (err != KErrNone) 
+		{
+		User::Leave(err);
+		}				
+	}
+	
+TBool CExtensionTest::CheckDeviceIdListL(const CX509Certificate& cert) 
+	{
+	TBool match = ETrue;
+	const CX509CertExtension* ext = cert.Extension(KDeviceIdListConstraint);	
+	if (ext)
+		{
+		// use NewL because this covers NewLC as well
+		CX509Utf8StringListExt* stringListExt = CX509Utf8StringListExt::NewL(ext->Data());	
+		CleanupStack::PushL(stringListExt);
+		if (! IsEqual(stringListExt->StringArray(), iExpectedDeviceIdList))
+			{
+			PrintLine(_L("Device Id list is different."));
+			match = EFalse;
+			}
+		CleanupStack::PopAndDestroy(stringListExt);		
+		}	
+	else if (iDeviceIdsPresent) 
+		{
+		PrintLine(_L("Device Id constraint is missing."));
+		match = EFalse;
+		}	
+	return match;
+	}
+	
+TBool CExtensionTest::CheckSidListL(const CX509Certificate& cert) 
+	{
+	const CX509CertExtension* ext = cert.Extension(KSidListConstraint);
+	TBool match = ETrue;
+	if (ext)
+		{				
+		// use NewL because this covers NewLC as well
+		CX509IntListExt* intListExt = CX509IntListExt::NewL(ext->Data());
+		CleanupStack::PushL(intListExt);
+		if (! IsEqual(intListExt->IntArray(), iExpectedSidList))
+			{
+			PrintLine(_L("SID list is different"));
+			match = EFalse;
+			}
+		CleanupStack::PopAndDestroy(intListExt);		
+		}	
+	else if (iSidsPresent) 
+		{
+			PrintLine(_L("SID constraint is missing."));
+			match = EFalse;
+		}
+	return match;	
+	}
+	
+TBool CExtensionTest::CheckVidListL(const CX509Certificate& cert) 
+	{
+	const CX509CertExtension* ext = cert.Extension(KVidListConstraint);
+	TBool match = ETrue;
+	if (ext)
+		{
+		// use NewL because this covers NewLC as well
+		CX509IntListExt* intListExt = CX509IntListExt::NewL(ext->Data());
+		CleanupStack::PushL(intListExt);
+								
+		if (! IsEqual(intListExt->IntArray(), iExpectedVidList))
+			{
+			PrintLine(_L("VID list is different"));
+			match = EFalse;
+			}
+		CleanupStack::PopAndDestroy(intListExt);		
+		}	
+	else if (iVidsPresent) 
+		{
+		PrintLine(_L("VID constraint is missing."));
+		match = EFalse;
+		}	
+	return match;
+	}	
+	
+TBool CExtensionTest::CheckCapabilitiesL(const CX509Certificate& cert) 
+	{
+	const CX509CertExtension* ext = cert.Extension(KCapabilitiesConstraint);
+	TBool match = ETrue;
+	if (ext)
+		{		
+		// use NewL because this covers NewLC as well
+		CX509CapabilitySetExt* capabilitySetExt = CX509CapabilitySetExt::NewL(ext->Data());		
+		CleanupStack::PushL(capabilitySetExt);
+		
+		const TCapabilitySet& capabilitySet = capabilitySetExt->CapabilitySet();		
+
+		if (! (capabilitySet.HasCapabilities(iExpectedCapabilities)
+			&& iExpectedCapabilities.HasCapabilities(capabilitySet)))
+			{
+			PrintLine(_L("Capability constraints are different."));
+			match = EFalse;
+			}
+		CleanupStack::PopAndDestroy(capabilitySetExt);		
+		}	
+	else if (iCapabilitiesPresent) 
+		{
+		PrintLine(_L("Capability constraint is missing."));
+		match = EFalse;
+		}	
+	return match;		
+	}
+
+TBool CExtensionTest::IsEqual(const RArray<TInt>& aArray1, const RArray<TInt>& aArray2) 
+	{			
+	if (aArray1.Count() == aArray2.Count())
+		{
+		TInt count = aArray1.Count();				
+		for (TInt i = 0; i < count; i++)
+			{
+			if (aArray1[i] != aArray2[i])
+				{
+				return EFalse;
+				}
+			}
+		return ETrue;
+		}	
+	return EFalse;
+	}
+
+TBool CExtensionTest::IsEqual(const RPointerArray<HBufC>& aArray1, const RPointerArray<HBufC>& aArray2) 
+	{			
+	if (aArray1.Count() == aArray2.Count())
+		{
+		TInt count = aArray1.Count();				
+		for (TInt i = 0; i < count; i++)
+			{
+			if (aArray1[i]->Compare(*aArray2[i]) != 0)
+				{
+				return EFalse;
+				}
+			}
+		return ETrue;
+		}	
+	return EFalse;
+	}
+	
+void CExtensionTest::DoReportAction() 
+	{	
+	}
+	
+void CExtensionTest::DoCheckResult(TInt /*aError*/)
+	{
+	}
+
+void CExtensionTest::Print(const TDesC& aText)
+	{
+	iConsole.Printf(aText);
+	iOut.writeString(aText);			
+	}
+void CExtensionTest::PrintLine(const TDesC& aText)
+	{
+	iConsole.Printf(aText);
+	iConsole.Printf(_L("\n"));
+	
+	iOut.writeString(aText);			
+	iOut.writeNewLine();					
+	}