cryptoservices/certificateandkeymgmt/certstore/CCheckedCertStore.cpp
changeset 0 2c201484c85f
child 8 35751d3474b7
equal deleted inserted replaced
-1:000000000000 0:2c201484c85f
       
     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     }