diff -r 000000000000 -r ba25891c3a9e secureswitools/swisistools/source/signsislib/signsis.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/secureswitools/swisistools/source/signsislib/signsis.cpp Thu Dec 17 08:51:10 2009 +0200 @@ -0,0 +1,162 @@ +/* +* 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: +* +*/ + + +/** + @file + @internalComponent + @released +*/ + +#ifdef _MSC_VER +#pragma warning (disable: 4786) +#endif // _MSC_VER + +#include +#include +#include + +#include "commontypes.h" +#include "sisblob.h" +#include "signsis.h" +#include "sissignaturecertificatechain.h" +#include "sisinstallblock.h" +#include "sissignature.h" + +CSignSis::CSignSis(const std::wstring aSisFileName) + { + ERR_load_crypto_strings (); + OpenSSL_add_all_algorithms (); + OpenSSL_add_all_ciphers (); + OpenSSL_add_all_digests (); + + iSisContents.Load(aSisFileName); + Verify(); + } + +void CSignSis::SignSis( const std::wstring& aOutputFileName, + const std::wstring& aCertificate, + const std::wstring& aPrivateKey, + const std::wstring& aPassPhrase, + const CSISSignatureAlgorithm::TAlgorithm aAlgorithm) + { + CSignatureCertChainData scc; + CSisSignatureCertificateChain certChain(scc); + CSISController& controller = const_cast(iSisContents.Controller()); + certChain.Sign(aAlgorithm, aCertificate, aPrivateKey, aPassPhrase, controller.RawBuffer(), controller.BufferSize()); + controller.AddSignatureChain(scc); + Verify(); + iSisContents.PrepareCrcs(); + iSisContents.Save(aOutputFileName); + } + +void CSignSis::RemoveSignature(const std::wstring& aOutputFileName) + { + CSISController& controller = const_cast(iSisContents.Controller()); + controller.RemoveSignature(); + Verify(); + iSisContents.PrepareCrcs(); + iSisContents.Save(aOutputFileName); + } +void CSignSis::RemoveAllSignatures(const std::wstring& aOutputFileName) + { + CSISController& controller = const_cast(iSisContents.Controller()); + int signatureCount = 0; + do + { + controller.RemoveSignature(); + signatureCount = controller.SignatureCount(); + }while(signatureCount > 0); + iSisContents.PrepareCrcs(); + iSisContents.Save(aOutputFileName); + } + +void CSignSis::Verify() + { + // Verify CSISContents + iSisContents.Verify(iSisContents.LanguageCount()); + const CSISController& controller = iSisContents.Controller(); + int signatureCount = controller.SignatureCount(); + // Verify all the signatures + for(int i = 0; i < signatureCount; ++i) + { + CSignatureCertChainData& scc = const_cast(controller.SignatureCertChain(i)); + CSisSignatureCertificateChain certChain(scc); + certChain.VerifySignature(&controller, controller.PostHeaderPos()); + } + // Verify stored hash with hash calculated from the files + // Skip the sis files with no data present (pre-installed apps) + if(iSisContents.SisData().DataPresent()) + { + // Check that the hash values stored in each file description correlate with the actual file data + // provided. This prevents a sis file being signed if it contains an incorrect hash. It + // thus prevents the situation where a malicious file with the specified hash can later be + // substituted into the signed sis file. + VerifyHashAgainstFileData(iSisContents.InstallBlock(), iSisContents.DataUnit()); + } + } + +void CSignSis::VerifyHashAgainstFileData(const CSISInstallBlock& aInstallBlock, const CSISDataUnit& aDataUnit) + { + TFileDescList fileList; + aInstallBlock.GetFileList(fileList); + for(int i = 0; i < fileList.size(); ++i) + { + const CSISFileDescription* fdesc = fileList[i]; + + // Retrieve the stored hash data + const CSISHash& storedSisHash = fdesc->Hash(); + CSISBlob storedDigestBlob = storedSisHash.Blob(); + TUint8* storedDigest = storedDigestBlob.Data(); + + // Check if the algorithm is correct + CSISException::ThrowIf (!(storedSisHash.VerifyAlgorithm()), CSISException::EVerification, "unsupported hash algorithm"); + + // First check if the hash exists (to cater for the FILENULL case) + if (storedDigest) + { + // Make a call to compute the hash of the actual file data + TSHADigest digest; + const CSISFileData& fileData = aDataUnit.FileData(fdesc->FileIndex()); + CalculateHash(digest, fileData.Data (), fileData.UncompressedSize ()); + + CSISHash computedSISHash; + computedSISHash.SetHash(digest, SHA_DIGEST_LENGTH); + + // Extract the computed hash data + CSISBlob computedBlob = computedSISHash.Blob(); + TUint8* computedDigest = computedBlob.Data(); + + + // The computed data shouldn't be Null (as it has already been determined that + // the stored digest is not Null) + CSISException::ThrowIf ((!computedDigest), CSISException::EVerification, "computed hash data is NULL"); + + + // The two hashes must match to ensure integrity of the sis file. + CSISException::ThrowIf (!(computedBlob == storedDigestBlob), CSISException::EVerification, "Stored and computed hash values do not match"); + } + } + } + +CSignSis::~CSignSis() + { + EVP_cleanup (); + ERR_free_strings (); + } + +