cryptoservices/certificateandkeymgmt/pkixcertbase/pkixcertchainao.cpp
changeset 0 2c201484c85f
child 8 35751d3474b7
equal deleted inserted replaced
-1:000000000000 0:2c201484c85f
       
     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 	}