2 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 * @file task_certify.cpp
18 * @author Pawel Sikorski (p.sikorski@samgsung.com)
26 #include <dpl/assert.h>
27 #include <appcore-common.h> //TODO is it necessary here?
31 #include <widget_install/task_certify.h>
32 #include <widget_install/job_widget_install.h>
33 #include <widget_install/widget_install_errors.h>
34 #include <widget_install/widget_install_context.h>
35 #include <dpl/log/log.h>
36 #include <dpl/wrt-dao-ro/global_config.h>
37 #include "wac_widget_id.h"
39 #include <vcore/Certificate.h>
40 #include <vcore/SignatureReader.h>
41 #include <vcore/SignatureFinder.h>
42 #include <vcore/WrtSignatureValidator.h>
43 #include <dpl/utils/wrt_global_settings.h>
44 #include <dpl/wrt-dao-ro/global_dao_read_only.h>
46 #include <ITapiModem.h>
47 #include <tapi_common.h>
49 using namespace ValidationCore;
50 using namespace WrtDB;
54 WidgetCertificateData toWidgetCertificateData(const SignatureData &data,
57 WidgetCertificateData result;
59 result.chainId = data.getSignatureNumber();
60 LogDebug("result.chainId : " << result.chainId);
62 result.owner = data.isAuthorSignature() ?
63 WidgetCertificateData::AUTHOR : WidgetCertificateData::DISTRIBUTOR;
66 WidgetCertificateData::ROOT : WidgetCertificateData::ENDENTITY;
68 CertificatePtr certificate;
71 certificate = data.getRootCaCertificatePtr();
73 certificate = data.getEndEntityCertificatePtr();
76 Assert(certificate && !certificate->getCommonName().IsNull() &&
77 "CommonName is Null");
79 result.strCommonName = *certificate->getCommonName();
81 result.strMD5Fingerprint = std::string("md5 ") +
82 Certificate::FingerprintToColonHex(
83 certificate->getFingerprint(Certificate::FINGERPRINT_MD5));
85 result.strSHA1Fingerprint = std::string("sha-1 ") +
86 Certificate::FingerprintToColonHex(
87 certificate->getFingerprint(Certificate::FINGERPRINT_SHA1));
92 CertificatePtr getOldAuthorSignerCertificate(DPL::String appid)
94 WidgetDAOReadOnly dao(appid);
95 CertificateChainList chainList = dao.getWidgetCertificate(SIGNATURE_AUTHOR);
97 FOREACH(it, chainList)
99 ValidationCore::CertificateCollection chain;
100 if (false == chain.load(*it)) {
101 LogError("Chain is broken");
105 LogError("Chain failed at sorting");
108 ValidationCore::CertificateList list = chain.getCertificateList();
112 if (!(*cert)->isRootCert() && !(*cert)->isCA()) {
117 return CertificatePtr(NULL);
119 } // namespace anonymous
122 namespace WidgetInstall {
123 TaskCertify::TaskCertify(InstallerContext &inCont) :
124 DPL::TaskDecl<TaskCertify>(this),
125 m_contextData(inCont)
127 AddStep(&TaskCertify::stepSignature);
128 // certi comparison determines whether the update.
129 if (true == m_contextData.isUpdateMode) {
130 AddStep(&TaskCertify::stepVerifyUpdate);
132 AddStep(&TaskCertify::stepFinalize);
135 void TaskCertify::processDistributorSignature(const SignatureData &data)
137 // this signature is verified -
138 // no point in check domain WAC_ROOT and WAC_RECOGNIZED
139 m_contextData.wacSecurity.setDistributorSigned(true);
141 CertificateCollection collection;
142 collection.load(data.getCertList());
143 Assert(collection.sort() &&
144 "Certificate collection can't sort");
146 Assert(collection.isChain() &&
147 "Certificate collection is not able to create chain. "
148 "It is not possible to verify this signature.");
150 m_contextData.wacSecurity.getCertificateChainListRef().push_back(
153 if (data.getSignatureNumber() == 1) {
154 m_contextData.wacSecurity.getCertificateListRef().push_back(
155 toWidgetCertificateData(data, true));
156 m_contextData.wacSecurity.getCertificateListRef().push_back(
157 toWidgetCertificateData(data, false));
161 void TaskCertify::processAuthorSignature(const SignatureData &data)
163 using namespace ValidationCore;
164 LogInfo("DNS Identity match!");
165 // this signature is verified or widget is distributor signed
166 m_contextData.wacSecurity.setAuthorCertificatePtr(data.getEndEntityCertificatePtr());
167 CertificatePtr test = m_contextData.wacSecurity.getAuthorCertificatePtr();
169 m_contextData.wacSecurity.getCertificateListRef().push_back(
170 toWidgetCertificateData(data, true));
171 m_contextData.wacSecurity.getCertificateListRef().push_back(
172 toWidgetCertificateData(data, false));
174 // match widget_id with one from dns identity set
175 WacWidgetId widgetId(m_contextData.widgetConfig.configInfo.widget_id);
177 CertificatePtr cert = data.getEndEntityCertificatePtr();
179 Certificate::AltNameSet dnsIdentity = cert->getAlternativeNameDNS();
181 CertificateCollection collection;
182 collection.load(data.getCertList());
184 Assert(collection.isChain() &&
185 "Certificate collection is not able to create chain. "
186 "It is not possible to verify this signature.");
188 m_contextData.wacSecurity.getAuthorsCertificateChainListRef().push_back(
191 FOREACH(it, dnsIdentity){
192 if (widgetId.matchHost(*it)) {
193 m_contextData.wacSecurity.setRecognized(true);
199 void TaskCertify::stepSignature()
201 LogInfo("================ Step: <<Signature>> ENTER ===============");
203 std::string widgetPath;
204 if (m_contextData.widgetConfig.packagingType ==
205 WrtDB::PKG_TYPE_DIRECTORY_WEB_APP)
207 widgetPath = m_contextData.locations->getSourceDir() + "/";
209 widgetPath = m_contextData.locations->getTemporaryPackageDir() + "/";
212 SignatureFileInfoSet signatureFiles;
213 SignatureFinder signatureFinder(widgetPath);
214 if (SignatureFinder::NO_ERROR != signatureFinder.find(signatureFiles)) {
215 LogError("Error in Signature Finder");
216 ThrowMsg(Exceptions::SignatureNotFound,
217 "Error openig temporary widget directory");
220 SignatureFileInfoSet::reverse_iterator iter = signatureFiles.rbegin();
221 LogInfo("Number of signatures: " << signatureFiles.size());
223 bool complianceMode = GlobalDAOReadOnly::getComplianceMode();
225 for (; iter != signatureFiles.rend(); ++iter) {
226 LogInfo("Checking signature with id=" << iter->getFileNumber());
227 SignatureData data(widgetPath + iter->getFileName(),
228 iter->getFileNumber());
232 xml.initialize(data, GlobalConfig::GetSignatureXmlSchema());
235 WrtSignatureValidator::AppType appType =
236 WrtSignatureValidator::WAC20;
238 if (m_contextData.widgetConfig.webAppType ==
239 APP_TYPE_TIZENWEBAPP)
241 appType = WrtSignatureValidator::TIZEN;
244 WrtSignatureValidator::Result result;
246 WrtSignatureValidator validator(
249 OCSPTestModeEnabled(),
251 CrlTestModeEnabled(),
254 result = validator.check(data, widgetPath);
256 if (m_contextData.widgetConfig.packagingType
257 == WrtDB::PKG_TYPE_DIRECTORY_WEB_APP ||
258 m_contextData.job->getInstallerStruct().m_installMode
259 == InstallMode::INSTALL_MODE_PRELOAD)
261 // In directory installation mode, the validation is skipped.
263 result = WrtSignatureValidator::SIGNATURE_VERIFIED;
266 if (result == WrtSignatureValidator::SIGNATURE_REVOKED) {
267 LogWarning("Certificate is REVOKED");
268 ThrowMsg(Exceptions::CertificateExpired,
269 "Certificate is REVOKED");
272 if (result == WrtSignatureValidator::SIGNATURE_INVALID) {
273 LogWarning("Signature is INVALID");
274 // TODO change exception name
275 ThrowMsg(Exceptions::SignatureInvalid,
279 if (data.isAuthorSignature()) {
280 if (result == WrtSignatureValidator::SIGNATURE_VERIFIED ||
281 m_contextData.wacSecurity.isDistributorSigned())
283 processAuthorSignature(data);
285 WrtSignatureValidator::SIGNATURE_DISREGARD)
290 // now signature _must_ be verified
291 processDistributorSignature(data);
293 } Catch(ParserSchemaException::Base) {
294 LogError("Error occured in ParserSchema.");
295 ReThrowMsg(Exceptions::SignatureInvalid,
296 "Error occured in ParserSchema.");
300 if (signatureFiles.empty()) {
301 LogInfo("No signature files has been found.");
304 LogInfo("================ Step: <<Signature>> DONE ================");
306 m_contextData.job->UpdateProgress(
307 InstallerContext::INSTALL_DIGSIG_CHECK,
308 "Widget Signature checked");
311 void TaskCertify::stepFinalize()
313 LogInfo("Step: <<CERTYFYING DONE>>");
315 m_contextData.job->UpdateProgress(
316 InstallerContext::INSTALL_CERT_CHECK,
317 "Widget Certification Check Finished");
320 bool TaskCertify::isTizenWebApp() const
323 if (m_contextData.widgetConfig.webAppType.appType
324 == WrtDB::AppType::APP_TYPE_TIZENWEBAPP)
332 void TaskCertify::stepVerifyUpdate()
334 LogInfo("Step: <<Check Update>>");
335 CertificatePtr newCertificate =
336 m_contextData.wacSecurity.getAuthorCertificatePtr();
337 CertificatePtr oldCertificate =
338 getOldAuthorSignerCertificate(m_contextData.widgetConfig.tzAppid);
340 if (!!newCertificate && !!oldCertificate) {
341 if (0 != newCertificate->getBase64().compare(oldCertificate->getBase64())) {
342 LogDebug("old widget's author signer certificate : " <<
343 oldCertificate->getBase64());
344 LogDebug("new widget's author signer certificate : " <<
345 newCertificate->getBase64());
346 ThrowMsg(Exceptions::NotMatchedCertification,
347 "Author signer certificates doesn't match \
348 between old widget and installing widget");
351 if (!(NULL == newCertificate.Get() && NULL == oldCertificate.Get())) {
352 ThrowMsg(Exceptions::NotMatchedCertification,
353 "Author signer certificates doesn't match \
354 between old widget and installing widget");
358 } //namespace WidgetInstall