|
1 /* |
|
2 * Copyright (c) 2005-2008 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 "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: Implementation of boot time integrity check program. |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 // INCLUDE FILES |
|
20 |
|
21 #include <e32cons.h> |
|
22 #include <f32file.h> |
|
23 #include <cctcertinfo.h> // TCapabilitySet |
|
24 #include <s32file.h> |
|
25 #include <signed.h> // VerifySignatureL |
|
26 #include <x500dn.h> // ExactMatchL |
|
27 #include <x509cert.h> // x509 |
|
28 #include <swi/hashcontainer.h> |
|
29 #include <swi/sisregistrysession.h> |
|
30 #include <swi/sisregistryentry.h> |
|
31 #include <swi/sisregistrypackage.h> |
|
32 #include <hash.h> |
|
33 #include <etelmm.h> // For serial number size |
|
34 |
|
35 #include "IntegrityCheck.h" |
|
36 #include "InfoServerClient.h" |
|
37 #include "IntegrityCheckDefs.h" |
|
38 #include "IntegrityCheckClient.h" |
|
39 #include "IntegrityCheckDebug.h" |
|
40 |
|
41 |
|
42 // CONSTANTS |
|
43 |
|
44 _LIT(KBTICThreadName,"BootIntegrityCheck"); |
|
45 _LIT(KBTICCertStoreZ,"z:\\resource\\swicertstore.dat"); |
|
46 _LIT(KBTICCertStoreCName,"updatedswicertstore.dat"); |
|
47 _LIT(KBTICCertStoreCPath,"c:\\resource\\swicertstore\\dat\\"); |
|
48 _LIT(KBTICDriveC,"c:\\"); |
|
49 _LIT(KBTICDriveCWildcard,"c:\\*"); |
|
50 _LIT(KBTICExtensionExe,"*.exe"); |
|
51 _LIT(KBTICSerialNumberFile,"*imei.txt"); |
|
52 _LIT(KBTICStarWildcard,"*\\"); |
|
53 /* |
|
54 #ifdef __BTIC_BINARIES_CHECK_ENABLED |
|
55 _LIT(KBTICSysPathC,"c:\\sys\\bin\\"); |
|
56 _LIT(KBTICCertStoreC, |
|
57 "c:\\resource\\swicertstore\\dat\\updatedswicertstore.dat"); |
|
58 _LIT(KBTICSysPathCWildcard,"c:\\sys\\bin\\*"); |
|
59 _LIT(KBTICExtensionDll,"*.dll"); |
|
60 _LIT(KBTICExtensionDat,"*.dat"); |
|
61 #endif //__BTIC_BINARIES_CHECK_ENABLED |
|
62 */ |
|
63 const TInt KBTICCapaCount = 2; //Number of capabilities. |
|
64 const TUint64 KBTIC_DRM = 64; //0000 0000 0000 0000 0000 0000 0100 0000 |
|
65 const TUint64 KBTIC_TCB = 1; //0000 0000 0000 0000 0000 0000 0000 0001 |
|
66 const TInt KBTICCabaWordOffset = 17; //File heder offset for capa. word @ 64bit. |
|
67 const TInt KBTICHashSize = 20; |
|
68 const TInt KBTICTryToOpen = 240; //Try to open file. (240 x 0.5sec = 120sec) |
|
69 const TInt KBTICTryToCreate = 5; // Try to create process. |
|
70 const TUint KBTICObserverTime = 1000000; // 1sec. |
|
71 const TUint KBTICRunCount = 10; |
|
72 |
|
73 // MACROS |
|
74 |
|
75 using namespace Swi; |
|
76 |
|
77 // DATA TYPES |
|
78 |
|
79 // FUNCTION PROTOTYPES |
|
80 |
|
81 LOCAL_C TInt ThreadStartL(); |
|
82 |
|
83 LOCAL_C TInt ReadCertificatesL( |
|
84 RFs& aFs, |
|
85 const TDesC& aPath, |
|
86 RPointerArray<CX509Certificate>& aX509CertArray, |
|
87 RPointerArray<TCapabilitySet>& aCapabilityArray ); |
|
88 |
|
89 LOCAL_C TBool ValidateCertStoreL( |
|
90 RFs& aFs, |
|
91 RPointerArray<CX509Certificate>& aX509CertArray, |
|
92 RPointerArray<TCapabilitySet>& aCapaArray, |
|
93 const TDesC& aCertStoreFileName, |
|
94 const TDesC& aCertStoreFilePath ); |
|
95 |
|
96 LOCAL_C TBool ValidateProvisonerCertStoreL( |
|
97 RFs& aFs, |
|
98 RPointerArray<CX509Certificate>& aX509CertArray, |
|
99 RPointerArray<TCapabilitySet>& aCapaArray, |
|
100 const TDesC& aCertStoreFileName, |
|
101 const TDesC& aCertStoreFilePath, |
|
102 RSisRegistryEntry& aEntry ); |
|
103 |
|
104 LOCAL_C TBool ValidateSymbianCertStoreL( |
|
105 RFs& aFs, |
|
106 RPointerArray<CX509Certificate>& aX509CertArray, |
|
107 RPointerArray<TCapabilitySet>& aCapaArray, |
|
108 RSisRegistryEntry& aEntry, |
|
109 RPointerArray<HBufC>& aUpdaterExePaths ); |
|
110 |
|
111 LOCAL_C TBool RunUpdaterL( RFs& aFs, RPointerArray<HBufC>& aUpdaterExePaths ); |
|
112 |
|
113 LOCAL_C TBool DeleteAllFilesL( RFs& aFs, const TDesC& aFolderPath ); |
|
114 |
|
115 LOCAL_C TBool SearchFilesFromArrayL( |
|
116 RPointerArray<HBufC>& aSourceArray, |
|
117 const TDesC& aDriveAndPath, |
|
118 RPointerArray<HBufC>& aStringArray, |
|
119 RPointerArray<HBufC>& aFilesArray ); |
|
120 |
|
121 LOCAL_C TBool SearchValidCertificateL( |
|
122 RSisRegistryEntry& aEntry, |
|
123 RPointerArray<CX509Certificate>& aX509CertArray, |
|
124 RPointerArray<TCapabilitySet>& aCertCapaArray, |
|
125 TUint64 aCapability ); |
|
126 |
|
127 LOCAL_C TCapability GetCapability( TUint64 aCapability ); |
|
128 |
|
129 LOCAL_C TBool VerifyHashL( |
|
130 RSisRegistryEntry& aEntry, |
|
131 RPointerArray<HBufC>& aPathArray, |
|
132 RPointerArray<HBufC8>& aHashArray ); |
|
133 |
|
134 LOCAL_C TBool CompareToRegisteryHashL( |
|
135 RSisRegistryEntry& aEntry, |
|
136 TDesC& aEntryFile, |
|
137 TDesC8& aHashBuffer ); |
|
138 |
|
139 LOCAL_C TBool CheckSerialNumberL( RFs& aFs, const TDesC& aFileName ); |
|
140 |
|
141 LOCAL_C void CorruptFileL( RFs& aFs, const TDesC& aFileName ); |
|
142 |
|
143 LOCAL_C TBool CheckCapabilityWordAndCalcHashL( |
|
144 RFs& aFs, |
|
145 TBool aCheckCapa, |
|
146 TUint64* aCapaVector, |
|
147 RPointerArray<HBufC>& aSourceArray, |
|
148 RPointerArray<HBufC>& aFilesArray, |
|
149 RPointerArray<HBufC8>& aHashArray, |
|
150 RArray<TUint64>& aCapaArray ); |
|
151 /* |
|
152 #ifdef __BTIC_BINARIES_CHECK_ENABLED |
|
153 |
|
154 LOCAL_C void RenameFileL( RFs& aFs, const TDesC& aFileName ); |
|
155 |
|
156 LOCAL_C void UniteCertArraysL( |
|
157 RPointerArray<CX509Certificate>& aTargetCertArray, |
|
158 RPointerArray<CX509Certificate>& aSourceCertArray ); |
|
159 |
|
160 LOCAL_C void UniteCapaArraysL( |
|
161 RPointerArray<TCapabilitySet>& aTargetCapaArray, |
|
162 RPointerArray<TCapabilitySet>& aSourceCapaArray ); |
|
163 |
|
164 LOCAL_C void CheckBinariesL( |
|
165 RFs& aFs, |
|
166 RPointerArray<CX509Certificate>& aX509CertArray, |
|
167 RPointerArray<TCapabilitySet>& aCertCapaArray ); |
|
168 |
|
169 LOCAL_C void FindFilesL( |
|
170 RFs& aFs, |
|
171 const TDesC& aPath, |
|
172 const TDesC& aSearchString, |
|
173 RPointerArray<HBufC>& aFoundFilesArray ); |
|
174 |
|
175 LOCAL_C TBool FindMatchFromSisPackageL( |
|
176 RFs& aFs, |
|
177 RPointerArray<HBufC>& aFilesArray, |
|
178 RPointerArray<HBufC8>& aHashArray, |
|
179 RArray<TUint64>& aCapaArray, |
|
180 RPointerArray<CX509Certificate>& aX509CertArray, |
|
181 RPointerArray<TCapabilitySet>& aCertCapaArray ); |
|
182 |
|
183 #endif //__BTIC_BINARIES_CHECK_ENABLED |
|
184 */ |
|
185 |
|
186 // FORWARD DECLARATIONS |
|
187 |
|
188 // LOCAL FUNCTION PROTOTYPES |
|
189 |
|
190 // ============================= LOCAL FUNCTIONS =============================== |
|
191 |
|
192 // ----------------------------------------------------------------------------- |
|
193 // E32Main() |
|
194 // Main for ARM environment. |
|
195 // Returns: KErrNone if successful |
|
196 // Othervice some system error code. |
|
197 // ----------------------------------------------------------------------------- |
|
198 // |
|
199 GLDEF_C TInt E32Main() |
|
200 { |
|
201 BTIC_TRACE_PRINT_ALLOC_CELLS("[BOOT INTECRITY CHECK] Main cell count = %d"); |
|
202 TInt err = KErrNone; |
|
203 |
|
204 CTrapCleanup* cleanup = CTrapCleanup::New(); |
|
205 |
|
206 if ( !cleanup ) |
|
207 { |
|
208 return KErrNoMemory; |
|
209 } |
|
210 |
|
211 TRAP( err, ThreadStartL() ); |
|
212 |
|
213 BTIC_TRACE_PRINT_NUM("[BOOT INTECRITY CHECK] Main TRAP error = %d", err); |
|
214 |
|
215 delete cleanup; |
|
216 |
|
217 BTIC_TRACE_PRINT_ALLOC_CELLS("[BOOT INTECRITY CHECK] Main cell count = %d"); |
|
218 return err; |
|
219 } |
|
220 |
|
221 |
|
222 // ----------------------------------------------------------------------------- |
|
223 // ThreadStart() |
|
224 // |
|
225 // This is programs main. |
|
226 // ----------------------------------------------------------------------------- |
|
227 // |
|
228 LOCAL_C TInt ThreadStartL() |
|
229 { |
|
230 BTIC_TRACE_PRINT("[BOOT INTECRITY CHECK] START PROGRAM"); |
|
231 __UHEAP_MARK; |
|
232 BTIC_TRACE_PRINT_ALLOC_CELLS("Start Cell count = %d"); |
|
233 |
|
234 BTIC_TRACE_PRINT("Rename thread to BootIntegrityCheck"); |
|
235 // Rename thread as SecEnvInit. |
|
236 User::RenameThread( KBTICThreadName ); |
|
237 |
|
238 // This should be read with feature manager etc. but since we |
|
239 // only support certificate database checking this is ok. |
|
240 TBool binariesCheckEnbled = EFalse; |
|
241 |
|
242 TBool certFileFound = EFalse; |
|
243 TInt err = KErrNone; |
|
244 TInt pushToStack = 0; |
|
245 |
|
246 // GET BOOT REASON |
|
247 |
|
248 BTIC_TRACE_PRINT("Get boot reason"); |
|
249 TBool bootReasonFormat = EFalse; |
|
250 RIntegrityCheckClient bticServer; |
|
251 |
|
252 err = bticServer.Connect(); |
|
253 BTIC_TRACE_PRINT_NUM("BTIC Server connect error = %d", err ); |
|
254 |
|
255 if ( err == KErrNone ) |
|
256 { |
|
257 CleanupClosePushL( bticServer ); |
|
258 TInt bootReason = KErrNone; |
|
259 |
|
260 // Get boot reason from btic server. |
|
261 err = bticServer.GetSWBootReason( bootReason ); |
|
262 BTIC_TRACE_PRINT_NUM("GetSWBootReason error = %d", err ); |
|
263 |
|
264 if ( err == KErrNone ) |
|
265 { |
|
266 BTIC_TRACE_PRINT_NUM("Boot Reason number = %d", bootReason ); |
|
267 |
|
268 if ( bootReason == EBTICRestoreFactorySetDeep ) |
|
269 { |
|
270 BTIC_TRACE_PRINT("[BOOT INTECRITY CHECK] Boot reason: FORMAT"); |
|
271 bootReasonFormat = ETrue; |
|
272 } |
|
273 } |
|
274 CleanupStack::PopAndDestroy(); //bticServer |
|
275 } |
|
276 |
|
277 // OPEN FILE SERVER |
|
278 BTIC_TRACE_PRINT("Open FS session"); |
|
279 |
|
280 RFs fs; |
|
281 // Connect to file server. |
|
282 User::LeaveIfError( fs.Connect() ); |
|
283 CleanupClosePushL( fs ); |
|
284 pushToStack++; |
|
285 |
|
286 // Find SWICertStore.dat in C drive. |
|
287 TFindFile find( fs ); |
|
288 TBool certStoreOk = EFalse; |
|
289 CDir* entryList = NULL; |
|
290 HBufC* certStoreFilePath = NULL; |
|
291 HBufC* certStoreFileName = NULL; |
|
292 |
|
293 BTIC_TRACE_PRINT("Find C SWI certificate store"); |
|
294 |
|
295 // Get all files from folder. |
|
296 if ( KErrNone == fs.GetDir ( |
|
297 KBTICCertStoreCPath, |
|
298 KEntryAttNormal, |
|
299 ESortByName|EDirsFirst, |
|
300 entryList ) ) |
|
301 { |
|
302 if ( entryList ) |
|
303 { |
|
304 CleanupStack::PushL( entryList ); |
|
305 |
|
306 TInt count = entryList->Count(); |
|
307 |
|
308 // If file is found. |
|
309 if ( count ) |
|
310 { |
|
311 BTIC_TRACE_PRINT("Store file found"); |
|
312 |
|
313 // Get the highest version certstore file |
|
314 const TEntry& entry = (*entryList)[count - 1]; |
|
315 |
|
316 // Make temp buffer for file path. |
|
317 TBuf<KMaxFileName> path( KBTICCertStoreCPath ); |
|
318 path.Append( entry.iName ); |
|
319 |
|
320 certStoreFilePath = path.AllocLC(); |
|
321 pushToStack++; |
|
322 |
|
323 certStoreFileName = entry.iName.AllocLC(); |
|
324 pushToStack++; |
|
325 |
|
326 certFileFound = ETrue; |
|
327 |
|
328 CleanupStack::Pop(); //certStoreFilePath |
|
329 CleanupStack::Pop(); //certStoreFileName |
|
330 CleanupStack::PopAndDestroy( 1, entryList ); |
|
331 CleanupStack::PushL( certStoreFilePath ); |
|
332 CleanupStack::PushL( certStoreFileName ); |
|
333 } |
|
334 else |
|
335 { |
|
336 BTIC_TRACE_PRINT("No store file present"); |
|
337 CleanupStack::PopAndDestroy( 1, entryList ); |
|
338 } |
|
339 } |
|
340 } |
|
341 |
|
342 BTIC_TRACE_PRINT("Check boot reason"); |
|
343 // Check boot reason. If certificate store file is found start active file |
|
344 // observer which checks that file is deleted. If not continue checking. |
|
345 if ( bootReasonFormat ) |
|
346 { |
|
347 BTIC_TRACE_PRINT("Boot reason format"); |
|
348 if( certFileFound ) |
|
349 { |
|
350 BTIC_TRACE_PRINT("Start active file observer"); |
|
351 TInt status = KErrUnknown; |
|
352 |
|
353 // Create active scheduler. |
|
354 CActiveScheduler* threadScheduler = new CActiveScheduler; |
|
355 CleanupStack::PushL( threadScheduler ); |
|
356 pushToStack++; |
|
357 |
|
358 CActiveScheduler::Install( threadScheduler ); |
|
359 |
|
360 // Create file observer object. |
|
361 CActiveFileObserver* observer = |
|
362 CActiveFileObserver::NewL( fs, *certStoreFilePath, status ); |
|
363 CleanupStack::PushL( observer ); |
|
364 pushToStack++; |
|
365 |
|
366 BTIC_TRACE_PRINT("Start active scheduler"); |
|
367 CActiveScheduler::Start(); |
|
368 |
|
369 BTIC_TRACE_PRINT_NUM("File observer status = %d", status ); |
|
370 |
|
371 if ( status == KErrNone ) |
|
372 { |
|
373 // Boot reason is fromat and certificate file is deleted. |
|
374 // Stop checking and exit. |
|
375 BTIC_TRACE_PRINT("Stop checking and exit"); |
|
376 certFileFound = EFalse; |
|
377 binariesCheckEnbled = EFalse; |
|
378 } |
|
379 } |
|
380 else |
|
381 { |
|
382 // Boot reason is fromat and no certificate file is found. |
|
383 // Stop checking and exit. |
|
384 BTIC_TRACE_PRINT("Stop checking and exit"); |
|
385 certFileFound = EFalse; |
|
386 binariesCheckEnbled = EFalse; |
|
387 } |
|
388 } |
|
389 |
|
390 |
|
391 BTIC_TRACE_PRINT_NUM("Updated store read enabled(1) = %d",certFileFound); |
|
392 BTIC_TRACE_PRINT_NUM("Binaries check enabled(0) = %d",binariesCheckEnbled); |
|
393 |
|
394 // Create pointer array for root certificates. |
|
395 RPointerArray<CX509Certificate> x509CertArray; |
|
396 RPointerArray<TCapabilitySet> certCapaArray; |
|
397 TInt fileError = 0; |
|
398 |
|
399 // Read root certificates if needed. |
|
400 if ( certFileFound || binariesCheckEnbled ) |
|
401 { |
|
402 // Get root certificates to x509 format. |
|
403 fileError = |
|
404 ReadCertificatesL( |
|
405 fs, |
|
406 KBTICCertStoreZ, |
|
407 x509CertArray, |
|
408 certCapaArray ); |
|
409 |
|
410 // Can't read root certificates or array is empty. |
|
411 // Let's return and try this in next boot. |
|
412 if ( fileError || x509CertArray.Count() == 0 ) |
|
413 { |
|
414 BTIC_TRACE_PRINT("ERROR Can't read root certificates ! ! !"); |
|
415 CleanupStack::PopAndDestroy( pushToStack ); |
|
416 x509CertArray.ResetAndDestroy(); |
|
417 certCapaArray.ResetAndDestroy(); |
|
418 User::Leave( fileError ); |
|
419 } |
|
420 } |
|
421 |
|
422 // Create temporary pointer array for C-drive updated certificates. |
|
423 RPointerArray<CX509Certificate> tempCertArray; |
|
424 RPointerArray<TCapabilitySet> tempCapaArray; |
|
425 |
|
426 // If candidate for certstore file is found read it and validate file. |
|
427 if ( certFileFound ) |
|
428 { |
|
429 BTIC_TRACE_PRINT("Read certificates from C"); |
|
430 |
|
431 // Read certificates from C drive and set them to x509 format |
|
432 TRAP( err , |
|
433 fileError = ReadCertificatesL( |
|
434 fs, |
|
435 *certStoreFilePath, |
|
436 tempCertArray, |
|
437 tempCapaArray ) ); |
|
438 |
|
439 BTIC_TRACE_PRINT_NUM("C read file error (0) = %d", fileError ); |
|
440 BTIC_TRACE_PRINT_NUM("C read Trap err (0) = %d", err ); |
|
441 |
|
442 // If ReadCertificatesL function leaves, we assume that something is |
|
443 // tampered and the file is corrupted. However if function returns |
|
444 // an error code, file is not corrupted. |
|
445 if ( err ) |
|
446 { |
|
447 fileError = err; |
|
448 TRAP_IGNORE( CorruptFileL( fs, *certStoreFilePath ) ); |
|
449 } |
|
450 |
|
451 // If there is no error when constructing a permanent file store object |
|
452 // let's continue. |
|
453 if ( fileError == KErrNone ) |
|
454 { |
|
455 BTIC_TRACE_PRINT("Validate cert store"); |
|
456 |
|
457 // Validate the certstore in C if certs are found. |
|
458 TRAP( err, |
|
459 certStoreOk = ValidateCertStoreL( |
|
460 fs, |
|
461 x509CertArray, |
|
462 certCapaArray, |
|
463 *certStoreFileName, |
|
464 *certStoreFilePath ) ); |
|
465 |
|
466 BTIC_TRACE_PRINT_NUM("Trap err (0) = %d", err ); |
|
467 BTIC_TRACE_PRINT_NUM("Cert storage valid (1) = %d", certStoreOk ); |
|
468 |
|
469 // If validation fails or function leaves we will assume |
|
470 // that database is tempered and it will be corrupted. |
|
471 // In practice this mean that all binaries signed with |
|
472 // certificates in C database will be corrupted. |
|
473 if ( ! certStoreOk || err != KErrNone ) |
|
474 { |
|
475 TRAP_IGNORE( CorruptFileL( fs, *certStoreFilePath ) ); |
|
476 } |
|
477 |
|
478 BTIC_TRACE_PRINT("\nStore validation complete"); |
|
479 } |
|
480 } |
|
481 /* |
|
482 #ifdef __BTIC_BINARIES_CHECK_ENABLED |
|
483 |
|
484 // If found cert store is valid unite arrays. |
|
485 if ( certStoreOk ) |
|
486 { |
|
487 UniteCertArraysL( x509CertArray, tempCertArray ); |
|
488 // Reset tempCertArray because x509CertArray owns entrys now. |
|
489 tempCertArray.Reset(); |
|
490 |
|
491 UniteCapaArraysL( certCapaArray, tempCapaArray ); |
|
492 // Reset tempCapaArray because certCapaArray owns entrys now. |
|
493 tempCapaArray.Reset(); |
|
494 } |
|
495 |
|
496 // Check that certificates are found before checking binaries. |
|
497 if ( x509CertArray.Count() ) |
|
498 { |
|
499 // Check that cert array and capa array has same amount of entrys. |
|
500 // If amount is diffrent do not check binaries. Something is wrong. |
|
501 if ( x509CertArray.Count() == certCapaArray.Count() ) |
|
502 { |
|
503 // Check that binaries found in C: are istalled from a valid SIS |
|
504 // pagaces and binary's hash is valid. |
|
505 CheckBinariesL( fs, x509CertArray, certCapaArray ); |
|
506 |
|
507 BTIC_TRACE_PRINT("\nBinaries check complete\n"); |
|
508 } |
|
509 } |
|
510 |
|
511 #endif //__BTIC_BINARIES_CHECK_ENABLED |
|
512 */ |
|
513 |
|
514 BTIC_TRACE_PRINT("\nProgram complete\n"); |
|
515 // DELETE ALL ARRAYS AND ARRAY CONTENT |
|
516 x509CertArray.ResetAndDestroy(); |
|
517 tempCertArray.ResetAndDestroy(); |
|
518 certCapaArray.ResetAndDestroy(); |
|
519 tempCapaArray.ResetAndDestroy(); |
|
520 |
|
521 CleanupStack::PopAndDestroy( pushToStack ); //fs, buffers |
|
522 |
|
523 BTIC_TRACE_PRINT("UHEAP MARK END"); |
|
524 __UHEAP_MARKEND; |
|
525 BTIC_TRACE_PRINT_ALLOC_CELLS("End Cell count = %d"); |
|
526 |
|
527 BTIC_TRACE_PRINT("[BOOT INTECRITY CHECK] PROGRAM END"); |
|
528 return KErrNone; |
|
529 } |
|
530 |
|
531 |
|
532 // ----------------------------------------------------------------------------- |
|
533 // ReadCertificatesL |
|
534 // |
|
535 // This function reads certificates from certificate storage and adds them in to |
|
536 // given cert array if certificate can grant TCB or/and DRM. Also certificates |
|
537 // capability set is added to given capability array. |
|
538 // Given path must be valid one, othervice function returns error code. |
|
539 // |
|
540 // Returns: KErrNone if successful |
|
541 // Othervice some system-wide error code. |
|
542 // ----------------------------------------------------------------------------- |
|
543 // |
|
544 LOCAL_C TInt ReadCertificatesL( |
|
545 RFs& aFs, // File server handle |
|
546 const TDesC& aPath, // Path to storage file. |
|
547 RPointerArray<CX509Certificate>& aX509CertArray, // Cert array. |
|
548 RPointerArray<TCapabilitySet>& aCapabilityArray )// Capability array. |
|
549 { |
|
550 TInt err = KErrNone; |
|
551 RFile file; |
|
552 |
|
553 err = file.Open( aFs, aPath, EFileRead ); |
|
554 |
|
555 if ( err == KErrNone ) |
|
556 { |
|
557 CleanupClosePushL( file ); |
|
558 |
|
559 CPermanentFileStore* certStore = NULL; |
|
560 |
|
561 // Trap FromL if file is not in correct form it may leave. |
|
562 TRAP( err, certStore = CPermanentFileStore::FromL( file ) ); |
|
563 |
|
564 if ( certStore && err == KErrNone ) |
|
565 { |
|
566 CleanupStack::Pop( &file ); // Now owned by store. |
|
567 CleanupStack::PushL( certStore ); |
|
568 |
|
569 // Read id of cert list stream |
|
570 TStreamId streamId; |
|
571 RStoreReadStream stream; |
|
572 stream.OpenLC( *certStore, certStore->Root() ); |
|
573 stream >> streamId; |
|
574 CleanupStack::PopAndDestroy( &stream ); |
|
575 |
|
576 // Read the certificate list |
|
577 RStoreReadStream certEntryStream; |
|
578 certEntryStream.OpenLC( *certStore, streamId ); |
|
579 |
|
580 // Count entrys from stream. |
|
581 TInt count = certEntryStream.ReadInt32L(); |
|
582 BTIC_TRACE_PRINT_NUM("CertEntryStream count = %d", count ); |
|
583 |
|
584 HBufC8* certDataBuf = NULL; |
|
585 |
|
586 for ( TInt index = 0 ; index < count ; index++ ) |
|
587 { |
|
588 // Read data from stream. |
|
589 CRootCertificateEntry* entry = |
|
590 CRootCertificateEntry::NewLC( certEntryStream ); |
|
591 |
|
592 // Get certificate's capabilties from entry. |
|
593 TCapabilitySet* capaSet = |
|
594 new( ELeave ) TCapabilitySet( entry->Capabilities() ); |
|
595 CleanupStack::PushL( capaSet ); |
|
596 |
|
597 // Check that certificate can grant TCB or DRM capabiltiy. |
|
598 if ( capaSet->HasCapability( GetCapability( KBTIC_TCB ) ) || |
|
599 capaSet->HasCapability( GetCapability( KBTIC_DRM ) ) ) |
|
600 { |
|
601 // Append certificates capability set to array. |
|
602 User::LeaveIfError( aCapabilityArray.Append( capaSet ) ); |
|
603 |
|
604 CleanupStack::Pop( capaSet ); |
|
605 |
|
606 // Open certificate data stream. This is actual x509 certificate. |
|
607 RStoreReadStream stream; |
|
608 stream.OpenLC( *certStore, entry->DataStreamId() ); |
|
609 |
|
610 // Get x509 size. |
|
611 TInt size = entry->Size(); |
|
612 |
|
613 // Since we do not have so meny certs in device let's make alloc |
|
614 // inside of the loop. |
|
615 certDataBuf = HBufC8::NewMaxLC( size ); |
|
616 |
|
617 TPtr8 dataBufPtr = certDataBuf->Des(); |
|
618 |
|
619 // Read x509 binary data to buffer. |
|
620 stream.ReadL( dataBufPtr, size ); |
|
621 |
|
622 // Create x509 certificate object from binary data. |
|
623 CX509Certificate* x509Cert = |
|
624 CX509Certificate::NewLC( *certDataBuf ); |
|
625 |
|
626 // Append x509 certificate object to pointer array. |
|
627 User::LeaveIfError( aX509CertArray.Append( x509Cert ) ); |
|
628 |
|
629 CleanupStack::Pop( x509Cert ); |
|
630 x509Cert = NULL; |
|
631 CleanupStack::PopAndDestroy( certDataBuf ); |
|
632 certDataBuf = NULL; |
|
633 CleanupStack::PopAndDestroy( &stream ); |
|
634 } |
|
635 else |
|
636 { |
|
637 // Delete capaSet if certificate has not TCB or DRM. |
|
638 CleanupStack::PopAndDestroy( capaSet ); |
|
639 capaSet = NULL; |
|
640 } |
|
641 |
|
642 CleanupStack::PopAndDestroy( entry ); |
|
643 entry = NULL; |
|
644 } |
|
645 |
|
646 CleanupStack::PopAndDestroy( 2 );//certStore, certEntryStream |
|
647 } |
|
648 else |
|
649 { |
|
650 // Clean up file is FromL leaves. |
|
651 CleanupStack::PopAndDestroy( &file ); |
|
652 BTIC_TRACE_PRINT("ERROR CPermanentFileStore - Can not read certs."); |
|
653 } |
|
654 } |
|
655 |
|
656 BTIC_TRACE_PRINT("[BOOT INTECRITY CHECK] ReadCertificatesL <---"); |
|
657 |
|
658 return err; |
|
659 } |
|
660 |
|
661 |
|
662 // ----------------------------------------------------------------------------- |
|
663 // ValidateCertStoreL() |
|
664 // |
|
665 // This function checks that updated SWI certstore in C drive has been installed |
|
666 // from valid SIS pacage. |
|
667 // SIS pacage must have valid certificate and exe with a TCB capabilities. |
|
668 // |
|
669 // NOTE this function assumes that Certprovisioner tool has imei.txt file. |
|
670 // |
|
671 // Returns: ETure if successful |
|
672 // EFalse othervice |
|
673 // ----------------------------------------------------------------------------- |
|
674 // |
|
675 LOCAL_C TBool ValidateCertStoreL( |
|
676 RFs& aFs, // File server handle |
|
677 RPointerArray<CX509Certificate>& aX509CertArray,// Certificate array |
|
678 RPointerArray<TCapabilitySet>& aCapaArray, // Capability array |
|
679 const TDesC& aCertStoreFileName, |
|
680 const TDesC& aCertStoreFilePath ) |
|
681 { |
|
682 BTIC_TRACE_PRINT("[BOOT INTECRITY CHECK] ValidateCertStoreL v2->"); |
|
683 __UHEAP_MARK; |
|
684 |
|
685 TBool storeOK = EFalse; |
|
686 |
|
687 RPointerArray<HBufC> updaterExePaths; |
|
688 |
|
689 Swi::RSisRegistrySession sisRegSession; |
|
690 |
|
691 // Leave if we can not connect to sis register. Othervice we have a risk |
|
692 // that valid files will be renamed if updated certstore is left out. |
|
693 User::LeaveIfError( sisRegSession.Connect() ); |
|
694 |
|
695 CleanupClosePushL( sisRegSession ); |
|
696 |
|
697 RPointerArray<CSisRegistryPackage> sisPackages; |
|
698 |
|
699 // Find installed packages. |
|
700 sisRegSession.InstalledPackagesL( sisPackages ); |
|
701 |
|
702 Swi::RSisRegistryEntry entry; |
|
703 |
|
704 TInt packageUID; |
|
705 |
|
706 BTIC_TRACE_PRINT("Find matching UID"); |
|
707 |
|
708 // If CertProvisioner tool has install updatedswicertstore file. |
|
709 if ( aCertStoreFileName.Compare( KBTICCertStoreCName ) == KErrNone ) |
|
710 { |
|
711 BTIC_TRACE_PRINT("UID -> KBTICCertProvUID"); |
|
712 packageUID = KBTICCertProvUID; |
|
713 } |
|
714 else |
|
715 { |
|
716 BTIC_TRACE_PRINT("UID -> KBTICSymbianSWIUpdaterUID"); |
|
717 packageUID = KBTICSymbianSWIUpdaterUID; |
|
718 } |
|
719 |
|
720 TBool entryOpen = EFalse; |
|
721 |
|
722 // Search correct sis pagace and open entry to it. |
|
723 for( TInt index = 0; index < sisPackages.Count(); index++) |
|
724 { |
|
725 BTIC_TRACE_PRINT_NUM("Search entry from sis reg. index = %d", index ); |
|
726 |
|
727 if ( sisPackages[index]->Uid() == TUid::Uid( packageUID ) ) |
|
728 { |
|
729 BTIC_TRACE_PRINT("Open entry"); |
|
730 |
|
731 User::LeaveIfError( entry.Open( |
|
732 sisRegSession, TUid::Uid( packageUID ) ) ); |
|
733 |
|
734 CleanupClosePushL( entry ); |
|
735 |
|
736 entryOpen = ETrue; |
|
737 break; |
|
738 } |
|
739 } |
|
740 |
|
741 // Validate cert storage. |
|
742 if ( entryOpen ) |
|
743 { |
|
744 TBool controllerOk = EFalse; |
|
745 |
|
746 #ifdef __BTIC_VERIFY_CONTROLLER |
|
747 // Check that sis controller is valid. |
|
748 controllerOk = entry.VerifyControllerSignatureL( aX509CertArray ); |
|
749 |
|
750 BTIC_TRACE_PRINT("Controller verify ENABLED"); |
|
751 BTIC_TRACE_PRINT_NUM("Controller verify result (1) = %d", controllerOk ); |
|
752 #else |
|
753 // If controller verify is disabled set boolen to true. |
|
754 controllerOk = ETrue; |
|
755 BTIC_TRACE_PRINT("Controller verify DISABLED" ); |
|
756 #endif |
|
757 |
|
758 if ( controllerOk ) |
|
759 { |
|
760 if ( packageUID == KBTICCertProvUID ) |
|
761 { |
|
762 storeOK = ValidateProvisonerCertStoreL( |
|
763 aFs, |
|
764 aX509CertArray, |
|
765 aCapaArray, |
|
766 aCertStoreFileName, |
|
767 aCertStoreFilePath, |
|
768 entry ); |
|
769 } |
|
770 else |
|
771 { |
|
772 storeOK = ValidateSymbianCertStoreL( |
|
773 aFs, |
|
774 aX509CertArray, |
|
775 aCapaArray, |
|
776 entry, |
|
777 updaterExePaths ); |
|
778 } |
|
779 } |
|
780 } |
|
781 |
|
782 // Cleanup array. |
|
783 sisPackages.ResetAndDestroy(); |
|
784 |
|
785 if ( entryOpen ) |
|
786 { |
|
787 CleanupStack::PopAndDestroy(); //RSisRegistryEntry |
|
788 } |
|
789 |
|
790 CleanupStack::PopAndDestroy(); //RSisRegistrySession |
|
791 |
|
792 // Ok Symbian store is valid, let's run Symbian updater exe. |
|
793 // NOTE SisRegistry server etc. has file handle open, so we should |
|
794 // close SisRegistryEntry before running updater. |
|
795 if ( storeOK && packageUID == KBTICSymbianSWIUpdaterUID ) |
|
796 { |
|
797 storeOK = RunUpdaterL( aFs, updaterExePaths ); |
|
798 } |
|
799 |
|
800 updaterExePaths.ResetAndDestroy(); |
|
801 |
|
802 BTIC_TRACE_PRINT("UHEAP MARK END"); |
|
803 __UHEAP_MARKEND; |
|
804 BTIC_TRACE_PRINT("[BOOT INTECRITY CHECK] ValidateCertStoreL v2 <-"); |
|
805 |
|
806 return storeOK; |
|
807 } |
|
808 |
|
809 |
|
810 // ----------------------------------------------------------------------------- |
|
811 // ValidateProvisonerCertStoreL() |
|
812 // |
|
813 // |
|
814 // |
|
815 // |
|
816 // Returns: ETure if successful |
|
817 // EFalse othervice |
|
818 // ----------------------------------------------------------------------------- |
|
819 // |
|
820 LOCAL_C TBool ValidateProvisonerCertStoreL( |
|
821 RFs& aFs, // File server handle |
|
822 RPointerArray<CX509Certificate>& aX509CertArray,// Certificate array |
|
823 RPointerArray<TCapabilitySet>& aCapaArray, // Capability array |
|
824 const TDesC& aCertStoreFileName, |
|
825 const TDesC& aCertStoreFilePath, |
|
826 RSisRegistryEntry& aEntry ) |
|
827 { |
|
828 BTIC_TRACE_PRINT("[BOOT INTECRITY CHECK] ValidateProvisonerStoreL --->"); |
|
829 __UHEAP_MARK; |
|
830 |
|
831 TBool retOK = EFalse; |
|
832 // installedFiles array owns entry's files. |
|
833 RPointerArray<HBufC> installedFilesArray; |
|
834 RPointerArray<HBufC> foundFilesArray; |
|
835 RPointerArray<HBufC> fileArray; // Files that need to be cheked. |
|
836 RPointerArray<HBufC8> hashArray; // Hash for each fileArray's file. |
|
837 RArray<TUint64> capaArray; |
|
838 RPointerArray<HBufC> stringArray; |
|
839 HBufC* string = NULL; |
|
840 |
|
841 TUint64* capaVector = new( ELeave ) TUint64[KBTICCapaCount]; |
|
842 CleanupArrayDeletePushL( capaVector ); |
|
843 capaVector[0] = KBTIC_TCB; |
|
844 |
|
845 // Get all installed files from this sis register entry |
|
846 // to installedFilesArray. |
|
847 aEntry.FilesL( installedFilesArray ); |
|
848 |
|
849 // Search all exes from array. |
|
850 if ( installedFilesArray.Count() > 0 ) |
|
851 { |
|
852 string = KBTICExtensionExe().AllocLC(); |
|
853 User::LeaveIfError( stringArray.Append( string ) ); |
|
854 CleanupStack::Pop(); |
|
855 |
|
856 retOK = SearchFilesFromArrayL( |
|
857 installedFilesArray, |
|
858 KBTICDriveCWildcard, |
|
859 stringArray, |
|
860 foundFilesArray ); |
|
861 } |
|
862 |
|
863 // Find a exe that has TCB capapility and calculate hash over the file. |
|
864 if ( retOK ) |
|
865 { |
|
866 retOK = CheckCapabilityWordAndCalcHashL( |
|
867 aFs, |
|
868 ETrue, |
|
869 capaVector, |
|
870 foundFilesArray, |
|
871 fileArray, |
|
872 hashArray, |
|
873 capaArray ); |
|
874 } |
|
875 |
|
876 // Validate certificate from this entry and check that |
|
877 // certificate can grant the capability which is neede for the exe (TCB). |
|
878 if ( retOK ) |
|
879 { |
|
880 retOK = SearchValidCertificateL( |
|
881 aEntry, |
|
882 aX509CertArray, |
|
883 aCapaArray, |
|
884 KBTIC_TCB ); |
|
885 } |
|
886 |
|
887 // Calculate hash over each exe file found in this entry. |
|
888 // Let's be confident that server is not tempered. |
|
889 if ( retOK ) |
|
890 { |
|
891 retOK = EFalse; |
|
892 |
|
893 // Ok so now we should have one TCB file in fileArray and 2 other |
|
894 // files in foundFilesArray. We do not need to calculate hash over |
|
895 // TCB files again, so let's remove TCB files from array. |
|
896 TInt countExe = foundFilesArray.Count(); |
|
897 TInt countTCB = fileArray.Count(); |
|
898 TBool removeFile = EFalse; |
|
899 |
|
900 for ( TInt i = countExe-1; i >= 0 ; i-- ) |
|
901 { |
|
902 removeFile = EFalse; |
|
903 |
|
904 for ( TInt k = countTCB-1; k >= 0; k-- ) |
|
905 { |
|
906 // If fileArray has this path remove it. |
|
907 if ( (fileArray[k]->Compare( *foundFilesArray[i] )) |
|
908 == KErrNone ) |
|
909 { |
|
910 removeFile = ETrue; |
|
911 } |
|
912 } |
|
913 |
|
914 if ( removeFile ) |
|
915 { |
|
916 foundFilesArray.Remove( i ); |
|
917 } |
|
918 } |
|
919 |
|
920 // Compress array so we don not have null pointers on it. |
|
921 foundFilesArray.Compress(); |
|
922 |
|
923 // If all files are removed something is wrong. Return False. |
|
924 if ( foundFilesArray.Count() ) |
|
925 { |
|
926 // Ok let's calculate hashes for the other exes. |
|
927 retOK = CheckCapabilityWordAndCalcHashL( |
|
928 aFs, |
|
929 EFalse, |
|
930 0, |
|
931 foundFilesArray, |
|
932 fileArray, |
|
933 hashArray, |
|
934 capaArray ); |
|
935 } |
|
936 } |
|
937 |
|
938 // Remove previous strings from array. |
|
939 stringArray.ResetAndDestroy(); |
|
940 // Remove pointers from array. Let's not calc. hash again. |
|
941 foundFilesArray.Reset(); |
|
942 |
|
943 // Search imei.txt file from array and check that device's serial number |
|
944 // is found in the file. NOTE file name must be imei.txt. |
|
945 if ( retOK ) |
|
946 { |
|
947 retOK = EFalse; |
|
948 |
|
949 string = KBTICSerialNumberFile().AllocLC(); |
|
950 User::LeaveIfError( stringArray.Append( string ) ); |
|
951 CleanupStack::Pop(); |
|
952 |
|
953 TBool foundFile = SearchFilesFromArrayL( |
|
954 installedFilesArray, |
|
955 KBTICDriveCWildcard, |
|
956 stringArray, |
|
957 foundFilesArray ); |
|
958 |
|
959 if ( foundFile && foundFilesArray.Count() ) |
|
960 { |
|
961 retOK = CheckSerialNumberL( aFs, *foundFilesArray[0] ); |
|
962 } |
|
963 } |
|
964 |
|
965 // Calculate hash over each file (*.dat and imei.txt) and check that |
|
966 // sisregistery has same hash (*.exe,*.dat,imei.txt). |
|
967 if ( retOK ) |
|
968 { |
|
969 retOK = EFalse; |
|
970 |
|
971 // Note that certstore path from sis reg. points to private |
|
972 // directory not file's current logation. So we have to switch |
|
973 // file paths to get correct hash. |
|
974 |
|
975 // Remove previous strings from array. |
|
976 stringArray.ResetAndDestroy(); |
|
977 |
|
978 string = HBufC::NewLC( |
|
979 aCertStoreFileName.Length() + |
|
980 sizeof( KBTICStarWildcard ) ); |
|
981 TPtr stringPtr = string->Des(); |
|
982 |
|
983 // Append certstorage name and wildcard (*\\) to string for search. |
|
984 // String should be = "*\\filename.dat" Let's add "\\" to string |
|
985 // so search do not accept eg. Öfilename.dat etc. |
|
986 stringPtr.Copy( KBTICStarWildcard ); |
|
987 stringPtr.Append( aCertStoreFileName ); |
|
988 |
|
989 User::LeaveIfError( stringArray.Append( string ) ); |
|
990 CleanupStack::Pop(); //String |
|
991 |
|
992 // Search correct certstorage file from installedFilesArray.(sis reg.) |
|
993 TBool foundFile = SearchFilesFromArrayL( |
|
994 installedFilesArray, |
|
995 KBTICDriveCWildcard, |
|
996 stringArray, |
|
997 foundFilesArray ); |
|
998 |
|
999 if ( foundFile ) |
|
1000 { |
|
1001 BTIC_TRACE_PRINT("Correct CertStore file found"); |
|
1002 |
|
1003 // Get original certstorage path from array. |
|
1004 HBufC* sisRegPath = foundFilesArray[foundFilesArray.Count() - 1]; |
|
1005 |
|
1006 // Remove original path from array. |
|
1007 foundFilesArray.Remove( foundFilesArray.Count() - 1 ); |
|
1008 CleanupStack::PushL( sisRegPath ); //sisRegPath |
|
1009 |
|
1010 // Get current certstorage path. |
|
1011 HBufC* currentPath = aCertStoreFilePath.AllocLC(); |
|
1012 |
|
1013 // Set current path to array. So now we get correct hash. |
|
1014 foundFilesArray.Append( currentPath ); |
|
1015 CleanupStack::Pop(); //currentPath |
|
1016 |
|
1017 BTIC_TRACE_PRINT("Calculate HASH for files"); |
|
1018 |
|
1019 // Calculate hash over files in foundFilesArray and add result to |
|
1020 // filesArray and hashArray |
|
1021 CheckCapabilityWordAndCalcHashL( |
|
1022 aFs, |
|
1023 EFalse, |
|
1024 0, |
|
1025 foundFilesArray, |
|
1026 fileArray, |
|
1027 hashArray, |
|
1028 capaArray ); |
|
1029 |
|
1030 // Ok now we have correct hash but certstore path is not |
|
1031 // correct for sis register. So we have to copy original |
|
1032 // certstorage file path from sis reg. to filesArray. |
|
1033 |
|
1034 // Remove currentPath entry from array. |
|
1035 fileArray.Remove( fileArray.Count() - 1 ); |
|
1036 |
|
1037 // Delete currentPath buffer. We need to delete buffer because |
|
1038 // we call only reset for foundFilesArray. Reset do not delete |
|
1039 // buffer. |
|
1040 delete currentPath; |
|
1041 |
|
1042 // Append orginal path from sis reg. for hash checking. |
|
1043 fileArray.Append( sisRegPath ); |
|
1044 CleanupStack::Pop(); //sisRegPath |
|
1045 |
|
1046 // Check that sis registery entry has same hash as we have. |
|
1047 retOK = VerifyHashL( aEntry, fileArray, hashArray ); |
|
1048 |
|
1049 } |
|
1050 } |
|
1051 |
|
1052 CleanupStack::PopAndDestroy(); //capaVector |
|
1053 |
|
1054 // Reset only. InstalledFiles array owns buffers. |
|
1055 foundFilesArray.Reset(); |
|
1056 fileArray.Reset(); |
|
1057 hashArray.ResetAndDestroy(); |
|
1058 installedFilesArray.ResetAndDestroy(); |
|
1059 stringArray.ResetAndDestroy(); |
|
1060 capaArray.Close(); |
|
1061 |
|
1062 BTIC_TRACE_PRINT("UHEAP MARK END"); |
|
1063 __UHEAP_MARKEND; |
|
1064 |
|
1065 BTIC_TRACE_PRINT("[BOOT INTECRITY CHECK] ValidateProvisonerStoreL <---"); |
|
1066 |
|
1067 return retOK; |
|
1068 } |
|
1069 |
|
1070 |
|
1071 // ----------------------------------------------------------------------------- |
|
1072 // ValidateSymbianCertStoreL() |
|
1073 // |
|
1074 // |
|
1075 // |
|
1076 // |
|
1077 // Returns: ETure if successful |
|
1078 // EFalse othervice |
|
1079 // ----------------------------------------------------------------------------- |
|
1080 // |
|
1081 LOCAL_C TBool ValidateSymbianCertStoreL( |
|
1082 RFs& aFs, // File server handle |
|
1083 RPointerArray<CX509Certificate>& aX509CertArray,// Certificate array |
|
1084 RPointerArray<TCapabilitySet>& aCapaArray, // Capability array |
|
1085 RSisRegistryEntry& aEntry, |
|
1086 RPointerArray<HBufC>& aUpdaterExePaths ) |
|
1087 { |
|
1088 BTIC_TRACE_PRINT("[BOOT INTECRITY CHECK] ValidateSymbianStoreL v2 --->"); |
|
1089 |
|
1090 TBool retOK = EFalse; |
|
1091 // installedFiles array owns entry's files. |
|
1092 RPointerArray<HBufC> installedFilesArray; |
|
1093 RPointerArray<HBufC> foundFilesArray; |
|
1094 RPointerArray<HBufC> fileArray; // Files that need to be cheked. |
|
1095 RPointerArray<HBufC8> hashArray; // Hash for each fileArray's file. |
|
1096 RArray<TUint64> capaArray; |
|
1097 RPointerArray<HBufC> stringArray; |
|
1098 HBufC* string = NULL; |
|
1099 |
|
1100 TUint64* capaVector = new( ELeave ) TUint64[KBTICCapaCount]; |
|
1101 CleanupArrayDeletePushL( capaVector ); |
|
1102 capaVector[0] = KBTIC_TCB; |
|
1103 |
|
1104 // Get all installed files from this sis register entry |
|
1105 // to installedFilesArray. |
|
1106 aEntry.FilesL( installedFilesArray ); |
|
1107 |
|
1108 // Search all exes from array. |
|
1109 if ( installedFilesArray.Count() > 0 ) |
|
1110 { |
|
1111 string = KBTICExtensionExe().AllocLC(); |
|
1112 User::LeaveIfError( stringArray.Append( string ) ); |
|
1113 CleanupStack::Pop(); |
|
1114 |
|
1115 retOK = SearchFilesFromArrayL( |
|
1116 installedFilesArray, |
|
1117 KBTICDriveCWildcard, |
|
1118 stringArray, |
|
1119 foundFilesArray ); |
|
1120 } |
|
1121 |
|
1122 // Find a exe that has TCB capapility and calculate hash over the file. |
|
1123 if ( retOK ) |
|
1124 { |
|
1125 retOK = CheckCapabilityWordAndCalcHashL( |
|
1126 aFs, |
|
1127 ETrue, |
|
1128 capaVector, |
|
1129 foundFilesArray, |
|
1130 fileArray, |
|
1131 hashArray, |
|
1132 capaArray ); |
|
1133 } |
|
1134 |
|
1135 // Validate certificate from this entry and check that |
|
1136 // certificate can grant the capability which is neede for the exe (TCB). |
|
1137 if ( retOK ) |
|
1138 { |
|
1139 retOK = SearchValidCertificateL( |
|
1140 aEntry, |
|
1141 aX509CertArray, |
|
1142 aCapaArray, |
|
1143 KBTIC_TCB ); |
|
1144 } |
|
1145 |
|
1146 // Check that sis registery has same hash as we have. |
|
1147 if ( retOK ) |
|
1148 { |
|
1149 retOK = VerifyHashL( aEntry, fileArray, hashArray ); |
|
1150 } |
|
1151 |
|
1152 // Return exe's path to caller. NOTE Updater exe can not be executed |
|
1153 // before SisRegistryEntry is closed. |
|
1154 if ( retOK ) |
|
1155 { |
|
1156 // We will assume that updater has only one exe with TCB. |
|
1157 HBufC* path = fileArray[0]->AllocLC(); |
|
1158 // Append path to pointer array. |
|
1159 User::LeaveIfError( aUpdaterExePaths.Append( path ) ); |
|
1160 CleanupStack::Pop(); //path |
|
1161 } |
|
1162 |
|
1163 CleanupStack::PopAndDestroy(); //capaVector |
|
1164 |
|
1165 // Reset only. InstalledFiles array owns buffers. |
|
1166 foundFilesArray.Reset(); |
|
1167 fileArray.Reset(); |
|
1168 hashArray.ResetAndDestroy(); |
|
1169 installedFilesArray.ResetAndDestroy(); |
|
1170 stringArray.ResetAndDestroy(); |
|
1171 capaArray.Close(); |
|
1172 |
|
1173 BTIC_TRACE_PRINT("[BOOT INTECRITY CHECK] ValidateSymbianStoreL v2 <---"); |
|
1174 |
|
1175 return retOK; |
|
1176 } |
|
1177 |
|
1178 |
|
1179 // ----------------------------------------------------------------------------- |
|
1180 // RunUpdaterL() |
|
1181 // |
|
1182 // Returns: ETure if successful |
|
1183 // EFalse othervice |
|
1184 // ----------------------------------------------------------------------------- |
|
1185 // |
|
1186 LOCAL_C TBool RunUpdaterL( RFs& aFs, RPointerArray<HBufC>& aUpdaterExePaths ) |
|
1187 { |
|
1188 BTIC_TRACE_PRINT("[BOOT INTECRITY CHECK] RunUpdaterL ->"); |
|
1189 // SIS register do not have hash values for storage file if it is provided |
|
1190 // by Symbian SWI updater exe. We have to remove current storage file |
|
1191 // and run exe again to get a verified swicertstorage in folder. |
|
1192 |
|
1193 TBool retOK = EFalse; |
|
1194 |
|
1195 BTIC_TRACE_PRINT("Delete old store file(s)"); |
|
1196 // Delete all files from dat folder. If delete fails storage file is |
|
1197 // corrupted. |
|
1198 // NOTE that SisRegistry Server has some closing time so we must try this |
|
1199 // in loop. |
|
1200 for ( TInt loop = 0; loop < KBTICTryToOpen; loop++ ) |
|
1201 { |
|
1202 if ( DeleteAllFilesL( aFs, KBTICCertStoreCPath ) ) |
|
1203 { |
|
1204 // We will assume that updater has only on exe with TCB. |
|
1205 HBufC* updaterExePath = aUpdaterExePaths[0]; |
|
1206 |
|
1207 RProcess process; |
|
1208 |
|
1209 BTIC_TRACE_PRINT("Run updater exe to get new store file"); |
|
1210 |
|
1211 for ( TInt i = 0; i < KBTICTryToCreate; i++ ) |
|
1212 { |
|
1213 BTIC_TRACE_PRINT("Try to create Updater process"); |
|
1214 |
|
1215 if ( process.Create( *updaterExePath, KNullDesC ) == KErrNone ) |
|
1216 { |
|
1217 // Run updater exe again. |
|
1218 process.Resume(); |
|
1219 // Get rid of our handle. |
|
1220 process.Close(); |
|
1221 |
|
1222 retOK = ETrue; |
|
1223 |
|
1224 BTIC_TRACE_PRINT("Updater process started OK"); |
|
1225 break; |
|
1226 } |
|
1227 } |
|
1228 |
|
1229 // Break the loop if delete is succesful. |
|
1230 break; |
|
1231 } |
|
1232 else |
|
1233 { |
|
1234 BTIC_TRACE_PRINT_NUM("Wait 0.5 sec. Attempt nr.%d", loop ); |
|
1235 User::After( 500000 ); |
|
1236 } |
|
1237 } |
|
1238 |
|
1239 return retOK; |
|
1240 } |
|
1241 |
|
1242 // ----------------------------------------------------------------------------- |
|
1243 // DeleteAllFiles() |
|
1244 // |
|
1245 // Delete all files from given folder. |
|
1246 // |
|
1247 // Returns: ETure if successful |
|
1248 // EFalse othervice |
|
1249 // ----------------------------------------------------------------------------- |
|
1250 // |
|
1251 LOCAL_C TBool DeleteAllFilesL( RFs& aFs, const TDesC& aFolderPath ) |
|
1252 { |
|
1253 BTIC_TRACE_PRINT("[BOOT INTECRITY CHECK] DeleteAllFilesL "); |
|
1254 |
|
1255 TBool folderEmpty = EFalse; |
|
1256 CDir* entryList = NULL; |
|
1257 TBuf<KMaxFileName> path; |
|
1258 |
|
1259 // Get all files from folder. |
|
1260 if ( KErrNone == |
|
1261 aFs.GetDir ( |
|
1262 aFolderPath, |
|
1263 KEntryAttNormal, |
|
1264 ESortByName|EDirsFirst, |
|
1265 entryList ) ) |
|
1266 { |
|
1267 if ( entryList ) |
|
1268 { |
|
1269 CleanupStack::PushL( entryList ); |
|
1270 |
|
1271 TInt delCount = KErrNone; |
|
1272 TInt count = entryList->Count(); |
|
1273 |
|
1274 for ( TInt index = 0; index < count; index++ ) |
|
1275 { |
|
1276 // Get file name. |
|
1277 const TEntry& entry = (*entryList)[index]; |
|
1278 |
|
1279 // Set path to file. |
|
1280 path.Copy( aFolderPath ); |
|
1281 path.Append( entry.iName ); |
|
1282 |
|
1283 // Remove Read Only attribute. |
|
1284 TInt err = aFs.SetAtt( path, 0, KEntryAttReadOnly ); |
|
1285 BTIC_TRACE_PRINT_NUM("Remove Read Only attrib. = %d", err ); |
|
1286 |
|
1287 if ( KErrNone == aFs.Delete( path ) ) |
|
1288 { |
|
1289 delCount++; |
|
1290 BTIC_TRACE_PRINT_NUM("Delete file with index = %d", index); |
|
1291 } |
|
1292 } |
|
1293 |
|
1294 // If all files are removed. |
|
1295 if ( delCount == count ) |
|
1296 { |
|
1297 folderEmpty = ETrue; |
|
1298 BTIC_TRACE_PRINT("All files removed"); |
|
1299 } |
|
1300 |
|
1301 CleanupStack::PopAndDestroy( 1, entryList ); |
|
1302 } |
|
1303 } |
|
1304 |
|
1305 return folderEmpty; |
|
1306 } |
|
1307 |
|
1308 |
|
1309 // ----------------------------------------------------------------------------- |
|
1310 // SearchFilesFromArrayL |
|
1311 // |
|
1312 // This function search file names containing given string from aSourceArray and |
|
1313 // add found file (path) to an aFilesArray. Search is limited to specified drive |
|
1314 // and path. |
|
1315 // Note this function only adds source arrays pointers to files array. It dos not |
|
1316 // create new heap descriptor. |
|
1317 // |
|
1318 // |
|
1319 // Returns: ETure if successful |
|
1320 // EFalse othervice |
|
1321 // ----------------------------------------------------------------------------- |
|
1322 // |
|
1323 LOCAL_C TBool SearchFilesFromArrayL( |
|
1324 RPointerArray<HBufC>& aSourceArray, // Array for searching. |
|
1325 const TDesC& aDriveAndPath, // Accepted drive or/and path. |
|
1326 RPointerArray<HBufC>& aStringArray, // String to be searched from path. |
|
1327 RPointerArray<HBufC>& aFilesArray ) // Result array. |
|
1328 { |
|
1329 BTIC_TRACE_PRINT("[BOOT INTECRITY CHECK] SearchFilesFromArrayL --->"); |
|
1330 |
|
1331 TBool retVal = EFalse; |
|
1332 |
|
1333 TInt count = aSourceArray.Count(); |
|
1334 TInt stringCount = aStringArray.Count(); |
|
1335 |
|
1336 // This loop gos through all paths from aSourceArray. |
|
1337 for ( TInt index = 0; index < count; index++ ) |
|
1338 { |
|
1339 HBufC* filePath = aSourceArray[index]; |
|
1340 |
|
1341 // Convert descriptor to lower case so we don't get problems with |
|
1342 // Match or Compare functions. |
|
1343 TPtr filePathPtr = filePath->Des(); |
|
1344 filePathPtr.LowerCase(); |
|
1345 |
|
1346 // Check that file is in correct directory. |
|
1347 TInt offsetA = filePath->Match( aDriveAndPath ); |
|
1348 |
|
1349 if ( offsetA >= 0 ) |
|
1350 { |
|
1351 // This loop gos through all strings what we are looking for. |
|
1352 for ( TInt indexB = 0; indexB < stringCount; indexB++ ) |
|
1353 { |
|
1354 // Search string from file path. |
|
1355 TInt offset = filePath->Match( *aStringArray[indexB] ); |
|
1356 |
|
1357 if ( offset >= 0 ) |
|
1358 { |
|
1359 User::LeaveIfError( aFilesArray.Append( filePath ) ); |
|
1360 |
|
1361 retVal = ETrue; |
|
1362 } |
|
1363 } |
|
1364 } |
|
1365 } |
|
1366 |
|
1367 BTIC_TRACE_PRINT("[BOOT INTECRITY CHECK] SearchFilesFromArrayL <---"); |
|
1368 |
|
1369 return retVal; |
|
1370 } |
|
1371 |
|
1372 |
|
1373 // ----------------------------------------------------------------------------- |
|
1374 // SearchValidCertificateL |
|
1375 // |
|
1376 // This function validates entry's certificate against to certificate found in |
|
1377 // given array. It check also that certificate has rigth to grant given |
|
1378 // capability. |
|
1379 // |
|
1380 // Note This function only validates first chain. |
|
1381 // |
|
1382 // Returns: ETure if successful |
|
1383 // EFalse othervice |
|
1384 // ----------------------------------------------------------------------------- |
|
1385 // |
|
1386 LOCAL_C TBool SearchValidCertificateL( |
|
1387 RSisRegistryEntry& aEntry, // SIS Registery entry |
|
1388 RPointerArray<CX509Certificate>& aX509CertArray,// Array for certificates |
|
1389 RPointerArray<TCapabilitySet>& aCertCapaArray, // Array for certs capability |
|
1390 TUint64 aCapability ) // Needed capabiltiy |
|
1391 { |
|
1392 BTIC_TRACE_PRINT("[BOOT INTECRITY CHECK] SearchValidCertificate v2.1 --->"); |
|
1393 |
|
1394 RPointerArray<HBufC8> binaryCertChainArray; |
|
1395 // Get certificates in binary format. |
|
1396 aEntry.CertificateChainsL( binaryCertChainArray ); |
|
1397 |
|
1398 TInt chainCount = binaryCertChainArray.Count(); |
|
1399 BTIC_TRACE_PRINT_NUM("Entry chain count (1) = %d", chainCount ); |
|
1400 |
|
1401 TBool retVal = EFalse; |
|
1402 |
|
1403 RPointerArray<CX509Certificate> chainCertArray; |
|
1404 |
|
1405 // Check all entry's chains |
|
1406 for ( TInt chain = 0; chain < chainCount; chain++ ) |
|
1407 { |
|
1408 BTIC_TRACE_PRINT_NUM("Check chain nr = %d", chain); |
|
1409 |
|
1410 TPtr8 chainData = binaryCertChainArray[chain]->Des(); |
|
1411 |
|
1412 TInt pos = 0; |
|
1413 TInt end = chainData.Length(); |
|
1414 |
|
1415 // Get all certificates from chain. |
|
1416 while ( pos < end ) |
|
1417 { |
|
1418 CX509Certificate* decoded = |
|
1419 CX509Certificate::NewLC( chainData, pos ); |
|
1420 |
|
1421 // Add x509 certificate to pointter array. |
|
1422 User::LeaveIfError( chainCertArray.Append( decoded ) ); |
|
1423 |
|
1424 CleanupStack::Pop( decoded ); |
|
1425 } |
|
1426 |
|
1427 TInt chainCertCount = chainCertArray.Count(); |
|
1428 BTIC_TRACE_PRINT_NUM("Chain's certificate count = %d", chainCertCount); |
|
1429 |
|
1430 // Search certificate issued to root and verify signature against the root. |
|
1431 if ( chainCertCount > 0 ) |
|
1432 { |
|
1433 BTIC_TRACE_PRINT("Validate last cert against root"); |
|
1434 // Last cert in chain should be issued to root. |
|
1435 const CX509Certificate* x509LastChainCert = chainCertArray[chainCertCount-1]; |
|
1436 |
|
1437 TInt rootCertCount = aX509CertArray.Count(); |
|
1438 BTIC_TRACE_PRINT_NUM("Root cert array count = %d", rootCertCount); |
|
1439 TBool rootFound = EFalse; |
|
1440 TInt rootIndex = 0; |
|
1441 |
|
1442 // Find matching root certificate and validate certificates. |
|
1443 for ( rootIndex = 0; rootIndex < rootCertCount; rootIndex++ ) |
|
1444 { |
|
1445 BTIC_TRACE_PRINT_NUM("Root cert index = %d", rootIndex ); |
|
1446 |
|
1447 const CX509Certificate* x509RootCert = aX509CertArray[rootIndex]; |
|
1448 |
|
1449 // Compare entry cert's issuer to root cert's subject. |
|
1450 if ( x509LastChainCert->IssuerName().ExactMatchL( |
|
1451 x509RootCert->SubjectName() ) ) |
|
1452 { |
|
1453 BTIC_TRACE_PRINT("Root found for this chain"); |
|
1454 BTIC_TRACE_PRINT("Verify signature"); |
|
1455 |
|
1456 // Verify signature |
|
1457 if ( x509LastChainCert->VerifySignatureL( |
|
1458 x509RootCert->PublicKey().KeyData() ) ) |
|
1459 { |
|
1460 BTIC_TRACE_PRINT("Signature OK"); |
|
1461 rootFound = ETrue; |
|
1462 break; // Break loop. |
|
1463 } |
|
1464 } |
|
1465 } |
|
1466 |
|
1467 // If root is found we have correct chain. |
|
1468 if ( rootFound ) |
|
1469 { |
|
1470 // If Chain has more then one certificate, verify chain. |
|
1471 if ( chainCertCount > 1 ) |
|
1472 { |
|
1473 BTIC_TRACE_PRINT("Verify certificate chain"); |
|
1474 TBool chainOK = ETrue; |
|
1475 TInt certindex; |
|
1476 |
|
1477 for ( certindex = 0; certindex < chainCertCount-1; certindex++ ) |
|
1478 { |
|
1479 BTIC_TRACE_PRINT_NUM("Cert index = %d", certindex); |
|
1480 BTIC_TRACE_PRINT_NUM("Signature Cert index = %d", certindex+1); |
|
1481 |
|
1482 const CX509Certificate* cert = chainCertArray[certindex]; |
|
1483 const CX509Certificate* signatureCert = |
|
1484 chainCertArray[certindex+1]; |
|
1485 |
|
1486 // Compare issuer name to subject name. |
|
1487 if ( cert->IssuerName().ExactMatchL( |
|
1488 signatureCert->SubjectName() ) ) |
|
1489 { |
|
1490 BTIC_TRACE_PRINT("Issuer match found."); |
|
1491 BTIC_TRACE_PRINT("Verify signature against next cert"); |
|
1492 // Validate certificate |
|
1493 if ( ! cert->VerifySignatureL( |
|
1494 signatureCert->PublicKey().KeyData() ) ) |
|
1495 { |
|
1496 // Chain is broken. Validation failed. |
|
1497 BTIC_TRACE_PRINT("ERROR Chain broken, validation failed"); |
|
1498 chainOK = EFalse; |
|
1499 break; |
|
1500 } |
|
1501 } |
|
1502 else |
|
1503 { |
|
1504 // Issuer do not match. Validation failed. |
|
1505 BTIC_TRACE_PRINT("ERROR Chain broken, issuer error"); |
|
1506 chainOK = EFalse; |
|
1507 break; |
|
1508 } |
|
1509 } |
|
1510 |
|
1511 if ( chainOK ) |
|
1512 { |
|
1513 BTIC_TRACE_PRINT("Entry's chain valid"); |
|
1514 retVal = ETrue; |
|
1515 } |
|
1516 |
|
1517 } |
|
1518 // Chain has only one certificate, root. |
|
1519 else |
|
1520 { |
|
1521 BTIC_TRACE_PRINT("Entry's chain has only one certificate"); |
|
1522 retVal = ETrue; |
|
1523 } |
|
1524 |
|
1525 } |
|
1526 else |
|
1527 { |
|
1528 BTIC_TRACE_PRINT("No root found for this chain"); |
|
1529 retVal = EFalse; |
|
1530 } |
|
1531 |
|
1532 // Check that matching root certificate has same capablitiy |
|
1533 // as aCapability parameter. |
|
1534 if ( aCapability && retVal ) |
|
1535 { |
|
1536 TCapabilitySet* rootCapaSet = aCertCapaArray[rootIndex]; |
|
1537 |
|
1538 retVal = rootCapaSet->HasCapability( GetCapability( aCapability ) ); |
|
1539 } |
|
1540 |
|
1541 // Reset array for next chain. |
|
1542 chainCertArray.ResetAndDestroy(); |
|
1543 } |
|
1544 |
|
1545 // If this is a valid certificate chain, break to loop. |
|
1546 if ( retVal ) |
|
1547 { |
|
1548 break; |
|
1549 } |
|
1550 |
|
1551 } // FOR LOOP |
|
1552 |
|
1553 binaryCertChainArray.ResetAndDestroy(); |
|
1554 |
|
1555 |
|
1556 BTIC_TRACE_PRINT("[BOOT INTECRITY CHECK] SearchValidCertificate v2.1 <---"); |
|
1557 |
|
1558 return retVal; |
|
1559 } |
|
1560 |
|
1561 |
|
1562 // ----------------------------------------------------------------------------- |
|
1563 // GetCapability |
|
1564 // |
|
1565 // This function converts 64 bit capability integer to Symbian capability |
|
1566 // enumeration. |
|
1567 // |
|
1568 // Returns: ECapabilityTCB if capabilty is TCB |
|
1569 // ECapabilityDRM if capabilty is DRM |
|
1570 // ECapability_Denied if capability not found |
|
1571 // ----------------------------------------------------------------------------- |
|
1572 // |
|
1573 LOCAL_C TCapability GetCapability( TUint64 aCapability ) |
|
1574 { |
|
1575 if ( aCapability == KBTIC_TCB ) |
|
1576 { |
|
1577 return ECapabilityTCB; |
|
1578 } |
|
1579 |
|
1580 else if ( aCapability == KBTIC_DRM ) |
|
1581 { |
|
1582 return ECapabilityDRM; |
|
1583 } |
|
1584 |
|
1585 else |
|
1586 { |
|
1587 BTIC_TRACE_PRINT("! ! ERROR GetCapability -> ECapability_Denied ! !"); |
|
1588 return ECapability_Denied; |
|
1589 } |
|
1590 } |
|
1591 |
|
1592 |
|
1593 // ----------------------------------------------------------------------------- |
|
1594 // VerifyHashL |
|
1595 // |
|
1596 // This function compare file's hash to hash found in SIS Register. |
|
1597 // |
|
1598 // Returns: ETure if all compare operations was successful. |
|
1599 // EFalse other vice |
|
1600 // ----------------------------------------------------------------------------- |
|
1601 // |
|
1602 LOCAL_C TBool VerifyHashL( |
|
1603 RSisRegistryEntry& aEntry, |
|
1604 RPointerArray<HBufC>& aPathArray, |
|
1605 RPointerArray<HBufC8>& aHashArray ) |
|
1606 { |
|
1607 BTIC_TRACE_PRINT("[BOOT INTECRITY CHECK] VerifyHashL --->"); |
|
1608 __UHEAP_MARK; |
|
1609 |
|
1610 TBool retVal = EFalse; |
|
1611 TInt hashOk = 0; |
|
1612 TInt count = aPathArray.Count(); |
|
1613 |
|
1614 for ( TInt index = 0; index < count; index++ ) |
|
1615 { |
|
1616 // Take first file |
|
1617 HBufC* path = aPathArray[index]; |
|
1618 HBufC8* hash = aHashArray[index]; |
|
1619 |
|
1620 if ( CompareToRegisteryHashL( |
|
1621 aEntry, |
|
1622 *path, |
|
1623 *hash ) ) |
|
1624 { |
|
1625 hashOk++; |
|
1626 } |
|
1627 } |
|
1628 |
|
1629 // If all hashes are ok return ETrue. |
|
1630 if ( hashOk == count ) |
|
1631 { |
|
1632 BTIC_TRACE_PRINT("\nAll hashes are ok\n"); |
|
1633 retVal = ETrue; |
|
1634 } |
|
1635 |
|
1636 __UHEAP_MARKEND; |
|
1637 BTIC_TRACE_PRINT("[BOOT INTECRITY CHECK] VerifyHashL <---"); |
|
1638 |
|
1639 return retVal; |
|
1640 } |
|
1641 |
|
1642 |
|
1643 // ----------------------------------------------------------------------------- |
|
1644 // CompareToRegisteryHashL |
|
1645 // |
|
1646 // Note this function returns EFalse is HashL function leaves. |
|
1647 // |
|
1648 // Returns: ETure if hash is valid. |
|
1649 // EFalse if hash was not valid. |
|
1650 // ----------------------------------------------------------------------------- |
|
1651 // |
|
1652 LOCAL_C TBool CompareToRegisteryHashL( |
|
1653 RSisRegistryEntry& aEntry, |
|
1654 TDesC& aEntryFile, |
|
1655 TDesC8& aHashBuffer ) |
|
1656 { |
|
1657 BTIC_TRACE_PRINT("[BOOT INTECRITY CHECK] CompareToRegisteryHashL --->"); |
|
1658 |
|
1659 TInt err = 0; |
|
1660 TBool hashOk = EFalse; |
|
1661 CHashContainer* hashContainer = NULL; |
|
1662 |
|
1663 BTIC_TRACE_PRINT("Get hash for file: "); |
|
1664 BTIC_TRACE_PRINT_RAW( aEntryFile ); |
|
1665 |
|
1666 BTIC_TRACE_PRINT("RSisRegistryEntry.HashL()"); |
|
1667 // Get hashConteiner for given file. |
|
1668 TRAP( err, hashContainer = aEntry.HashL( aEntryFile ) ); |
|
1669 |
|
1670 if ( err == KErrNone && hashContainer ) |
|
1671 { |
|
1672 CleanupStack::PushL( hashContainer ); |
|
1673 |
|
1674 // Get hash data from hashConteiner. |
|
1675 TBufC8<KBTICHashSize> hashFromReg( hashContainer->Data() ); |
|
1676 |
|
1677 if ( hashFromReg.Compare( aHashBuffer ) == 0 ) |
|
1678 { |
|
1679 hashOk = ETrue; |
|
1680 |
|
1681 BTIC_TRACE_PRINT("Hash ok"); |
|
1682 } |
|
1683 |
|
1684 CleanupStack::PopAndDestroy(); //hashContainer |
|
1685 } |
|
1686 else |
|
1687 { |
|
1688 // If HashL function leaves, return false. |
|
1689 hashOk = EFalse; |
|
1690 BTIC_TRACE_PRINT_NUM("ERROR RSisRegistryEntry HashL = %d", err ); |
|
1691 } |
|
1692 |
|
1693 BTIC_TRACE_PRINT("[BOOT INTECRITY CHECK] CompareToRegisteryHashL <---"); |
|
1694 |
|
1695 return hashOk; |
|
1696 } |
|
1697 |
|
1698 |
|
1699 // ----------------------------------------------------------------------------- |
|
1700 // CheckSerialNumberL |
|
1701 // |
|
1702 // This function opens IMEI file and checks that device's serial number is found |
|
1703 // in the file. |
|
1704 // |
|
1705 // Returns: ETure if serial number is found or some error with server. |
|
1706 // EFalse if serial number not found |
|
1707 // ----------------------------------------------------------------------------- |
|
1708 // |
|
1709 LOCAL_C TBool CheckSerialNumberL( RFs& aFs, const TDesC& aFileName ) |
|
1710 { |
|
1711 BTIC_TRACE_PRINT("[BOOT INTECRITY CHECK] CheckSerialNumberL --->"); |
|
1712 __UHEAP_MARK; |
|
1713 |
|
1714 TBool matchFound = EFalse; |
|
1715 |
|
1716 RInfoServerClient server; |
|
1717 |
|
1718 // Connect to server. |
|
1719 TInt err = server.Connect(); |
|
1720 |
|
1721 BTIC_TRACE_PRINT_NUM("Server connect error = %d", err ); |
|
1722 |
|
1723 if ( err == KErrNone ) |
|
1724 { |
|
1725 CleanupClosePushL( server ); |
|
1726 |
|
1727 TBuf<RMobilePhone::KPhoneSerialNumberSize> deviceSerialNumber; |
|
1728 |
|
1729 // Get device serial number from server. |
|
1730 err = server.GetSerialNumber( deviceSerialNumber ); |
|
1731 |
|
1732 RFile file; |
|
1733 |
|
1734 if ( err == KErrNone ) |
|
1735 { |
|
1736 // Open text file. |
|
1737 User::LeaveIfError( file.Open( aFs, aFileName, EFileRead ) ); |
|
1738 CleanupClosePushL( file ); |
|
1739 |
|
1740 TInt size; |
|
1741 file.Size( size ); |
|
1742 |
|
1743 HBufC8* content = HBufC8::NewLC( size ); |
|
1744 TPtr8 ptr(content->Des()); |
|
1745 |
|
1746 // Read content |
|
1747 User::LeaveIfError( file.Read( ptr, size ) ); |
|
1748 |
|
1749 TLex8 input( ptr ); |
|
1750 TBool lineEnd( EFalse ); |
|
1751 TChar ch; |
|
1752 |
|
1753 TBuf<RMobilePhone::KPhoneSerialNumberSize> serialNumber; |
|
1754 |
|
1755 while ( ! input.Eos() ) |
|
1756 { |
|
1757 ch = input.Get(); |
|
1758 |
|
1759 if ( ( ch != '\n' ) && ( ch != '\r' ) ) |
|
1760 { |
|
1761 // Check that we have space for next number. |
|
1762 if ( serialNumber.Size() < serialNumber.MaxSize() ) |
|
1763 { |
|
1764 serialNumber.Append( ch ); |
|
1765 } |
|
1766 else |
|
1767 { |
|
1768 // Buffer size is 50 and it should be enoug, if not |
|
1769 // then something is wrong. Let's break to loop and |
|
1770 // return false. |
|
1771 break; |
|
1772 } |
|
1773 } |
|
1774 else |
|
1775 { |
|
1776 lineEnd = ETrue; |
|
1777 } |
|
1778 |
|
1779 if ( ( lineEnd ) || ( input.Eos() ) ) |
|
1780 { |
|
1781 if ( deviceSerialNumber == serialNumber ) |
|
1782 { |
|
1783 BTIC_TRACE_PRINT("Correct serial number found"); |
|
1784 matchFound = ETrue; |
|
1785 break; |
|
1786 } |
|
1787 |
|
1788 serialNumber.FillZ(0); |
|
1789 serialNumber.SetLength(0); |
|
1790 lineEnd = EFalse; |
|
1791 } |
|
1792 } |
|
1793 CleanupStack::PopAndDestroy( 2 ); //file, content |
|
1794 } |
|
1795 CleanupStack::PopAndDestroy(); //client |
|
1796 } |
|
1797 |
|
1798 __UHEAP_MARKEND; |
|
1799 BTIC_TRACE_PRINT("[BOOT INTECRITY CHECK] CheckSerialNumberL <---"); |
|
1800 |
|
1801 return matchFound; |
|
1802 } |
|
1803 |
|
1804 |
|
1805 // ----------------------------------------------------------------------------- |
|
1806 // CorruptFileL |
|
1807 // |
|
1808 // This function corrupts certificate file so that certs can not be read. |
|
1809 // ----------------------------------------------------------------------------- |
|
1810 // |
|
1811 LOCAL_C void CorruptFileL( RFs& aFs, const TDesC& aFileName ) |
|
1812 { |
|
1813 BTIC_TRACE_PRINT("[BOOT INTECRITY CHECK] ! ! CORRUPT STORE FILE ! !"); |
|
1814 |
|
1815 TFindFile find( aFs ); |
|
1816 |
|
1817 TUint8 byteVector[8] = { 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF }; |
|
1818 |
|
1819 // Find given file in C drive. |
|
1820 if ( find.FindByDir( aFileName, KBTICDriveC ) == KErrNone ) |
|
1821 { |
|
1822 RFile file; |
|
1823 TInt err; |
|
1824 |
|
1825 for ( TInt loop = 0; loop < KBTICTryToOpen; loop++ ) |
|
1826 { |
|
1827 err = file.Open( aFs, aFileName, EFileRead | EFileWrite ); |
|
1828 BTIC_TRACE_PRINT_NUM("File Open error = %d", err ); |
|
1829 |
|
1830 // If file is open or it has ReadOnly attribute wait and try again. |
|
1831 if ( err ) |
|
1832 { |
|
1833 BTIC_TRACE_PRINT_NUM("Wait 0.5 sec. Attempt nr.%d", loop ); |
|
1834 User::After( 500000 ); |
|
1835 |
|
1836 TInt seterr = aFs.SetAtt( aFileName, 0, KEntryAttReadOnly ); |
|
1837 BTIC_TRACE_PRINT_NUM("Remove Read Only attrib. = %d", seterr ); |
|
1838 } |
|
1839 else |
|
1840 { |
|
1841 break; |
|
1842 } |
|
1843 } |
|
1844 |
|
1845 // Leave if error. |
|
1846 User::LeaveIfError( err ); |
|
1847 |
|
1848 CleanupClosePushL( file ); |
|
1849 |
|
1850 TInt size = 0; |
|
1851 file.Size( size ); |
|
1852 |
|
1853 HBufC8* fileData = HBufC8::NewLC( size ); |
|
1854 TPtr8 dataPtr = fileData->Des(); |
|
1855 |
|
1856 HBufC8* newFileData = HBufC8::NewLC( size + sizeof( byteVector ) ); |
|
1857 TPtr8 newDataPtr = newFileData->Des(); |
|
1858 |
|
1859 file.Read( dataPtr ); |
|
1860 // Copy corrupted bytes to buffer. |
|
1861 newDataPtr.Copy( &byteVector[0], sizeof( byteVector ) ); |
|
1862 // Copy original file data to buffer. |
|
1863 newDataPtr.Append( dataPtr ); |
|
1864 // Write data at start of file. |
|
1865 file.Write( 0, *newFileData ); |
|
1866 |
|
1867 file.Flush(); |
|
1868 |
|
1869 CleanupStack::PopAndDestroy( 3 ); |
|
1870 |
|
1871 BTIC_TRACE_PRINT("File corrupted" ); |
|
1872 } |
|
1873 } |
|
1874 |
|
1875 |
|
1876 // ----------------------------------------------------------------------------- |
|
1877 // CheckCapabilityWordAndCalcHashL |
|
1878 // |
|
1879 // This function reads capability word from file heder and compares that to given |
|
1880 // capability (aCapaVector). If there is more then one whanted capability the |
|
1881 // first match is selected. If match is found file path is added to aFilesArray |
|
1882 // and hash is calculated over the binary and found capa is added to array. |
|
1883 // If aCheckCapa is set as EFalse, capability word is not checked and all files |
|
1884 // from aSourceArray is added to aFilesArray. |
|
1885 // Note aCapaArray conteins only matched capability. Not all file's capabilities. |
|
1886 // |
|
1887 // Returns: ETure if successful |
|
1888 // EFalse othervice |
|
1889 // ----------------------------------------------------------------------------- |
|
1890 // |
|
1891 LOCAL_C TBool CheckCapabilityWordAndCalcHashL( |
|
1892 RFs& aFs, // File server handle |
|
1893 TBool aCheckCapa, // Enables capability check. |
|
1894 TUint64* aCapaVector, // Vector con. capa. that are checked. |
|
1895 RPointerArray<HBufC>& aSourceArray, // Files to be checked. |
|
1896 RPointerArray<HBufC>& aFilesArray, // Passed files |
|
1897 RPointerArray<HBufC8>& aHashArray, // File's hash |
|
1898 RArray<TUint64>& aCapaArray ) // File's capability. |
|
1899 { |
|
1900 BTIC_TRACE_PRINT("[BOOT INTECRITY CHECK] CheckCapaWordAndCalcHashL v3.1 ->"); |
|
1901 |
|
1902 TFindFile find( aFs ); |
|
1903 |
|
1904 TInt pathCount = aSourceArray.Count(); |
|
1905 |
|
1906 TBool retVal = EFalse; |
|
1907 TInt index; |
|
1908 TInt err; |
|
1909 |
|
1910 CSHA1* sha = CSHA1::NewL(); |
|
1911 CleanupStack::PushL( sha ); |
|
1912 |
|
1913 RFile file; |
|
1914 |
|
1915 for ( index = 0; index < pathCount; index++ ) |
|
1916 { |
|
1917 BTIC_TRACE_PRINT_NUM("File array index = %d", index ); |
|
1918 |
|
1919 HBufC* path = aSourceArray[index]; |
|
1920 |
|
1921 BTIC_TRACE_PRINT("File path: "); |
|
1922 BTIC_TRACE_PRINT_RAW( *path ); |
|
1923 |
|
1924 err = file.Open( aFs, *path, EFileShareReadersOnly ); |
|
1925 |
|
1926 if ( err == KErrNone ) |
|
1927 { |
|
1928 CleanupClosePushL( file ); |
|
1929 |
|
1930 TInt size = 0; |
|
1931 file.Size( size ); |
|
1932 |
|
1933 // Alloc buffer for file. |
|
1934 HBufC8* buffer = HBufC8::NewLC( size ); |
|
1935 |
|
1936 if ( buffer ) |
|
1937 { |
|
1938 TPtr8 bufferPtr = buffer->Des(); |
|
1939 |
|
1940 // Read file binary to buffer. |
|
1941 err = file.Read( bufferPtr ); |
|
1942 |
|
1943 if ( err == KErrNone || buffer->Length() != 0 ) |
|
1944 { |
|
1945 TUint64 capa = 0; |
|
1946 TBool capabilityOk = EFalse; |
|
1947 |
|
1948 // Check capability if needed. |
|
1949 if ( aCheckCapa ) |
|
1950 { |
|
1951 // Get pointer to heap buffer. |
|
1952 const TUint8* ptr = buffer->Ptr(); |
|
1953 |
|
1954 // Capapility word (64bit) is found in 0x88 bytes after |
|
1955 // file heder offset. 0x88 = 136 bytes/8=17 words@64. |
|
1956 TUint64 word = ((TUint64*)ptr)[KBTICCabaWordOffset]; |
|
1957 |
|
1958 for ( TInt iCapa = 0; iCapa < KBTICCapaCount; iCapa++ ) |
|
1959 { |
|
1960 BTIC_TRACE_PRINT_NUM("Capa index = %d", iCapa ); |
|
1961 |
|
1962 capa = aCapaVector[iCapa]; |
|
1963 |
|
1964 if ( (word & capa) == capa ) |
|
1965 { |
|
1966 BTIC_TRACE_PRINT("Capability match found"); |
|
1967 capabilityOk = ETrue; |
|
1968 break; |
|
1969 } |
|
1970 } |
|
1971 } |
|
1972 |
|
1973 // If capa check is not needed calculate hash over the file. |
|
1974 // Capability is set as zero. |
|
1975 else |
|
1976 { |
|
1977 BTIC_TRACE_PRINT("Capability NOT REGUIRED"); |
|
1978 capabilityOk = ETrue; |
|
1979 } |
|
1980 |
|
1981 if ( capabilityOk ) |
|
1982 { |
|
1983 BTIC_TRACE_PRINT("Append file information to array"); |
|
1984 |
|
1985 // Add found capability to array |
|
1986 User::LeaveIfError( aCapaArray.Append( capa ) ); |
|
1987 |
|
1988 // Append pointer to files path. |
|
1989 User::LeaveIfError( aFilesArray.Append( path ) ); |
|
1990 |
|
1991 HBufC8* hash = HBufC8::NewLC( KBTICHashSize ); |
|
1992 TPtr8 hashPtr = hash->Des(); |
|
1993 |
|
1994 sha->Reset(); |
|
1995 |
|
1996 // Calucalte hash over file's binary. |
|
1997 hashPtr.Copy( sha->Hash( bufferPtr ) ); |
|
1998 |
|
1999 // Check that digest has correct length. |
|
2000 if ( hash->Length() != KBTICHashSize ) |
|
2001 { |
|
2002 BTIC_TRACE_PRINT("\nERROR HASH SIZE"); |
|
2003 User::Leave( KErrGeneral ); |
|
2004 } |
|
2005 |
|
2006 // Add file's hash to array |
|
2007 User::LeaveIfError( aHashArray.Append( hash ) ); |
|
2008 |
|
2009 CleanupStack::Pop(); // hash; |
|
2010 |
|
2011 retVal = ETrue; |
|
2012 } |
|
2013 } |
|
2014 else |
|
2015 { |
|
2016 BTIC_TRACE_PRINT_NUM("\nERROR File read = %d", err ); |
|
2017 User::Leave( KErrGeneral ); |
|
2018 } |
|
2019 } |
|
2020 else |
|
2021 { |
|
2022 BTIC_TRACE_PRINT("\nERROR HBufC8 buffer alloc failed"); |
|
2023 User::Leave( KErrGeneral ); |
|
2024 } |
|
2025 |
|
2026 CleanupStack::PopAndDestroy( 2 ); // file, fileBuffer |
|
2027 } |
|
2028 else |
|
2029 { |
|
2030 BTIC_TRACE_PRINT_NUM("\nERROR File open = %d", err ); |
|
2031 User::Leave( KErrGeneral ); |
|
2032 } |
|
2033 } |
|
2034 |
|
2035 CleanupStack::PopAndDestroy(); // sha |
|
2036 |
|
2037 BTIC_TRACE_PRINT("[BOOT INTECRITY CHECK] CheckCapaWordAndCalcHashL v3 <---"); |
|
2038 |
|
2039 return retVal; |
|
2040 } |
|
2041 |
|
2042 /* |
|
2043 #ifdef __BTIC_BINARIES_CHECK_ENABLED |
|
2044 |
|
2045 |
|
2046 // ----------------------------------------------------------------------------- |
|
2047 // RenameFileL |
|
2048 // |
|
2049 // This function renames given file by replacing existing file extension to .bak |
|
2050 // ----------------------------------------------------------------------------- |
|
2051 // |
|
2052 LOCAL_C void RenameFileL( RFs& aFs, const TDesC& aFileName ) |
|
2053 { |
|
2054 BTIC_TRACE_PRINT("[BOOT INTECRITY CHECK] ! ! ! RenameFileL --->"); |
|
2055 |
|
2056 _LIT( KBTICFileExtensionBak,".bak" ); |
|
2057 |
|
2058 TFindFile find( aFs ); |
|
2059 |
|
2060 // Find given file in C drive. |
|
2061 if ( find.FindByDir( aFileName, KBTICSysPathC ) == KErrNone ) |
|
2062 { |
|
2063 TInt length = aFileName.Length(); |
|
2064 HBufC* newName = HBufC::NewLC( length + sizeof( KBTICFileExtensionBak ) ); |
|
2065 TPtr newNamePtr = newName->Des(); |
|
2066 |
|
2067 newNamePtr.Copy( aFileName ); |
|
2068 // Add ".bak" extension to file name. |
|
2069 newNamePtr.Append( KBTICFileExtensionBak ); |
|
2070 |
|
2071 // Rename file. |
|
2072 TInt err = aFs.Rename( aFileName, *newName ); |
|
2073 |
|
2074 // If error try ones more. |
|
2075 if ( err != KErrNone ) |
|
2076 { |
|
2077 aFs.Rename( aFileName, *newName ); |
|
2078 } |
|
2079 } |
|
2080 |
|
2081 BTIC_TRACE_PRINT("[BOOT INTECRITY CHECK] ! ! ! RenameFileL <---"); |
|
2082 } |
|
2083 |
|
2084 |
|
2085 // ----------------------------------------------------------------------------- |
|
2086 // UniteCertArraysL |
|
2087 // |
|
2088 // Function append source array's pointers to target array. |
|
2089 // ----------------------------------------------------------------------------- |
|
2090 // |
|
2091 LOCAL_C void UniteCertArraysL( |
|
2092 RPointerArray<CX509Certificate>& aTargetCertArray, |
|
2093 RPointerArray<CX509Certificate>& aSourceCertArray ) |
|
2094 { |
|
2095 BTIC_TRACE_PRINT("[BOOT INTECRITY CHECK] UniteCertArraysL --->"); |
|
2096 |
|
2097 TInt count = aSourceCertArray.Count(); |
|
2098 |
|
2099 if ( count > 0 ) |
|
2100 { |
|
2101 for ( TInt index = 0; index < count; index++ ) |
|
2102 { |
|
2103 CX509Certificate* x509Cert = aSourceCertArray[index]; |
|
2104 // Note if append fails -> some binaries will be corrupted. |
|
2105 aTargetCertArray.Append( x509Cert ); |
|
2106 } |
|
2107 } |
|
2108 |
|
2109 BTIC_TRACE_PRINT("[BOOT INTECRITY CHECK] UniteCertArraysL <---"); |
|
2110 } |
|
2111 |
|
2112 |
|
2113 // ----------------------------------------------------------------------------- |
|
2114 // UniteCapaArraysL |
|
2115 // |
|
2116 // Function append source array's pointers to target array. |
|
2117 // ----------------------------------------------------------------------------- |
|
2118 // |
|
2119 LOCAL_C void UniteCapaArraysL( |
|
2120 RPointerArray<TCapabilitySet>& aTargetCapaArray, |
|
2121 RPointerArray<TCapabilitySet>& aSourceCapaArray ) |
|
2122 { |
|
2123 BTIC_TRACE_PRINT("[BOOT INTECRITY CHECK] UniteCapaArraysL --->"); |
|
2124 |
|
2125 TInt count = aSourceCapaArray.Count(); |
|
2126 |
|
2127 if ( count > 0 ) |
|
2128 { |
|
2129 for ( TInt index = 0; index < count; index++ ) |
|
2130 { |
|
2131 TCapabilitySet* capaSet = aSourceCapaArray[index]; |
|
2132 // Note if append fails -> some binaries will be corrupted. |
|
2133 aTargetCapaArray.Append( capaSet ); |
|
2134 } |
|
2135 } |
|
2136 |
|
2137 BTIC_TRACE_PRINT("[BOOT INTECRITY CHECK] UniteCapaArraysL <---"); |
|
2138 } |
|
2139 |
|
2140 |
|
2141 // ----------------------------------------------------------------------------- |
|
2142 // CheckBinariesL |
|
2143 // |
|
2144 // This function checks all exe or dll binarys conteining TCB and DRM capability |
|
2145 // in C:\sys\bin directory. It calculates hash over the binary and compares that |
|
2146 // to one found in SIS Registery. It check also that SIS pacage's certificate |
|
2147 // has rigth to grant TCB or DRM capabiltity. |
|
2148 // If some file in C:\sys\bin directory is not found in SIS Registery it is |
|
2149 // renamed. |
|
2150 // |
|
2151 // ----------------------------------------------------------------------------- |
|
2152 // |
|
2153 LOCAL_C void CheckBinariesL( |
|
2154 RFs& aFs, |
|
2155 RPointerArray<CX509Certificate>& aX509CertArray, |
|
2156 RPointerArray<TCapabilitySet>& aCertCapaArray ) |
|
2157 { |
|
2158 BTIC_TRACE_PRINT("[BOOT INTECRITY CHECK] CheckBinariesL --->"); |
|
2159 __UHEAP_MARK; |
|
2160 |
|
2161 TInt pushToStack = 0; |
|
2162 TInt err = 0; |
|
2163 |
|
2164 RPointerArray<HBufC> allFilesArray; |
|
2165 |
|
2166 // Find all exe files from c:\sys\bin. |
|
2167 FindFilesL( aFs, KBTICSysPathC, KBTICExtensionExe, allFilesArray ); |
|
2168 // Find all dll files from c:\sys\bin. |
|
2169 FindFilesL( aFs, KBTICSysPathC, KBTICExtensionDll, allFilesArray ); |
|
2170 |
|
2171 TInt count = allFilesArray.Count(); |
|
2172 |
|
2173 if ( count > 0 ) |
|
2174 { |
|
2175 RPointerArray<HBufC> filesArray; |
|
2176 RPointerArray<HBufC8> hashArray; |
|
2177 RArray<TUint64> capaArray; |
|
2178 |
|
2179 TBool foundFiles = EFalse; |
|
2180 |
|
2181 // Copy whanted capabilities to array. |
|
2182 TUint64* capaVector = new( ELeave ) TUint64[KBTICCapaCount]; |
|
2183 CleanupArrayDeletePushL( capaVector ); |
|
2184 capaVector[0] = KBTIC_TCB; |
|
2185 capaVector[1] = KBTIC_DRM; |
|
2186 |
|
2187 // Find files conteining whanted capability and calculate hash over file. |
|
2188 |
|
2189 // NOTE NOTE currently this function addends only one capability to |
|
2190 // capaArray. This must be changed if all capabilities should be |
|
2191 // checked from certificate. |
|
2192 |
|
2193 foundFiles = CheckCapabilityWordAndCalcHashL( |
|
2194 aFs, |
|
2195 ETrue, |
|
2196 capaVector, |
|
2197 allFilesArray, |
|
2198 filesArray, |
|
2199 hashArray, |
|
2200 capaArray ); |
|
2201 |
|
2202 CleanupStack::PopAndDestroy(); //capaVector |
|
2203 |
|
2204 if ( foundFiles && err == KErrNone ) |
|
2205 { |
|
2206 // Find match for fileArray's files from SIS registery |
|
2207 // Check that file's (binary) hash matches to SIS registery's hash |
|
2208 // Check that SIS registery cert. is valid and has file's capability. |
|
2209 FindMatchFromSisPackageL( |
|
2210 aFs, |
|
2211 filesArray, |
|
2212 hashArray, |
|
2213 capaArray, |
|
2214 aX509CertArray, |
|
2215 aCertCapaArray ); |
|
2216 |
|
2217 count = filesArray.Count(); |
|
2218 |
|
2219 BTIC_TRACE_PRINT_NUM("Files array count = %d (should be 0 )", count ); |
|
2220 |
|
2221 // Rename all files which was not found in sis registery. |
|
2222 if ( count ) |
|
2223 { |
|
2224 for ( TInt index = 0; index < count; index++ ) |
|
2225 { |
|
2226 HBufC* filePath = filesArray[index]; |
|
2227 |
|
2228 RenameFileL( aFs, *filePath ); |
|
2229 } |
|
2230 } |
|
2231 } |
|
2232 |
|
2233 filesArray.Reset(); // Reset only. allFilesArray owns heap memory. |
|
2234 hashArray.ResetAndDestroy(); |
|
2235 } |
|
2236 |
|
2237 allFilesArray.ResetAndDestroy(); |
|
2238 |
|
2239 CleanupStack::PopAndDestroy( pushToStack ); //searchPath |
|
2240 |
|
2241 BTIC_TRACE_PRINT("UHEAP MARK END"); |
|
2242 __UHEAP_MARKEND; |
|
2243 BTIC_TRACE_PRINT("[BOOT INTECRITY CHECK] CheckBinariesL <---"); |
|
2244 } |
|
2245 |
|
2246 |
|
2247 // ----------------------------------------------------------------------------- |
|
2248 // FindFilesL |
|
2249 // |
|
2250 // This function searches one or more files that conteins given string in file |
|
2251 // name. File names are added to array with complete path. |
|
2252 // ----------------------------------------------------------------------------- |
|
2253 // |
|
2254 LOCAL_C void FindFilesL( |
|
2255 RFs& aFs, // File server handle. |
|
2256 const TDesC& aPath, // Search directory and drive. |
|
2257 const TDesC& aSearchString, // String to be found in file name. |
|
2258 RPointerArray<HBufC>& aFoundFilesArray )// Result files. |
|
2259 { |
|
2260 BTIC_TRACE_PRINT("[BOOT INTECRITY CHECK] FindFilesL --->"); |
|
2261 |
|
2262 TInt err = 0; |
|
2263 TFindFile find( aFs ); |
|
2264 CDir* dirList = NULL; |
|
2265 HBufC* path; |
|
2266 |
|
2267 TFileName searchExtension; |
|
2268 searchExtension.Copy( aSearchString ); |
|
2269 |
|
2270 // Find files from searchPath directory. Note that dirlist |
|
2271 // contains only file name not path to it. |
|
2272 err = find.FindWildByPath( searchExtension, &aPath, dirList ); |
|
2273 |
|
2274 TInt pathLength = aPath.Length(); |
|
2275 |
|
2276 if ( err == KErrNone && dirList ) |
|
2277 { |
|
2278 CleanupStack::PushL( dirList ); |
|
2279 |
|
2280 // Get the count of find files. |
|
2281 TInt count = dirList->Count(); |
|
2282 |
|
2283 BTIC_TRACE_PRINT_NUM("Dir list count = %d", count ); |
|
2284 |
|
2285 for ( TInt index = 0; index < count; index++ ) |
|
2286 { |
|
2287 path = HBufC::NewLC( pathLength + (*dirList)[index].iName.Length() ); |
|
2288 TPtr ptrPath = path->Des(); |
|
2289 |
|
2290 // Copy system path to buffer. |
|
2291 ptrPath.Copy( KBTICSysPathC ); |
|
2292 // Append files name to path buffer. |
|
2293 ptrPath.Append( (*dirList)[index].iName ); |
|
2294 |
|
2295 ptrPath.LowerCase(); |
|
2296 |
|
2297 aFoundFilesArray.Append( path ); |
|
2298 |
|
2299 CleanupStack::Pop(); //path |
|
2300 } |
|
2301 |
|
2302 CleanupStack::Pop(); //dirList |
|
2303 delete dirList; |
|
2304 } |
|
2305 |
|
2306 BTIC_TRACE_PRINT("[BOOT INTECRITY CHECK] FindFilesL <---"); |
|
2307 } |
|
2308 |
|
2309 |
|
2310 |
|
2311 // ----------------------------------------------------------------------------- |
|
2312 // FindMatchFromSisPackageL |
|
2313 // |
|
2314 // This function search given files from SIS Registery. Function removes file |
|
2315 // from aFilesArray alway when it is found in Registery. If aFilesArray contains |
|
2316 // files after function return those files are not found in SIS Registery. |
|
2317 // |
|
2318 // Returns: ETure if successful |
|
2319 // EFalse othervice |
|
2320 // ----------------------------------------------------------------------------- |
|
2321 // |
|
2322 LOCAL_C TBool FindMatchFromSisPackageL( |
|
2323 RFs& aFs, // File server handle |
|
2324 RPointerArray<HBufC>& aFilesArray, // Files to be checked |
|
2325 RPointerArray<HBufC8>& aHashArray, // File's hash |
|
2326 RArray<TUint64>& aCapaArray, // File's capability |
|
2327 RPointerArray<CX509Certificate>& aX509CertArray, // Cert array |
|
2328 RPointerArray<TCapabilitySet>& aCertCapaArray ) // Cert's capability |
|
2329 { |
|
2330 BTIC_TRACE_PRINT("[BOOT INTECRITY CHECK] FindMatchFromSisPackageL --->"); |
|
2331 __UHEAP_MARK; |
|
2332 |
|
2333 TInt err = KErrNone; |
|
2334 TBool allOK = EFalse; |
|
2335 |
|
2336 Swi::RSisRegistrySession sisRegSession; |
|
2337 |
|
2338 err = sisRegSession.Connect(); |
|
2339 |
|
2340 if ( err == KErrNone ) |
|
2341 { |
|
2342 CleanupClosePushL( sisRegSession ); |
|
2343 |
|
2344 RPointerArray<CSisRegistryPackage> sisPackages; |
|
2345 |
|
2346 // Find installed packages. |
|
2347 sisRegSession.InstalledPackagesL( sisPackages ); |
|
2348 |
|
2349 TBool entryOpen = EFalse; |
|
2350 TInt entryFilesCount = 0; |
|
2351 TInt fileCount = 0; |
|
2352 Swi::RSisRegistryEntry entry; |
|
2353 // Array for entrys files. This owns heap memory. |
|
2354 RPointerArray<HBufC> installedFiles; |
|
2355 // Array for dll and exe files found in sis registery. |
|
2356 RPointerArray<HBufC> entryFiles; |
|
2357 // Array for wild card string to be search from file list. |
|
2358 RPointerArray<HBufC> stringArray; |
|
2359 HBufC* string; |
|
2360 |
|
2361 // Add wild card strings to array. |
|
2362 string = KBTICExtensionExe().AllocLC(); |
|
2363 User::LeaveIfError( stringArray.Append( string ) ); |
|
2364 CleanupStack::Pop(); |
|
2365 |
|
2366 string = KBTICExtensionDll().AllocLC(); |
|
2367 User::LeaveIfError( stringArray.Append( string ) ); |
|
2368 CleanupStack::Pop(); |
|
2369 |
|
2370 // Open sis registery entry and search paths to installed exes and dlls. |
|
2371 for( TInt index = 0; index < sisPackages.Count(); index++) |
|
2372 { |
|
2373 BTIC_TRACE_PRINT_NUM("entry loop Index = %d", index ); |
|
2374 |
|
2375 // If error happens make leave. If some pacage is left out we can |
|
2376 // not continue, because all files found in C must be found also |
|
2377 // in sis registery. |
|
2378 User::LeaveIfError( |
|
2379 entry.OpenL( sisRegSession, *sisPackages[index] ) ); |
|
2380 |
|
2381 CleanupClosePushL( entry ); |
|
2382 entryOpen = ETrue; |
|
2383 |
|
2384 // Get this entrys installed files. |
|
2385 entry.FilesL( installedFiles ); |
|
2386 |
|
2387 if ( installedFiles.Count() > 0 ) |
|
2388 { |
|
2389 // Search match for string array conten from entrys files. |
|
2390 // Note that heap memory is owned by installeFiles array. |
|
2391 SearchFilesFromArrayL( |
|
2392 installedFiles, |
|
2393 KBTICSysPathCWildcard, |
|
2394 stringArray, |
|
2395 entryFiles ); |
|
2396 } |
|
2397 |
|
2398 entryFilesCount = entryFiles.Count(); |
|
2399 |
|
2400 BTIC_TRACE_PRINT_NUM("Entry files count = %d", entryFilesCount ); |
|
2401 |
|
2402 if ( entryFilesCount > 0 ) |
|
2403 { |
|
2404 TBool pagaceCertValid = EFalse; |
|
2405 |
|
2406 // Go torug all file paths from entryFiles aray. |
|
2407 for ( TInt indexB = 0; indexB < entryFilesCount; indexB++ ) |
|
2408 { |
|
2409 BTIC_TRACE_PRINT_NUM("file path loop IndexB = %d", indexB ); |
|
2410 |
|
2411 // Get file's path from sis pagace entry. |
|
2412 HBufC* entryFile = entryFiles[indexB]; |
|
2413 |
|
2414 fileCount = aFilesArray.Count(); |
|
2415 |
|
2416 // Compare registery file path to files found in C:\sys\bin. |
|
2417 for ( TInt indexC = fileCount - 1; indexC >= 0; indexC-- ) |
|
2418 { |
|
2419 // Get file's path from array conteining dlls and exes. |
|
2420 HBufC* file = aFilesArray[indexC]; |
|
2421 |
|
2422 TInt result = entryFile->CompareC( *file ); |
|
2423 |
|
2424 BTIC_TRACE_PRINT_NUM("\nCompare result = %d", result ); |
|
2425 |
|
2426 // If result is zero match is found. |
|
2427 if ( result == 0 ) |
|
2428 { |
|
2429 BTIC_TRACE_PRINT("File path Match found" ); |
|
2430 |
|
2431 // Get file's hash |
|
2432 HBufC8* hash = aHashArray[indexC]; |
|
2433 |
|
2434 BTIC_TRACE_PRINT("CompareToRegisteryHashL -->" ); |
|
2435 |
|
2436 TBool hashOk = CompareToRegisteryHashL( |
|
2437 entry, |
|
2438 *entryFile, |
|
2439 *hash ); |
|
2440 |
|
2441 BTIC_TRACE_PRINT("CompareToRegisteryHashL <--" ); |
|
2442 |
|
2443 |
|
2444 if ( hashOk ) |
|
2445 { |
|
2446 BTIC_TRACE_PRINT("HASH OK"); |
|
2447 |
|
2448 // Check if entry cert is already valid. |
|
2449 if ( ! pagaceCertValid ) |
|
2450 { |
|
2451 BTIC_TRACE_PRINT("Validate pagace cert"); |
|
2452 |
|
2453 // Validate entry's certificate and |
|
2454 // check that certificate has correct |
|
2455 // capablities. |
|
2456 TBool certOk = SearchValidCertificateL( |
|
2457 entry, |
|
2458 aX509CertArray, |
|
2459 aCertCapaArray, |
|
2460 aCapaArray[indexC] ); |
|
2461 |
|
2462 if ( certOk ) |
|
2463 { |
|
2464 BTIC_TRACE_PRINT("Pagace CERT VALID - OK"); |
|
2465 |
|
2466 // Validate pagace cert. only once. |
|
2467 pagaceCertValid = ETrue; |
|
2468 } |
|
2469 else |
|
2470 { |
|
2471 // Rename file if cert is not ok. |
|
2472 |
|
2473 RenameFileL( aFs, *entryFile ); |
|
2474 // Should we rename all files in this |
|
2475 // entry or only this one. |
|
2476 } |
|
2477 } |
|
2478 } |
|
2479 else |
|
2480 { |
|
2481 BTIC_TRACE_PRINT("HASH Error -> Rename file"); |
|
2482 // If hash is false rename file. |
|
2483 RenameFileL( aFs, *entryFile ); |
|
2484 } |
|
2485 |
|
2486 // Set arrays entry to zero so we will not |
|
2487 // compear it twice. We do not have to delete |
|
2488 // entry because aFilesArray do not own heap |
|
2489 // memory. |
|
2490 aFilesArray.Remove( indexC ); |
|
2491 |
|
2492 //Remove also hash and capa entry from array. |
|
2493 HBufC8* hashBuffer = aHashArray[indexC]; |
|
2494 delete hashBuffer; |
|
2495 aHashArray.Remove( indexC); |
|
2496 |
|
2497 aCapaArray.Remove( indexC ); |
|
2498 |
|
2499 break; |
|
2500 } |
|
2501 } |
|
2502 } |
|
2503 } |
|
2504 |
|
2505 if ( entryOpen ) |
|
2506 { |
|
2507 BTIC_TRACE_PRINT("Clear ENTRY and installedFiles array"); |
|
2508 |
|
2509 CleanupStack::PopAndDestroy(); //entry |
|
2510 entryFiles.Reset(); //Reset only. |
|
2511 installedFiles.ResetAndDestroy(); |
|
2512 } |
|
2513 |
|
2514 // Break entry loop if all files are removed. |
|
2515 if ( aFilesArray.Count() == 0 ) |
|
2516 { |
|
2517 BTIC_TRACE_PRINT("NO MORE EXE/DLL FILES -> BREAK LOOP"); |
|
2518 break; |
|
2519 } |
|
2520 } |
|
2521 |
|
2522 stringArray.ResetAndDestroy(); |
|
2523 CleanupStack::PopAndDestroy(); // sisRegSession |
|
2524 |
|
2525 allOK = ETrue; |
|
2526 } |
|
2527 |
|
2528 |
|
2529 BTIC_TRACE_PRINT("UHEAP MARK END"); |
|
2530 __UHEAP_MARKEND; |
|
2531 BTIC_TRACE_PRINT("[BOOT INTECRITY CHECK] FindMatchFromSisPackageL <---"); |
|
2532 |
|
2533 return allOK; |
|
2534 } |
|
2535 |
|
2536 |
|
2537 #endif //__BTIC_BINARIES_CHECK_ENABLED |
|
2538 */ |
|
2539 |
|
2540 // =========================== CRootCertificateEntry =========================== |
|
2541 |
|
2542 // ----------------------------------------------------------------------------- |
|
2543 // NewLC() |
|
2544 // |
|
2545 // ----------------------------------------------------------------------------- |
|
2546 // |
|
2547 CRootCertificateEntry* CRootCertificateEntry::NewLC( RReadStream& aStream ) |
|
2548 { |
|
2549 CRootCertificateEntry* self = new(ELeave) CRootCertificateEntry(); |
|
2550 CleanupStack::PushL(self); |
|
2551 |
|
2552 self->InternalizeL( aStream ); |
|
2553 |
|
2554 return self; |
|
2555 } |
|
2556 |
|
2557 |
|
2558 // ----------------------------------------------------------------------------- |
|
2559 // CRootCertificateEntry() |
|
2560 // |
|
2561 // ----------------------------------------------------------------------------- |
|
2562 // |
|
2563 CRootCertificateEntry::CRootCertificateEntry() |
|
2564 { |
|
2565 } |
|
2566 |
|
2567 |
|
2568 // ----------------------------------------------------------------------------- |
|
2569 // ~CRootCertificateEntry() |
|
2570 // |
|
2571 // ----------------------------------------------------------------------------- |
|
2572 // |
|
2573 CRootCertificateEntry::~CRootCertificateEntry() |
|
2574 { |
|
2575 iApplications.Close(); |
|
2576 } |
|
2577 |
|
2578 |
|
2579 // ----------------------------------------------------------------------------- |
|
2580 // InternalizeL() |
|
2581 // |
|
2582 // ----------------------------------------------------------------------------- |
|
2583 // |
|
2584 void CRootCertificateEntry::InternalizeL( RReadStream& aStream ) |
|
2585 { |
|
2586 BTIC_TRACE_PRINT("[BOOT INTECRITY CHECK] InternalizeL"); |
|
2587 |
|
2588 iX509CertificateType = aStream.ReadUint8L(); |
|
2589 |
|
2590 iSize = aStream.ReadInt32L(); |
|
2591 |
|
2592 aStream >> iLabel; |
|
2593 |
|
2594 iCertId = aStream.ReadInt32L(); |
|
2595 |
|
2596 iCACertificateType = aStream.ReadUint8L(); |
|
2597 |
|
2598 aStream >> iSubjectKeyId; |
|
2599 |
|
2600 aStream >> iIssuerKeyId; |
|
2601 |
|
2602 TInt count = aStream.ReadInt32L(); |
|
2603 |
|
2604 for ( TInt i = 0 ; i < count ; ++i ) |
|
2605 { |
|
2606 TUid id; |
|
2607 aStream >> id; |
|
2608 User::LeaveIfError( iApplications.Append( id ) ); |
|
2609 } |
|
2610 |
|
2611 iTrusted = !!aStream.ReadUint8L(); // converts TUint8 to TBool |
|
2612 |
|
2613 aStream >> iDataStreamId; |
|
2614 |
|
2615 TPckg<TCapabilitySet> capsPckg( iCapabilities ); |
|
2616 aStream >> capsPckg; |
|
2617 |
|
2618 iMandatory = !!aStream.ReadUint8L(); |
|
2619 } |
|
2620 |
|
2621 |
|
2622 // ----------------------------------------------------------------------------- |
|
2623 // DataStreamId() |
|
2624 // |
|
2625 // ----------------------------------------------------------------------------- |
|
2626 // |
|
2627 TStreamId CRootCertificateEntry::DataStreamId() const |
|
2628 { |
|
2629 return iDataStreamId; |
|
2630 } |
|
2631 |
|
2632 |
|
2633 // ----------------------------------------------------------------------------- |
|
2634 // Capabilities() |
|
2635 // |
|
2636 // ----------------------------------------------------------------------------- |
|
2637 // |
|
2638 const TCapabilitySet& CRootCertificateEntry::Capabilities() const |
|
2639 { |
|
2640 return iCapabilities; |
|
2641 } |
|
2642 |
|
2643 // ----------------------------------------------------------------------------- |
|
2644 // Size() |
|
2645 // |
|
2646 // ----------------------------------------------------------------------------- |
|
2647 // |
|
2648 TInt CRootCertificateEntry::Size() const |
|
2649 { |
|
2650 return iSize; |
|
2651 } |
|
2652 |
|
2653 |
|
2654 // ----------------------------------------------------------------------------- |
|
2655 // CertID() |
|
2656 // |
|
2657 // ----------------------------------------------------------------------------- |
|
2658 // |
|
2659 TInt CRootCertificateEntry::CertID() const |
|
2660 { |
|
2661 return iCertId; |
|
2662 } |
|
2663 |
|
2664 |
|
2665 |
|
2666 // =========================== CActiveFileObserver ============================ |
|
2667 |
|
2668 // ----------------------------------------------------------------------------- |
|
2669 // CActiveFileObserver::CActiveFileObserver() |
|
2670 // ----------------------------------------------------------------------------- |
|
2671 // |
|
2672 CActiveFileObserver::CActiveFileObserver( RFs& aFs, TInt& aResult) |
|
2673 : CActive( EPriorityNormal ), |
|
2674 iFs( aFs ), |
|
2675 iResult( aResult ) |
|
2676 { |
|
2677 } |
|
2678 |
|
2679 |
|
2680 // ----------------------------------------------------------------------------- |
|
2681 // CActiveFileObserver::~CActiveFileObserver() |
|
2682 // Destructor |
|
2683 // ----------------------------------------------------------------------------- |
|
2684 // |
|
2685 CActiveFileObserver::~CActiveFileObserver() |
|
2686 { |
|
2687 BTIC_TRACE_PRINT("[BOOT INTECRITY CHECK] ~CActiveFileObserver"); |
|
2688 // Cancel the outstanding request. This calls DoCancel(). |
|
2689 Cancel(); |
|
2690 // Close timer. |
|
2691 iRTimer.Close(); |
|
2692 |
|
2693 if ( iPath ) |
|
2694 { |
|
2695 delete iPath; |
|
2696 iPath = NULL; |
|
2697 } |
|
2698 } |
|
2699 |
|
2700 |
|
2701 // ----------------------------------------------------------------------------- |
|
2702 // CActiveFileObserver* CActiveFileObserver::NewL() |
|
2703 // Factory method. |
|
2704 // ----------------------------------------------------------------------------- |
|
2705 // |
|
2706 CActiveFileObserver* CActiveFileObserver::NewL( |
|
2707 RFs& aFs, |
|
2708 const TDesC& aPath, |
|
2709 TInt& aResult ) |
|
2710 { |
|
2711 CActiveFileObserver* observer = |
|
2712 new(ELeave) CActiveFileObserver( aFs, aResult ); |
|
2713 |
|
2714 CleanupStack::PushL( observer ); |
|
2715 |
|
2716 observer->ConstructL( aPath ); |
|
2717 |
|
2718 CleanupStack::Pop(); |
|
2719 |
|
2720 return observer; |
|
2721 } |
|
2722 |
|
2723 |
|
2724 // ----------------------------------------------------------------------------- |
|
2725 // CActiveFileObserver::ConstructL() |
|
2726 // Second-phase constructor. |
|
2727 // ----------------------------------------------------------------------------- |
|
2728 // |
|
2729 void CActiveFileObserver::ConstructL( const TDesC& aPath ) |
|
2730 { |
|
2731 BTIC_TRACE_PRINT("[BOOT INTECRITY CHECK] CActiveFileObserver::ConstructL"); |
|
2732 |
|
2733 iRunCount = 0; |
|
2734 |
|
2735 iPath = HBufC::NewL( aPath.Length() ); |
|
2736 TPtr iPathPtr = iPath->Des(); |
|
2737 iPathPtr.Copy( aPath ); |
|
2738 |
|
2739 iRTimer.CreateLocal(); |
|
2740 |
|
2741 // Add to scheduler. |
|
2742 CActiveScheduler::Add( this ); |
|
2743 |
|
2744 // Issue first timer request. |
|
2745 IssueRequest(); |
|
2746 } |
|
2747 |
|
2748 |
|
2749 // ----------------------------------------------------------------------------- |
|
2750 // CActiveFileObserver::DoCancel() |
|
2751 // Cancel function for active object. |
|
2752 // ----------------------------------------------------------------------------- |
|
2753 // |
|
2754 void CActiveFileObserver::DoCancel() |
|
2755 { |
|
2756 BTIC_TRACE_PRINT("[BOOT INTECRITY CHECK] CActiveFileObserver::DoCancel"); |
|
2757 // Cancel outstanding request. |
|
2758 iRTimer.Cancel(); |
|
2759 } |
|
2760 |
|
2761 |
|
2762 // ----------------------------------------------------------------------------- |
|
2763 // CActiveFileObserver::RunError() |
|
2764 // Handles a leave occurring in the request completion event handler RunL. |
|
2765 // ----------------------------------------------------------------------------- |
|
2766 // |
|
2767 TInt CActiveFileObserver::RunError( TInt aError ) |
|
2768 { |
|
2769 BTIC_TRACE_PRINT("[BOOT INTECRITY CHECK] CActiveFileObserver::RunError"); |
|
2770 iResult = aError; |
|
2771 BTIC_TRACE_PRINT_NUM("[BOOT INTE.] RunError: err = %d", aError ); |
|
2772 return aError; |
|
2773 } |
|
2774 |
|
2775 |
|
2776 // ----------------------------------------------------------------------------- |
|
2777 // CActiveFileObserver::IssueRequest() |
|
2778 // This function issues new |
|
2779 // ----------------------------------------------------------------------------- |
|
2780 void CActiveFileObserver::IssueRequest() |
|
2781 { |
|
2782 BTIC_TRACE_PRINT("[BOOT INTECRITY CHECK] CActiveFileObserver::IssueRequest"); |
|
2783 //iFs.NotifyChange( ENotifyEntry, iStatus, *iPath ); |
|
2784 iRunCount++; |
|
2785 |
|
2786 iRTimer.After( iStatus, KBTICObserverTime ); |
|
2787 |
|
2788 // Wait request to complete. |
|
2789 SetActive(); |
|
2790 } |
|
2791 |
|
2792 |
|
2793 // ----------------------------------------------------------------------------- |
|
2794 // CActiveFileObserver::RunL() |
|
2795 // This function handles active object’s request completion event |
|
2796 // ----------------------------------------------------------------------------- |
|
2797 // |
|
2798 void CActiveFileObserver::RunL() |
|
2799 { |
|
2800 BTIC_TRACE_PRINT("[BOOT INTECRITY CHECK] CActiveFileObserver::RunL"); |
|
2801 |
|
2802 TInt err = KErrNone; |
|
2803 RFile file; |
|
2804 // Try to open the file. |
|
2805 err = file.Open( iFs, *iPath, EFileShareReadersOrWriters | EFileRead ); |
|
2806 |
|
2807 BTIC_TRACE_PRINT_NUM("[BOOT INTE.] RunL: file open err = %d", err ); |
|
2808 |
|
2809 if ( err == KErrNone ) |
|
2810 { |
|
2811 // Close the file. |
|
2812 file.Close(); |
|
2813 |
|
2814 if ( iRunCount < KBTICRunCount ) |
|
2815 { |
|
2816 // Make new request. |
|
2817 IssueRequest(); |
|
2818 } |
|
2819 else |
|
2820 { |
|
2821 BTIC_TRACE_PRINT("[BOOT INTE.] RunL: File not deleted -> CANCEL"); |
|
2822 // File is not deleted. Stop active observer |
|
2823 // and continue data base checking. |
|
2824 iResult = KErrCancel; |
|
2825 Deque(); |
|
2826 CActiveScheduler::Stop(); |
|
2827 } |
|
2828 } |
|
2829 else if ( err == KErrNotFound || err == KErrPathNotFound ) |
|
2830 { |
|
2831 // Ok file is deleted. Stop active observer and return. |
|
2832 BTIC_TRACE_PRINT("[BOOT INTE.] RunL: File deleted -> OK"); |
|
2833 iResult = KErrNone; |
|
2834 Deque(); |
|
2835 CActiveScheduler::Stop(); |
|
2836 } |
|
2837 else |
|
2838 { |
|
2839 // Some other file open error etc. KErrInUse. Let's continue. |
|
2840 |
|
2841 if ( iRunCount < KBTICRunCount ) |
|
2842 { |
|
2843 // Make new request. |
|
2844 IssueRequest(); |
|
2845 } |
|
2846 else |
|
2847 { |
|
2848 BTIC_TRACE_PRINT("[BOOT INTE.] RunL: File not deleted -> CANCEL"); |
|
2849 // File is not deleted. Stop active observer |
|
2850 // and continue data base checking. |
|
2851 iResult = KErrCancel; |
|
2852 Deque(); |
|
2853 CActiveScheduler::Stop(); |
|
2854 } |
|
2855 } |
|
2856 } |
|
2857 |
|
2858 //EOF |