boottimeintegritycheck/src/IntegrityCheck.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Mon, 15 Mar 2010 12:43:21 +0200
branchRCL_3
changeset 8 ece4bbb094df
parent 0 164170e6151a
permissions -rw-r--r--
Revision: 201009 Kit: 201010

/*
* Copyright (c) 2005-2008 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description:  Implementation of boot time integrity check program.
*
*/


// INCLUDE FILES

#include <e32cons.h>
#include <f32file.h>
#include <cctcertinfo.h>        // TCapabilitySet
#include <s32file.h> 
#include <signed.h>             // VerifySignatureL
#include <x500dn.h>             // ExactMatchL
#include <x509cert.h>           // x509
#include <swi/hashcontainer.h>
#include <swi/sisregistrysession.h>
#include <swi/sisregistryentry.h>
#include <swi/sisregistrypackage.h>
#include <hash.h>
#include <etelmm.h>             // For serial number size

#include "IntegrityCheck.h"
#include "InfoServerClient.h"
#include "IntegrityCheckDefs.h"
#include "IntegrityCheckClient.h"
#include "IntegrityCheckDebug.h"


// CONSTANTS

_LIT(KBTICThreadName,"BootIntegrityCheck"); 
_LIT(KBTICCertStoreZ,"z:\\resource\\swicertstore.dat");
_LIT(KBTICCertStoreCName,"updatedswicertstore.dat");
_LIT(KBTICCertStoreCPath,"c:\\resource\\swicertstore\\dat\\");
_LIT(KBTICDriveC,"c:\\");
_LIT(KBTICDriveCWildcard,"c:\\*");
_LIT(KBTICExtensionExe,"*.exe");
_LIT(KBTICSerialNumberFile,"*imei.txt");
_LIT(KBTICStarWildcard,"*\\");
/*
#ifdef __BTIC_BINARIES_CHECK_ENABLED
_LIT(KBTICSysPathC,"c:\\sys\\bin\\");
_LIT(KBTICCertStoreC,
    "c:\\resource\\swicertstore\\dat\\updatedswicertstore.dat"); 
_LIT(KBTICSysPathCWildcard,"c:\\sys\\bin\\*");
_LIT(KBTICExtensionDll,"*.dll");
_LIT(KBTICExtensionDat,"*.dat");
#endif //__BTIC_BINARIES_CHECK_ENABLED 
*/    
const TInt KBTICCapaCount = 2;  //Number of capabilities.
const TUint64 KBTIC_DRM = 64;   //0000 0000 0000 0000 0000 0000 0100 0000
const TUint64 KBTIC_TCB = 1;    //0000 0000 0000 0000 0000 0000 0000 0001
const TInt KBTICCabaWordOffset = 17; //File heder offset for capa. word @ 64bit.  
const TInt KBTICHashSize = 20; 
const TInt KBTICTryToOpen = 240;  //Try to open file. (240 x 0.5sec = 120sec)   
const TInt KBTICTryToCreate = 5; // Try to create process.
const TUint KBTICObserverTime = 1000000; // 1sec.
const TUint KBTICRunCount = 10; 
        
// MACROS

using namespace Swi;

// DATA TYPES

// FUNCTION PROTOTYPES

template <class T>
class CleanupResetAndDestroy
    {
public:
    inline static void PushL(T& aRef);
private:
    static void ResetAndDestroy(TAny *aPtr);
    };
    
template <class T>
inline void CleanupResetAndDestroyPushL(T& aRef);

template <class T>
inline void CleanupResetAndDestroy<T>::PushL(T& aRef)
    {
    CleanupStack::PushL(TCleanupItem(&ResetAndDestroy,&aRef));
    }

template <class T>
void CleanupResetAndDestroy<T>::ResetAndDestroy(TAny *aPtr)
    {
    static_cast<T*>(aPtr)->ResetAndDestroy();
    }

template <class T>
inline void CleanupResetAndDestroyPushL(T& aRef)
    {
    CleanupResetAndDestroy<T>::PushL(aRef);
    }


LOCAL_C TInt ThreadStartL();

LOCAL_C TInt ReadCertificatesL( 
    RFs& aFs, 
    const TDesC& aPath,     
    RPointerArray<CX509Certificate>& aX509CertArray,
    RPointerArray<TCapabilitySet>& aCapabilityArray  );
 
LOCAL_C TBool ValidateCertStoreL(
    RFs& aFs,     
    RPointerArray<CX509Certificate>& aX509CertArray,
    RPointerArray<TCapabilitySet>& aCapaArray,
    const TDesC& aCertStoreFileName,
    const TDesC& aCertStoreFilePath ); 
    
LOCAL_C TBool ValidateProvisonerCertStoreL(
    RFs& aFs,                                           
    RPointerArray<CX509Certificate>& aX509CertArray,
    RPointerArray<TCapabilitySet>& aCapaArray,     
    const TDesC& aCertStoreFileName,
    const TDesC& aCertStoreFilePath,
    RSisRegistryEntry& aEntry );
    
LOCAL_C TBool ValidateSymbianCertStoreL(
    RFs& aFs,                                           
    RPointerArray<CX509Certificate>& aX509CertArray,
    RPointerArray<TCapabilitySet>& aCapaArray,              
    RSisRegistryEntry& aEntry,
    RPointerArray<HBufC>& aUpdaterExePaths ); 
    
LOCAL_C TBool RunUpdaterL( RFs& aFs, RPointerArray<HBufC>& aUpdaterExePaths );    
    
LOCAL_C TBool DeleteAllFilesL( RFs& aFs, const TDesC& aFolderPath );                

LOCAL_C TBool SearchFilesFromArrayL( 
    RPointerArray<HBufC>& aSourceArray,
    const TDesC& aDriveAndPath,
    RPointerArray<HBufC>& aStringArray, 
    RPointerArray<HBufC>& aFilesArray );
                  
LOCAL_C TBool SearchValidCertificateL( 
    RSisRegistryEntry& aEntry, 
    RPointerArray<CX509Certificate>& aX509CertArray,
    RPointerArray<TCapabilitySet>& aCertCapaArray,
    TUint64 aCapability );

LOCAL_C TCapability GetCapability( TUint64 aCapability );
    
LOCAL_C TBool VerifyHashL(    
    RSisRegistryEntry& aEntry, 
    RPointerArray<HBufC>& aPathArray,
    RPointerArray<HBufC8>& aHashArray );

LOCAL_C TBool CompareToRegisteryHashL( 
    RSisRegistryEntry& aEntry, 
    TDesC& aEntryFile, 
    TDesC8& aHashBuffer ); 
      
LOCAL_C TBool CheckSerialNumberL( RFs& aFs, const TDesC& aFileName ); 

LOCAL_C void CorruptFileL( RFs& aFs, const TDesC& aFileName );                              

LOCAL_C TBool CheckCapabilityWordAndCalcHashL( 
    RFs& aFs, 
    TBool aCheckCapa,
    TUint64* aCapaVector,    
    RPointerArray<HBufC>& aSourceArray,
    RPointerArray<HBufC>& aFilesArray,
    RPointerArray<HBufC8>& aHashArray,
    RArray<TUint64>& aCapaArray );
/*
#ifdef __BTIC_BINARIES_CHECK_ENABLED

LOCAL_C void RenameFileL( RFs& aFs, const TDesC& aFileName );

LOCAL_C void UniteCertArraysL(     
    RPointerArray<CX509Certificate>& aTargetCertArray,
    RPointerArray<CX509Certificate>& aSourceCertArray );

LOCAL_C void UniteCapaArraysL( 
    RPointerArray<TCapabilitySet>& aTargetCapaArray,
    RPointerArray<TCapabilitySet>& aSourceCapaArray );     
        
LOCAL_C void CheckBinariesL( 
    RFs& aFs, 
    RPointerArray<CX509Certificate>& aX509CertArray,
    RPointerArray<TCapabilitySet>& aCertCapaArray );  
 
LOCAL_C void FindFilesL( 
    RFs& aFs, 
    const TDesC& aPath,
    const TDesC& aSearchString,    
    RPointerArray<HBufC>& aFoundFilesArray );
                 
LOCAL_C TBool FindMatchFromSisPackageL( 
    RFs& aFs,    
    RPointerArray<HBufC>& aFilesArray, 
    RPointerArray<HBufC8>& aHashArray, 
    RArray<TUint64>& aCapaArray,
    RPointerArray<CX509Certificate>& aX509CertArray,
    RPointerArray<TCapabilitySet>& aCertCapaArray ); 

#endif //__BTIC_BINARIES_CHECK_ENABLED
*/     

// FORWARD DECLARATIONS

// LOCAL FUNCTION PROTOTYPES

// ============================= LOCAL FUNCTIONS ===============================

// -----------------------------------------------------------------------------
// E32Main()
// Main for ARM environment.
// Returns: KErrNone if successful  
//          Othervice some system error code.
// -----------------------------------------------------------------------------
//
GLDEF_C TInt E32Main()
    {
    BTIC_TRACE_PRINT_ALLOC_CELLS("[BOOT INTECRITY CHECK] Main cell count = %d");  
    TInt err = KErrNone;

    CTrapCleanup* cleanup = CTrapCleanup::New();

    if ( !cleanup )
        {
        return KErrNoMemory;
        }

    TRAP( err, ThreadStartL() );

    BTIC_TRACE_PRINT_NUM("[BOOT INTECRITY CHECK] Main TRAP error = %d", err);
    
    delete cleanup;

    BTIC_TRACE_PRINT_ALLOC_CELLS("[BOOT INTECRITY CHECK] Main cell count = %d"); 
    return err;
    }


