From ea22043ee08662b3f181f7ea0d41c6b9a1d3781f Mon Sep 17 00:00:00 2001 From: "sangwan.kwon" Date: Fri, 23 Sep 2016 09:49:58 +0900 Subject: [PATCH] [C++ API +] Add proxy mode on SignatureValidator * Purpose : Improve signature validation performance. * Key-idea : Reference validation should be done only once on multiple-signatures during signature validation. [Added C++ API] - SignatureValidator::checkAll(bool checkOcsp, bool checkReferences, SignatureDataList &sigDataSet) - SignatureValidator::checkListAll(bool checkOcsp, const UriList &uriList, SignatureDataList &sigDataSet) Change-Id: I6abba2100fecd5fe779f0e7cdd977b6281f74d9c Signed-off-by: sangwan.kwon --- src/vcore/BaseValidator.cpp | 12 +++- src/vcore/BaseValidator.h | 13 ++-- src/vcore/SignatureData.h | 14 +++- src/vcore/SignatureFinder.h | 10 ++- src/vcore/SignatureValidator.cpp | 114 +++++++++++++++++++++++++++++-- src/vcore/SignatureValidator.h | 12 +++- src/vcore/XmlsecAdapter.cpp | 27 +++++++- src/vcore/XmlsecAdapter.h | 16 ++++- tests/vcore/test-signature-validator.cpp | 59 ++++++++++++++++ 9 files changed, 251 insertions(+), 26 deletions(-) diff --git a/src/vcore/BaseValidator.cpp b/src/vcore/BaseValidator.cpp index 6917a6d..1c7ac68 100644 --- a/src/vcore/BaseValidator.cpp +++ b/src/vcore/BaseValidator.cpp @@ -81,8 +81,14 @@ inline bool _isTimeStrict(const Set &stores) namespace ValidationCore { BaseValidator::BaseValidator(const SignatureFileInfo &info) : - m_fileInfo(info), - m_disregarded(false) + m_disregarded(false), + m_fileInfo(info) +{ +} + +BaseValidator::BaseValidator(const std::string &packagePath) : + m_disregarded(false), + m_packagePath(packagePath) { } @@ -171,7 +177,7 @@ VCerr BaseValidator::parseSignature(void) */ VCerr BaseValidator::makeDataBySignature(bool completeWithSystemCert) { - LogDebug("Start to make chain."); + LogDebug("Start to make chain about > " << m_fileInfo.getFileName()); m_data = SignatureData(m_fileInfo.getFileName(), m_fileInfo.getFileNumber()); if (parseSignature()) { diff --git a/src/vcore/BaseValidator.h b/src/vcore/BaseValidator.h index 41e83e1..2a084a7 100644 --- a/src/vcore/BaseValidator.h +++ b/src/vcore/BaseValidator.h @@ -39,8 +39,9 @@ using UriList = std::list; class BaseValidator { public: - BaseValidator(const SignatureFileInfo &info); - virtual ~BaseValidator() {}; + explicit BaseValidator(const SignatureFileInfo &info); + explicit BaseValidator(const std::string &packagePath); + virtual ~BaseValidator() {} VCerr makeChainBySignature(bool completeWithSystemCert, CertificateList &certList); @@ -54,6 +55,11 @@ protected: VCerr additionalCheck(VCerr result); SignatureData m_data; + bool m_disregarded; + std::string m_packagePath; + SignatureFileInfo m_fileInfo; + SignatureFileInfoSet m_fileInfoSet; + XmlSec::XmlSecContext m_context; private: VCerr makeDataBySignature(bool completeWithSystemCert); @@ -65,9 +71,6 @@ private: bool checkObjectReferences(void); PluginHandler m_pluginHandler; - SignatureFileInfo m_fileInfo; - XmlSec::XmlSecContext m_context; - bool m_disregarded; }; } // namespace ValidationCore diff --git a/src/vcore/SignatureData.h b/src/vcore/SignatureData.h index 91b5b21..b3677d4 100644 --- a/src/vcore/SignatureData.h +++ b/src/vcore/SignatureData.h @@ -24,6 +24,7 @@ #include #include +#include #include #include @@ -31,8 +32,18 @@ namespace ValidationCore { +enum SignatureType { + AUTHOR = -1, + DISTRIBUTOR1 = 1, + DISTRIBUTOR2 = 2 +}; // Distributor type can be increase, do not use enum class. + +class SignatureData; + typedef std::set ReferenceSet; +typedef std::set ProxySet; typedef std::list ObjectList; +typedef std::map SignatureDataMap; class SignatureData { public: @@ -69,6 +80,7 @@ public: private: ReferenceSet m_referenceSet; + ProxySet m_proxySet; CertificateList m_certList; //TargetRestriction @@ -90,8 +102,6 @@ private: bool m_certificateSorted; }; -typedef std::set SignatureDataSet; - } // ValidationCore #endif diff --git a/src/vcore/SignatureFinder.h b/src/vcore/SignatureFinder.h index 4fea63a..141a598 100644 --- a/src/vcore/SignatureFinder.h +++ b/src/vcore/SignatureFinder.h @@ -29,9 +29,13 @@ namespace ValidationCore { class SignatureFileInfo { public: - SignatureFileInfo(const std::string &fileName, int num) - : m_fileName(fileName) - , m_fileNumber(num) + SignatureFileInfo() : m_fileName(std::string()), m_fileNumber(-1) + { + } + + SignatureFileInfo(const std::string &fileName, int num) : + m_fileName(fileName), + m_fileNumber(num) {} std::string getFileName() const diff --git a/src/vcore/SignatureValidator.cpp b/src/vcore/SignatureValidator.cpp index 29ef870..87c3672 100644 --- a/src/vcore/SignatureValidator.cpp +++ b/src/vcore/SignatureValidator.cpp @@ -23,12 +23,17 @@ #include #include +#include + +#include + namespace ValidationCore { class SignatureValidator::Impl : public BaseValidator { public: - Impl(const SignatureFileInfo &info); - virtual ~Impl() {}; + explicit Impl(const SignatureFileInfo &info); + explicit Impl(const std::string &packagePath); + virtual ~Impl() {} VCerr check(const std::string &contentPath, bool checkOcsp, @@ -37,6 +42,13 @@ public: VCerr checkList(bool checkOcsp, const UriList &uriList, SignatureData &outData); + + VCerr checkAll(bool checkOcsp, + bool checkReferences, + SignatureDataMap &sigDataMap); + VCerr checkListAll(bool checkOcsp, + const UriList &uriList, + SignatureDataMap &sigDataMap); }; SignatureValidator::Impl::Impl(const SignatureFileInfo &info) : @@ -44,6 +56,16 @@ SignatureValidator::Impl::Impl(const SignatureFileInfo &info) : { } +SignatureValidator::Impl::Impl(const std::string &packagePath) : + BaseValidator(packagePath) +{ + m_context.isProxyMode = true; + + SignatureFinder signatureFinder(m_packagePath); + if (SignatureFinder::NO_ERROR != signatureFinder.find(m_fileInfoSet)) + LogError("Failed to find signature files."); +} + VCerr SignatureValidator::Impl::check(const std::string &contentPath, bool checkOcsp, bool checkReferences, @@ -56,10 +78,9 @@ VCerr SignatureValidator::Impl::check(const std::string &contentPath, return result; } -VCerr SignatureValidator::Impl::checkList( - bool checkOcsp, - const UriList &uriList, - SignatureData &outData) +VCerr SignatureValidator::Impl::checkList(bool checkOcsp, + const UriList &uriList, + SignatureData &outData) { VCerr result; result = baseCheckList(checkOcsp, uriList); @@ -68,6 +89,60 @@ VCerr SignatureValidator::Impl::checkList( return result; } +VCerr SignatureValidator::Impl::checkAll(bool checkOcsp, + bool checkReferences, + SignatureDataMap &sigDataMap) +{ + if (m_fileInfoSet.size() < 2) + return E_SIG_UNKNOWN; // TODO(sangwan.kwon) Add error code (INVALID SIZE) + + VCerr result; + for (const auto &sig : m_fileInfoSet) { + m_fileInfo = sig; + m_disregarded = false; + + result = baseCheck(m_packagePath, checkOcsp, checkReferences); + result = additionalCheck(result); + if (result != E_SIG_NONE) { + LogError("Failed to check on > " << m_fileInfo.getFileName()); + break; + } + sigDataMap.insert(std::make_pair(m_data.getSignatureNumber(), m_data)); + LogDebug("Check done signature > " << m_data.getSignatureNumber()); + for (const auto &certPtr : m_data.getCertList()) + LogDebug(certPtr->getBase64()); + } + + return result; +} + +VCerr SignatureValidator::Impl::checkListAll(bool checkOcsp, + const UriList &uriList, + SignatureDataMap &sigDataMap) +{ + if (m_fileInfoSet.size() < 2) + return E_SIG_UNKNOWN; // TODO(sangwan.kwon) Add error code (INVALID SIZE) + + VCerr result; + for (const auto &sig : m_fileInfoSet) { + m_fileInfo = sig; + m_disregarded = false; + + result = baseCheckList(checkOcsp, uriList); + result = additionalCheck(result); + if (result != E_SIG_NONE) { + LogError("Failed to check on > " << m_fileInfo.getFileName()); + break; + } + sigDataMap.insert(std::make_pair(m_data.getSignatureNumber(), m_data)); + LogDebug("CheckList done signature > " << m_data.getSignatureNumber()); + for (const auto &certPtr : m_data.getCertList()) + LogDebug(certPtr->getBase64()); + } + + return result; +} + SignatureValidator::SignatureValidator(const SignatureFileInfo &info) { using SVImpl = SignatureValidator::Impl; @@ -75,6 +150,13 @@ SignatureValidator::SignatureValidator(const SignatureFileInfo &info) m_pImpl = std::move(impl); } +SignatureValidator::SignatureValidator(const std::string &packagePath) +{ + using SVImpl = SignatureValidator::Impl; + std::unique_ptr impl(new(std::nothrow) SVImpl(packagePath)); + m_pImpl = std::move(impl); +} + SignatureValidator::~SignatureValidator() {} VCerr SignatureValidator::check(const std::string &contentPath, @@ -98,6 +180,26 @@ VCerr SignatureValidator::checkList(bool checkOcsp, return m_pImpl->checkList(checkOcsp, uriList, outData); } +VCerr SignatureValidator::checkAll(bool checkOcsp, + bool checkReferences, + SignatureDataMap &sigDataMap) +{ + if (!m_pImpl) + return E_SIG_OUT_OF_MEM; + + return m_pImpl->checkAll(checkOcsp, checkReferences, sigDataMap); +} + +VCerr SignatureValidator::checkListAll(bool checkOcsp, + const UriList &uriList, + SignatureDataMap &sigDataMap) +{ + if (!m_pImpl) + return E_SIG_OUT_OF_MEM; + + return m_pImpl->checkListAll(checkOcsp, uriList, sigDataMap); +} + VCerr SignatureValidator::makeChainBySignature( bool completeWithSystemCert, CertificateList &certList) diff --git a/src/vcore/SignatureValidator.h b/src/vcore/SignatureValidator.h index 6541180..048f7fa 100644 --- a/src/vcore/SignatureValidator.h +++ b/src/vcore/SignatureValidator.h @@ -26,7 +26,6 @@ #include #include -#include #include #include #include @@ -64,7 +63,8 @@ using UriList = std::list; */ class SignatureValidator { public: - SignatureValidator(const SignatureFileInfo &info); + explicit SignatureValidator(const SignatureFileInfo &info); + explicit SignatureValidator(const std::string &packagePath); virtual ~SignatureValidator(); SignatureValidator() = delete; @@ -75,11 +75,17 @@ public: bool checkOcsp, bool checkReferences, SignatureData &outData); - VCerr checkList(bool checkOcsp, const UriList &uriList, SignatureData &outData); + VCerr checkAll(bool checkOcsp, + bool checkReferences, + SignatureDataMap &sigDataMap); + VCerr checkListAll(bool checkOcsp, + const UriList &uriList, + SignatureDataMap &sigDataMap); + /* * @Remarks : cert list isn't completed with self-signed root CA system cert * if completeWithSystemCert is false. diff --git a/src/vcore/XmlsecAdapter.cpp b/src/vcore/XmlsecAdapter.cpp index e870713..2eb1574 100644 --- a/src/vcore/XmlsecAdapter.cpp +++ b/src/vcore/XmlsecAdapter.cpp @@ -301,10 +301,27 @@ void XmlSec::validateFile(XmlSecContext &context, xmlSecKeysMngrPtr mngrPtr) dsigCtx->keyInfoReadCtx.certsVerificationTime = context.validationTime; } + // Set proxy data to dsigCtx + if (context.isProxyMode && !context.proxySet.empty()) { + LogDebug("Set proxy data to xmlsec1 handle."); + for (auto data : context.proxySet) { + if (!strcmp(data.c_str(), "#prop")) + continue; + + if(xmlSecProxyCtxAdd(&(dsigCtx.get()->proxyCtxPtr), + reinterpret_cast(data.c_str()))) + ThrowMsg(Exception::InternalError, "Failed to add proxy data."); + + } + } + int res; switch (m_mode) { case ValidateMode::NORMAL: { + if (context.isProxyMode) + dsigCtx.get()->flags |= XMLSEC_DSIG_FLAGS_SKIP_PROXY; + res = xmlSecDSigCtxVerify(dsigCtx.get(), node); break; } @@ -318,7 +335,7 @@ void XmlSec::validateFile(XmlSecContext &context, xmlSecKeysMngrPtr mngrPtr) dsigCtx.get()->flags |= XMLSEC_DSIG_FLAGS_CHECK_PROXY; for (auto uri : *m_pList) { if(xmlSecProxyCtxAdd(&(dsigCtx.get()->proxyCtxPtr), - reinterpret_cast(uri.c_str()))) + reinterpret_cast(uri.c_str()))) ThrowMsg(Exception::InternalError, "PARTIAL_HASH mode failed."); } res = xmlSecDSigCtxVerify(dsigCtx.get(), node); @@ -341,8 +358,12 @@ void XmlSec::validateFile(XmlSecContext &context, xmlSecKeysMngrPtr mngrPtr) if (dsigCtx->status != xmlSecDSigStatusSucceeded) ThrowMsg(Exception::InvalidSig, "Signature status is not succedded."); - xmlSecSize refSize = xmlSecPtrListGetSize(&(dsigCtx->signedInfoReferences)); + // Set references for reverse reference check by ReferenceValidator + if (context.isProxyMode) + for (auto &proxy : context.proxySet) + context.referenceSet.insert(proxy); + xmlSecSize refSize = xmlSecPtrListGetSize(&(dsigCtx->signedInfoReferences)); for (xmlSecSize i = 0; i < refSize; ++i) { xmlSecDSigReferenceCtxPtr dsigRefCtx = static_cast( xmlSecPtrListGetItem(&(dsigCtx->signedInfoReferences), i)); @@ -362,6 +383,8 @@ void XmlSec::validateFile(XmlSecContext &context, xmlSecKeysMngrPtr mngrPtr) } context.referenceSet.emplace(reinterpret_cast(dsigRefCtx->uri)); + if (context.isProxyMode) + context.proxySet.emplace(reinterpret_cast(dsigRefCtx->uri)); } } diff --git a/src/vcore/XmlsecAdapter.h b/src/vcore/XmlsecAdapter.h index 10573e7..269ebd9 100644 --- a/src/vcore/XmlsecAdapter.h +++ b/src/vcore/XmlsecAdapter.h @@ -50,7 +50,8 @@ public: XmlSecContext() : validationTime(0) , allowBrokenChain(false) - , errorBrokenChain(false) {} + , errorBrokenChain(false) + , isProxyMode(false) {} /* * Absolute path to signature file. @@ -89,9 +90,20 @@ public: bool errorBrokenChain; /* * Output parameter. - * Reference checked by xmlsec + * Reference checked by xmlsec. */ ReferenceSet referenceSet; + /* + * Input parameter. + * If true, proxy validation mode on and set XMLSEC_DSIG_FLAGS_SKIP_PROXY. + */ + bool isProxyMode; + /* + * Output parameter. + * Reference checked by xmlsec. + * Reuse for proxy valdiation. + */ + ProxySet proxySet; }; struct Exception { diff --git a/tests/vcore/test-signature-validator.cpp b/tests/vcore/test-signature-validator.cpp index cf7c04d..07008f6 100644 --- a/tests/vcore/test-signature-validator.cpp +++ b/tests/vcore/test-signature-validator.cpp @@ -574,6 +574,65 @@ RUNNER_TEST(T00159_negative_tpk_with_nohash) } } +RUNNER_TEST(T00160_positive_checkAll) +{ + SignatureValidator validator(TestData::widget_path); + SignatureDataMap sigDataMap; + VCerr result = validator.checkAll(true, true, sigDataMap); + + RUNNER_ASSERT_MSG(result == E_SIG_NONE, + "sig validation should be success: " + << validator.errorToString(result)); + + /* Below codes is example for client. + * + auto authorSigData = sigDataMap[ValidationCore::SignatureType::AUTHOR]; + for (const auto &certPtr : authorSigData.getCertList()) + std::cout << "Author certificate > " << certPtr->getBase64() << std::endl; + + auto distSigData = sigDataMap[ValidationCore::SignatureType::DISTRIBUTOR1]; + for (const auto &certPtr : distSigData.getCertList()) + std::cout << "Distributor certificate > " + << certPtr->getBase64() << std::endl; + * + */ + +} + +RUNNER_TEST(T00161_positive_checkListAll) +{ + SignatureValidator validator(TestData::tpk_with_userdata_path); + UriList uriList; + uriList.emplace_back("author-siganture.xml"); + uriList.emplace_back("bin/preference"); + uriList.emplace_back("res/edje/pref_buttons_panel.edj"); + uriList.emplace_back("res/edje/pref_edit_panel.edj"); + uriList.emplace_back("res/edje/preference.edj"); + uriList.emplace_back("res/images/icon_delete.png"); + uriList.emplace_back("res/res.xml"); + uriList.emplace_back("shared/res/preference.png"); + uriList.emplace_back("tizen-manifest.xml"); + + SignatureDataMap sigDataMap; + VCerr result = validator.checkListAll(true, uriList, sigDataMap); + RUNNER_ASSERT_MSG(result == E_SIG_NONE, + "sig validation should be success: " + << validator.errorToString(result)); + + /* Below codes is example for client. + * + auto authorSigData = sigDataMap[ValidationCore::SignatureType::AUTHOR]; + for (const auto &certPtr : authorSigData.getCertList()) + std::cout << "Author certificate > " << certPtr->getBase64() << std::endl; + + auto distSigData = sigDataMap[ValidationCore::SignatureType::DISTRIBUTOR1]; + for (const auto &certPtr : distSigData.getCertList()) + std::cout << "Distributor certificate > " + << certPtr->getBase64() << std::endl; + * + */ +} + RUNNER_TEST_GROUP_INIT(T0020_SigVal_errorstring) RUNNER_TEST(T0021) -- 2.7.4