os/security/cryptoservices/certificateandkeymgmt/wtlscert/wtlscertchainao.cpp
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/security/cryptoservices/certificateandkeymgmt/wtlscert/wtlscertchainao.cpp	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,535 @@
     1.4 +/*
     1.5 +* Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies).
     1.6 +* All rights reserved.
     1.7 +* This component and the accompanying materials are made available
     1.8 +* under the terms of the License "Eclipse Public License v1.0"
     1.9 +* which accompanies this distribution, and is available
    1.10 +* at the URL "http://www.eclipse.org/legal/epl-v10.html".
    1.11 +*
    1.12 +* Initial Contributors:
    1.13 +* Nokia Corporation - initial contribution.
    1.14 +*
    1.15 +* Contributors:
    1.16 +*
    1.17 +* Description: 
    1.18 +*
    1.19 +*/
    1.20 +
    1.21 +
    1.22 +#include "wtlscertchainao.h"
    1.23 +#include <asymmetric.h>
    1.24 +#include <bigint.h>
    1.25 +#include <ccertattributefilter.h>
    1.26 +#include <cctcertinfo.h>
    1.27 +
    1.28 +CWTLSCertChainAO* CWTLSCertChainAO::NewL(RFs& aFs, 
    1.29 +										 CWTLSCertChain& aWTLSCertChain,
    1.30 +										 const CArrayPtr<CWTLSCertificate>& aRootCerts)
    1.31 +	{
    1.32 +	CWTLSCertChainAO* self = new(ELeave) CWTLSCertChainAO(aFs, aWTLSCertChain);
    1.33 +	CleanupStack::PushL(self);
    1.34 +	self->ConstructL(aRootCerts);
    1.35 +	CleanupStack::Pop(self);
    1.36 +	return self;
    1.37 +	}
    1.38 +
    1.39 +CWTLSCertChainAO* CWTLSCertChainAO::NewL(RFs& aFs, 
    1.40 +										 CWTLSCertChain& aWTLSCertChain,
    1.41 +										 const TUid aClient)
    1.42 +	{
    1.43 +	return new(ELeave) CWTLSCertChainAO(aFs, aWTLSCertChain, aClient);
    1.44 +	}
    1.45 +
    1.46 +CWTLSCertChainAO::~CWTLSCertChainAO()
    1.47 +	{
    1.48 +	Cancel();
    1.49 +	delete iCertStoreManager;
    1.50 +	delete iFilter;
    1.51 +	delete iEncodedCertTemp;
    1.52 +	iRootSubjectClientHashList.ResetAndDestroy();
    1.53 +	iRootSubjectStoreHashList.Close();
    1.54 +	iCertInfos.Close(); //In an RMPointerArray Close deletes all elements as 
    1.55 +						//well as any personal allocated space
    1.56 +	iRootsFromStore.ResetAndDestroy();
    1.57 +	iRootsFromStore.Close();
    1.58 +	iRootsFromClient.ResetAndDestroy();
    1.59 +	}
    1.60 +
    1.61 +CWTLSCertChainAO::CWTLSCertChainAO(RFs& aFs, 
    1.62 +								   CWTLSCertChain& aWTLSCertChain)
    1.63 +	: CActive(EPriorityNormal), iFs(aFs), iWTLSCertChain(aWTLSCertChain), iEncodedCert(NULL, 0)
    1.64 +	{
    1.65 +	CActiveScheduler::Add(this);
    1.66 +	}
    1.67 +
    1.68 +CWTLSCertChainAO::CWTLSCertChainAO(RFs& aFs, 
    1.69 +								   CWTLSCertChain& aWTLSCertChain,
    1.70 +								   const TUid aClient)
    1.71 +	: CActive(0), iFs(aFs), iWTLSCertChain(aWTLSCertChain), iClient(aClient),
    1.72 +		iEncodedCert(NULL, 0)
    1.73 +	{
    1.74 +	CActiveScheduler::Add(this);
    1.75 +	}
    1.76 +
    1.77 +void CWTLSCertChainAO::ConstructL(const CArrayPtr<CWTLSCertificate>& aRootCerts)
    1.78 +	{
    1.79 +	for(TInt i=0; i< aRootCerts.Count(); i++)
    1.80 +		{
    1.81 +		CWTLSCertificate* root = CWTLSCertificate::NewLC(*(aRootCerts[i]));
    1.82 +		User::LeaveIfError( iRootsFromClient.Append(root) );
    1.83 +		CleanupStack::Pop(); //root
    1.84 +		}
    1.85 +	}
    1.86 +
    1.87 +void CWTLSCertChainAO::RunL()
    1.88 +	{
    1.89 +	//If any of my active objects complete with errors then we don't
    1.90 +	//want to proceed
    1.91 +	User::LeaveIfError(iStatus.Int());
    1.92 +
    1.93 +	switch (iState)
    1.94 +		{
    1.95 +		case EStoreManagerInitialization:
    1.96 +			HandleEStoreManagerInitializationL();
    1.97 +			break;
    1.98 +
    1.99 +		case EStoreManagerInitialized:
   1.100 +			HandleEStoreManagerInitializedL();
   1.101 +			break;
   1.102 +
   1.103 +		case EGetCertHashes:
   1.104 +			HandleEGetCertHashesL();
   1.105 +			break;
   1.106 +
   1.107 +		case EPruneList:
   1.108 +			HandleEPruneListL();
   1.109 +			break;
   1.110 +
   1.111 +		case EPruneListDone:
   1.112 +			HandleEPruneListDoneL();
   1.113 +			break;
   1.114 +
   1.115 +		case ECheckTCA:
   1.116 +			HandleECheckTCAL();
   1.117 +			break;
   1.118 +
   1.119 +		case EIsChainSelfSigned:
   1.120 +			HandleEIsChainSelfSignedL();
   1.121 +			break;
   1.122 +
   1.123 +		case ERetrieveRoots:
   1.124 +			HandleERetrieveRootsL();
   1.125 +			break;
   1.126 +
   1.127 +		case EAddRootToList:
   1.128 +			HandleEAddRootToListL();
   1.129 +			break;
   1.130 +
   1.131 +		case EFindRoot:
   1.132 +			HandleEFindRootL();
   1.133 +			break;
   1.134 +
   1.135 +		case EValidateEnd:
   1.136 +			HandleEValidateEndL();
   1.137 +			break;
   1.138 +		
   1.139 +		default:
   1.140 +			__ASSERT_DEBUG(EFalse, User::Panic(_L("CWTLSCertChainAO"), 1));
   1.141 +			User::Leave(KErrArgument);
   1.142 +			break;
   1.143 +		}
   1.144 +	}
   1.145 +
   1.146 +TInt CWTLSCertChainAO::RunError(TInt aError)
   1.147 +	{
   1.148 +	User::RequestComplete(iOriginalRequestStatus, aError);
   1.149 +
   1.150 +	delete iCertStoreManager;
   1.151 +	iCertStoreManager = 0;
   1.152 +
   1.153 +	return 0;
   1.154 +	}
   1.155 +
   1.156 +void CWTLSCertChainAO::DoCancel()
   1.157 +	{
   1.158 +	TRequestStatus* status = &iStatus;
   1.159 +	User::RequestComplete(status, KErrCancel);
   1.160 +	if (iOriginalRequestStatus)
   1.161 +		{
   1.162 +		User::RequestComplete(iOriginalRequestStatus, KErrCancel);
   1.163 +		}
   1.164 +	}
   1.165 +
   1.166 +void CWTLSCertChainAO::Validate(CWTLSValidationResult& aValidationResult,
   1.167 +								const TTime& aValidationTime,								 
   1.168 +								TRequestStatus& aStatus)
   1.169 +	{
   1.170 +	iValidationResult = &aValidationResult;
   1.171 +	iValidationResult->Reset();
   1.172 +	iValidationTime = &aValidationTime;
   1.173 +	iOriginalRequestStatus = &aStatus;
   1.174 +	aStatus = KRequestPending;
   1.175 +
   1.176 +	__ASSERT_DEBUG(!IsActive(), User::Panic(_L("CWTLSCertChainAO"), 1));
   1.177 +	__ASSERT_DEBUG(!iCertStoreManager, User::Panic(_L("CWTLSCertChainAO"), 1));
   1.178 +	
   1.179 +	iState = EStoreManagerInitialization;
   1.180 +	TRequestStatus *status = &iStatus;
   1.181 +	User::RequestComplete(status, KErrNone);
   1.182 +	SetActive();
   1.183 +	}
   1.184 +
   1.185 +TBool CWTLSCertChainAO::CheckSignatureAndNameL(const CWTLSCertificate& aCert, 
   1.186 +											   CWTLSValidationResult& aResult,
   1.187 +											   TInt aPos) const
   1.188 +	{
   1.189 +	TInt issuerPos = aPos + 1;
   1.190 +	TBool res = EFalse;
   1.191 +	if (issuerPos == iWTLSCertChain.iChain->Count())
   1.192 +		//then it's the root
   1.193 +		{
   1.194 +		if (aCert.IssuerName().ExactMatchL(aCert.SubjectName()))
   1.195 +			//then it claims to be self signed, sig must verify
   1.196 +			{
   1.197 +			if (aCert.VerifySignatureL(aCert.PublicKey().KeyData()))
   1.198 +				{
   1.199 +				res = ETrue;
   1.200 +				}
   1.201 +			else 
   1.202 +				{
   1.203 +				aResult.SetError(ESignatureInvalid, aPos);
   1.204 +				}
   1.205 +			}
   1.206 +		else
   1.207 +			{
   1.208 +			aResult.AppendWarningL(TWTLSValidationStatus(ERootCertNotSelfSigned, aPos));
   1.209 +			res = ETrue; //if its a warning we continue the validation process with the 
   1.210 +						//warning duly noted so we can check for further warn/errors
   1.211 +			}
   1.212 +		}
   1.213 +	else
   1.214 +		//then it isn't the root: so names must chain & sigs must verify
   1.215 +		{
   1.216 +		const CWTLSCertificate* issuer = iWTLSCertChain.iChain->At(issuerPos);
   1.217 +		TBool subject = EFalse;
   1.218 +		TBool signature = EFalse;
   1.219 +		subject = aCert.IssuerName().ExactMatchL(issuer->SubjectName());
   1.220 +		if( !subject ) 
   1.221 +			{
   1.222 +			aResult.SetError(ENamesDontChain, aPos);
   1.223 +			return EFalse;
   1.224 +			}
   1.225 +		signature = aCert.VerifySignatureL(issuer->PublicKey().KeyData());
   1.226 +		if( !signature )
   1.227 +			{
   1.228 +			aResult.SetError(ESignatureInvalid, aPos);
   1.229 +			return EFalse;
   1.230 +			}
   1.231 +		res = subject && signature;
   1.232 +		}
   1.233 +	return res;
   1.234 +	}
   1.235 +
   1.236 +TBool CWTLSCertChainAO::CheckValidityPeriod(const CWTLSCertificate& aCert,
   1.237 +											CWTLSValidationResult& aResult, 
   1.238 +											const TTime aTime,
   1.239 +											TInt aPos) const
   1.240 +	{
   1.241 +	if (aCert.ValidityPeriod().Valid(aTime))
   1.242 +		{
   1.243 +		return ETrue;
   1.244 +		}
   1.245 +	aResult.SetError(EDateOutOfRange, aPos);
   1.246 +	return EFalse;
   1.247 +	}
   1.248 +
   1.249 +void CWTLSCertChainAO::HandleEStoreManagerInitializationL()
   1.250 +	{
   1.251 +	iFilter = CCertAttributeFilter::NewL();
   1.252 +	iFilter->SetFormat(EWTLSCertificate);
   1.253 +	iFilter->SetUid(iClient);
   1.254 +	iFilter->SetOwnerType(ECACertificate);
   1.255 +
   1.256 +	iCertStoreManager = CUnifiedCertStore::NewL(iFs, EFalse);
   1.257 +	iCertStoreManager->Initialize(iStatus);
   1.258 +
   1.259 +	iState = EStoreManagerInitialized;
   1.260 +	SetActive();
   1.261 +	}
   1.262 +
   1.263 +void CWTLSCertChainAO::HandleEStoreManagerInitializedL()
   1.264 +	{
   1.265 +	iCertStoreManager->List(iCertInfos, *iFilter, iStatus);
   1.266 +
   1.267 +	iState = EGetCertHashes;
   1.268 +	SetActive();
   1.269 +	}
   1.270 +
   1.271 +void CWTLSCertChainAO::HandleEGetCertHashesL()
   1.272 +	{
   1.273 +	for(TInt i=0; i<iRootsFromClient.Count(); i++)
   1.274 +		{
   1.275 +		HBufC8* hash = &GeneratePublicKeyHashL( *(iRootsFromClient[i]));
   1.276 +		CleanupStack::PushL(hash);
   1.277 +		User::LeaveIfError( iRootSubjectClientHashList.Append(hash) );
   1.278 +		CleanupStack::Pop(); //hash
   1.279 +		}
   1.280 +	for(TInt j=0; j < iCertInfos.Count(); j++ )
   1.281 +		{
   1.282 +		User::LeaveIfError( iRootSubjectStoreHashList.Append( &((iCertInfos[j])->SubjectKeyId()) ) );
   1.283 +		}
   1.284 +
   1.285 +	iPruned = EFalse;	
   1.286 +	iPrunedChainLength = iWTLSCertChain.iChain->Count();
   1.287 +	iIndex = -1;
   1.288 +
   1.289 +	iState = EPruneList;
   1.290 +	TRequestStatus* status = &iStatus;
   1.291 +	User::RequestComplete(status, KErrNone);
   1.292 +	SetActive();
   1.293 +	}
   1.294 +
   1.295 +/* Walk through the canadiate list and compare the hash of the subjects with the previously
   1.296 + * computed subject hash of certs from the CertStore and certs supplied by the client
   1.297 + */
   1.298 +void CWTLSCertChainAO::HandleEPruneListL()
   1.299 +	{
   1.300 +	iIndex++;
   1.301 +	if(iIndex < iWTLSCertChain.iChain->Count() )
   1.302 +		{
   1.303 +		CWTLSCertificate* cert = iWTLSCertChain.iChain->At(iIndex);
   1.304 +		HBufC8* hash = &GeneratePublicKeyHashL(*cert);
   1.305 +		CleanupStack::PushL(hash);
   1.306 +
   1.307 +		for(TInt i=0; i < iRootSubjectClientHashList.Count(); i++)
   1.308 +			{
   1.309 +			if( (iRootSubjectClientHashList[i])->Compare(*hash) == 0 )
   1.310 +				{
   1.311 +				iPrunedChainLength = iIndex;
   1.312 +				iPruned = ETrue;
   1.313 +				break;
   1.314 +				}
   1.315 +			}
   1.316 +		if(!iPruned)
   1.317 +			{
   1.318 +			for(TInt j=0; j<iRootSubjectStoreHashList.Count(); j++) 
   1.319 +				{
   1.320 +				if( (iRootSubjectStoreHashList[j])->Compare(*hash) == 0 )
   1.321 +					{
   1.322 +					iPrunedChainLength = iIndex;
   1.323 +					iPruned = ETrue;
   1.324 +					break;
   1.325 +					}
   1.326 +				}
   1.327 +			}
   1.328 +		CleanupStack::PopAndDestroy(hash);
   1.329 +		if(iPruned)
   1.330 +			{
   1.331 +			iState = EPruneListDone;
   1.332 +			}
   1.333 +		else 
   1.334 +			{
   1.335 +			iState = EPruneList;
   1.336 +			}
   1.337 +		}
   1.338 +	else
   1.339 +		{
   1.340 +		iState = EPruneListDone;
   1.341 +		}
   1.342 +	TRequestStatus* status = &iStatus;
   1.343 +	User::RequestComplete(status, KErrNone);
   1.344 +	SetActive();
   1.345 +	}
   1.346 +
   1.347 +void CWTLSCertChainAO::HandleEPruneListDoneL()
   1.348 +	{
   1.349 +	if(iPruned) 
   1.350 +		{
   1.351 +		TInt count = iWTLSCertChain.iChain->Count();
   1.352 +		for( TInt i=count - 1; i > iPrunedChainLength; i-- )
   1.353 +			{
   1.354 +			delete iWTLSCertChain.iChain->At(i);
   1.355 +			iWTLSCertChain.iChain->Delete(i);
   1.356 +			}
   1.357 +		iWTLSCertChain.iChain->Compress();
   1.358 +		}
   1.359 +	iState = ECheckTCA;
   1.360 +	TRequestStatus* status = &iStatus;
   1.361 +	User::RequestComplete(status, KErrNone);
   1.362 +	SetActive();
   1.363 +	}
   1.364 +
   1.365 +//checks to see if each certificate in a chain has the authority to sign other certificates
   1.366 +void CWTLSCertChainAO::HandleECheckTCAL()
   1.367 +	{
   1.368 +	TBool validChain = ETrue;
   1.369 +	for( TInt i = 1; i < iWTLSCertChain.iChain->Count(); i++ ) 
   1.370 +		//all intermediate certs (ie not EE certs and not self signed) need
   1.371 +		// to have a field T=ca indicating that they can sign other certs
   1.372 +		{
   1.373 +		if( (iWTLSCertChain.iChain)->At(i)->IsTCAL() == EFalse && 
   1.374 +			(iWTLSCertChain.iChain)->At(i)->IsSelfSignedL() == EFalse ) 
   1.375 +			{
   1.376 +			iValidationResult->SetError(ENotCACert, i);
   1.377 +			User::RequestComplete(iOriginalRequestStatus, KErrNone);
   1.378 +			validChain = EFalse;
   1.379 +			break;
   1.380 +			}
   1.381 +		}
   1.382 +	if(validChain && iPruned) 
   1.383 +		{
   1.384 +		//if we've pruned the list and the chain we have is valid,
   1.385 +		//then our chain already has a root that we trust.
   1.386 +		//therefore there is no need to retrieve one :)
   1.387 +		//therefore goto validation
   1.388 +		iState = EValidateEnd;
   1.389 +		TRequestStatus *status = &iStatus;
   1.390 +		User::RequestComplete(status, KErrNone);
   1.391 +		SetActive();
   1.392 +		}
   1.393 +	else if(validChain) // ie && !iPruned
   1.394 +		{
   1.395 +		//if we haven't pruned but chain is valid then we're back a square one.
   1.396 +		iState = EIsChainSelfSigned;
   1.397 +		TRequestStatus *status = &iStatus;
   1.398 +		User::RequestComplete(status, KErrNone);
   1.399 +		SetActive();
   1.400 +		}
   1.401 +	}
   1.402 +
   1.403 +void CWTLSCertChainAO::HandleEIsChainSelfSignedL()
   1.404 +	{
   1.405 +
   1.406 +	TInt last = iWTLSCertChain.iChain->Count() - 1;
   1.407 +	if( iWTLSCertChain.iChain->At(last)->IsSelfSignedL() )
   1.408 +		{
   1.409 +		//if chained is self signed, and no earlier cert in the sequence was trusted
   1.410 +		//then this is going to fail validation
   1.411 +		//This is just an optimisation to avoid retrieving all the roots from the store
   1.412 +
   1.413 +		iValidationResult->SetError(EChainHasNoRoot, last);
   1.414 +		User::RequestComplete(iOriginalRequestStatus, KErrNone);
   1.415 +		}
   1.416 +	else 
   1.417 +		{
   1.418 +		//standard chain -> need to find the appropriate trusted root for chain if it exists
   1.419 +		iState = ERetrieveRoots;
   1.420 +		iIndex = -1;
   1.421 +		TRequestStatus* status = &iStatus;
   1.422 +		User::RequestComplete(status, KErrNone);
   1.423 +		SetActive();
   1.424 +		}
   1.425 +	}
   1.426 +
   1.427 +void CWTLSCertChainAO::HandleERetrieveRootsL()
   1.428 +	{
   1.429 +	iIndex++;	
   1.430 +	if(iIndex < iCertInfos.Count() )
   1.431 +		{
   1.432 +		if( iEncodedCertTemp != NULL ) 
   1.433 +			{
   1.434 +			delete iEncodedCertTemp;
   1.435 +			}
   1.436 +		iEncodedCertTemp = HBufC8::NewMaxL( (iCertInfos[iIndex])->Size() );
   1.437 +		iEncodedCert.Set( iEncodedCertTemp->Des() );
   1.438 +		iCertStoreManager->Retrieve( *(iCertInfos[iIndex]), iEncodedCert, iStatus );
   1.439 +		iState = EAddRootToList;
   1.440 +		}
   1.441 +	else 
   1.442 +		{
   1.443 +		iState = EFindRoot;
   1.444 +		TRequestStatus* status = &iStatus;
   1.445 +		User::RequestComplete(status, KErrNone);
   1.446 +		}	
   1.447 +	SetActive();
   1.448 +	}
   1.449 +
   1.450 +void CWTLSCertChainAO::HandleEAddRootToListL()
   1.451 +	{
   1.452 +	//are we guarenteed that a cert from the store is a valid WTLScert?
   1.453 +	//ie is this going to leave for reasons other than OOM?
   1.454 +	CWTLSCertificate *cert = CWTLSCertificate::NewL( iEncodedCert );
   1.455 +	User::LeaveIfError( iRootsFromStore.Append(cert) );
   1.456 +
   1.457 +	iState = ERetrieveRoots;
   1.458 +	TRequestStatus* status = &iStatus;
   1.459 +	User::RequestComplete(status, KErrNone);
   1.460 +	SetActive();
   1.461 +	}
   1.462 +
   1.463 +void CWTLSCertChainAO::HandleEFindRootL()
   1.464 +	{
   1.465 +	TInt last = iWTLSCertChain.iChain->Count() - 1;
   1.466 +	const CWTLSName* issuerName = &(iWTLSCertChain.iChain->At(last)->IssuerName());
   1.467 +
   1.468 +	iFoundRoot = EFalse;
   1.469 +	for(TInt i=0; i<iRootsFromClient.Count(); i++) 
   1.470 +		{
   1.471 +		if( issuerName->ExactMatchL( (iRootsFromClient[i])->SubjectName() ) )
   1.472 +			{
   1.473 +			iFoundRoot = ETrue;
   1.474 +			CWTLSCertificate* cert = CWTLSCertificate::NewLC( *(iRootsFromClient[i]) );
   1.475 +			iWTLSCertChain.iChain->AppendL( cert ); 
   1.476 +			CleanupStack::Pop(cert);
   1.477 +			break;
   1.478 +			}
   1.479 +		}
   1.480 +	if(!iFoundRoot) 
   1.481 +		{
   1.482 +		for(TInt j=0; j<iRootsFromStore.Count(); j++)
   1.483 +			{
   1.484 +			if( issuerName->ExactMatchL( (iRootsFromStore[j])->SubjectName() ) )
   1.485 +				{
   1.486 +				iFoundRoot = ETrue;
   1.487 +				CWTLSCertificate* cert = CWTLSCertificate::NewLC( *(iRootsFromStore[j]) );
   1.488 +				iWTLSCertChain.iChain->AppendL( cert );
   1.489 +				CleanupStack::Pop(cert);
   1.490 +				break;
   1.491 +				}
   1.492 +			}
   1.493 +		}
   1.494 +	if(!iFoundRoot)
   1.495 +		{
   1.496 +		iValidationResult->SetError(EChainHasNoRoot, last);
   1.497 +		User::RequestComplete(iOriginalRequestStatus, KErrNone);
   1.498 +		}
   1.499 +	else
   1.500 +		{
   1.501 +		iState = EValidateEnd;
   1.502 +		TRequestStatus* status = &iStatus;
   1.503 +		User::RequestComplete(status, KErrNone);
   1.504 +		SetActive();
   1.505 +		}
   1.506 +	}
   1.507 +
   1.508 +void CWTLSCertChainAO::HandleEValidateEndL()
   1.509 +	{
   1.510 +	TInt i = iWTLSCertChain.iChain->Count() -1;//we can guarantee that chain has at least 1 cert
   1.511 +	for (; i >= 0; i--)
   1.512 +		{
   1.513 +		const CWTLSCertificate* current = iWTLSCertChain.iChain->At(i);
   1.514 +		if ((!CheckSignatureAndNameL(*current, *iValidationResult, i))	||
   1.515 +			(!CheckValidityPeriod(*current, *iValidationResult, *iValidationTime, i)))
   1.516 +			{
   1.517 +			//these functions set the error internally if there is one
   1.518 +			break;
   1.519 +			}
   1.520 +		}		
   1.521 +
   1.522 +	User::RequestComplete(iOriginalRequestStatus, KErrNone);
   1.523 +	}
   1.524 +
   1.525 +HBufC8& CWTLSCertChainAO::GeneratePublicKeyHashL(const CWTLSCertificate& aCert) const
   1.526 +	{
   1.527 +	TWTLSKeyFactory keyFactory;
   1.528 +	CRSAPublicKey* key = keyFactory.RSAPublicKeyL( aCert.PublicKey().KeyData() );
   1.529 +	CleanupStack::PushL(key);
   1.530 +	HBufC8* modulusBuffer = key->N().BufferLC();
   1.531 +	CSHA1* sha1 = CSHA1::NewL();
   1.532 +	CleanupStack::PushL(sha1);
   1.533 +	TPtrC8 hash = sha1->Final(*modulusBuffer);
   1.534 +	HBufC8* permHash = hash.AllocL();
   1.535 +	CleanupStack::PopAndDestroy(3); //sha1, modulusBuffer, key
   1.536 +	return *permHash;
   1.537 +	}
   1.538 +