From: sangwan.kwon Date: Thu, 3 Nov 2016 07:35:11 +0000 (+0900) Subject: Detach Impl class on SignatureValidator X-Git-Tag: submit/tizen/20161202.021015~6 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=b2616f8b42fcea034df7e77c48643d373ae89bd4;p=platform%2Fcore%2Fsecurity%2Fcert-svc.git Detach Impl class on SignatureValidator [AS-IS] * check(), checkList() is implemented on Impl class. [TO-BE] * check(), checkList() should be implemented on derived class by using baseCheck(), baseCheckList() on BaseValidator. Change-Id: I1d5b81d02e5f576e9c0c47b484e6429d3e9b88fa Signed-off-by: sangwan.kwon --- diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 68ae230..8589ad6 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -52,6 +52,7 @@ SET(VCORE_SOURCES vcore/api.cpp vcore/Base64.cpp + vcore/BaseValidator.cpp vcore/Certificate.cpp vcore/CertificateCollection.cpp vcore/CertificateConfigReader.cpp diff --git a/src/vcore/BaseValidator.cpp b/src/vcore/BaseValidator.cpp new file mode 100644 index 0000000..6917a6d --- /dev/null +++ b/src/vcore/BaseValidator.cpp @@ -0,0 +1,509 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @file BaseValidator.cpp + * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com) + * @author Sangwan Kwon (sangwan.kwon@samsung.com) + * @version 1.0 + * @brief Implementation of based validation protocol. + */ +#include + +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#ifdef TIZEN_PROFILE_MOBILE +#include +#endif + +using namespace ValidationCore::CertStoreId; + +namespace { + +const std::string TOKEN_PREFIX = "http://www.w3.org/ns/widgets-digsig#"; +const std::string TOKEN_ROLE_AUTHOR_URI = TOKEN_PREFIX + "role-author"; +const std::string TOKEN_ROLE_DIST_URI = TOKEN_PREFIX + "role-distributor"; +const std::string TOKEN_PROFILE_URI = TOKEN_PREFIX + "profile"; + +enum class CertTimeStatus : int { + VALID, + NOT_YET, + EXPIRED +}; + +inline time_t _getMidTime(time_t lower, time_t upper) +{ + return (lower >> 1) + (upper >> 1); +} + +inline CertTimeStatus _timeValidation(time_t lower, time_t upper, time_t current) +{ + if (current < lower) + return CertTimeStatus::NOT_YET; + else if (current > upper) + return CertTimeStatus::EXPIRED; + else + return CertTimeStatus::VALID; +} + +inline bool _isTimeStrict(const Set &stores) +{ + return (stores.contains(TIZEN_TEST) || stores.contains(TIZEN_VERIFY)) + ? true : false; +} + +} // namespace anonymous + +namespace ValidationCore { + +BaseValidator::BaseValidator(const SignatureFileInfo &info) : + m_fileInfo(info), + m_disregarded(false) +{ +} + +bool BaseValidator::checkRoleURI(void) +{ + std::string roleURI = m_data.getRoleURI(); + + if (roleURI.empty()) { + LogWarning("URI attribute in Role tag couldn't be empty."); + return false; + } + + if (roleURI != TOKEN_ROLE_AUTHOR_URI && m_data.isAuthorSignature()) { + LogWarning("URI attribute in Role tag does not " + "match with signature filename."); + return false; + } + + if (roleURI != TOKEN_ROLE_DIST_URI && !m_data.isAuthorSignature()) { + LogWarning("URI attribute in Role tag does not " + "match with signature filename."); + return false; + } + + return true; +} + +bool BaseValidator::checkProfileURI(void) +{ + if (TOKEN_PROFILE_URI != m_data.getProfileURI()) { + LogWarning("Profile tag contains unsupported value " + "in URI attribute " << m_data.getProfileURI()); + return false; + } + + return true; +} + +bool BaseValidator::checkObjectReferences(void) +{ + for (const auto &object : m_data.getObjectList()) { + if (!m_data.containObjectReference(object)) { + LogWarning("Signature does not contain reference for object " << object); + return false; + } + } + + return true; +} + +VCerr BaseValidator::additionalCheck(VCerr result) +{ + try { + if (m_pluginHandler.fail()) { + LogInfo("No validator plugin found. Skip additional check."); + return result; + } + + return m_pluginHandler.step(result, m_data); + } catch (...) { + LogError("Exception in additional check by plugin."); + return E_SIG_PLUGIN; + } +} + +VCerr BaseValidator::parseSignature(void) +{ + try { + SignatureReader xml; + xml.initialize(m_data, SIGNATURE_SCHEMA_PATH); + xml.read(m_data); + } catch (ParserSchemaException::CertificateLoaderError &e) { + LogError("Certificate loader error: " << e.DumpToString()); + return E_SIG_INVALID_CERT; + } catch (...) { + LogError("Failed to parse signature file by signature reader."); + return E_SIG_INVALID_FORMAT; + } + + return E_SIG_NONE; +} + +/* + * Make SignatureData by parsing signature file. + * and get certificate chain with attached certificate in signature + */ +VCerr BaseValidator::makeDataBySignature(bool completeWithSystemCert) +{ + LogDebug("Start to make chain."); + m_data = SignatureData(m_fileInfo.getFileName(), m_fileInfo.getFileNumber()); + + if (parseSignature()) { + LogError("Failed to parse signature."); + return E_SIG_INVALID_FORMAT; + } + + if (!checkRoleURI() || !checkProfileURI()) + return E_SIG_INVALID_FORMAT; + + try { + CertificateCollection collection; + // Load Certificates and make chain. + collection.load(m_data.getCertList()); + + if (!collection.sort() || collection.empty()) { + LogError("Certificates do not form valid chain."); + return E_SIG_INVALID_CHAIN; + } + + // Add root certificate to chain. + if (completeWithSystemCert && !collection.completeCertificateChain()) { + if (m_data.isAuthorSignature() || m_data.getSignatureNumber() == 1) { + LogError("Failed to complete cert chain with system cert"); + return E_SIG_INVALID_CHAIN; + } else { + LogDebug("Distributor N's certificate has got " + "unrecognized root CA certificate."); + m_disregarded = true; + } + } + + m_data.setSortedCertificateList(collection.getChain()); + LogDebug("Finish making chain successfully."); + } catch (const CertificateCollection::Exception::Base &e) { + LogError("CertificateCollection exception : " << e.DumpToString()); + return E_SIG_INVALID_CHAIN; + } catch (const std::exception &e) { + LogError("std exception occured : " << e.what()); + return E_SIG_UNKNOWN; + } catch (...) { + LogError("Unknown exception in BaseValidator::makeChainBySignature"); + return E_SIG_UNKNOWN; + } + + return E_SIG_NONE; +} + +VCerr BaseValidator::preStep(void) +{ + // Make chain process. + VCerr result = makeDataBySignature(true); + + if (result != E_SIG_NONE) + return result; + + for (const auto &certptr : m_data.getCertList()) { + auto storeIdSet = createCertificateIdentifier().find(certptr); + if (!storeIdSet.contains(TIZEN_REVOKED)) + continue; + + LogInfo("Revoked certificate: " << certptr->getOneLine()); + return E_SIG_REVOKED; + } + + // Get Identifier from fingerprint original, extention file. + LogDebug("Start to check certificate domain."); + auto certificatePtr = m_data.getCertList().back(); + auto storeIdSet = createCertificateIdentifier().find(certificatePtr); + + // Check root CA certificate has proper domain. + LogDebug("root certificate from " << storeIdSet.typeToString() << " domain"); + if (m_data.isAuthorSignature()) { + if (!storeIdSet.contains(TIZEN_DEVELOPER)) { + LogError("author-signature.xml's root certificate " + "isn't in tizen developer domain."); + return E_SIG_INVALID_CHAIN; + } + } else { + if (storeIdSet.contains(TIZEN_DEVELOPER)) { + LogError("distributor signautre root certificate " + "shouldn't be in tizen developer domain."); + return E_SIG_INVALID_CHAIN; + } + + if (m_data.getSignatureNumber() == 1 && !storeIdSet.isContainsVis()) { + LogError("signature1.xml has got unrecognized root CA certificate."); + return E_SIG_INVALID_CHAIN; + } else if (!storeIdSet.isContainsVis()) { + LogDebug("signatureN.xml has got unrecognized root CA certificate."); + m_disregarded = true; + } + } + + m_data.setStorageType(storeIdSet); + LogDebug("Finish checking certificate domain."); + /* + * We add only Root CA certificate because the rest + * of certificates are present in signature files ;-) + */ + m_context.signatureFile = m_data.getSignatureFileName(); + m_context.certificatePtr = m_data.getCertList().back(); + /* certificate time check */ + time_t lower = m_data.getEndEntityCertificatePtr()->getNotBefore(); + time_t upper = m_data.getEndEntityCertificatePtr()->getNotAfter(); + time_t current = time(NULL); + CertTimeStatus status = _timeValidation(lower, upper, current); + + if (status != CertTimeStatus::VALID) { + LogDebug("Certificate's time is invalid."); + + if (_isTimeStrict(storeIdSet)) + return status == CertTimeStatus::EXPIRED + ? E_SIG_CERT_EXPIRED : E_SIG_CERT_NOT_YET; + + time_t mid = _getMidTime(lower, upper); + LogInfo("Use middle notBeforeTime and notAfterTime." + " lower: " << lower + << " upper: " << upper + << " mid: " << mid + << " current: " << current); + m_context.validationTime = mid; + } + + return E_SIG_NONE; +} + +VCerr BaseValidator::baseCheck(const std::string &contentPath, + bool checkOcsp, + bool checkReferences) +{ + try { + // Make certificate chain, check certificate info + VCerr result = preStep(); + + if (result != E_SIG_NONE) + return result; + + // Since disregard case, uncheck root certs in signatureN.xml + if (!m_data.isAuthorSignature() && m_data.getSignatureNumber() != 1) + m_context.allowBrokenChain = true; + + // XmlSec validate + XmlSecSingleton::Instance().validate(m_context); + // Check reference of 'Object' tag - OID + m_data.setReference(m_context.referenceSet); + + if (!checkObjectReferences()) { + LogWarning("Failed to check Object References"); + return E_SIG_INVALID_REF; + } + + // Check reference's existence + if (checkReferences) { + ReferenceValidator fileValidator(contentPath); + + if (ReferenceValidator::NO_ERROR != fileValidator.checkReferences(m_data)) { + LogWarning("Invalid package - file references broken"); + return E_SIG_INVALID_REF; + } + } + + // Check OCSP + if (checkOcsp && Ocsp::check(m_data) == Ocsp::Result::REVOKED) { + LogError("Certificate is Revoked by OCSP server."); + return E_SIG_REVOKED; + } + + LogDebug("Signature validation check done successfully "); + } catch (const CertificateCollection::Exception::Base &e) { + LogError("CertificateCollection exception : " << e.DumpToString()); + return E_SIG_INVALID_CHAIN; + } catch (const XmlSec::Exception::InternalError &e) { + LogError("XmlSec internal error : " << e.DumpToString()); + return E_SIG_INVALID_FORMAT; + } catch (const XmlSec::Exception::InvalidFormat &e) { + LogError("XmlSec invalid format : " << e.DumpToString()); + return E_SIG_INVALID_FORMAT; + } catch (const XmlSec::Exception::InvalidSig &e) { + LogError("XmlSec invalid signature : " << e.DumpToString()); + return E_SIG_INVALID_SIG; + } catch (const XmlSec::Exception::OutOfMemory &e) { + LogError("XmlSec out of memory : " << e.DumpToString()); + return E_SIG_OUT_OF_MEM; + } catch (const XmlSec::Exception::Base &e) { + LogError("XmlSec unknown exception : " << e.DumpToString()); + return E_SIG_INVALID_FORMAT; + } catch (const Ocsp::Exception::OcspUnsupported &e) { + LogInfo("Ocsp unsupported : " << e.DumpToString()); + } catch (const Ocsp::Exception::Base &e) { + LogInfo("Ocsp check throw exeption : " << e.DumpToString()); +#ifdef TIZEN_PROFILE_MOBILE + LogInfo("Launch cert-checker."); + try { + if (cchecker_ocsp_request() != 0) + LogError("Load cert-checker failed."); + } catch (const std::exception &e) { + LogError("std exception occured while cchecker running : " << e.what()); + } catch (...) { + LogError("Unknown exception occuured while cchecker running. "); + } +#endif + } catch (const std::exception &e) { + LogError("std exception occured : " << e.what()); + return E_SIG_UNKNOWN; + } catch (...) { + LogError("Unknown exception in BaseValidator::check"); + return E_SIG_UNKNOWN; + } + + return m_disregarded ? E_SIG_DISREGARDED : E_SIG_NONE; +} + +VCerr BaseValidator::baseCheckList(bool checkOcsp, const UriList &uriList) +{ + try { + // Make certificate chain, check certificate info + VCerr result = preStep(); + + if (result != E_SIG_NONE) + return result; + + // XmlSec validate + if (uriList.size() == 0) + XmlSecSingleton::Instance().validateNoHash(m_context); + else + XmlSecSingleton::Instance().validatePartialHash(m_context, uriList); + + if (checkOcsp && Ocsp::check(m_data) == Ocsp::Result::REVOKED) { + LogError("Certificate is Revoked by OCSP server."); + return E_SIG_REVOKED; + } + + LogDebug("Signature validation of check list done successfully "); + } catch (const CertificateCollection::Exception::Base &e) { + LogError("CertificateCollection exception : " << e.DumpToString()); + return E_SIG_INVALID_CHAIN; + } catch (const XmlSec::Exception::InternalError &e) { + LogError("XmlSec internal error : " << e.DumpToString()); + return E_SIG_INVALID_FORMAT; + } catch (const XmlSec::Exception::InvalidFormat &e) { + LogError("XmlSec invalid format : " << e.DumpToString()); + return E_SIG_INVALID_FORMAT; + } catch (const XmlSec::Exception::InvalidSig &e) { + LogError("XmlSec invalid signature : " << e.DumpToString()); + return E_SIG_INVALID_SIG; + } catch (const XmlSec::Exception::OutOfMemory &e) { + LogError("XmlSec out of memory : " << e.DumpToString()); + return E_SIG_OUT_OF_MEM; + } catch (const XmlSec::Exception::Base &e) { + LogError("XmlSec unknown exception : " << e.DumpToString()); + return E_SIG_INVALID_FORMAT; + } catch (const Ocsp::Exception::OcspUnsupported &e) { + LogInfo("Ocsp unsupported : " << e.DumpToString()); + } catch (const Ocsp::Exception::Base &e) { + LogInfo("Ocsp check throw exeption : " << e.DumpToString()); +#ifdef TIZEN_PROFILE_MOBILE + LogInfo("Launch cert-checker."); + try { + if (cchecker_ocsp_request() != 0) + LogError("Load cert-checker failed."); + } catch (const std::exception &e) { + LogError("std exception occured while cchecker running : " << e.what()); + } catch (...) { + LogError("Unknown exception occuured while cchecker running. "); + } +#endif + } catch (...) { + LogError("Unknown exception in BaseValidator::checkList"); + return E_SIG_UNKNOWN; + } + + return m_disregarded ? E_SIG_DISREGARDED : E_SIG_NONE; +} + +VCerr BaseValidator::makeChainBySignature(bool completeWithSystemCert, + CertificateList &certList) +{ + VCerr result = makeDataBySignature(completeWithSystemCert); + + if (result != E_SIG_NONE) + return result; + + certList = m_data.getCertList(); + return E_SIG_NONE; +} + +std::string BaseValidator::errorToString(VCerr code) +{ + switch (code) { + case E_SIG_NONE: + return "Success."; + + case E_SIG_INVALID_FORMAT: + return "Invalid format of signature file."; + + case E_SIG_INVALID_CERT: + return "Invalid format of certificate in signature."; + + case E_SIG_INVALID_CHAIN: + return "Invalid certificate chain with certificate in signature."; + + case E_SIG_INVALID_SIG: + return "Invalid signature. Signed with wrong key, changed signature file or changed package file."; + + case E_SIG_INVALID_REF: + return "Invalid file reference. An unsinged file was found."; + + case E_SIG_CERT_EXPIRED: + return "Certificate in signature was expired."; + + case E_SIG_CERT_NOT_YET: + return "Certificate in signature is not valid yet."; + + case E_SIG_DISREGARDED: + return "Signature validation can be disregarded in some cases."; + + case E_SIG_REVOKED: + return "One of certificate was revoked in certificate chain."; + + case E_SIG_PLUGIN: + return "Failed to load plugin for additional validation check."; + + case E_SIG_OUT_OF_MEM: + return "Out of memory."; + + case E_SIG_UNKNOWN: + return "Unknown error."; + + default: + return m_pluginHandler.errorToString(code); + } +} + +} // namespace ValidationCore diff --git a/src/vcore/BaseValidator.h b/src/vcore/BaseValidator.h new file mode 100644 index 0000000..41e83e1 --- /dev/null +++ b/src/vcore/BaseValidator.h @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * @file BaseValidator.h + * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com) + * @author Sangwan Kwon (sangwan.kwon@samsung.com) + * @version 1.0 + * @brief Implementation of based validation protocol. + */ +#pragma once + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace ValidationCore { + +using UriList = std::list; + +class BaseValidator { +public: + BaseValidator(const SignatureFileInfo &info); + virtual ~BaseValidator() {}; + + VCerr makeChainBySignature(bool completeWithSystemCert, + CertificateList &certList); + std::string errorToString(VCerr code); + +protected: + VCerr baseCheck(const std::string &contentPath, + bool checkOcsp, + bool checkReferences); + VCerr baseCheckList(bool checkOcsp, const UriList &uriList); + VCerr additionalCheck(VCerr result); + + SignatureData m_data; + +private: + VCerr makeDataBySignature(bool completeWithSystemCert); + + VCerr parseSignature(void); + VCerr preStep(void); + bool checkRoleURI(void); + bool checkProfileURI(void); + bool checkObjectReferences(void); + + PluginHandler m_pluginHandler; + SignatureFileInfo m_fileInfo; + XmlSec::XmlSecContext m_context; + bool m_disregarded; +}; + +} // namespace ValidationCore diff --git a/src/vcore/SignatureValidator.cpp b/src/vcore/SignatureValidator.cpp index a130bee..29ef870 100644 --- a/src/vcore/SignatureValidator.cpp +++ b/src/vcore/SignatureValidator.cpp @@ -20,495 +20,34 @@ * @version 1.0 * @brief Implementatin of tizen signature validation protocol. */ - -#include -#include -#include - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - #include - -#ifdef TIZEN_PROFILE_MOBILE -#include -#endif - -using namespace ValidationCore::CertStoreId; - -namespace { - -const std::string TOKEN_PREFIX = "http://www.w3.org/ns/widgets-digsig#"; -const std::string TOKEN_ROLE_AUTHOR_URI = TOKEN_PREFIX + "role-author"; -const std::string TOKEN_ROLE_DIST_URI = TOKEN_PREFIX + "role-distributor"; -const std::string TOKEN_PROFILE_URI = TOKEN_PREFIX + "profile"; - -enum class CertTimeStatus : int { - VALID, - NOT_YET, - EXPIRED -}; - -inline time_t _getMidTime(time_t lower, time_t upper) -{ - return (lower >> 1) + (upper >> 1); -} - -inline CertTimeStatus _timeValidation(time_t lower, time_t upper, time_t current) -{ - if (current < lower) - return CertTimeStatus::NOT_YET; - else if (current > upper) - return CertTimeStatus::EXPIRED; - else - return CertTimeStatus::VALID; -} - -inline bool _isTimeStrict(const Set &stores) -{ - return (stores.contains(TIZEN_TEST) || stores.contains(TIZEN_VERIFY)) - ? true : false; -} - -} // namespace anonymous - +#include namespace ValidationCore { -class SignatureValidator::Impl { +class SignatureValidator::Impl : public BaseValidator { public: Impl(const SignatureFileInfo &info); virtual ~Impl() {}; - VCerr check( - const std::string &contentPath, - bool checkOcsp, - bool checkReferences, - SignatureData &outData); - - VCerr checkList( - bool checkOcsp, - const UriList &uriList, - SignatureData &outData); - - VCerr makeChainBySignature( - bool completeWithSystemCert, - CertificateList &certList); - - std::string errorToString(VCerr code); - -private: - VCerr baseCheck( - const std::string &contentPath, - bool checkOcsp, - bool checkReferences); - - VCerr baseCheckList( - bool checkOcsp, - const UriList &uriList); - - VCerr makeDataBySignature(bool completeWithSystemCert); - VCerr additionalCheck(VCerr result); - - VCerr parseSignature(void); - VCerr preStep(void); - bool checkRoleURI(void); - bool checkProfileURI(void); - bool checkObjectReferences(void); - - PluginHandler m_pluginHandler; - SignatureFileInfo m_fileInfo; - XmlSec::XmlSecContext m_context; - SignatureData m_data; - bool m_disregarded; + VCerr check(const std::string &contentPath, + bool checkOcsp, + bool checkReferences, + SignatureData &outData); + VCerr checkList(bool checkOcsp, + const UriList &uriList, + SignatureData &outData); }; - SignatureValidator::Impl::Impl(const SignatureFileInfo &info) : - m_fileInfo(info), - m_disregarded(false) -{ -} - -bool SignatureValidator::Impl::checkRoleURI(void) -{ - std::string roleURI = m_data.getRoleURI(); - - if (roleURI.empty()) { - LogWarning("URI attribute in Role tag couldn't be empty."); - return false; - } - - if (roleURI != TOKEN_ROLE_AUTHOR_URI && m_data.isAuthorSignature()) { - LogWarning("URI attribute in Role tag does not " - "match with signature filename."); - return false; - } - - if (roleURI != TOKEN_ROLE_DIST_URI && !m_data.isAuthorSignature()) { - LogWarning("URI attribute in Role tag does not " - "match with signature filename."); - return false; - } - - return true; -} - - -bool SignatureValidator::Impl::checkProfileURI(void) -{ - if (TOKEN_PROFILE_URI != m_data.getProfileURI()) { - LogWarning("Profile tag contains unsupported value " - "in URI attribute " << m_data.getProfileURI()); - return false; - } - - return true; -} - -bool SignatureValidator::Impl::checkObjectReferences(void) -{ - for (const auto &object : m_data.getObjectList()) { - if (!m_data.containObjectReference(object)) { - LogWarning("Signature does not contain reference for object " << object); - return false; - } - } - - return true; -} - -VCerr SignatureValidator::Impl::additionalCheck(VCerr result) -{ - try { - if (m_pluginHandler.fail()) { - LogInfo("No validator plugin found. Skip additional check."); - return result; - } - - return m_pluginHandler.step(result, m_data); - } catch (...) { - LogError("Exception in additional check by plugin."); - return E_SIG_PLUGIN; - } -} - -VCerr SignatureValidator::Impl::parseSignature(void) -{ - try { - SignatureReader xml; - xml.initialize(m_data, SIGNATURE_SCHEMA_PATH); - xml.read(m_data); - } catch (ParserSchemaException::CertificateLoaderError &e) { - LogError("Certificate loader error: " << e.DumpToString()); - return E_SIG_INVALID_CERT; - } catch (...) { - LogError("Failed to parse signature file by signature reader."); - return E_SIG_INVALID_FORMAT; - } - - return E_SIG_NONE; -} - -/* - * Make SignatureData by parsing signature file. - * and get certificate chain with attached certificate in signature - */ -VCerr SignatureValidator::Impl::makeDataBySignature(bool completeWithSystemCert) -{ - LogDebug("Start to make chain."); - m_data = SignatureData(m_fileInfo.getFileName(), m_fileInfo.getFileNumber()); - - if (parseSignature()) { - LogError("Failed to parse signature."); - return E_SIG_INVALID_FORMAT; - } - - if (!checkRoleURI() || !checkProfileURI()) - return E_SIG_INVALID_FORMAT; - - try { - CertificateCollection collection; - // Load Certificates and make chain. - collection.load(m_data.getCertList()); - - if (!collection.sort() || collection.empty()) { - LogError("Certificates do not form valid chain."); - return E_SIG_INVALID_CHAIN; - } - - // Add root certificate to chain. - if (completeWithSystemCert && !collection.completeCertificateChain()) { - if (m_data.isAuthorSignature() || m_data.getSignatureNumber() == 1) { - LogError("Failed to complete cert chain with system cert"); - return E_SIG_INVALID_CHAIN; - } else { - LogDebug("Distributor N's certificate has got " - "unrecognized root CA certificate."); - m_disregarded = true; - } - } - - m_data.setSortedCertificateList(collection.getChain()); - LogDebug("Finish making chain successfully."); - } catch (const CertificateCollection::Exception::Base &e) { - LogError("CertificateCollection exception : " << e.DumpToString()); - return E_SIG_INVALID_CHAIN; - } catch (const std::exception &e) { - LogError("std exception occured : " << e.what()); - return E_SIG_UNKNOWN; - } catch (...) { - LogError("Unknown exception in SignatureValidator::makeChainBySignature"); - return E_SIG_UNKNOWN; - } - - return E_SIG_NONE; -} - -VCerr SignatureValidator::Impl::preStep(void) -{ - // Make chain process. - VCerr result = makeDataBySignature(true); - - if (result != E_SIG_NONE) - return result; - - for (const auto &certptr : m_data.getCertList()) { - auto storeIdSet = createCertificateIdentifier().find(certptr); - if (!storeIdSet.contains(TIZEN_REVOKED)) - continue; - - LogInfo("Revoked certificate: " << certptr->getOneLine()); - return E_SIG_REVOKED; - } - - // Get Identifier from fingerprint original, extention file. - LogDebug("Start to check certificate domain."); - auto certificatePtr = m_data.getCertList().back(); - auto storeIdSet = createCertificateIdentifier().find(certificatePtr); - - // Check root CA certificate has proper domain. - LogDebug("root certificate from " << storeIdSet.typeToString() << " domain"); - if (m_data.isAuthorSignature()) { - if (!storeIdSet.contains(TIZEN_DEVELOPER)) { - LogError("author-signature.xml's root certificate " - "isn't in tizen developer domain."); - return E_SIG_INVALID_CHAIN; - } - } else { - if (storeIdSet.contains(TIZEN_DEVELOPER)) { - LogError("distributor signautre root certificate " - "shouldn't be in tizen developer domain."); - return E_SIG_INVALID_CHAIN; - } - - if (m_data.getSignatureNumber() == 1 && !storeIdSet.isContainsVis()) { - LogError("signature1.xml has got unrecognized root CA certificate."); - return E_SIG_INVALID_CHAIN; - } else if (!storeIdSet.isContainsVis()) { - LogDebug("signatureN.xml has got unrecognized root CA certificate."); - m_disregarded = true; - } - } - - m_data.setStorageType(storeIdSet); - LogDebug("Finish checking certificate domain."); - /* - * We add only Root CA certificate because the rest - * of certificates are present in signature files ;-) - */ - m_context.signatureFile = m_data.getSignatureFileName(); - m_context.certificatePtr = m_data.getCertList().back(); - /* certificate time check */ - time_t lower = m_data.getEndEntityCertificatePtr()->getNotBefore(); - time_t upper = m_data.getEndEntityCertificatePtr()->getNotAfter(); - time_t current = time(NULL); - CertTimeStatus status = _timeValidation(lower, upper, current); - - if (status != CertTimeStatus::VALID) { - LogDebug("Certificate's time is invalid."); - - if (_isTimeStrict(storeIdSet)) - return status == CertTimeStatus::EXPIRED - ? E_SIG_CERT_EXPIRED : E_SIG_CERT_NOT_YET; - - time_t mid = _getMidTime(lower, upper); - LogInfo("Use middle notBeforeTime and notAfterTime." - " lower: " << lower - << " upper: " << upper - << " mid: " << mid - << " current: " << current); - m_context.validationTime = mid; - } - - return E_SIG_NONE; -} - -VCerr SignatureValidator::Impl::baseCheck( - const std::string &contentPath, - bool checkOcsp, - bool checkReferences) -{ - try { - // Make certificate chain, check certificate info - VCerr result = preStep(); - - if (result != E_SIG_NONE) - return result; - - // Since disregard case, uncheck root certs in signatureN.xml - if (!m_data.isAuthorSignature() && m_data.getSignatureNumber() != 1) - m_context.allowBrokenChain = true; - - // XmlSec validate - XmlSecSingleton::Instance().validate(m_context); - // Check reference of 'Object' tag - OID - m_data.setReference(m_context.referenceSet); - - if (!checkObjectReferences()) { - LogWarning("Failed to check Object References"); - return E_SIG_INVALID_REF; - } - - // Check reference's existence - if (checkReferences) { - ReferenceValidator fileValidator(contentPath); - - if (ReferenceValidator::NO_ERROR != fileValidator.checkReferences(m_data)) { - LogWarning("Invalid package - file references broken"); - return E_SIG_INVALID_REF; - } - } - - // Check OCSP - if (checkOcsp && Ocsp::check(m_data) == Ocsp::Result::REVOKED) { - LogError("Certificate is Revoked by OCSP server."); - return E_SIG_REVOKED; - } - - LogDebug("Signature validation check done successfully "); - } catch (const CertificateCollection::Exception::Base &e) { - LogError("CertificateCollection exception : " << e.DumpToString()); - return E_SIG_INVALID_CHAIN; - } catch (const XmlSec::Exception::InternalError &e) { - LogError("XmlSec internal error : " << e.DumpToString()); - return E_SIG_INVALID_FORMAT; - } catch (const XmlSec::Exception::InvalidFormat &e) { - LogError("XmlSec invalid format : " << e.DumpToString()); - return E_SIG_INVALID_FORMAT; - } catch (const XmlSec::Exception::InvalidSig &e) { - LogError("XmlSec invalid signature : " << e.DumpToString()); - return E_SIG_INVALID_SIG; - } catch (const XmlSec::Exception::OutOfMemory &e) { - LogError("XmlSec out of memory : " << e.DumpToString()); - return E_SIG_OUT_OF_MEM; - } catch (const XmlSec::Exception::Base &e) { - LogError("XmlSec unknown exception : " << e.DumpToString()); - return E_SIG_INVALID_FORMAT; - } catch (const Ocsp::Exception::OcspUnsupported &e) { - LogInfo("Ocsp unsupported : " << e.DumpToString()); - } catch (const Ocsp::Exception::Base &e) { - LogInfo("Ocsp check throw exeption : " << e.DumpToString()); -#ifdef TIZEN_PROFILE_MOBILE - LogInfo("Launch cert-checker."); - try { - if (cchecker_ocsp_request() != 0) - LogError("Load cert-checker failed."); - } catch (const std::exception &e) { - LogError("std exception occured while cchecker running : " << e.what()); - } catch (...) { - LogError("Unknown exception occuured while cchecker running. "); - } -#endif - } catch (const std::exception &e) { - LogError("std exception occured : " << e.what()); - return E_SIG_UNKNOWN; - } catch (...) { - LogError("Unknown exception in SignatureValidator::check"); - return E_SIG_UNKNOWN; - } - - return m_disregarded ? E_SIG_DISREGARDED : E_SIG_NONE; -} - -VCerr SignatureValidator::Impl::baseCheckList( - bool checkOcsp, - const UriList &uriList) + BaseValidator(info) { - try { - // Make certificate chain, check certificate info - VCerr result = preStep(); - - if (result != E_SIG_NONE) - return result; - - // XmlSec validate - if (uriList.size() == 0) - XmlSecSingleton::Instance().validateNoHash(m_context); - else - XmlSecSingleton::Instance().validatePartialHash(m_context, uriList); - - if (checkOcsp && Ocsp::check(m_data) == Ocsp::Result::REVOKED) { - LogError("Certificate is Revoked by OCSP server."); - return E_SIG_REVOKED; - } - - LogDebug("Signature validation of check list done successfully "); - } catch (const CertificateCollection::Exception::Base &e) { - LogError("CertificateCollection exception : " << e.DumpToString()); - return E_SIG_INVALID_CHAIN; - } catch (const XmlSec::Exception::InternalError &e) { - LogError("XmlSec internal error : " << e.DumpToString()); - return E_SIG_INVALID_FORMAT; - } catch (const XmlSec::Exception::InvalidFormat &e) { - LogError("XmlSec invalid format : " << e.DumpToString()); - return E_SIG_INVALID_FORMAT; - } catch (const XmlSec::Exception::InvalidSig &e) { - LogError("XmlSec invalid signature : " << e.DumpToString()); - return E_SIG_INVALID_SIG; - } catch (const XmlSec::Exception::OutOfMemory &e) { - LogError("XmlSec out of memory : " << e.DumpToString()); - return E_SIG_OUT_OF_MEM; - } catch (const XmlSec::Exception::Base &e) { - LogError("XmlSec unknown exception : " << e.DumpToString()); - return E_SIG_INVALID_FORMAT; - } catch (const Ocsp::Exception::OcspUnsupported &e) { - LogInfo("Ocsp unsupported : " << e.DumpToString()); - } catch (const Ocsp::Exception::Base &e) { - LogInfo("Ocsp check throw exeption : " << e.DumpToString()); -#ifdef TIZEN_PROFILE_MOBILE - LogInfo("Launch cert-checker."); - try { - if (cchecker_ocsp_request() != 0) - LogError("Load cert-checker failed."); - } catch (const std::exception &e) { - LogError("std exception occured while cchecker running : " << e.what()); - } catch (...) { - LogError("Unknown exception occuured while cchecker running. "); - } -#endif - } catch (...) { - LogError("Unknown exception in SignatureValidator::checkList"); - return E_SIG_UNKNOWN; - } - - return m_disregarded ? E_SIG_DISREGARDED : E_SIG_NONE; } -VCerr SignatureValidator::Impl::check( - const std::string &contentPath, - bool checkOcsp, - bool checkReferences, - SignatureData &outData) +VCerr SignatureValidator::Impl::check(const std::string &contentPath, + bool checkOcsp, + bool checkReferences, + SignatureData &outData) { VCerr result; result = baseCheck(contentPath, checkOcsp, checkReferences); @@ -529,110 +68,34 @@ VCerr SignatureValidator::Impl::checkList( return result; } -VCerr SignatureValidator::Impl::makeChainBySignature( - bool completeWithSystemCert, - CertificateList &certList) -{ - VCerr result = makeDataBySignature(completeWithSystemCert); - - if (result != E_SIG_NONE) - return result; - - certList = m_data.getCertList(); - return E_SIG_NONE; -} - -std::string SignatureValidator::Impl::errorToString(VCerr code) -{ - switch (code) { - case E_SIG_NONE: - return "Success."; - - case E_SIG_INVALID_FORMAT: - return "Invalid format of signature file."; - - case E_SIG_INVALID_CERT: - return "Invalid format of certificate in signature."; - - case E_SIG_INVALID_CHAIN: - return "Invalid certificate chain with certificate in signature."; - - case E_SIG_INVALID_SIG: - return "Invalid signature. Signed with wrong key, changed signature file or changed package file."; - - case E_SIG_INVALID_REF: - return "Invalid file reference. An unsinged file was found."; - - case E_SIG_CERT_EXPIRED: - return "Certificate in signature was expired."; - - case E_SIG_CERT_NOT_YET: - return "Certificate in signature is not valid yet."; - - case E_SIG_DISREGARDED: - return "Signature validation can be disregarded in some cases."; - - case E_SIG_REVOKED: - return "One of certificate was revoked in certificate chain."; - - case E_SIG_PLUGIN: - return "Failed to load plugin for additional validation check."; - - case E_SIG_OUT_OF_MEM: - return "Out of memory."; - - case E_SIG_UNKNOWN: - return "Unknown error."; - - default: - return m_pluginHandler.errorToString(code); - } -} - - SignatureValidator::SignatureValidator(const SignatureFileInfo &info) { - std::unique_ptr impl(new(std::nothrow) SignatureValidator::Impl(info)); + using SVImpl = SignatureValidator::Impl; + std::unique_ptr impl(new(std::nothrow) SVImpl(info)); m_pImpl = std::move(impl); } -SignatureValidator::~SignatureValidator() {} - -std::string SignatureValidator::errorToString(VCerr code) -{ - if (!m_pImpl) - return "out of memory. error."; - return m_pImpl->errorToString(code); -} +SignatureValidator::~SignatureValidator() {} -VCerr SignatureValidator::check( - const std::string &contentPath, - bool checkOcsp, - bool checkReferences, - SignatureData &outData) +VCerr SignatureValidator::check(const std::string &contentPath, + bool checkOcsp, + bool checkReferences, + SignatureData &outData) { if (!m_pImpl) return E_SIG_OUT_OF_MEM; - return m_pImpl->check( - contentPath, - checkOcsp, - checkReferences, - outData); + return m_pImpl->check(contentPath, checkOcsp, checkReferences, outData); } -VCerr SignatureValidator::checkList( - bool checkOcsp, - const UriList &uriList, - SignatureData &outData) +VCerr SignatureValidator::checkList(bool checkOcsp, + const UriList &uriList, + SignatureData &outData) { if (!m_pImpl) return E_SIG_OUT_OF_MEM; - return m_pImpl->checkList( - checkOcsp, - uriList, - outData); + return m_pImpl->checkList(checkOcsp, uriList, outData); } VCerr SignatureValidator::makeChainBySignature( @@ -645,4 +108,12 @@ VCerr SignatureValidator::makeChainBySignature( return m_pImpl->makeChainBySignature(completeWithSystemCert, certList); } +std::string SignatureValidator::errorToString(VCerr code) +{ + if (!m_pImpl) + return "out of memory. error."; + + return m_pImpl->errorToString(code); +} + } // namespace ValidationCore diff --git a/src/vcore/SignatureValidator.h b/src/vcore/SignatureValidator.h index 1c818a1..6541180 100644 --- a/src/vcore/SignatureValidator.h +++ b/src/vcore/SignatureValidator.h @@ -71,24 +71,21 @@ public: SignatureValidator(const SignatureValidator &) = delete; const SignatureValidator &operator=(const SignatureValidator &) = delete; - VCerr check( - const std::string &contentPath, - bool checkOcsp, - bool checkReferences, - SignatureData &outData); + VCerr check(const std::string &contentPath, + bool checkOcsp, + bool checkReferences, + SignatureData &outData); - VCerr checkList( - bool checkOcsp, - const UriList &uriList, - SignatureData &outData); + VCerr checkList(bool checkOcsp, + const UriList &uriList, + SignatureData &outData); /* * @Remarks : cert list isn't completed with self-signed root CA system cert * if completeWithSystemCert is false. */ - VCerr makeChainBySignature( - bool completeWithSystemCert, - CertificateList &certList); + VCerr makeChainBySignature(bool completeWithSystemCert, + CertificateList &certList); std::string errorToString(int code);