os/security/cryptoservices/certificateandkeymgmt/swicertstore/CSWICertStoreImpl.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) 2005-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 "CSWICertStoreImpl.h"
    20 #include "CSWICertStoreEntryList.h"
    21 #include "CSWICertStoreEntry.h"
    22 #include "CSWICertStoreTokenType.h"
    23 #include "CSWICertStoreToken.h"
    24 #include "unifiedcertstore.h"
    25 #include "log.h"
    26 
    27 #include <certstorepatchdata.h>
    28 #include <ccertattributefilter.h>
    29 #include <f32file.h>
    30 #include <u32hal.h> 
    31 #include <e32svr.h>
    32 
    33 _LIT(KSWICertStoreZFilename,"z:\\resource\\swicertstore.dat");
    34 _LIT(KSWIWritableCertStorePath,"!:\\resource\\swicertstore\\dat\\");
    35 _LIT(KSWIROMCertStoreFilenamePattern,"z:\\resource\\swicertstore*.dat");
    36 
    37 /////////////////////////////////////////////////////////////////////////////////////////
    38 //CFSCertStoreServer
    39 /////////////////////////////////////////////////////////////////////////////////////////
    40 
    41 CSWICertStoreImpl* CSWICertStoreImpl::NewL(MCTToken& aToken, RFs& aFs)
    42 	{
    43 	CSWICertStoreImpl* self = new (ELeave) CSWICertStoreImpl(aToken, aFs);
    44 	CleanupStack::PushL(self);
    45 	self->ConstructL();
    46 	CleanupStack::Pop(self);
    47 	return self;
    48 	}
    49 
    50 CSWICertStoreImpl::CSWICertStoreImpl(MCTToken& aToken, RFs& aFs) :
    51         CActive(EPriorityStandard), iToken(aToken), iFs(aFs)
    52 	{
    53 	CActiveScheduler::Add(this);
    54 	}
    55 
    56 void CSWICertStoreImpl::ConstructL()
    57 	{
    58 	TInt err = iSwicertstoreProperty.Attach(KUnifiedCertStorePropertyCat,
    59 											EUnifiedCertStoreFlag, EOwnerThread);
    60 	
    61 	User::LeaveIfError(err);
    62 
    63 	iPatchableConst = KAggregateCertStore;
    64 	
    65 	#ifdef __WINS__
    66 		// For the emulator allow the constant to be patched via epoc.ini
    67 		UserSvr::HalFunction(EHalGroupEmulator, EEmulatorHalIntProperty,
    68 		(TAny*)"KAggregateCertStore", &iPatchableConst); // read emulator property (if present)
    69 	#endif		
    70 	
    71 	
    72 	// if patchable constant is enabled
    73 	if(iPatchableConst)
    74 		{
    75 		// Setup composite ROM Certstore
    76 		SetupCompositeROMCertStoreL();
    77 		}
    78 	else
    79 		{
    80 		// Setup the ROM CertStore
    81 		SetupROMCertStoreL();		
    82 		}
    83 	
    84 	// Setup the Writable CertStore
    85 	// Bear in mind we need to trap NewL(), OpenLC() etc.
    86 	// Any error occurs, it should still setup the z:\ certstore
    87 	TRAP_IGNORE(SetupWritableCertStoreL());
    88 
    89 	// aggregate ROM composite certstore and writable certstore if patchable constant is enabled
    90 	if(iPatchableConst)
    91 		{
    92 		if(iCEntryList)
    93 			{
    94 			// ETrue to indicate that we are passing 'iZEntryList'.
    95 			// This action will remove duplicate entries from 'iZEntryList'.
    96 			MergeCertificateEntryListsL(*iZEntryList, ETrue);	
    97 			}
    98 		}
    99 	// Subscribe to the Property
   100 	iSwicertstoreProperty.Subscribe(iStatus);
   101 	SetActive();
   102 	}
   103 
   104 void CSWICertStoreImpl::DoCancel()
   105 	{
   106 	// Cancel outstanding request
   107     iSwicertstoreProperty.Cancel();
   108 	}
   109 
   110 void CSWICertStoreImpl::RunL()
   111 	{
   112 	// Resubscribe before processing new value to prevent missing updates
   113 	iSwicertstoreProperty.Subscribe(iStatus);
   114 	SetActive();
   115 
   116 	// Bear in mind we need to trap NewL(), OpenLC() etc.
   117 	TRAP_IGNORE(SetupWritableCertStoreL());
   118 	}
   119 
   120 void CSWICertStoreImpl::SetupWritableCertStoreL()
   121 	{
   122 	TInt err = KErrNone;
   123  	
   124  	delete iCEntryList;
   125 	iCEntryList = NULL;
   126 	
   127 	// The attached file will be freed as well.
   128 	delete iCStore;
   129 	iCStore = NULL;
   130 		
   131  	do
   132  		{
   133  		// Open the store if it is there
   134  		RFile file;
   135  		CDir* entryList = NULL;
   136 
   137 		TPath writableSwiCertStorePath(KSWIWritableCertStorePath);
   138 		
   139 		TChar systemDriveChar = RFs::GetSystemDriveChar();
   140 
   141 		writableSwiCertStorePath[0] = systemDriveChar;
   142 		
   143 		if (KErrNone == iFs.GetDir (writableSwiCertStorePath, KEntryAttNormal,
   144 		 	ESortByName|EDirsFirst, entryList))
   145 				{
   146 				if (entryList)
   147 		                {
   148 						CleanupStack::PushL(entryList);
   149 				 
   150 						TFileName certstoreFile;
   151 						TInt count = entryList->Count();
   152 			
   153 						if (count > 0)
   154 					            {
   155 								// Get the highest version certstore file
   156 							 	const TEntry& entry = (*entryList)[count - 1];
   157 				
   158 							 	certstoreFile.Append(writableSwiCertStorePath);
   159 							 	certstoreFile.Append(entry.iName);
   160 							 
   161 							 	CleanupStack::PopAndDestroy(1, entryList);
   162 							 	}
   163 						else
   164 					            {
   165 								CleanupStack::PopAndDestroy(1, entryList);
   166 
   167 							 	// No certstore in this directory
   168 							 	// Currently there should not have any directory in this path
   169 							 	return;
   170 							 	}
   171 
   172 						err = file.Open(iFs, certstoreFile, EFileShareReadersOnly);
   173 						 
   174 						if (err != KErrNone && err != KErrNotFound)
   175 								{
   176 								// Log the error to the system file.
   177 								DEBUG_PRINTF2(_L8("Error Opening SWI writable certstore: %S."), &certstoreFile);
   178 							 	return;
   179 							 	}
   180 						 
   181 						 if (err == KErrNone)
   182 					            {
   183 							 	// File exist
   184 							 	CleanupClosePushL(file);
   185 							 
   186 							 	TRAP_IGNORE(iCStore = CPermanentFileStore::FromL(file));
   187 							 
   188 							 	if (iCStore)
   189 							    		{
   190 								 		CleanupStack::Pop(&file); // now owned by store
   191 							 
   192 										// Read id of cert list stream
   193 								 		TStreamId streamId;
   194 								 		RStoreReadStream stream;
   195 										stream.OpenLC(*iCStore, iCStore->Root());
   196 										stream >> streamId;
   197 										CleanupStack::PopAndDestroy(&stream);
   198 										 
   199 										// Read the certificate list
   200 										RStoreReadStream entryStream;
   201 										entryStream.OpenLC(*iCStore, streamId);
   202 										iCEntryList = CSWICertStoreEntryList::NewL(entryStream, iToken, iCertIndex);
   203 										 
   204 								 		CleanupStack::PopAndDestroy(&entryStream);
   205 
   206 								 		// Record the writable certstore index
   207 								 		// The index will then be used to set the tokenId in the
   208 								 		// in handle, so to make the handle unique.
   209 								 		iCertIndex += iCEntryList->Count();
   210 								 		}
   211 						 		else
   212 							         	{
   213 										// The file format might not comply to the CPermanentFileStore format
   214 										CleanupStack::PopAndDestroy(&file);
   215 
   216 								 		// Log the error to the system file.
   217 								 		DEBUG_PRINTF2(_L8("Error Opening SWI writable certstore: %S."), &certstoreFile);
   218 
   219 								 		return;
   220 							         	}   
   221 					            }
   222 		                }
   223 				}
   224  		}while (err == KErrNotFound);  // There is a very slight chance that the file has been deleted
   225 	}
   226 
   227 void CSWICertStoreImpl::MergeCertificateEntryListsL(const CSWICertStoreEntryList& aSourceList, TBool aIsZEntryList)
   228 	{
   229 	ASSERT(iPatchableConst);
   230 	// if patchable constant is enabled
   231 	
   232 	TInt sourceCount = aSourceList.Count();
   233 	for(TInt i = 0; i < sourceCount; i++)
   234 		{
   235 		if(!aIsZEntryList)
   236 			{
   237 			if (!iZEntryList->LabelExists(aSourceList.GetByIndex(i).CertInfo().Label()))
   238 				{
   239 				// Aggregation: Append this entry in the ROM composite list 
   240 				const CSWICertStoreEntry& entry = aSourceList.GetByIndex(i);
   241 				CSWICertStoreEntry* newEntry = CSWICertStoreEntry::NewL(entry.CertInfo(),
   242 																entry.CertificateApps(),
   243 																entry.Trusted(),
   244 																entry.DataStreamId(),
   245 																entry.CertMetaInfo(), 
   246 																entry.StoreIndex());
   247 				CleanupStack::PushL(newEntry);
   248 				iZEntryList->AppendL(newEntry);
   249 				// iZEntryList has taken ownership
   250 				CleanupStack::Pop(newEntry); 
   251 				}
   252 			// Eclipsing: Higher order store certificates with same labels take precedence over lower order store certificates.
   253 			// therefore the later are not included in the composite certificate entry list.
   254 			// N.B iCertIndex will not give total count of certificates because of Eclipsing mechanism.
   255 			// Higher order store certificates are ones which are aggregated prior to other certificates. 
   256 			}
   257 		else
   258 			{
   259 			// remove duplicate label entries from the 'iZEntryList'
   260 			if (iCEntryList->LabelExists(aSourceList.GetByIndex(i).CertInfo().Label()))
   261 				{
   262 				// Remove entries from iZEntryList having same labels as in iCEntryList.
   263 				iZEntryList->Remove(i);
   264 				}
   265 			}
   266 		}
   267 	}
   268 
   269 void CSWICertStoreImpl::SetupCompositeROMCertStoreL()
   270 	{
   271 	ASSERT(iPatchableConst);
   272 	
   273 	// Collect the file present in ROM certstore private directory.
   274 	//The files in this list will be in descending order by name.
   275 	CDir* filenameList = NULL;
   276 
   277 	User::LeaveIfError(iFs.GetDir(KSWIROMCertStoreFilenamePattern, KEntryAttNormal, ESortByName|EDescending, filenameList));	
   278 	CleanupStack::PushL(filenameList);
   279 	TInt count = filenameList->Count();
   280 	TStreamId streamId;
   281 
   282 	// make full path to the certstore files residing on ROM drive	
   283 	// N.B filenameList will contain filenames in descending order.
   284 	RFile file;
   285 	RStoreReadStream stream;
   286 	
   287 	// create an empty list, this will be the composite certificate entry list
   288 	iZEntryList = CSWICertStoreEntryList::NewL();
   289 	// the 'corruptCount' is used for proper correctly referencing valid certstores   
   290 	TInt corruptCount=0;
   291 	for(TInt i = 0; i < count; i++)
   292 		{
   293 		RBuf romFile;
   294 		romFile.CreateL(KMaxFileName);
   295 		CleanupClosePushL(romFile);
   296 		romFile.Append(_L("z:\\resource\\"));
   297 		romFile.Append(((*filenameList)[i]).iName);
   298 		User::LeaveIfError(file.Open(iFs,romFile,EFileShareReadersOnly));
   299 		CleanupClosePushL(file);
   300 		// open and append the store in array of stores
   301 		CPermanentFileStore* store = NULL;
   302 		// if there is any corrupt certstore present then we will simply ignore its
   303 		// aggregation and proceed with aggregating remaining stores.
   304 		// ownership is transfered to 'iZArrayOfStores' 
   305 		TRAPD(err, store = CPermanentFileStore::FromL(file));
   306 		if(err != KErrNone)
   307 			{
   308 			corruptCount++;
   309 			//cleanup file and romFile.
   310 			CleanupStack::PopAndDestroy(2, &romFile);
   311 			continue;
   312 			}
   313 		iZArrayOfStores.AppendL(store);
   314 		TInt index = i - corruptCount;
   315 		// open the root stream containing the streamId of info stream.
   316 		stream.OpenLC(*(iZArrayOfStores)[index],(iZArrayOfStores[index])->Root());
   317 		stream >> streamId;
   318 		CleanupStack::PopAndDestroy(&stream);
   319 
   320 		// re-open the info stream containing the certificates entry list.
   321 		stream.OpenLC(*(iZArrayOfStores)[index],streamId);
   322 		
   323 		// store index for these entries will be 'index'.
   324 		// iCertIndex will be 0 for the first certificate entry list passed.
   325 		CSWICertStoreEntryList* temp_list = CSWICertStoreEntryList::NewL(stream, iToken,iCertIndex,index);
   326 		// increment to have unique certificate Ids allocation.
   327 		iCertIndex += temp_list->Count();
   328 		CleanupStack::PushL(temp_list);
   329 		MergeCertificateEntryListsL(*temp_list);
   330 		//temp_list, stream, file and romFile.
   331 		CleanupStack::PopAndDestroy(4, &romFile);
   332 		} 
   333 	CleanupStack::PopAndDestroy(filenameList);
   334 	}
   335 
   336 void CSWICertStoreImpl::SetupROMCertStoreL()
   337 	{
   338 	// Open the store
   339 	RFile file;
   340 	User::LeaveIfError(file.Open(iFs, KSWICertStoreZFilename, EFileShareReadersOnly));
   341 	CleanupClosePushL(file);
   342 	iZStore = CPermanentFileStore::FromL(file);
   343 	CleanupStack::Pop(&file); // now owned by store
   344 
   345 	// Read id of cert list stream
   346 	TStreamId streamId;
   347 	RStoreReadStream stream;
   348 	stream.OpenLC(*iZStore, iZStore->Root());
   349 	stream >> streamId;
   350 	CleanupStack::PopAndDestroy(&stream);
   351 
   352 	// Read the certificate list
   353 	RStoreReadStream entryStream;
   354 	entryStream.OpenLC(*iZStore, streamId);
   355 	iZEntryList = CSWICertStoreEntryList::NewL(entryStream, iToken);
   356 	CleanupStack::PopAndDestroy(&entryStream);
   357 
   358 	// set the valid indexes of writable certstore
   359 	iCertIndex = iZEntryList->Count();
   360 	}
   361 
   362 CSWICertStoreImpl::~CSWICertStoreImpl()
   363 	{
   364 	Cancel();
   365 	iSwicertstoreProperty.Close();
   366 	delete iCEntryList;
   367 	delete iZEntryList;
   368 	delete iCStore;
   369 	delete iZStore;
   370 	iZArrayOfStores.ResetAndDestroy();
   371 	}
   372 
   373 void CSWICertStoreImpl::ListL(RMPointerArray<CCTCertInfo>& aCerts,
   374 			      const CCertAttributeFilter& aFilter)
   375 	{
   376 	if (iCEntryList)
   377 	        {
   378 			FilterCertificateListL(aCerts, aFilter, *iCEntryList);
   379 			}
   380 	FilterCertificateListL(aCerts, aFilter, *iZEntryList);
   381 	}
   382 
   383 CCTCertInfo* CSWICertStoreImpl::GetCertL(const TCTTokenObjectHandle& aHandle)
   384 	{
   385 	TBool isCEntryHandle = EFalse;
   386 	const CSWICertStoreEntry* entry = GetCSWICertStoreEntryL(aHandle, isCEntryHandle);	
   387 	return CCTCertInfo::NewL(entry->CertInfo());
   388 	}
   389 
   390 void CSWICertStoreImpl::ApplicationsL(const TCTTokenObjectHandle& aHandle, RArray<TUid>& aApplications)
   391 	{
   392 	TBool isCEntryHandle = EFalse;
   393 	const CSWICertStoreEntry* entry = GetCSWICertStoreEntryL(aHandle, isCEntryHandle);
   394 	
   395 	const RArray<TUid>& apps = entry->CertificateApps();
   396 	TInt count = apps.Count();
   397 	
   398 	for (TInt i = 0 ; i < count ; ++i)
   399 		{
   400 		User::LeaveIfError(aApplications.Append(apps[i]));
   401 		}
   402 	}
   403 
   404 TBool CSWICertStoreImpl::IsApplicableL(const TCTTokenObjectHandle& aHandle, TUid aApplication)
   405 	{
   406 	TBool isCEntryHandle = EFalse;
   407 	const CSWICertStoreEntry* entry = GetCSWICertStoreEntryL(aHandle, isCEntryHandle);
   408 	return entry->IsApplicable(aApplication);
   409 	}
   410 
   411 TBool CSWICertStoreImpl::TrustedL(const TCTTokenObjectHandle& aHandle)
   412 	{
   413 	TBool isCEntryHandle = EFalse;	
   414 	const CSWICertStoreEntry* entry = GetCSWICertStoreEntryL(aHandle, isCEntryHandle);
   415 	return entry->Trusted();
   416 	}
   417 
   418 void CSWICertStoreImpl::RetrieveL(const TCTTokenObjectHandle& aHandle, TDes8& aEncodedCert)
   419 	{
   420 	TBool isCEntryHandle = EFalse;
   421 	const CSWICertStoreEntry* entry = GetCSWICertStoreEntryL(aHandle, isCEntryHandle);
   422 	RStoreReadStream stream;
   423 	
   424 	if (iCEntryList && isCEntryHandle)
   425 		{
   426 		stream.OpenLC(*iCStore, entry->DataStreamId());
   427 		}
   428 	else
   429 	    {
   430 	    // if patchable constant is enabled
   431 	    if (iPatchableConst)
   432 	    	{
   433 	    	stream.OpenLC(*(iZArrayOfStores[entry->StoreIndex()]), entry->DataStreamId());
   434 	    	}
   435 	    else
   436 	    	{
   437 	    	stream.OpenLC(*iZStore, entry->DataStreamId());
   438 	    	}
   439 		}
   440 
   441 	TInt size = entry->CertInfo().Size();
   442 
   443 	if (aEncodedCert.MaxLength() < size)
   444 			{
   445 			User::Leave(KErrOverflow);
   446 			}
   447 
   448 	stream.ReadL(aEncodedCert, size);
   449 	CleanupStack::PopAndDestroy(&stream);
   450 	}
   451 
   452 const TCertMetaInfo& CSWICertStoreImpl::CertMetaInfoL(const TCTTokenObjectHandle& aHandle) const
   453 	{
   454 	TBool isCEntryHandle = EFalse;
   455 	const CSWICertStoreEntry* entry = GetCSWICertStoreEntryL(aHandle, isCEntryHandle);
   456 	return entry->CertMetaInfo(); 
   457 	}
   458 
   459 const CSWICertStoreEntry* CSWICertStoreImpl::GetCSWICertStoreEntryL(const TCTTokenObjectHandle& aHandle, TBool& aCEntryHandle) const
   460 	{
   461 	if (iCEntryList)
   462 	        {
   463 			const CSWICertStoreEntry* entry = NULL;
   464 
   465 			TRAPD (retCode, entry = &(iCEntryList->GetByHandleL(aHandle)));
   466 
   467 			if (entry && (retCode == KErrNone))
   468 			        {
   469 			        aCEntryHandle = ETrue;
   470 					return entry;
   471 					}
   472 			}
   473 	return &iZEntryList->GetByHandleL(aHandle);
   474 	}
   475 
   476 void CSWICertStoreImpl::AddIfMatchesFilterL(RMPointerArray<CCTCertInfo>& aCerts, const CCertAttributeFilter& aFilter, const CSWICertStoreEntry& aEntry)
   477 	{
   478 	const CCTCertInfo& certInfo = aEntry.CertInfo();
   479 	TBool accept = ETrue;
   480 			  
   481 	if (aFilter.iUidIsSet)
   482 		{
   483 		accept = aEntry.IsApplicable(aFilter.iUid);
   484 		}
   485 	if (aFilter.iFormatIsSet && accept)
   486 		{
   487 		accept = (aFilter.iFormat == certInfo.CertificateFormat());
   488 		}
   489 	if (aFilter.iOwnerTypeIsSet && accept)
   490 		{
   491 		accept = (aFilter.iOwnerType == certInfo.CertificateOwnerType());
   492 		}
   493 	if (aFilter.iSubjectKeyIdIsSet && accept)
   494 		{
   495 		accept = (aFilter.iSubjectKeyId == certInfo.SubjectKeyId());
   496 		}
   497 	if (aFilter.iLabelIsSet && accept)
   498 		{
   499 		accept = (aFilter.iLabel == certInfo.Label());
   500 		}
   501 			  
   502 	if (accept)
   503 		{
   504 		CCTCertInfo* newCertInfo = CCTCertInfo::NewLC(certInfo);
   505 		User::LeaveIfError(aCerts.Append(newCertInfo));
   506 		CleanupStack::Pop(newCertInfo);
   507 		}
   508 	}
   509 
   510 void CSWICertStoreImpl::FilterCertificateListL(RMPointerArray<CCTCertInfo>& aCerts,
   511 			   const CCertAttributeFilter& aFilter, const CSWICertStoreEntryList& aEntryList)
   512 	{
   513 	TInt count = aEntryList.Count();
   514 	for (TInt index = 0; index < count; index++)
   515 		{
   516 		const CSWICertStoreEntry& entry = aEntryList.GetByIndex(index);
   517 		AddIfMatchesFilterL(aCerts, aFilter, entry);
   518 		}
   519 	}
   520 
   521