diff -r 000000000000 -r ba25891c3a9e installationservices/swi/source/sisfile/siscontroller.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/installationservices/swi/source/sisfile/siscontroller.cpp Thu Dec 17 08:51:10 2009 +0200 @@ -0,0 +1,305 @@ +/* +* Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of the License "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: +* Definition of the Swi::Sis::CController +* +*/ + + +/** + @file siscontroller.cpp +*/ + +#include "siscontroller.h" +#include "sisinfo.h" +#include "sissupportedlanguages.h" +#include "sissupportedoptions.h" +#include "sisproperties.h" +#include "sislogo.h" +#include "sisinstallblock.h" +#include "sisproperties.h" +#include "sisprerequisites.h" +#include "swi/sistruststatus.h" +#include "certchainconstraints.h" +#include "sisptrprovider.h" +#include "log.h" + +using namespace Swi::Sis; + + +EXPORT_C /*static*/ CController* CController::NewLC(MSisDataProvider& aDataProvider, TInt64& aBytesRead, TReadTypeBehaviour aTypeReadBehaviour) + { + CController* self = new(ELeave) CController(); + CleanupStack::PushL(self); + self->ConstructL(aDataProvider, aBytesRead, aTypeReadBehaviour); + return self; + } + +EXPORT_C /*static*/ CController* CController::NewL(MSisDataProvider& aDataProvider, TInt64& aBytesRead, TReadTypeBehaviour aTypeReadBehaviour) + { + CController* self = NewLC(aDataProvider, aBytesRead, aTypeReadBehaviour); + CleanupStack::Pop(self); + return self; + } + +EXPORT_C /*static*/ CController* CController::NewLC(MSisDataProvider& aDataProvider, TReadTypeBehaviour aTypeReadBehaviour) + { + CController* self = new(ELeave) CController(); + CleanupStack::PushL(self); + TInt64 bytesRead=0; + self->ConstructL(aDataProvider, bytesRead, aTypeReadBehaviour); + return self; + } + +EXPORT_C /*static*/ CController* CController::NewL(MSisDataProvider& aDataProvider, TReadTypeBehaviour aTypeReadBehaviour) + { + CController* self = NewLC(aDataProvider, aTypeReadBehaviour); + CleanupStack::Pop(self); + return self; + } + +CController::CController() : iTrust(ESisPackageUnsignedOrSelfSigned) + { + } + +EXPORT_C CController* CController::NewLC(TPtrProvider& aDataProvider, TReadTypeBehaviour aTypeReadBehaviour) + { + CController* self = new(ELeave) CController(); + CleanupStack::PushL(self); + TInt64 bytesRead(0); + self->ConstructL(aDataProvider, bytesRead, aTypeReadBehaviour); + return self; + } + +EXPORT_C CController* CController::NewL(TPtrProvider& aDataProvider, TReadTypeBehaviour aTypeReadBehaviour) + { + CController* self = NewLC(aDataProvider, aTypeReadBehaviour); + CleanupStack::Pop(self); + return self; + } + +EXPORT_C CController* CController::NewLC(TPtrProvider& aDataProvider, TInt64& aBytesRead, TReadTypeBehaviour aTypeReadBehaviour) + { + CController* self = new(ELeave) CController(); + CleanupStack::PushL(self); + self->ConstructL(aDataProvider, aBytesRead, aTypeReadBehaviour); + return self; + } + +EXPORT_C CController* CController::NewL(TPtrProvider& aDataProvider, TInt64& aBytesRead, TReadTypeBehaviour aTypeReadBehaviour) + { + CController* self = NewLC(aDataProvider, aBytesRead, aTypeReadBehaviour); + CleanupStack::Pop(self); + return self; + } + +EXPORT_C CController::~CController() + { + delete iInfo; + delete iInstallBlock; + delete iLanguages; + delete iSupportedOptions; + delete iProperties; + delete iLogo; + delete iPrerequisites; + delete iDataIndex; + delete iTrustStatus; + delete iCertChainConstraints; + + iCertChainIndices.Close(); + iSignatureCertificateChains.ResetAndDestroy(); + } + +void CController::ConstructL(MSisDataProvider& aDataProvider, TInt64& aBytesRead, TReadTypeBehaviour aTypeReadBehaviour) + { + iDataOffset=aBytesRead; + + CField::ConstructL(aDataProvider, EFieldTypeController, aBytesRead, aTypeReadBehaviour); + + iInfo=CInfo::NewL(aDataProvider, aBytesRead); + + iSupportedOptions=CSupportedOptions::NewL(aDataProvider, aBytesRead); + + iLanguages=CSupportedLanguages::NewL(aDataProvider, aBytesRead); + + iPrerequisites=CPrerequisites::NewL(aDataProvider, aBytesRead); + + iProperties=CProperties::NewL(aDataProvider, aBytesRead); + + TFieldType fieldType; + CField::ReadEnumL(aDataProvider, fieldType, aBytesRead); + + if (fieldType == EFieldTypeLogo) + { + // Logo present + iLogo=CLogo::NewL(aDataProvider, aBytesRead, EAssumeType); + iInstallBlock=CInstallBlock::NewL(aDataProvider, aBytesRead); + } + else if (fieldType == EFieldTypeInstallBlock) + { + // No logo present + iInstallBlock=CInstallBlock::NewL(aDataProvider, aBytesRead, EAssumeType); + } + else + { + User::Leave(KErrSISUnexpectedFieldType); + } + + ReadMemberCollectionL(aDataProvider, iSignatureCertificateChains, EFieldTypeSignatureCertificateChain, EFieldTypeDataIndex, aBytesRead); + + iDataIndex=CDataIndex::NewL(aDataProvider, aBytesRead, EAssumeType); + + CField::SkipUnknownFieldsL(aDataProvider, aBytesRead - iDataOffset, aBytesRead, aTypeReadBehaviour); + CField::EnsureAlignedL(aDataProvider, aBytesRead - iDataOffset, aBytesRead, aTypeReadBehaviour); + + iTrustStatus = new (ELeave)Swi::TSisTrustStatus(); + + // Create unconstrained cert chain constraints object; this may be replaced. + iCertChainConstraints = CCertChainConstraints::NewL(); + + iRemoveWithLastDependent = 0; + + #ifdef SYMBIAN_UNIVERSAL_INSTALL_FRAMEWORK + iUserGrantableCapabilities.SetEmpty(); + #endif + } + +void CController::ConstructL(TPtrProvider& aDataProvider, TInt64& aBytesRead, TReadTypeBehaviour aTypeReadBehaviour) + { + iDataOffset=aBytesRead; + + CField::ConstructL(aDataProvider, EFieldTypeController, aBytesRead, aTypeReadBehaviour); + + iInfo=CInfo::NewL(aDataProvider, aBytesRead); + + iSupportedOptions=CSupportedOptions::NewL(aDataProvider, aBytesRead); + + iLanguages=CSupportedLanguages::NewL(aDataProvider, aBytesRead); + + iPrerequisites=CPrerequisites::NewL(aDataProvider, aBytesRead); + + iProperties=CProperties::NewL(aDataProvider, aBytesRead); + + TFieldType fieldType; + CField::ReadEnumL(aDataProvider, fieldType, aBytesRead); + + if (fieldType == EFieldTypeLogo) + { + // Logo present + iLogo=CLogo::NewL(aDataProvider, aBytesRead, EAssumeType); + iInstallBlock=CInstallBlock::NewL(aDataProvider, aBytesRead); + } + else if (fieldType == EFieldTypeInstallBlock) + { + // No logo present + iInstallBlock=CInstallBlock::NewL(aDataProvider, aBytesRead, EAssumeType); + } + else + { + User::Leave(KErrSISUnexpectedFieldType); + } + + ReadMemberCollectionL(aDataProvider, iSignatureCertificateChains, EFieldTypeSignatureCertificateChain, EFieldTypeDataIndex, aBytesRead); + + iDataIndex=CDataIndex::NewL(aDataProvider, aBytesRead, EAssumeType); + + CField::SkipUnknownFieldsL(aDataProvider, aBytesRead - iDataOffset, aBytesRead, aTypeReadBehaviour); + CField::EnsureAlignedL(aDataProvider, aBytesRead - iDataOffset, aBytesRead, aTypeReadBehaviour); + + iTrustStatus = new (ELeave)Swi::TSisTrustStatus(); + + // Create unconstrained cert chain constraints object; this may be replaced. + iCertChainConstraints = CCertChainConstraints::NewL(); + + iRemoveWithLastDependent = 0; + + #ifdef SYMBIAN_UNIVERSAL_INSTALL_FRAMEWORK + iUserGrantableCapabilities.SetEmpty(); + #endif + } + +EXPORT_C void CController::AddChainIndex(TInt aIndex) const + { + iCertChainIndices.Append(aIndex); + } + +EXPORT_C void CController::ClearCertChainIndices() const + { + iCertChainIndices.Reset(); + } + +EXPORT_C void CController::SetCertChainConstraints(CCertChainConstraints* aConstraints) + { + // Delete existing cert chain constraints object. + delete iCertChainConstraints; + iCertChainConstraints=aConstraints; + } + +EXPORT_C TInt CController::RemoveWithLastDependent() const + { + return iRemoveWithLastDependent; + } + +EXPORT_C void CController::SetRemoveWithLastDependent() + { + iRemoveWithLastDependent = 1; + } + + +EXPORT_C CMessageDigest* CController::GenerateControllerHashLC(const TDesC8& aController) + { + TInt64 infoLength = iInfo->Length() + iInfo->HeaderSize() + iInfo->PaddingSize(); + TInt64 installBLength = iInstallBlock->Length() + iInstallBlock->HeaderSize() + iInstallBlock->PaddingSize(); + TInt64 supportLLength = iLanguages->Length() + iLanguages->HeaderSize() + iLanguages->PaddingSize(); + TInt64 supportOLength = iSupportedOptions->Length() + iSupportedOptions->HeaderSize() + iSupportedOptions->PaddingSize(); + TInt64 propertiesLength = iProperties->Length() + iProperties->HeaderSize() + iProperties->PaddingSize(); + TInt64 prerequisitesLength = iPrerequisites->Length() + iPrerequisites->HeaderSize() + iPrerequisites->PaddingSize(); + TInt64 logoLength = 0; + + if (iLogo) + { + logoLength = iLogo->Length() + iLogo->HeaderSize() + iLogo->PaddingSize(); + } + + TInt64 controllerLength = 0; + controllerLength = infoLength + installBLength + supportLLength + supportOLength + propertiesLength + prerequisitesLength + logoLength; + + // Length octets are either 4 or 8 bytes but since controllers are loaded into + // bytes should ALWAYS be sufficient. + TInt offset = 4; + + // Should really modify the length and not the offset skipping the length octets. + // This makes the controller hash independent of the signature chains. + // + // Unfortunately, this is fixed and changing it potentially breaks compatibility + // E.g. If the firmware is upgraded without reformatting the system drive then SWI + // may think that an application on removable media has not been installed. + controllerLength += (Length() > 0x80000000 ? 8 : 4); + + DEBUG_PRINTF4(_L8("GenerateControllerHashLC aController.Length()=%d, offset=%d, controllerLength=%d"), + aController.Length(), offset, controllerLength); + + if (offset + controllerLength >= aController.Length()) + { + // Mid will panic if the lengths are outside the buffer. + User::Leave(KErrCorrupt); + } + TPtrC8 ptr; + ptr.Set(aController.Mid(offset, controllerLength)); + + CMessageDigest* digest = CMessageDigestFactory::NewDigestLC(CMessageDigest::ESHA1); + digest->Update(ptr); + + return digest; + }