// -----------------------------------------------------------------------------
// ThreadStart()
// 
// This is programs main.
// -----------------------------------------------------------------------------
//
LOCAL_C TInt ThreadStartL()
    {                                                       
    BTIC_TRACE_PRINT("[BOOT INTECRITY CHECK] START PROGRAM");    
    __UHEAP_MARK;
    BTIC_TRACE_PRINT_ALLOC_CELLS("Start Cell count = %d");  
   
    BTIC_TRACE_PRINT("Rename thread to BootIntegrityCheck");
    // Rename thread as SecEnvInit.
    User::RenameThread( KBTICThreadName );  
      
    // This should be read with feature manager etc. but since we 
    // only support certificate database checking this is ok.
    TBool binariesCheckEnbled = EFalse;   
    
    TBool certFileFound = EFalse; 
    TInt err = KErrNone; 
    TInt pushToStack = 0; 
        
    // GET BOOT REASON   
    
    BTIC_TRACE_PRINT("Get boot reason");     
    TBool bootReasonFormat = EFalse;   
    RIntegrityCheckClient bticServer;
        
    err = bticServer.Connect();    
    BTIC_TRACE_PRINT_NUM("BTIC Server connect error = %d", err );
    
    if ( err == KErrNone )
        {            
        CleanupClosePushL( bticServer );                                
        TInt bootReason = KErrNone;     
                                               
        // Get boot reason from btic server.
        err = bticServer.GetSWBootReason( bootReason );                          
        BTIC_TRACE_PRINT_NUM("GetSWBootReason error = %d", err );
                            
        if ( err == KErrNone )
            {                                  
            BTIC_TRACE_PRINT_NUM("Boot Reason number = %d", bootReason );
            
            if ( bootReason == EBTICRestoreFactorySetDeep )
                {                                                                
                BTIC_TRACE_PRINT("[BOOT INTECRITY CHECK] Boot reason: FORMAT");  
                bootReasonFormat = ETrue;
                }                                   
            }             
        CleanupStack::PopAndDestroy(); //bticServer                                  
        }
               
    // OPEN FILE SERVER    
    BTIC_TRACE_PRINT("Open FS session");

    RFs fs;
    // Connect to file server.
    User::LeaveIfError( fs.Connect() );
    CleanupClosePushL( fs );
    pushToStack++;

    // Find SWICertStore.dat in C drive.
    TFindFile find( fs ); 
    TBool certStoreOk = EFalse;  
    CDir* entryList = NULL;   
    HBufC* certStoreFilePath = NULL; 
    HBufC* certStoreFileName = NULL; 
           
    BTIC_TRACE_PRINT("Find C SWI certificate store");    
    
    // Get all files from folder. 
    if ( KErrNone == fs.GetDir ( 
        KBTICCertStoreCPath, 
        KEntryAttNormal,
        ESortByName|EDirsFirst, 
        entryList ) )
        {     
        if ( entryList )
            {
            CleanupStack::PushL( entryList );

            TInt count = entryList->Count(); 

            // If file is found.            
            if ( count )
                {                                              
                BTIC_TRACE_PRINT("Store file found");
                
                // Get the highest version certstore file
                const TEntry& entry = (*entryList)[count - 1];                                
                
                // Make temp buffer for file path. 
                TBuf<KMaxFileName> path( KBTICCertStoreCPath );
                path.Append( entry.iName );
                
                certStoreFilePath = path.AllocLC(); 
                pushToStack++;                              
                                                   
                certStoreFileName = entry.iName.AllocLC(); 
                pushToStack++;                                                              
                                                
                certFileFound = ETrue; 
                
                CleanupStack::Pop(); //certStoreFilePath
                CleanupStack::Pop(); //certStoreFileName
                CleanupStack::PopAndDestroy( 1, entryList ); 
                CleanupStack::PushL( certStoreFilePath );                         
                CleanupStack::PushL( certStoreFileName );                           
                }
            else
                {
                BTIC_TRACE_PRINT("No store file present");
                CleanupStack::PopAndDestroy( 1, entryList ); 
                }                                                
            }
        }
    
    BTIC_TRACE_PRINT("Check boot reason");  
    // Check boot reason. If certificate store file is found start active file
    // observer which checks that file is deleted. If not continue checking.        
    if ( bootReasonFormat )
        {
        BTIC_TRACE_PRINT("Boot reason format");    
        if( certFileFound )
            {
            BTIC_TRACE_PRINT("Start active file observer"); 
            TInt status = KErrUnknown;
                        
            // Create active scheduler.
            CActiveScheduler* threadScheduler = new CActiveScheduler;
            CleanupStack::PushL( threadScheduler );
            pushToStack++;

            CActiveScheduler::Install( threadScheduler );

            // Create file observer object.
            CActiveFileObserver* observer =
                CActiveFileObserver::NewL( fs, *certStoreFilePath, status );
            CleanupStack::PushL( observer );
            pushToStack++;
             
            BTIC_TRACE_PRINT("Start active scheduler");            
            CActiveScheduler::Start();            
            
            BTIC_TRACE_PRINT_NUM("File observer status = %d", status );
            
            if ( status == KErrNone )
                {
                // Boot reason is fromat and certificate file is deleted.
                // Stop checking and exit.                    
                BTIC_TRACE_PRINT("Stop checking and exit");
                certFileFound = EFalse;   
                binariesCheckEnbled = EFalse;                 
                }
            }
        else
            {  
            // Boot reason is fromat and no certificate file is found.
            // Stop checking and exit.      
            BTIC_TRACE_PRINT("Stop checking and exit");
            certFileFound = EFalse;   
            binariesCheckEnbled = EFalse;        
            }    
        }
               
 
    BTIC_TRACE_PRINT_NUM("Updated store read enabled(1) = %d",certFileFound);
    BTIC_TRACE_PRINT_NUM("Binaries check enabled(0) = %d",binariesCheckEnbled);           
//FIX   
    // Create pointer array for root certificates.  
    RPointerArray<CX509Certificate> x509CertArray; 
    CleanupResetAndDestroyPushL( x509CertArray );
    pushToStack++;
    RPointerArray<TCapabilitySet> certCapaArray;
    CleanupResetAndDestroyPushL( certCapaArray );
    pushToStack++;
    TInt fileError = 0;
     
    // Read root certificates if needed.      
    if ( certFileFound || binariesCheckEnbled )
        {                                    
        // Get root certificates to x509 format.  
        fileError = 
          ReadCertificatesL( 
              fs, 
              KBTICCertStoreZ, 
              x509CertArray, 
              certCapaArray );

        // Can't read root certificates or array is empty. 
        // Let's return and try this in next boot.    
        if ( fileError || x509CertArray.Count() == 0 )
            {
            BTIC_TRACE_PRINT("ERROR Can't read root certificates ! ! !");
            CleanupStack::PopAndDestroy( pushToStack );

            User::Leave( fileError );
            }               
        }
            
    // Create temporary pointer array for C-drive updated certificates. 
    RPointerArray<CX509Certificate> tempCertArray; 
    CleanupResetAndDestroyPushL( tempCertArray );
    pushToStack++;
    RPointerArray<TCapabilitySet> tempCapaArray; 
    CleanupResetAndDestroyPushL( tempCapaArray );
    pushToStack++;
    
    // If candidate for certstore file is found read it and validate file.
    if ( certFileFound )
        {        
        BTIC_TRACE_PRINT("Read certificates from C");       
                                        
        // Read certificates from C drive and set them to x509 format         
        TRAP( err ,
            fileError = ReadCertificatesL( 
                fs, 
                *certStoreFilePath, 
                tempCertArray,                                          
                tempCapaArray ) );
                
        BTIC_TRACE_PRINT_NUM("C read file error (0) = %d", fileError );
        BTIC_TRACE_PRINT_NUM("C read Trap err (0) = %d", err );                
               
        // If ReadCertificatesL function leaves, we assume that something is
        // tampered and the file is corrupted. However if function returns
        // an error code, file is not corrupted.           
        if ( err )
            {
            fileError = err;
            TRAP_IGNORE( CorruptFileL( fs, *certStoreFilePath ) );
            }                     
                
        // If there is no error when constructing a permanent file store object
        // let's continue.                      
        if ( fileError == KErrNone )
            {
            BTIC_TRACE_PRINT("Validate cert store");
             
            // Validate the certstore in C if certs are found. 
            TRAP( err, 
                  certStoreOk = ValidateCertStoreL( 
                        fs, 
                        x509CertArray, 
                        certCapaArray, 
                        *certStoreFileName,
                        *certStoreFilePath ) );
          
            BTIC_TRACE_PRINT_NUM("Trap err (0) = %d", err );
            BTIC_TRACE_PRINT_NUM("Cert storage valid (1) = %d", certStoreOk ); 
         
            // If validation fails or function leaves we will assume
            // that database is tempered and it will be corrupted. 
            // In practice this mean that all binaries signed with 
            // certificates in C database will be corrupted.                                                                            
            if ( ! certStoreOk || err != KErrNone )
                {                                                    
                TRAP_IGNORE( CorruptFileL( fs, *certStoreFilePath ) );
                } 
                
            BTIC_TRACE_PRINT("\nStore validation complete"); 
            }                                                
        }  
/*                               
#ifdef __BTIC_BINARIES_CHECK_ENABLED
          
    // If found cert store is valid unite arrays.
    if ( certStoreOk )
        {
        UniteCertArraysL( x509CertArray, tempCertArray ); 
        // Reset tempCertArray because x509CertArray owns entrys now.
        tempCertArray.Reset();
         
        UniteCapaArraysL( certCapaArray, tempCapaArray );
        // Reset tempCapaArray because certCapaArray owns entrys now.               
        tempCapaArray.Reset();
        }

    // Check that certificates are found before checking binaries.
    if ( x509CertArray.Count() )
        {
        // Check that cert array and capa array has same amount of entrys.
        // If amount is diffrent do not check binaries. Something is wrong.
        if ( x509CertArray.Count() == certCapaArray.Count() )
            {
            // Check that binaries found in C: are istalled from a valid SIS 
            // pagaces and binary's hash is valid.        
            CheckBinariesL( fs, x509CertArray, certCapaArray );              
            
            BTIC_TRACE_PRINT("\nBinaries check complete\n");
            }                     
        }
                                  
#endif //__BTIC_BINARIES_CHECK_ENABLED
*/      
                            
    BTIC_TRACE_PRINT("\nProgram complete\n");
    // DELETE ALL ARRAYS AND ARRAY CONTENT  
    // x509CertArray, tempCertArray, certCapaArray, tempCapaArray, fs,  buffers
    CleanupStack::PopAndDestroy( pushToStack ); 
      
    BTIC_TRACE_PRINT("UHEAP MARK END");
    __UHEAP_MARKEND;
    BTIC_TRACE_PRINT_ALLOC_CELLS("End Cell count = %d");
     
    BTIC_TRACE_PRINT("[BOOT INTECRITY CHECK] PROGRAM END");   
    return KErrNone;
    }


// -----------------------------------------------------------------------------
// ReadCertificatesL
// 
// This function reads certificates from certificate storage and adds them in to 
// given cert array if certificate can grant TCB or/and DRM. Also certificates 
// capability set is added to given capability array. 
// Given path must be valid one, othervice function returns error code.
//
// Returns: KErrNone if successful 
//          Othervice some system-wide error code.
// -----------------------------------------------------------------------------
//
LOCAL_C TInt ReadCertificatesL( 
    RFs& aFs,                                        // File server handle 
    const TDesC& aPath,                              // Path to storage file. 
    RPointerArray<CX509Certificate>& aX509CertArray, // Cert array.
    RPointerArray<TCapabilitySet>& aCapabilityArray )// Capability array.
    {            
    TInt err = KErrNone;      
    RFile file;
    
    err = file.Open( aFs, aPath, EFileRead );
    
    if ( err == KErrNone )
        {                             
        CleanupClosePushL( file );
      
        CPermanentFileStore* certStore = NULL;
      
        // Trap FromL if file is not in correct form it may leave.
        TRAP( err, certStore = CPermanentFileStore::FromL( file ) );    
          
        if ( certStore && err == KErrNone )
            {
            CleanupStack::Pop( &file ); // Now owned by store.
            CleanupStack::PushL( certStore );

            // Read id of cert list stream
            TStreamId streamId;
            RStoreReadStream stream;  
            stream.OpenLC( *certStore, certStore->Root() );     
            stream >> streamId; 
            CleanupStack::PopAndDestroy( &stream ); 

            // Read the certificate list
            RStoreReadStream certEntryStream;
            certEntryStream.OpenLC( *certStore, streamId );

            // Count entrys from stream.
            TInt count = certEntryStream.ReadInt32L();    
            BTIC_TRACE_PRINT_NUM("CertEntryStream count = %d", count );
                       
            HBufC8* certDataBuf = NULL;
                               
            for ( TInt index = 0 ; index < count ; index++ )
                {
                // Read data from stream.
                CRootCertificateEntry* entry = 
                    CRootCertificateEntry::NewLC( certEntryStream );
                        
                // Get certificate's capabilties from entry.
                TCapabilitySet* capaSet = 
                new( ELeave ) TCapabilitySet( entry->Capabilities() );        
                CleanupStack::PushL( capaSet );
              
                // Check that certificate can grant TCB or DRM capabiltiy.                                 
                if ( capaSet->HasCapability( GetCapability( KBTIC_TCB ) ) || 
                    capaSet->HasCapability( GetCapability( KBTIC_DRM ) ) )
                    {         
                    // Append certificates capability set to array.         
                    User::LeaveIfError( aCapabilityArray.Append( capaSet ) );

                    CleanupStack::Pop( capaSet );                 
                        
                    // Open certificate data stream. This is actual x509 certificate.    
                    RStoreReadStream stream;                  
                    stream.OpenLC( *certStore, entry->DataStreamId() );
                                                      
                    // Get x509 size.
                    TInt size = entry->Size();                                  

                    // Since we do not have so meny certs in device let's make alloc
                    // inside of the loop.                 
                    certDataBuf = HBufC8::NewMaxLC( size );

                    TPtr8 dataBufPtr = certDataBuf->Des();                       
                                
                    // Read x509 binary data to buffer.
                    stream.ReadL( dataBufPtr, size );                   

                    // Create x509 certificate object from binary data.   
                    CX509Certificate* x509Cert = 
                        CX509Certificate::NewLC( *certDataBuf ); 

                    // Append x509 certificate object to pointer array. 
                    User::LeaveIfError( aX509CertArray.Append( x509Cert ) );
                                                  
                    CleanupStack::Pop( x509Cert );
                    x509Cert = NULL;
                    CleanupStack::PopAndDestroy( certDataBuf );
                    certDataBuf = NULL; 
                    CleanupStack::PopAndDestroy( &stream );                     
                    }
                else
                    {
                    // Delete capaSet if certificate has not TCB or DRM.
                    CleanupStack::PopAndDestroy( capaSet );
                    capaSet = NULL;
                    }    
                        
                CleanupStack::PopAndDestroy( entry );
                entry = NULL;       
                }   
              
            CleanupStack::PopAndDestroy( 2 );//certStore, certEntryStream               
            }
        else
            {
            // Clean up file is FromL leaves.
            CleanupStack::PopAndDestroy( &file );
            BTIC_TRACE_PRINT("ERROR CPermanentFileStore - Can not read certs.");
            }           
        }
      
    BTIC_TRACE_PRINT("[BOOT INTECRITY CHECK] ReadCertificatesL <---"); 
  
    return err;      
    }                


