secureswitools/swisistools/source/signsislib/signsis.cpp
changeset 0 ba25891c3a9e
equal deleted inserted replaced
-1:000000000000 0:ba25891c3a9e
       
     1 /*
       
     2 * Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of the License "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description: 
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 /**
       
    20  @file 
       
    21  @internalComponent
       
    22  @released
       
    23 */
       
    24 
       
    25 #ifdef _MSC_VER
       
    26 #pragma warning (disable: 4786)
       
    27 #endif // _MSC_VER
       
    28 
       
    29 #include <openssl/err.h>
       
    30 #include <openssl/x509.h>
       
    31 #include <iostream>
       
    32 
       
    33 #include "commontypes.h"
       
    34 #include "sisblob.h"
       
    35 #include "signsis.h"
       
    36 #include "sissignaturecertificatechain.h"
       
    37 #include "sisinstallblock.h"
       
    38 #include "sissignature.h" 
       
    39 
       
    40 CSignSis::CSignSis(const std::wstring aSisFileName)
       
    41 	{
       
    42 	ERR_load_crypto_strings ();
       
    43 	OpenSSL_add_all_algorithms ();
       
    44 	OpenSSL_add_all_ciphers ();
       
    45 	OpenSSL_add_all_digests ();
       
    46 
       
    47 	iSisContents.Load(aSisFileName);
       
    48 	Verify();
       
    49 	}
       
    50 
       
    51 void CSignSis::SignSis(	const std::wstring& aOutputFileName, 
       
    52 						const std::wstring& aCertificate, 
       
    53 						const std::wstring& aPrivateKey, 
       
    54 						const std::wstring& aPassPhrase, 
       
    55 						const CSISSignatureAlgorithm::TAlgorithm aAlgorithm)
       
    56 	{
       
    57 	CSignatureCertChainData scc;
       
    58 	CSisSignatureCertificateChain certChain(scc);
       
    59 	CSISController& controller = const_cast<CSISController&>(iSisContents.Controller());
       
    60 	certChain.Sign(aAlgorithm, aCertificate, aPrivateKey, aPassPhrase, controller.RawBuffer(), controller.BufferSize());
       
    61 	controller.AddSignatureChain(scc);
       
    62 	Verify();
       
    63 	iSisContents.PrepareCrcs();
       
    64 	iSisContents.Save(aOutputFileName);
       
    65 	}
       
    66 
       
    67 void CSignSis::RemoveSignature(const std::wstring& aOutputFileName)
       
    68 	{
       
    69 	CSISController& controller = const_cast<CSISController&>(iSisContents.Controller());
       
    70 	controller.RemoveSignature();
       
    71 	Verify();
       
    72 	iSisContents.PrepareCrcs();
       
    73 	iSisContents.Save(aOutputFileName);
       
    74 	}
       
    75 void CSignSis::RemoveAllSignatures(const std::wstring& aOutputFileName)
       
    76 	{
       
    77 	CSISController& controller = const_cast<CSISController&>(iSisContents.Controller());
       
    78 	int signatureCount = 0;
       
    79 	do
       
    80 		{
       
    81 		controller.RemoveSignature();
       
    82 		signatureCount = controller.SignatureCount();
       
    83 		}while(signatureCount > 0);
       
    84 	iSisContents.PrepareCrcs();
       
    85 	iSisContents.Save(aOutputFileName);
       
    86 	}
       
    87 
       
    88 void CSignSis::Verify()
       
    89 	{
       
    90 	// Verify CSISContents
       
    91 	iSisContents.Verify(iSisContents.LanguageCount());
       
    92 	const CSISController& controller = iSisContents.Controller();
       
    93 	int signatureCount = controller.SignatureCount();
       
    94 	// Verify all the signatures
       
    95 	for(int i = 0; i < signatureCount; ++i)
       
    96 		{
       
    97 		CSignatureCertChainData& scc = const_cast<CSignatureCertChainData&>(controller.SignatureCertChain(i));
       
    98 		CSisSignatureCertificateChain certChain(scc);
       
    99 		certChain.VerifySignature(&controller, controller.PostHeaderPos());
       
   100 		}
       
   101 	// Verify stored hash with hash calculated from the files
       
   102 	// Skip the sis files with no data present (pre-installed apps)
       
   103 	if(iSisContents.SisData().DataPresent())
       
   104 		{
       
   105 		// Check that the hash values stored in each file description correlate with the actual file data 
       
   106 		// provided. This prevents a sis file being signed if it contains an incorrect hash. It 
       
   107 		// thus prevents the situation where a malicious file with the specified hash can later be 
       
   108 		// substituted into the signed sis file.   
       
   109 		VerifyHashAgainstFileData(iSisContents.InstallBlock(), iSisContents.DataUnit());
       
   110 		}
       
   111 	}
       
   112 
       
   113 void CSignSis::VerifyHashAgainstFileData(const CSISInstallBlock& aInstallBlock, const CSISDataUnit& aDataUnit)
       
   114 	{
       
   115 	TFileDescList fileList;
       
   116 	aInstallBlock.GetFileList(fileList);
       
   117 	for(int i = 0; i < fileList.size(); ++i)
       
   118 		{
       
   119 		const CSISFileDescription* fdesc = fileList[i];
       
   120 
       
   121 		// Retrieve the stored hash data 
       
   122 		const CSISHash& storedSisHash = fdesc->Hash();   
       
   123 		CSISBlob storedDigestBlob = storedSisHash.Blob();
       
   124 		TUint8* storedDigest = storedDigestBlob.Data();
       
   125 
       
   126 		// Check if the algorithm is correct
       
   127  		CSISException::ThrowIf (!(storedSisHash.VerifyAlgorithm()), CSISException::EVerification, "unsupported hash algorithm");
       
   128 
       
   129 		// First check if the hash exists (to cater for the FILENULL case)					
       
   130 		if (storedDigest)  
       
   131 			{
       
   132 			// Make a call to compute the hash of the actual file data
       
   133 			TSHADigest digest;
       
   134 			const CSISFileData& fileData = aDataUnit.FileData(fdesc->FileIndex());
       
   135 			CalculateHash(digest, fileData.Data (), fileData.UncompressedSize ());
       
   136 			
       
   137 			CSISHash computedSISHash;
       
   138 			computedSISHash.SetHash(digest, SHA_DIGEST_LENGTH);
       
   139 															 
       
   140 			// Extract the computed hash data 													
       
   141 			CSISBlob computedBlob = computedSISHash.Blob();
       
   142 			TUint8* computedDigest = computedBlob.Data();
       
   143 			
       
   144 								 
       
   145 		 	// The computed data shouldn't be Null (as it has already been determined that 
       
   146 		 	// the stored digest is not Null)
       
   147 			CSISException::ThrowIf ((!computedDigest), CSISException::EVerification, "computed hash data is NULL");	
       
   148 
       
   149 																	 			 
       
   150 			// The two hashes must match to ensure integrity of the sis file.
       
   151 			CSISException::ThrowIf (!(computedBlob == storedDigestBlob), CSISException::EVerification, "Stored and computed hash values do not match");	
       
   152 			}
       
   153 		}
       
   154 	}
       
   155 
       
   156 CSignSis::~CSignSis()
       
   157 	{
       
   158 	EVP_cleanup ();
       
   159 	ERR_free_strings ();
       
   160 	}
       
   161 
       
   162