--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/cryptoservices/certificateandkeymgmt/swicertstore/CSWICertStoreImpl.cpp Wed Jul 08 11:25:26 2009 +0100
@@ -0,0 +1,515 @@
+/*
+* Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the License "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:
+*
+*/
+
+
+#include "CSWICertStoreImpl.h"
+#include "CSWICertStoreEntryList.h"
+#include "CSWICertStoreEntry.h"
+#include "CSWICertStoreTokenType.h"
+#include "CSWICertStoreToken.h"
+#include "unifiedcertstore.h"
+#include "log.h"
+#include "certstorepatchdata.h"
+#include <ccertattributefilter.h>
+#include <sectcbutil.h>
+#include <u32hal.h>
+
+_LIT(KSWICertStoreZFilename,"z:\\resource\\swicertstore.dat");
+_LIT(KSWIWritableCertStorePath,"!:\\resource\\swicertstore\\dat\\");
+_LIT(KSWIROMCertStoreFilenamePattern,"z:\\resource\\swicertstore*.dat");
+
+/////////////////////////////////////////////////////////////////////////////////////////
+//CFSCertStoreServer
+/////////////////////////////////////////////////////////////////////////////////////////
+
+CSWICertStoreImpl* CSWICertStoreImpl::NewL(MCTToken& aToken, RFs& aFs)
+ {
+ CSWICertStoreImpl* self = new (ELeave) CSWICertStoreImpl(aToken, aFs);
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+CSWICertStoreImpl::CSWICertStoreImpl(MCTToken& aToken, RFs& aFs) :
+ CActive(EPriorityStandard), iToken(aToken), iFs(aFs)
+ {
+ CActiveScheduler::Add(this);
+ }
+
+void CSWICertStoreImpl::ConstructL()
+ {
+ TInt err = iSwicertstoreProperty.Attach(KUnifiedCertStorePropertyCat,
+ EUnifiedCertStoreFlag, EOwnerThread);
+
+ User::LeaveIfError(err);
+
+ iPatchableConst = KAggregateCertStore;
+
+ #ifdef __WINS__
+ // For the emulator allow the constant to be patched via epoc.ini
+ UserSvr::HalFunction(EHalGroupEmulator, EEmulatorHalIntProperty,
+ (TAny*)"KAggregateCertStore", &iPatchableConst); // read emulator property (if present)
+ #endif
+
+
+ // if patchable constant is enabled
+ if(iPatchableConst)
+ {
+ // Setup composite ROM Certstore
+ SetupCompositeROMCertStoreL();
+ }
+ else
+ {
+ // Setup the ROM CertStore
+ SetupROMCertStoreL();
+ }
+
+ // Setup the Writable CertStore
+ // Bear in mind we need to trap NewL(), OpenLC() etc.
+ // Any error occurs, it should still setup the z:\ certstore
+ TRAP_IGNORE(SetupWritableCertStoreL());
+
+ // aggregate ROM composite certstore and writable certstore if patchable constant is enabled
+ if(iPatchableConst)
+ {
+ if(iCEntryList)
+ {
+ // ETrue to indicate that we are passing 'iZEntryList'.
+ // This action will remove duplicate entries from 'iZEntryList'.
+ MergeCertificateEntryListsL(*iZEntryList, ETrue);
+ }
+ }
+ // Subscribe to the Property
+ iSwicertstoreProperty.Subscribe(iStatus);
+ SetActive();
+ }
+
+void CSWICertStoreImpl::DoCancel()
+ {
+ // Cancel outstanding request
+ iSwicertstoreProperty.Cancel();
+ }
+
+void CSWICertStoreImpl::RunL()
+ {
+ // Resubscribe before processing new value to prevent missing updates
+ iSwicertstoreProperty.Subscribe(iStatus);
+ SetActive();
+
+ // Bear in mind we need to trap NewL(), OpenLC() etc.
+ TRAP_IGNORE(SetupWritableCertStoreL());
+ }
+
+void CSWICertStoreImpl::SetupWritableCertStoreL()
+ {
+ TInt err = KErrNone;
+
+ delete iCEntryList;
+ iCEntryList = NULL;
+
+ // The attached file will be freed as well.
+ delete iCStore;
+ iCStore = NULL;
+
+ do
+ {
+ // Open the store if it is there
+ RFile file;
+ CDir* entryList = NULL;
+
+ TPath writableSwiCertStorePath(KSWIWritableCertStorePath);
+ TChar systemDriveChar = SecTcbUtil::GetSystemDriveChar(SecTcbUtil::GetSystemDrive());
+ writableSwiCertStorePath[0] = systemDriveChar;
+
+ if (KErrNone == iFs.GetDir (writableSwiCertStorePath, KEntryAttNormal,
+ ESortByName|EDirsFirst, entryList))
+ {
+ if (entryList)
+ {
+ CleanupStack::PushL(entryList);
+
+ TFileName certstoreFile;
+ TInt count = entryList->Count();
+
+ if (count > 0)
+ {
+ // Get the highest version certstore file
+ const TEntry& entry = (*entryList)[count - 1];
+
+ certstoreFile.Append(writableSwiCertStorePath);
+ certstoreFile.Append(entry.iName);
+
+ CleanupStack::PopAndDestroy(1, entryList);
+ }
+ else
+ {
+ CleanupStack::PopAndDestroy(1, entryList);
+
+ // No certstore in this directory
+ // Currently there should not have any directory in this path
+ return;
+ }
+
+ err = file.Open(iFs, certstoreFile, EFileShareReadersOnly);
+
+ if (err != KErrNone && err != KErrNotFound)
+ {
+ // Log the error to the system file.
+ DEBUG_PRINTF2(_L8("Error Opening SWI writable certstore: %S."), &certstoreFile);
+ return;
+ }
+
+ if (err == KErrNone)
+ {
+ // File exist
+ CleanupClosePushL(file);
+
+ TRAP_IGNORE(iCStore = CPermanentFileStore::FromL(file));
+
+ if (iCStore)
+ {
+ CleanupStack::Pop(&file); // now owned by store
+
+ // Read id of cert list stream
+ TStreamId streamId;
+ RStoreReadStream stream;
+ stream.OpenLC(*iCStore, iCStore->Root());
+ stream >> streamId;
+ CleanupStack::PopAndDestroy(&stream);
+
+ // Read the certificate list
+ RStoreReadStream entryStream;
+ entryStream.OpenLC(*iCStore, streamId);
+ iCEntryList = CSWICertStoreEntryList::NewL(entryStream, iToken, iCertIndex);
+
+ CleanupStack::PopAndDestroy(&entryStream);
+
+ // Record the writable certstore index
+ // The index will then be used to set the tokenId in the
+ // in handle, so to make the handle unique.
+ iCertIndex += iCEntryList->Count();
+ }
+ else
+ {
+ // The file format might not comply to the CPermanentFileStore format
+ CleanupStack::PopAndDestroy(&file);
+
+ // Log the error to the system file.
+ DEBUG_PRINTF2(_L8("Error Opening SWI writable certstore: %S."), &certstoreFile);
+
+ return;
+ }
+ }
+ }
+ }
+ }while (err == KErrNotFound); // There is a very slight chance that the file has been deleted
+ }
+
+void CSWICertStoreImpl::MergeCertificateEntryListsL(const CSWICertStoreEntryList& aSourceList, TBool aIsZEntryList)
+ {
+ ASSERT(iPatchableConst);
+ // if patchable constant is enabled
+
+ TInt sourceCount = aSourceList.Count();
+ for(TInt i = 0; i < sourceCount; i++)
+ {
+ if(!aIsZEntryList)
+ {
+ if (!iZEntryList->LabelExists(aSourceList.GetByIndex(i).CertInfo().Label()))
+ {
+ // Aggregation: Append this entry in the ROM composite list
+ const CSWICertStoreEntry& entry = aSourceList.GetByIndex(i);
+ CSWICertStoreEntry* newEntry = CSWICertStoreEntry::NewL(entry.CertInfo(),
+ entry.CertificateApps(),
+ entry.Trusted(),
+ entry.DataStreamId(),
+ entry.CertMetaInfo(),
+ entry.StoreIndex());
+ CleanupStack::PushL(newEntry);
+ iZEntryList->AppendL(newEntry);
+ // iZEntryList has taken ownership
+ CleanupStack::Pop(newEntry);
+ }
+ // Eclipsing: Higher order store certificates with same labels take precedence over lower order store certificates.
+ // therefore the later are not included in the composite certificate entry list.
+ // N.B iCertIndex will not give total count of certificates because of Eclipsing mechanism.
+ // Higher order store certificates are ones which are aggregated prior to other certificates.
+ }
+ else
+ {
+ // remove duplicate label entries from the 'iZEntryList'
+ if (iCEntryList->LabelExists(aSourceList.GetByIndex(i).CertInfo().Label()))
+ {
+ // Remove entries from iZEntryList having same labels as in iCEntryList.
+ iZEntryList->Remove(i);
+ }
+ }
+ }
+ }
+
+void CSWICertStoreImpl::SetupCompositeROMCertStoreL()
+ {
+ ASSERT(iPatchableConst);
+
+ // Collect the file present in ROM certstore private directory.
+ //The files in this list will be in descending order by name.
+ CDir* filenameList = NULL;
+
+ User::LeaveIfError(iFs.GetDir(KSWIROMCertStoreFilenamePattern, KEntryAttNormal, ESortByName|EDescending, filenameList));
+ CleanupStack::PushL(filenameList);
+ TInt count = filenameList->Count();
+ TStreamId streamId;
+
+ // make full path to the certstore files residing on ROM drive
+ // N.B filenameList will contain filenames in descending order.
+ RFile file;
+ RStoreReadStream stream;
+
+ // create an empty list, this will be the composite certificate entry list
+ iZEntryList = CSWICertStoreEntryList::NewL();
+ // the 'corruptCount' is used for proper correctly referencing valid certstores
+ TInt corruptCount=0;
+ for(TInt i = 0; i < count; i++)
+ {
+ RBuf romFile;
+ romFile.CreateL(KMaxFileName);
+ CleanupClosePushL(romFile);
+ romFile.Append(_L("z:\\resource\\"));
+ romFile.Append(((*filenameList)[i]).iName);
+ User::LeaveIfError(file.Open(iFs,romFile,EFileShareReadersOnly));
+ CleanupClosePushL(file);
+ // open and append the store in array of stores
+ CPermanentFileStore* store = NULL;
+ // if there is any corrupt certstore present then we will simply ignore its
+ // aggregation and proceed with aggregating remaining stores.
+ // ownership is transfered to 'iZArrayOfStores'
+ TRAPD(err, store = CPermanentFileStore::FromL(file));
+ if(err != KErrNone)
+ {
+ corruptCount++;
+ //cleanup file and romFile.
+ CleanupStack::PopAndDestroy(2, &romFile);
+ continue;
+ }
+ iZArrayOfStores.AppendL(store);
+ TInt index = i - corruptCount;
+ // open the root stream containing the streamId of info stream.
+ stream.OpenLC(*(iZArrayOfStores)[index],(iZArrayOfStores[index])->Root());
+ stream >> streamId;
+ CleanupStack::PopAndDestroy(&stream);
+
+ // re-open the info stream containing the certificates entry list.
+ stream.OpenLC(*(iZArrayOfStores)[index],streamId);
+
+ // store index for these entries will be 'index'.
+ // iCertIndex will be 0 for the first certificate entry list passed.
+ CSWICertStoreEntryList* temp_list = CSWICertStoreEntryList::NewL(stream, iToken,iCertIndex,index);
+ // increment to have unique certificate Ids allocation.
+ iCertIndex += temp_list->Count();
+ CleanupStack::PushL(temp_list);
+ MergeCertificateEntryListsL(*temp_list);
+ //temp_list, stream, file and romFile.
+ CleanupStack::PopAndDestroy(4, &romFile);
+ }
+ CleanupStack::PopAndDestroy(filenameList);
+ }
+
+void CSWICertStoreImpl::SetupROMCertStoreL()
+ {
+ // Open the store
+ RFile file;
+ User::LeaveIfError(file.Open(iFs, KSWICertStoreZFilename, EFileShareReadersOnly));
+ CleanupClosePushL(file);
+ iZStore = CPermanentFileStore::FromL(file);
+ CleanupStack::Pop(&file); // now owned by store
+
+ // Read id of cert list stream
+ TStreamId streamId;
+ RStoreReadStream stream;
+ stream.OpenLC(*iZStore, iZStore->Root());
+ stream >> streamId;
+ CleanupStack::PopAndDestroy(&stream);
+
+ // Read the certificate list
+ RStoreReadStream entryStream;
+ entryStream.OpenLC(*iZStore, streamId);
+ iZEntryList = CSWICertStoreEntryList::NewL(entryStream, iToken);
+ CleanupStack::PopAndDestroy(&entryStream);
+
+ // set the valid indexes of writable certstore
+ iCertIndex = iZEntryList->Count();
+ }
+
+CSWICertStoreImpl::~CSWICertStoreImpl()
+ {
+ Cancel();
+ iSwicertstoreProperty.Close();
+ delete iCEntryList;
+ delete iZEntryList;
+ delete iCStore;
+ delete iZStore;
+ iZArrayOfStores.ResetAndDestroy();
+ }
+
+void CSWICertStoreImpl::ListL(RMPointerArray<CCTCertInfo>& aCerts,
+ const CCertAttributeFilter& aFilter)
+ {
+ if (iCEntryList)
+ {
+ FilterCertificateListL(aCerts, aFilter, *iCEntryList);
+ }
+ FilterCertificateListL(aCerts, aFilter, *iZEntryList);
+ }
+
+CCTCertInfo* CSWICertStoreImpl::GetCertL(const TCTTokenObjectHandle& aHandle)
+ {
+ TBool isCEntryHandle = EFalse;
+ const CSWICertStoreEntry* entry = GetCSWICertStoreEntryL(aHandle, isCEntryHandle);
+ return CCTCertInfo::NewL(entry->CertInfo());
+ }
+
+void CSWICertStoreImpl::ApplicationsL(const TCTTokenObjectHandle& aHandle, RArray<TUid>& aApplications)
+ {
+ TBool isCEntryHandle = EFalse;
+ const CSWICertStoreEntry* entry = GetCSWICertStoreEntryL(aHandle, isCEntryHandle);
+
+ const RArray<TUid>& apps = entry->CertificateApps();
+ TInt count = apps.Count();
+
+ for (TInt i = 0 ; i < count ; ++i)
+ {
+ User::LeaveIfError(aApplications.Append(apps[i]));
+ }
+ }
+
+TBool CSWICertStoreImpl::IsApplicableL(const TCTTokenObjectHandle& aHandle, TUid aApplication)
+ {
+ TBool isCEntryHandle = EFalse;
+ const CSWICertStoreEntry* entry = GetCSWICertStoreEntryL(aHandle, isCEntryHandle);
+ return entry->IsApplicable(aApplication);
+ }
+
+TBool CSWICertStoreImpl::TrustedL(const TCTTokenObjectHandle& aHandle)
+ {
+ TBool isCEntryHandle = EFalse;
+ const CSWICertStoreEntry* entry = GetCSWICertStoreEntryL(aHandle, isCEntryHandle);
+ return entry->Trusted();
+ }
+
+void CSWICertStoreImpl::RetrieveL(const TCTTokenObjectHandle& aHandle, TDes8& aEncodedCert)
+ {
+ TBool isCEntryHandle = EFalse;
+ const CSWICertStoreEntry* entry = GetCSWICertStoreEntryL(aHandle, isCEntryHandle);
+ RStoreReadStream stream;
+
+ if (iCEntryList && isCEntryHandle)
+ {
+ stream.OpenLC(*iCStore, entry->DataStreamId());
+ }
+ else
+ {
+ // if patchable constant is enabled
+ if (iPatchableConst)
+ {
+ stream.OpenLC(*(iZArrayOfStores[entry->StoreIndex()]), entry->DataStreamId());
+ }
+ else
+ {
+ stream.OpenLC(*iZStore, entry->DataStreamId());
+ }
+ }
+
+ TInt size = entry->CertInfo().Size();
+
+ if (aEncodedCert.MaxLength() < size)
+ {
+ User::Leave(KErrOverflow);
+ }
+
+ stream.ReadL(aEncodedCert, size);
+ CleanupStack::PopAndDestroy(&stream);
+ }
+
+const TCertMetaInfo& CSWICertStoreImpl::CertMetaInfoL(const TCTTokenObjectHandle& aHandle) const
+ {
+ TBool isCEntryHandle = EFalse;
+ const CSWICertStoreEntry* entry = GetCSWICertStoreEntryL(aHandle, isCEntryHandle);
+ return entry->CertMetaInfo();
+ }
+
+const CSWICertStoreEntry* CSWICertStoreImpl::GetCSWICertStoreEntryL(const TCTTokenObjectHandle& aHandle, TBool& aCEntryHandle) const
+ {
+ if (iCEntryList)
+ {
+ const CSWICertStoreEntry* entry = NULL;
+
+ TRAPD (retCode, entry = &(iCEntryList->GetByHandleL(aHandle)));
+
+ if (entry && (retCode == KErrNone))
+ {
+ aCEntryHandle = ETrue;
+ return entry;
+ }
+ }
+ return &iZEntryList->GetByHandleL(aHandle);
+ }
+
+void CSWICertStoreImpl::AddIfMatchesFilterL(RMPointerArray<CCTCertInfo>& aCerts, const CCertAttributeFilter& aFilter, const CSWICertStoreEntry& aEntry)
+ {
+ const CCTCertInfo& certInfo = aEntry.CertInfo();
+ TBool accept = ETrue;
+
+ if (aFilter.iUidIsSet)
+ {
+ accept = aEntry.IsApplicable(aFilter.iUid);
+ }
+ if (aFilter.iFormatIsSet && accept)
+ {
+ accept = (aFilter.iFormat == certInfo.CertificateFormat());
+ }
+ if (aFilter.iOwnerTypeIsSet && accept)
+ {
+ accept = (aFilter.iOwnerType == certInfo.CertificateOwnerType());
+ }
+ if (aFilter.iSubjectKeyIdIsSet && accept)
+ {
+ accept = (aFilter.iSubjectKeyId == certInfo.SubjectKeyId());
+ }
+ if (aFilter.iLabelIsSet && accept)
+ {
+ accept = (aFilter.iLabel == certInfo.Label());
+ }
+
+ if (accept)
+ {
+ CCTCertInfo* newCertInfo = CCTCertInfo::NewLC(certInfo);
+ User::LeaveIfError(aCerts.Append(newCertInfo));
+ CleanupStack::Pop(newCertInfo);
+ }
+ }
+
+void CSWICertStoreImpl::FilterCertificateListL(RMPointerArray<CCTCertInfo>& aCerts,
+ const CCertAttributeFilter& aFilter, const CSWICertStoreEntryList& aEntryList)
+ {
+ TInt count = aEntryList.Count();
+ for (TInt index = 0; index < count; index++)
+ {
+ const CSWICertStoreEntry& entry = aEntryList.GetByIndex(index);
+ AddIfMatchesFilterL(aCerts, aFilter, entry);
+ }
+ }