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)
27 #include <dpl/assert.h>
28 #include <appcore-common.h> //TODO is it necessary here?
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/log/log.h>
37 #include <dpl/wrt-dao-ro/global_config.h>
38 #include "wac_widget_id.h"
40 #include <vcore/Certificate.h>
41 #include <vcore/SignatureReader.h>
42 #include <vcore/SignatureFinder.h>
43 #include <vcore/WrtSignatureValidator.h>
44 #include <dpl/utils/wrt_global_settings.h>
45 #include <dpl/wrt-dao-ro/global_dao_read_only.h>
47 #include <ITapiModem.h>
48 #include <tapi_common.h>
50 using namespace ValidationCore;
51 using namespace WrtDB;
55 WidgetCertificateData toWidgetCertificateData(const SignatureData &data,
58 WidgetCertificateData result;
60 result.chainId = data.getSignatureNumber();
61 LogDebug("result.chainId : " << result.chainId);
63 result.owner = data.isAuthorSignature() ?
64 WidgetCertificateData::AUTHOR : WidgetCertificateData::DISTRIBUTOR;
67 WidgetCertificateData::ROOT : WidgetCertificateData::ENDENTITY;
69 CertificatePtr certificate;
72 certificate = data.getRootCaCertificatePtr();
74 certificate = data.getEndEntityCertificatePtr();
77 Assert(certificate && !certificate->getCommonName().IsNull() &&
78 "CommonName is Null");
80 result.strCommonName = *certificate->getCommonName();
82 result.strMD5Fingerprint = std::string("md5 ") +
83 Certificate::FingerprintToColonHex(
84 certificate->getFingerprint(Certificate::FINGERPRINT_MD5));
86 result.strSHA1Fingerprint = std::string("sha-1 ") +
87 Certificate::FingerprintToColonHex(
88 certificate->getFingerprint(Certificate::FINGERPRINT_SHA1));
93 CertificatePtr getOldAuthorSignerCertificate(DPL::String appid)
95 WidgetDAOReadOnly dao(appid);
96 CertificateChainList chainList = dao.getWidgetCertificate(SIGNATURE_AUTHOR);
98 FOREACH(it, chainList)
100 ValidationCore::CertificateCollection chain;
101 if (false == chain.load(*it)) {
102 LogError("Chain is broken");
106 LogError("Chain failed at sorting");
109 ValidationCore::CertificateList list = chain.getCertificateList();
113 if (!(*cert)->isRootCert() && !(*cert)->isCA()) {
118 return CertificatePtr(NULL);
120 } // namespace anonymous
123 namespace WidgetInstall {
124 TaskCertify::TaskCertify(InstallerContext &inCont) :
125 DPL::TaskDecl<TaskCertify>(this),
126 m_contextData(inCont)
128 AddStep(&TaskCertify::stepSignature);
129 // certi comparison determines whether the update.
130 if (true == m_contextData.isUpdateMode) {
131 AddStep(&TaskCertify::stepVerifyUpdate);
133 AddStep(&TaskCertify::stepFinalize);
136 void TaskCertify::processDistributorSignature(const SignatureData &data)
138 // this signature is verified -
139 // no point in check domain WAC_ROOT and WAC_RECOGNIZED
140 m_contextData.wacSecurity.setDistributorSigned(true);
142 CertificateCollection collection;
143 collection.load(data.getCertList());
144 Assert(collection.sort() &&
145 "Certificate collection can't sort");
147 Assert(collection.isChain() &&
148 "Certificate collection is not able to create chain. "
149 "It is not possible to verify this signature.");
151 m_contextData.wacSecurity.getCertificateChainListRef().push_back(
154 if (data.getSignatureNumber() == 1) {
155 m_contextData.wacSecurity.getCertificateListRef().push_back(
156 toWidgetCertificateData(data, true));
157 m_contextData.wacSecurity.getCertificateListRef().push_back(
158 toWidgetCertificateData(data, false));
162 void TaskCertify::processAuthorSignature(const SignatureData &data)
164 using namespace ValidationCore;
165 LogInfo("DNS Identity match!");
166 // this signature is verified or widget is distributor signed
167 m_contextData.wacSecurity.setAuthorCertificatePtr(data.getEndEntityCertificatePtr());
168 CertificatePtr test = m_contextData.wacSecurity.getAuthorCertificatePtr();
170 m_contextData.wacSecurity.getCertificateListRef().push_back(
171 toWidgetCertificateData(data, true));
172 m_contextData.wacSecurity.getCertificateListRef().push_back(
173 toWidgetCertificateData(data, false));
175 // match widget_id with one from dns identity set
176 WacWidgetId widgetId(m_contextData.widgetConfig.configInfo.widget_id);
178 CertificatePtr cert = data.getEndEntityCertificatePtr();
180 Certificate::AltNameSet dnsIdentity = cert->getAlternativeNameDNS();
182 CertificateCollection collection;
183 collection.load(data.getCertList());
185 Assert(collection.isChain() &&
186 "Certificate collection is not able to create chain. "
187 "It is not possible to verify this signature.");
189 m_contextData.wacSecurity.getAuthorsCertificateChainListRef().push_back(
192 FOREACH(it, dnsIdentity){
193 if (widgetId.matchHost(*it)) {
194 m_contextData.wacSecurity.setRecognized(true);
200 void TaskCertify::getSignatureFiles(std::string path, SignatureFileInfoSet& file)
202 SignatureFileInfoSet signatureFiles;
203 SignatureFinder signatureFinder(path);
204 if (SignatureFinder::NO_ERROR != signatureFinder.find(file)) {
205 LogError("Error in Signature Finder : " << path);
206 ThrowMsg(Exceptions::SignatureNotFound,
207 "Error openig temporary widget directory");
211 void TaskCertify::stepSignature()
213 LogInfo("================ Step: <<Signature>> ENTER ===============");
215 std::string widgetPath;
216 widgetPath = m_contextData.locations->getTemporaryPackageDir() + "/";
218 SignatureFileInfoSet signatureFiles;
221 getSignatureFiles(widgetPath, signatureFiles);
223 if (signatureFiles.size() <= 0) {
224 widgetPath = m_contextData.locations->getTemporaryPackageDir() +
225 WrtDB::GlobalConfig::GetWidgetSrcPath() + "/";
226 if (0 == access(widgetPath.c_str(), F_OK)) {
227 getSignatureFiles(widgetPath, signatureFiles);
230 } Catch(Exceptions::SignatureNotFound) {
231 ReThrowMsg(Exceptions::SignatureNotFound, widgetPath);
234 SignatureFileInfoSet::reverse_iterator iter = signatureFiles.rbegin();
235 LogInfo("Number of signatures: " << signatureFiles.size());
237 bool complianceMode = GlobalDAOReadOnly::getComplianceMode();
239 for (; iter != signatureFiles.rend(); ++iter) {
240 LogInfo("Checking signature with id=" << iter->getFileNumber());
241 SignatureData data(widgetPath + iter->getFileName(),
242 iter->getFileNumber());
246 xml.initialize(data, GlobalConfig::GetSignatureXmlSchema());
249 WrtSignatureValidator::AppType appType =
250 WrtSignatureValidator::WAC20;
252 if (m_contextData.widgetConfig.webAppType ==
253 APP_TYPE_TIZENWEBAPP)
255 appType = WrtSignatureValidator::TIZEN;
258 WrtSignatureValidator::Result result;
260 WrtSignatureValidator validator(
263 OCSPTestModeEnabled(),
265 CrlTestModeEnabled(),
268 result = validator.check(data, widgetPath);
270 if (m_contextData.mode.installTime
271 == InstallMode::InstallTime::PRELOAD)
273 result = WrtSignatureValidator::SIGNATURE_VERIFIED;
276 if (result == WrtSignatureValidator::SIGNATURE_REVOKED) {
277 LogWarning("Certificate is REVOKED");
278 ThrowMsg(Exceptions::CertificateExpired,
279 "Certificate is REVOKED");
282 if (result == WrtSignatureValidator::SIGNATURE_INVALID &&
283 iter->getFileNumber() <= 1) {
284 LogWarning("Signature is INVALID");
285 // TODO change exception name
286 ThrowMsg(Exceptions::SignatureInvalid,
290 if (data.isAuthorSignature()) {
291 if (result == WrtSignatureValidator::SIGNATURE_VERIFIED ) {
292 processAuthorSignature(data);
295 if (result != WrtSignatureValidator::SIGNATURE_INVALID) {
296 processDistributorSignature(data);
299 } Catch(ParserSchemaException::Base) {
300 LogError("Error occured in ParserSchema.");
301 ReThrowMsg(Exceptions::SignatureInvalid,
302 "Error occured in ParserSchema.");
306 if (signatureFiles.empty()) {
307 LogInfo("No signature files has been found.");
310 LogInfo("================ Step: <<Signature>> DONE ================");
312 m_contextData.job->UpdateProgress(
313 InstallerContext::INSTALL_DIGSIG_CHECK,
314 "Widget Signature checked");
317 void TaskCertify::stepFinalize()
319 LogInfo("Step: <<CERTYFYING DONE>>");
321 m_contextData.job->UpdateProgress(
322 InstallerContext::INSTALL_CERT_CHECK,
323 "Widget Certification Check Finished");
326 bool TaskCertify::isTizenWebApp() const
329 if (m_contextData.widgetConfig.webAppType.appType
330 == WrtDB::AppType::APP_TYPE_TIZENWEBAPP)
338 void TaskCertify::stepVerifyUpdate()
340 LogInfo("Step: <<Check Update>>");
341 CertificatePtr newCertificate =
342 m_contextData.wacSecurity.getAuthorCertificatePtr();
343 CertificatePtr oldCertificate =
344 getOldAuthorSignerCertificate(m_contextData.widgetConfig.tzAppid);
346 if (!!newCertificate && !!oldCertificate) {
347 if (0 != newCertificate->getBase64().compare(oldCertificate->getBase64())) {
348 LogDebug("old widget's author signer certificate : " <<
349 oldCertificate->getBase64());
350 LogDebug("new widget's author signer certificate : " <<
351 newCertificate->getBase64());
352 ThrowMsg(Exceptions::NotMatchedCertification,
353 "Author signer certificates doesn't match \
354 between old widget and installing widget");
357 if (!(NULL == newCertificate.Get() && NULL == oldCertificate.Get())) {
358 ThrowMsg(Exceptions::NotMatchedCertification,
359 "Author signer certificates doesn't match \
360 between old widget and installing widget");
364 } //namespace WidgetInstall