os/security/cryptoservices/certificateandkeymgmt/swicertstore/CSWICertStoreImpl.cpp
First public contribution.
2 * Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
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".
9 * Initial Contributors:
10 * Nokia Corporation - initial contribution.
19 #include "CSWICertStoreImpl.h"
20 #include "CSWICertStoreEntryList.h"
21 #include "CSWICertStoreEntry.h"
22 #include "CSWICertStoreTokenType.h"
23 #include "CSWICertStoreToken.h"
24 #include "unifiedcertstore.h"
27 #include <certstorepatchdata.h>
28 #include <ccertattributefilter.h>
33 _LIT(KSWICertStoreZFilename,"z:\\resource\\swicertstore.dat");
34 _LIT(KSWIWritableCertStorePath,"!:\\resource\\swicertstore\\dat\\");
35 _LIT(KSWIROMCertStoreFilenamePattern,"z:\\resource\\swicertstore*.dat");
37 /////////////////////////////////////////////////////////////////////////////////////////
39 /////////////////////////////////////////////////////////////////////////////////////////
41 CSWICertStoreImpl* CSWICertStoreImpl::NewL(MCTToken& aToken, RFs& aFs)
43 CSWICertStoreImpl* self = new (ELeave) CSWICertStoreImpl(aToken, aFs);
44 CleanupStack::PushL(self);
46 CleanupStack::Pop(self);
50 CSWICertStoreImpl::CSWICertStoreImpl(MCTToken& aToken, RFs& aFs) :
51 CActive(EPriorityStandard), iToken(aToken), iFs(aFs)
53 CActiveScheduler::Add(this);
56 void CSWICertStoreImpl::ConstructL()
58 TInt err = iSwicertstoreProperty.Attach(KUnifiedCertStorePropertyCat,
59 EUnifiedCertStoreFlag, EOwnerThread);
61 User::LeaveIfError(err);
63 iPatchableConst = KAggregateCertStore;
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)
72 // if patchable constant is enabled
75 // Setup composite ROM Certstore
76 SetupCompositeROMCertStoreL();
80 // Setup the ROM CertStore
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());
89 // aggregate ROM composite certstore and writable certstore if patchable constant is enabled
94 // ETrue to indicate that we are passing 'iZEntryList'.
95 // This action will remove duplicate entries from 'iZEntryList'.
96 MergeCertificateEntryListsL(*iZEntryList, ETrue);
99 // Subscribe to the Property
100 iSwicertstoreProperty.Subscribe(iStatus);
104 void CSWICertStoreImpl::DoCancel()
106 // Cancel outstanding request
107 iSwicertstoreProperty.Cancel();
110 void CSWICertStoreImpl::RunL()
112 // Resubscribe before processing new value to prevent missing updates
113 iSwicertstoreProperty.Subscribe(iStatus);
116 // Bear in mind we need to trap NewL(), OpenLC() etc.
117 TRAP_IGNORE(SetupWritableCertStoreL());
120 void CSWICertStoreImpl::SetupWritableCertStoreL()
127 // The attached file will be freed as well.
133 // Open the store if it is there
135 CDir* entryList = NULL;
137 TPath writableSwiCertStorePath(KSWIWritableCertStorePath);
139 TChar systemDriveChar = RFs::GetSystemDriveChar();
141 writableSwiCertStorePath[0] = systemDriveChar;
143 if (KErrNone == iFs.GetDir (writableSwiCertStorePath, KEntryAttNormal,
144 ESortByName|EDirsFirst, entryList))
148 CleanupStack::PushL(entryList);
150 TFileName certstoreFile;
151 TInt count = entryList->Count();
155 // Get the highest version certstore file
156 const TEntry& entry = (*entryList)[count - 1];
158 certstoreFile.Append(writableSwiCertStorePath);
159 certstoreFile.Append(entry.iName);
161 CleanupStack::PopAndDestroy(1, entryList);
165 CleanupStack::PopAndDestroy(1, entryList);
167 // No certstore in this directory
168 // Currently there should not have any directory in this path
172 err = file.Open(iFs, certstoreFile, EFileShareReadersOnly);
174 if (err != KErrNone && err != KErrNotFound)
176 // Log the error to the system file.
177 DEBUG_PRINTF2(_L8("Error Opening SWI writable certstore: %S."), &certstoreFile);
184 CleanupClosePushL(file);
186 TRAP_IGNORE(iCStore = CPermanentFileStore::FromL(file));
190 CleanupStack::Pop(&file); // now owned by store
192 // Read id of cert list stream
194 RStoreReadStream stream;
195 stream.OpenLC(*iCStore, iCStore->Root());
197 CleanupStack::PopAndDestroy(&stream);
199 // Read the certificate list
200 RStoreReadStream entryStream;
201 entryStream.OpenLC(*iCStore, streamId);
202 iCEntryList = CSWICertStoreEntryList::NewL(entryStream, iToken, iCertIndex);
204 CleanupStack::PopAndDestroy(&entryStream);
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();
213 // The file format might not comply to the CPermanentFileStore format
214 CleanupStack::PopAndDestroy(&file);
216 // Log the error to the system file.
217 DEBUG_PRINTF2(_L8("Error Opening SWI writable certstore: %S."), &certstoreFile);
224 }while (err == KErrNotFound); // There is a very slight chance that the file has been deleted
227 void CSWICertStoreImpl::MergeCertificateEntryListsL(const CSWICertStoreEntryList& aSourceList, TBool aIsZEntryList)
229 ASSERT(iPatchableConst);
230 // if patchable constant is enabled
232 TInt sourceCount = aSourceList.Count();
233 for(TInt i = 0; i < sourceCount; i++)
237 if (!iZEntryList->LabelExists(aSourceList.GetByIndex(i).CertInfo().Label()))
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(),
244 entry.DataStreamId(),
245 entry.CertMetaInfo(),
247 CleanupStack::PushL(newEntry);
248 iZEntryList->AppendL(newEntry);
249 // iZEntryList has taken ownership
250 CleanupStack::Pop(newEntry);
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.
259 // remove duplicate label entries from the 'iZEntryList'
260 if (iCEntryList->LabelExists(aSourceList.GetByIndex(i).CertInfo().Label()))
262 // Remove entries from iZEntryList having same labels as in iCEntryList.
263 iZEntryList->Remove(i);
269 void CSWICertStoreImpl::SetupCompositeROMCertStoreL()
271 ASSERT(iPatchableConst);
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;
277 User::LeaveIfError(iFs.GetDir(KSWIROMCertStoreFilenamePattern, KEntryAttNormal, ESortByName|EDescending, filenameList));
278 CleanupStack::PushL(filenameList);
279 TInt count = filenameList->Count();
282 // make full path to the certstore files residing on ROM drive
283 // N.B filenameList will contain filenames in descending order.
285 RStoreReadStream stream;
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
291 for(TInt i = 0; i < count; i++)
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));
309 //cleanup file and romFile.
310 CleanupStack::PopAndDestroy(2, &romFile);
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());
318 CleanupStack::PopAndDestroy(&stream);
320 // re-open the info stream containing the certificates entry list.
321 stream.OpenLC(*(iZArrayOfStores)[index],streamId);
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);
333 CleanupStack::PopAndDestroy(filenameList);
336 void CSWICertStoreImpl::SetupROMCertStoreL()
340 User::LeaveIfError(file.Open(iFs, KSWICertStoreZFilename, EFileShareReadersOnly));
341 CleanupClosePushL(file);
342 iZStore = CPermanentFileStore::FromL(file);
343 CleanupStack::Pop(&file); // now owned by store
345 // Read id of cert list stream
347 RStoreReadStream stream;
348 stream.OpenLC(*iZStore, iZStore->Root());
350 CleanupStack::PopAndDestroy(&stream);
352 // Read the certificate list
353 RStoreReadStream entryStream;
354 entryStream.OpenLC(*iZStore, streamId);
355 iZEntryList = CSWICertStoreEntryList::NewL(entryStream, iToken);
356 CleanupStack::PopAndDestroy(&entryStream);
358 // set the valid indexes of writable certstore
359 iCertIndex = iZEntryList->Count();
362 CSWICertStoreImpl::~CSWICertStoreImpl()
365 iSwicertstoreProperty.Close();
370 iZArrayOfStores.ResetAndDestroy();
373 void CSWICertStoreImpl::ListL(RMPointerArray<CCTCertInfo>& aCerts,
374 const CCertAttributeFilter& aFilter)
378 FilterCertificateListL(aCerts, aFilter, *iCEntryList);
380 FilterCertificateListL(aCerts, aFilter, *iZEntryList);
383 CCTCertInfo* CSWICertStoreImpl::GetCertL(const TCTTokenObjectHandle& aHandle)
385 TBool isCEntryHandle = EFalse;
386 const CSWICertStoreEntry* entry = GetCSWICertStoreEntryL(aHandle, isCEntryHandle);
387 return CCTCertInfo::NewL(entry->CertInfo());
390 void CSWICertStoreImpl::ApplicationsL(const TCTTokenObjectHandle& aHandle, RArray<TUid>& aApplications)
392 TBool isCEntryHandle = EFalse;
393 const CSWICertStoreEntry* entry = GetCSWICertStoreEntryL(aHandle, isCEntryHandle);
395 const RArray<TUid>& apps = entry->CertificateApps();
396 TInt count = apps.Count();
398 for (TInt i = 0 ; i < count ; ++i)
400 User::LeaveIfError(aApplications.Append(apps[i]));
404 TBool CSWICertStoreImpl::IsApplicableL(const TCTTokenObjectHandle& aHandle, TUid aApplication)
406 TBool isCEntryHandle = EFalse;
407 const CSWICertStoreEntry* entry = GetCSWICertStoreEntryL(aHandle, isCEntryHandle);
408 return entry->IsApplicable(aApplication);
411 TBool CSWICertStoreImpl::TrustedL(const TCTTokenObjectHandle& aHandle)
413 TBool isCEntryHandle = EFalse;
414 const CSWICertStoreEntry* entry = GetCSWICertStoreEntryL(aHandle, isCEntryHandle);
415 return entry->Trusted();
418 void CSWICertStoreImpl::RetrieveL(const TCTTokenObjectHandle& aHandle, TDes8& aEncodedCert)
420 TBool isCEntryHandle = EFalse;
421 const CSWICertStoreEntry* entry = GetCSWICertStoreEntryL(aHandle, isCEntryHandle);
422 RStoreReadStream stream;
424 if (iCEntryList && isCEntryHandle)
426 stream.OpenLC(*iCStore, entry->DataStreamId());
430 // if patchable constant is enabled
433 stream.OpenLC(*(iZArrayOfStores[entry->StoreIndex()]), entry->DataStreamId());
437 stream.OpenLC(*iZStore, entry->DataStreamId());
441 TInt size = entry->CertInfo().Size();
443 if (aEncodedCert.MaxLength() < size)
445 User::Leave(KErrOverflow);
448 stream.ReadL(aEncodedCert, size);
449 CleanupStack::PopAndDestroy(&stream);
452 const TCertMetaInfo& CSWICertStoreImpl::CertMetaInfoL(const TCTTokenObjectHandle& aHandle) const
454 TBool isCEntryHandle = EFalse;
455 const CSWICertStoreEntry* entry = GetCSWICertStoreEntryL(aHandle, isCEntryHandle);
456 return entry->CertMetaInfo();
459 const CSWICertStoreEntry* CSWICertStoreImpl::GetCSWICertStoreEntryL(const TCTTokenObjectHandle& aHandle, TBool& aCEntryHandle) const
463 const CSWICertStoreEntry* entry = NULL;
465 TRAPD (retCode, entry = &(iCEntryList->GetByHandleL(aHandle)));
467 if (entry && (retCode == KErrNone))
469 aCEntryHandle = ETrue;
473 return &iZEntryList->GetByHandleL(aHandle);
476 void CSWICertStoreImpl::AddIfMatchesFilterL(RMPointerArray<CCTCertInfo>& aCerts, const CCertAttributeFilter& aFilter, const CSWICertStoreEntry& aEntry)
478 const CCTCertInfo& certInfo = aEntry.CertInfo();
479 TBool accept = ETrue;
481 if (aFilter.iUidIsSet)
483 accept = aEntry.IsApplicable(aFilter.iUid);
485 if (aFilter.iFormatIsSet && accept)
487 accept = (aFilter.iFormat == certInfo.CertificateFormat());
489 if (aFilter.iOwnerTypeIsSet && accept)
491 accept = (aFilter.iOwnerType == certInfo.CertificateOwnerType());
493 if (aFilter.iSubjectKeyIdIsSet && accept)
495 accept = (aFilter.iSubjectKeyId == certInfo.SubjectKeyId());
497 if (aFilter.iLabelIsSet && accept)
499 accept = (aFilter.iLabel == certInfo.Label());
504 CCTCertInfo* newCertInfo = CCTCertInfo::NewLC(certInfo);
505 User::LeaveIfError(aCerts.Append(newCertInfo));
506 CleanupStack::Pop(newCertInfo);
510 void CSWICertStoreImpl::FilterCertificateListL(RMPointerArray<CCTCertInfo>& aCerts,
511 const CCertAttributeFilter& aFilter, const CSWICertStoreEntryList& aEntryList)
513 TInt count = aEntryList.Count();
514 for (TInt index = 0; index < count; index++)
516 const CSWICertStoreEntry& entry = aEntryList.GetByIndex(index);
517 AddIfMatchesFilterL(aCerts, aFilter, entry);