secureswitools/swisistools/source/signsislib/signsis.cpp
changeset 0 ba25891c3a9e
--- /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 ();
+	}
+
+