// -----------------------------------------------------------------------------
// ValidateCertStoreL()
//
// This function checks that updated SWI certstore in C drive has been installed 
// from valid SIS pacage. 
// SIS pacage must have valid certificate and exe with a TCB capabilities. 
//
// NOTE this function assumes that Certprovisioner tool has imei.txt file. 
//
// Returns: ETure if successful  
//          EFalse othervice
// -----------------------------------------------------------------------------
//
LOCAL_C TBool ValidateCertStoreL( 
    RFs& aFs,                                       // File server handle
    RPointerArray<CX509Certificate>& aX509CertArray,// Certificate array
    RPointerArray<TCapabilitySet>& aCapaArray,      // Capability array
    const TDesC& aCertStoreFileName,
    const TDesC& aCertStoreFilePath  )     
    {
    BTIC_TRACE_PRINT("[BOOT INTECRITY CHECK] ValidateCertStoreL v2->");
    __UHEAP_MARK;
                          
    TBool storeOK = EFalse;                  
 
    RPointerArray<HBufC> updaterExePaths;
    CleanupResetAndDestroyPushL( updaterExePaths );
    
    RPointerArray<CSisRegistryPackage> sisPackages;
    CleanupResetAndDestroyPushL( sisPackages );
         
    Swi::RSisRegistrySession sisRegSession;  

    // Leave if we can not connect to sis register. Othervice we have a risk 
    // that valid files will be renamed if updated certstore is left out.             
    User::LeaveIfError( sisRegSession.Connect() );
        
    CleanupClosePushL( sisRegSession );
                
    // Find installed packages.
    sisRegSession.InstalledPackagesL( sisPackages );            
            
    Swi::RSisRegistryEntry entry;        
        
    TInt packageUID;   
        
    BTIC_TRACE_PRINT("Find matching UID");
    
    // If CertProvisioner tool has install updatedswicertstore file.
    if ( aCertStoreFileName.Compare( KBTICCertStoreCName ) == KErrNone )
        {
        BTIC_TRACE_PRINT("UID -> KBTICCertProvUID");
        packageUID = KBTICCertProvUID;
        }
    else
        {
        BTIC_TRACE_PRINT("UID -> KBTICSymbianSWIUpdaterUID");
        packageUID = KBTICSymbianSWIUpdaterUID;
        }
                
    TBool entryOpen = EFalse;       
    
    // Search correct sis pagace and open entry to it.
    for( TInt index = 0; index < sisPackages.Count(); index++)
        {  
        BTIC_TRACE_PRINT_NUM("Search entry from sis reg. index = %d", index );
             
        if ( sisPackages[index]->Uid() == TUid::Uid( packageUID ) )
            { 
            BTIC_TRACE_PRINT("Open entry");
                                                                    
            User::LeaveIfError( entry.Open( 
                sisRegSession, TUid::Uid( packageUID ) ) );
 
            CleanupClosePushL( entry );

            entryOpen = ETrue;                                                          
            break;                                       
            }             
        } 
                        
    // Validate cert storage.     
    if ( entryOpen )
        {        
        TBool controllerOk = EFalse;   

#ifdef __BTIC_VERIFY_CONTROLLER        
        // Check that sis controller is valid.       
        controllerOk = entry.VerifyControllerSignatureL( aX509CertArray );
                                     
        BTIC_TRACE_PRINT("Controller verify ENABLED"); 
        BTIC_TRACE_PRINT_NUM("Controller verify result (1) = %d", controllerOk );                                             
#else   
        // If controller verify is disabled set boolen to true.     
        controllerOk = ETrue;          
        BTIC_TRACE_PRINT("Controller verify DISABLED" );      
#endif
    
        if ( controllerOk )
            {            
            if ( packageUID == KBTICCertProvUID )
                {                   
                storeOK = ValidateProvisonerCertStoreL(
                    aFs,                                       
                    aX509CertArray,
                    aCapaArray,      
                    aCertStoreFileName,
                    aCertStoreFilePath,
                    entry );
                }
            else
                {
                storeOK = ValidateSymbianCertStoreL(
                    aFs,                                       
                    aX509CertArray,
                    aCapaArray,                                      
                    entry,
                    updaterExePaths );
                }                
            }                                                        
        }                       
                                         
    if ( entryOpen )
        {        
        CleanupStack::PopAndDestroy(); //RSisRegistryEntry               
        }
                       
    CleanupStack::PopAndDestroy(); //RSisRegistrySession    
    
    // Ok Symbian store is valid, let's run Symbian updater exe.
    // NOTE SisRegistry server etc. has file handle open, so we should
    // close SisRegistryEntry before running updater. 
    if ( storeOK && packageUID == KBTICSymbianSWIUpdaterUID )
        {              
        storeOK = RunUpdaterL( aFs, updaterExePaths );                        
        }
    
    CleanupStack::PopAndDestroy( 1, &sisPackages );    
    CleanupStack::PopAndDestroy( 1, &updaterExePaths ); 
                  
    BTIC_TRACE_PRINT("UHEAP MARK END");     
    __UHEAP_MARKEND;   
    BTIC_TRACE_PRINT("[BOOT INTECRITY CHECK] ValidateCertStoreL v2 <-");        
    
    return storeOK;        
    }
    
    
// -----------------------------------------------------------------------------
// ValidateProvisonerCertStoreL()
//
// 
//
//
// Returns: ETure if successful  
//          EFalse othervice
// -----------------------------------------------------------------------------
//
LOCAL_C TBool ValidateProvisonerCertStoreL(
    RFs& aFs,                                       // File server handle
    RPointerArray<CX509Certificate>& aX509CertArray,// Certificate array
    RPointerArray<TCapabilitySet>& aCapaArray,      // Capability array
    const TDesC& aCertStoreFileName,
    const TDesC& aCertStoreFilePath,
    RSisRegistryEntry& aEntry )
    {
    BTIC_TRACE_PRINT("[BOOT INTECRITY CHECK] ValidateProvisonerStoreL --->");
    __UHEAP_MARK;
       
    TBool retOK = EFalse;                      
    // installedFiles array owns entry's files.
    RPointerArray<HBufC> installedFilesArray;
    RPointerArray<HBufC> foundFilesArray;  
    RPointerArray<HBufC> fileArray;  // Files that need to be cheked.
    RPointerArray<HBufC8> hashArray; // Hash for each fileArray's file.
    RArray<TUint64> capaArray;              
    RPointerArray<HBufC> stringArray;
    HBufC* string = NULL;
    
    CleanupResetAndDestroyPushL( installedFilesArray );
    CleanupResetAndDestroyPushL( foundFilesArray );
    CleanupResetAndDestroyPushL( fileArray );
    CleanupResetAndDestroyPushL( hashArray );
    CleanupResetAndDestroyPushL( stringArray );
    
    TUint64* capaVector = new( ELeave ) TUint64[KBTICCapaCount];
    CleanupArrayDeletePushL( capaVector );
    capaVector[0] = KBTIC_TCB;
                                                                                    
    // Get all installed files from this sis register entry 
    // to installedFilesArray.                                                            
    aEntry.FilesL( installedFilesArray );  
                                                                  
    // Search all exes from array.   
    if ( installedFilesArray.Count() > 0 )
        { 
        string = KBTICExtensionExe().AllocLC();
        User::LeaveIfError( stringArray.Append( string ) );
        CleanupStack::Pop();
        
        retOK = SearchFilesFromArrayL( 
            installedFilesArray,
            KBTICDriveCWildcard, 
            stringArray, 
            foundFilesArray );                                  
        } 
                                                                                                               
    // Find a exe that has TCB capapility and calculate hash over the file. 
    if ( retOK )                       
        {                                     
        retOK = CheckCapabilityWordAndCalcHashL( 
            aFs, 
            ETrue, 
            capaVector, 
            foundFilesArray,
            fileArray,
            hashArray,
            capaArray );                        
        }                           
                                                  
    // Validate certificate from this entry and check that 
    // certificate can grant the capability which is neede for the exe (TCB).     
    if ( retOK )
        {                                   
        retOK = SearchValidCertificateL( 
            aEntry, 
            aX509CertArray, 
            aCapaArray, 
            KBTIC_TCB );     
        }         
                 
    // Calculate hash over each exe file found in this entry.     
    // Let's be confident that server is not tempered.    
    if ( retOK )
        {
        retOK = EFalse;
        
        // Ok so now we should have one TCB file in fileArray and 2 other 
        // files in foundFilesArray. We do not need to calculate hash over 
        // TCB files again, so let's remove TCB files from array.              
        TInt countExe = foundFilesArray.Count();        
        TInt countTCB =  fileArray.Count();        
        TBool removeFile = EFalse;                
        
        for ( TInt i = countExe-1; i >= 0 ; i-- )
            {
            removeFile = EFalse;            
            
            for ( TInt k = countTCB-1; k >= 0; k-- )
                {  
                // If fileArray has this path remove it.                               
                if ( (fileArray[k]->Compare( *foundFilesArray[i] )) 
                    == KErrNone )
                    {
                    removeFile = ETrue;                 
                    }
                }
            
            if ( removeFile )
                {                
                foundFilesArray.Remove( i );                      
                }                          
            }
            
        // Compress array so we don not have null pointers on it.        
        foundFilesArray.Compress(); 
        
        // If all files are removed something is wrong. Return False.
        if ( foundFilesArray.Count() )
            {
            // Ok let's calculate hashes for the other exes.
            retOK = CheckCapabilityWordAndCalcHashL( 
                aFs, 
                EFalse, 
                0, 
                foundFilesArray,
                fileArray,
                hashArray,
                capaArray );                             
            }                   
        }          
           
    // Remove previous strings from array.
    stringArray.ResetAndDestroy();
    // Remove pointers from array. Let's not calc. hash again.
    foundFilesArray.Reset();                                    
     
    // Search imei.txt file from array and check that device's serial number
    // is found in the file. NOTE file name must be imei.txt. 
    if ( retOK )
        {          
        retOK = EFalse;
                                 
        string = KBTICSerialNumberFile().AllocLC();
        User::LeaveIfError( stringArray.Append( string ) );
        CleanupStack::Pop();
               
        TBool foundFile = SearchFilesFromArrayL( 
            installedFilesArray,
            KBTICDriveCWildcard, 
            stringArray, 
            foundFilesArray );               
                                   
        if ( foundFile && foundFilesArray.Count() )
            {
            retOK = CheckSerialNumberL( aFs, *foundFilesArray[0] ); 
            }                            
        }        
    
    // Calculate hash over each file (*.dat and imei.txt) and check that 
    // sisregistery has same hash (*.exe,*.dat,imei.txt).             
    if ( retOK )
        {        
        retOK = EFalse;
                        
        // Note that certstore path from sis reg. points to private 
        // directory not file's current logation. So we have to switch 
        // file paths to get correct hash.

        // Remove previous strings from array.
        stringArray.ResetAndDestroy();
                        
        string = HBufC::NewLC( 
            aCertStoreFileName.Length() + 
            sizeof( KBTICStarWildcard ) );            
        TPtr stringPtr = string->Des();  
        
        // Append certstorage name and wildcard (*\\) to string for search. 
        // String should be = "*\\filename.dat"  Let's add "\\" to string
        // so search do not accept eg. Öfilename.dat etc.
        stringPtr.Copy( KBTICStarWildcard );     
        stringPtr.Append( aCertStoreFileName );
         
        User::LeaveIfError( stringArray.Append( string ) );
        CleanupStack::Pop(); //String                
                                        
        // Search correct certstorage file from installedFilesArray.(sis reg.)                           
        TBool foundFile = SearchFilesFromArrayL( 
            installedFilesArray,
            KBTICDriveCWildcard, 
            stringArray, 
            foundFilesArray );                   
                
        if ( foundFile )
            { 
            BTIC_TRACE_PRINT("Correct CertStore file found");
                                   
            // Get original certstorage path from array. 
            HBufC* sisRegPath = foundFilesArray[foundFilesArray.Count() - 1];
                
            // Remove original path from array.     
            foundFilesArray.Remove( foundFilesArray.Count() - 1 );
            CleanupStack::PushL( sisRegPath ); //sisRegPath
            
            // Get current certstorage path.
            HBufC* currentPath = aCertStoreFilePath.AllocLC();

            // Set current path to array. So now we get correct hash. 
            foundFilesArray.Append( currentPath );
            CleanupStack::Pop(); //currentPath

            BTIC_TRACE_PRINT("Calculate HASH for files");

            // Calculate hash over files in foundFilesArray and add result to
            // filesArray and hashArray                                 
            CheckCapabilityWordAndCalcHashL( 
                aFs, 
                EFalse, 
                0, 
                foundFilesArray,
                fileArray,
                hashArray,
                capaArray );   
                
             // Ok now we have correct hash but certstore path is not 
             // correct for sis register. So we have to copy original 
             // certstorage file path from sis reg. to filesArray.
             
             // Remove currentPath entry from array.             
             fileArray.Remove( fileArray.Count() - 1 );
             
             // Delete currentPath buffer. We need to delete buffer because 
             // we call only reset for foundFilesArray. Reset do not delete 
             // buffer.  
             delete currentPath;
             
             // Append orginal path from sis reg. for hash checking. 
             fileArray.Append( sisRegPath ); 
             CleanupStack::Pop(); //sisRegPath                                                                
                                         
            // Check that sis registery entry has same hash as we have.                                                                                                                                              
            retOK = VerifyHashL( aEntry, fileArray, hashArray );   
                         
            }                                                                       
        }
    
    CleanupStack::PopAndDestroy(); //capaVector   

    CleanupStack::Pop( &stringArray );
    CleanupStack::Pop( &hashArray );
    CleanupStack::Pop( &fileArray );
    CleanupStack::Pop( &foundFilesArray );
    CleanupStack::Pop( &installedFilesArray );
                 
    // Reset only. InstalledFiles array owns buffers.
    foundFilesArray.Reset();
    fileArray.Reset(); 
    hashArray.ResetAndDestroy();                                    
    installedFilesArray.ResetAndDestroy();         
    stringArray.ResetAndDestroy(); 
    capaArray.Close();                 
    
    BTIC_TRACE_PRINT("UHEAP MARK END");     
    __UHEAP_MARKEND;
    
    BTIC_TRACE_PRINT("[BOOT INTECRITY CHECK] ValidateProvisonerStoreL <---");
    
    return retOK;    
    }
  
            
