diff -r 000000000000 -r ba25891c3a9e secureswitools/swisistools/source/dumpsislib/dumpsis.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/secureswitools/swisistools/source/dumpsislib/dumpsis.cpp Thu Dec 17 08:51:10 2009 +0200 @@ -0,0 +1,444 @@ +/* +* Copyright (c) 2008-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: +* +*/ + + +#ifdef _MSC_VER +#pragma warning (disable: 4786) +#endif + +#include +#include // for strstream, wistringstream +#include +#include +#include +#include +#include + + +#include "dumpsis.h" +#include "siscontroller.h" +#include "exception.h" + +CDumpSis::CDumpSis(const std::wstring& aSISFileName, bool aVerbose) + : iController(NULL), + iSisFileName(aSISFileName), + iVerbose(aVerbose), + iIsStub(false) + { + bool isSiSFile = CSISContents::IsSisFile(aSISFileName); + if(isSiSFile) + { + iSisContents.Load (iSisFileName); + iController = &iSisContents.Controller(); + } + else + { + iIsStub = true; + iController = new CSISController; + SISLogger::Log(L"Dumping Stub SIS Controller\n"); + iController->Load(iSisFileName); + } + } + +CDumpSis::~CDumpSis() + { + if(iIsStub) + { + delete iController; + } + } + +void CDumpSis::CreatePackage(const std::wstring& aPkgFileName) + { + std::wistringstream inStream (std::ios::in | std::ios::out); + std::wostream outStream (inStream.rdbuf ()); + + outStream << wchar_t(0xfeff); + if(iIsStub) + { + iController->AddPackageEntry (outStream, iVerbose); + } + else + { + iSisContents.AddPackageEntry (outStream, iVerbose); + } + + std::wstring str = inStream.str(); + WriteToFile(aPkgFileName, reinterpret_cast(str.c_str()), str.length()*2); + } + +void CDumpSis::CreatePackage(const CSISController& aSisController, const std::wstring& aPkgFileName) + { + std::wistringstream inStream (std::ios::in | std::ios::out); + std::wostream outStream (inStream.rdbuf ()); + + outStream << wchar_t(0xfeff); + aSisController.AddPackageEntry (outStream, iVerbose); + std::wstring str = inStream.str(); + WriteToFile(aPkgFileName, reinterpret_cast(str.c_str()), str.length()*2); + } + +void CDumpSis::ExtractFiles(const std::wstring& aTargetDir, TExtractionLevel aLevel) + { + std::wstring targetDir = aTargetDir; + CreateTargetDir(targetDir); + + switch(aLevel) + { + case EOnlyPackage: + { + ExtractBasePackageFile(targetDir); + break; + } + case ECertificates: + { + ExtractCertificates(*iController, targetDir); + break; + } + case EBaseFiles: + { + ExtractFiles(*iController, targetDir); + break; + } + case EAllDataFiles: + { + ExtractBasePackageFile(targetDir); + ExtractFiles(*iController, targetDir); + ExtractNestedSisFile(targetDir, *iController, false, 0, iSisContents.SisData().DataUnitCount()); + break; + } + case EAllButCerts: + { + ExtractBasePackageFile(targetDir); + ExtractFiles(*iController, targetDir); + ExtractNestedSisFile(targetDir, *iController, true, 0, iSisContents.SisData().DataUnitCount()); + break; + } + case EEverything: + { + ExtractBasePackageFile(targetDir); + ExtractFiles(*iController, targetDir); + ExtractNestedSisFile(targetDir, *iController, true, 0, iSisContents.SisData().DataUnitCount()); + ExtractAllCertificates(targetDir); + break; + } + } + } + +void CDumpSis::ExtractAllCertificates(const std::wstring& aTargetDir) + { + ExtractCertificates(*iController, aTargetDir); + + TControllerMap controllerList; + iController->InstallBlock().GetEmbeddedControllers(controllerList); + + for (TControllerMapConstIter iter = controllerList.begin(); iter != controllerList.end(); ++iter) + { + wchar_t pathName[20]; + swprintf(pathName, 20, L"sis%d", iter->first); + + std::wstring extractionPath = aTargetDir + KSisDirectorySeparator + pathName; + CreateTargetDir(extractionPath); + ExtractCertificates(*iter->second, extractionPath); + } + } +void CDumpSis::ExtractCertificates(const CSISController& aSisController, const std::wstring& aTargetDir) + { + TUint32 certChainCount = aSisController.SignatureCount(); + for(TUint32 i = 0; i < certChainCount; ++i) + { + wchar_t certName[30]; + swprintf(certName, 30, L"certChain%d%d.der", aSisController.DataIndex(), i+1); + std::wstring certFullPath = aTargetDir + KSisDirectorySeparator + certName; + const CCertChainData certChain = aSisController.SignatureCertChain(i).CertificateChain(); + const TUint8* certChainData = certChain.CertificateData().Data(); + TUint32 certSize = certChain.CertificateData().Size(); + WriteToFile(certFullPath, certChainData, certSize); + } + } + + +void CDumpSis::ExtractBasePackageFile(const std::wstring& aTargetDir) + { + std::wstring pkgFileName = iSisFileName; + pkgFileName = FixPathDelimiters(pkgFileName); + SisFileNameToPkgFileName(pkgFileName); + pkgFileName = aTargetDir + KSisDirectorySeparator + pkgFileName; + CreatePackage(pkgFileName); + } +void CDumpSis::ExtractFiles(const CSISController& aSisController, const std::wstring& aTargetDir, int aBaseIndex) + { + if(iIsStub) + { + // There is no data associated with stub sis file. + return; + } + TFileDescList fileList; + aSisController.InstallBlock().GetFileList(fileList); + // Controller's index is relative to base controller's index. + TUint32 dataIndex = aBaseIndex + aSisController.DataIndex(); + if(dataIndex >= iSisContents.SisData().DataUnitCount()) + { + return; + } + const CSISDataUnit& dataUnit = iSisContents.SisData().DataUnit(dataIndex); + + const CSISLogo& logo = aSisController.Logo(); + if(!logo.WasteOfSpace()) + { + const CSISFileDescription& logoFile = logo.FileDesc(); + const wchar_t* fileName = logoFile.GetFileName(); + std::wstring filePath = aTargetDir + KSisDirectorySeparator + fileName; + const CSISFileData& fileData = dataUnit.FileData(logoFile.FileIndex()); + WriteToFile(filePath, fileData.Data(), fileData.UncompressedSize()); + delete[] const_cast(fileName); + } + + + if(dataUnit.FileCount() <= 0) + { + return; // No files present to extract. + } + + for(int i = 0; i < fileList.size(); ++i) + { + const CSISFileDescription* fdesc = fileList[i]; + const wchar_t* fileName = fdesc->GetFileName(); + std::wstring filePath = aTargetDir + KSisDirectorySeparator + fileName; + const CSISFileData& fileData = dataUnit.FileData(fdesc->FileIndex()); + WriteToFile(filePath, fileData.Data(), fileData.UncompressedSize()); + delete[] const_cast(fileName); + } + } + +void CDumpSis::ExtractNestedSisFile(const std::wstring& aTargetDir, + const CSISController& aController, + bool aExtractSis, + int aStartIndex, + int aEndIndex) + { + TControllerMap controllerList; + aController.InstallBlock().GetEmbeddedControllers(controllerList); + + for (TControllerMapConstIter iter = controllerList.begin(); iter != controllerList.end(); ++iter) + { + TControllerMapConstIter nextIter = iter; + int curindex = iter->second->DataIndex(); + int maxDataUnit = 0; + if (++nextIter != controllerList.end()) + { + maxDataUnit = nextIter->first; + } + else + { + maxDataUnit = aEndIndex; + } + wchar_t pathName[20]; +#ifdef _MSC_VER + swprintf(pathName, L"sis%d", iter->second->GetControllerID()); +#else + swprintf(pathName, 20, L"sis%d", iter->second->GetControllerID()); +#endif //_MSC_VER + + if(aExtractSis) + { + std::wstring sisPath = aTargetDir + KSisDirectorySeparator + pathName + L".sis"; + CSISController* ctl = const_cast(iter->second); + CreateEmbeddedSis(sisPath, *ctl, aStartIndex + iter->first, maxDataUnit); + } + + std::wstring extractionPath = aTargetDir + KSisDirectorySeparator + pathName; + CreateTargetDir(extractionPath); + ExtractFiles(*iter->second, extractionPath, aStartIndex); + extractionPath = extractionPath + KSisDirectorySeparator + pathName + L".pkg"; + CreatePackage(*iter->second, extractionPath); + ExtractNestedSisFile(aTargetDir, *(iter->second), aExtractSis, aStartIndex + iter->first, maxDataUnit); + } + } + +void CDumpSis::CreateTargetDir(std::wstring& aTargetDir) + { + aTargetDir = FixPathDelimiters(aTargetDir); + if(CreateDir(aTargetDir.c_str()) != 0) + { + return; + } + + int err = GetErrorValue(); + + switch (err) + { + case ERROR_ALREADY_EXISTS: + { + int attrs; + + if (0xFFFFFFFF != (attrs = FileAttributes(aTargetDir.c_str()))) + { + if (!(attrs & FILE_ATTRIBUTE_DIRECTORY)) + { + throw CSISException::EDirIsFile; + } + else if (attrs & FILE_ATTRIBUTE_READONLY) + { + throw CSISException::EPermissionDenied; + } + } + else + { + throw CSISException::EInvalidDestination; + } + break; + } + case ERROR_PATH_NOT_FOUND: + CreateDirectoriesRecursively(aTargetDir); + break; + + case ERROR_ACCESS_DENIED: + throw CSISException::EInvalidDestination; + break; + + case ERROR_INVALID_NAME: + aTargetDir = L"."; + break; + + default: + throw CSISException::EInvalidDestination; + } + } + + +void CDumpSis::CreateDirectoriesRecursively(std::wstring aTargetDir) + { + int pos = aTargetDir.find(L'/'); + + if(0 == pos) + { + // Path starting with "/" can be skipped + pos = aTargetDir.find(L'/', 1); + } + + while(pos != std::wstring::npos) + { + std::wstring path = aTargetDir.substr(0, pos); + + if (0 == CreateDir(path.c_str())) + { + int err = GetErrorValue(); + switch(err) + { + case ERROR_ACCESS_DENIED: + { + // If this is caused by a path like "D:" we can continue + bool validPath = ((aTargetDir.size() >= 2) && (isalpha(aTargetDir[0])) && (aTargetDir[1] ==L':')); + if (!validPath) + { + throw CSISException::EInvalidDestination; + } + break; + } + + case ERROR_ALREADY_EXISTS: + // NOOP + break; + + default: + throw CSISException::EInvalidDestination; + } + } + pos = aTargetDir.find(L'/', pos+1); + } + + if (0 == CreateDir(aTargetDir.c_str())) + { + if ( GetErrorValue() != ERROR_ALREADY_EXISTS) + { + throw CSISException::EInvalidDestination; + } + } + } + +void CDumpSis::SisFileNameToPkgFileName(std::wstring& aFileName) + { + int pos = aFileName.find_last_of(L'/'); + if(std::wstring::npos != pos) + { + aFileName = aFileName.substr(pos+1); + } + + for(int i = 0; i < aFileName.size(); ++i) + { + aFileName[i] = tolower(aFileName[i]); + } + + pos = aFileName.rfind(L".sis"); + if(std::wstring::npos == pos) + { + pos = aFileName.rfind(L".ctl"); + } + + aFileName = aFileName.substr(0, pos); + aFileName.append(L".pkg"); + } + +void CDumpSis::CreateEmbeddedSis(const std::wstring& aFileName, CSISController& aController, int aStart, int aEnd) + { + const CSISData& parentSisData = iSisContents.SisData(); + TUint32 dataIndex = aController.DataIndex(); + aController.SetDataIndex(0); + CSISCompressed compressedController(aController); + aController.SetDataIndex(dataIndex); + + CSISData sisData; + for (int i = aStart; i < aEnd; ++i) + { + sisData.AddDataUnit(parentSisData.DataUnit(i)); + } + + CSISContents contents( const_cast(iSisContents.ControllerChecksum()), + const_cast(iSisContents.DataChecksum()), + compressedController, + sisData + ); + + contents.Save(aFileName); + } + +void CDumpSis::GetCapVerifiedFileList(TFileCapTestList& aFileCapList) + { + TFileDescList fileList; + iSisContents.Controller().InstallBlock().GetFileList(fileList); + const CSISDataUnit& dataUnit = iSisContents.SisData().DataUnit(0); + int fileCount = fileList.size(); + for(int i = 0; i < fileCount; ++i) + { + const CSISFileDescription* fdesc = fileList[i]; + const wchar_t* fileName = L"symbiantemp.xyz"; + const CSISFileData& fileData = dataUnit.FileData(fdesc->FileIndex()); + WriteToFile(fileName, fileData.Data(), fileData.UncompressedSize()); + CSISCapabilities capObj; + capObj.ExtractCapabilities(fileName); + TFileCapTest fileCapTest; + fileCapTest.iFileDesc = fdesc; + fileCapTest.iActualCap = capObj.Capabilities(); + fileCapTest.iCapVerified = (fileCapTest.iActualCap == fileList[i]->Capabilities())? true : false; + aFileCapList.push_back(fileCapTest); + MakeSISDeleteFile(fileName); + } + } + + +// End Of File