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