// -----------------------------------------------------------------------------
// ValidateSymbianCertStoreL()
//
// 
//
//
// Returns: ETure if successful  
//          EFalse othervice
// -----------------------------------------------------------------------------
//
LOCAL_C TBool ValidateSymbianCertStoreL(
    RFs& aFs,                                       // File server handle
    RPointerArray<CX509Certificate>& aX509CertArray,// Certificate array
    RPointerArray<TCapabilitySet>& aCapaArray,      // Capability array        
    RSisRegistryEntry& aEntry,
    RPointerArray<HBufC>& aUpdaterExePaths )
    {  
    BTIC_TRACE_PRINT("[BOOT INTECRITY CHECK] ValidateSymbianStoreL v2 --->");   
      
    TBool retOK  = EFalse;                       
    // installedFiles array owns entry's files.
    RPointerArray<HBufC> installedFilesArray;
    RPointerArray<HBufC> foundFilesArray;  
    RPointerArray<HBufC> fileArray;  // Files that need to be cheked.
    RPointerArray<HBufC8> hashArray; // Hash for each fileArray's file.
    RArray<TUint64> capaArray;              
    RPointerArray<HBufC> stringArray;
    HBufC* string = NULL;
   
    CleanupResetAndDestroyPushL( installedFilesArray );
    CleanupResetAndDestroyPushL( foundFilesArray );
    CleanupResetAndDestroyPushL( fileArray );
    CleanupResetAndDestroyPushL( hashArray );
    CleanupResetAndDestroyPushL( stringArray );
    
    TUint64* capaVector = new( ELeave ) TUint64[KBTICCapaCount];
    CleanupArrayDeletePushL( capaVector );
    capaVector[0] = KBTIC_TCB;
                                                                                   
    // Get all installed files from this sis register entry 
    // to installedFilesArray.                                                            
    aEntry.FilesL( installedFilesArray );                                          
                     
    // Search all exes from array.   
    if ( installedFilesArray.Count() > 0 )
        { 
        string = KBTICExtensionExe().AllocLC();
        User::LeaveIfError( stringArray.Append( string ) );
        CleanupStack::Pop();
        
        retOK = SearchFilesFromArrayL( 
            installedFilesArray,
            KBTICDriveCWildcard, 
            stringArray, 
            foundFilesArray );                                  
        } 
                                                                                             
    // Find a exe that has TCB capapility and calculate hash over the file. 
    if ( retOK )                       
        {                                     
        retOK = CheckCapabilityWordAndCalcHashL( 
            aFs, 
            ETrue, 
            capaVector, 
            foundFilesArray,
            fileArray,
            hashArray,
            capaArray );                        
        }    
                                                          
    // Validate certificate from this entry and check that 
    // certificate can grant the capability which is neede for the exe (TCB).     
    if ( retOK )
        {                                   
        retOK = SearchValidCertificateL( 
            aEntry, 
            aX509CertArray, 
            aCapaArray, 
            KBTIC_TCB );     
        } 
    
    // Check that sis registery has same hash as we have.              
    if ( retOK )
        {                                                  
        retOK = VerifyHashL( aEntry, fileArray, hashArray );             
        } 
    
    // Return exe's path to caller. NOTE Updater exe can not be executed
    // before SisRegistryEntry is closed.    
    if ( retOK )
        {
        // We will assume that updater has only one exe with TCB.
        HBufC* path = fileArray[0]->AllocLC();          
        // Append path to pointer array. 
        User::LeaveIfError( aUpdaterExePaths.Append( path ) );         
        CleanupStack::Pop(); //path          
        }
   
    CleanupStack::PopAndDestroy(); //capaVector   
    
    CleanupStack::Pop( &stringArray ); 
    CleanupStack::Pop( &hashArray );
    CleanupStack::Pop( &fileArray );
    CleanupStack::Pop( &foundFilesArray );
    CleanupStack::Pop( &installedFilesArray );
                                                               
    // Reset only. InstalledFiles array owns buffers.
    foundFilesArray.Reset();
    fileArray.Reset(); 
    hashArray.ResetAndDestroy();                                    
    installedFilesArray.ResetAndDestroy();         
    stringArray.ResetAndDestroy();  
    capaArray.Close();              
        
    BTIC_TRACE_PRINT("[BOOT INTECRITY CHECK] ValidateSymbianStoreL v2 <---"); 
                                     
    return retOK;
    }


// -----------------------------------------------------------------------------
// RunUpdaterL()
//
// Returns: ETure if successful  
//          EFalse othervice
// -----------------------------------------------------------------------------
// 
LOCAL_C TBool RunUpdaterL( RFs& aFs, RPointerArray<HBufC>& aUpdaterExePaths )
    {
    BTIC_TRACE_PRINT("[BOOT INTECRITY CHECK] RunUpdaterL ->");
    // SIS register do not have hash values for storage file if it is provided 
    // by Symbian SWI updater exe. We have to remove current storage file 
    // and run exe again to get a verified swicertstorage in folder.
            
    TBool retOK = EFalse; 
    
    BTIC_TRACE_PRINT("Delete old store file(s)");          
    // Delete all files from dat folder. If delete fails storage file is 
    // corrupted.
    // NOTE that SisRegistry Server has some closing time so we must try this 
    // in loop.                
    for ( TInt loop = 0; loop < KBTICTryToOpen; loop++ )
        {                
        if ( DeleteAllFilesL( aFs, KBTICCertStoreCPath ) )
            {            
            // We will assume that updater has only on exe with TCB.
            HBufC* updaterExePath = aUpdaterExePaths[0];
                                                           
            RProcess process;
            
            BTIC_TRACE_PRINT("Run updater exe to get new store file"); 
            
            for ( TInt i = 0; i < KBTICTryToCreate; i++ )
                {  
                BTIC_TRACE_PRINT("Try to create Updater process");
                              
                if ( process.Create( *updaterExePath, KNullDesC ) == KErrNone )
                    {
                    // Run updater exe again.
                    process.Resume(); 
                    // Get rid of our handle. 
                    process.Close();
                                        
                    retOK = ETrue;  

                    BTIC_TRACE_PRINT("Updater process started OK"); 
                    break;                                                 
                    }                
                }
                                        
            // Break the loop if delete is succesful.    
            break;    			                                      
            }
        else
            {
            BTIC_TRACE_PRINT_NUM("Wait 0.5 sec. Attempt nr.%d", loop );
            User::After( 500000 );
            }                                                                   
        }
        
    return retOK;                                                     
    }

// -----------------------------------------------------------------------------
// DeleteAllFiles()
//
// Delete all files from given folder.
//
// Returns: ETure if successful  
//          EFalse othervice
// -----------------------------------------------------------------------------
// 
LOCAL_C TBool DeleteAllFilesL( RFs& aFs, const TDesC& aFolderPath )
    {
    BTIC_TRACE_PRINT("[BOOT INTECRITY CHECK] DeleteAllFilesL ");
    
    TBool folderEmpty = EFalse;                      
    CDir* entryList = NULL; 
    TBuf<KMaxFileName> path;        
    
    // Get all files from folder.    
    if ( KErrNone == 
            aFs.GetDir ( 
                aFolderPath, 
                KEntryAttNormal, 
                ESortByName|EDirsFirst, 
                entryList ) )
        {
        if ( entryList )
            {
            CleanupStack::PushL( entryList );
            
            TInt delCount = KErrNone;
            TInt count = entryList->Count();            
            
            for ( TInt index = 0; index < count; index++ )
                {
                // Get file name.
                const TEntry& entry = (*entryList)[index];
                
                // Set path to file. 
                path.Copy( aFolderPath );
                path.Append( entry.iName ); 
                
                // Remove Read Only attribute.
                TInt err = aFs.SetAtt( path, 0, KEntryAttReadOnly );
                BTIC_TRACE_PRINT_NUM("Remove Read Only attrib. = %d", err );                                 
                       
                if ( KErrNone == aFs.Delete( path ) )
                    {                    
                    delCount++;
                    BTIC_TRACE_PRINT_NUM("Delete file with index = %d", index);
                    }
                }
            
            // If all files are removed.           
            if ( delCount == count )
                {
                folderEmpty = ETrue; 
                BTIC_TRACE_PRINT("All files removed");
                }

            CleanupStack::PopAndDestroy( 1, entryList );                             
            }                                     
        }
                                    
    return folderEmpty;
    }


