|
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 |