os/security/cryptoservices/certificateandkeymgmt/tx509/extensiontest.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     1 /*
     2 * Copyright (c) 2005-2010 Nokia Corporation and/or its subsidiary(-ies).
     3 * All rights reserved.
     4 * This component and the accompanying materials are made available
     5 * under the terms of the License "Eclipse Public License v1.0"
     6 * which accompanies this distribution, and is available
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
     8 *
     9 * Initial Contributors:
    10 * Nokia Corporation - initial contribution.
    11 *
    12 * Contributors:
    13 *
    14 * Description: 
    15 *
    16 */
    17 
    18 
    19 #include "x509constraintext.h"
    20 #include "extensiontest.h"
    21 #include "t_input.h"
    22 
    23 _LIT(KFileNameStart, "<filename>");
    24 _LIT(KExpectedDeviceIdList, "<device_id_list>");
    25 _LIT(KExpectedDevice, "<device_id>");
    26 _LIT(KExpectedSidList, "<sid_list>");
    27 _LIT(KExpectedSid, "<sid>");
    28 _LIT(KExpectedVidList, "<vid_list>");
    29 _LIT(KExpectedVid, "<vid>");
    30 _LIT(KExpectedCapabilities, "<capabilities>");
    31 _LIT(KCorrupt, "<corrupt>");
    32 _LIT(KMatch, "<match>");
    33 
    34 CTestAction* CExtensionTest::NewL(RFs& aFs, CConsoleBase& aConsole, 
    35 	Output& aOut, const TTestActionSpec& aTestActionSpec)
    36 	{
    37 	CTestAction* self = CExtensionTest::NewLC(aFs, aConsole, aOut, aTestActionSpec);
    38 	CleanupStack::Pop(self);
    39 	return self;
    40 	}
    41 
    42 CTestAction* CExtensionTest::NewLC(RFs& aFs, CConsoleBase& aConsole, 
    43 	Output& aOut, const TTestActionSpec& aTestActionSpec)
    44 	{
    45 	CExtensionTest* self = new(ELeave) CExtensionTest(aFs, aConsole, aOut);
    46 	CleanupStack::PushL(self);
    47 	self->ConstructL(aTestActionSpec);
    48 	return self;
    49 	}
    50 
    51 CExtensionTest::CExtensionTest(RFs& aFs, CConsoleBase& aConsole, Output& aOut)
    52 	: CTestAction(aConsole, aOut), 
    53 	iFs(aFs)
    54 	{
    55 	}
    56 
    57 CExtensionTest::~CExtensionTest()
    58 	{	
    59 	iExpectedDeviceIdList.ResetAndDestroy();
    60 	iExpectedDeviceIdList.Close();		
    61 	iExpectedSidList.Close();
    62 	iExpectedVidList.Close();
    63 	}	
    64 
    65 void CExtensionTest::ConstructL(const TTestActionSpec& aTestActionSpec)
    66 	{
    67 	CTestAction::ConstructL(aTestActionSpec);
    68 	TInt startPos = 0;
    69 	TInt err = 0;
    70 	
    71 	HBufC* aBody = HBufC::NewLC(aTestActionSpec.iActionBody.Length());	
    72 	aBody->Des().Copy(aTestActionSpec.iActionBody);
    73 	
    74 	// Filename of the certificate file
    75 	TPtrC fileNameStart = Input::ParseElement(*aBody, KFileNameStart);
    76 	iCertFileName.Copy(fileNameStart);
    77 
    78 	// Whether we expect at least on of the extensions to be corrupt
    79 	TPtrC corruptStart = Input::ParseElement(*aBody, KCorrupt);	
    80 	if (corruptStart.CompareF(_L("True")) == 0)
    81 		{
    82 		iExpectedCorrupt = ETrue;
    83 		}				
    84 		
    85 	// We expect the certificate to match the constraints
    86 	TPtrC matchStart = Input::ParseElement(*aBody, KMatch);	
    87 	if (matchStart.CompareF(_L("True")) == 0)
    88 		{
    89 		iExpectedMatch = ETrue;
    90 		}						
    91 
    92 	// Extract the lists of constraints that are expected to be present 		
    93 	startPos = 0;
    94 	TPtrC deviceListStart = Input::ParseElement(*aBody, KExpectedDeviceIdList, startPos, err);
    95 	if (err >= 0)
    96 		{
    97 		BuildStringListL(iExpectedDeviceIdList, deviceListStart, KExpectedDevice);
    98 		iDeviceIdsPresent = ETrue;		
    99 		}
   100 
   101 	startPos = 0;
   102 	TPtrC sidListStart = Input::ParseElement(*aBody, KExpectedSidList, startPos, err);
   103 	if (err >= 0)
   104 		{
   105 		BuildIntList(iExpectedSidList, sidListStart, KExpectedSid);
   106 		iSidsPresent = ETrue;
   107 		}	
   108 
   109 	startPos = 0;
   110 	TPtrC vidListStart = Input::ParseElement(*aBody, KExpectedVidList, startPos, err);
   111 	if (err >= 0)
   112 		{
   113 		BuildIntList(iExpectedVidList, vidListStart, KExpectedVid);
   114 		iVidsPresent = ETrue;
   115 		}	
   116 		
   117 	startPos = 0;
   118 	TPtrC capabilities = Input::ParseElement(*aBody, KExpectedCapabilities, startPos, err);
   119 	if (err >= 0)
   120 		{
   121 		BuildCapabilitySet(iExpectedCapabilities, capabilities);
   122 		iCapabilitiesPresent = ETrue;
   123 		}	
   124 	
   125 	CleanupStack::PopAndDestroy(aBody);
   126 	}	
   127 
   128 void CExtensionTest::BuildStringListL(RPointerArray<HBufC>& aStrings, const TDesC& aBuf, const TDesC& aTag)
   129 	{
   130 	TInt pos = 0;
   131 	TInt err = 0;	
   132 	do
   133 		{			
   134 		// Find next value for the specified tag and add it to the string array
   135 		// if it exists.
   136 		TPtrC str = Input::ParseElement(aBuf, aTag, pos, err);
   137 		if (err >= 0)
   138 			{
   139 			HBufC* string = str.AllocLC();			
   140 			aStrings.AppendL(string);
   141 			CleanupStack::Pop(string);
   142 			}								
   143 		}
   144 	while (err >= 0);	
   145 	}
   146 
   147 void CExtensionTest::BuildIntList(RArray<TInt>& aInts, const TDesC& aBuf, const TDesC& aTag)
   148 	{	
   149 	TInt pos = 0;
   150 	TInt err = 0;	
   151 	do
   152 		{			
   153 		// Attempt to convert the contents of val to an int and store in  
   154 		// the aInts array if it is a valid integer.
   155 		TInt n = Input::ParseIntElement(aBuf, aTag, pos, err);
   156 		if (err >= 0)
   157 			{
   158 			// This append should not fail as the parsing went fine. 
   159 			// So, ignoring the leave just to satisfy non leaving method convention.
   160 			TRAP_IGNORE(aInts.AppendL(n));
   161 			}								
   162 		}
   163 	while (err >= 0);
   164 	}
   165 
   166 void CExtensionTest::BuildCapabilitySet(TCapabilitySet& aCapabilitySet, const TDesC& aBuf)	
   167 	{
   168 	aCapabilitySet.SetEmpty();
   169 	TUint length = aBuf.Length();
   170 	for (TUint i = 0; i < length && i < ECapability_Limit; i++) 
   171 		{
   172 		if (aBuf[i] == '1')
   173 			{
   174 			aCapabilitySet.AddCapability(static_cast<TCapability>(i));
   175 			}			
   176 		}
   177 	}
   178 			
   179 void CExtensionTest::PerformAction(TRequestStatus& aStatus)
   180 	{
   181 	HBufC8* buf = NULL;
   182 	TInt err = KErrNone;
   183 	
   184 	TRAP(err, buf = Input::ReadFileL(iCertFileName, iFs));
   185 	if (err == KErrNotFound)
   186 		{
   187 		iResult = EFalse;
   188 		iFinished = ETrue;
   189 		SetScriptError(EFileNotFound, iCertFileName);
   190 		TRequestStatus* status = &aStatus;
   191 		iActionState = EPostrequisite;
   192 		User::RequestComplete(status, KErrNone);
   193 		return;
   194 		}
   195 	else if (err != KErrNone)
   196 		{
   197 		User::Leave(err);
   198 		}
   199 		
   200 	CleanupStack::PushL(buf);
   201 	CX509Certificate* cert = CX509Certificate::NewLC(buf->Des());
   202 
   203 	Print(_L("Checking certificate extensions in file "));
   204 	PrintLine(iCertFileName);
   205 	
   206 	TBool match = EFalse;
   207 	TBool corrupt = EFalse;
   208 	CheckExtensionsL(*cert, match, corrupt);
   209 	if (corrupt)
   210 		{
   211 		iResult = iExpectedCorrupt;
   212 		if (!iResult)
   213 			{
   214 			Print(_L("Found unexpected corrupt extension."));
   215 			}
   216 		}
   217 	else 
   218 		{
   219 		// no error. test whether the certificate matched the
   220 		// test script.
   221 		iResult = (match == iExpectedMatch);
   222 		}
   223 	CleanupStack::PopAndDestroy(2, buf); // cert, buf	
   224 
   225 	TRequestStatus* status = &aStatus;
   226 	iActionState = EPostrequisite;
   227 	User::RequestComplete(status, KErrNone);
   228 	}	
   229 	
   230 void CExtensionTest::CheckExtensionsL(const CX509Certificate& cert, 
   231 	TBool& match, TBool& corrupt)
   232 	{
   233 	TInt err = KErrNone;
   234 	
   235 	match = ETrue;
   236 	corrupt = EFalse;
   237 
   238 	TRAP(err, match &= CheckDeviceIdListL(cert));
   239 	if (err == KErrArgument)
   240 		{		
   241 		PrintLine(_L("The device id constraint is corrupt."));
   242 		corrupt = ETrue;
   243 		}
   244 	else if (err != KErrNone) 
   245 		{
   246 		User::Leave(err);
   247 		}	
   248 				
   249 	TRAP(err, match &= CheckSidListL(cert));
   250 	if (err == KErrArgument)
   251 		{		
   252 		PrintLine(_L("The secure id constraint is corrupt."));
   253 		corrupt = ETrue;
   254 		}
   255 	else if (err != KErrNone) 
   256 		{
   257 		User::Leave(err);
   258 		}
   259 		
   260 	TRAP(err, match &= CheckVidListL(cert));
   261 	if (err == KErrArgument)
   262 		{		
   263 		PrintLine(_L("The vendor id constraint is corrupt."));
   264 		corrupt = ETrue;
   265 		}
   266 	else if (err != KErrNone) 
   267 		{
   268 		User::Leave(err);
   269 		}		
   270 		
   271 	TRAP(err, match &= CheckCapabilitiesL(cert));
   272 	if (err == KErrArgument)
   273 		{		
   274 		PrintLine(_L("The capabilities constraint is corrupt."));
   275 		corrupt = ETrue;
   276 		}
   277 	else if (err != KErrNone) 
   278 		{
   279 		User::Leave(err);
   280 		}				
   281 	}
   282 	
   283 TBool CExtensionTest::CheckDeviceIdListL(const CX509Certificate& cert) 
   284 	{
   285 	TBool match = ETrue;
   286 	const CX509CertExtension* ext = cert.Extension(KDeviceIdListConstraint);	
   287 	if (ext)
   288 		{
   289 		// use NewL because this covers NewLC as well
   290 		CX509Utf8StringListExt* stringListExt = CX509Utf8StringListExt::NewL(ext->Data());	
   291 		CleanupStack::PushL(stringListExt);
   292 		if (! IsEqual(stringListExt->StringArray(), iExpectedDeviceIdList))
   293 			{
   294 			PrintLine(_L("Device Id list is different."));
   295 			match = EFalse;
   296 			}
   297 		CleanupStack::PopAndDestroy(stringListExt);		
   298 		}	
   299 	else if (iDeviceIdsPresent) 
   300 		{
   301 		PrintLine(_L("Device Id constraint is missing."));
   302 		match = EFalse;
   303 		}	
   304 	return match;
   305 	}
   306 	
   307 TBool CExtensionTest::CheckSidListL(const CX509Certificate& cert) 
   308 	{
   309 	const CX509CertExtension* ext = cert.Extension(KSidListConstraint);
   310 	TBool match = ETrue;
   311 	if (ext)
   312 		{				
   313 		// use NewL because this covers NewLC as well
   314 		CX509IntListExt* intListExt = CX509IntListExt::NewL(ext->Data());
   315 		CleanupStack::PushL(intListExt);
   316 		if (! IsEqual(intListExt->IntArray(), iExpectedSidList))
   317 			{
   318 			PrintLine(_L("SID list is different"));
   319 			match = EFalse;
   320 			}
   321 		CleanupStack::PopAndDestroy(intListExt);		
   322 		}	
   323 	else if (iSidsPresent) 
   324 		{
   325 			PrintLine(_L("SID constraint is missing."));
   326 			match = EFalse;
   327 		}
   328 	return match;	
   329 	}
   330 	
   331 TBool CExtensionTest::CheckVidListL(const CX509Certificate& cert) 
   332 	{
   333 	const CX509CertExtension* ext = cert.Extension(KVidListConstraint);
   334 	TBool match = ETrue;
   335 	if (ext)
   336 		{
   337 		// use NewL because this covers NewLC as well
   338 		CX509IntListExt* intListExt = CX509IntListExt::NewL(ext->Data());
   339 		CleanupStack::PushL(intListExt);
   340 								
   341 		if (! IsEqual(intListExt->IntArray(), iExpectedVidList))
   342 			{
   343 			PrintLine(_L("VID list is different"));
   344 			match = EFalse;
   345 			}
   346 		CleanupStack::PopAndDestroy(intListExt);		
   347 		}	
   348 	else if (iVidsPresent) 
   349 		{
   350 		PrintLine(_L("VID constraint is missing."));
   351 		match = EFalse;
   352 		}	
   353 	return match;
   354 	}	
   355 	
   356 TBool CExtensionTest::CheckCapabilitiesL(const CX509Certificate& cert) 
   357 	{
   358 	const CX509CertExtension* ext = cert.Extension(KCapabilitiesConstraint);
   359 	TBool match = ETrue;
   360 	if (ext)
   361 		{		
   362 		// use NewL because this covers NewLC as well
   363 		CX509CapabilitySetExt* capabilitySetExt = CX509CapabilitySetExt::NewL(ext->Data());		
   364 		CleanupStack::PushL(capabilitySetExt);
   365 		
   366 		const TCapabilitySet& capabilitySet = capabilitySetExt->CapabilitySet();		
   367 
   368 		if (! (capabilitySet.HasCapabilities(iExpectedCapabilities)
   369 			&& iExpectedCapabilities.HasCapabilities(capabilitySet)))
   370 			{
   371 			PrintLine(_L("Capability constraints are different."));
   372 			match = EFalse;
   373 			}
   374 		CleanupStack::PopAndDestroy(capabilitySetExt);		
   375 		}	
   376 	else if (iCapabilitiesPresent) 
   377 		{
   378 		PrintLine(_L("Capability constraint is missing."));
   379 		match = EFalse;
   380 		}	
   381 	return match;		
   382 	}
   383 
   384 TBool CExtensionTest::IsEqual(const RArray<TInt>& aArray1, const RArray<TInt>& aArray2) 
   385 	{			
   386 	if (aArray1.Count() == aArray2.Count())
   387 		{
   388 		TInt count = aArray1.Count();				
   389 		for (TInt i = 0; i < count; i++)
   390 			{
   391 			if (aArray1[i] != aArray2[i])
   392 				{
   393 				return EFalse;
   394 				}
   395 			}
   396 		return ETrue;
   397 		}	
   398 	return EFalse;
   399 	}
   400 
   401 TBool CExtensionTest::IsEqual(const RPointerArray<HBufC>& aArray1, const RPointerArray<HBufC>& aArray2) 
   402 	{			
   403 	if (aArray1.Count() == aArray2.Count())
   404 		{
   405 		TInt count = aArray1.Count();				
   406 		for (TInt i = 0; i < count; i++)
   407 			{
   408 			if (aArray1[i]->Compare(*aArray2[i]) != 0)
   409 				{
   410 				return EFalse;
   411 				}
   412 			}
   413 		return ETrue;
   414 		}	
   415 	return EFalse;
   416 	}
   417 	
   418 void CExtensionTest::DoReportAction() 
   419 	{	
   420 	}
   421 	
   422 void CExtensionTest::DoCheckResult(TInt /*aError*/)
   423 	{
   424 	}
   425 
   426 void CExtensionTest::Print(const TDesC& aText)
   427 	{
   428 	iConsole.Printf(aText);
   429 	iOut.writeString(aText);			
   430 	}
   431 void CExtensionTest::PrintLine(const TDesC& aText)
   432 	{
   433 	iConsole.Printf(aText);
   434 	iConsole.Printf(_L("\n"));
   435 	
   436 	iOut.writeString(aText);			
   437 	iOut.writeNewLine();					
   438 	}