--- /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 <openssl/err.h>
+#include <openssl/x509.h>
+#include <iostream>
+
+#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<CSISController&>(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<CSISController&>(iSisContents.Controller());
+ controller.RemoveSignature();
+ Verify();
+ iSisContents.PrepareCrcs();
+ iSisContents.Save(aOutputFileName);
+ }
+void CSignSis::RemoveAllSignatures(const std::wstring& aOutputFileName)
+ {
+ CSISController& controller = const_cast<CSISController&>(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<CSignatureCertChainData&>(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 ();
+ }
+
+