os/security/cryptoservices/certificateandkeymgmt/pkixcertbase/pkixcertchainao.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) 1998-2009 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 "pkixcertchainao.h"
    20 #include "pkixCons.h"
    21 #include <x509keys.h>
    22 #include <pkixcertchain.h>
    23 #include "x509constraintext.h"
    24 
    25 CPKIXCertChainAO* CPKIXCertChainAO::NewL(MCertStore& aCertStore,
    26 										 CPKIXCertChainBase &aPKIXCertChain,
    27 										 const RPointerArray<CX509Certificate>& aRootCerts)
    28 	{
    29 	CPKIXCertChainAO* self = new(ELeave) CPKIXCertChainAO(aCertStore, aPKIXCertChain);
    30 	CleanupStack::PushL(self);
    31 	self->ConstructL(aRootCerts);
    32 	CleanupStack::Pop(self);
    33 	return self;
    34 	}
    35 
    36 CPKIXCertChainAO* CPKIXCertChainAO::NewL(MCertStore& aCertStore, 
    37 										 CPKIXCertChainBase &aPKIXCertChain,
    38 										 const TUid aClient)
    39 	{
    40 	return new(ELeave) CPKIXCertChainAO(aCertStore, aPKIXCertChain, aClient);
    41 	}
    42 
    43 CPKIXCertChainAO::~CPKIXCertChainAO()
    44 	{
    45 	Cancel();
    46 
    47 	delete iRoots;
    48 	delete iBuilder;
    49 	delete iCertsFromStoreRoots;
    50 	}
    51 
    52 CPKIXCertChainAO::CPKIXCertChainAO(MCertStore& aCertStore,
    53 								   CPKIXCertChainBase &aPKIXCertChain)
    54 	: CActive(EPriorityNormal), iCertStore(&aCertStore), iPKIXCertChain(aPKIXCertChain)
    55 	{
    56 	CActiveScheduler::Add(this);
    57 	}
    58 
    59 CPKIXCertChainAO::CPKIXCertChainAO(MCertStore& aCertStore, 
    60 								   CPKIXCertChainBase &aPKIXCertChain,
    61 								   const TUid aClient)
    62 	: CActive(EPriorityNormal), iCertStore(&aCertStore),
    63 	  iPKIXCertChain(aPKIXCertChain), iClient(aClient)
    64 	{
    65 	CActiveScheduler::Add(this);
    66 	}
    67 
    68 void CPKIXCertChainAO::ConstructL(const RPointerArray<CX509Certificate>& aRootCerts)
    69 	{
    70 	CPKIXCertsFromClient* roots = CPKIXCertsFromClient::NewLC(aRootCerts);
    71 	iRoots = CPKIXChainBuilder::NewL();
    72 	iRoots->AddSourceL(roots);
    73 	CleanupStack::Pop(roots);
    74 	}
    75 
    76 void CPKIXCertChainAO::RunL()
    77 	{
    78 	User::LeaveIfError(iStatus.Int());
    79 
    80 	switch (iState)
    81 		{
    82 		case EAddRoots:
    83 			HandleEAddRootsL();
    84 			break;
    85 
    86 		case ERootsInitialized:
    87 			HandleERootsInitializedL();
    88 			break;
    89 
    90 		case EBuildChainStart:
    91 			HandleEBuildChainStartL();
    92 			break;
    93 
    94 		case EBuildChainAddCandidateEnd:
    95 			HandleEBuildChainAddCandidateEndL();
    96 			break;
    97 
    98 		case EBuildChainCertsFromStoreBegin:
    99 			HandleEBuildChainCertsFromStoreBeginL();
   100 			break;
   101 
   102 		case EBuildChainCertsFromStoreEnd:
   103 			HandleEBuildChainCertsFromStoreEndL();
   104 			break;
   105 
   106 		case EAddCandidateIntermediateCertsEnd:
   107 			HandleEAddCandidateIntermediateCertsEndL();
   108 			break;
   109 
   110 		case EValidateEnd:
   111 			HandleEValidateEndL();
   112 			break;
   113 
   114 		default:
   115 			User::Panic(_L("CPKIXCertChainAO"), 1);
   116 			break;
   117 		}
   118 	}
   119 
   120 TInt CPKIXCertChainAO::RunError(TInt aError)
   121 {
   122 	iPKIXCertChain.RemoveLastCerts(iNumberOfAddedCertificates);
   123 	iNumberOfAddedCertificates = 0;
   124 
   125 	delete iRoots;
   126 	iRoots = 0;
   127 		
   128 	delete iBuilder;
   129 	iBuilder = 0;
   130 	delete iCertsFromStoreRoots;
   131 	iCertsFromStoreRoots = 0;
   132 
   133 	iValidationResult->RemovePolicies();
   134 
   135 	User::RequestComplete(iOriginalRequestStatus, aError);
   136 	return KErrNone;
   137 }
   138 
   139 /**
   140  * Creates a list of all the certificates retrieved from the store based on the filter passed.  
   141  */
   142 
   143 void CPKIXCertChainAO::HandleEAddRootsL()
   144 	{
   145 	__ASSERT_DEBUG(!iCertsFromStoreRoots, User::Panic(_L("CPKICCertChainAO"), 1));
   146 	iCertsFromStoreRoots = CPKIXCertsFromStore::NewL(*iCertStore, iClient);
   147 	iCertsFromStoreRoots->Initialize(iStatus);
   148 	iState = ERootsInitialized;	
   149 	SetActive();
   150 	}
   151 
   152 /**
   153  * Adds the list of certificates retrieved from the store, iRoots (CPKIXChainBuilder)
   154  * maintains a templatized list of all the certificates in MPKIXCertSource format.
   155  */
   156 
   157 void CPKIXCertChainAO::HandleERootsInitializedL()
   158 	{
   159 	iRoots->AddSourceL(iCertsFromStoreRoots);
   160 	// Ownership has been passed to iRoots
   161 	iCertsFromStoreRoots = 0;
   162 	iState = EBuildChainStart;
   163 	TRequestStatus* status = &iStatus;
   164 	User::RequestComplete(status, KErrNone);
   165 	SetActive();
   166 	}
   167 
   168 void CPKIXCertChainAO::HandleEBuildChainStartL()
   169 	{
   170 	if ( false == iPKIXCertChain.ChainHasRoot())
   171 		{
   172 		if (iPKIXCertChain.Chain().Count() == 0)
   173 			{
   174 			iState = EValidateEnd;
   175 			TRequestStatus* status = &iStatus;
   176 			User::RequestComplete(status, KErrNone);
   177 			}
   178 		else
   179 			{
   180 			//1) look for an issuer that's a root
   181 			iRoots->AddIssuer(iNumberOfAddedCertificates, iAddIssuerResult, iPKIXCertChain.Chain(), iStatus);
   182 			iState = EBuildChainAddCandidateEnd;
   183 			}
   184 		}
   185 	else
   186 		{
   187 		// This is the correct state as at this point the chain of certificate has been build upto a
   188 		// root certificate.
   189 		iState = EValidateEnd;
   190 		TRequestStatus* status = &iStatus;
   191 		User::RequestComplete(status, KErrNone);
   192 		}
   193 	SetActive();
   194 	}
   195 
   196 void CPKIXCertChainAO::HandleEBuildChainAddCandidateEndL()
   197 	{
   198 	if (iAddIssuerResult)
   199 		{
   200 		iPKIXCertChain.SetChainHasRoot(ETrue);
   201 		iState = EValidateEnd;
   202 		}
   203 	else
   204 		{
   205 		//2) look for a non-root issuer in intermediate certs
   206 		iBuilder = CPKIXChainBuilder::NewL();
   207 		
   208 		CPKIXCertsFromClient* serverCerts = CPKIXCertsFromClient::NewLC(iPKIXCertChain.IntermediateCerts());
   209 		iBuilder->AddSourceL(serverCerts);
   210 		CleanupStack::Pop(serverCerts);
   211 
   212 		iState = EBuildChainCertsFromStoreBegin;
   213 		}
   214 
   215 	TRequestStatus* status = &iStatus;
   216 	User::RequestComplete(status, KErrNone);
   217 	SetActive();
   218 	}
   219 
   220 void CPKIXCertChainAO::HandleEBuildChainCertsFromStoreBeginL()
   221 	{
   222 	//3) look for a non-root issuer in the store
   223 	iCertsFromStoreRoots = CPKIXCertsFromStore::NewL(*iCertStore);
   224 	iCertsFromStoreRoots->Initialize(iStatus);
   225 	iState = EBuildChainCertsFromStoreEnd;
   226 	SetActive();
   227 	}
   228 
   229 void CPKIXCertChainAO::HandleEBuildChainCertsFromStoreEndL()
   230 	{
   231 	iBuilder->AddSourceL(iCertsFromStoreRoots);
   232 	iCertsFromStoreRoots = 0;
   233 
   234 	iBuilder->AddIssuer(iNumberOfAddedCertificates, iAddIssuerResult, iPKIXCertChain.Chain(), iStatus);
   235 	iState = EAddCandidateIntermediateCertsEnd;
   236 	SetActive();
   237 	}
   238 
   239 void CPKIXCertChainAO::HandleEAddCandidateIntermediateCertsEndL()
   240 	{
   241 	if (iAddIssuerResult)
   242 		{
   243 		// cert is a pointer to something we don't own
   244 		CX509Certificate* cert = iPKIXCertChain.Chain().At(iPKIXCertChain.Chain().Count() - 1);
   245 		
   246 		/* If the issuer is not a self signed certificate then it cannot be trusted anchor for the chain 
   247 		 * validation process, this means that we restart the certification validation process.
   248 		 */ 
   249 		
   250 		if (!(cert->IsSelfSignedL()))
   251 			{
   252 			iState = EBuildChainStart;	
   253 			}
   254 		else
   255 			{
   256 			iState = EValidateEnd;			
   257 			}
   258 		}
   259 	else
   260 		{
   261 		iState = EValidateEnd;	
   262 		}
   263 
   264 	delete iBuilder;
   265 	iBuilder = 0;
   266 
   267 	TRequestStatus* status = &iStatus;
   268 	User::RequestComplete(status, KErrNone);
   269 	SetActive();
   270 	}
   271 
   272 void CPKIXCertChainAO::HandleEValidateEndL()
   273 	{
   274 	InitParamsL();
   275 	
   276 	__ASSERT_DEBUG(iValidationResult, User::Panic(_L("CPKICCertChainAO"), 1));
   277 	DoValidateL(*iValidationResult, iValidationTime, iInitialPolicies);
   278 
   279 	User::RequestComplete(iOriginalRequestStatus, KErrNone);
   280 	}
   281 
   282 void CPKIXCertChainAO::DoCancel()
   283 	{
   284 	delete iRoots;
   285 	iRoots = 0;
   286 
   287 	delete iBuilder;
   288 	iBuilder = 0;
   289 
   290 	delete iCertsFromStoreRoots;
   291 	iCertsFromStoreRoots = 0;
   292 
   293 	User::RequestComplete(iOriginalRequestStatus, KErrCancel);
   294 	}
   295 
   296 void CPKIXCertChainAO::ValidateL(CPKIXValidationResultBase& aValidationResult,
   297 								 const TTime& aValidationTime,								 
   298 								 const CArrayPtr<HBufC>* aInitialPolicies,
   299 								 TRequestStatus& aStatus)
   300 	{
   301 	aValidationResult.Reset();
   302 	iValidationResult = &aValidationResult;
   303 	iValidationTime = aValidationTime;
   304 	iInitialPolicies = aInitialPolicies;
   305 	iOriginalRequestStatus = &aStatus;
   306 	iNumberOfAddedCertificates = 0;
   307 
   308 	__ASSERT_ALWAYS(!IsActive(), User::Panic(_L("CPKICCertChainAO"), 1));
   309 
   310 	if (!iRoots)
   311 		{
   312 		// If iRoots is 0, it means that the caller gave a uid and that
   313 		// we must retrieve the trusted certificates from the different
   314 		// stores
   315 		iRoots = CPKIXChainBuilder::NewL();
   316 		iState = EAddRoots;
   317 		}
   318 	else
   319 		{
   320 		// The caller gave a set of certificates it trusts,
   321 		// so we don't have to retrieve anything from the stores
   322 		iState = EBuildChainStart;
   323 		}
   324 
   325 	aStatus = KRequestPending;
   326 	TRequestStatus *status = &iStatus;
   327 	User::RequestComplete(status, KErrNone);
   328 	SetActive();
   329 	}
   330 
   331 void CPKIXCertChainAO::CancelValidate()
   332 	{
   333 	Cancel();
   334 	}
   335 
   336 void CPKIXCertChainAO::InitParamsL()
   337 /*
   338 this function initialises signing key parameters for the certificates
   339 -only DSA needs these at present
   340 -we get the signing key, from the spki of the issuer
   341 -if it's dsa, we look for params here
   342 	-if we find them we initialise the cert with them
   343 	-otherwise, we look in the issuer's issuer
   344 		-if we don't find them there we give up.
   345 */
   346 	{
   347 	
   348 	// If the root is DSA signed, set its parameters
   349 
   350 	TInt count = iPKIXCertChain.Chain().Count();
   351 	
   352 	CX509Certificate* current = iPKIXCertChain.Chain().At(count-1);
   353 	TAlgorithmId signingAlgorithm = current->SigningAlgorithm().AsymmetricAlgorithm().Algorithm();
   354 	
   355 	if (signingAlgorithm == EDSA)
   356 		{
   357 		
   358 		const CSubjectPublicKeyInfo& key = current->PublicKey();
   359 		SetParamsL(*current, key.EncodedParams());
   360 		
   361 		}
   362 	
   363 	// Also the rest of the chain
   364 	
   365 	for (TInt i = count - 2; i >= 0; i--)
   366 		{
   367 		
   368 		current = iPKIXCertChain.Chain().At(i);
   369 		TAlgorithmId signingAlgorithm = current->SigningAlgorithm().AsymmetricAlgorithm().Algorithm();
   370 		
   371 		if (signingAlgorithm == EDSA)
   372 			{
   373 			
   374 			// Look down the chain for parameters
   375 			
   376 			for (TInt j = i+1; j < count; j++)
   377 				{
   378 				
   379 				CX509Certificate* issuer = iPKIXCertChain.Chain().At(j);
   380 				const CSubjectPublicKeyInfo& key = issuer->PublicKey();
   381 				if (key.EncodedParams() != KNullDesC8 && key.AlgorithmId() == EDSA)
   382 					{
   383 					SetParamsL(*current, key.EncodedParams());
   384 					break;
   385 					}
   386 				
   387 				}
   388 			
   389 			}
   390 		
   391 		}
   392 	}
   393 
   394 void CPKIXCertChainAO::SetParamsL(CX509Certificate& aCert, const TPtrC8& aEncodedParams)
   395 	{
   396 	TX509KeyFactory factory;
   397 	CDSAParameters* theDSAParams = factory.DSAParametersL(aEncodedParams);
   398 	CleanupStack::PushL(theDSAParams);
   399 	
   400 	CSigningKeyParameters* params = CSigningKeyParameters::NewLC();
   401 	params->SetDSAParamsL(*theDSAParams);
   402 	
   403 	aCert.SetParametersL(*params);
   404 
   405 	CleanupStack::PopAndDestroy(2, theDSAParams);
   406 	}
   407 
   408 void CPKIXCertChainAO::DoValidateL(CPKIXValidationResultBase& aValidationResult,
   409 								 const TTime& aValidationTime, 
   410 								 const CArrayPtr<HBufC>* aInitialPolicies)
   411 	{
   412 	if (!iPKIXCertChain.ChainHasRoot())
   413 		{
   414 		aValidationResult.SetError(EChainHasNoRoot, 0);
   415 		}
   416 	else
   417 		{
   418 		CPKIXValidationState* state = CPKIXValidationState::NewLC(aValidationTime, iPKIXCertChain.Chain().Count(), aInitialPolicies);
   419 		TRAPD(err, ProcessCertsL(*state, aValidationResult));
   420 		//a leave here means either:
   421 		//	-a validation error, in which case we've set the error field in result, or
   422 		//	-some other error (e.g. OOM) in which case error is still EChainHasNoRoot
   423 		if ((err != KErrNone) && ((aValidationResult.Error().iReason) == EChainHasNoRoot))
   424 			//then we left with a non-validation-related error, so leave again...
   425 			{
   426 			User::Leave(err);
   427 			}
   428 		CleanupStack::PopAndDestroy(state);
   429 		}
   430 	}
   431 
   432 // ProcessCertsL: This function validates a complete certificate 
   433 //                chain. If an error occurs in this function the function
   434 //                SetErrorAndLeaveL must be called. 
   435 // 
   436 // Note Do not use SetErrorAndLeaveL with EChainHasNoRoot (see TRAP code in 
   437 // CPKIXCertChainAO::DoValidateL )             
   438 void CPKIXCertChainAO::ProcessCertsL(CPKIXValidationState& aState,
   439 									 CPKIXValidationResultBase& aResult) const
   440 	{
   441 	TPKIXPolicyConstraint policy(aState, aResult);
   442 	TPKIXNameConstraint name(aState, aResult);
   443 	TPKIXBasicConstraint basic(aState, aResult);
   444 	TPKIXKeyUsageConstraint keyUsage(aState, aResult);
   445 	for (; aState.iPos >= 0; aState.iPos--)
   446 		{
   447 		aState.iMaxPathLength--;
   448 		if (aState.iMaxPathLength < aState.iPos)
   449 			{
   450 			aResult.SetErrorAndLeaveL(EPathTooLong, aState.iPos);
   451 			}
   452 		const CX509Certificate* current = iPKIXCertChain.Chain().At(aState.iPos);
   453 		CCertificateValidationWarnings* certWarnings = CCertificateValidationWarnings::NewLC(aState.iPos);
   454 		aResult.AppendCertificateValidationObjectL(*certWarnings);
   455 		CleanupStack::Pop(certWarnings);
   456 		CriticalExtsL(aState, *current);
   457 		CheckCriticalExtsL(aState, aResult);
   458 		CheckSignatureAndNameL(*current, aState, aResult);
   459 		//!!!!NO!!checks for revocation at this time!!
   460 		
   461 		if (!(current->ValidityPeriod().Valid(aState.iValidationTime)))
   462 			{
   463 			//validity period invalid, now check how to report this
   464 			if (iPKIXCertChain.ValidityPeriodCheckFatal())
   465 				{
   466 				aResult.SetErrorAndLeaveL(EDateOutOfRange, aState.iPos);
   467 				}
   468 			else
   469 				{
   470 				aResult.AppendWarningL(TValidationStatus(EDateOutOfRange, aState.iPos));
   471 				}
   472 			}
   473 		
   474 		policy.CheckCertPoliciesL(*current);
   475 		name.CheckNameConstraintsL(*current);
   476 		keyUsage.CheckKeyUsageL(*current);
   477 		if (aState.iPos < (iPKIXCertChain.Chain().Count() - 1))
   478 			{
   479 			basic.CheckCertSubjectTypeL(*current);
   480 			}
   481 		basic.UpdatePathLengthConstraintsL(*current);
   482 		name.UpdateNameConstraintsL(*current);
   483 		policy.UpdatePolicyConstraintsL(*current);
   484 		aState.iCriticalExts->Reset();
   485 		}
   486 	policy.FinishPolicyCheckL();
   487 	//*copy* all policies from aState.iAuthorityConstrainedPolicies into aResult.iPolicies
   488 	TInt policyCount = aState.iAuthorityConstrainedPolicies->Count();
   489 	for (TInt i = 0; i < policyCount; i ++)
   490 		{
   491 		CX509CertPolicyInfo* policyInfo = CX509CertPolicyInfo::NewLC(*(aState.iAuthorityConstrainedPolicies->At(i)));
   492 		aResult.AppendPolicyL(*policyInfo);
   493 		CleanupStack::Pop(policyInfo);
   494 		}
   495 
   496 	aResult.SetError(EValidatedOK, 0);
   497 	}
   498 
   499 void CPKIXCertChainAO::CriticalExtsL(CPKIXValidationState& aState, 
   500 									 const CX509Certificate& aCert) const
   501 	{
   502 	const CArrayPtrFlat<CX509CertExtension>& exts = aCert.Extensions();
   503 	TInt count = exts.Count();
   504 	for (TInt i = 0; i < count; i++)
   505 		{
   506 		CX509CertExtension* ext = exts.At(i);
   507 		if (ext->Critical())
   508 			{
   509 			aState.iCriticalExts->AppendL(ext);
   510 			}
   511 		}	 
   512 	}
   513 
   514 void CPKIXCertChainAO::CheckSignatureAndNameL(const CX509Certificate& aCert, CPKIXValidationState& aState, 
   515 											CPKIXValidationResultBase& aResult) const
   516 	{
   517 	TInt issuerPos = aState.iPos + 1;
   518 	if (issuerPos == iPKIXCertChain.Chain().Count())
   519 		//then it's the root
   520 		{
   521 		if (aCert.IssuerName().ExactMatchL(aCert.SubjectName()))
   522 			//then it claims to be self signed, sig must verify
   523 			{
   524 			if (!(aCert.VerifySignatureL(aCert.PublicKey().KeyData())))
   525 				{
   526 				aResult.SetErrorAndLeaveL(ESignatureInvalid, aState.iPos);
   527 				}
   528 			}
   529 		else
   530 			//we generate a warning
   531 			{
   532 			aResult.AppendWarningL(TValidationStatus(ERootCertNotSelfSigned, aState.iPos));
   533 			}
   534 		}
   535 	else
   536 		//then it isn't the root: so names must chain & sigs must verify
   537 		{
   538 		const CX509Certificate* issuer = iPKIXCertChain.Chain().At(issuerPos);
   539 		if (!(aCert.IssuerName().ExactMatchL(issuer->SubjectName())))
   540 			{
   541 			aResult.SetErrorAndLeaveL(ENamesDontChain, aState.iPos);
   542 			}
   543 		if (!(aCert.VerifySignatureL(issuer->PublicKey().KeyData())))
   544 			{
   545 			aResult.SetErrorAndLeaveL(ESignatureInvalid, aState.iPos);
   546 			}
   547 		}
   548 	}
   549 
   550 void CPKIXCertChainAO::CheckCriticalExtsL(CPKIXValidationState& aState, CPKIXValidationResultBase& aResult) const
   551 	{
   552 	TBool foundUnrecognisedCritExt;
   553 	
   554 	// retrieve the supported list of critical extensions. If a critical extension is found whose OID matches an 
   555 	// element in this set then certificate validation shall treat this as a warning instead of an error.
   556 	const RPointerArray<TDesC>& supportedCritExt = iPKIXCertChain.SupportedCriticalExtensions();
   557 	
   558 	TInt count = aState.iCriticalExts->Count();
   559 	TInt supportedCount = supportedCritExt.Count();
   560 	for (TInt i = 0; i < count; i++)
   561 		{
   562 		foundUnrecognisedCritExt = ETrue;
   563 		const CX509CertExtension* ext = aState.iCriticalExts->At(i);
   564 		const TPtrC& extName = ext->Id();
   565 		
   566 		for (TInt j = 0; j < supportedCount; ++j)
   567 			{
   568 			if (extName == *supportedCritExt[j])
   569 				{
   570 				foundUnrecognisedCritExt = EFalse;
   571 				HBufC* oid = extName.AllocLC();
   572 				aResult.AppendCriticalExtensionWarningL(*oid);
   573 				CleanupStack::Pop(oid);
   574 				break;
   575 				}
   576 			}			
   577 		
   578 		if (extName == KExtendedKeyUsage)
   579 			{
   580 			aResult.AppendWarningL(TValidationStatus(ECriticalExtendedKeyUsage, aState.iPos));
   581 			}
   582 		else if (extName == KPolicyMapping)
   583 			{
   584 			aResult.AppendWarningL(TValidationStatus(ECriticalPolicyMapping, aState.iPos));
   585 			}
   586 		else if (extName == KInhibitAnyPolicy)
   587 			{
   588 			//ignore this in the same way
   589 			}
   590 		else if (extName == KDeviceIdListConstraint)
   591 			{
   592 			aResult.AppendWarningL(TValidationStatus(ECriticalDeviceId, aState.iPos));
   593 			}
   594 		else if(extName == KSidListConstraint)
   595 			{
   596 			aResult.AppendWarningL(TValidationStatus(ECriticalSid, aState.iPos));
   597 			}
   598 		else if(extName == KVidListConstraint)
   599 			{
   600 			aResult.AppendWarningL(TValidationStatus(ECriticalVid, aState.iPos));
   601 			}
   602 		else if(extName == KCapabilitiesConstraint)
   603 			{
   604 			aResult.AppendWarningL(TValidationStatus(ECriticalCapabilities, aState.iPos));
   605 			}
   606 		
   607 		if (foundUnrecognisedCritExt)
   608 			{
   609 			aResult.SetErrorAndLeaveL(EUnrecognizedCriticalExtension, aState.iPos);
   610 			}			
   611 		
   612 		}
   613 	}