// -----------------------------------------------------------------------------
// SearchFilesFromArrayL
// 
// This function search file names containing given string from aSourceArray and 
// add found file (path) to an aFilesArray. Search is limited to specified drive 
// and path.
// Note this function only adds source arrays pointers to files array. It dos not
// create new heap descriptor.    
// 
//
// Returns: ETure if successful  
//          EFalse othervice
// -----------------------------------------------------------------------------
// 
LOCAL_C TBool SearchFilesFromArrayL( 
    RPointerArray<HBufC>& aSourceArray, // Array for searching.
    const TDesC& aDriveAndPath,         // Accepted drive or/and path. 
    RPointerArray<HBufC>& aStringArray, // String to be searched from path.
    RPointerArray<HBufC>& aFilesArray ) // Result array.
    {
    BTIC_TRACE_PRINT("[BOOT INTECRITY CHECK] SearchFilesFromArrayL --->");

    TBool retVal = EFalse; 
                
    TInt count = aSourceArray.Count();
    TInt stringCount = aStringArray.Count();
    
    // This loop gos through all paths from aSourceArray.                                 
    for ( TInt index = 0; index < count; index++ )
        {                
        HBufC* filePath = aSourceArray[index];
        
        // Convert descriptor to lower case so we don't get problems with 
        // Match or Compare functions. 
        TPtr filePathPtr = filePath->Des();
        filePathPtr.LowerCase(); 
        
        // Check that file is in correct directory.
        TInt offsetA = filePath->Match( aDriveAndPath );
        
        if ( offsetA >= 0 )
            {                                                       
            // This loop gos through all strings what we are looking for.
            for ( TInt indexB = 0; indexB < stringCount; indexB++ )
                {                                
                // Search string from file path.            
                TInt offset = filePath->Match( *aStringArray[indexB] );
                                                    
                if ( offset >= 0 )
                    {            
                    User::LeaveIfError( aFilesArray.Append( filePath ) );  
                                        
                    retVal = ETrue;                                    
                    }
                }  
            }
        }                              
     
    BTIC_TRACE_PRINT("[BOOT INTECRITY CHECK] SearchFilesFromArrayL <---");         
        
    return retVal;                    
    }


// -----------------------------------------------------------------------------
// SearchValidCertificateL
// 
// This function validates entry's certificate against to certificate found in 
// given array. It check also that certificate has rigth to grant given 
// capability. 
//
// Note This function only validates first chain.    
// 
// Returns: ETure if successful  
//          EFalse othervice
// -----------------------------------------------------------------------------
//              
LOCAL_C TBool SearchValidCertificateL( 
    RSisRegistryEntry& aEntry,                      // SIS Registery entry
    RPointerArray<CX509Certificate>& aX509CertArray,// Array for certificates
    RPointerArray<TCapabilitySet>& aCertCapaArray,  // Array for certs capability
    TUint64 aCapability )                           // Needed capabiltiy
    {
    BTIC_TRACE_PRINT("[BOOT INTECRITY CHECK] SearchValidCertificate v2.1 --->");      

    RPointerArray<HBufC8> binaryCertChainArray;
    CleanupResetAndDestroyPushL( binaryCertChainArray );
    
    // Get certificates in binary format.
    aEntry.CertificateChainsL( binaryCertChainArray );
                            
    TInt chainCount = binaryCertChainArray.Count();
    BTIC_TRACE_PRINT_NUM("Entry chain count (1) = %d", chainCount );
        
    TBool retVal = EFalse;                                                                  

    RPointerArray<CX509Certificate> chainCertArray;
    CleanupResetAndDestroyPushL( chainCertArray );
    
    // Check all entry's chains    
    for ( TInt chain = 0; chain < chainCount; chain++ )
        {  
        BTIC_TRACE_PRINT_NUM("Check chain nr = %d", chain);
                                   
        TPtr8 chainData = binaryCertChainArray[chain]->Des();

        TInt pos = 0;
        TInt end = chainData.Length();                                                    

        // Get all certificates from chain.
        while ( pos < end )
            {                                   
            CX509Certificate* decoded = 
                CX509Certificate::NewLC( chainData, pos ); 
                                    
            // Add x509 certificate to pointter array. 
            User::LeaveIfError( chainCertArray.Append( decoded ) );  
                                                                     
            CleanupStack::Pop( decoded );
            }
                       
        TInt chainCertCount = chainCertArray.Count();    
        BTIC_TRACE_PRINT_NUM("Chain's certificate count = %d", chainCertCount);

        // Search certificate issued to root and verify signature against the root.
        if ( chainCertCount > 0 )
            {        
            BTIC_TRACE_PRINT("Validate last cert against root");                  
            // Last cert in chain should be issued to root.
            const CX509Certificate* x509LastChainCert = chainCertArray[chainCertCount-1];    
                
            TInt rootCertCount = aX509CertArray.Count();                   
            BTIC_TRACE_PRINT_NUM("Root cert array count = %d", rootCertCount);
            TBool rootFound = EFalse;
            TInt rootIndex = 0;         
                
            // Find matching root certificate and validate certificates.
            for ( rootIndex = 0; rootIndex < rootCertCount; rootIndex++ )
                {
                BTIC_TRACE_PRINT_NUM("Root cert index = %d", rootIndex );
                            
                const CX509Certificate* x509RootCert = aX509CertArray[rootIndex];

                // Compare entry cert's issuer to root cert's subject. 
                if ( x509LastChainCert->IssuerName().ExactMatchL(
                     x509RootCert->SubjectName() ) )
                    {
                    BTIC_TRACE_PRINT("Root found for this chain"); 
                    BTIC_TRACE_PRINT("Verify signature");                                
                    
                    // Verify signature 
                    if ( x509LastChainCert->VerifySignatureL( 
                        x509RootCert->PublicKey().KeyData() ) )
                        {                                                    
                        BTIC_TRACE_PRINT("Signature OK");                    
                        rootFound = ETrue;
                        break; // Break loop.
                        }
                    }
                }            
              
              // If root is found we have correct chain.
              if ( rootFound )
                  {              
                  // If Chain has more then one certificate, verify chain.
                  if ( chainCertCount > 1 )
                    {
                    BTIC_TRACE_PRINT("Verify certificate chain"); 
                    TBool chainOK = ETrue;
                    TInt certindex;
                    
                    for ( certindex = 0; certindex < chainCertCount-1; certindex++ )
                        {    
                        BTIC_TRACE_PRINT_NUM("Cert index = %d", certindex);
                        BTIC_TRACE_PRINT_NUM("Signature Cert index = %d", certindex+1);                    
                                        
                        const CX509Certificate* cert = chainCertArray[certindex];
                        const CX509Certificate* signatureCert = 
                            chainCertArray[certindex+1];                    
                                            
                        // Compare issuer name to subject name.
                        if ( cert->IssuerName().ExactMatchL(
                             signatureCert->SubjectName() ) )
                            {  
                            BTIC_TRACE_PRINT("Issuer match found."); 
                            BTIC_TRACE_PRINT("Verify signature against next cert");                                               
                            // Validate certificate 
                            if ( ! cert->VerifySignatureL( 
                                signatureCert->PublicKey().KeyData() ) )
                                {                                                    
                                // Chain is broken. Validation failed. 
                                BTIC_TRACE_PRINT("ERROR Chain broken, validation failed"); 
                                chainOK = EFalse;
                                break;                       
                                } 
                            }
                         else
                            {
                            // Issuer do not match. Validation failed.
                            BTIC_TRACE_PRINT("ERROR Chain broken, issuer error"); 
                            chainOK = EFalse;
                            break;
                            }   
                        }
                    
                    if ( chainOK )
                        {
                        BTIC_TRACE_PRINT("Entry's chain valid"); 
                        retVal = ETrue;
                        }
                                   
                    }
                  // Chain has only one certificate, root.  
                  else
                    {
                    BTIC_TRACE_PRINT("Entry's chain has only one certificate"); 
                    retVal = ETrue;
                    }  
                    
                  }
              else
                {
                BTIC_TRACE_PRINT("No root found for this chain");
                retVal = EFalse; 
                }

            // Check that matching root certificate has same capablitiy 
            // as aCapability parameter.
            if ( aCapability && retVal )
                {            
                TCapabilitySet* rootCapaSet = aCertCapaArray[rootIndex];  
                
                retVal = rootCapaSet->HasCapability( GetCapability( aCapability ) );
                }
            
            // Reset array for next chain.                                                             
            chainCertArray.ResetAndDestroy();  
            }
        
        // If this is a valid certificate chain, break to loop.   
        if ( retVal )
            {                
            break;
            }           
        } // FOR LOOP

    CleanupStack::PopAndDestroy( &chainCertArray );
    CleanupStack::PopAndDestroy( &binaryCertChainArray );
                                            
    BTIC_TRACE_PRINT("[BOOT INTECRITY CHECK] SearchValidCertificate v2.1 <---");         
    
    return retVal;
    }


// -----------------------------------------------------------------------------
// GetCapability
// 
// This function converts 64 bit capability integer to Symbian capability 
// enumeration. 
//
// Returns: ECapabilityTCB if capabilty is TCB 
//          ECapabilityDRM if capabilty is DRM
//          ECapability_Denied if capability not found 
// -----------------------------------------------------------------------------
//  
LOCAL_C TCapability GetCapability( TUint64 aCapability )
    {            
    if ( aCapability == KBTIC_TCB )
        {        
        return ECapabilityTCB;
        }
        
    else if ( aCapability == KBTIC_DRM )    
        {        
        return ECapabilityDRM;
        }
        
    else
        {
        BTIC_TRACE_PRINT("! ! ERROR GetCapability -> ECapability_Denied ! !");
        return ECapability_Denied;
        }            
    }


// -----------------------------------------------------------------------------
// VerifyHashL
// 
// This function compare file's hash to hash found in SIS Register. 
//
// Returns: ETure if all compare operations was successful.  
//          EFalse other vice
// -----------------------------------------------------------------------------
//  
LOCAL_C TBool VerifyHashL(    
    RSisRegistryEntry& aEntry, 
    RPointerArray<HBufC>& aPathArray,
    RPointerArray<HBufC8>& aHashArray )
    {
    BTIC_TRACE_PRINT("[BOOT INTECRITY CHECK] VerifyHashL --->");
    __UHEAP_MARK;
           
    TBool retVal = EFalse; 
    TInt hashOk = 0;                        
    TInt count = aPathArray.Count();                    
    
    for ( TInt index = 0; index < count; index++ )
        {        
        // Take first file        
        HBufC* path = aPathArray[index];
        HBufC8* hash = aHashArray[index];
                                            
        if ( CompareToRegisteryHashL( 
            aEntry, 
            *path, 
            *hash ) )
            {
            hashOk++;                    
            }                                                               
        }
        
    // If all hashes are ok return ETrue.
    if ( hashOk == count )
        {
        BTIC_TRACE_PRINT("\nAll hashes are ok\n");
        retVal = ETrue;
        }
         
     __UHEAP_MARKEND;     
    BTIC_TRACE_PRINT("[BOOT INTECRITY CHECK] VerifyHashL <---");
    
    return retVal;
    }


// -----------------------------------------------------------------------------
// CompareToRegisteryHashL
// 
// Note this function returns EFalse is HashL function leaves.   
//
// Returns: ETure if hash is valid.
//          EFalse if hash was not valid.
// -----------------------------------------------------------------------------
// 
LOCAL_C TBool CompareToRegisteryHashL( 
    RSisRegistryEntry& aEntry, 
    TDesC& aEntryFile, 
    TDesC8& aHashBuffer )
    {    
    BTIC_TRACE_PRINT("[BOOT INTECRITY CHECK] CompareToRegisteryHashL --->");    
       
    TInt err = 0; 
    TBool hashOk = EFalse;    
    CHashContainer* hashContainer = NULL; 

    BTIC_TRACE_PRINT("Get hash for file: ");        
    BTIC_TRACE_PRINT_RAW( aEntryFile );     
    
    BTIC_TRACE_PRINT("RSisRegistryEntry.HashL()");                       
    // Get hashConteiner for given file. 
    TRAP( err, hashContainer = aEntry.HashL( aEntryFile ) ); 
                
    if ( err == KErrNone && hashContainer )    
        {                            
        CleanupStack::PushL( hashContainer );
        
        // Get hash data from hashConteiner.                                                                                                                                       
        TBufC8<KBTICHashSize> hashFromReg( hashContainer->Data() );
                                                
        if ( hashFromReg.Compare( aHashBuffer ) == 0 )
            {
            hashOk = ETrue;
            
            BTIC_TRACE_PRINT("Hash ok"); 
            }
                                               
        CleanupStack::PopAndDestroy(); //hashContainer       
        }
    else
        {
        // If HashL function leaves, return false.          
        hashOk = EFalse;
        BTIC_TRACE_PRINT_NUM("ERROR RSisRegistryEntry HashL = %d", err ); 
        }    
              
    BTIC_TRACE_PRINT("[BOOT INTECRITY CHECK] CompareToRegisteryHashL <---");         
           
    return hashOk;
    }
    
    
