os/security/cryptoservices/certificateandkeymgmt/certstore/CCheckedCertStore.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200 (2012-06-15)
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     1 /*
     2 * Copyright (c) 2002-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 "CCheckedCertStore.h"
    20 
    21 #include <signed.h>
    22 #include <x509cert.h>
    23 #include <x509certext.h>
    24 #include <wtlscert.h>
    25 #include <x509keys.h>
    26 #include <securityerr.h>
    27 
    28 #include "certificateapps.h"
    29 
    30 _LIT(KPanicCategory, "CCheckedCertStore");
    31 #define assert(x) __ASSERT_ALWAYS((x), User::Panic(KPanicCategory, 1));
    32 
    33 /////////////////////////////////////////////////////////////////////
    34 //	CCheckedCertStore
    35 /////////////////////////////////////////////////////////////////////
    36 
    37 CCheckedCertStore::~CCheckedCertStore()
    38     {
    39     Cancel();
    40     Cleanup();
    41     
    42 	// Release the cert store - no need to release the token since this would
    43 	// have been done as part of MCTTokenInterface::Release()
    44     iCertStore.Release();
    45 
    46 	iFs.Close();
    47     }
    48 
    49 CCheckedCertStore::CCheckedCertStore(MCTCertStore& aTokenIF, RProperty& aProperty)
    50 :	CActive(EPriorityStandard), 
    51 	iCertStore(aTokenIF),
    52 	iPSCertstoreChangePropertyRef(aProperty)	
    53     {
    54 	// need to add reference since we now have the token
    55 	iCertStore.Token().AddRef();
    56     }
    57 
    58 CCheckedCertStore::CCheckedCertStore(MCTWritableCertStore& aTokenIF, RProperty& aProperty)
    59 :	CActive(EPriorityStandard),
    60 	iCertStore(aTokenIF),
    61 	iWritableCertStore(&aTokenIF),
    62 	iPSCertstoreChangePropertyRef(aProperty)
    63     {
    64 	// need to add reference since we now have the token
    65 	iCertStore.Token().AddRef();
    66     }
    67 
    68 /*static*/ CCheckedCertStore* CCheckedCertStore::NewCheckedCertStoreL(MCTTokenInterface* aTokenIF, RProperty& aProperty)
    69     {
    70     assert(aTokenIF);
    71 	MCTCertStore& tokenInterface = static_cast<MCTCertStore&>(*aTokenIF);
    72 	CCheckedCertStore* me = new (ELeave) CCheckedCertStore(tokenInterface, aProperty);
    73     CleanupReleasePushL(*me);
    74     me->ConstructL();
    75     CleanupStack::Pop();
    76 	return (me);
    77     }
    78 	
    79 /*static*/ CCheckedCertStore* CCheckedCertStore::NewCheckedWritableCertStoreL(MCTTokenInterface* aTokenIF, RProperty& aProperty)
    80     {
    81     assert(aTokenIF);
    82 	MCTWritableCertStore& tokenInterface = static_cast<MCTWritableCertStore&>(*aTokenIF);
    83 	CCheckedCertStore* me = new (ELeave) CCheckedCertStore(tokenInterface, aProperty);
    84     CleanupReleasePushL(*me);
    85     me->ConstructL();
    86     CleanupStack::Pop();
    87 	return (me);
    88     }
    89 
    90 void CCheckedCertStore::ConstructL()
    91     {
    92 	User::LeaveIfError(iFs.Connect());	
    93 	CActiveScheduler::Add(this);
    94     }
    95 
    96 MCTToken& CCheckedCertStore::Token()
    97     {
    98 	return iCertStore.Token();
    99     }
   100 
   101 //	May require checking against the keystore *after* calling the server to complete
   102 //	the List request
   103 void CCheckedCertStore::List(RMPointerArray<CCTCertInfo>& aCerts, const CCertAttributeFilter& aFilter,
   104                              TRequestStatus& aStatus)
   105     {
   106     assert(iState == EIdleState);
   107 
   108     // Only allow filtering on key usage for user certs
   109     if (aFilter.iKeyUsage != EX509UsageAll &&
   110         (!aFilter.iOwnerTypeIsSet || EUserCertificate != aFilter.iOwnerType))
   111         {
   112         TRequestStatus* status = &aStatus;
   113         User::RequestComplete(status, KErrNotSupported);
   114         return;
   115         }
   116 
   117     // Store caller parameters for later reference
   118     iCallerCerts = &aCerts;
   119     iCallerFilter = &aFilter;
   120     aStatus = KRequestPending;
   121     iCallerStatus = &aStatus;
   122 
   123     iState = EList;
   124     iCertStore.List(aCerts, aFilter, iStatus);
   125     SetActive();
   126     }
   127 
   128 void CCheckedCertStore::CancelList()
   129     {
   130     if (iState == EList ||
   131         iState == EInitKeyStoreForList ||
   132         iState == EGetKeyInfosForList)
   133         {
   134         Cancel();
   135         }
   136     }
   137 
   138 void CCheckedCertStore::GetCert(CCTCertInfo*& aCertInfo, const TCTTokenObjectHandle& aHandle, 
   139                                 TRequestStatus& aStatus)
   140     {
   141     assert(iState == EIdleState);
   142     iCertStore.GetCert(aCertInfo, aHandle, aStatus);
   143     }
   144 
   145 void CCheckedCertStore::CancelGetCert()
   146     {
   147     iCertStore.CancelGetCert();
   148     }
   149 
   150 void CCheckedCertStore::Applications(const CCTCertInfo& aCertInfo, RArray<TUid>& aApplications,
   151 									 TRequestStatus& aStatus)
   152     {
   153     assert(iState == EIdleState);
   154     iCertStore.Applications(aCertInfo, aApplications, aStatus);
   155     }
   156 
   157 void CCheckedCertStore::CancelApplications()
   158     {
   159     iCertStore.CancelApplications();
   160     }
   161 
   162 void CCheckedCertStore::IsApplicable(const CCTCertInfo& aCertInfo, TUid aApplication, 
   163                                      TBool& aIsApplicable, TRequestStatus& aStatus)
   164     {
   165     assert(iState == EIdleState);
   166     iCertStore.IsApplicable(aCertInfo, aApplication, aIsApplicable, aStatus);
   167     }
   168 
   169 void CCheckedCertStore::CancelIsApplicable()
   170     {
   171     iCertStore.CancelIsApplicable();
   172     }
   173 
   174 void CCheckedCertStore::Trusted(const CCTCertInfo& aCertInfo, TBool& aTrusted, 
   175                                 TRequestStatus& aStatus)
   176     {
   177     assert(iState == EIdleState);
   178     iCertStore.Trusted(aCertInfo, aTrusted, aStatus);
   179     }
   180 
   181 void CCheckedCertStore::CancelTrusted()
   182     {
   183     iCertStore.CancelTrusted();
   184     }
   185 
   186 void CCheckedCertStore::Retrieve(const CCTCertInfo& aCertInfo, TDes8& aEncodedCert, 
   187                                  TRequestStatus& aStatus)
   188     {
   189     assert(iState == EIdleState);
   190     iCertStore.Retrieve(aCertInfo, aEncodedCert, aStatus);
   191     }
   192 
   193 void CCheckedCertStore::CancelRetrieve()
   194     {
   195     iCertStore.CancelRetrieve();
   196     }
   197 
   198 
   199 void CCheckedCertStore::Add(const TDesC& aLabel, 
   200 							TCertificateFormat aFormat,
   201                             TCertificateOwnerType aCertificateOwnerType, 
   202                             const TKeyIdentifier* aSubjectKeyId,
   203                             const TKeyIdentifier* aIssuerKeyId,
   204                             const TDesC8& aCert, 
   205                             TRequestStatus& aStatus)
   206     {
   207  	// default value for aDeletable = ETrue		
   208 	Add( aLabel, aFormat, aCertificateOwnerType, aSubjectKeyId, 
   209 			aIssuerKeyId, aCert, ETrue, aStatus );
   210     }
   211   
   212 // new Add(.., TBool aDeletable, ..) method from MCTWritableCertStore
   213 void CCheckedCertStore::Add( const TDesC& aLabel, 
   214 							 TCertificateFormat aFormat,
   215                              TCertificateOwnerType aCertificateOwnerType, 
   216                              const TKeyIdentifier* aSubjectKeyId,
   217                              const TKeyIdentifier* aIssuerKeyId,
   218                              const TDesC8& aCert, 
   219                              const TBool aDeletable,
   220                              TRequestStatus& aStatus
   221                              )
   222     {
   223     assert(iWritableCertStore);
   224     assert(iState == EIdleState);
   225 
   226     TRAPD(err, DoAddL(	aLabel, 
   227     					aFormat,
   228     					aCertificateOwnerType, 
   229     					aSubjectKeyId, 
   230     					aIssuerKeyId, 
   231     					aCert, 
   232     					aDeletable,
   233     					aStatus		) );
   234     
   235 	if (err != KErrNone)
   236 		{
   237     	    Complete(err);
   238 		}
   239 	}
   240 
   241  
   242 void CCheckedCertStore::DoAddL(	const TDesC& aLabel,
   243 								TCertificateFormat aFormat,
   244                                	TCertificateOwnerType aCertificateOwnerType, 
   245                                	const TKeyIdentifier* aSubjectKeyId,
   246                                	const TKeyIdentifier* aIssuerKeyId,
   247                                	const TDesC8& aCert, 
   248                                	const TBool aDeletable,
   249                                	TRequestStatus& aStatus)
   250     {
   251     
   252     //	Store caller parameters for later use
   253 	    aStatus			= KRequestPending;
   254 	    iCallerStatus	= &aStatus;
   255 	    iFormat 	 	= aFormat;
   256 	    iCertificateOwnerType = aCertificateOwnerType;
   257 	    iSubjectKeyId	= aSubjectKeyId;
   258 	    iIssuerKeyId	= aIssuerKeyId;
   259 		iDeletable  	= aDeletable;
   260 
   261 	// Store (copy)  aCert (cert data) into iCertificate[:HBufC8]
   262 	    assert(!iCertificate);
   263 	    iCertificate = HBufC8::NewMaxL(aCert.Size());
   264 	    TPtr8 theCert(iCertificate->Des());
   265 	    theCert.FillZ();
   266 	    theCert.Copy(aCert);
   267 
   268 	// Store (copy) aLabel (cert label) into iCertLabel[:HBufC]
   269 	    assert(!iCertLabel);
   270 	    iCertLabel = HBufC::NewMaxL(aLabel.Length());
   271 	    TPtr theLabel(iCertLabel->Des());
   272 	    theLabel.FillZ();
   273 	    theLabel.Copy(aLabel);
   274 
   275     //	Checks subject key ID with certificate data, and sets up key filter
   276     //	which is used later to determine whether there is a key with the
   277     //	appropriate subject and thus, if it is OK to add the certificate	
   278 	    ComputeAndCheckSubjectKeyIdL();
   279 
   280     //	Is keystore checking required? Only if a user certificate
   281     if (EUserCertificate==aCertificateOwnerType)
   282 		{
   283         	InitialiseKeyStoreL(EInitKeyStoreForAdd);
   284 		}
   285     else
   286 		{
   287         iState = EAdd;
   288         
   289         // try new method first
   290         iWritableCertStore->Add( *iCertLabel,			// call new method
   291         						 iFormat,
   292         						 iCertificateOwnerType,
   293                                  iSubjectKeyId,
   294                                  iIssuerKeyId,
   295                                  *iCertificate,
   296                                  iDeletable,			// with deletable param
   297                                  iStatus );                    
   298         SetActive();
   299 		}
   300 	}
   301 
   302 
   303 
   304 void CCheckedCertStore::CancelAdd()
   305     {
   306     if (iState == EInitKeyStoreForAdd ||
   307         iState == EGetKeyInfosForAdd ||
   308         iState == EAdd || iState == EOldAdd )
   309         {
   310         Cancel();
   311         }
   312     }
   313 
   314 void CCheckedCertStore::ComputeAndCheckSubjectKeyIdL()
   315     {
   316 	switch (iFormat)
   317         {
   318 		case EX509Certificate:
   319             {
   320 			TPtr8 thePtr(iCertificate->Des());
   321 			CX509Certificate* cert = CX509Certificate::NewLC(thePtr);
   322 
   323 			TKeyUsageX509 x509Usage = EX509UsageNone;
   324 			const CX509CertExtension* ext = cert->Extension(KKeyUsage);
   325 
   326 			if (!ext)
   327                 {
   328 				x509Usage = EX509UsageAll;
   329                 }
   330 			else
   331                 {
   332 				CX509KeyUsageExt* keyUsageExt = CX509KeyUsageExt::NewLC(ext->Data());
   333 				
   334 				if (keyUsageExt->IsSet(EX509DigitalSignature))
   335 					{
   336 					x509Usage |= EX509UsageDigitalSignature;
   337 					}
   338 				if (keyUsageExt->IsSet(EX509NonRepudiation))
   339 					{
   340 					x509Usage |= EX509UsageNonRepudiation;
   341 					}
   342 				if (keyUsageExt->IsSet(EX509KeyEncipherment))
   343 					{
   344 					x509Usage |= EX509UsageKeyEncipherment;
   345 					}
   346 				if (keyUsageExt->IsSet(EX509DataEncipherment))
   347 					{
   348 					x509Usage |= EX509UsageDataEncipherment;
   349 					}
   350 				if (keyUsageExt->IsSet(EX509KeyAgreement))
   351 					{
   352 					x509Usage |= EX509UsageKeyAgreement;
   353 					}
   354 				if (keyUsageExt->IsSet(EX509KeyCertSign))
   355 					{
   356 					x509Usage |= EX509UsageKeyCertSign;
   357 					}
   358 				if (keyUsageExt->IsSet(EX509CRLSign))
   359 					{
   360 					x509Usage |= EX509UsageCRLSign;
   361 					}
   362 				if (keyUsageExt->IsSet(EX509EncipherOnly))
   363 					{
   364 					x509Usage |= EX509UsageEncipherOnly;
   365 					}
   366 				if (keyUsageExt->IsSet(EX509DecipherOnly))
   367 					{
   368 					x509Usage |= EX509UsageDecipherOnly;
   369 					}
   370 
   371 				CleanupStack::PopAndDestroy(keyUsageExt);
   372                 }
   373 
   374 			iKeyFilter.iUsage = KeyUsageX509ToPKCS15Private(x509Usage);
   375 			
   376 			iComputedSubjectKeyId.Zero();
   377 			// For non-user ceriticates (i.e. CA certificates), we use the SubjectKeyIdentifier API, as it
   378 			// tries to get the extension from cert., and calculates a value only if it is not found. This behaviour corresponds to the RFC.
   379 			// For user ceritificates, the key identifier is used for matching key store with cert store, so we cannot use the value in the certificate itself.
   380 			if (iCertificateOwnerType != EUserCertificate)
   381 				{
   382 				iComputedSubjectKeyId = cert->SubjectKeyIdentifierL();
   383 				}
   384 			else
   385 				{
   386 				// For non-CA certs, use the recommended method of computing it from RFC3280, section 4.2.1.2
   387 				iComputedSubjectKeyId = cert->KeyIdentifierL();									
   388 				}
   389 			if (!iSubjectKeyId || *iSubjectKeyId == KNullDesC8)
   390                 {
   391 				iSubjectKeyId = &iComputedSubjectKeyId;
   392                 }
   393 			else if (iSubjectKeyId->Compare(iComputedSubjectKeyId)!=0)
   394                 {//	Different subject ids
   395 				User::Leave(KErrArgument);
   396                 }
   397 			
   398 			CleanupStack::PopAndDestroy(cert);
   399             }	
   400             break;
   401 	
   402         case EWTLSCertificate:
   403             {
   404             CCertificate* cert = CWTLSCertificate::NewLC(*iCertificate);
   405             iComputedSubjectKeyId = cert->KeyIdentifierL();
   406             if (!iSubjectKeyId || *iSubjectKeyId == KNullDesC8)
   407                 {
   408                 iSubjectKeyId = &iComputedSubjectKeyId;
   409                 }
   410             else if (iSubjectKeyId->Compare(iComputedSubjectKeyId)!=0)
   411                 {//	Different subject ids
   412                 User::Leave(KErrArgument);
   413                 }
   414 	
   415             CleanupStack::PopAndDestroy(cert);
   416             }
   417             break;
   418 
   419         case EX509CertificateUrl:
   420             {
   421             iKeyFilter.iUsage = EPKCS15UsageAll;
   422 		
   423             if (!iSubjectKeyId || *iSubjectKeyId == KNullDesC8)
   424                 {
   425                 User::Leave(KErrArgument);
   426                 }
   427             }
   428             break;
   429 
   430         default:
   431             User::Leave(KErrNotSupported);	
   432             break;
   433         }
   434 
   435 	iKeyFilter.iKeyId = *iSubjectKeyId;
   436     }
   437 
   438 void CCheckedCertStore::Remove(const CCTCertInfo& aCertInfo, TRequestStatus& aStatus)
   439     {
   440     assert(iWritableCertStore);
   441     assert(iState == EIdleState);
   442     aStatus = KRequestPending;
   443     iCallerStatus = &aStatus;
   444     iState = ERemove;
   445     iWritableCertStore->Remove(aCertInfo, iStatus);
   446     SetActive();
   447     }
   448 
   449 void CCheckedCertStore::CancelRemove()
   450     {
   451     if (iState == ERemove)
   452         {
   453         Cancel();
   454         }
   455     }
   456 
   457 void CCheckedCertStore::SetApplicability(const CCTCertInfo& aCertInfo, const RArray<TUid>& aApplications, TRequestStatus &aStatus)
   458     {
   459     assert(iWritableCertStore);
   460     assert(iState == EIdleState);
   461     aStatus = KRequestPending;
   462     iCallerStatus = &aStatus;
   463     iState = ESetApplicability;
   464     iWritableCertStore->SetApplicability(aCertInfo, aApplications, iStatus);
   465     SetActive();
   466     }
   467 	
   468 void CCheckedCertStore::CancelSetApplicability()
   469     {
   470     if (iState == ESetApplicability)
   471         {
   472         Cancel();
   473         }    
   474     }
   475 
   476 void CCheckedCertStore::SetTrust(const CCTCertInfo& aCertInfo, TBool aTrusted, TRequestStatus& aStatus)
   477     {
   478     assert(iWritableCertStore);
   479     assert(iState == EIdleState);
   480     aStatus = KRequestPending;
   481     iCallerStatus = &aStatus;
   482     iState = ESetTrust;
   483     iWritableCertStore->SetTrust(aCertInfo, aTrusted, iStatus);
   484     SetActive();
   485     }
   486 
   487 void CCheckedCertStore::CancelSetTrust()
   488     {
   489     if (iState == ESetTrust)
   490         {
   491         Cancel();
   492         }        
   493     }
   494 
   495 TInt CCheckedCertStore::RunError(TInt aError)
   496     {
   497     Complete(aError);
   498 	return KErrNone;
   499     }
   500 	
   501 void CCheckedCertStore::DoCancel()
   502     {
   503 	// (see notes on cancellation in CUnifiedCertStore::DoCancel)
   504 
   505 	switch (iState)
   506 		{
   507         case EGetKeyInfosForList:
   508         case EAdd:
   509 		case ERemove:
   510 		case ESetApplicability:
   511 		case ESetTrust:
   512 			if (iStatus == KRequestPending)
   513 				{
   514 				// Attempt to cancel outstanding request and pass status back to
   515 				// client
   516 				CancelOutstandingRequest();
   517 				Complete(iStatus.Int());
   518 				}
   519 			else
   520 				{
   521 				// We've already been completed - call RunL() to process results
   522 				// and complete client
   523 				TRAPD(err, RunL());
   524 				if (err != KErrNone)
   525 					{
   526 					RunError(err);
   527 					}
   528 				}
   529 			break;
   530 			
   531 		default:
   532 			CancelOutstandingRequest();
   533 			Complete(KErrCancel);
   534 			break;
   535 		}	
   536 	}
   537 
   538 void CCheckedCertStore::CancelOutstandingRequest()
   539 	{
   540     switch (iState)
   541         {
   542         case EList:
   543             iCertStore.CancelList();
   544             break;
   545 
   546         case EInitKeyStoreForAdd:
   547         case EInitKeyStoreForList:
   548             assert(iUnifiedKeyStore);
   549             iUnifiedKeyStore->CancelInitialize();
   550             break;
   551 
   552         case EGetKeyInfosForAdd:
   553         case EGetKeyInfosForList:
   554             assert(iUnifiedKeyStore);
   555             iUnifiedKeyStore->CancelList();
   556             break;
   557 
   558         case EAdd:
   559         case EOldAdd:
   560             assert(iWritableCertStore);
   561             iWritableCertStore->CancelAdd();
   562             break;
   563             
   564         case ERemove:
   565 		    assert(iWritableCertStore);
   566    			iWritableCertStore->CancelRemove();
   567 			break;
   568 			
   569         case ESetApplicability:
   570 		    assert(iWritableCertStore);
   571    			iWritableCertStore->CancelSetApplicability();
   572 			break;
   573 			
   574         case ESetTrust:
   575 		    assert(iWritableCertStore);
   576    			iWritableCertStore->CancelSetTrust();
   577 			break;
   578 
   579 
   580         default:
   581             assert(EFalse);
   582             break;            
   583         }
   584 
   585     Complete(KErrCancel);
   586     }
   587 
   588 void CCheckedCertStore::RunL()
   589     {
   590     assert(iCallerStatus);
   591     
   592 	// we allow only KErrNone OR, possibly, KErrNotSupported after new Add()
   593 	// otherwise - Leave!
   594 	if (iStatus!=KErrNone &&
   595 	    !(iStatus==KErrNotSupported && iState==EAdd) &&
   596 	    !(iStatus == KErrNotFound && (iState==EList || iState==EGetKeyInfosForList || iState==EInitKeyStoreForList)))
   597 		{
   598     	User::Leave(iStatus.Int());
   599     	}
   600 		
   601     switch (iState)
   602         {
   603         case EList:
   604             if (iCallerFilter->iKeyUsage == EX509UsageAll)
   605                 {
   606                 // No key usage filter, so we're done
   607                 Complete(KErrNone);
   608                 }
   609             else
   610                 {
   611                 // Set up key filter according list cert parameters
   612                 if (iCallerFilter->iSubjectKeyIdIsSet)
   613                     {
   614                     iKeyFilter.iKeyId = iCallerFilter->iSubjectKeyId;
   615                     }
   616                 else
   617                     {
   618                     iKeyFilter.iKeyId = KNullDesC8;
   619                     }
   620                 iKeyFilter.iUsage = KeyUsageX509ToPKCS15Private(iCallerFilter->iKeyUsage);
   621                 InitialiseKeyStoreL(EInitKeyStoreForList);
   622                 }
   623             break;
   624 
   625         case EInitKeyStoreForAdd:
   626         case EInitKeyStoreForList:
   627             assert(iUnifiedKeyStore);
   628             iState = (iState == EInitKeyStoreForAdd) ? EGetKeyInfosForAdd : EGetKeyInfosForList;
   629             iUnifiedKeyStore->List(iKeyInfos, iKeyFilter, iStatus);			
   630             SetActive();
   631             break;
   632 
   633         case EGetKeyInfosForList:
   634             BuildCheckedCertificateListL();	//	Not async
   635             Complete(KErrNone);
   636             break;
   637 
   638         case EGetKeyInfosForAdd:
   639             // We have a filter list of keys - there should be one with
   640             // the appropriate subject if we are to add it
   641             if (iKeyInfos.Count() == 0)
   642                 {
   643                 //	The private key can't be found in any key store
   644                 Complete(KErrPrivateKeyNotFound); 
   645                 }
   646             else
   647                 {
   648                 //	OK to go ahead and add the key
   649                 assert(iWritableCertStore);
   650                 iState = EAdd;
   651                 
   652                 // try to use new Add(.., TBool aDeletable, ..)
   653                 // if it's not supported it will return with
   654                 // iStatus set to KErrNotSupported
   655                 iWritableCertStore->Add( *iCertLabel,	// call new Add() method
   656                 						 iFormat,
   657                 						 iCertificateOwnerType,
   658                                          iSubjectKeyId,
   659                                          iIssuerKeyId,
   660                                          *iCertificate,
   661                                          iDeletable,  	// with deletable param
   662                                          iStatus);
   663                 SetActive();
   664                 }
   665             break;
   666                 
   667         case EAdd:
   668          	if (iStatus!=KErrNotSupported)
   669          		{
   670  	     		// Set published property
   671  		      	iPSCertstoreChangePropertyRef.Set(KUnifiedCertStorePropertyCat, // category
   672   												EUnifiedCertStoreFlag,        // key
   673   	    										1);                           // value
   674          		
   675 		        // when here means MCTWritableCertStore was able to find 
   676 		        // child's new Add(..,aDeletable,..) method
   677 				// thus, ok and complete with whatever result it returned
   678 			    Complete(iStatus.Int());
   679 		        }
   680 		    else
   681 		       	{
   682 				// here: call to the new Add() method above didn't work,
   683 				// try to call old Add() method
   684 			    iState = EOldAdd;
   685                	iStatus = KRequestPending;
   686                	iWritableCertStore->Add( *iCertLabel,	
   687                 						 iFormat,
   688                 						 iCertificateOwnerType,
   689                                          iSubjectKeyId,
   690                                          iIssuerKeyId,
   691                                          *iCertificate,
   692                                          iStatus);
   693                 SetActive();                                         
   694                	} 
   695            	break;
   696 
   697         case EOldAdd:
   698         case ERemove:  
   699         case ESetApplicability:     
   700 		case ESetTrust:              
   701       		// Set published property
   702  	      	iPSCertstoreChangePropertyRef.Set(KUnifiedCertStorePropertyCat, // category
   703 											EUnifiedCertStoreFlag,        // key
   704  	      									1);                           // value      
   705             Complete(iStatus.Int());
   706             break;
   707             
   708         default:
   709             assert(EFalse);
   710             break;
   711         }
   712     }
   713 	
   714 void CCheckedCertStore::InitialiseKeyStoreL(TState aNextState)
   715     {
   716     assert(aNextState == EInitKeyStoreForAdd || aNextState == EInitKeyStoreForList);
   717 	assert(!iUnifiedKeyStore);
   718     
   719 	iUnifiedKeyStore = CUnifiedKeyStore::NewL(iFs);
   720     iUnifiedKeyStore->Initialize(iStatus);		
   721     iState = aNextState;
   722     SetActive();
   723     }
   724 
   725 void CCheckedCertStore::BuildCheckedCertificateListL()
   726     {
   727 	TInt certCount = iCallerCerts->Count();
   728     TInt keyCount = iKeyInfos.Count();
   729     
   730     // Iterate backwards through cert array so remove doesn't affect indicies
   731     for (TInt i = certCount - 1 ; i >= 0 ; --i)
   732         {
   733 		CCTCertInfo* certInfo = (*iCallerCerts)[i];
   734 
   735         // It's problem in the certstore implementation if the list contains NULL pointers
   736         assert(certInfo); 
   737 
   738         // Check for key with corresponding id
   739 		TBool accept = EFalse;
   740         for (TInt j = 0 ; j < keyCount ; ++j)
   741             {
   742             if (iKeyInfos[j]->ID()==certInfo->SubjectKeyId())
   743                 {
   744                 accept = ETrue;
   745                 break;
   746                 }
   747             }
   748 
   749         // If we don't have it, remove and release the cert info
   750         if (!accept)
   751             {
   752             iCallerCerts->Remove(i);
   753             certInfo->Release();
   754             }
   755         }
   756     }
   757 
   758 void CCheckedCertStore::Complete(TInt aError)
   759     {
   760 	if (iCallerStatus)
   761         {
   762 		User::RequestComplete(iCallerStatus, aError);
   763         }
   764     Cleanup();
   765     }
   766 
   767 void CCheckedCertStore::Cleanup()
   768     {
   769     //	Reset the state machine	
   770 	iState = EIdleState;
   771 	iKeyInfos.Close();
   772     iSubjectKeyId = NULL;
   773     iIssuerKeyId = NULL;
   774 
   775     delete iCertLabel;
   776     iCertLabel = NULL;
   777 
   778     delete iCertificate;
   779     iCertificate = NULL;
   780 
   781     delete iUnifiedKeyStore;
   782     iUnifiedKeyStore = 0;		
   783 
   784     iCallerCerts = NULL;
   785     iCallerFilter = NULL;
   786     }