From fd8d5aa19442aecb276f9287cb7409ce217b5096 Mon Sep 17 00:00:00 2001 From: Kyungwook Tak Date: Tue, 24 Nov 2015 17:01:16 +0900 Subject: [PATCH] Refactor XmlsecAdaptor class Change-Id: Icd2b43ad4e48629b62f478abd949c6105359d9aa Signed-off-by: Kyungwook Tak --- vcore/vcore/SignatureValidator.cpp | 60 +++-- vcore/vcore/ValidatorCommon.h | 100 -------- vcore/vcore/XmlsecAdapter.cpp | 464 +++++++++++++++---------------------- vcore/vcore/XmlsecAdapter.h | 90 ++++--- 4 files changed, 262 insertions(+), 452 deletions(-) delete mode 100644 vcore/vcore/ValidatorCommon.h diff --git a/vcore/vcore/SignatureValidator.cpp b/vcore/vcore/SignatureValidator.cpp index 5dc2f07..ec3a1f2 100644 --- a/vcore/vcore/SignatureValidator.cpp +++ b/vcore/vcore/SignatureValidator.cpp @@ -205,6 +205,9 @@ VCerr SignatureValidator::Impl::parseSignature(void) 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; @@ -276,11 +279,10 @@ VCerr SignatureValidator::Impl::preStep(void) m_disregarded = true; } } else { - LogDebug("signaturefile name = " << m_data.getSignatureFileName()); if (storeIdSet.contains(TIZEN_DEVELOPER)) { - LogError("distributor has author level siganture! " - "Signature will be disregarded."); - return E_SIG_INVALID_FORMAT; + LogError("distributor should not have developer set: " + << m_data.getSignatureFileName()); + return E_SIG_INVALID_CHAIN; } if (m_data.getSignatureNumber() == 1 && !storeIdSet.isContainsVis()) { @@ -333,10 +335,7 @@ VCerr SignatureValidator::Impl::baseCheck( return result; if (!m_data.isAuthorSignature()) { - if (XmlSec::NO_ERROR != XmlSecSingleton::Instance().validate(&m_context)) { - LogWarning("Installation break - invalid package!"); - return E_SIG_INVALID_FORMAT; - } + XmlSecSingleton::Instance().validate(m_context); m_data.setReference(m_context.referenceSet); if (!checkObjectReferences()) { @@ -363,8 +362,20 @@ VCerr SignatureValidator::Impl::baseCheck( } 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 exception : " << e.DumpToString()); + LogError("XmlSec unknown exception : " << e.DumpToString()); return E_SIG_INVALID_FORMAT; } catch (const Ocsp::Exception::Base &e) { LogInfo("OCSP will be handled by cert-checker later. : " << e.DumpToString()); @@ -395,18 +406,10 @@ VCerr SignatureValidator::Impl::baseCheckList( if (result != E_SIG_NONE) return result; - if (uriList.size() == 0) { - if (XmlSec::NO_ERROR != XmlSecSingleton::Instance().validateNoHash(&m_context)) { - LogWarning("Installation break - invalid package! >> validateNoHash"); - return E_SIG_INVALID_FORMAT; - } - } else { - XmlSecSingleton::Instance().setPartialHashList(uriList); - if (XmlSec::NO_ERROR != XmlSecSingleton::Instance().validatePartialHash(&m_context)) { - LogWarning("Installation break - invalid package! >> validatePartialHash"); - return E_SIG_INVALID_FORMAT; - } - } + if (uriList.size() == 0) + XmlSecSingleton::Instance().validateNoHash(m_context); + else + XmlSecSingleton::Instance().validatePartialHash(m_context, uriList); m_data.setReference(m_context.referenceSet); /* @@ -434,8 +437,20 @@ VCerr SignatureValidator::Impl::baseCheckList( } 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 exception : " << e.DumpToString()); + LogError("XmlSec unknown exception : " << e.DumpToString()); return E_SIG_INVALID_FORMAT; } catch (const Ocsp::Exception::Base &e) { LogInfo("OCSP will be handled by cert-checker later. : " << e.DumpToString()); @@ -580,4 +595,3 @@ VCerr SignatureValidator::makeChainBySignature( } } // namespace ValidationCore - diff --git a/vcore/vcore/ValidatorCommon.h b/vcore/vcore/ValidatorCommon.h deleted file mode 100644 index 05f2b7c..0000000 --- a/vcore/vcore/ValidatorCommon.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (c) 2011 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 ValidatorCommon.h - * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com) - * @version 1.0 - * @brief This file contais definictions of common types used in ValidationCore. - */ -#ifndef _VALIDATORCOMMON_H_ -#define _VALIDATORCOMMON_H_ - -#include -#include -#include - -namespace ValidationCore { - -/* - * base deleter func - */ -template -struct ValidatorCoreUniversalFree {}; - -// Template Specialization -#define VC_DECLARE_DELETER(type, function) \ - template <> \ - struct ValidatorCoreUniversalFree { \ - void universal_free(type *ptr){ \ - if (ptr) { \ - function(ptr); } \ - } \ - }; - -template -class AutoPtr -{ - public: - AutoPtr(T *ptr) : - m_data(ptr) - { - } - - AutoPtr(const AutoPtr &second) - { - m_data = second.m_data; - second.m_data = 0; - } - - AutoPtr & operator=(const AutoPtr &second) - { - if (this != &second) { - ValidatorCoreUniversalFree deleter; - deleter.universal_free(m_data); - m_data = second.m_data; - second.m_data = 0; - } - return *this; - } - - /** - * overloaded -> operator, so smart ptr could act as ordinary ptr - */ - T* operator->() - { - return m_data; - } - - ~AutoPtr() - { - ValidatorCoreUniversalFree deleter; - deleter.universal_free(m_data); - } - - /** - * get internal pointer - */ - T* get(void) - { - return m_data; - } - - private: - mutable T *m_data; -}; -} // namespace ValidationCore - -#endif // _VALIDATORCOMMON_H_ diff --git a/vcore/vcore/XmlsecAdapter.cpp b/vcore/vcore/XmlsecAdapter.cpp index 6f3c8e7..e77a5d7 100644 --- a/vcore/vcore/XmlsecAdapter.cpp +++ b/vcore/vcore/XmlsecAdapter.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * Copyright (c) 2015 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. @@ -16,11 +16,12 @@ /* * @file XmlsecAdapter.cpp * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com) - * @version 1.0 + * @version 2.0 * @brief */ #include #include +#include #include #include @@ -28,7 +29,7 @@ #ifndef XMLSEC_NO_XSLT #include -#endif /* XMLSEC_NO_XSLT */ +#endif #include #include @@ -40,16 +41,46 @@ #include #include +#include #include -#include - -#include IMPLEMENT_SINGLETON(ValidationCore::XmlSec) namespace { +template +struct CustomPtr { + Type ptr; + std::function deleter; + + CustomPtr() = delete; + + explicit CustomPtr(Type in, std::function d) + : ptr(in) + , deleter(d) {} + + ~CustomPtr() + { + deleter(ptr); + } + + inline Type get(void) const + { + return ptr; + } + + inline Type operator->() const + { + return ptr; + } + + inline bool operator!() const + { + return (ptr == nullptr) ? true : false; + } +}; + struct FileWrapper { FileWrapper(void *argFile, bool argReleased) : file(argFile) @@ -62,24 +93,24 @@ struct FileWrapper { } // anonymous namespace namespace ValidationCore { -VC_DECLARE_DELETER(xmlSecKeysMngr, xmlSecKeysMngrDestroy) -static const char* DIGEST_MD5 = "md5"; +static const std::string DIGEST_MD5 = "md5"; std::string XmlSec::s_prefixPath; int XmlSec::fileMatchCallback(const char *filename) { std::string path = s_prefixPath + filename; + return xmlFileMatch(path.c_str()); } -void* XmlSec::fileOpenCallback(const char *filename) +void *XmlSec::fileOpenCallback(const char *filename) { std::string path = s_prefixPath + filename; - // LogDebug("Xmlsec opening : " << path); - return new FileWrapper(xmlFileOpen(path.c_str()),false); + LogDebug("Xmlsec opening : " << path); + return new FileWrapper(xmlFileOpen(path.c_str()), false); } int XmlSec::fileReadCallback(void *context, @@ -87,14 +118,15 @@ int XmlSec::fileReadCallback(void *context, int len) { FileWrapper *fw = static_cast(context); - if (fw->released) { + if (fw->released) return 0; - } + int output = xmlFileRead(fw->file, buffer, len); if (output == 0) { fw->released = true; xmlFileClose(fw->file); } + return output; } @@ -102,52 +134,51 @@ int XmlSec::fileCloseCallback(void *context) { FileWrapper *fw = static_cast(context); int output = 0; - if (!(fw->released)) { + if (!fw->released) output = xmlFileClose(fw->file); - } + delete fw; + return output; } -void XmlSec::fileExtractPrefix(XmlSecContext *context) +void XmlSec::fileExtractPrefix(XmlSecContext &context) { - if (!(context->workingDirectory.empty())) { - s_prefixPath = context->workingDirectory; + if (!context.workingDirectory.empty()) { + s_prefixPath = context.workingDirectory; return; } - s_prefixPath = context->signatureFile; + s_prefixPath = context.signatureFile; size_t pos = s_prefixPath.rfind('/'); - if (pos == std::string::npos) { + if (pos == std::string::npos) s_prefixPath.clear(); - } else { + else s_prefixPath.erase(pos + 1, std::string::npos); - } } -void LogDebugPrint(const char* file, int line, const char* func, - const char* errorObject, const char* errorSubject, - int reason, const char* msg) +void LogDebugPrint(const char *file, + int line, + const char *func, + const char *errorObject, + const char *errorSubject, + int reason, + const char *msg) { - char total[1024]; - snprintf(total, sizeof(total), "[%s:%d][%s] : [%s] : [%s] : [%s]", file, line, func, errorObject, errorSubject, msg); + std::stringstream ss; + ss << "[" << file << ":" << line << "][" << func + << "] : [" << errorObject << "] : [" << errorSubject + << "] : [" << msg << "]" << std::endl; - if(reason != 256) - { - fprintf(stderr, "## [validate error]: %s\n", total); - LogError(" " << total); - } + if (reason == 256) + LogError(ss.str()); else - { - LogDebug(" " << total); - } + LogDebug(ss.str()); } -XmlSec::XmlSec() : - m_initialized(false), - m_noHash(false), - m_partialHash(false), - m_pList(NULL) +XmlSec::XmlSec() + : m_initialized(false) + , m_pList(nullptr) { LIBXML_TEST_VERSION xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS; @@ -156,14 +187,11 @@ XmlSec::XmlSec() : xmlIndentTreeOutput = 1; #endif - if (xmlSecInit() < 0) { - LogError("Xmlsec initialization failed."); + if (xmlSecInit() < 0) ThrowMsg(Exception::InternalError, "Xmlsec initialization failed."); - } if (xmlSecCheckVersion() != 1) { xmlSecShutdown(); - LogError("Loaded xmlsec library version is not compatible."); ThrowMsg(Exception::InternalError, "Loaded xmlsec library version is not compatible."); } @@ -180,16 +208,14 @@ XmlSec::XmlSec() : } #endif - if (xmlSecCryptoAppInit(NULL) < 0) { + if (xmlSecCryptoAppInit(nullptr) < 0) { xmlSecShutdown(); - LogError("Crypto initialization failed."); ThrowMsg(Exception::InternalError, "Crypto initialization failed."); } if (xmlSecCryptoInit() < 0) { xmlSecCryptoAppShutdown(); xmlSecShutdown(); - LogError("Xmlsec-crypto initialization failed."); ThrowMsg(Exception::InternalError, "Xmlsec-crypto initialization failed."); } @@ -197,45 +223,25 @@ XmlSec::XmlSec() : m_initialized = true; } -void XmlSec::deinitialize(void) +XmlSec::~XmlSec() { - Assert(m_initialized); + if (m_initialized) + return; - /* Shutdown xmlsec-crypto library */ xmlSecCryptoShutdown(); - - /* Shutdown crypto library */ xmlSecCryptoAppShutdown(); - - /* Shutdown xmlsec library */ xmlSecShutdown(); - /* Shutdown libxslt/libxml */ #ifndef XMLSEC_NO_XSLT xsltCleanupGlobals(); -#endif /* XMLSEC_NO_XSLT */ +#endif s_prefixPath.clear(); m_initialized = false; } -XmlSec::~XmlSec() +void XmlSec::validateFile(XmlSecContext &context, xmlSecKeysMngrPtr mngrPtr) { - m_noHash= false; - m_partialHash = false; - if (m_initialized) { - deinitialize(); - } -} - -XmlSec::Result XmlSec::validateFile(XmlSecContext *context, - xmlSecKeysMngrPtr mngr) -{ - xmlDocPtr doc = NULL; - xmlNodePtr node = NULL; - xmlSecDSigCtxPtr dsigCtx = NULL; - int size, res = -1; - fileExtractPrefix(context); LogDebug("Prefix path : " << s_prefixPath); @@ -247,266 +253,168 @@ XmlSec::Result XmlSec::validateFile(XmlSecContext *context, fileReadCallback, fileCloseCallback); - /* load file */ - doc = xmlParseFile(context->signatureFile.c_str()); - if ((doc == NULL) || (xmlDocGetRootElement(doc) == NULL)) { - LogWarning("Unable to parse file " << context->signatureFile); - goto done; - } + CustomPtr docPtr(xmlParseFile(context.signatureFile.c_str()), xmlFreeDoc); + if (!docPtr || xmlDocGetRootElement(docPtr.get()) == nullptr) + ThrowMsg(Exception::InvalidFormat, + "Unable to parse sig xml file: " << context.signatureFile); - /* find start node */ - node = xmlSecFindNode(xmlDocGetRootElement( - doc), xmlSecNodeSignature, xmlSecDSigNs); - if (node == NULL) { - LogWarning("Start node not found in " << context->signatureFile); - goto done; - } + xmlNodePtr node = xmlSecFindNode( + xmlDocGetRootElement(docPtr.get()), + xmlSecNodeSignature, + xmlSecDSigNs); + if (node == nullptr) + ThrowMsg(Exception::InvalidFormat, + "Start node not found in " << context.signatureFile); - /* create signature context */ - dsigCtx = xmlSecDSigCtxCreate(mngr); - if (dsigCtx == NULL) { - LogError("Failed to create signature context."); - goto done; - } + CustomPtr dsigCtx(xmlSecDSigCtxCreate(mngrPtr), xmlSecDSigCtxDestroy); + if (!dsigCtx) + ThrowMsg(Exception::OutOfMemory, "Failed to create signature context."); - if (context->allowBrokenChain) { - dsigCtx->keyInfoReadCtx.flags |= - XMLSEC_KEYINFO_FLAGS_ALLOW_BROKEN_CHAIN; - } + if (context.allowBrokenChain) + dsigCtx->keyInfoReadCtx.flags |= XMLSEC_KEYINFO_FLAGS_ALLOW_BROKEN_CHAIN; - if (context->validationTime) { + if (context.validationTime) { LogDebug("Setting validation time."); - dsigCtx->keyInfoReadCtx.certsVerificationTime = context->validationTime; + dsigCtx->keyInfoReadCtx.certsVerificationTime = context.validationTime; } - if( m_noHash == true || m_partialHash == true ) { - LogDebug("SignatureEx start >> "); - if( m_pList == NULL ) { - LogWarning("## [validate]: uriList does not exist" ); - fprintf(stderr, "## [validate]: uriList does not exist\n"); - res = xmlSecDSigCtxVerifyEx(dsigCtx, node, 1, NULL); - } else { - int n = 0; - int i = 0; - - if(m_pList == NULL) - { - LogWarning("## [validate]: uriList does not exist" ); - fprintf(stderr, "## [validate]: uriList does not exist\n"); - res = -1; - goto done; - } + int res; + switch (m_mode) { + case ValidateMode::NORMAL: + res = xmlSecDSigCtxVerify(dsigCtx.get(), node); + break; - n = m_pList->size(); - - char* pList[n + 1]; - std::list::const_iterator itr = m_pList->begin(); - std::string tmpString; - char* uri = NULL; - int len; - - for(; itr != m_pList->end(); ++itr) { - tmpString = (*itr); - uri = (char*)tmpString.c_str(); - len = strlen(uri); - pList[i] = (char*)malloc(len + 1); - memcpy(pList[i], uri, len); - pList[i][len] = '\0'; - fprintf(stderr, "## [validate]: uriList[%d] = %s\n", i, pList[i]); - ++i; - } - pList[n] = '\0'; + case ValidateMode::NO_HASH: + res = xmlSecDSigCtxVerifyEx(dsigCtx.get(), node, 1, nullptr); + break; - res = xmlSecDSigCtxVerifyEx(dsigCtx, node, 0, (void*)pList); - i = 0; - while(pList[i] != NULL) { - free(pList[i]); - ++i; - } - } - - if(res < 0) { - LogError("SignatureEx verify error."); - fprintf(stderr, "## [validate error]: SignatureEx verify error\n"); - res = -1; - goto done; - } - } else { - LogDebug("Signature start >> "); - - /* Verify signature */ - if (xmlSecDSigCtxVerify(dsigCtx, node) < 0) { - LogError("Signature verify error."); - fprintf(stderr, "## [validate error]: Signature verify error\n"); - res = -1; - goto done; - } - } + case ValidateMode::PARTIAL_HASH: + { + size_t n = m_pList->size(); + const char *pList[n + 1] = {0}; - if (dsigCtx->keyInfoReadCtx.flags2 & - XMLSEC_KEYINFO_ERROR_FLAGS_BROKEN_CHAIN) { - LogWarning("XMLSEC_KEYINFO_FLAGS_ALLOW_BROKEN_CHAIN was set to true!"); - LogWarning("Signature contains broken chain!"); - context->errorBrokenChain = true; - } + size_t i = 0; + for (auto uri : *m_pList) + pList[i++] = uri.c_str(); - /* print verification result to stdout */ - if (dsigCtx->status == xmlSecDSigStatusSucceeded) { - LogDebug("Signature is OK"); - res = 0; - } else { - LogDebug("Signature is INVALID"); - res = -1; - goto done; + res = xmlSecDSigCtxVerifyEx(dsigCtx.get(), node, 0, pList); + break; } - - if (dsigCtx->c14nMethod && dsigCtx->c14nMethod->id && - dsigCtx->c14nMethod->id->name) { - // LogInfo("Canonicalization method: " << (reinterpret_cast(dsigCtx->c14nMethod->id->name)).c_str()); + default: + ThrowMsg(Exception::InternalError, "ValidateMode is invalid"); } - size = xmlSecPtrListGetSize(&(dsigCtx->signedInfoReferences)); - for (int i = 0; i < size; ++i) { - xmlSecDSigReferenceCtxPtr dsigRefCtx = - (xmlSecDSigReferenceCtxPtr)xmlSecPtrListGetItem(&(dsigCtx-> - signedInfoReferences), - i); - if (dsigRefCtx && dsigRefCtx->uri) { - if (dsigRefCtx->digestMethod && dsigRefCtx->digestMethod->id && - dsigRefCtx->digestMethod->id->name) { - const char* pDigest = - reinterpret_cast(dsigRefCtx->digestMethod->id - ->name); - std::string strDigest(pDigest); - /*LogInfo("reference digest method: " << (reinterpret_cast(dsigRefCtx->digestMethod->id->name)).c_str());*/ - if (strDigest == DIGEST_MD5) { - LogWarning("MD5 digest method used! Please use sha"); - res = -1; - break; - } - } - context->referenceSet.insert(std::string(reinterpret_cast( - dsigRefCtx->uri))); - } + if (res != 0) + ThrowMsg(Exception::InvalidSig, "Signature verify error."); + + if (dsigCtx->keyInfoReadCtx.flags2 & XMLSEC_KEYINFO_ERROR_FLAGS_BROKEN_CHAIN) { + LogWarning("Signature contains broken chain!"); + context.errorBrokenChain = true; } -done: - m_pList = NULL; - m_noHash = false; - m_partialHash = false; + if (dsigCtx->status != xmlSecDSigStatusSucceeded) + ThrowMsg(Exception::InvalidSig, "Signature status is not succedded."); - /* cleanup */ - if (dsigCtx != NULL) { - xmlSecDSigCtxDestroy(dsigCtx); - } + xmlSecSize refSize = xmlSecPtrListGetSize(&(dsigCtx->signedInfoReferences)); + for (xmlSecSize i = 0; i < refSize; ++i) { + xmlSecDSigReferenceCtxPtr dsigRefCtx = static_cast( + xmlSecPtrListGetItem(&(dsigCtx->signedInfoReferences), i)); - if (doc != NULL) { - xmlFreeDoc(doc); - } + if (!dsigRefCtx || !dsigRefCtx->uri) + continue; + + if (dsigRefCtx->digestMethod + && dsigRefCtx->digestMethod->id + && dsigRefCtx->digestMethod->id->name) { + auto digest = reinterpret_cast( + dsigRefCtx->digestMethod->id->name); - if (res) { - return ERROR_INVALID_SIGNATURE; + if (DIGEST_MD5.compare(digest) == 0) + ThrowMsg(Exception::InvalidFormat, + "MD5 digest method used! Please use sha"); + } + + context.referenceSet.emplace(reinterpret_cast(dsigRefCtx->uri)); } - return NO_ERROR; } -void XmlSec::loadDERCertificateMemory(XmlSecContext *context, - xmlSecKeysMngrPtr mngr) +void XmlSec::loadDERCertificateMemory(XmlSecContext &context, xmlSecKeysMngrPtr mngrPtr) { - unsigned char *derCertificate = NULL; - int size = i2d_X509(context->certificatePtr->getX509(), &derCertificate); - - if (!derCertificate) { - LogError("Failed during x509 conversion to der format."); - ThrowMsg(Exception::InternalError, - "Failed during x509 conversion to der format."); - } + std::string derCert; - if (xmlSecCryptoAppKeysMngrCertLoadMemory(mngr, - derCertificate, - size, - xmlSecKeyDataFormatDer, - xmlSecKeyDataTypeTrusted) < 0) { - OPENSSL_free(derCertificate); - LogError("Failed to load der certificate from memory."); + try { + derCert = context.certificatePtr->getDER(); + } catch (Certificate::Exception::Base &e) { ThrowMsg(Exception::InternalError, - "Failed to load der certificate from memory."); + "Failed during x509 conversion to der format: " << e.DumpToString()); } - OPENSSL_free(derCertificate); + if (xmlSecCryptoAppKeysMngrCertLoadMemory( + mngrPtr, + reinterpret_cast(derCert.data()), + reinterpret_cast(derCert.length()), + xmlSecKeyDataFormatDer, + xmlSecKeyDataTypeTrusted) < 0) + ThrowMsg(Exception::InternalError, "Failed to load der cert from memory."); } -void XmlSec::loadPEMCertificateFile(XmlSecContext *context, - xmlSecKeysMngrPtr mngr) +void XmlSec::loadPEMCertificateFile(XmlSecContext &context, xmlSecKeysMngrPtr mngrPtr) { - if (xmlSecCryptoAppKeysMngrCertLoad(mngr, - context->certificatePath.c_str(), - xmlSecKeyDataFormatPem, - xmlSecKeyDataTypeTrusted) < 0) { - LogError("Failed to load PEM certificate from file."); - ThrowMsg(Exception::InternalError, - "Failed to load PEM certificate from file."); - } + if (xmlSecCryptoAppKeysMngrCertLoad( + mngrPtr, + context.certificatePath.c_str(), + xmlSecKeyDataFormatPem, + xmlSecKeyDataTypeTrusted) < 0) + ThrowMsg(Exception::InternalError, "Failed to load PEM cert from file."); } -XmlSec::Result XmlSec::validate(XmlSecContext *context) +void XmlSec::validateInternal(XmlSecContext &context) { - Assert(context); - Assert(!(context->signatureFile.empty())); - Assert(context->certificatePtr.get() || !(context->certificatePath.empty())); + Assert(!context.signatureFile.empty()); + Assert(!!context.certificatePtr || !context.certificatePath.empty()); xmlSecErrorsSetCallback(LogDebugPrint); - if (!m_initialized) { - LogError("XmlSec is not initialized."); + if (!m_initialized) ThrowMsg(Exception::InternalError, "XmlSec is not initialized"); - } - AutoPtr mngr(xmlSecKeysMngrCreate()); + CustomPtr mngrPtr(xmlSecKeysMngrCreate(), xmlSecKeysMngrDestroy); - if (!mngr.get()) { - LogError("Failed to create keys manager."); + if (!mngrPtr) ThrowMsg(Exception::InternalError, "Failed to create keys manager."); - } - if (xmlSecCryptoAppDefaultKeysMngrInit(mngr.get()) < 0) { - LogError("Failed to initialize keys manager."); + if (xmlSecCryptoAppDefaultKeysMngrInit(mngrPtr.get()) < 0) ThrowMsg(Exception::InternalError, "Failed to initialize keys manager."); - } - context->referenceSet.clear(); - if (context->certificatePtr.get()) { - loadDERCertificateMemory(context, mngr.get()); - } + context.referenceSet.clear(); - if (!context->certificatePath.empty()) { - loadPEMCertificateFile(context, mngr.get()); - } + if (!!context.certificatePtr) + loadDERCertificateMemory(context, mngrPtr.get()); + + if (!context.certificatePath.empty()) + loadPEMCertificateFile(context, mngrPtr.get()); - return validateFile(context, mngr.get()); + validateFile(context, mngrPtr.get()); } -XmlSec::Result XmlSec::validateNoHash(XmlSecContext *context) +void XmlSec::validate(XmlSecContext &context) { - xmlSecErrorsSetCallback(LogDebugPrint); - - m_noHash = true; - return validate(context); + m_mode = ValidateMode::NORMAL; + validateInternal(context); } -XmlSec::Result XmlSec::validatePartialHash(XmlSecContext *context) +void XmlSec::validateNoHash(XmlSecContext &context) { - xmlSecErrorsSetCallback(LogDebugPrint); - - m_partialHash = true; - return validate(context); + m_mode = ValidateMode::NO_HASH; + validateInternal(context); } -XmlSec::Result XmlSec::setPartialHashList(const std::list& targetUri) +void XmlSec::validatePartialHash(XmlSecContext &context, const std::list &targetUri) { - xmlSecErrorsSetCallback(LogDebugPrint); + m_mode = ValidateMode::PARTIAL_HASH; + m_pList = &targetUri; - m_pList = (std::list*)&targetUri; - return NO_ERROR; + validateInternal(context); } + } // namespace ValidationCore diff --git a/vcore/vcore/XmlsecAdapter.h b/vcore/vcore/XmlsecAdapter.h index 3c8d94f..7c4d6ab 100644 --- a/vcore/vcore/XmlsecAdapter.h +++ b/vcore/vcore/XmlsecAdapter.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * Copyright (c) 2015 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. @@ -16,11 +16,13 @@ /* * @file XmlSecAdapter.h * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com) - * @version 1.0 + * @version 2.0 * @brief */ -#ifndef _VALIDATION_CORE_XMLSECADAPTER_H_ -#define _VALIDATION_CORE_XMLSECADAPTER_H_ +#pragma once + +#include +#include #include @@ -32,19 +34,15 @@ #include namespace ValidationCore { -class XmlSec : public VcoreDPL::Noncopyable -{ - public: +class XmlSec : public VcoreDPL::Noncopyable { - struct XmlSecContext - { +public: + struct XmlSecContext { /* You _must_ set one of the value: certificatePath or certificate. */ - XmlSecContext() : - validationTime(0), - allowBrokenChain(false), - errorBrokenChain(false) - { - } + XmlSecContext() + : validationTime(0) + , allowBrokenChain(false) + , errorBrokenChain(false) {} /* * Absolute path to signature file. @@ -88,57 +86,47 @@ class XmlSec : public VcoreDPL::Noncopyable ReferenceSet referenceSet; }; - enum Result - { - NO_ERROR, - ERROR_INVALID_SIGNATURE - }; - - class Exception - { - public: + struct Exception { DECLARE_EXCEPTION_TYPE(VcoreDPL::Exception, Base) DECLARE_EXCEPTION_TYPE(Base, InternalError) + DECLARE_EXCEPTION_TYPE(Base, InvalidFormat) + DECLARE_EXCEPTION_TYPE(Base, InvalidSig) + DECLARE_EXCEPTION_TYPE(Base, OutOfMemory) }; - /* - * Context - input/output param. - */ - Result validate(XmlSecContext *context); - Result validateNoHash(XmlSecContext *context); - Result validatePartialHash(XmlSecContext *context); - Result setPartialHashList(const std::list& targetUri); - - protected: + /* context - input/output param. */ + void validate(XmlSecContext &context); + void validateNoHash(XmlSecContext &context); + void validatePartialHash(XmlSecContext &context, const std::list &targetUri); + +protected: XmlSec(); ~XmlSec(); - private: - void deinitialize(void); - void loadDERCertificateMemory(XmlSecContext *context, - xmlSecKeysMngrPtr mngr); - void loadPEMCertificateFile(XmlSecContext *context, - xmlSecKeysMngrPtr mngr); - Result validateFile(XmlSecContext *context, - xmlSecKeysMngrPtr mngr); +private: + enum class ValidateMode : int { + NORMAL, + NO_HASH, + PARTIAL_HASH + }; + ValidateMode m_mode; bool m_initialized; - bool m_noHash; - bool m_partialHash; - std::list* m_pList; + const std::list *m_pList; + + void loadDERCertificateMemory(XmlSecContext &context, xmlSecKeysMngrPtr mngr); + void loadPEMCertificateFile(XmlSecContext &context, xmlSecKeysMngrPtr mngr); + void validateInternal(XmlSecContext &context); + void validateFile(XmlSecContext &context, xmlSecKeysMngrPtr mngr); static std::string s_prefixPath; static int fileMatchCallback(const char *filename); - static void* fileOpenCallback(const char *filename); - static int fileReadCallback(void *context, - char *buffer, - int len); + static void *fileOpenCallback(const char *filename); + static int fileReadCallback(void *context, char *buffer, int len); static int fileCloseCallback(void *context); - static void fileExtractPrefix(XmlSecContext *context); + static void fileExtractPrefix(XmlSecContext &context); }; typedef VcoreDPL::Singleton XmlSecSingleton; } // namespace ValidationCore - -#endif // _VALIDATION_CORE_XMLSECVERIFICATOR_H_ -- 2.7.4