// -----------------------------------------------------------------------------
// CheckSerialNumberL
//
// This function opens IMEI file and checks that device's serial number is found 
// in the file.
//
// Returns: ETure if serial number is found or some error with server. 
//          EFalse if serial number not found
// -----------------------------------------------------------------------------
//     
LOCAL_C TBool CheckSerialNumberL( RFs& aFs, const TDesC& aFileName )
    {
    BTIC_TRACE_PRINT("[BOOT INTECRITY CHECK] CheckSerialNumberL --->");
    __UHEAP_MARK;      
    
    TBool matchFound = EFalse;        
           
    RInfoServerClient server;
              
    // Connect to server.    
    TInt err = server.Connect();
    
    BTIC_TRACE_PRINT_NUM("Server connect error = %d", err );
    
    if ( err == KErrNone )
        {            
        CleanupClosePushL( server );
        
        TBuf<RMobilePhone::KPhoneSerialNumberSize> deviceSerialNumber;
                            
        // Get device serial number from server.
        err = server.GetSerialNumber( deviceSerialNumber );          
        
        RFile file;  
            
        if ( err == KErrNone )
            {                        
            // Open text file.
            User::LeaveIfError( file.Open( aFs, aFileName, EFileRead ) );         
            CleanupClosePushL( file );
          
            TInt size; 
            file.Size( size );
          
            HBufC8* content = HBufC8::NewLC( size );      
            TPtr8 ptr(content->Des());

            // Read content
            User::LeaveIfError( file.Read( ptr, size ) );                                
            
            TLex8 input( ptr );
            TBool lineEnd( EFalse );
            TChar ch;

            TBuf<RMobilePhone::KPhoneSerialNumberSize> serialNumber;                
            
            while ( ! input.Eos() )
                {                         
                ch = input.Get();
                                                          
                if ( ( ch != '\n' ) && ( ch != '\r' ) )
                    {
                    // Check that we have space for next number. 
                    if ( serialNumber.Size() < serialNumber.MaxSize() )
                        {
                        serialNumber.Append( ch ); 
                        } 
                    else
                        {
                        // Buffer size is 50 and it should be enoug, if not 
                        // then something is wrong. Let's break to loop and
                        // return false.      
                        break;
                        }                                        
                   }                                  
                else
                   {
                   lineEnd = ETrue;
                   }

                if ( ( lineEnd ) || ( input.Eos() ) )
                   {                   
                   if ( deviceSerialNumber == serialNumber )
                        {
                        BTIC_TRACE_PRINT("Correct serial number found");
                        matchFound = ETrue;
                        break;
                        }                              
                   
                   serialNumber.FillZ(0);
                   serialNumber.SetLength(0);
                   lineEnd = EFalse;
                   }               
                }                
            CleanupStack::PopAndDestroy( 2 ); //file, content                   
            }                       
        CleanupStack::PopAndDestroy(); //client                                                           
        }  
                
    __UHEAP_MARKEND;                                  
    BTIC_TRACE_PRINT("[BOOT INTECRITY CHECK] CheckSerialNumberL <---");
                         
    return matchFound;     
    }
 
           
// -----------------------------------------------------------------------------
// CorruptFileL
//
// This function corrupts certificate file so that certs can not be read.
// -----------------------------------------------------------------------------
//
LOCAL_C void CorruptFileL( RFs& aFs, const TDesC& aFileName )
    {
    BTIC_TRACE_PRINT("[BOOT INTECRITY CHECK] ! ! CORRUPT STORE FILE ! !");           
              
    TFindFile find( aFs );
    
    TUint8 byteVector[8] = { 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF };    
    
    // Find given file in C drive.
    if ( find.FindByDir( aFileName, KBTICDriveC ) == KErrNone )
        {             
        RFile file;
        TInt err;
                     
        for ( TInt loop = 0; loop < KBTICTryToOpen; loop++ )
            {
            err = file.Open( aFs, aFileName, EFileRead | EFileWrite );
            BTIC_TRACE_PRINT_NUM("File Open error = %d", err );            
            
            // If file is open or it has ReadOnly attribute wait and try again. 
            if ( err )
                {
                BTIC_TRACE_PRINT_NUM("Wait 0.5 sec. Attempt nr.%d", loop );
                User::After( 500000 );
                
                TInt seterr = aFs.SetAtt( aFileName, 0, KEntryAttReadOnly );
                BTIC_TRACE_PRINT_NUM("Remove Read Only attrib. = %d", seterr );                    
                }
            else
                {
                break;
                }    
            }
            
        // Leave if error.
        User::LeaveIfError( err );          
        
        CleanupClosePushL( file );
           
        TInt size = 0;
        file.Size( size );

        HBufC8* fileData = HBufC8::NewLC( size );
        TPtr8 dataPtr = fileData->Des();                        

        HBufC8* newFileData = HBufC8::NewLC( size + sizeof( byteVector ) );
        TPtr8 newDataPtr = newFileData->Des();

        file.Read( dataPtr ); 
        // Copy corrupted bytes to buffer.
        newDataPtr.Copy( &byteVector[0], sizeof( byteVector ) ); 
        // Copy original file data to buffer.
        newDataPtr.Append( dataPtr );            
        // Write data at start of file.  
        file.Write( 0, *newFileData ); 

        file.Flush();  

        CleanupStack::PopAndDestroy( 3 ); 
        
        BTIC_TRACE_PRINT("File corrupted" );        
        }                        
    }


// -----------------------------------------------------------------------------
// CheckCapabilityWordAndCalcHashL
//
// This function reads capability word from file heder and compares that to given
// capability (aCapaVector). If there is more then one whanted capability the 
// first match is selected. If match is found file path is added to aFilesArray
// and hash is calculated over the binary and found capa is added to array. 
// If aCheckCapa is set as EFalse, capability word is not checked and all files 
// from aSourceArray is added to aFilesArray.
// Note aCapaArray conteins only matched capability. Not all file's capabilities.
//
// Returns: ETure if successful  
//          EFalse othervice
// -----------------------------------------------------------------------------
//        
LOCAL_C TBool CheckCapabilityWordAndCalcHashL( 
    RFs& aFs,                           // File server handle
    TBool aCheckCapa,                   // Enables capability check.
    TUint64* aCapaVector,               // Vector con. capa. that are checked.
    RPointerArray<HBufC>& aSourceArray, // Files to be checked.
    RPointerArray<HBufC>& aFilesArray,  // Passed files
    RPointerArray<HBufC8>& aHashArray,  // File's hash
    RArray<TUint64>& aCapaArray )       // File's capability.
    {
    BTIC_TRACE_PRINT("[BOOT INTECRITY CHECK] CheckCapaWordAndCalcHashL v3.1 ->");
       
    TFindFile find( aFs );    
    
    TInt pathCount = aSourceArray.Count();    
    
    TBool retVal = EFalse;     
    TInt index;
    TInt err;    
    
    CSHA1* sha = CSHA1::NewL();
    CleanupStack::PushL( sha );
    
    RFile file; 
    
    for ( index = 0; index < pathCount; index++ )
        {
        BTIC_TRACE_PRINT_NUM("File array index = %d", index );
        
        HBufC* path = aSourceArray[index]; 
        
        BTIC_TRACE_PRINT("File path: ");
        BTIC_TRACE_PRINT_RAW( *path );        
                                                            
        err = file.Open( aFs, *path, EFileShareReadersOnly );              
      
        if ( err == KErrNone )
            {                               
            CleanupClosePushL( file );                

            TInt size = 0; 
            file.Size( size );                                                               

            // Alloc buffer for file.
            HBufC8* buffer = HBufC8::NewLC( size );

            if ( buffer )
                {
                TPtr8 bufferPtr = buffer->Des();                            

                // Read file binary to buffer.          
                err = file.Read( bufferPtr );               
                                 
                if ( err == KErrNone || buffer->Length() != 0 )
                    { 
                    TUint64 capa = 0;
                    TBool capabilityOk = EFalse;   
                     
                    // Check capability if needed.                    
                    if ( aCheckCapa )
                        {
                        // Get pointer to heap buffer.
                        const TUint8* ptr = buffer->Ptr();   
                                                     
                        // Capapility word (64bit) is found in 0x88 bytes after 
                        // file heder offset. 0x88 = 136 bytes/8=17 words@64.                                                     
                        TUint64 word = ((TUint64*)ptr)[KBTICCabaWordOffset]; 
                                                                            
                        for ( TInt iCapa = 0; iCapa < KBTICCapaCount; iCapa++ ) 
                            {
                            BTIC_TRACE_PRINT_NUM("Capa index = %d", iCapa );
                            
                            capa = aCapaVector[iCapa];
                            
                            if ( (word & capa) == capa )
                                {  
                                BTIC_TRACE_PRINT("Capability match found");                      
                                capabilityOk = ETrue;
                                break;
                                }                                     
                            }                                                              
                        }
                        
                    // If capa check is not needed calculate hash over the file. 
                    // Capability is set as zero.   
                    else
                        {
                        BTIC_TRACE_PRINT("Capability NOT REGUIRED");
                        capabilityOk = ETrue;    
                        }
                                           
                    if ( capabilityOk )
                        {              
                        BTIC_TRACE_PRINT("Append file information to array"); 
                        
                        // Add found capability to array
                        User::LeaveIfError( aCapaArray.Append( capa ) );                    
                                                                         
                        // Append pointer to files path.
                        User::LeaveIfError( aFilesArray.Append( path ) ); 
                                               
                        HBufC8* hash = HBufC8::NewLC( KBTICHashSize );                        
                        TPtr8 hashPtr = hash->Des();
                                                                                
                        sha->Reset();                        
                                                
                        // Calucalte hash over file's binary.
                        hashPtr.Copy( sha->Hash( bufferPtr ) );
                        
                        // Check that digest has correct length.
                        if ( hash->Length() != KBTICHashSize )
                            {
                            BTIC_TRACE_PRINT("\nERROR HASH SIZE"); 
                            User::Leave( KErrGeneral );
                            }                                                        
                        
                        // Add file's hash to array
                        User::LeaveIfError( aHashArray.Append( hash ) );                                                  
                        
                        CleanupStack::Pop(); // hash; 
                        
                        retVal = ETrue;                          
                        }
                    }
                else
                    {
                    BTIC_TRACE_PRINT_NUM("\nERROR File read = %d", err );            
                    User::Leave( KErrGeneral );  
                    }                                                   
                }
            else
                {
                BTIC_TRACE_PRINT("\nERROR HBufC8 buffer alloc failed");              
                User::Leave( KErrGeneral );  
                }      
                                                                                
            CleanupStack::PopAndDestroy( 2 ); // file,  fileBuffer         
            }
        else
            {
            BTIC_TRACE_PRINT_NUM("\nERROR File open = %d", err );              
            User::Leave( KErrGeneral );  
            }                                    
        } 
            
    CleanupStack::PopAndDestroy(); // sha                 
                    
    BTIC_TRACE_PRINT("[BOOT INTECRITY CHECK] CheckCapaWordAndCalcHashL v3 <---");     
    
    return retVal;            
    }    

