os/security/cryptoservices/certificateandkeymgmt/certstore/unifiedkeystore.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) 2001-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 "unifiedkeystore.h"
    20 #include <ecom/ecom.h>
    21 #include <random.h>
    22 #include <pbedata.h>
    23 #include <asnpkcs.h>
    24 #include "mctcertappinterface.h"
    25 #include <mctkeystoreuids.h>
    26 
    27 _LIT(KUnifiedKeyStore, "UnifiedKeyStore");
    28 
    29 /////////////////////////////////////////////////////////////////////////////////////
    30 //CUnifiedKeyStore
    31 /////////////////////////////////////////////////////////////////////////////////////
    32 
    33 EXPORT_C CUnifiedKeyStore* CUnifiedKeyStore::NewL(RFs& aFs)
    34 	{
    35 	CUnifiedKeyStore* self = CUnifiedKeyStore::NewLC(aFs);
    36 	CleanupStack::Pop(self);
    37 	return self;
    38 	}
    39 
    40 EXPORT_C CUnifiedKeyStore* CUnifiedKeyStore::NewLC(RFs& aFs)
    41 	{
    42 	CUnifiedKeyStore* self = new(ELeave) CUnifiedKeyStore(aFs);
    43 	CleanupStack::PushL(self);
    44 	self->ConstructL();
    45 	return self;
    46 	}
    47 
    48 EXPORT_C CUnifiedKeyStore::~CUnifiedKeyStore()
    49 	{
    50 	Cancel();
    51 	Cleanup();
    52 
    53 	iKeyStoresHolder.ResetAndDestroy();
    54 	iKeyStoresHolder.Close();
    55 
    56 	REComSession::FinalClose();
    57 	}
    58 
    59 void CUnifiedKeyStore::DoInitializeL()
    60 {//	We want the list of all token types that support a keystore interface
    61 	RArray<TUid> uidArray;
    62 	CleanupClosePushL(uidArray);
    63 	
    64 	User::LeaveIfError(uidArray.Append(TUid::Uid(KInterfaceKeyStore)));
    65 
    66 	TCTFindTokenTypesByInterface filter(uidArray.Array());
    67 	CCTTokenTypeInfo::ListL(iTokenTypes, filter);
    68 	
    69 	CleanupStack::PopAndDestroy();	// uidArray
    70 }
    71 
    72 EXPORT_C void CUnifiedKeyStore::Initialize(TRequestStatus& aStatus)
    73 {// The following assertion checks that we didn't call Initialize twice
    74 	__ASSERT_DEBUG((iKeyStoresHolder.Count()==0), User::Panic(KUnifiedKeyStore, EUnexpectedInitialise));
    75 
    76 	TRAPD(err, DoInitializeL());
    77 	if (err != KErrNone)
    78 		{
    79 		TRequestStatus* status = &aStatus;
    80 		User::RequestComplete(status, err);
    81 		return;
    82 		}
    83 	
    84 	iIndexTokenTypes = -1;
    85 	StartAsyncOperation(EInitializeGetTokenList, aStatus);
    86 
    87 	SetActive();
    88 	TRequestStatus* status = &iStatus;
    89 	User::RequestComplete(status, KErrNone);
    90 }
    91 
    92 EXPORT_C void CUnifiedKeyStore::CancelInitialize()
    93 	{
    94 	if (iState == EInitializeGetTokenList ||
    95 		iState == EInitializeGetToken ||
    96 		iState == EInitialiseGetKeyManagerInterface ||
    97 		iState == EInitializeGetKeyUserInterface ||
    98 		iState == EInitializeGetKeyUserInterfaceFinished ||
    99 		iState == EInitializeFinished)
   100 		{
   101 		Cancel();
   102 		}
   103 	}
   104 
   105 EXPORT_C void CUnifiedKeyStore::CreateKey(TInt aKeyStoreIndex, TKeyUsagePKCS15 aUsage,TUint aSize, 
   106 										  const TDesC& aLabel, CCTKeyInfo::EKeyAlgorithm aAlgorithm, 
   107 										  TInt aAccessType, TTime aStartDate, TTime aEndDate, 
   108 										  CCTKeyInfo*& aKeyInfoOut, TRequestStatus& aStatus)
   109 	{
   110 	StartAsyncOperation(ECreateKey, aStatus);
   111 	TRAPD(err, PrepareToCreateKeyL(aKeyStoreIndex, aUsage, aSize, aLabel, aAlgorithm, aAccessType,
   112 								   aStartDate, aEndDate, aStatus));
   113 	if (KErrNone != err)
   114 		{
   115 		Complete(err);
   116 		return;
   117 		}
   118 	
   119 	iKeyInfoOut = &aKeyInfoOut;
   120 	aKeyInfoOut = NULL;
   121 	iKeyStoreManager->CreateKey(iKeyInfo, iStatus);
   122 	SetActive();
   123 	}
   124 
   125 EXPORT_C void CUnifiedKeyStore::CancelCreateKey()
   126 	{
   127 	if (iState == ECreateKey)
   128 		{			
   129 		Cancel();
   130 		}
   131 	}
   132 
   133 EXPORT_C void CUnifiedKeyStore::ImportKey(TInt aKeyStoreIndex, const TDesC8& aKeyData,
   134 										  TKeyUsagePKCS15 aUsage, const TDesC& aLabel, 
   135 										  TInt aAccessType, TTime aStartDate, TTime aEndDate, 
   136 										  CCTKeyInfo*& aKeyInfoOut, TRequestStatus& aStatus)
   137 	{
   138 	TBool isEncrypted = TASN1DecPKCS8::IsEncryptedPKCS8Data(aKeyData);
   139 	StartAsyncOperation(isEncrypted ? EImportKeyEncrypted : EImportKey, aStatus);
   140 
   141 	ASSERT(!iKeyData);
   142 	iKeyData = aKeyData.Alloc();
   143 	if (!iKeyData)	//	OOM or some other catastrophe
   144 		{
   145 		Complete(KErrNoMemory);
   146 		return;
   147 		}
   148 	
   149 	TRAPD(err, PrepareToCreateKeyL(aKeyStoreIndex, aUsage, 0, aLabel, CCTKeyInfo::EInvalidAlgorithm, aAccessType,
   150 								   aStartDate, aEndDate, aStatus));
   151 	if (KErrNone != err)
   152 		{
   153 		Complete(err);
   154 		return;
   155 		}
   156 
   157 	iKeyInfoOut = &aKeyInfoOut;
   158 	aKeyInfoOut = NULL;
   159 
   160 	if (isEncrypted)
   161 		{
   162 		iKeyStoreManager->ImportEncryptedKey(*iKeyData, iKeyInfo, iStatus);
   163 		}
   164 	else
   165 		{
   166 		iKeyStoreManager->ImportKey(*iKeyData, iKeyInfo, iStatus);
   167 		}
   168 	SetActive();
   169 	}
   170 
   171 EXPORT_C void CUnifiedKeyStore::CancelImportKey()
   172 	{
   173 	if (iState == EImportKey ||
   174 		iState == EImportKeyEncrypted)
   175 		{
   176 		Cancel();
   177 		}
   178 	}
   179 
   180 void CUnifiedKeyStore::PrepareToCreateKeyL(	TInt aKeyStoreIndex,
   181 											TKeyUsagePKCS15 aUsage, TUint aSize, 
   182 											const TDesC& aLabel, 
   183 											CCTKeyInfo::EKeyAlgorithm aAlgorithm,
   184 											TInt aAccessType, 
   185 											TTime aStartTime, TTime aEndTime,
   186 											TRequestStatus& aStatus)
   187 	{
   188 	ASSERT(!iKeyStoreManager);
   189 	
   190 	//	These values are filled in by the server when the key is created
   191 	TKeyIdentifier keyID;
   192 	keyID.MaxSize();
   193 	keyID.FillZ(keyID.MaxSize());
   194 	TInt keyHandle = 0;
   195 
   196 	// Get the secure ID of the current process
   197 	RProcess thisProcess;
   198 	User::LeaveIfError(thisProcess.Open(thisProcess.Id()));
   199 	TSecureId creatorId = thisProcess.SecureId();
   200 	thisProcess.Close();
   201 
   202 	// Default management policy: resict to creating process
   203 	TSecurityPolicy managementPolicy(creatorId);
   204 
   205 	// Default use policy: also resict to creating process
   206 	TSecurityPolicy usePolicy(creatorId);
   207 
   208 	HBufC* label = aLabel.AllocLC();
   209 
   210 	// Panics if keystore manager index invalid
   211 	MCTKeyStoreManager& keystore = KeyStoreManager(aKeyStoreIndex);
   212 
   213 	iKeyInfo = CCTKeyInfo::NewL(keyID, aUsage, aSize, NULL, label, keystore.Token(),
   214 								keyHandle, usePolicy, managementPolicy, aAlgorithm,
   215 								aAccessType, ETrue, aStartTime, aEndTime);
   216 	CleanupStack::Pop(label);
   217 
   218 	iKeyStoreManager = &keystore;
   219 	iOriginalRequestStatus = &aStatus;
   220 	aStatus = KRequestPending;
   221 	}
   222 
   223 //	************************************************************************
   224 //	MKeyStore
   225 //	************************************************************************
   226 
   227 void CUnifiedKeyStore::List(RMPointerArray<CCTKeyInfo>& aKeys, 
   228 							const TCTKeyAttributeFilter& aFilter, 
   229 							TRequestStatus& aStatus)
   230 	{
   231 	StartAsyncOperation(EList, aStatus);
   232 
   233 	iKeyInfos = &aKeys;
   234 
   235 	delete iFilter;
   236 	iFilter = new TCTKeyAttributeFilter(aFilter);
   237 	if (!iFilter)
   238 		{
   239 		Complete(KErrNoMemory);
   240 		return;
   241 		}
   242 	
   243 	iIndex = -1;
   244 
   245 	SetActive();
   246 	TRequestStatus* status = &iStatus;
   247 	User::RequestComplete(status, KErrNone);
   248 }
   249 
   250 void CUnifiedKeyStore::CancelList()
   251 	{
   252 	if (iState == EList)
   253 		{
   254 		Cancel();
   255 		}
   256 	}
   257 
   258 void CUnifiedKeyStore::GetKeyInfo(TCTTokenObjectHandle aHandle, 
   259 										   CCTKeyInfo*& aKeyInfo,
   260 										   TRequestStatus& aStatus)
   261 	{
   262 	StartAsyncOperation(EGetKeyInfo, aStatus);
   263 	
   264 	ASSERT(!iKeyStore);	
   265 	iKeyStore = FindKeyStore(aHandle);
   266 	if (!iKeyStore)
   267 		{
   268 		Complete(KErrNotFound);
   269 		return;
   270 		}
   271 
   272 	iKeyStore->GetKeyInfo(aHandle, aKeyInfo, iStatus);
   273 	SetActive();
   274 	}
   275 
   276 void CUnifiedKeyStore::CancelGetKeyInfo()
   277 	{
   278 	if (iState == EGetKeyInfo)
   279 		{
   280 		Cancel();
   281 		}
   282 	}
   283 
   284 // Implementation for most of the Open() method
   285 TBool CUnifiedKeyStore::DoOpen(const TCTTokenObjectHandle& aHandle, 
   286 							   TRequestStatus& aStatus)
   287 	{
   288 	StartAsyncOperation(EOpen, aStatus);
   289 	
   290 	ASSERT(!iKeyStore);	
   291 	iKeyStore = FindKeyStore(aHandle);
   292 	if (!iKeyStore)
   293 		{
   294 		Complete(KErrNotFound);
   295 		return EFalse;
   296 		} 
   297 
   298 	SetActive();
   299 	return ETrue;
   300 	}
   301 
   302 void CUnifiedKeyStore::Open(const TCTTokenObjectHandle& aHandle, 
   303 							MRSASigner*& aSigner,
   304 							TRequestStatus& aStatus)
   305 	{
   306 	if (DoOpen(aHandle, aStatus))
   307 		{
   308 		iKeyStore->Open(aHandle, aSigner, iStatus);
   309 		}
   310 	}
   311 
   312 void CUnifiedKeyStore::Open(const TCTTokenObjectHandle& aHandle, 
   313 							MDSASigner*& aSigner, 
   314 							TRequestStatus& aStatus)
   315 	{
   316 	if (DoOpen(aHandle, aStatus))
   317 		{			
   318 		iKeyStore->Open(aHandle, aSigner, iStatus);
   319 		}
   320 	}
   321 
   322 void CUnifiedKeyStore::Open(const TCTTokenObjectHandle& aHandle, 
   323 							MCTDecryptor*& aDecryptor,
   324 							TRequestStatus& aStatus)
   325 	{
   326 	if (DoOpen(aHandle, aStatus))
   327 		{
   328 		iKeyStore->Open(aHandle, aDecryptor, iStatus);
   329 		}
   330 	}
   331 
   332 void CUnifiedKeyStore::Open(const TCTTokenObjectHandle& aHandle, 
   333 							MCTDH*& aDH, TRequestStatus& aStatus)
   334 	{	
   335 	if (DoOpen(aHandle, aStatus))
   336 		{
   337 		iKeyStore->Open(aHandle, aDH, iStatus);
   338 		}
   339 	}
   340 
   341 void CUnifiedKeyStore::CancelOpen()
   342 	{
   343 	if (iState == EOpen)
   344 		{
   345 		Cancel();
   346 		}
   347 	}
   348 
   349 /** Returns the public key in DER-encoded ASN-1 */
   350 void CUnifiedKeyStore::ExportPublic(const TCTTokenObjectHandle& aHandle,
   351 									HBufC8*& aPublicKey,
   352 									TRequestStatus& aStatus)
   353 	{
   354 	StartAsyncOperation(EExportPublic, aStatus);
   355 
   356 	iKeyStore = FindKeyStore(aHandle);
   357 	if (!iKeyStore)
   358 		{
   359 		Complete(KErrNotFound);
   360 		return;
   361 		}
   362 		
   363 	iKeyStore->ExportPublic(aHandle, aPublicKey, iStatus);
   364 	SetActive();
   365 	}
   366 
   367 void CUnifiedKeyStore::CancelExportPublic()
   368 	{
   369 	if (iState == EExportPublic)
   370 		{
   371 		Cancel();
   372 		}
   373 	}
   374 
   375 #ifdef SYMBIAN_ENABLE_SDP_WMDRM_SUPPORT
   376 void CUnifiedKeyStore::Open(const TCTTokenObjectHandle& aHandle,
   377                             CryptoSpi::CSigner*& aSigner,
   378                             TRequestStatus& aStatus)
   379     {
   380     if (DoOpen(aHandle, aStatus))
   381         {
   382         iKeyStore->Open(aHandle, aSigner, iStatus);
   383         }
   384     }
   385 
   386 void CUnifiedKeyStore::Open(const TCTTokenObjectHandle& aHandle,
   387                             CryptoSpi:: CAsymmetricCipher*& asymmetricCipherObj,
   388                             TRequestStatus& aStatus)
   389     {
   390     if (DoOpen(aHandle, aStatus))
   391         {
   392         iKeyStore->Open(aHandle, asymmetricCipherObj, iStatus);
   393         }
   394     }
   395 
   396 void CUnifiedKeyStore::Decrypt(const TCTTokenObjectHandle& aHandle,
   397                                const TDesC8& aCiphertext,
   398                                HBufC8*& aPlaintextPtr,
   399                                TRequestStatus& aStatus)
   400     {
   401     if (DoOpen(aHandle, aStatus))
   402         {
   403         iKeyStore->Decrypt(aHandle, aCiphertext, aPlaintextPtr, iStatus);
   404         }
   405     }
   406 
   407 void CUnifiedKeyStore::Sign(const TCTTokenObjectHandle& aHandle,
   408                             const TDesC8& aPlaintext,
   409                             CryptoSpi::CCryptoParams*& aSignature,
   410                             TRequestStatus& aStatus)
   411     {
   412     if (DoOpen(aHandle, aStatus))
   413         {
   414         iKeyStore->Sign(aHandle, aPlaintext, aSignature, iStatus);
   415         }
   416     }
   417 #endif //SYMBIAN_ENABLE_SDP_WMDRM_SUPPORT
   418 
   419 //	************************************************************************
   420 //	MKeyStoreManager
   421 //	************************************************************************
   422 	
   423 EXPORT_C void CUnifiedKeyStore::ExportKey(TCTTokenObjectHandle aHandle, 
   424 										  HBufC8*& aKey, TRequestStatus& aStatus)
   425 	{
   426 	StartAsyncOperation(EExportKey, aStatus);
   427 
   428 	ASSERT(!iKeyStoreManager);
   429 	iKeyStoreManager = FindKeyStoreManager(aHandle);
   430 	if (!iKeyStoreManager)
   431 		{
   432 		Complete(KErrNotFound);
   433 		return;
   434 		} 
   435 
   436 	iKeyStoreManager->ExportKey(aHandle, aKey, iStatus);
   437 	SetActive();
   438 	}
   439 
   440 EXPORT_C void CUnifiedKeyStore::CancelExportKey()
   441 	{
   442 	if (iState == EExportKey)
   443 		{
   444 		Cancel();
   445 		}
   446 	} 
   447 
   448 EXPORT_C void CUnifiedKeyStore::ExportEncryptedKey(TCTTokenObjectHandle aHandle, 
   449 												   const CPBEncryptParms& aEncryptParams,
   450 												   HBufC8*& aKey, TRequestStatus& aStatus)
   451 	{
   452 	StartAsyncOperation(EExportEncryptedKey, aStatus);
   453 	
   454 	ASSERT(!iKeyStoreManager);	
   455 	iKeyStoreManager = FindKeyStoreManager(aHandle);
   456 	if (!iKeyStoreManager)
   457 		{
   458 		Complete(KErrNotFound);
   459 		return;
   460 		} 
   461 		
   462 	iKeyStoreManager->ExportEncryptedKey(aHandle, aEncryptParams, aKey, iStatus);
   463 	SetActive();
   464 	}
   465 
   466 EXPORT_C void CUnifiedKeyStore::CancelExportEncryptedKey()
   467 	{
   468 	if (iState == EExportEncryptedKey)
   469 		{
   470 		Cancel();
   471 		}	
   472 	}
   473 
   474 EXPORT_C void CUnifiedKeyStore::DeleteKey(TCTTokenObjectHandle aHandle, 
   475 										  TRequestStatus& aStatus)
   476 	{
   477 	StartAsyncOperation(EDeleteKey, aStatus);
   478 
   479 	iKeyStoreManager = FindKeyStoreManager(aHandle);
   480 	if (!iKeyStoreManager)
   481 		{
   482 		Complete(KErrNotFound);
   483 		return;
   484 		}
   485 	
   486 	iKeyStoreManager->DeleteKey(aHandle, iStatus);
   487 	SetActive();
   488 	}
   489 
   490 EXPORT_C void CUnifiedKeyStore::CancelDeleteKey()
   491 	{
   492 	if (iState == EDeleteKey)
   493 		{
   494 		Cancel();
   495 		}
   496 	}
   497 
   498 EXPORT_C void CUnifiedKeyStore::SetUsePolicy(TCTTokenObjectHandle aHandle, 
   499 											 const TSecurityPolicy& aPolicy,
   500 											 TRequestStatus& aStatus)
   501 	{
   502 	StartAsyncOperation(ESetUsePolicy, aStatus);
   503 
   504 	iKeyStoreManager = FindKeyStoreManager(aHandle);
   505 	if (!iKeyStoreManager)
   506 		{
   507 		Complete(KErrNotFound);
   508 		return;
   509 		}
   510 	
   511 	iKeyStoreManager->SetUsePolicy(aHandle, aPolicy, iStatus);
   512 	SetActive();
   513 	}
   514 
   515 EXPORT_C void CUnifiedKeyStore::CancelSetUsePolicy()
   516 	{
   517 	if (iState == ESetUsePolicy)
   518 		{
   519 		Cancel();
   520 		}
   521 	}
   522 
   523 EXPORT_C void CUnifiedKeyStore::SetManagementPolicy(TCTTokenObjectHandle aHandle, 
   524 													const TSecurityPolicy& aPolicy,
   525 													TRequestStatus& aStatus)
   526 	{
   527 	StartAsyncOperation(ESetManagementPolicy, aStatus);
   528 
   529 	iKeyStoreManager = FindKeyStoreManager(aHandle);
   530 	if (!iKeyStoreManager)
   531 		{
   532 		Complete(KErrNotFound);
   533 		return;
   534 		}
   535 	
   536 	iKeyStoreManager->SetManagementPolicy(aHandle, aPolicy, iStatus);
   537 	SetActive();
   538 	}
   539 
   540 EXPORT_C void CUnifiedKeyStore::CancelSetManagementPolicy()
   541 	{
   542 	if (iState == ESetManagementPolicy)
   543 		{
   544 		Cancel();
   545 		}
   546 	}
   547 
   548 EXPORT_C void CUnifiedKeyStore::SetPassphraseTimeout(TInt aTimeout, 
   549 													 TRequestStatus& aStatus)
   550 	{
   551 	StartAsyncOperation(ESetPassphraseTimeout, aStatus);
   552 
   553 	iIndex = -1;
   554 	iNewTimeout = aTimeout;
   555 	SetActive();
   556 	
   557 	TRequestStatus* status = &iStatus;
   558 	User::RequestComplete(status, KErrNone);
   559 	}
   560 
   561 EXPORT_C void CUnifiedKeyStore::CancelSetPassphraseTimeout()
   562 	{
   563 	if (iState == ESetPassphraseTimeout)
   564 		{
   565 		Cancel();
   566 		}
   567 	}
   568 
   569 EXPORT_C void CUnifiedKeyStore::Relock(TRequestStatus& aStatus)
   570 	{
   571 	StartAsyncOperation(ERelock, aStatus);
   572 
   573 	iIndex = -1;
   574 	SetActive();
   575 	
   576 	TRequestStatus* status = &iStatus;
   577 	User::RequestComplete(status, KErrNone);
   578 	}
   579 
   580 EXPORT_C void CUnifiedKeyStore::CancelRelock()
   581 	{
   582 	if (iState == ERelock)
   583 		{
   584 		Cancel();
   585 		}
   586 	}
   587 
   588 //	************************************************************************
   589 //	Other exports
   590 //	************************************************************************
   591 
   592 EXPORT_C TInt CUnifiedKeyStore::KeyStoreCount() const
   593 {
   594 	return (iKeyStoresHolder.Count());
   595 }
   596 
   597 EXPORT_C MCTKeyStore& CUnifiedKeyStore::KeyStore(TInt aIndex)
   598 {
   599 	__ASSERT_ALWAYS(aIndex >= 0 && aIndex < iKeyStoresHolder.Count(),
   600 					User::Panic(KUnifiedKeyStore, EArrayAccessOutOfBounds));
   601 	
   602 	MCTKeyStore* keyStore = static_cast<MCTKeyStore*>(iKeyStoresHolder[aIndex]->KeyStore());
   603 	return (*keyStore);
   604 }
   605 
   606 EXPORT_C TInt CUnifiedKeyStore::KeyStoreManagerCount() const
   607 	{
   608 	TInt result = 0;
   609 	for (TInt i = 0 ; i < iKeyStoresHolder.Count() ; ++i)
   610 		{
   611 		if (iKeyStoresHolder[i]->IsKeyManager())
   612 			{
   613 			++result;
   614 			}
   615 		}
   616 	return result;
   617 	}
   618 
   619 EXPORT_C MCTKeyStoreManager& CUnifiedKeyStore::KeyStoreManager(TInt aIndex)
   620 	{
   621 	__ASSERT_ALWAYS(aIndex >= 0, User::Panic(KUnifiedKeyStore, EArrayAccessOutOfBounds));
   622 	TInt managerIndex = 0;
   623 	MCTKeyStoreManager* result = NULL;
   624 	for (TInt i = 0 ; i < iKeyStoresHolder.Count() ; ++i)
   625 		{
   626 		if (iKeyStoresHolder[i]->IsKeyManager())
   627 			{
   628 			if (managerIndex == aIndex)
   629 				{
   630 				result = static_cast<MCTKeyStoreManager*>(iKeyStoresHolder[i]->KeyStore());
   631 				break;
   632 				}
   633 			++managerIndex;
   634 			}
   635 		}
   636 	__ASSERT_ALWAYS(result != NULL, User::Panic(KUnifiedKeyStore, EArrayAccessOutOfBounds));
   637 	return *result;
   638 	}
   639 
   640 #ifdef SYMBIAN_AUTH_SERVER
   641 	
   642 EXPORT_C void CUnifiedKeyStore::CreateKey(	TInt aKeyStoreIndex, TKeyUsagePKCS15 aUsage,TUint aSize, 
   643 								const TDesC& aLabel, CCTKeyInfo::EKeyAlgorithm aAlgorithm, 
   644 								TInt aAccessType, TTime aStartDate, TTime aEndDate, 
   645 								const TDesC& aAuthenticationString, TInt aFreshness,
   646 								CCTKeyInfo*& aKeyInfoOut, TRequestStatus& aStatus)
   647 		{
   648 		
   649 		StartAsyncOperation(ECreateKey, aStatus);
   650 		TRAPD(err, PrepareToCreateKeyL(aKeyStoreIndex, aUsage, aSize, aLabel, aAlgorithm, aAccessType,
   651 									   aStartDate, aEndDate, aStatus));
   652 		if (KErrNone != err)
   653 			{
   654 			Complete(err);
   655 			return;
   656 			}
   657 		
   658 		iKeyInfoOut = &aKeyInfoOut;
   659 		aKeyInfoOut = NULL;
   660 		iKeyStoreManager->CreateKey(aAuthenticationString, aFreshness, iKeyInfo, iStatus);
   661 		SetActive();
   662 		
   663 		}
   664 
   665 
   666 EXPORT_C void CUnifiedKeyStore::ImportKey(	TInt aKeyStoreIndex, const TDesC8& aKeyData,
   667 								TKeyUsagePKCS15 aUsage, const TDesC& aLabel, 
   668 								TInt aAccessType, TTime aStartDate, TTime aEndDate, 
   669 								const TDesC& aAuthenticationString, TInt aFreshness,
   670 								CCTKeyInfo*& aKeyInfoOut, TRequestStatus& aStatus)
   671 		{
   672 		TBool isEncrypted = TASN1DecPKCS8::IsEncryptedPKCS8Data(aKeyData);
   673 		StartAsyncOperation(isEncrypted ? EImportKeyEncrypted : EImportKey, aStatus);
   674 
   675 		ASSERT(!iKeyData);
   676 		iKeyData = aKeyData.Alloc();
   677 		if (!iKeyData)	//	OOM or some other catastrophe
   678 			{
   679 			Complete(KErrNoMemory);
   680 			return;
   681 			}
   682 		
   683 		TRAPD(err, PrepareToCreateKeyL(aKeyStoreIndex, aUsage, 0, aLabel, CCTKeyInfo::EInvalidAlgorithm, aAccessType,
   684 									   aStartDate, aEndDate, aStatus));
   685 		if (KErrNone != err)
   686 			{
   687 			Complete(err);
   688 			return;
   689 			}
   690 
   691 		iKeyInfoOut = &aKeyInfoOut;
   692 		aKeyInfoOut = NULL;
   693 
   694 		if (isEncrypted)
   695 			{
   696 			iKeyStoreManager->ImportEncryptedKey(*iKeyData, aAuthenticationString, aFreshness, iKeyInfo, iStatus);
   697 			}
   698 		else
   699 			{
   700 			iKeyStoreManager->ImportKey(*iKeyData, aAuthenticationString, aFreshness, iKeyInfo, iStatus);
   701 			}
   702 		SetActive();
   703 		}
   704 
   705 EXPORT_C void CUnifiedKeyStore::SetAuthenticationPolicy(	const TCTTokenObjectHandle aHandle, 
   706 															const TDesC& aAuthenticationString,
   707 															TInt aFreshness,					
   708 															TRequestStatus& aStatus)
   709 	{
   710 	StartAsyncOperation(ESetAuthenticationPolicy, aStatus);
   711 		
   712 	ASSERT(!iKeyStoreManager);	
   713 	iKeyStoreManager = FindKeyStoreManager(aHandle);
   714 	if (!iKeyStoreManager)
   715 		{
   716 		Complete(KErrNotFound);
   717 		return;
   718 		} 
   719 		
   720 	iKeyStoreManager->SetAuthenticationPolicy(aHandle, aAuthenticationString, aFreshness, iStatus);
   721 	SetActive();
   722 		
   723 	}
   724 
   725 EXPORT_C void CUnifiedKeyStore::GetAuthenticationPolicy(	const TCTTokenObjectHandle aHandle, 
   726 															HBufC*& aAuthenticationString,
   727 															TInt& aFreshness,					
   728 															TRequestStatus& aStatus)
   729 	{
   730 	StartAsyncOperation(EGetAuthenticationPolicy, aStatus);
   731 		
   732 	ASSERT(!iKeyStoreManager);	
   733 	iKeyStoreManager = FindKeyStoreManager(aHandle);
   734 	if (!iKeyStoreManager)
   735 		{
   736 		Complete(KErrNotFound);
   737 		return;
   738 		} 
   739 		
   740 	iKeyStoreManager->GetAuthenticationPolicy(aHandle, aAuthenticationString, aFreshness, iStatus);
   741 	SetActive();
   742 		
   743 	}
   744 
   745 #endif // SYMBIAN_AUTH_SERVER
   746 
   747 CUnifiedKeyStore::CUnifiedKeyStore(RFs& aFs)
   748 	:	CActive(EPriorityNormal), iFs(aFs), iState(EIdle)
   749 {//	Currently defaults to always try for key store manager interface
   750 //	This may change (add parameter to NewL for required interface)
   751 	iRequestUid.iUid = KInterfaceKeyStoreManager;
   752 	CActiveScheduler::Add(this);
   753 }
   754 
   755 void CUnifiedKeyStore::ConstructL()
   756 {}
   757 
   758 void CUnifiedKeyStore::StartAsyncOperation(TState aState, TRequestStatus& aStatus)
   759 	{
   760 	ASSERT(iState == EIdle);
   761 	ASSERT(iOriginalRequestStatus == NULL);
   762 	iState = aState;
   763 	iOriginalRequestStatus = &aStatus;
   764 	aStatus = KRequestPending;
   765 	}
   766 
   767 MCTKeyStore* CUnifiedKeyStore::FindKeyStore(const TCTTokenObjectHandle& aHandle)
   768 	{
   769 	for (TInt index = 0 ; index < iKeyStoresHolder.Count() ; ++index)
   770 		{
   771 		MCTTokenInterface* store = iKeyStoresHolder[index]->KeyStore();
   772 		ASSERT(store);
   773 		if (store->Token().Handle() == aHandle.iTokenHandle)
   774 			{
   775 			return static_cast<MCTKeyStoreManager*>(store);
   776 			}
   777 		}
   778 	return NULL;
   779 	}
   780 	
   781 MCTKeyStoreManager* CUnifiedKeyStore::FindKeyStoreManager(const TCTTokenObjectHandle& aHandle)
   782 	{
   783 	for (TInt index = 0 ; index < iKeyStoresHolder.Count() ; ++index)
   784 		{
   785 		MCTTokenInterface* store = iKeyStoresHolder[index]->KeyStore();
   786 		ASSERT(store);
   787 		if (store->Token().Handle() == aHandle.iTokenHandle && iKeyStoresHolder[index]->IsKeyManager())
   788 			{
   789 			return static_cast<MCTKeyStoreManager*>(store);
   790 			}
   791 		}
   792 	return NULL;
   793 	}
   794 	
   795 void CUnifiedKeyStore::RunL()
   796 {
   797 	if (EInitializeGetKeyUserInterfaceFinished != iState &&
   798 		EInitializeGetKeyUserInterface != iState && 
   799 		EInitializeGetToken != iState)
   800 	{
   801 		User::LeaveIfError(iStatus.Int());
   802 	}
   803 
   804 	switch (iState)
   805 	{
   806 		case EInitializeGetTokenList:
   807 		{//	Try to get a list of Tokens for each of the Token Types
   808 			iIndexTokenTypes++;
   809 			if (iIndexTokenTypes < iTokenTypes.Count())
   810 			{
   811 				__ASSERT_DEBUG(!iTokenType, User::Panic(KUnifiedKeyStore, EArrayAccessOutOfBounds));
   812 				iTokenType = MCTTokenType::NewL(*iTokenTypes[iIndexTokenTypes], iFs);
   813 				__ASSERT_DEBUG(iTokens.Count()==0, User::Panic(KUnifiedKeyStore, ETokensArrayAlreadyInUse));
   814 				iTokenType->List(iTokens, iStatus);
   815 				iIndexTokens = -1;
   816 				iState = EInitializeGetToken;
   817 			}
   818 			else
   819 			{// We don't need the list of Token Types anymore
   820 				iTokenTypes.ResetAndDestroy();
   821 				iTokenTypes.Close();
   822 				iState = EInitializeFinished;
   823 				TRequestStatus* status = &iStatus;
   824 				User::RequestComplete(status, KErrNone);
   825 			}
   826 			SetActive();
   827 			break;
   828 		}
   829 		case EInitializeGetToken:
   830 		{
   831 			if (iStatus.Int() == KErrHardwareNotAvailable)
   832 				{
   833 				// If the hardware corresponding to this
   834 				// TokenType has been removed then just skip it
   835 				// but DO NOT leave!
   836 				++iIndexTokens;
   837 				iState = EInitializeGetToken;
   838 				TRequestStatus* status = &iStatus;
   839 				User::RequestComplete(status, KErrNone);
   840 				}
   841             else
   842 				{
   843 				User::LeaveIfError(iStatus.Int());
   844     			iIndexTokens++;		
   845 		
   846 				if (iIndexTokens < iTokens.Count())
   847 					{
   848 					iTokenType->OpenToken(*iTokens[iIndexTokens], iToken, iStatus);
   849 					iRequestUid.iUid = KInterfaceKeyStoreManager;
   850 					iState = EInitialiseGetKeyManagerInterface;
   851 					}
   852 				else
   853 					{// Don't need the iTokenType anymore
   854 					iTokenType->Release();
   855 					iTokenType = 0;
   856 
   857 					iTokens.Close();	// Don't need the list of Tokens anymore
   858 					iState = EInitializeGetTokenList;
   859 					TRequestStatus* status = &iStatus;
   860 					User::RequestComplete(status, KErrNone);
   861 					}
   862 				}
   863 			SetActive();
   864 			break;
   865 		}
   866 		case EInitialiseGetKeyManagerInterface:
   867 		{// First try to get a manager interface to the store, if
   868 		//	unsuccessful, try once to get a user interface
   869 			if (iToken)
   870 			{
   871 				iRequestUid.iUid = KInterfaceKeyStoreManager;			
   872 				iToken->GetInterface(iRequestUid, iTokenInterface, iStatus);
   873 				iState = EInitializeGetKeyUserInterface;
   874 				SetActive();			
   875 			}
   876 			else
   877 			{//	No token
   878 				User::Leave(KErrNotReady);
   879 			}
   880 			break;
   881 		}
   882 		case EInitializeGetKeyUserInterface:
   883 		{//	Did we get a manager interface?
   884 			if (iStatus==KErrNoMemory)
   885 			{
   886 				User::Leave(KErrNoMemory);
   887 			}
   888 
   889 			if (iRequestUid.iUid==KInterfaceKeyStoreManager)
   890 			{
   891 				if (KErrNone==iStatus.Int())
   892 				{//	Success! Store it and finish up
   893 					CKeyStoreIF* keyStore = new (ELeave) CKeyStoreIF(iTokenInterface, ETrue);
   894 					CleanupStack::PushL(keyStore);
   895 					User::LeaveIfError(iKeyStoresHolder.Append(keyStore));
   896 					CleanupStack::Pop(keyStore);
   897 
   898 					iTokenInterface = 0;
   899 					iToken->Release();
   900 					iToken = 0;
   901 					iState = EInitializeGetToken;
   902 					TRequestStatus* status = &iStatus;
   903 					User::RequestComplete(status, KErrNone);
   904 				}
   905 				else
   906 				{//	No luck getting a manager, so try getting a user
   907 					iRequestUid.iUid = KInterfaceKeyStore;			
   908 					iToken->GetInterface(iRequestUid, iTokenInterface, iStatus);
   909 					iState = EInitializeGetKeyUserInterfaceFinished;					
   910 				}
   911 			}
   912 			else if (iRequestUid.iUid==KInterfaceKeyStore) 
   913 			{//	We were trying for user IF								
   914 				if (iStatus==KErrNone)
   915 				{
   916 					if (iToken)
   917 					{
   918 						iRequestUid.iUid = KInterfaceKeyStore;			
   919 						iToken->GetInterface(iRequestUid, iTokenInterface, iStatus);
   920 						iState = EInitializeGetKeyUserInterfaceFinished;	
   921 					}
   922 					else
   923 					{
   924 						User::Leave(KErrNotReady);
   925 					}
   926 				}
   927 				else
   928 				{//	Couldn't even get a user IF
   929 					User::Leave(iStatus.Int());
   930 				}				
   931 			}
   932 
   933 			SetActive();
   934 			break;
   935 		}
   936 		case EInitializeGetKeyUserInterfaceFinished:
   937 		{
   938 			if (iStatus==KErrNone)
   939 			{
   940 				CKeyStoreIF* keyStore = new (ELeave) CKeyStoreIF(iTokenInterface, EFalse);
   941 				CleanupStack::PushL(keyStore);
   942 				User::LeaveIfError(iKeyStoresHolder.Append(keyStore));
   943 				CleanupStack::Pop(keyStore);
   944 
   945 				iTokenInterface = 0;
   946 				iToken->Release();
   947 				iToken = 0;
   948 				iState = EInitializeGetToken;
   949 				TRequestStatus* status = &iStatus;
   950 				User::RequestComplete(status, KErrNone);
   951 			}
   952 			else if (iStatus == KErrNoMemory)
   953 			{
   954 				User::Leave(KErrNoMemory);
   955 			}
   956 			else
   957 			{
   958 				iState = EInitializeGetToken;
   959 				TRequestStatus* status = &iStatus;
   960 				User::RequestComplete(status,iStatus.Int());
   961 			}
   962 			
   963 			SetActive();
   964 			break;
   965 		}
   966 		case EInitializeFinished:
   967 			Complete(KErrNone);
   968 			break;
   969 			
   970 		case EList:
   971 		{//	iIndex has been initialized in List function
   972 			++iIndex;
   973 			if (iIndex < iKeyStoresHolder.Count())
   974 				{
   975 				iKeyStore = static_cast<MCTKeyStore*>(iKeyStoresHolder[iIndex]->KeyStore());
   976 				ASSERT(iKeyStore);
   977 				iKeyStore->List(*iKeyInfos, *iFilter, iStatus);
   978 				SetActive();
   979 				}
   980 			else
   981 				{
   982 				Complete(KErrNone);
   983 				}
   984 			break;
   985 		}
   986 		
   987 	    case EGetKeyInfo:
   988 			Complete(KErrNone);
   989 			break;
   990 			
   991 		case ECreateKey:
   992 			*iKeyInfoOut = iKeyInfo;
   993 			iKeyInfo = NULL; // Release ownership
   994 			Complete(KErrNone);
   995 			break;
   996 			
   997 		case EImportKey:
   998 		case EImportKeyEncrypted:
   999 			*iKeyInfoOut = iKeyInfo;
  1000 			iKeyInfo = NULL; // Release ownership
  1001 			Complete(KErrNone);
  1002 			break;
  1003 			
  1004 		case EExportKey:
  1005 		case EExportEncryptedKey:
  1006 			Complete(KErrNone);
  1007 			break;		
  1008 
  1009 	    case ERelock:
  1010 			++iIndex;
  1011 			
  1012 			// Find next key store manager
  1013 			while (iIndex < iKeyStoresHolder.Count() && !iKeyStoresHolder[iIndex]->IsKeyManager())
  1014 				++iIndex;
  1015 			
  1016 			if (iIndex < iKeyStoresHolder.Count())
  1017 				{
  1018 				iKeyStoreManager = static_cast<MCTKeyStoreManager*>(iKeyStoresHolder[iIndex]->KeyStore());
  1019 				ASSERT(iKeyStoreManager);
  1020 				iKeyStoreManager->Relock(iStatus);
  1021 				SetActive();
  1022 				}
  1023 			else
  1024 				{
  1025 				Complete(KErrNone);
  1026 				}
  1027 			break;
  1028 
  1029 	    case ESetPassphraseTimeout:
  1030 			++iIndex;
  1031 			
  1032 			// Find next key store manager
  1033 			while (iIndex < iKeyStoresHolder.Count() && !iKeyStoresHolder[iIndex]->IsKeyManager())
  1034 				++iIndex;
  1035 			
  1036 			if (iIndex < iKeyStoresHolder.Count())
  1037 				{
  1038 				iKeyStoreManager = static_cast<MCTKeyStoreManager*>(iKeyStoresHolder[iIndex]->KeyStore());
  1039 				ASSERT(iKeyStoreManager);
  1040 				iKeyStoreManager->SetPassphraseTimeout(iNewTimeout, iStatus);
  1041 				SetActive();
  1042 				}
  1043 			else
  1044 				{
  1045 				Complete(KErrNone);
  1046 				}
  1047 			break;
  1048 
  1049 	    case EOpen:
  1050 		case EExportPublic:
  1051 	    case EDeleteKey:
  1052 	    case ESetUsePolicy:
  1053 	    case ESetManagementPolicy:
  1054 	    case EGetAuthenticationPolicy:
  1055 	    case ESetAuthenticationPolicy:
  1056 			Complete(KErrNone);
  1057 			break;
  1058 		default:
  1059 			User::Panic(KUnifiedKeyStore, EUnrecognisedState);
  1060 			break;
  1061 	}
  1062 }
  1063 
  1064 TInt CUnifiedKeyStore::RunError(TInt aError)
  1065 	{
  1066 	Complete(aError); 
  1067 	return KErrNone;
  1068 	}
  1069 
  1070 void CUnifiedKeyStore::DoCancel()
  1071 	{
  1072 	// If the current state is the last state involved in handling a request, we
  1073 	// check to see if we have already been completed - in this case we can
  1074 	// simply complete the client with iStatus (this may be KErrNone).  If we
  1075 	// have not we cancel the outstanding request and pass the resulting iStatus
  1076 	// back to the client - this too may indicate a successful completion if the
  1077 	// cancel arrived after the request was executed.
  1078 	//
  1079 	// For more complex cases, where there are more states to go through before
  1080 	// we finish servicing the client request, we cancel any outstanding
  1081 	// request, and return KErrCancel to the client.
  1082 
  1083 	switch (iState)
  1084 		{
  1085 		case EInitializeFinished:
  1086 		case EGetKeyInfo:
  1087 		case ECreateKey:
  1088 		case EImportKey:
  1089 		case EImportKeyEncrypted:
  1090 		case EExportKey:
  1091 		case EExportEncryptedKey:
  1092 	    case EOpen:
  1093 		case EExportPublic:
  1094 	    case EDeleteKey:
  1095 	    case ESetUsePolicy:
  1096 	    case ESetManagementPolicy:
  1097 			if (iStatus == KRequestPending)
  1098 				{
  1099 				// Attempt to cancel outstanding request and pass status back to
  1100 				// client
  1101 				CancelOutstandingRequest();
  1102 				Complete(iStatus.Int());
  1103 				}
  1104 			else
  1105 				{
  1106 				// We've already been completed - call RunL() to process results
  1107 				// and complete client
  1108 				TRAPD(err, RunL());
  1109 				if (err != KErrNone)
  1110 					{
  1111 					RunError(err);
  1112 					}
  1113 				}
  1114 			break;
  1115 
  1116 		default:
  1117 			CancelOutstandingRequest();
  1118 			Complete(KErrCancel);
  1119 			break;
  1120 		}
  1121 	}
  1122 
  1123 void CUnifiedKeyStore::CancelOutstandingRequest()
  1124 	{
  1125 	switch (iState)
  1126 		{
  1127 		case EInitializeGetTokenList:
  1128 		case EInitializeGetToken:
  1129 		case EInitialiseGetKeyManagerInterface:
  1130 		case EInitializeGetKeyUserInterface:
  1131 		case EInitializeGetKeyUserInterfaceFinished:
  1132 		case EInitializeFinished:
  1133 			// Don't have to cancel initialisation stuff - this happens when we
  1134 			// release the objects in Cleanup().
  1135 			iStatus = KErrCancel;
  1136 			break;
  1137 
  1138 		case EList:
  1139 			if (iKeyStore)
  1140 				{
  1141 				iKeyStore->CancelList();
  1142 				}
  1143 			break;
  1144 
  1145 		case EGetKeyInfo:
  1146 			ASSERT(iKeyStore);
  1147 			iKeyStore->CancelGetKeyInfo();
  1148 			break;
  1149 
  1150 		case EOpen:
  1151 			ASSERT(iKeyStore);
  1152 			iKeyStore->CancelOpen();
  1153 			break;
  1154 
  1155 		case EExportPublic:
  1156 			ASSERT(iKeyStore);
  1157 			iKeyStore->CancelExportPublic();
  1158 			break;			
  1159 
  1160 		case ECreateKey:
  1161 			ASSERT(iKeyStoreManager);
  1162 			iKeyStoreManager->CancelCreateKey();
  1163 			break;
  1164 
  1165 		case EImportKey:
  1166 		case EImportKeyEncrypted:
  1167 			ASSERT(iKeyStoreManager);
  1168 			iKeyStoreManager->CancelImportKey();
  1169 			break;
  1170 			
  1171 		case EExportKey:
  1172 		case EExportEncryptedKey:
  1173 			ASSERT(iKeyStoreManager);
  1174 			iKeyStoreManager->CancelExportKey();
  1175 			break;
  1176 			
  1177 		case EDeleteKey:
  1178 			ASSERT(iKeyStoreManager);
  1179 			iKeyStoreManager->CancelDeleteKey();
  1180 			break;
  1181 
  1182 		case ERelock:
  1183 			ASSERT(iKeyStoreManager);
  1184 			iKeyStoreManager->CancelRelock();
  1185 			break;
  1186 
  1187 		case ESetPassphraseTimeout:
  1188 			ASSERT(iKeyStoreManager);
  1189 			iKeyStoreManager->CancelSetPassphraseTimeout();
  1190 			break;
  1191 		
  1192 	    case ESetUsePolicy:
  1193 			ASSERT(iKeyStoreManager);
  1194 			iKeyStoreManager->CancelSetUsePolicy();
  1195 			break;
  1196 
  1197 	    case ESetManagementPolicy:
  1198 			ASSERT(iKeyStoreManager);
  1199 			iKeyStoreManager->CancelSetManagementPolicy();
  1200 			break;
  1201 
  1202 		default:
  1203 			User::Panic(KUnifiedKeyStore, EUnrecognisedState);
  1204 			break;
  1205 		}
  1206 	}
  1207 
  1208 
  1209 void CUnifiedKeyStore::Complete(TInt aError)
  1210 	{
  1211 	Cleanup();
  1212 	if (iOriginalRequestStatus)
  1213 		{
  1214 		User::RequestComplete(iOriginalRequestStatus, aError);
  1215 		}
  1216 	}
  1217 
  1218 void CUnifiedKeyStore::Cleanup()
  1219 	{
  1220 	// If we have a key info, we want to release it
  1221 	if (iKeyInfo)
  1222 	{
  1223 		iKeyInfo->Release();
  1224 		iKeyInfo = NULL;
  1225 	}
  1226 
  1227 	delete iKeyData;
  1228 	iKeyData = NULL;
  1229 
  1230 	delete iFilter;
  1231 	iFilter = NULL;
  1232 
  1233 	delete iPbeParams;
  1234 	iPbeParams = NULL;
  1235 
  1236 	iTokenTypes.Close();
  1237 
  1238 	if (iTokenType)
  1239 		{
  1240 		iTokenType->Release();
  1241 		iTokenType = 0;
  1242 		}
  1243 
  1244 	iTokens.Close();
  1245 
  1246 	if (iToken)
  1247 		{
  1248 		iToken->Release();
  1249 		iToken = 0;
  1250 		}
  1251 
  1252 	if (iTokenInterface)
  1253 		{
  1254 		iTokenInterface->Release();
  1255 		iTokenInterface = 0;
  1256 		}
  1257 	
  1258 	iKeyInfoOut = NULL;
  1259 	iKeyStore = NULL;
  1260 	iKeyStoreManager = NULL;
  1261 	
  1262 	iState = EIdle;
  1263 	}
  1264 
  1265 CUnifiedKeyStore::CKeyStoreIF::CKeyStoreIF(MCTTokenInterface* aKeyStore, TBool aIsKeyManager)
  1266 :	iKeyStore(aKeyStore), iIsKeyManager(aIsKeyManager)
  1267 {}
  1268 
  1269 CUnifiedKeyStore::CKeyStoreIF::~CKeyStoreIF()
  1270 {
  1271 	if (iKeyStore)
  1272 	{
  1273 		iKeyStore->Release();
  1274 		iKeyStore = NULL;
  1275 	}
  1276 }
  1277