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