/*
#ifdef __BTIC_BINARIES_CHECK_ENABLED


// -----------------------------------------------------------------------------
// RenameFileL
//
// This function renames given file by replacing existing file extension to .bak
// -----------------------------------------------------------------------------
//    
LOCAL_C void RenameFileL( RFs& aFs, const TDesC& aFileName )
    { 
    BTIC_TRACE_PRINT("[BOOT INTECRITY CHECK] ! ! ! RenameFileL --->");
       
    _LIT( KBTICFileExtensionBak,".bak" );
              
    TFindFile find( aFs );
      
    // Find given file in C drive.
    if ( find.FindByDir( aFileName, KBTICSysPathC ) == KErrNone )
        {          
        TInt length = aFileName.Length();
        HBufC* newName = HBufC::NewLC( length + sizeof( KBTICFileExtensionBak ) );
        TPtr newNamePtr = newName->Des();                        
        
        newNamePtr.Copy( aFileName ); 
        // Add ".bak" extension to file name.
        newNamePtr.Append( KBTICFileExtensionBak );                              
        
        // Rename file.
        TInt err = aFs.Rename( aFileName, *newName );
        
        // If error try ones more. 
        if ( err != KErrNone )
            {
            aFs.Rename( aFileName, *newName );
            }
        }

    BTIC_TRACE_PRINT("[BOOT INTECRITY CHECK] ! ! ! RenameFileL <---");        
    }
    

// -----------------------------------------------------------------------------
// UniteCertArraysL
//
// Function append source array's pointers to target array. 
// -----------------------------------------------------------------------------
//
LOCAL_C void UniteCertArraysL(     
    RPointerArray<CX509Certificate>& aTargetCertArray,
    RPointerArray<CX509Certificate>& aSourceCertArray )
    {
    BTIC_TRACE_PRINT("[BOOT INTECRITY CHECK] UniteCertArraysL --->");    
        
    TInt count = aSourceCertArray.Count();
        
    if ( count > 0 )
        {
        for ( TInt index = 0; index < count; index++ )
            {
            CX509Certificate* x509Cert = aSourceCertArray[index];
            // Note if append fails -> some binaries will be corrupted.          
            aTargetCertArray.Append( x509Cert );                        
            }                
        }
            
    BTIC_TRACE_PRINT("[BOOT INTECRITY CHECK] UniteCertArraysL <---");            
    }


// -----------------------------------------------------------------------------
// UniteCapaArraysL
//
// Function append source array's pointers to target array. 
// -----------------------------------------------------------------------------
//
LOCAL_C void UniteCapaArraysL( 
    RPointerArray<TCapabilitySet>& aTargetCapaArray,
    RPointerArray<TCapabilitySet>& aSourceCapaArray )
    {
    BTIC_TRACE_PRINT("[BOOT INTECRITY CHECK] UniteCapaArraysL --->");    
   
    TInt count = aSourceCapaArray.Count();            
        
    if ( count > 0 )
        {
        for ( TInt index = 0; index < count; index++ )
            {
            TCapabilitySet* capaSet = aSourceCapaArray[index];
            // Note if append fails -> some binaries will be corrupted.           
            aTargetCapaArray.Append( capaSet );                        
            }                
        }       
        
    BTIC_TRACE_PRINT("[BOOT INTECRITY CHECK] UniteCapaArraysL <---");    
    }


// -----------------------------------------------------------------------------
// CheckBinariesL
//
// This function checks all exe or dll binarys conteining TCB and DRM capability 
// in C:\sys\bin directory. It calculates hash over the binary and compares that 
// to one found in SIS Registery. It check also that SIS pacage's certificate 
// has rigth to grant TCB or DRM capabiltity.
// If some file in C:\sys\bin directory is not found in SIS Registery it is 
// renamed.
// 
// -----------------------------------------------------------------------------
//
LOCAL_C void CheckBinariesL( 
    RFs& aFs, 
    RPointerArray<CX509Certificate>& aX509CertArray,
    RPointerArray<TCapabilitySet>& aCertCapaArray )    
    {
    BTIC_TRACE_PRINT("[BOOT INTECRITY CHECK] CheckBinariesL --->");
    __UHEAP_MARK;          
    
    TInt pushToStack = 0;
    TInt err = 0;            
    
    RPointerArray<HBufC> allFilesArray;
    
    // Find all exe files from c:\sys\bin.
    FindFilesL( aFs, KBTICSysPathC, KBTICExtensionExe, allFilesArray );    
    // Find all dll files from c:\sys\bin.
    FindFilesL( aFs, KBTICSysPathC, KBTICExtensionDll, allFilesArray );
     
    TInt count = allFilesArray.Count();
    
    if ( count > 0 )
        {            
        RPointerArray<HBufC> filesArray;
        RPointerArray<HBufC8> hashArray; 
        RArray<TUint64> capaArray;  
                
        TBool foundFiles = EFalse;

        // Copy whanted capabilities to array.                   
        TUint64* capaVector = new( ELeave ) TUint64[KBTICCapaCount];
        CleanupArrayDeletePushL( capaVector );
        capaVector[0] = KBTIC_TCB;
        capaVector[1] = KBTIC_DRM;
        
        // Find files conteining whanted capability and calculate hash over file.  
        
        // NOTE NOTE currently this function addends only one capability to 
        // capaArray. This must be changed if all capabilities should be 
        // checked from certificate.        
                         
        foundFiles = CheckCapabilityWordAndCalcHashL( 
            aFs,
            ETrue, 
            capaVector,                        
            allFilesArray, 
            filesArray, 
            hashArray,
            capaArray );                             
                                                 
        CleanupStack::PopAndDestroy();  //capaVector 
                    
        if ( foundFiles && err == KErrNone )
            {
            // Find match for fileArray's files from SIS registery
            // Check that file's (binary) hash matches to SIS registery's hash 
            // Check that SIS registery cert. is valid and has file's capability.              
            FindMatchFromSisPackageL( 
                aFs,                 
                filesArray, 
                hashArray,
                capaArray, 
                aX509CertArray,
                aCertCapaArray );                           
                            
            count = filesArray.Count();
            
            BTIC_TRACE_PRINT_NUM("Files array count = %d (should be 0 )", count );
            
            // Rename all files which was not found in sis registery.
            if ( count )  
                {                               
                for ( TInt index = 0; index < count; index++ )
                    {
                    HBufC* filePath = filesArray[index];
                                        
                    RenameFileL( aFs, *filePath );                                                                 
                    }
                }                
            }    
                                           
        filesArray.Reset(); // Reset only. allFilesArray owns heap memory.                               
        hashArray.ResetAndDestroy();                                       
        }
    
    allFilesArray.ResetAndDestroy(); 
               
    CleanupStack::PopAndDestroy( pushToStack );  //searchPath    
       
    BTIC_TRACE_PRINT("UHEAP MARK END");  
    __UHEAP_MARKEND;    
    BTIC_TRACE_PRINT("[BOOT INTECRITY CHECK] CheckBinariesL <---");  
    }


// -----------------------------------------------------------------------------
// FindFilesL
//
// This function searches one or more files that conteins given string in file 
// name. File names are added to array with complete path.  
// -----------------------------------------------------------------------------
//       
LOCAL_C void FindFilesL( 
    RFs& aFs,                               // File server handle.
    const TDesC& aPath,                     // Search directory and drive.
    const TDesC& aSearchString,             // String to be found in file name.
    RPointerArray<HBufC>& aFoundFilesArray )// Result files.
    {  
    BTIC_TRACE_PRINT("[BOOT INTECRITY CHECK] FindFilesL --->"); 
     
    TInt err = 0;
    TFindFile find( aFs ); 
    CDir* dirList = NULL;
    HBufC* path;
          
    TFileName searchExtension;
    searchExtension.Copy( aSearchString );
    
    // Find files from searchPath directory. Note that dirlist
    // contains only file name not path to it.                  
    err = find.FindWildByPath( searchExtension, &aPath, dirList );
                    
    TInt pathLength = aPath.Length(); 
    
    if ( err == KErrNone && dirList )
        {
        CleanupStack::PushL( dirList );
        
        // Get the count of find files.
        TInt count = dirList->Count();
        
        BTIC_TRACE_PRINT_NUM("Dir list count = %d", count ); 
                                   
        for ( TInt index = 0; index < count; index++ )
            {                                    
            path = HBufC::NewLC( pathLength + (*dirList)[index].iName.Length() );              
            TPtr ptrPath = path->Des();
            
            // Copy system path to buffer.
            ptrPath.Copy( KBTICSysPathC );
            // Append files name to path buffer.
            ptrPath.Append( (*dirList)[index].iName ); 
            
            ptrPath.LowerCase();                                   
            
            aFoundFilesArray.Append( path );
            
            CleanupStack::Pop(); //path
            }
            
        CleanupStack::Pop(); //dirList 
        delete dirList;  
        }
                       
    BTIC_TRACE_PRINT("[BOOT INTECRITY CHECK] FindFilesL <---");                 
    }



// -----------------------------------------------------------------------------  
// FindMatchFromSisPackageL
//
// This function search given files from SIS Registery. Function removes file 
// from aFilesArray alway when it is found in Registery. If aFilesArray contains 
// files after function return those files are not found in SIS Registery.
// 
// Returns: ETure if successful  
//          EFalse othervice
// -----------------------------------------------------------------------------
//  
LOCAL_C TBool FindMatchFromSisPackageL( 
    RFs& aFs,                           // File server handle
    RPointerArray<HBufC>& aFilesArray,  // Files to be checked
    RPointerArray<HBufC8>& aHashArray,  // File's hash
    RArray<TUint64>& aCapaArray,        // File's capability
    RPointerArray<CX509Certificate>& aX509CertArray, // Cert array
    RPointerArray<TCapabilitySet>& aCertCapaArray )  // Cert's capability
    {
    BTIC_TRACE_PRINT("[BOOT INTECRITY CHECK] FindMatchFromSisPackageL --->");
    __UHEAP_MARK; 
    
    TInt err = KErrNone;        
    TBool allOK = EFalse; 
               
    Swi::RSisRegistrySession sisRegSession;  
            
    err = sisRegSession.Connect();
    
    if ( err == KErrNone )
        {
        CleanupClosePushL( sisRegSession );
        
        RPointerArray<CSisRegistryPackage> sisPackages;
                       
        // Find installed packages.
        sisRegSession.InstalledPackagesL( sisPackages );                
                      
        TBool entryOpen = EFalse;    
        TInt entryFilesCount = 0;
        TInt fileCount = 0;        
        Swi::RSisRegistryEntry entry; 
        // Array for entrys files. This owns heap memory.                       
        RPointerArray<HBufC> installedFiles; 
        // Array for dll and exe files found in sis registery.
        RPointerArray<HBufC> entryFiles;
        // Array for wild card string to be search from file list.
        RPointerArray<HBufC> stringArray;
        HBufC* string;
        
        // Add wild card strings to array.                    
        string = KBTICExtensionExe().AllocLC();
        User::LeaveIfError( stringArray.Append( string ) );
        CleanupStack::Pop();
        
        string = KBTICExtensionDll().AllocLC();
        User::LeaveIfError( stringArray.Append( string ) );
        CleanupStack::Pop();                     
                
        // Open sis registery entry and search paths to installed exes and dlls.
        for( TInt index = 0; index < sisPackages.Count(); index++)
            {  
            BTIC_TRACE_PRINT_NUM("entry loop Index = %d", index );

            // If error happens make leave. If some pacage is left out we can 
            // not continue, because all files found in C must be found also 
            // in sis registery.                                           
            User::LeaveIfError( 
                entry.OpenL( sisRegSession, *sisPackages[index] ) );                         
                                                 
            CleanupClosePushL( entry );
            entryOpen = ETrue; 
            
            // Get this entrys installed files.                                                                          
            entry.FilesL( installedFiles );                                          
                        
            if ( installedFiles.Count() > 0 )
                {                     
                // Search match for string array conten from entrys files.
                // Note that heap memory is owned by installeFiles array.
                SearchFilesFromArrayL( 
                    installedFiles, 
                    KBTICSysPathCWildcard,
                    stringArray, 
                    entryFiles );                                                                                             
                }                                                                                                                                                                              
                                                                            
            entryFilesCount = entryFiles.Count();
            
            BTIC_TRACE_PRINT_NUM("Entry files count = %d", entryFilesCount );
                    
            if ( entryFilesCount > 0 )
                {
                TBool pagaceCertValid = EFalse;                                
                
                // Go torug all file paths from entryFiles aray.
                for ( TInt indexB = 0; indexB < entryFilesCount; indexB++ )
                    {
                    BTIC_TRACE_PRINT_NUM("file path loop IndexB = %d", indexB );
                    
                    // Get file's path from sis pagace entry.
                    HBufC* entryFile = entryFiles[indexB];                                         
                    
                    fileCount = aFilesArray.Count();
                                                                     
                    // Compare registery file path to files found in C:\sys\bin.            
                    for ( TInt indexC = fileCount - 1; indexC >= 0; indexC-- )
                        {                                                
                        // Get file's path from array conteining dlls and exes.
                        HBufC* file = aFilesArray[indexC];                                                                                                
                        
                        TInt result = entryFile->CompareC( *file );
                                               
                        BTIC_TRACE_PRINT_NUM("\nCompare result = %d", result );                        
                        
                        // If result is zero match is found.
                        if ( result == 0 )                        
                            {
                            BTIC_TRACE_PRINT("File path Match found" ); 
                            
                            // Get file's hash
                            HBufC8* hash = aHashArray[indexC];                                                                                                                                                                       
                                                    
                            BTIC_TRACE_PRINT("CompareToRegisteryHashL -->" );                            
                           
                            TBool hashOk = CompareToRegisteryHashL( 
                                entry, 
                                *entryFile, 
                                *hash );
                                
                            BTIC_TRACE_PRINT("CompareToRegisteryHashL <--" );     
                            
                                                      
                            if ( hashOk )
                                {
                                BTIC_TRACE_PRINT("HASH OK");
                                
                                // Check if entry cert is already valid.
                                if ( ! pagaceCertValid )
                                    {                                          
                                    BTIC_TRACE_PRINT("Validate pagace cert");
                                     
                                    // Validate entry's certificate and 
                                    // check that certificate has correct 
                                    // capablities.                                                                                                                  
                                    TBool certOk = SearchValidCertificateL( 
                                        entry, 
                                        aX509CertArray,                                             
                                        aCertCapaArray,
                                        aCapaArray[indexC] );
                                    
                                    if ( certOk )
                                        {
                                        BTIC_TRACE_PRINT("Pagace CERT VALID - OK");
                                        
                                        // Validate pagace cert. only once.
                                        pagaceCertValid = ETrue;
                                        }
                                    else
                                        {
                                        // Rename file if cert is not ok.
                                        
                                        RenameFileL( aFs, *entryFile );                                            
                                        // Should we rename all files in this
                                        // entry or only this one.
                                        }                                            
                                    }                                                                   
                                } 
                            else
                                {
                                BTIC_TRACE_PRINT("HASH Error -> Rename file");
                                // If hash is false rename file.
                                RenameFileL( aFs, *entryFile );
                                }      
                                                                                                                                                                                                                     
                            // Set arrays entry to zero so we will not 
                            // compear it twice. We do not have to delete 
                            // entry because aFilesArray do not own heap 
                            // memory.                                
                            aFilesArray.Remove( indexC );
                            
                            //Remove also hash and capa entry from array.
                            HBufC8* hashBuffer = aHashArray[indexC];
                            delete hashBuffer;
                            aHashArray.Remove( indexC);
                            
                            aCapaArray.Remove( indexC );                                                        
                                                                                                                                                         
                            break;                  
                            }                                                                                                         
                        }
                    }
                } 
                
            if ( entryOpen )
                {    
                BTIC_TRACE_PRINT("Clear ENTRY and installedFiles array");
                    
                CleanupStack::PopAndDestroy(); //entry                   
                entryFiles.Reset(); //Reset only.
                installedFiles.ResetAndDestroy();               
                }
                
           // Break entry loop if all files are removed.     
           if ( aFilesArray.Count() == 0 )
                {
                BTIC_TRACE_PRINT("NO MORE EXE/DLL FILES -> BREAK LOOP");
                break;
                }                                                                                                                   
            }                       
        
        stringArray.ResetAndDestroy();
        CleanupStack::PopAndDestroy(); // sisRegSession 
        
        allOK = ETrue;    
        }
     
     
    BTIC_TRACE_PRINT("UHEAP MARK END");  
    __UHEAP_MARKEND;          
    BTIC_TRACE_PRINT("[BOOT INTECRITY CHECK] FindMatchFromSisPackageL <---"); 
    
    return allOK;
    }


#endif //__BTIC_BINARIES_CHECK_ENABLED
*/
      
