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