1 // Copyright (c) 2014 Intel Corporation. All rights reserved.
2 // Copyright (C) 2002-2003 Aleksey Sanin. All Rights Reserved.
4 // Use of this source code is governed by a BSD-style license that can be
5 // found in the LICENSE file.
7 #include "xwalk/application/common/tizen/signature_xmlsec_adaptor.h"
14 #include "base/logging.h"
15 #include "base/file_util.h"
16 #include "base/files/file_path.h"
17 #include "net/cert/x509_certificate.h"
18 #include "libxml/parser.h"
19 #include "xmlsec/crypto.h"
20 #include "xmlsec/io.h"
21 #include "xmlsec/keysmngr.h"
22 #include "xmlsec/xmlsec.h"
23 #include "xmlsec/xmltree.h"
24 #include "xmlsec/xmldsig.h"
25 #ifndef XMLSEC_NO_XSLT
26 #include "libxslt/xslt.h"
27 #endif // XMLSEC_NO_XSLT
31 // TODO(XU): Once tizen platform provide certificate manager util APIs,
32 // we should call API from system to query certificate's file path.
33 class CertificateUtil {
35 static const std::map<std::string, std::string>& certificate_path() {
36 return certificate_path_;
40 static std::map<std::string, std::string> InitCertificatePath() {
41 std::map<std::string, std::string> root_certificates;
42 root_certificates["Tizen Partner-Manufacturer Distributor Root CA"] =
43 "tizen-distributor-root-ca-partner-manufacturer.pem";
44 root_certificates["SLP WebApp Temporary CA"] =
45 "tizen.root.preproduction.cert.pem";
46 root_certificates["Tizen Test Developer Root CA"] =
47 "tizen-developer-root-ca.pem";
48 root_certificates["Tizen Developers Root"] =
49 "tizen-developers-root.pem";
50 root_certificates["Tizen Partner Distributor Root CA"] =
51 "tizen-distributor-root-ca-partner.pem";
52 root_certificates["Tizen Partner-Operator Distributor Root CA"] =
53 "tizen-distributor-root-ca-partner-operator.pem";
54 root_certificates["Tizen Public Distributor Root CA"] =
55 "tizen-distributor-root-ca-public.pem";
56 root_certificates["Partner Class Developer Root"] =
57 "tizen-partner-class-developer-root.pem";
58 root_certificates["Partner Class Root Authority"] =
59 "tizen-partner-class-root-authority.pem";
60 root_certificates["Platform Class Developer Root"] =
61 "tizen-platform-class-developer-root.pem";
62 root_certificates["Platform Class Root Authority"] =
63 "tizen-platform-class-root-authority.pem";
64 root_certificates["Public Class Developer Root"] =
65 "tizen-public-class-developer-root.pem";
66 root_certificates["Public Class Root Authority"] =
67 "tizen-public-class-root-authority.pem";
69 return root_certificates;
72 static std::map<std::string, std::string> certificate_path_;
75 std::map<std::string, std::string>
76 CertificateUtil::certificate_path_ = InitCertificatePath();
80 static void GetExtractedPath(const xwalk::application::SignatureData& data);
81 static xmlSecKeysMngrPtr LoadTrustedCerts(
82 const xwalk::application::SignatureData& signature_data);
83 static int VerifyFile(
84 xmlSecKeysMngrPtr mngr, const xwalk::application::SignatureData& data);
87 static int FileMatchCallback(const char* file_name);
88 static void* FileOpenCallback(const char* file_name);
89 static int FileReadCallback(void* context, char* buffer, int len);
90 static int FileCloseCallback(void* context);
91 static void ConvertToPemCert(std::string* cert);
92 static base::FilePath GetCertFromStore(const std::string& subject);
94 static std::string prefix_path_;
95 static std::pair<void*, bool> file_wrapper_;
98 std::string XmlSecContext::prefix_path_;
99 std::pair<void*, bool> XmlSecContext::file_wrapper_;
101 void XmlSecContext::GetExtractedPath(
102 const xwalk::application::SignatureData& data) {
103 XmlSecContext::prefix_path_ = data.GetExtractedWidgetPath().MaybeAsASCII();
106 int XmlSecContext::FileMatchCallback(const char* file_name) {
107 std::string path = XmlSecContext::prefix_path_ + std::string(file_name);
108 return xmlFileMatch(path.c_str());
111 void* XmlSecContext::FileOpenCallback(const char* file_name) {
112 std::string path = XmlSecContext::prefix_path_ + std::string(file_name);
113 XmlSecContext::file_wrapper_ =
114 std::make_pair(xmlFileOpen(path.c_str()), false);
115 return &(XmlSecContext::file_wrapper_);
118 int XmlSecContext::FileReadCallback(void* context, char* buffer, int len) {
119 std::pair<void*, bool>* file_wrapper =
120 static_cast<std::pair<void*, bool>*>(context);
121 DCHECK(file_wrapper);
122 if (file_wrapper->second)
125 int output = xmlFileRead(file_wrapper->first, buffer, len);
127 file_wrapper->second = true;
128 xmlFileClose(file_wrapper->first);
133 int XmlSecContext::FileCloseCallback(void* context) {
134 std::pair<void*, bool>* file_wrapper =
135 static_cast<std::pair<void*, bool>*>(context);
136 DCHECK(file_wrapper);
138 if (!file_wrapper->second)
139 output = xmlFileClose(file_wrapper->first);
144 xmlSecKeysMngrPtr XmlSecContext::LoadTrustedCerts(
145 const xwalk::application::SignatureData& signature_data) {
146 xmlSecKeysMngrPtr mngr = xmlSecKeysMngrCreate();
148 LOG(ERROR) << "Error: failed to create keys manager.";
151 if (xmlSecCryptoAppDefaultKeysMngrInit(mngr) < 0) {
152 LOG(ERROR) << "Error: failed to initialize keys manager.";
153 xmlSecKeysMngrDestroy(mngr);
157 std::list<std::string> certificate_list = signature_data.certificate_list();
160 for (std::list<std::string>::iterator it = certificate_list.begin();
161 it != certificate_list.end(); ++it) {
163 XmlSecContext::ConvertToPemCert(&cert);
164 net::CertificateList certs =
165 net::X509Certificate::CreateCertificateListFromBytes(
166 cert.data(), cert.length(), net::X509Certificate::FORMAT_AUTO);
167 issuer = certs[0]->issuer().GetDisplayName();
169 if (xmlSecCryptoAppKeysMngrCertLoadMemory(mngr,
170 reinterpret_cast<const unsigned char*>(cert.c_str()), cert.size(),
171 xmlSecKeyDataFormatCertPem, xmlSecKeyDataTypeTrusted) < 0) {
172 LOG(ERROR) << "Error: failed to load pem certificate.";
173 xmlSecKeysMngrDestroy(mngr);
178 const base::FilePath& root_cert_path =
179 XmlSecContext::GetCertFromStore(issuer);
180 if (!base::PathExists(root_cert_path)) {
181 LOG(ERROR) << "Failed to find root certificate.";
185 if (xmlSecCryptoAppKeysMngrCertLoad(mngr,
186 root_cert_path.MaybeAsASCII().c_str(), xmlSecKeyDataFormatPem,
187 xmlSecKeyDataTypeTrusted) < 0) {
188 LOG(ERROR) << "Error: failed to load root certificate";
189 xmlSecKeysMngrDestroy(mngr);
196 // Verifies XML signature in #xml_file
197 // Returns 0 on success or a negative value if an error occurs.
198 int XmlSecContext::VerifyFile(xmlSecKeysMngrPtr mngr,
199 const xwalk::application::SignatureData& data) {
200 LOG(INFO) << "Verify " << data.signature_file_name();
201 xmlSecIOCleanupCallbacks();
202 XmlSecContext::GetExtractedPath(data);
203 xmlSecIORegisterCallbacks(
204 XmlSecContext::FileMatchCallback,
205 XmlSecContext::FileOpenCallback,
206 XmlSecContext::FileReadCallback,
207 XmlSecContext::FileCloseCallback);
209 xmlDocPtr doc = xmlParseFile(data.signature_file_name().c_str());
211 LOG(ERROR) << "Error: failed to parse " << data.signature_file_name();
215 if (!xmlDocGetRootElement(doc)) {
216 LOG(ERROR) << "Error: unable to get root element.";
221 xmlNodePtr node = xmlSecFindNode(
222 xmlDocGetRootElement(doc), xmlSecNodeSignature, xmlSecDSigNs);
224 LOG(ERROR) << "Error: unable to find SecNodeSignature node.";
229 xmlSecDSigCtxPtr dsig_ctx = xmlSecDSigCtxCreate(mngr);
231 LOG(ERROR) << "Error: failed to create signature context.";
236 if (xmlSecDSigCtxVerify(dsig_ctx, node) < 0) {
237 LOG(ERROR) << "Error: signature verify.";
239 xmlSecDSigCtxDestroy(dsig_ctx);
244 if (dsig_ctx->status != xmlSecDSigStatusSucceeded)
245 LOG(ERROR) << "Signature " << data.signature_file_name() <<" is INVALID";
247 LOG(INFO) << "Signature "<< data.signature_file_name() << " is OK.";
251 xmlSecDSigCtxDestroy(dsig_ctx);
255 void XmlSecContext::ConvertToPemCert(std::string* cert) {
256 *cert = "-----BEGIN CERTIFICATE-----" + *cert;
257 *cert = *cert + "-----END CERTIFICATE-----";
260 base::FilePath XmlSecContext::GetCertFromStore(const std::string& subject) {
261 const char cert_prefix_path[] = "/usr/share/ca-certificates/tizen/";
262 std::map<std::string, std::string>::const_iterator iter =
263 CertificateUtil::certificate_path().find(subject);
265 if (iter == CertificateUtil::certificate_path().end()) {
266 LOG(ERROR) << "Failing to find root certificate.";
267 return base::FilePath("");
269 LOG(INFO) << "root cert path is " << cert_prefix_path + iter->second;
270 return base::FilePath(cert_prefix_path + iter->second);
276 namespace application {
279 bool SignatureXmlSecAdaptor::ValidateFile(
280 const SignatureData& signature_data, const base::FilePath& widget_path) {
282 xmlSubstituteEntitiesDefault(1);
283 #ifndef XMLSEC_NO_XSLT
284 xsltSecurityPrefsPtr xslt_sec_prefs = xsltNewSecurityPrefs();
285 xsltSetSecurityPrefs(
286 xslt_sec_prefs, XSLT_SECPREF_READ_FILE, xsltSecurityForbid);
287 xsltSetSecurityPrefs(
288 xslt_sec_prefs, XSLT_SECPREF_WRITE_FILE, xsltSecurityForbid);
289 xsltSetSecurityPrefs(
290 xslt_sec_prefs, XSLT_SECPREF_CREATE_DIRECTORY, xsltSecurityForbid);
291 xsltSetSecurityPrefs(
292 xslt_sec_prefs, XSLT_SECPREF_READ_NETWORK, xsltSecurityForbid);
293 xsltSetSecurityPrefs(
294 xslt_sec_prefs, XSLT_SECPREF_WRITE_NETWORK, xsltSecurityForbid);
295 xsltSetDefaultSecurityPrefs(xslt_sec_prefs);
296 #endif // XMLSEC_NO_XSLT
298 if (xmlSecInit() < 0) {
299 LOG(ERROR) << "Error: xmlsec initialization failed.";
303 if (xmlSecCheckVersion() != 1) {
304 LOG(ERROR) << "Error: loaded xmlsec library version is not compatible.";
308 #ifdef XMLSEC_CRYPTO_DYNAMIC_LOADING
309 if (xmlSecCryptoDLLoadLibrary(BAD_CAST XMLSEC_CRYPTO) < 0) {
310 LOG(ERROR) << "Error: unable to load default xmlsec-crypto library.";
313 #endif // XMLSEC_CRYPTO_DYNAMIC_LOADING
315 if (xmlSecCryptoAppInit(NULL) < 0) {
316 LOG(ERROR) << "Error: crypto initialization failed.";
320 if (xmlSecCryptoInit() < 0) {
321 LOG(ERROR) << "Error: xmlsec-crypto initialization failed.";
325 xmlSecKeysMngrPtr mngr = XmlSecContext::LoadTrustedCerts(signature_data);
329 if (XmlSecContext::VerifyFile(mngr, signature_data) < 0) {
330 xmlSecKeysMngrDestroy(mngr);
334 xmlSecKeysMngrDestroy(mngr);
335 xmlSecCryptoShutdown();
336 xmlSecCryptoAppShutdown();
339 #ifndef XMLSEC_NO_XSLT
340 xsltFreeSecurityPrefs(xslt_sec_prefs);
341 xsltCleanupGlobals();
342 #endif // XMLSEC_NO_XSLT
348 } // namespace application