os/security/cryptoservices/certificateandkeymgmt/wtlscert/wtlscertchainao.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 "wtlscertchainao.h"
sl@0
    20
#include <asymmetric.h>
sl@0
    21
#include <bigint.h>
sl@0
    22
#include <ccertattributefilter.h>
sl@0
    23
#include <cctcertinfo.h>
sl@0
    24
sl@0
    25
CWTLSCertChainAO* CWTLSCertChainAO::NewL(RFs& aFs, 
sl@0
    26
										 CWTLSCertChain& aWTLSCertChain,
sl@0
    27
										 const CArrayPtr<CWTLSCertificate>& aRootCerts)
sl@0
    28
	{
sl@0
    29
	CWTLSCertChainAO* self = new(ELeave) CWTLSCertChainAO(aFs, aWTLSCertChain);
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
CWTLSCertChainAO* CWTLSCertChainAO::NewL(RFs& aFs, 
sl@0
    37
										 CWTLSCertChain& aWTLSCertChain,
sl@0
    38
										 const TUid aClient)
sl@0
    39
	{
sl@0
    40
	return new(ELeave) CWTLSCertChainAO(aFs, aWTLSCertChain, aClient);
sl@0
    41
	}
sl@0
    42
sl@0
    43
CWTLSCertChainAO::~CWTLSCertChainAO()
sl@0
    44
	{
sl@0
    45
	Cancel();
sl@0
    46
	delete iCertStoreManager;
sl@0
    47
	delete iFilter;
sl@0
    48
	delete iEncodedCertTemp;
sl@0
    49
	iRootSubjectClientHashList.ResetAndDestroy();
sl@0
    50
	iRootSubjectStoreHashList.Close();
sl@0
    51
	iCertInfos.Close(); //In an RMPointerArray Close deletes all elements as 
sl@0
    52
						//well as any personal allocated space
sl@0
    53
	iRootsFromStore.ResetAndDestroy();
sl@0
    54
	iRootsFromStore.Close();
sl@0
    55
	iRootsFromClient.ResetAndDestroy();
sl@0
    56
	}
sl@0
    57
sl@0
    58
CWTLSCertChainAO::CWTLSCertChainAO(RFs& aFs, 
sl@0
    59
								   CWTLSCertChain& aWTLSCertChain)
sl@0
    60
	: CActive(EPriorityNormal), iFs(aFs), iWTLSCertChain(aWTLSCertChain), iEncodedCert(NULL, 0)
sl@0
    61
	{
sl@0
    62
	CActiveScheduler::Add(this);
sl@0
    63
	}
sl@0
    64
sl@0
    65
CWTLSCertChainAO::CWTLSCertChainAO(RFs& aFs, 
sl@0
    66
								   CWTLSCertChain& aWTLSCertChain,
sl@0
    67
								   const TUid aClient)
sl@0
    68
	: CActive(0), iFs(aFs), iWTLSCertChain(aWTLSCertChain), iClient(aClient),
sl@0
    69
		iEncodedCert(NULL, 0)
sl@0
    70
	{
sl@0
    71
	CActiveScheduler::Add(this);
sl@0
    72
	}
sl@0
    73
sl@0
    74
void CWTLSCertChainAO::ConstructL(const CArrayPtr<CWTLSCertificate>& aRootCerts)
sl@0
    75
	{
sl@0
    76
	for(TInt i=0; i< aRootCerts.Count(); i++)
sl@0
    77
		{
sl@0
    78
		CWTLSCertificate* root = CWTLSCertificate::NewLC(*(aRootCerts[i]));
sl@0
    79
		User::LeaveIfError( iRootsFromClient.Append(root) );
sl@0
    80
		CleanupStack::Pop(); //root
sl@0
    81
		}
sl@0
    82
	}
sl@0
    83
sl@0
    84
void CWTLSCertChainAO::RunL()
sl@0
    85
	{
sl@0
    86
	//If any of my active objects complete with errors then we don't
sl@0
    87
	//want to proceed
sl@0
    88
	User::LeaveIfError(iStatus.Int());
sl@0
    89
sl@0
    90
	switch (iState)
sl@0
    91
		{
sl@0
    92
		case EStoreManagerInitialization:
sl@0
    93
			HandleEStoreManagerInitializationL();
sl@0
    94
			break;
sl@0
    95
sl@0
    96
		case EStoreManagerInitialized:
sl@0
    97
			HandleEStoreManagerInitializedL();
sl@0
    98
			break;
sl@0
    99
sl@0
   100
		case EGetCertHashes:
sl@0
   101
			HandleEGetCertHashesL();
sl@0
   102
			break;
sl@0
   103
sl@0
   104
		case EPruneList:
sl@0
   105
			HandleEPruneListL();
sl@0
   106
			break;
sl@0
   107
sl@0
   108
		case EPruneListDone:
sl@0
   109
			HandleEPruneListDoneL();
sl@0
   110
			break;
sl@0
   111
sl@0
   112
		case ECheckTCA:
sl@0
   113
			HandleECheckTCAL();
sl@0
   114
			break;
sl@0
   115
sl@0
   116
		case EIsChainSelfSigned:
sl@0
   117
			HandleEIsChainSelfSignedL();
sl@0
   118
			break;
sl@0
   119
sl@0
   120
		case ERetrieveRoots:
sl@0
   121
			HandleERetrieveRootsL();
sl@0
   122
			break;
sl@0
   123
sl@0
   124
		case EAddRootToList:
sl@0
   125
			HandleEAddRootToListL();
sl@0
   126
			break;
sl@0
   127
sl@0
   128
		case EFindRoot:
sl@0
   129
			HandleEFindRootL();
sl@0
   130
			break;
sl@0
   131
sl@0
   132
		case EValidateEnd:
sl@0
   133
			HandleEValidateEndL();
sl@0
   134
			break;
sl@0
   135
		
sl@0
   136
		default:
sl@0
   137
			__ASSERT_DEBUG(EFalse, User::Panic(_L("CWTLSCertChainAO"), 1));
sl@0
   138
			User::Leave(KErrArgument);
sl@0
   139
			break;
sl@0
   140
		}
sl@0
   141
	}
sl@0
   142
sl@0
   143
TInt CWTLSCertChainAO::RunError(TInt aError)
sl@0
   144
	{
sl@0
   145
	User::RequestComplete(iOriginalRequestStatus, aError);
sl@0
   146
sl@0
   147
	delete iCertStoreManager;
sl@0
   148
	iCertStoreManager = 0;
sl@0
   149
sl@0
   150
	return 0;
sl@0
   151
	}
sl@0
   152
sl@0
   153
void CWTLSCertChainAO::DoCancel()
sl@0
   154
	{
sl@0
   155
	TRequestStatus* status = &iStatus;
sl@0
   156
	User::RequestComplete(status, KErrCancel);
sl@0
   157
	if (iOriginalRequestStatus)
sl@0
   158
		{
sl@0
   159
		User::RequestComplete(iOriginalRequestStatus, KErrCancel);
sl@0
   160
		}
sl@0
   161
	}
sl@0
   162
sl@0
   163
void CWTLSCertChainAO::Validate(CWTLSValidationResult& aValidationResult,
sl@0
   164
								const TTime& aValidationTime,								 
sl@0
   165
								TRequestStatus& aStatus)
sl@0
   166
	{
sl@0
   167
	iValidationResult = &aValidationResult;
sl@0
   168
	iValidationResult->Reset();
sl@0
   169
	iValidationTime = &aValidationTime;
sl@0
   170
	iOriginalRequestStatus = &aStatus;
sl@0
   171
	aStatus = KRequestPending;
sl@0
   172
sl@0
   173
	__ASSERT_DEBUG(!IsActive(), User::Panic(_L("CWTLSCertChainAO"), 1));
sl@0
   174
	__ASSERT_DEBUG(!iCertStoreManager, User::Panic(_L("CWTLSCertChainAO"), 1));
sl@0
   175
	
sl@0
   176
	iState = EStoreManagerInitialization;
sl@0
   177
	TRequestStatus *status = &iStatus;
sl@0
   178
	User::RequestComplete(status, KErrNone);
sl@0
   179
	SetActive();
sl@0
   180
	}
sl@0
   181
sl@0
   182
TBool CWTLSCertChainAO::CheckSignatureAndNameL(const CWTLSCertificate& aCert, 
sl@0
   183
											   CWTLSValidationResult& aResult,
sl@0
   184
											   TInt aPos) const
sl@0
   185
	{
sl@0
   186
	TInt issuerPos = aPos + 1;
sl@0
   187
	TBool res = EFalse;
sl@0
   188
	if (issuerPos == iWTLSCertChain.iChain->Count())
sl@0
   189
		//then it's the root
sl@0
   190
		{
sl@0
   191
		if (aCert.IssuerName().ExactMatchL(aCert.SubjectName()))
sl@0
   192
			//then it claims to be self signed, sig must verify
sl@0
   193
			{
sl@0
   194
			if (aCert.VerifySignatureL(aCert.PublicKey().KeyData()))
sl@0
   195
				{
sl@0
   196
				res = ETrue;
sl@0
   197
				}
sl@0
   198
			else 
sl@0
   199
				{
sl@0
   200
				aResult.SetError(ESignatureInvalid, aPos);
sl@0
   201
				}
sl@0
   202
			}
sl@0
   203
		else
sl@0
   204
			{
sl@0
   205
			aResult.AppendWarningL(TWTLSValidationStatus(ERootCertNotSelfSigned, aPos));
sl@0
   206
			res = ETrue; //if its a warning we continue the validation process with the 
sl@0
   207
						//warning duly noted so we can check for further warn/errors
sl@0
   208
			}
sl@0
   209
		}
sl@0
   210
	else
sl@0
   211
		//then it isn't the root: so names must chain & sigs must verify
sl@0
   212
		{
sl@0
   213
		const CWTLSCertificate* issuer = iWTLSCertChain.iChain->At(issuerPos);
sl@0
   214
		TBool subject = EFalse;
sl@0
   215
		TBool signature = EFalse;
sl@0
   216
		subject = aCert.IssuerName().ExactMatchL(issuer->SubjectName());
sl@0
   217
		if( !subject ) 
sl@0
   218
			{
sl@0
   219
			aResult.SetError(ENamesDontChain, aPos);
sl@0
   220
			return EFalse;
sl@0
   221
			}
sl@0
   222
		signature = aCert.VerifySignatureL(issuer->PublicKey().KeyData());
sl@0
   223
		if( !signature )
sl@0
   224
			{
sl@0
   225
			aResult.SetError(ESignatureInvalid, aPos);
sl@0
   226
			return EFalse;
sl@0
   227
			}
sl@0
   228
		res = subject && signature;
sl@0
   229
		}
sl@0
   230
	return res;
sl@0
   231
	}
sl@0
   232
sl@0
   233
TBool CWTLSCertChainAO::CheckValidityPeriod(const CWTLSCertificate& aCert,
sl@0
   234
											CWTLSValidationResult& aResult, 
sl@0
   235
											const TTime aTime,
sl@0
   236
											TInt aPos) const
sl@0
   237
	{
sl@0
   238
	if (aCert.ValidityPeriod().Valid(aTime))
sl@0
   239
		{
sl@0
   240
		return ETrue;
sl@0
   241
		}
sl@0
   242
	aResult.SetError(EDateOutOfRange, aPos);
sl@0
   243
	return EFalse;
sl@0
   244
	}
sl@0
   245
sl@0
   246
void CWTLSCertChainAO::HandleEStoreManagerInitializationL()
sl@0
   247
	{
sl@0
   248
	iFilter = CCertAttributeFilter::NewL();
sl@0
   249
	iFilter->SetFormat(EWTLSCertificate);
sl@0
   250
	iFilter->SetUid(iClient);
sl@0
   251
	iFilter->SetOwnerType(ECACertificate);
sl@0
   252
sl@0
   253
	iCertStoreManager = CUnifiedCertStore::NewL(iFs, EFalse);
sl@0
   254
	iCertStoreManager->Initialize(iStatus);
sl@0
   255
sl@0
   256
	iState = EStoreManagerInitialized;
sl@0
   257
	SetActive();
sl@0
   258
	}
sl@0
   259
sl@0
   260
void CWTLSCertChainAO::HandleEStoreManagerInitializedL()
sl@0
   261
	{
sl@0
   262
	iCertStoreManager->List(iCertInfos, *iFilter, iStatus);
sl@0
   263
sl@0
   264
	iState = EGetCertHashes;
sl@0
   265
	SetActive();
sl@0
   266
	}
sl@0
   267
sl@0
   268
void CWTLSCertChainAO::HandleEGetCertHashesL()
sl@0
   269
	{
sl@0
   270
	for(TInt i=0; i<iRootsFromClient.Count(); i++)
sl@0
   271
		{
sl@0
   272
		HBufC8* hash = &GeneratePublicKeyHashL( *(iRootsFromClient[i]));
sl@0
   273
		CleanupStack::PushL(hash);
sl@0
   274
		User::LeaveIfError( iRootSubjectClientHashList.Append(hash) );
sl@0
   275
		CleanupStack::Pop(); //hash
sl@0
   276
		}
sl@0
   277
	for(TInt j=0; j < iCertInfos.Count(); j++ )
sl@0
   278
		{
sl@0
   279
		User::LeaveIfError( iRootSubjectStoreHashList.Append( &((iCertInfos[j])->SubjectKeyId()) ) );
sl@0
   280
		}
sl@0
   281
sl@0
   282
	iPruned = EFalse;	
sl@0
   283
	iPrunedChainLength = iWTLSCertChain.iChain->Count();
sl@0
   284
	iIndex = -1;
sl@0
   285
sl@0
   286
	iState = EPruneList;
sl@0
   287
	TRequestStatus* status = &iStatus;
sl@0
   288
	User::RequestComplete(status, KErrNone);
sl@0
   289
	SetActive();
sl@0
   290
	}
sl@0
   291
sl@0
   292
/* Walk through the canadiate list and compare the hash of the subjects with the previously
sl@0
   293
 * computed subject hash of certs from the CertStore and certs supplied by the client
sl@0
   294
 */
sl@0
   295
void CWTLSCertChainAO::HandleEPruneListL()
sl@0
   296
	{
sl@0
   297
	iIndex++;
sl@0
   298
	if(iIndex < iWTLSCertChain.iChain->Count() )
sl@0
   299
		{
sl@0
   300
		CWTLSCertificate* cert = iWTLSCertChain.iChain->At(iIndex);
sl@0
   301
		HBufC8* hash = &GeneratePublicKeyHashL(*cert);
sl@0
   302
		CleanupStack::PushL(hash);
sl@0
   303
sl@0
   304
		for(TInt i=0; i < iRootSubjectClientHashList.Count(); i++)
sl@0
   305
			{
sl@0
   306
			if( (iRootSubjectClientHashList[i])->Compare(*hash) == 0 )
sl@0
   307
				{
sl@0
   308
				iPrunedChainLength = iIndex;
sl@0
   309
				iPruned = ETrue;
sl@0
   310
				break;
sl@0
   311
				}
sl@0
   312
			}
sl@0
   313
		if(!iPruned)
sl@0
   314
			{
sl@0
   315
			for(TInt j=0; j<iRootSubjectStoreHashList.Count(); j++) 
sl@0
   316
				{
sl@0
   317
				if( (iRootSubjectStoreHashList[j])->Compare(*hash) == 0 )
sl@0
   318
					{
sl@0
   319
					iPrunedChainLength = iIndex;
sl@0
   320
					iPruned = ETrue;
sl@0
   321
					break;
sl@0
   322
					}
sl@0
   323
				}
sl@0
   324
			}
sl@0
   325
		CleanupStack::PopAndDestroy(hash);
sl@0
   326
		if(iPruned)
sl@0
   327
			{
sl@0
   328
			iState = EPruneListDone;
sl@0
   329
			}
sl@0
   330
		else 
sl@0
   331
			{
sl@0
   332
			iState = EPruneList;
sl@0
   333
			}
sl@0
   334
		}
sl@0
   335
	else
sl@0
   336
		{
sl@0
   337
		iState = EPruneListDone;
sl@0
   338
		}
sl@0
   339
	TRequestStatus* status = &iStatus;
sl@0
   340
	User::RequestComplete(status, KErrNone);
sl@0
   341
	SetActive();
sl@0
   342
	}
sl@0
   343
sl@0
   344
void CWTLSCertChainAO::HandleEPruneListDoneL()
sl@0
   345
	{
sl@0
   346
	if(iPruned) 
sl@0
   347
		{
sl@0
   348
		TInt count = iWTLSCertChain.iChain->Count();
sl@0
   349
		for( TInt i=count - 1; i > iPrunedChainLength; i-- )
sl@0
   350
			{
sl@0
   351
			delete iWTLSCertChain.iChain->At(i);
sl@0
   352
			iWTLSCertChain.iChain->Delete(i);
sl@0
   353
			}
sl@0
   354
		iWTLSCertChain.iChain->Compress();
sl@0
   355
		}
sl@0
   356
	iState = ECheckTCA;
sl@0
   357
	TRequestStatus* status = &iStatus;
sl@0
   358
	User::RequestComplete(status, KErrNone);
sl@0
   359
	SetActive();
sl@0
   360
	}
sl@0
   361
sl@0
   362
//checks to see if each certificate in a chain has the authority to sign other certificates
sl@0
   363
void CWTLSCertChainAO::HandleECheckTCAL()
sl@0
   364
	{
sl@0
   365
	TBool validChain = ETrue;
sl@0
   366
	for( TInt i = 1; i < iWTLSCertChain.iChain->Count(); i++ ) 
sl@0
   367
		//all intermediate certs (ie not EE certs and not self signed) need
sl@0
   368
		// to have a field T=ca indicating that they can sign other certs
sl@0
   369
		{
sl@0
   370
		if( (iWTLSCertChain.iChain)->At(i)->IsTCAL() == EFalse && 
sl@0
   371
			(iWTLSCertChain.iChain)->At(i)->IsSelfSignedL() == EFalse ) 
sl@0
   372
			{
sl@0
   373
			iValidationResult->SetError(ENotCACert, i);
sl@0
   374
			User::RequestComplete(iOriginalRequestStatus, KErrNone);
sl@0
   375
			validChain = EFalse;
sl@0
   376
			break;
sl@0
   377
			}
sl@0
   378
		}
sl@0
   379
	if(validChain && iPruned) 
sl@0
   380
		{
sl@0
   381
		//if we've pruned the list and the chain we have is valid,
sl@0
   382
		//then our chain already has a root that we trust.
sl@0
   383
		//therefore there is no need to retrieve one :)
sl@0
   384
		//therefore goto validation
sl@0
   385
		iState = EValidateEnd;
sl@0
   386
		TRequestStatus *status = &iStatus;
sl@0
   387
		User::RequestComplete(status, KErrNone);
sl@0
   388
		SetActive();
sl@0
   389
		}
sl@0
   390
	else if(validChain) // ie && !iPruned
sl@0
   391
		{
sl@0
   392
		//if we haven't pruned but chain is valid then we're back a square one.
sl@0
   393
		iState = EIsChainSelfSigned;
sl@0
   394
		TRequestStatus *status = &iStatus;
sl@0
   395
		User::RequestComplete(status, KErrNone);
sl@0
   396
		SetActive();
sl@0
   397
		}
sl@0
   398
	}
sl@0
   399
sl@0
   400
void CWTLSCertChainAO::HandleEIsChainSelfSignedL()
sl@0
   401
	{
sl@0
   402
sl@0
   403
	TInt last = iWTLSCertChain.iChain->Count() - 1;
sl@0
   404
	if( iWTLSCertChain.iChain->At(last)->IsSelfSignedL() )
sl@0
   405
		{
sl@0
   406
		//if chained is self signed, and no earlier cert in the sequence was trusted
sl@0
   407
		//then this is going to fail validation
sl@0
   408
		//This is just an optimisation to avoid retrieving all the roots from the store
sl@0
   409
sl@0
   410
		iValidationResult->SetError(EChainHasNoRoot, last);
sl@0
   411
		User::RequestComplete(iOriginalRequestStatus, KErrNone);
sl@0
   412
		}
sl@0
   413
	else 
sl@0
   414
		{
sl@0
   415
		//standard chain -> need to find the appropriate trusted root for chain if it exists
sl@0
   416
		iState = ERetrieveRoots;
sl@0
   417
		iIndex = -1;
sl@0
   418
		TRequestStatus* status = &iStatus;
sl@0
   419
		User::RequestComplete(status, KErrNone);
sl@0
   420
		SetActive();
sl@0
   421
		}
sl@0
   422
	}
sl@0
   423
sl@0
   424
void CWTLSCertChainAO::HandleERetrieveRootsL()
sl@0
   425
	{
sl@0
   426
	iIndex++;	
sl@0
   427
	if(iIndex < iCertInfos.Count() )
sl@0
   428
		{
sl@0
   429
		if( iEncodedCertTemp != NULL ) 
sl@0
   430
			{
sl@0
   431
			delete iEncodedCertTemp;
sl@0
   432
			}
sl@0
   433
		iEncodedCertTemp = HBufC8::NewMaxL( (iCertInfos[iIndex])->Size() );
sl@0
   434
		iEncodedCert.Set( iEncodedCertTemp->Des() );
sl@0
   435
		iCertStoreManager->Retrieve( *(iCertInfos[iIndex]), iEncodedCert, iStatus );
sl@0
   436
		iState = EAddRootToList;
sl@0
   437
		}
sl@0
   438
	else 
sl@0
   439
		{
sl@0
   440
		iState = EFindRoot;
sl@0
   441
		TRequestStatus* status = &iStatus;
sl@0
   442
		User::RequestComplete(status, KErrNone);
sl@0
   443
		}	
sl@0
   444
	SetActive();
sl@0
   445
	}
sl@0
   446
sl@0
   447
void CWTLSCertChainAO::HandleEAddRootToListL()
sl@0
   448
	{
sl@0
   449
	//are we guarenteed that a cert from the store is a valid WTLScert?
sl@0
   450
	//ie is this going to leave for reasons other than OOM?
sl@0
   451
	CWTLSCertificate *cert = CWTLSCertificate::NewL( iEncodedCert );
sl@0
   452
	User::LeaveIfError( iRootsFromStore.Append(cert) );
sl@0
   453
sl@0
   454
	iState = ERetrieveRoots;
sl@0
   455
	TRequestStatus* status = &iStatus;
sl@0
   456
	User::RequestComplete(status, KErrNone);
sl@0
   457
	SetActive();
sl@0
   458
	}
sl@0
   459
sl@0
   460
void CWTLSCertChainAO::HandleEFindRootL()
sl@0
   461
	{
sl@0
   462
	TInt last = iWTLSCertChain.iChain->Count() - 1;
sl@0
   463
	const CWTLSName* issuerName = &(iWTLSCertChain.iChain->At(last)->IssuerName());
sl@0
   464
sl@0
   465
	iFoundRoot = EFalse;
sl@0
   466
	for(TInt i=0; i<iRootsFromClient.Count(); i++) 
sl@0
   467
		{
sl@0
   468
		if( issuerName->ExactMatchL( (iRootsFromClient[i])->SubjectName() ) )
sl@0
   469
			{
sl@0
   470
			iFoundRoot = ETrue;
sl@0
   471
			CWTLSCertificate* cert = CWTLSCertificate::NewLC( *(iRootsFromClient[i]) );
sl@0
   472
			iWTLSCertChain.iChain->AppendL( cert ); 
sl@0
   473
			CleanupStack::Pop(cert);
sl@0
   474
			break;
sl@0
   475
			}
sl@0
   476
		}
sl@0
   477
	if(!iFoundRoot) 
sl@0
   478
		{
sl@0
   479
		for(TInt j=0; j<iRootsFromStore.Count(); j++)
sl@0
   480
			{
sl@0
   481
			if( issuerName->ExactMatchL( (iRootsFromStore[j])->SubjectName() ) )
sl@0
   482
				{
sl@0
   483
				iFoundRoot = ETrue;
sl@0
   484
				CWTLSCertificate* cert = CWTLSCertificate::NewLC( *(iRootsFromStore[j]) );
sl@0
   485
				iWTLSCertChain.iChain->AppendL( cert );
sl@0
   486
				CleanupStack::Pop(cert);
sl@0
   487
				break;
sl@0
   488
				}
sl@0
   489
			}
sl@0
   490
		}
sl@0
   491
	if(!iFoundRoot)
sl@0
   492
		{
sl@0
   493
		iValidationResult->SetError(EChainHasNoRoot, last);
sl@0
   494
		User::RequestComplete(iOriginalRequestStatus, KErrNone);
sl@0
   495
		}
sl@0
   496
	else
sl@0
   497
		{
sl@0
   498
		iState = EValidateEnd;
sl@0
   499
		TRequestStatus* status = &iStatus;
sl@0
   500
		User::RequestComplete(status, KErrNone);
sl@0
   501
		SetActive();
sl@0
   502
		}
sl@0
   503
	}
sl@0
   504
sl@0
   505
void CWTLSCertChainAO::HandleEValidateEndL()
sl@0
   506
	{
sl@0
   507
	TInt i = iWTLSCertChain.iChain->Count() -1;//we can guarantee that chain has at least 1 cert
sl@0
   508
	for (; i >= 0; i--)
sl@0
   509
		{
sl@0
   510
		const CWTLSCertificate* current = iWTLSCertChain.iChain->At(i);
sl@0
   511
		if ((!CheckSignatureAndNameL(*current, *iValidationResult, i))	||
sl@0
   512
			(!CheckValidityPeriod(*current, *iValidationResult, *iValidationTime, i)))
sl@0
   513
			{
sl@0
   514
			//these functions set the error internally if there is one
sl@0
   515
			break;
sl@0
   516
			}
sl@0
   517
		}		
sl@0
   518
sl@0
   519
	User::RequestComplete(iOriginalRequestStatus, KErrNone);
sl@0
   520
	}
sl@0
   521
sl@0
   522
HBufC8& CWTLSCertChainAO::GeneratePublicKeyHashL(const CWTLSCertificate& aCert) const
sl@0
   523
	{
sl@0
   524
	TWTLSKeyFactory keyFactory;
sl@0
   525
	CRSAPublicKey* key = keyFactory.RSAPublicKeyL( aCert.PublicKey().KeyData() );
sl@0
   526
	CleanupStack::PushL(key);
sl@0
   527
	HBufC8* modulusBuffer = key->N().BufferLC();
sl@0
   528
	CSHA1* sha1 = CSHA1::NewL();
sl@0
   529
	CleanupStack::PushL(sha1);
sl@0
   530
	TPtrC8 hash = sha1->Final(*modulusBuffer);
sl@0
   531
	HBufC8* permHash = hash.AllocL();
sl@0
   532
	CleanupStack::PopAndDestroy(3); //sha1, modulusBuffer, key
sl@0
   533
	return *permHash;
sl@0
   534
	}
sl@0
   535