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)
28 #include <dpl/assert.h>
32 #include <widget_install/task_certify.h>
33 #include <widget_install/job_widget_install.h>
34 #include <widget_install/widget_install_errors.h>
35 #include <widget_install/widget_install_context.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 #include <installer_log.h>
51 using namespace ValidationCore;
52 using namespace WrtDB;
56 WidgetCertificateData toWidgetCertificateData(const SignatureData &data,
59 WidgetCertificateData result;
61 result.chainId = data.getSignatureNumber();
62 _D("result.chainId : %d", result.chainId);
64 result.owner = data.isAuthorSignature() ?
65 WidgetCertificateData::AUTHOR : WidgetCertificateData::DISTRIBUTOR;
68 WidgetCertificateData::ROOT : WidgetCertificateData::ENDENTITY;
70 CertificatePtr certificate;
73 certificate = data.getRootCaCertificatePtr();
75 certificate = data.getEndEntityCertificatePtr();
78 Assert(certificate && !certificate->getCommonName().IsNull() &&
79 "CommonName is Null");
81 result.strCommonName = *certificate->getCommonName();
83 result.strMD5Fingerprint = std::string("md5 ") +
84 Certificate::FingerprintToColonHex(
85 certificate->getFingerprint(Certificate::FINGERPRINT_MD5));
87 result.strSHA1Fingerprint = std::string("sha-1 ") +
88 Certificate::FingerprintToColonHex(
89 certificate->getFingerprint(Certificate::FINGERPRINT_SHA1));
94 CertificatePtr getOldAuthorSignerCertificate(DPL::String appid)
96 WidgetDAOReadOnly dao(appid);
97 CertificateChainList chainList = dao.getWidgetCertificate(SIGNATURE_AUTHOR);
99 FOREACH(it, chainList)
101 ValidationCore::CertificateCollection chain;
102 if (false == chain.load(*it)) {
103 _E("Chain is broken");
107 _E("Chain failed at sorting");
110 ValidationCore::CertificateList list = chain.getCertificateList();
114 if (!(*cert)->isRootCert() && !(*cert)->isCA()) {
119 return CertificatePtr(NULL);
121 } // namespace anonymous
124 namespace WidgetInstall {
125 TaskCertify::TaskCertify(InstallerContext &inCont) :
126 DPL::TaskDecl<TaskCertify>(this),
127 m_contextData(inCont)
129 AddStep(&TaskCertify::StartStep);
130 AddStep(&TaskCertify::stepSignature);
131 // certi comparison determines whether the update.
132 if (true == m_contextData.isUpdateMode) {
133 AddStep(&TaskCertify::stepVerifyUpdate);
135 AddStep(&TaskCertify::EndStep);
138 void TaskCertify::processDistributorSignature(const SignatureData &data)
140 // this signature is verified -
141 // no point in check domain WAC_ROOT and WAC_RECOGNIZED
142 m_contextData.widgetSecurity.setDistributorSigned(true);
144 CertificateCollection collection;
145 collection.load(data.getCertList());
146 Assert(collection.sort() &&
147 "Certificate collection can't sort");
149 Assert(collection.isChain() &&
150 "Certificate collection is not able to create chain. "
151 "It is not possible to verify this signature.");
153 m_contextData.widgetSecurity.getCertificateChainListRef().push_back(
156 if (data.getSignatureNumber() == 1) {
157 m_contextData.widgetSecurity.getCertificateListRef().push_back(
158 toWidgetCertificateData(data, true));
159 m_contextData.widgetSecurity.getCertificateListRef().push_back(
160 toWidgetCertificateData(data, false));
164 void TaskCertify::processAuthorSignature(const SignatureData &data)
166 using namespace ValidationCore;
167 _D("DNS Identity match!");
168 // this signature is verified or widget is distributor signed
169 m_contextData.widgetSecurity.setAuthorCertificatePtr(data.getEndEntityCertificatePtr());
170 CertificatePtr test = m_contextData.widgetSecurity.getAuthorCertificatePtr();
172 m_contextData.widgetSecurity.getCertificateListRef().push_back(
173 toWidgetCertificateData(data, true));
174 m_contextData.widgetSecurity.getCertificateListRef().push_back(
175 toWidgetCertificateData(data, false));
177 // match widget_id with one from dns identity set
178 WacWidgetId widgetId(m_contextData.widgetConfig.configInfo.widget_id);
180 CertificatePtr cert = data.getEndEntityCertificatePtr();
182 Certificate::AltNameSet dnsIdentity = cert->getAlternativeNameDNS();
184 CertificateCollection collection;
185 collection.load(data.getCertList());
187 Assert(collection.isChain() &&
188 "Certificate collection is not able to create chain. "
189 "It is not possible to verify this signature.");
191 m_contextData.widgetSecurity.getAuthorsCertificateChainListRef().push_back(
194 FOREACH(it, dnsIdentity){
195 if (widgetId.matchHost(*it)) {
196 m_contextData.widgetSecurity.setRecognized(true);
202 void TaskCertify::getSignatureFiles(std::string path, SignatureFileInfoSet& file)
204 _D("path : %s", path.c_str());
205 SignatureFileInfoSet signatureFiles;
206 SignatureFinder signatureFinder(path);
207 if (SignatureFinder::NO_ERROR != signatureFinder.find(file)) {
208 _E("Error in Signature Finder : %s", path.c_str());
209 ThrowMsg(Exceptions::SignatureNotFound,
210 "Error openig temporary widget directory");
214 void TaskCertify::stepSignature()
216 _D("================ Step: <<Signature>> ENTER ===============");
218 std::string widgetPath;
219 widgetPath = m_contextData.locations->getTemporaryPackageDir() + "/";
221 if (m_contextData.mode.command ==
222 InstallMode::Command::REINSTALL)
224 widgetPath = m_contextData.locations->getPackageInstallationDir() + "/";
227 SignatureFileInfoSet signatureFiles;
230 getSignatureFiles(widgetPath, signatureFiles);
232 if (signatureFiles.size() <= 0) {
233 widgetPath += std::string(WrtDB::GlobalConfig::GetWidgetSrcPath())
235 if (0 == access(widgetPath.c_str(), F_OK)) {
236 getSignatureFiles(widgetPath, signatureFiles);
239 } Catch(Exceptions::SignatureNotFound) {
240 ReThrowMsg(Exceptions::SignatureNotFound, widgetPath);
243 SignatureFileInfoSet::reverse_iterator iter = signatureFiles.rbegin();
244 _D("Number of signatures: %d", signatureFiles.size());
246 for (; iter != signatureFiles.rend(); ++iter) {
247 _D("Checking signature with id=%d", iter->getFileNumber());
248 SignatureData data(widgetPath + iter->getFileName(),
249 iter->getFileNumber());
253 xml.initialize(data, GlobalConfig::GetSignatureXmlSchema());
256 WrtSignatureValidator::Result result;
258 WrtSignatureValidator validator(
259 WrtSignatureValidator::TIZEN,
261 OCSPTestModeEnabled(),
263 CrlTestModeEnabled(),
266 result = validator.check(data, widgetPath);
268 if (m_contextData.mode.installTime
269 == InstallMode::InstallTime::PRELOAD)
271 result = WrtSignatureValidator::SIGNATURE_VERIFIED;
274 if (result == WrtSignatureValidator::SIGNATURE_REVOKED) {
275 _W("Certificate is REVOKED");
276 ThrowMsg(Exceptions::CertificateExpired,
277 "Certificate is REVOKED");
280 if (result == WrtSignatureValidator::SIGNATURE_INVALID &&
281 iter->getFileNumber() <= 1) {
282 _W("Signature is INVALID");
283 // TODO change exception name
284 ThrowMsg(Exceptions::SignatureInvalid,
288 if (data.isAuthorSignature()) {
289 if (result == WrtSignatureValidator::SIGNATURE_VERIFIED ) {
290 processAuthorSignature(data);
293 if (result != WrtSignatureValidator::SIGNATURE_INVALID) {
294 processDistributorSignature(data);
297 } Catch(ParserSchemaException::Base) {
298 _E("Error occured in ParserSchema.");
299 ReThrowMsg(Exceptions::SignatureInvalid,
300 "Error occured in ParserSchema.");
304 if (signatureFiles.empty()) {
305 _D("No signature files has been found.");
308 _D("================ Step: <<Signature>> DONE ================");
310 m_contextData.job->UpdateProgress(
311 InstallerContext::INSTALL_DIGSIG_CHECK,
312 "Widget Signature checked");
315 bool TaskCertify::isTizenWebApp() const
318 if (m_contextData.widgetConfig.webAppType.appType
319 == WrtDB::AppType::APP_TYPE_TIZENWEBAPP)
327 void TaskCertify::stepVerifyUpdate()
329 _D("Step: <<Check Update>>");
330 CertificatePtr newCertificate =
331 m_contextData.widgetSecurity.getAuthorCertificatePtr();
332 CertificatePtr oldCertificate =
333 getOldAuthorSignerCertificate(m_contextData.widgetConfig.tzAppid);
335 if (!!newCertificate && !!oldCertificate) {
336 if (0 != newCertificate->getBase64().compare(oldCertificate->getBase64())) {
337 _D("old widget's author signer certificate : %s", (oldCertificate->getBase64()).c_str());
338 _D("new widget's author signer certificate : %s", (newCertificate->getBase64()).c_str());
339 ThrowMsg(Exceptions::NotMatchedCertification,
340 "Author signer certificates doesn't match \
341 between old widget and installing widget");
344 if (!(NULL == newCertificate.Get() && NULL == oldCertificate.Get())) {
345 ThrowMsg(Exceptions::NotMatchedCertification,
346 "Author signer certificates doesn't match \
347 between old widget and installing widget");
352 void TaskCertify::StartStep()
354 _D("--------- <TaskCertify> : START ----------");
357 void TaskCertify::EndStep()
359 _D("Step: <<CERTYFYING DONE>>");
361 m_contextData.job->UpdateProgress(
362 InstallerContext::INSTALL_CERT_CHECK,
363 "Widget Certification Check Finished");
365 _D("--------- <TaskCertify> : END ----------");
367 } //namespace WidgetInstall