// =========================== CRootCertificateEntry ===========================

// -----------------------------------------------------------------------------
// NewLC()
// 
// -----------------------------------------------------------------------------
//
CRootCertificateEntry* CRootCertificateEntry::NewLC( RReadStream& aStream )
    {
    CRootCertificateEntry* self = new(ELeave) CRootCertificateEntry();
    CleanupStack::PushL(self);

    self->InternalizeL( aStream );

    return self;
    }


// -----------------------------------------------------------------------------
// CRootCertificateEntry()
// 
// -----------------------------------------------------------------------------
//
CRootCertificateEntry::CRootCertificateEntry()
    { 
    }


// -----------------------------------------------------------------------------
// ~CRootCertificateEntry()
// 
// -----------------------------------------------------------------------------
//
CRootCertificateEntry::~CRootCertificateEntry()
    {
    iApplications.Close();    
    }


// -----------------------------------------------------------------------------
// InternalizeL()
// 
// -----------------------------------------------------------------------------
//
void CRootCertificateEntry::InternalizeL( RReadStream& aStream )
    {
    BTIC_TRACE_PRINT("[BOOT INTECRITY CHECK] InternalizeL");

    iX509CertificateType = aStream.ReadUint8L();

    iSize = aStream.ReadInt32L();

    aStream >> iLabel;

    iCertId = aStream.ReadInt32L();

    iCACertificateType = aStream.ReadUint8L();

    aStream >> iSubjectKeyId;

    aStream >> iIssuerKeyId; 

    TInt count = aStream.ReadInt32L();

    for ( TInt i = 0 ; i < count ; ++i )
        {
        TUid id;
        aStream >> id;
        User::LeaveIfError( iApplications.Append( id ) );
        }

    iTrusted = !!aStream.ReadUint8L();  // converts TUint8 to TBool

    aStream >> iDataStreamId;

    TPckg<TCapabilitySet> capsPckg( iCapabilities );  
    aStream >> capsPckg;  

    iMandatory = !!aStream.ReadUint8L();    
    }

     
// -----------------------------------------------------------------------------
// DataStreamId()
// 
// -----------------------------------------------------------------------------
//
TStreamId CRootCertificateEntry::DataStreamId() const
    {
    return iDataStreamId;
    }


// -----------------------------------------------------------------------------
// Capabilities()
// 
// -----------------------------------------------------------------------------
//
const TCapabilitySet& CRootCertificateEntry::Capabilities() const
    {
    return iCapabilities;
    }

// -----------------------------------------------------------------------------
// Size()
// 
// -----------------------------------------------------------------------------
//
TInt CRootCertificateEntry::Size() const
    {
    return iSize;
    }

  
// -----------------------------------------------------------------------------
// CertID()
// 
// -----------------------------------------------------------------------------
//
TInt CRootCertificateEntry::CertID() const
    {
    return iCertId;
    }



// =========================== CActiveFileObserver ============================

// -----------------------------------------------------------------------------
// CActiveFileObserver::CActiveFileObserver()
// -----------------------------------------------------------------------------
//
CActiveFileObserver::CActiveFileObserver( RFs&  aFs, TInt& aResult) 
    : CActive( EPriorityNormal ),
    iFs( aFs ), 
    iResult( aResult )    
    {
    }


// -----------------------------------------------------------------------------
// CActiveFileObserver::~CActiveFileObserver()
// Destructor
// -----------------------------------------------------------------------------
//
CActiveFileObserver::~CActiveFileObserver()
    {  
    BTIC_TRACE_PRINT("[BOOT INTECRITY CHECK] ~CActiveFileObserver");   
    // Cancel the outstanding request. This calls DoCancel().
    Cancel();  
    // Close timer.    
    iRTimer.Close();
    
    if ( iPath )
        {
        delete iPath;
        iPath = NULL;
        }        
    }


// -----------------------------------------------------------------------------
// CActiveFileObserver* CActiveFileObserver::NewL()
// Factory method.
// -----------------------------------------------------------------------------
//
CActiveFileObserver* CActiveFileObserver::NewL( 
    RFs&  aFs,
    const TDesC& aPath,      
    TInt& aResult )
    {
    CActiveFileObserver* observer = 
        new(ELeave) CActiveFileObserver( aFs, aResult );
        
    CleanupStack::PushL( observer );

    observer->ConstructL( aPath );

    CleanupStack::Pop();

    return observer;
    }


// -----------------------------------------------------------------------------
// CActiveFileObserver::ConstructL()
// Second-phase constructor.
// -----------------------------------------------------------------------------
//
void CActiveFileObserver::ConstructL( const TDesC& aPath )
    {
    BTIC_TRACE_PRINT("[BOOT INTECRITY CHECK] CActiveFileObserver::ConstructL"); 
    
    iRunCount = 0;
       
    iPath = HBufC::NewL( aPath.Length() );
    TPtr iPathPtr = iPath->Des();
    iPathPtr.Copy( aPath );
    
    iRTimer.CreateLocal();
    
    // Add to scheduler.    
    CActiveScheduler::Add( this );
    
    // Issue first timer request.
    IssueRequest();
    }


// -----------------------------------------------------------------------------
// CActiveFileObserver::DoCancel()
// Cancel function for active object.
// -----------------------------------------------------------------------------
//
void CActiveFileObserver::DoCancel()
    {
    BTIC_TRACE_PRINT("[BOOT INTECRITY CHECK] CActiveFileObserver::DoCancel"); 
    // Cancel outstanding request.    
    iRTimer.Cancel();
    }


// -----------------------------------------------------------------------------
// CActiveFileObserver::RunError()
// Handles a leave occurring in the request completion event handler RunL.
// -----------------------------------------------------------------------------
//
TInt CActiveFileObserver::RunError( TInt aError )
    { 
    BTIC_TRACE_PRINT("[BOOT INTECRITY CHECK] CActiveFileObserver::RunError"); 
    iResult = aError;             
    BTIC_TRACE_PRINT_NUM("[BOOT INTE.] RunError: err = %d", aError );
    return aError;
    }


// -----------------------------------------------------------------------------
// CActiveFileObserver::IssueRequest()
// This function issues new 
// -----------------------------------------------------------------------------
void CActiveFileObserver::IssueRequest()
    {     
    BTIC_TRACE_PRINT("[BOOT INTECRITY CHECK] CActiveFileObserver::IssueRequest");            
    //iFs.NotifyChange( ENotifyEntry, iStatus, *iPath );
    iRunCount++;

    iRTimer.After( iStatus, KBTICObserverTime );
       
    // Wait request to complete.
    SetActive();
    }


// -----------------------------------------------------------------------------
// CActiveFileObserver::RunL()
// This function handles active object’s request completion event
// -----------------------------------------------------------------------------
//
void CActiveFileObserver::RunL()
    {
    BTIC_TRACE_PRINT("[BOOT INTECRITY CHECK] CActiveFileObserver::RunL"); 
                                      
    TInt err = KErrNone; 
    RFile file;
    // Try to open the file.
    err = file.Open( iFs, *iPath, EFileShareReadersOrWriters | EFileRead );               
    
    BTIC_TRACE_PRINT_NUM("[BOOT INTE.] RunL: file open err = %d", err );
    
    if ( err == KErrNone )
        {
        // Close the file.
        file.Close();
        
        if ( iRunCount < KBTICRunCount )        
            {
            // Make new request.
            IssueRequest();      
            }
        else
            {
            BTIC_TRACE_PRINT("[BOOT INTE.] RunL: File not deleted -> CANCEL"); 
            // File is not deleted. Stop active observer 
            // and continue data base checking.
            iResult = KErrCancel;
            Deque();
            CActiveScheduler::Stop();             
            }    
        }        
    else if ( err == KErrNotFound || err == KErrPathNotFound )
        {
        // Ok file is deleted. Stop active observer and return.
        BTIC_TRACE_PRINT("[BOOT INTE.] RunL: File deleted -> OK");         
        iResult = KErrNone;   
        Deque();
        CActiveScheduler::Stop();       
        } 
    else
        {
        // Some other file open error etc. KErrInUse. Let's continue.
                         
        if ( iRunCount < KBTICRunCount )        
            {
            // Make new request.
            IssueRequest();      
            }
        else
            {
            BTIC_TRACE_PRINT("[BOOT INTE.] RunL: File not deleted -> CANCEL"); 
            // File is not deleted. Stop active observer 
            // and continue data base checking.
            iResult = KErrCancel;
            Deque();
            CActiveScheduler::Stop();             
            }            
        }                                               
    }

//EOF