* 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 <sangwan.kwon@samsung.com>
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)
{
}
*/
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()) {
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);
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);
bool checkObjectReferences(void);
PluginHandler m_pluginHandler;
- SignatureFileInfo m_fileInfo;
- XmlSec::XmlSecContext m_context;
- bool m_disregarded;
};
} // namespace ValidationCore
#include <list>
#include <set>
+#include <map>
#include <string>
#include <vcore/Certificate.h>
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<std::string> ReferenceSet;
+typedef std::set<std::string> ProxySet;
typedef std::list<std::string> ObjectList;
+typedef std::map<int, SignatureData> SignatureDataMap;
class SignatureData {
public:
private:
ReferenceSet m_referenceSet;
+ ProxySet m_proxySet;
CertificateList m_certList;
//TargetRestriction
bool m_certificateSorted;
};
-typedef std::set<SignatureData> SignatureDataSet;
-
} // ValidationCore
#endif
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
#include <vcore/SignatureValidator.h>
#include <vcore/BaseValidator.h>
+#include <dpl/log/log.h>
+
+#include <utility>
+
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,
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) :
{
}
+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,
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);
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;
m_pImpl = std::move(impl);
}
+SignatureValidator::SignatureValidator(const std::string &packagePath)
+{
+ using SVImpl = SignatureValidator::Impl;
+ std::unique_ptr<SVImpl> impl(new(std::nothrow) SVImpl(packagePath));
+ m_pImpl = std::move(impl);
+}
+
SignatureValidator::~SignatureValidator() {}
VCerr SignatureValidator::check(const std::string &contentPath,
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)
#include <list>
#include <memory>
-#include <vcore/Certificate.h>
#include <vcore/SignatureData.h>
#include <vcore/SignatureFinder.h>
#include <vcore/Error.h>
*/
class SignatureValidator {
public:
- SignatureValidator(const SignatureFileInfo &info);
+ explicit SignatureValidator(const SignatureFileInfo &info);
+ explicit SignatureValidator(const std::string &packagePath);
virtual ~SignatureValidator();
SignatureValidator() = delete;
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.
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<const xmlChar *>(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;
}
dsigCtx.get()->flags |= XMLSEC_DSIG_FLAGS_CHECK_PROXY;
for (auto uri : *m_pList) {
if(xmlSecProxyCtxAdd(&(dsigCtx.get()->proxyCtxPtr),
- reinterpret_cast<const xmlChar *>(uri.c_str())))
+ reinterpret_cast<const xmlChar *>(uri.c_str())))
ThrowMsg(Exception::InternalError, "PARTIAL_HASH mode failed.");
}
res = xmlSecDSigCtxVerify(dsigCtx.get(), node);
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<xmlSecDSigReferenceCtxPtr>(
xmlSecPtrListGetItem(&(dsigCtx->signedInfoReferences), i));
}
context.referenceSet.emplace(reinterpret_cast<char *>(dsigRefCtx->uri));
+ if (context.isProxyMode)
+ context.proxySet.emplace(reinterpret_cast<char *>(dsigRefCtx->uri));
}
}
XmlSecContext()
: validationTime(0)
, allowBrokenChain(false)
- , errorBrokenChain(false) {}
+ , errorBrokenChain(false)
+ , isProxyMode(false) {}
/*
* Absolute path to signature file.
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 {
}
}
+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)