Signature implementation moved from xwalk 81/32481/8
authorTomasz Iwanek <t.iwanek@samsung.com>
Thu, 4 Dec 2014 10:16:01 +0000 (11:16 +0100)
committerPawel Sikorski <p.sikorski@samsung.com>
Tue, 23 Dec 2014 12:10:34 +0000 (13:10 +0100)
This is digital signature implementation moved from xwalk.
It is based on following PRs:
 - https://github.com/crosswalk-project/crosswalk/pull/2169
 - https://github.com/crosswalk-project/crosswalk/pull/2291
 - https://github.com/crosswalk-project/crosswalk/pull/2422

There are some not solved issues:
 - test correctness for valid widgets,
 - seperation from managing root certificate,
 - style of this code.

[[ PLEASE NOTE THE COMMIT CONTAINS CROSSWALK'S BSD-STYLE LICENSE ]]

Change-Id: I42db7e8a02b44a88ca88d143ad034fd1e253f3e2
Signed-off-by: Pawel Sikorski <p.sikorski@samsung.com>
20 files changed:
CMakeLists.txt
LICENSE-xwalk [new file with mode: 0644]
common/CMakeLists.txt
common/include/step/signature_step.h [new file with mode: 0644]
common/src/step/signature_step.cc [new file with mode: 0644]
data/CMakeLists.txt [new file with mode: 0644]
data/signature_schema.xsd [new file with mode: 0644]
packaging/app-installers.spec
signature/CMakeLists.txt [new file with mode: 0644]
signature/include/logging.h [new file with mode: 0644]
signature/include/marcos.h [new file with mode: 0644]
signature/include/signature_data.h [new file with mode: 0644]
signature/include/signature_parser.h [new file with mode: 0644]
signature/include/signature_validator.h [new file with mode: 0644]
signature/include/signature_xmlsec_adaptor.h [new file with mode: 0644]
signature/src/signature_data.cc [new file with mode: 0644]
signature/src/signature_parser.cc [new file with mode: 0644]
signature/src/signature_validator.cc [new file with mode: 0644]
signature/src/signature_xmlsec_adaptor.cc [new file with mode: 0644]
wgt/src/wgt_backend.cc

index 9feaf90..d689aab 100644 (file)
@@ -22,6 +22,7 @@ SET(CMAKE_CXX_FLAGS_CCOV       "-O0 -std=c++11 -g --coverage")
 
 # Targets
 SET(TARGET_LIBNAME_COMMON "common-installer")
+SET(TARGET_LIBNAME_SIGNATURE "common-installer-signature")
 SET(TARGET_WGT_BACKEND "wgt-backend")
 SET(TARGET_XPK_BACKEND "xpk-backend")
 SET(TARGET_NATIVE_BACKEND "native-backend")
@@ -43,11 +44,18 @@ PKG_CHECK_MODULES(PKGMGR_PARSER_DEPS REQUIRED pkgmgr-parser)
 PKG_CHECK_MODULES(PKGMGR_INSTALLER_DEPS REQUIRED pkgmgr-installer)
 PKG_CHECK_MODULES(MINIZIP_DEPS REQUIRED minizip)
 PKG_CHECK_MODULES(ZLIB_DEPS REQUIRED zlib)
+PKG_CHECK_MODULES(OPENSSL_DEPS REQUIRED openssl)
 PKG_CHECK_MODULES(LIBXML_DEPS REQUIRED libxml-2.0)
+PKG_CHECK_MODULES(XMLSEC1_DEPS REQUIRED xmlsec1)
 
-FIND_PACKAGE(Boost COMPONENTS filesystem system REQUIRED)
+FIND_PACKAGE(Boost REQUIRED COMPONENTS system filesystem)
+
+# xmlsec1 - choose crypto library which to use
+ADD_DEFINITIONS("-DXMLSEC_CRYPTO_OPENSSL")
 
 ADD_SUBDIRECTORY(common)
+ADD_SUBDIRECTORY(signature)
 ADD_SUBDIRECTORY(wgt)
 #ADD_SUBDIRECTORY(xpk)
 #ADD_SUBDIRECTORY(native)
+ADD_SUBDIRECTORY(data)
diff --git a/LICENSE-xwalk b/LICENSE-xwalk
new file mode 100644 (file)
index 0000000..ac380b1
--- /dev/null
@@ -0,0 +1,27 @@
+// Copyright (c) 2013 Intel Corporation. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//    * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//    * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//    * Neither the name of Intel Corporation nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
index a13e2eb..d083ce6 100644 (file)
@@ -2,6 +2,7 @@
 SET(SRCS
   src/app_installer.cc
   src/step/step_unzip.cc
+  src/step/signature_step.cc
 )
 # Target - definition
 ADD_LIBRARY(${TARGET_LIBNAME_COMMON} SHARED ${SRCS})
@@ -18,6 +19,8 @@ APPLY_PKG_CONFIG(${TARGET_LIBNAME_COMMON} PUBLIC
   LIBXML_DEPS
   Boost
 )
+# Target in-package deps
+TARGET_LINK_LIBRARIES(${TARGET_LIBNAME_COMMON} ${TARGET_LIBNAME_SIGNATURE})
 
 # Extra
 SET_TARGET_PROPERTIES(${TARGET_LIBNAME_COMMON} PROPERTIES VERSION ${VERSION})
diff --git a/common/include/step/signature_step.h b/common/include/step/signature_step.h
new file mode 100644 (file)
index 0000000..bfe0ec5
--- /dev/null
@@ -0,0 +1,24 @@
+// Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by an apache 2.0 license that can be
+// found in the LICENSE file.
+
+#ifndef COMMON_STEP_SIGNATURE_SIGNATURE_STEP_H_
+#define COMMON_STEP_SIGNATURE_SIGNATURE_STEP_H_
+
+#include "context_installer.h"
+#include "step.h"
+
+namespace common {
+
+class SignatureStep : public Step {
+ public:
+  using Step::Step;
+
+  int process(Context_installer* context) override;
+  int undo(Context_installer*) override { return 0; }
+  int clean(Context_installer*) override { return 0; }
+};
+
+}  // namespace common
+
+#endif  // COMMON_STEP_SIGNATURE_SIGNATURE_STEP_H_
diff --git a/common/src/step/signature_step.cc b/common/src/step/signature_step.cc
new file mode 100644 (file)
index 0000000..b63926d
--- /dev/null
@@ -0,0 +1,22 @@
+// Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by an apache 2.0 license that can be
+// found in the LICENSE file.
+
+#include <step/signature_step.h>
+
+#include <boost/filesystem/path.hpp>
+
+#include <string>
+
+#include <signature_validator.h>
+
+namespace bf = boost::filesystem;
+
+namespace common {
+
+int SignatureStep::process(Context_installer* context) {
+  return (signature::SignatureValidator::Check(bf::path(context->unpack_directory))
+      == signature::SignatureValidator::INVALID) ? -1 : 0;
+}
+
+}  // namespace common
diff --git a/data/CMakeLists.txt b/data/CMakeLists.txt
new file mode 100644 (file)
index 0000000..5ebfd2f
--- /dev/null
@@ -0,0 +1 @@
+INSTALL(FILES "signature_schema.xsd" DESTINATION "share/app-installers/")
diff --git a/data/signature_schema.xsd b/data/signature_schema.xsd
new file mode 100644 (file)
index 0000000..8028f3e
--- /dev/null
@@ -0,0 +1,415 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE schema
+  PUBLIC "-//W3C//DTD XMLSchema 200102//EN" "http://www.w3.org/2001/XMLSchema.dtd"
+ [
+   <!ATTLIST schema
+     xmlns:ds CDATA #FIXED "http://www.w3.org/2000/09/xmldsig#">
+   <!ENTITY dsig 'http://www.w3.org/2000/09/xmldsig#'>
+   <!ENTITY % p ''>
+   <!ENTITY % s ''>
+  ]>
+
+<!-- Schema for XML Signatures
+    http://www.w3.org/2000/09/xmldsig#
+    $Revision: 1.1 $ on $Date: 2002/02/08 20:32:26 $ by $Author: reagle $
+
+    Copyright 2001 The Internet Society and W3C (Massachusetts Institute
+    of Technology, Institut National de Recherche en Informatique et en
+    Automatique, Keio University). All Rights Reserved.
+    http://www.w3.org/Consortium/Legal/
+
+    This document is governed by the W3C Software License [1] as described
+    in the FAQ [2].
+
+    [1] http://www.w3.org/Consortium/Legal/copyright-software-19980720
+    [2] http://www.w3.org/Consortium/Legal/IPR-FAQ-20000620.html#DTD
+-->
+
+
+<schema xmlns="http://www.w3.org/2001/XMLSchema"
+        xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
+        targetNamespace="http://www.w3.org/2000/09/xmldsig#"
+        version="0.1" elementFormDefault="qualified">
+
+<!-- Basic Types Defined for Signatures -->
+
+<simpleType name="CryptoBinary">
+  <restriction base="base64Binary">
+  </restriction>
+</simpleType>
+
+<!-- Start Signature -->
+
+<element name="Signature" type="ds:SignatureType"/>
+<complexType name="SignatureType">
+  <sequence>
+    <element ref="ds:SignedInfo"/>
+    <element ref="ds:SignatureValue"/>
+    <element ref="ds:KeyInfo" minOccurs="0"/>
+    <element ref="ds:Object" minOccurs="0" maxOccurs="unbounded"/>
+  </sequence>
+  <attribute name="Id" type="ID" use="optional"/>
+</complexType>
+
+  <element name="SignatureValue" type="ds:SignatureValueType"/>
+  <complexType name="SignatureValueType">
+    <simpleContent>
+      <extension base="base64Binary">
+        <attribute name="Id" type="ID" use="optional"/>
+      </extension>
+    </simpleContent>
+  </complexType>
+
+<!-- Start SignedInfo -->
+
+<element name="SignedInfo" type="ds:SignedInfoType"/>
+<complexType name="SignedInfoType">
+  <sequence>
+    <element ref="ds:CanonicalizationMethod"/>
+    <element ref="ds:SignatureMethod"/>
+    <element ref="ds:Reference" maxOccurs="unbounded"/>
+  </sequence>
+  <attribute name="Id" type="ID" use="optional"/>
+</complexType>
+
+  <element name="CanonicalizationMethod" type="ds:CanonicalizationMethodType"/>
+  <complexType name="CanonicalizationMethodType" mixed="true">
+    <sequence>
+      <any namespace="##any" minOccurs="0" maxOccurs="unbounded"/>
+      <!-- (0,unbounded) elements from (1,1) namespace -->
+    </sequence>
+    <attribute name="Algorithm" type="anyURI" use="required"/>
+  </complexType>
+
+  <element name="SignatureMethod" type="ds:SignatureMethodType"/>
+  <complexType name="SignatureMethodType" mixed="true">
+    <sequence>
+      <element name="HMACOutputLength" minOccurs="0" type="ds:HMACOutputLengthType"/>
+      <any namespace="##other" minOccurs="0" maxOccurs="unbounded"/>
+      <!-- (0,unbounded) elements from (1,1) external namespace -->
+    </sequence>
+    <attribute name="Algorithm" type="anyURI" use="required"/>
+  </complexType>
+
+<!-- Start Reference -->
+
+<element name="Reference" type="ds:ReferenceType"/>
+<complexType name="ReferenceType">
+  <sequence>
+    <element ref="ds:Transforms" minOccurs="0"/>
+    <element ref="ds:DigestMethod"/>
+    <element ref="ds:DigestValue"/>
+  </sequence>
+  <attribute name="Id" type="ID" use="optional"/>
+  <attribute name="URI" type="anyURI" use="optional"/>
+  <attribute name="Type" type="anyURI" use="optional"/>
+</complexType>
+
+  <element name="Transforms" type="ds:TransformsType"/>
+  <complexType name="TransformsType">
+    <sequence>
+      <element ref="ds:Transform" maxOccurs="unbounded"/>
+    </sequence>
+  </complexType>
+
+  <element name="Transform" type="ds:TransformType"/>
+  <complexType name="TransformType" mixed="true">
+    <choice minOccurs="0" maxOccurs="unbounded">
+      <any namespace="##other" processContents="lax"/>
+      <!-- (1,1) elements from (0,unbounded) namespaces -->
+      <element name="XPath" type="string"/>
+    </choice>
+    <attribute name="Algorithm" type="anyURI" use="required"/>
+  </complexType>
+
+<!-- End Reference -->
+
+<element name="DigestMethod" type="ds:DigestMethodType"/>
+<complexType name="DigestMethodType" mixed="true">
+  <sequence>
+    <any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
+  </sequence>
+  <attribute name="Algorithm" type="anyURI" use="required"/>
+</complexType>
+
+<element name="DigestValue" type="ds:DigestValueType"/>
+<simpleType name="DigestValueType">
+  <restriction base="base64Binary"/>
+</simpleType>
+
+<!-- End SignedInfo -->
+
+<!-- Start KeyInfo -->
+
+<element name="KeyInfo" type="ds:KeyInfoType"/>
+<complexType name="KeyInfoType" mixed="true">
+  <choice maxOccurs="unbounded">
+    <element ref="ds:KeyName"/>
+    <element ref="ds:KeyValue"/>
+    <element ref="ds:RetrievalMethod"/>
+    <element ref="ds:X509Data"/>
+    <element ref="ds:PGPData"/>
+    <element ref="ds:SPKIData"/>
+    <element ref="ds:MgmtData"/>
+    <any processContents="lax" namespace="##other"/>
+    <!-- (1,1) elements from (0,unbounded) namespaces -->
+  </choice>
+  <attribute name="Id" type="ID" use="optional"/>
+</complexType>
+
+  <element name="KeyName" type="string"/>
+  <element name="MgmtData" type="string"/>
+
+  <element name="KeyValue" type="ds:KeyValueType"/>
+  <complexType name="KeyValueType" mixed="true">
+   <choice>
+     <element ref="ds:DSAKeyValue"/>
+     <element ref="ds:RSAKeyValue"/>
+     <element ref="ds:ECKeyValue"/>
+     <any namespace="##other" processContents="lax"/>
+   </choice>
+  </complexType>
+
+<!-- ECDSA KEY DEFINITIONS -->
+
+  <element name="ECKeyValue" type="ds:ECKeyValueType"/>
+  <complexType name="ECKeyValueType">
+    <sequence>
+      <choice>
+        <element name="ECParameters" type="ds:ECParametersType"/>
+        <element name="NamedCurve" type="ds:NamedCurveType"/>
+      </choice>
+      <element name="PublicKey" type="ds:ECPointType"/>
+    </sequence>
+    <attribute name="Id" type="ID" use="optional"/>
+  </complexType>
+
+  <complexType name="NamedCurveType">
+    <attribute name="URI" type="anyURI" use="required"/>
+  </complexType>
+
+  <simpleType name="ECPointType">
+    <restriction base="ds:CryptoBinary"/>
+  </simpleType>
+
+  <element name="RetrievalMethod" type="ds:RetrievalMethodType"/>
+  <complexType name="RetrievalMethodType">
+    <sequence>
+      <element ref="ds:Transforms" minOccurs="0"/>
+    </sequence>
+    <attribute name="URI" type="anyURI"/>
+    <attribute name="Type" type="anyURI" use="optional"/>
+  </complexType>
+
+    <complexType name="ECParametersType">
+      <sequence>
+        <element name="FieldID" type="ds:FieldIDType"/>
+        <element name="Curve" type="ds:CurveType"/>
+        <element name="Base" type="ds:ECPointType"/>
+        <element name="Order" type="ds:CryptoBinary"/>
+        <element name="CoFactor" type="integer" minOccurs="0"/>
+        <element name="ValidationData" type="ds:ECValidationDataType" minOccurs="0"/>
+      </sequence>
+    </complexType>
+
+    <complexType name="FieldIDType">
+      <choice>
+        <element ref="ds:Prime"/>
+        <element ref="ds:TnB"/>
+        <element ref="ds:PnB"/>
+        <element ref="ds:GnB"/>
+        <any namespace="##other" processContents="lax"/>
+      </choice>
+    </complexType>
+
+    <element name="Prime" type="ds:PrimeFieldParamsType"/>
+    <complexType name="PrimeFieldParamsType">
+      <sequence>
+        <element name="P" type="ds:CryptoBinary"/>
+      </sequence>
+    </complexType>
+
+    <element name="GnB" type="ds:CharTwoFieldParamsType"/>
+    <complexType name="CharTwoFieldParamsType">
+      <sequence>
+        <element name="M" type="positiveInteger"/>
+      </sequence>
+    </complexType>
+
+    <element name="TnB" type="ds:TnBFieldParamsType"/>
+    <complexType name="TnBFieldParamsType">
+      <complexContent>
+        <extension base="ds:CharTwoFieldParamsType">
+          <sequence>
+            <element name="K" type="positiveInteger"/>
+          </sequence>
+        </extension>
+      </complexContent>
+    </complexType>
+
+    <element name="PnB" type="ds:PnBFieldParamsType"/>
+    <complexType name="PnBFieldParamsType">
+      <complexContent>
+        <extension base="ds:CharTwoFieldParamsType">
+          <sequence>
+            <element name="K1" type="positiveInteger"/>
+            <element name="K2" type="positiveInteger"/>
+            <element name="K3" type="positiveInteger"/>
+          </sequence>
+        </extension>
+      </complexContent>
+    </complexType>
+
+    <complexType name="CurveType">
+      <sequence>
+        <element name="A" type="ds:CryptoBinary"/>
+        <element name="B" type="ds:CryptoBinary"/>
+      </sequence>
+    </complexType>
+
+  <complexType name="ECValidationDataType">
+    <sequence>
+      <element name="seed" type="ds:CryptoBinary"/>
+    </sequence>
+    <attribute name="hashAlgorithm" type="anyURI" use="required"/>
+  </complexType>
+
+
+<!-- Start X509Data -->
+
+<element name="X509Data" type="ds:X509DataType"/>
+<complexType name="X509DataType">
+  <sequence maxOccurs="unbounded">
+    <choice>
+      <element name="X509IssuerSerial" type="ds:X509IssuerSerialType"/>
+      <element name="X509SKI" type="base64Binary"/>
+      <element name="X509SubjectName" type="string"/>
+      <element name="X509Certificate" type="base64Binary"/>
+      <element name="X509CRL" type="base64Binary"/>
+      <any namespace="##other" processContents="lax"/>
+    </choice>
+  </sequence>
+</complexType>
+
+<complexType name="X509IssuerSerialType">
+  <sequence>
+    <element name="X509IssuerName" type="string"/>
+    <element name="X509SerialNumber" type="integer"/>
+  </sequence>
+</complexType>
+
+<!-- End X509Data -->
+
+<!-- Begin PGPData -->
+
+<element name="PGPData" type="ds:PGPDataType"/>
+<complexType name="PGPDataType">
+  <choice>
+    <sequence>
+      <element name="PGPKeyID" type="base64Binary"/>
+      <element name="PGPKeyPacket" type="base64Binary" minOccurs="0"/>
+      <any namespace="##other" processContents="lax" minOccurs="0"
+       maxOccurs="unbounded"/>
+    </sequence>
+    <sequence>
+      <element name="PGPKeyPacket" type="base64Binary"/>
+      <any namespace="##other" processContents="lax" minOccurs="0"
+       maxOccurs="unbounded"/>
+    </sequence>
+  </choice>
+</complexType>
+
+<!-- End PGPData -->
+
+<!-- Begin SPKIData -->
+
+<element name="SPKIData" type="ds:SPKIDataType"/>
+<complexType name="SPKIDataType">
+  <sequence maxOccurs="unbounded">
+    <element name="SPKISexp" type="base64Binary"/>
+    <any namespace="##other" processContents="lax" minOccurs="0"/>
+  </sequence>
+</complexType>
+
+<!-- End SPKIData -->
+
+<!-- End KeyInfo -->
+
+<!-- Start Object (Manifest, SignatureProperty) -->
+
+<element name="Object" type="ds:ObjectType"/>
+<complexType name="ObjectType" mixed="true">
+  <sequence minOccurs="0" maxOccurs="unbounded">
+    <any namespace="##any" processContents="lax"/>
+  </sequence>
+  <attribute name="Id" type="ID" use="optional"/>
+  <attribute name="MimeType" type="string" use="optional"/> <!-- add a grep facet -->
+  <attribute name="Encoding" type="anyURI" use="optional"/>
+</complexType>
+
+<element name="Manifest" type="ds:ManifestType"/>
+<complexType name="ManifestType">
+  <sequence>
+    <element ref="ds:Reference" maxOccurs="unbounded"/>
+  </sequence>
+  <attribute name="Id" type="ID" use="optional"/>
+</complexType>
+
+<element name="SignatureProperties" type="ds:SignaturePropertiesType"/>
+<complexType name="SignaturePropertiesType">
+  <sequence>
+    <element ref="ds:SignatureProperty" maxOccurs="unbounded"/>
+  </sequence>
+  <attribute name="Id" type="ID" use="optional"/>
+</complexType>
+
+   <element name="SignatureProperty" type="ds:SignaturePropertyType"/>
+   <complexType name="SignaturePropertyType" mixed="true">
+     <choice maxOccurs="unbounded">
+       <any namespace="##other" processContents="lax"/>
+       <!-- (1,1) elements from (1,unbounded) namespaces -->
+     </choice>
+     <attribute name="Target" type="anyURI" use="required"/>
+     <attribute name="Id" type="ID" use="optional"/>
+   </complexType>
+
+<!-- End Object (Manifest, SignatureProperty) -->
+
+<!-- Start Algorithm Parameters -->
+
+<simpleType name="HMACOutputLengthType">
+  <restriction base="integer"/>
+</simpleType>
+
+<!-- Start KeyValue Element-types -->
+
+<element name="DSAKeyValue" type="ds:DSAKeyValueType"/>
+<complexType name="DSAKeyValueType">
+  <sequence>
+    <sequence minOccurs="0">
+      <element name="P" type="ds:CryptoBinary"/>
+      <element name="Q" type="ds:CryptoBinary"/>
+    </sequence>
+    <element name="G" type="ds:CryptoBinary" minOccurs="0"/>
+    <element name="Y" type="ds:CryptoBinary"/>
+    <element name="J" type="ds:CryptoBinary" minOccurs="0"/>
+    <sequence minOccurs="0">
+      <element name="Seed" type="ds:CryptoBinary"/>
+      <element name="PgenCounter" type="ds:CryptoBinary"/>
+    </sequence>
+  </sequence>
+</complexType>
+
+<element name="RSAKeyValue" type="ds:RSAKeyValueType"/>
+<complexType name="RSAKeyValueType">
+  <sequence>
+    <element name="Modulus" type="ds:CryptoBinary"/>
+    <element name="Exponent" type="ds:CryptoBinary"/>
+  </sequence>
+</complexType>
+
+<!-- End KeyValue Element-types -->
+
+<!-- End Signature -->
+
+</schema>
index a965f75..f11c323 100644 (file)
@@ -6,16 +6,21 @@ Group:          Application Framework/Package Management
 License:        Apache-2.0
 Source0:        %{name}-%{version}.tar.gz
 
-BuildRequires:  libcap-devel
+BuildRequires:  boost-devel
 BuildRequires:  cmake
+BuildRequires:  libcap-devel
 BuildRequires:  pkgconfig(pkgmgr)
 BuildRequires:  pkgconfig(pkgmgr-parser)
 BuildRequires:  pkgconfig(pkgmgr-info)
 BuildRequires:  pkgconfig(pkgmgr-installer)
+BuildRequires:  pkgconfig(openssl)
 BuildRequires:  pkgconfig(libxml-2.0)
 BuildRequires:  pkgconfig(zlib)
 BuildRequires:  pkgconfig(minizip)
-BuildRequires:  boost-devel
+BuildRequires:  pkgconfig(libzip)
+BuildRequires:  pkgconfig(xmlsec1)
+
+Requires: ca-certificates-tizen
 
 %description
 This is a meta package that installs the common application
@@ -54,7 +59,9 @@ ln -s %{_bindir}/xpk-backend %{buildroot}%{_sysconfdir}/package-manager/backend/
 %files
 %defattr(-,root,root)
 %{_libdir}/libcommon-installer.so*
-%license LICENSE
+%{_libdir}/libcommon-installer-signature.so*
+%{_datarootdir}/app-installers/signature_schema.xsd
+%license LICENSE LICENSE-xwalk
 
 %files -n wgt-backend
 %{_sysconfdir}/package-manager/backend/wgt
diff --git a/signature/CMakeLists.txt b/signature/CMakeLists.txt
new file mode 100644 (file)
index 0000000..15f91cf
--- /dev/null
@@ -0,0 +1,24 @@
+# Target - sources
+SET(SRCS
+  src/signature_data.cc
+  src/signature_parser.cc
+  src/signature_validator.cc
+  src/signature_xmlsec_adaptor.cc
+)
+# Target - definition
+ADD_LIBRARY(${TARGET_LIBNAME_SIGNATURE} SHARED ${SRCS})
+# Target - includes
+TARGET_INCLUDE_DIRECTORIES(${TARGET_LIBNAME_SIGNATURE} PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include")
+# Target - deps
+APPLY_PKG_CONFIG(${TARGET_LIBNAME_SIGNATURE} PUBLIC
+  OPENSSL_DEPS
+  XMLSEC1_DEPS
+  Boost
+)
+
+# Extra
+SET_TARGET_PROPERTIES(${TARGET_LIBNAME_SIGNATURE} PROPERTIES VERSION ${VERSION})
+SET_TARGET_PROPERTIES(${TARGET_LIBNAME_SIGNATURE} PROPERTIES SOVERSION ${VERSION_MAJOR})
+
+# Install
+INSTALL(TARGETS ${TARGET_LIBNAME_SIGNATURE} DESTINATION ${LIB_INSTALL_DIR})
diff --git a/signature/include/logging.h b/signature/include/logging.h
new file mode 100644 (file)
index 0000000..1a3103c
--- /dev/null
@@ -0,0 +1,30 @@
+// Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by a apache 2.0 license that can be
+// found in the LICENSE file.
+
+#ifndef UTILS_LOGGING_H_
+#define UTILS_LOGGING_H_
+
+#include <iostream>
+#include <sstream>
+
+// TODO(tiwanek): Logging...
+
+namespace detail {
+
+class LogCatcher {
+ public:
+  LogCatcher() { }
+  void operator&(const std::ostream& str) const {
+    // TODO(tiwanek): this cast is error-prone - fix it
+    std::cerr << static_cast<const std::ostringstream*>(&str)->str()
+              << std::endl;
+  }
+};
+
+}
+
+#define LOG(LEVEL)                                                             \
+    ::detail::LogCatcher() & std::ostringstream() << "[" << #LEVEL << "] "     \
+
+#endif  // UTILS_LOGGING_H_
diff --git a/signature/include/marcos.h b/signature/include/marcos.h
new file mode 100644 (file)
index 0000000..4e70345
--- /dev/null
@@ -0,0 +1,12 @@
+// Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by a apache 2.0 license that can be
+// found in the LICENSE file.
+
+#ifndef UTILS_MARCOS_H_
+#define UTILS_MARCOS_H_
+
+#define DISALLOW_COPY_AND_ASSIGN(CLASS)            \
+  CLASS(const CLASS&) = delete;                    \
+  CLASS& operator=(const CLASS&) = delete          \
+
+#endif  // UTILS_MARCOS_H_
diff --git a/signature/include/signature_data.h b/signature/include/signature_data.h
new file mode 100644 (file)
index 0000000..c6f16ab
--- /dev/null
@@ -0,0 +1,123 @@
+// Copyright (c) 2013 Intel Corporation. All rights reserved.
+// Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by an apache 2.0 license that can be
+// found in the LICENSE file.
+// Part of this file is redistributed from crosswalk project under BDS-style
+// license. Check LICENSE-xwalk file.
+
+#ifndef SIGNATURE_SIGNATURE_DATA_H_
+#define SIGNATURE_SIGNATURE_DATA_H_
+
+#include <boost/filesystem/path.hpp>
+#include <libxml/tree.h>
+#include <libxml/xpath.h>
+
+#include <list>
+#include <set>
+#include <string>
+
+#include <marcos.h>
+
+namespace signature {
+
+class SignatureData {
+ public:
+  SignatureData(const boost::filesystem::path& signature_file_name,
+      int signature_number);
+  ~SignatureData();
+
+  boost::filesystem::path signature_file_name() const {
+    return signature_file_name_;
+  }
+
+  const std::set<std::string>& reference_set() const {
+    return reference_set_;
+  }
+
+  void set_reference_set(const std::set<std::string>& reference_set) {
+    reference_set_ = reference_set;
+  }
+
+  std::string role_uri() const {
+    return role_uri_;
+  }
+
+  void set_role_uri(const std::string& role_uri) {
+    role_uri_ = role_uri;
+  }
+
+  std::string profile_uri() const {
+    return profile_uri_;
+  }
+
+  void set_profile_uri(const std::string& profile_uri) {
+    profile_uri_ = profile_uri;
+  }
+
+  std::string object_id() const {
+    return object_id_;
+  }
+
+  void set_object_id(const std::string& object_id) {
+    object_id_ = object_id;
+  }
+
+  std::string signature_value() const {
+    return signature_value_;
+  }
+
+  void set_signature_value(const std::string& signature_value) {
+    signature_value_ = signature_value;
+  }
+
+  std::string canonicalization_method() const {
+    return canonicalization_method_;
+  }
+
+  void set_canonicalization_method(const std::string& canonicalization_method) {
+    canonicalization_method_ = canonicalization_method;
+  }
+
+  std::string signature_method() const {
+    return signature_method_;
+  }
+
+  void set_signature_method(const std::string& signature_method) {
+    signature_method_ = signature_method;
+  }
+
+  const std::list<std::string>& certificate_list() const {
+    return certificate_list_;
+  }
+
+  void set_certificate_list(const std::list<std::string>& certificate_list) {
+    certificate_list_ = certificate_list;
+  }
+
+  bool isAuthorSignature() const {
+    return signature_number_ == -1;
+  }
+
+  boost::filesystem::path GetExtractedWidgetPath() const;
+
+ private:
+  boost::filesystem::path signature_file_name_;
+  // This number is taken from distributor signature file name.
+  // Author signature do not contain any number on the file name.
+  // Author signature should have signature number equal to -1.
+  int signature_number_;
+  std::string role_uri_;
+  std::string profile_uri_;
+  std::string signature_value_;
+  std::string identifier;
+  std::string object_id_;
+  std::string canonicalization_method_;
+  std::string signature_method_;
+  std::set<std::string> reference_set_;
+  std::list<std::string> certificate_list_;
+};
+
+}  // namespace signature
+
+
+#endif  // SIGNATURE_SIGNATURE_DATA_H_
diff --git a/signature/include/signature_parser.h b/signature/include/signature_parser.h
new file mode 100644 (file)
index 0000000..6f06c73
--- /dev/null
@@ -0,0 +1,31 @@
+// Copyright (c) 2013 Intel Corporation. All rights reserved.
+// Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by an apache 2.0 license that can be
+// found in the LICENSE file.
+// Part of this file is redistributed from crosswalk project under BDS-style
+// license. Check LICENSE-xwalk file.
+
+#ifndef SIGNATURE_SIGNATURE_PARSER_H_
+#define SIGNATURE_SIGNATURE_PARSER_H_
+
+#include <boost/filesystem/path.hpp>
+
+#include <memory>
+
+#include <marcos.h>
+#include <signature_data.h>
+
+namespace signature {
+
+class SignatureParser {
+ public:
+  static std::unique_ptr<SignatureData> CreateSignatureData(
+      const boost::filesystem::path& signature_path, int signature_number);
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(SignatureParser);
+};
+
+}  // namespace signature
+
+#endif  // SIGNATURE_SIGNATURE_PARSER_H_
diff --git a/signature/include/signature_validator.h b/signature/include/signature_validator.h
new file mode 100644 (file)
index 0000000..eb5e8d9
--- /dev/null
@@ -0,0 +1,35 @@
+// Copyright (c) 2013 Intel Corporation. All rights reserved.
+// Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by an apache 2.0 license that can be
+// found in the LICENSE file.
+// Part of this file is redistributed from crosswalk project under BDS-style
+// license. Check LICENSE-xwalk file.
+
+#ifndef COMMON_STEP_SIGNATURE_SIGNATURE_VALIDATOR_H_
+#define COMMON_STEP_SIGNATURE_SIGNATURE_VALIDATOR_H_
+
+#include <boost/filesystem.hpp>
+
+#include <string>
+
+#include <marcos.h>
+
+namespace signature {
+
+class SignatureValidator {
+ public:
+  enum Status {
+    UNTRUSTED,
+    VALID,
+    INVALID
+  };
+
+  static Status Check(const boost::filesystem::path& widget_path);
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(SignatureValidator);
+};
+
+}  // namespace signature
+
+#endif  // COMMON_STEP_SIGNATURE_SIGNATURE_VALIDATOR_H_
diff --git a/signature/include/signature_xmlsec_adaptor.h b/signature/include/signature_xmlsec_adaptor.h
new file mode 100644 (file)
index 0000000..7bb81e1
--- /dev/null
@@ -0,0 +1,27 @@
+// Copyright (c) 2014 Intel Corporation. All rights reserved.
+// Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by an apache 2.0 license that can be
+// found in the LICENSE file.
+// Part of this file is redistributed from crosswalk project under BDS-style
+// license. Check LICENSE-xwalk file.
+
+#ifndef SIGNATURE_SIGNATURE_XMLSEC_ADAPTOR_H_
+#define SIGNATURE_SIGNATURE_XMLSEC_ADAPTOR_H_
+
+#include <boost/filesystem/path.hpp>
+
+#include <signature_data.h>
+
+namespace signature {
+
+class SignatureXmlSecAdaptor {
+ public:
+  static bool ValidateFile(const SignatureData& signature_data);
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(SignatureXmlSecAdaptor);
+};
+
+}  // namespace signature
+
+#endif  // COMMON_STEP_SIGNATURE_SIGNATURE_XMLSEC_ADAPTOR_H_
diff --git a/signature/src/signature_data.cc b/signature/src/signature_data.cc
new file mode 100644 (file)
index 0000000..9dbc2ff
--- /dev/null
@@ -0,0 +1,25 @@
+// Copyright (c) 2014 Intel Corporation. All rights reserved.
+// Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by an apache 2.0 license that can be
+// found in the LICENSE file.
+// Part of this file is redistributed from crosswalk project under BDS-style
+// license. Check LICENSE-xwalk file.
+
+#include <signature_data.h>
+
+namespace signature {
+
+SignatureData::SignatureData(const boost::filesystem::path& signature_file_name,
+    int signature_number)
+    : signature_file_name_(signature_file_name),
+      signature_number_(signature_number) {
+}
+
+SignatureData::~SignatureData() {
+}
+
+boost::filesystem::path SignatureData::GetExtractedWidgetPath() const {
+  return signature_file_name().parent_path();
+}
+
+}  // namespace signature
diff --git a/signature/src/signature_parser.cc b/signature/src/signature_parser.cc
new file mode 100644 (file)
index 0000000..7e6f15d
--- /dev/null
@@ -0,0 +1,331 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright (c) 2014 Intel Corporation.
+// Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by an apache 2.0 license that can be
+// found in the LICENSE file.
+// Part of this file is redistributed from crosswalk project under BDS-style
+// license. Check LICENSE-xwalk file.
+
+#include <signature_parser.h>
+
+#include <libxml/parser.h>
+#include <libxml/xmlschemas.h>
+#include <libxml/xpathInternals.h>
+#include <libxml/xmlreader.h>
+
+#include <cstring>
+#include <list>
+#include <set>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include <logging.h>
+#include <marcos.h>
+
+namespace {
+const char kExpectedXmlns[] = "http://www.w3.org/2000/09/xmldsig#";
+// TAG TOKENS
+const char kTokenSignature[] = "Signature";
+const char kTokenSignedInfo[] = "SignedInfo";
+const char kTokenCanonicalizationMethod[] = "CanonicalizationMethod";
+const char kTokenSignatureMethod[] = "SignatureMethod";
+const char kTokenReference[] = "Reference";
+const char kTokenTransforms[] = "Transforms";
+const char kTokenTransform[] = "Transform";
+const char kTokenDigestMethod[] = "DigestMethod";
+const char kTokenDigestValue[] = "DigestValue";
+const char kTokenSignatureValue[] = "SignatureValue";
+const char kTokenkeyInfo[] = "KeyInfo";
+const char kTokenX509Data[] = "X509Data";
+const char kTokenX509Certificate[] = "X509Certificate";
+const char kTokenObject[] = "Object";
+const char kTokenSignatureProperties[] = "SignatureProperties";
+const char kTokenSignatureProperty[] = "SignatureProperty";
+
+// ATTRIBUTE TOKENS
+const char kTokenAlgorithm[] = "Algorithm";
+const char kTokenURI[] = "URI";
+const char kTokenID[] = "Id";
+
+// ATTRIBUTE VALUES
+const char kTokenAttrProfile[] = "profile";
+const char kTokenAttrRole[] = "role";
+const char kTokenAttrIdentifier[] = "identifier";
+
+bool TagNameEquals(const xmlNodePtr node,
+    const char* expected_name, const xmlNsPtr expected_namespace) {
+  if (node->ns != expected_namespace)
+    return false;
+
+  return 0 == strcmp(expected_name, reinterpret_cast<const char*>(node->name));
+}
+
+// Returns child nodes of |root| with name |name|.
+std::vector<xmlNodePtr> GetChildren(
+    const xmlNodePtr root, const xmlNsPtr xml_namespace, const char* name) {
+  std::vector<xmlNodePtr> result;
+  for (xmlNodePtr child = root->children; child != nullptr;
+      child = child->next) {
+    if (!TagNameEquals(child, name, xml_namespace))
+      continue;
+
+    result.push_back(child);
+  }
+  return result;
+}
+
+// Returns the first child node of |root| with name |name|.
+xmlNodePtr GetFirstChild(
+    const xmlNodePtr root, const xmlNsPtr xml_namespace, const char* name) {
+  xmlNodePtr result = nullptr;
+  for (xmlNodePtr child = root->children; child != nullptr;
+      child = child->next) {
+    if (TagNameEquals(child, name, xml_namespace)) {
+      result = child;
+      break;
+    }
+  }
+  return result;
+}
+
+// Returns the value of a named attribute, or the empty string.
+std::string GetAttribute(
+    const xmlNodePtr node, const char* attribute_name) {
+  const xmlChar* name =
+    reinterpret_cast<const xmlChar*>(attribute_name);
+  for (xmlAttr* attr = node->properties; attr != nullptr; attr = attr->next) {
+    if (!xmlStrcmp(attr->name, name) && attr->children &&
+        attr->children->content)
+      return std::string(reinterpret_cast<const char*>(
+           attr->children->content));
+  }
+  return std::string();
+}
+
+// Returns a pointer to the xmlNs on |node| with the |expected_href|, or
+// nullptr if there isn't one with that href.
+xmlNsPtr GetNamespace(const xmlNodePtr node, const char* expected_href) {
+  const xmlChar* href = reinterpret_cast<const xmlChar*>(expected_href);
+  for (xmlNsPtr ns = node->ns; ns != nullptr; ns = ns->next) {
+    if (ns->href && !xmlStrcmp(ns->href, href))
+      return ns;
+  }
+  return nullptr;
+}
+
+std::string XmlStringToStdString(const xmlChar* xmlstring) {
+  if (xmlstring)
+    return std::string(reinterpret_cast<const char*>(xmlstring));
+  else
+    return "";
+}
+
+}  // namespace
+
+namespace signature {
+
+bool ParseSignedInfoElement(
+    const xmlNodePtr node, const xmlNsPtr signature_ns, SignatureData* data) {
+  xmlNodePtr signed_info_node =
+    GetFirstChild(node, signature_ns, kTokenSignedInfo);
+  if (!signed_info_node) {
+    LOG(ERROR) << "Missing SignedInfo tag.";
+    return false;
+  }
+
+  // Parse <CanonicalizationMethod>
+  xmlNodePtr canonicalization_method_node =
+    GetFirstChild(signed_info_node, signature_ns, kTokenCanonicalizationMethod);
+  if (!canonicalization_method_node) {
+    LOG(ERROR) << "Missing SignedInfo tag.";
+    return false;
+  }
+  std::string canonicalization_method =
+    GetAttribute(canonicalization_method_node, kTokenAlgorithm);
+  data->set_canonicalization_method(canonicalization_method);
+
+  // Parse <SignatureMethod>
+  xmlNodePtr signature_method_node =
+    GetFirstChild(signed_info_node, signature_ns, kTokenSignatureMethod);
+  if (!signature_method_node) {
+    LOG(ERROR) << "Missing SignatureMethod tag.";
+    return false;
+  }
+  std::string signature_method =
+    GetAttribute(signature_method_node, kTokenAlgorithm);
+  data->set_signature_method(signature_method);
+
+  // Parse <Reference>
+  std::vector<xmlNodePtr> reference_vec =
+    GetChildren(signed_info_node, signature_ns, kTokenReference);
+  if (reference_vec.empty()) {
+    LOG(ERROR) << "Missing Reference tag.";
+    return false;
+  }
+
+  std::string uri;
+  xmlNodePtr refer_node;
+  std::set<std::string> reference_set;
+  for (size_t i = 0; i < reference_vec.size(); ++i) {
+    refer_node = reference_vec[i];
+    uri = GetAttribute(refer_node, kTokenURI);
+    if (uri.empty()) {
+      LOG(ERROR) << "Missing URI attribute.";
+      return false;
+    }
+    reference_set.insert(uri);
+  }
+  data->set_reference_set(reference_set);
+
+  return true;
+}
+
+bool ParseSignatureValueElement(
+    const xmlNodePtr node, const xmlNsPtr ns, SignatureData* data) {
+  xmlNodePtr sign_value_node = GetFirstChild(node, ns, kTokenSignatureValue);
+  if (!sign_value_node) {
+    LOG(ERROR) << "Missing SignatureValue tag.";
+    return false;
+  }
+  std::string signature_value = XmlStringToStdString(
+      xmlNodeGetContent(sign_value_node));
+  data->set_signature_value(signature_value);
+  return true;
+}
+
+bool ParseKeyInfoElement(
+    const xmlNodePtr node, const xmlNsPtr ns, SignatureData* data) {
+  xmlNodePtr key_info_node = GetFirstChild(node, ns, kTokenkeyInfo);
+  if (!key_info_node) {
+    LOG(INFO) << "Missing KeyInfo tag, it is allowed by schema.xsd.";
+    return true;
+  }
+
+  // KeyInfo may contain keys, names, certificates and other public key
+  // management. Now I only handle X509 certifcates which is commonly used.
+  // TODO(Xu): Other types of element
+  xmlNodePtr X509_data_node =
+    GetFirstChild(key_info_node, ns, kTokenX509Data);
+  if (!X509_data_node) {
+    LOG(INFO) << "Missing X509Data tag.";
+    return true;
+  }
+
+  // Parse <X509Certificate>
+  std::vector<xmlNodePtr> cert_vec =
+    GetChildren(X509_data_node, ns, kTokenX509Certificate);
+  if (cert_vec.empty()) {
+    LOG(ERROR) << "Missing X509Certificate tag.";
+    return false;
+  }
+
+  std::list<std::string> certificate_list;
+  for (auto certificate_node : cert_vec) {
+    certificate_list.push_back(
+        XmlStringToStdString(xmlNodeGetContent(certificate_node)));
+  }
+  data->set_certificate_list(certificate_list);
+  return true;
+}
+
+bool ParseObjectElement(
+    const xmlNodePtr node, const xmlNsPtr ns, SignatureData* data) {
+  xmlNodePtr object_node = GetFirstChild(node, ns, kTokenObject);
+  if (!object_node) {
+    LOG(ERROR) << "Missing Object tag.";
+    return false;
+  }
+
+  std::string object_id = GetAttribute(object_node, kTokenID);
+  data->set_object_id(object_id);
+  // Parse <SignatureProperties>
+  xmlNodePtr properties_node =
+    GetFirstChild(object_node, ns, kTokenSignatureProperties);
+  if (!properties_node) {
+    LOG(ERROR) << "Missing Object tag.";
+    return false;
+  }
+
+  std::vector<xmlNodePtr> prop_vec =
+    GetChildren(properties_node, ns, kTokenSignatureProperty);
+  std::string Id, element_name, profile_uri, role_uri;
+  for (xmlNodePtr sign_property_node : prop_vec) {
+    Id = GetAttribute(sign_property_node, kTokenID);
+    xmlNodePtr child = sign_property_node->children;
+    if (!child) {
+      LOG(ERROR) << "Failing to find " << element_name
+                 << "  element.";
+      return false;
+    }
+
+    if (Id.compare(kTokenAttrProfile) == 0) {
+      profile_uri = GetAttribute(child, kTokenURI);
+      data->set_profile_uri(profile_uri);
+    }
+    if (Id.compare(kTokenAttrRole) == 0) {
+      role_uri = GetAttribute(child, kTokenURI);
+      data->set_role_uri(role_uri);
+    }
+  }
+
+  return true;
+}
+
+bool ParseXML(xmlDocPtr docPtr, SignatureData* data) {
+  xmlNodePtr root = xmlDocGetRootElement(docPtr);
+  if (!root) {
+    LOG(ERROR) << "Missinging root node.";
+    return false;
+  }
+
+  // Look for the required namespace declaration.
+  xmlNsPtr signature_ns = GetNamespace(root, kExpectedXmlns);
+  if (!signature_ns) {
+    LOG(ERROR) << "Missinging or incorrect xmlns on signature tag.";
+    return false;
+  }
+  if (!TagNameEquals(root, kTokenSignature, signature_ns)) {
+    LOG(ERROR) << "Missinging Signature tag.";
+    return false;
+  }
+
+  if (!ParseSignedInfoElement(root, signature_ns, data))
+    return false;
+
+  if (!ParseSignatureValueElement(root, signature_ns, data))
+    return false;
+
+  if (!ParseKeyInfoElement(root, signature_ns, data))
+    return false;
+
+  if (!ParseObjectElement(root, signature_ns, data))
+    return false;
+
+  return true;
+}
+
+std::unique_ptr<SignatureData> SignatureParser::CreateSignatureData(
+    const boost::filesystem::path& signature_path, int signature_number) {
+  std::unique_ptr<SignatureData>
+    data(new SignatureData(signature_path, signature_number));
+
+  xmlInitParser();
+  xmlDocPtr doc = xmlParseFile(signature_path.string().c_str());
+  if (!doc) {
+    LOG(ERROR) << "Opening signature " << signature_path << " failed.";
+    return nullptr;
+  }
+
+  if (!ParseXML(doc, data.get())) {
+    LOG(ERROR) << "Parsering failed.";
+    xmlFreeDoc(doc);
+    return nullptr;
+  }
+
+  xmlFreeDoc(doc);
+  xmlCleanupParser();
+  return data;
+}
+
+}  // namespace signature
diff --git a/signature/src/signature_validator.cc b/signature/src/signature_validator.cc
new file mode 100644 (file)
index 0000000..f1d4ddb
--- /dev/null
@@ -0,0 +1,300 @@
+// Copyright (c) 2013 Intel Corporation. All rights reserved.
+// Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by an apache 2.0 license that can be
+// found in the LICENSE file.
+// Part of this file is redistributed from crosswalk project under BDS-style
+// license. Check LICENSE-xwalk file.
+
+#include <signature_validator.h>
+
+#include <libxml/tree.h>
+#include <libxml/parser.h>
+#include <libxml/xmlschemas.h>
+
+#include <memory>
+#include <regex>
+#include <set>
+#include <string>
+
+#include <logging.h>
+#include <signature_data.h>
+#include <signature_parser.h>
+#include <signature_xmlsec_adaptor.h>
+
+namespace bf = boost::filesystem;
+
+namespace {
+
+const int kXMLLogSize = 1024;
+
+const char kAuthorSignatureName[] = "author-signature.xml";
+const char kTokenRoleAuthorURI[] =
+    "http://www.w3.org/ns/widgets-digsig#role-author";
+const char kTokenRoleDistributor[] =
+    "http://www.w3.org/ns/widgets-digsig#role-distributor";
+const char kTokenProfileURI[] =
+    "http://www.w3.org/ns/widgets-digsig#profile";
+const char kSignatureSchemaPath[] =
+    "/usr/share/app-installers/signature_schema.xsd";
+
+const std::regex kDistributorSignatureRegex("^signature([1-9][0-9]*)\\.xml$");
+
+//  A wrapper of LOG(ERROR) function, which  is used as parameter of function
+//  xmlSchemaSetValidErrors
+void LogErrorLibxml2(void *, const char *msg, ...) {
+  char buffer[kXMLLogSize];
+  va_list args;
+  va_start(args, msg);
+  vsnprintf(buffer, sizeof(buffer), msg, args);
+  va_end(args);
+  LOG(ERROR) << "ERROR: " << buffer;
+}
+
+//  A wrapper of LOG(WARNING) function, which  is used as parameter of function
+//  xmlSchemaSetValidErrors
+void LogWarningLibxml2(void *, const char *msg, ...) {
+  char buffer[kXMLLogSize];
+  va_list args;
+  va_start(args, msg);
+  vsnprintf(buffer, sizeof(buffer), msg, args);
+  va_end(args);
+  LOG(WARNING) << "Warning: " << buffer;
+}
+
+class SignatureFile {
+ public:
+  SignatureFile(const std::string& file_name, int file_number)
+    : file_name_(file_name), file_number_(file_number) {
+  }
+
+  std::string file_name() const {
+    return file_name_;
+  }
+
+  int file_number() const {
+    return file_number_;
+  }
+
+  bool operator<(const SignatureFile &second) const {
+    return file_number_ < second.file_number();
+  }
+
+ private:
+  std::string file_name_;
+  int file_number_;
+};
+typedef std::set<SignatureFile> SignatureFileSet;
+
+const SignatureFileSet GetSignatureFiles(
+    const boost::filesystem::path& widget_path) {
+  SignatureFileSet signature_set;
+
+  for (bf::directory_iterator dir_iterator(widget_path);
+      dir_iterator != bf::directory_iterator(); ++dir_iterator) {
+    const bf::path& path = dir_iterator->path();
+    if (path.extension() == ".xml" && bf::is_regular_file(path)) {
+      std::string file_name = path.filename().string();
+      if (file_name == kAuthorSignatureName) {
+        // Find author signature file.
+        signature_set.insert(SignatureFile(file_name, -1));
+        continue;
+      }
+      std::smatch match;
+      if (std::regex_match(file_name, match, kDistributorSignatureRegex)) {
+        if (match.size() == 2) {
+          // Find distributor signature file.
+          signature_set.insert(
+              SignatureFile(file_name, std::stoi(match[1].str())));
+        }
+      }
+    }
+  }
+  return signature_set;
+}
+
+bool XMLSchemaValidate(
+    const SignatureFile& signature_file,
+    const boost::filesystem::path& widget_path) {
+  xmlDocPtr schema_doc = xmlReadFile(
+      kSignatureSchemaPath, nullptr, XML_PARSE_NONET|XML_PARSE_NOENT);
+  if (!schema_doc) {
+    LOG(ERROR) << "Reading schema file failed.";
+    return false;
+  }
+
+  xmlSchemaParserCtxtPtr ctx = xmlSchemaNewParserCtxt(kSignatureSchemaPath);
+  if (!ctx) {
+    LOG(ERROR) << "Initing xml schema parser context failed.";
+    return false;
+  }
+
+  xmlSchemaPtr xschema = xmlSchemaParse(ctx);
+  if (!xschema) {
+    LOG(ERROR) << "Parsing xml schema failed.";
+    return false;
+  }
+
+  xmlSchemaValidCtxtPtr vctx = xmlSchemaNewValidCtxt(xschema);
+  if (!vctx) {
+    LOG(ERROR) << "Initing xml schema context failed.";
+    return false;
+  }
+  xmlSchemaSetValidErrors(vctx, (xmlSchemaValidityErrorFunc)&LogErrorLibxml2,
+      (xmlSchemaValidityWarningFunc)&LogWarningLibxml2, nullptr);
+
+  bf::path signature_path = widget_path / signature_file.file_name();
+  int ret = xmlSchemaValidateFile(vctx, signature_path.string().c_str(), 0);
+
+  if (ret != 0) {
+    LOG(ERROR) << "Validating " << signature_file.file_name()
+               << " schema failed.";
+    return false;
+  }
+  return true;
+}
+
+bool CheckObjectID(
+    const signature::SignatureData& signature_data) {
+  std::string object_id = signature_data.object_id();
+  std::set<std::string> reference_set = signature_data.reference_set();
+
+  std::set<std::string>::const_iterator result =
+    reference_set.find(std::string("#") + object_id);
+  if (result == reference_set.end()) {
+    LOG(ERROR) << "No reference to object.";
+    return false;
+  }
+  return true;
+}
+
+bool CheckRoleURI(
+    const signature::SignatureData& signature_data) {
+  std::string role_uri = signature_data.role_uri();
+
+  if (role_uri.empty()) {
+    LOG(ERROR) << "URI attribute in Role tag couldn't be empty.";
+    return false;
+  }
+
+  if (role_uri != kTokenRoleAuthorURI && signature_data.isAuthorSignature()) {
+    LOG(ERROR) << "URI attribute in Role tag does not "
+               << "match with signature filename.";
+    return false;
+  }
+
+  if (role_uri != kTokenRoleDistributor &&
+      !signature_data.isAuthorSignature()) {
+    LOG(ERROR) << "URI attribute in Role tag does not "
+               << "match with signature filename.";
+    return false;
+  }
+
+  return true;
+}
+
+bool CheckProfileURI(const signature::SignatureData& signature_data) {
+  if (kTokenProfileURI != signature_data.profile_uri()) {
+    LOG(ERROR) << "Profile tag contains unsupported value in URI attribute.";
+    return false;
+  }
+  return true;
+}
+
+boost::filesystem::path RelativePath(const boost::filesystem::path& path,
+    const boost::filesystem::path& root) {
+  if (root.empty())
+    return path;
+
+  std::string path_str = path.string();
+  std::string root_str = root.string();
+
+  if (root_str != path_str.substr(0, root_str.size()))
+    return bf::path();
+
+  auto index = root_str.size();
+
+  if (root_str[root_str.size() - 1] != '/') {
+    if (path_str[root_str.size()] != '/') {
+      return bf::path();
+    } else {
+      ++index;
+    }
+  }
+
+  return path_str.substr(index);
+}
+
+bool CheckReference(const signature::SignatureData& signature_data) {
+  const bf::path& widget_path = signature_data.GetExtractedWidgetPath();
+  const std::set<std::string>& reference_set = signature_data.reference_set();
+
+  for (bf::recursive_directory_iterator dir_iterator(widget_path);
+      dir_iterator != bf::recursive_directory_iterator(); ++dir_iterator) {
+    const bf::path& path = dir_iterator->path();
+    if (bf::is_regular_file(path)) {
+      std::string relative_path = RelativePath(path, widget_path).string();
+      if (relative_path == kAuthorSignatureName ||
+          std::regex_match(relative_path, kDistributorSignatureRegex)) {
+        // Skip signtature file.
+        continue;
+      }
+      std::set<std::string>::iterator ref_iter =
+          reference_set.find(relative_path);
+      if (ref_iter == reference_set.end()) {
+        LOG(ERROR) << relative_path << " is not in signature ds:Reference.";
+        return false;
+      }
+    }
+  }
+  return true;
+}
+
+}  // anonymous namespace
+
+namespace signature {
+// static
+SignatureValidator::Status SignatureValidator::Check(
+    const boost::filesystem::path& widget_path) {
+  LOG(INFO) << "Verifying widget signature file.";
+  // Process every signature files (author and distributor) according to
+  // http://www.w3.org/TR/widgets-digsig/#signature-verification.
+  const SignatureFileSet& signature_set = GetSignatureFiles(widget_path);
+  if (signature_set.empty()) {
+    LOG(INFO) << "No signed signature in the package.";
+    return UNTRUSTED;
+  }
+
+  SignatureFileSet::reverse_iterator iter = signature_set.rbegin();
+  for (; iter != signature_set.rend(); ++iter) {
+    // Verify whether signature xml is a valid [XMLDSIG] document.
+    if (!XMLSchemaValidate(*iter, widget_path)) {
+      LOG(ERROR) << "Validating " << iter->file_name() << "schema failed.";
+      return INVALID;
+    }
+
+    std::unique_ptr<SignatureData> data = SignatureParser::CreateSignatureData(
+        widget_path / iter->file_name(), iter->file_number());
+    // Check whether each file in the widget can be found from ds:Reference.
+    if (!CheckReference(*data.get()))
+      return INVALID;
+
+    // Validate the profile property.
+    if (!CheckProfileURI(*data.get()))
+      return INVALID;
+
+    // Validate the identifier property.
+    if (!CheckObjectID(*data.get()))
+      return INVALID;
+
+    // Validate role property.
+    if (!CheckRoleURI(*data.get()))
+      return INVALID;
+
+    // Perform reference validation and signature validation on signature
+    if (!SignatureXmlSecAdaptor::ValidateFile(*data.get()))
+      return INVALID;
+  }
+  return VALID;
+}
+
+}  // namespace signature
diff --git a/signature/src/signature_xmlsec_adaptor.cc b/signature/src/signature_xmlsec_adaptor.cc
new file mode 100644 (file)
index 0000000..c72291b
--- /dev/null
@@ -0,0 +1,413 @@
+// Copyright (c) 2014 Intel Corporation. All rights reserved.
+// Copyright (C) 2002-2003 Aleksey Sanin.  All Rights Reserved.
+// Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by an apache 2.0 license that can be
+// found in the LICENSE file.
+// Part of this file is redistributed from crosswalk project under BDS-style
+// license. Check LICENSE-xwalk file.
+
+#include <signature_xmlsec_adaptor.h>
+
+#include <libxml/parser.h>
+#include <openssl/bio.h>
+#include <openssl/x509.h>
+#include <xmlsec/crypto.h>
+#include <xmlsec/io.h>
+#include <xmlsec/keysmngr.h>
+#include <xmlsec/xmlsec.h>
+#include <xmlsec/xmltree.h>
+#include <xmlsec/xmldsig.h>
+#ifndef XMLSEC_NO_XSLT
+#include <libxslt/xslt.h>
+#endif
+
+#include <boost/archive/iterators/binary_from_base64.hpp>
+#include <boost/archive/iterators/transform_width.hpp>
+#include <boost/filesystem/operations.hpp>
+
+#include <algorithm>
+#include <array>
+#include <cassert>
+#include <list>
+#include <map>
+#include <sstream>
+#include <string>
+#include <utility>
+
+#include <logging.h>
+
+namespace bai = boost::archive::iterators;
+namespace bf = boost::filesystem;
+
+namespace {
+
+const bf::path cert_prefix_path = "/usr/share/ca-certificates/tizen/";
+
+// TODO(XU): Once tizen platform provide certificate manager util APIs,
+// we should call API from system to query certificate's file path.
+class CertificateUtil {
+ public:
+  static const std::map<std::string, std::string>& certificate_path() {
+    return certificate_path_;
+  }
+
+ private:
+  static std::map<std::string, std::string> InitCertificatePath() {
+    std::map<std::string, std::string> root_certificates;
+    root_certificates["Tizen Partner-Manufacturer Distributor Root CA"] =
+        "tizen-distributor-root-ca-partner-manufacturer.pem";
+    root_certificates["SLP WebApp Temporary CA"] =
+        "tizen.root.preproduction.cert.pem";
+    root_certificates["Tizen Test Developer Root CA"] =
+        "tizen-developer-root-ca.pem";
+    root_certificates["Tizen Developers Root"] =
+        "tizen-developers-root.pem";
+    root_certificates["Tizen Partner Distributor Root CA"] =
+        "tizen-distributor-root-ca-partner.pem";
+    root_certificates["Tizen Partner-Operator Distributor Root CA"] =
+        "tizen-distributor-root-ca-partner-operator.pem";
+    root_certificates["Tizen Public Distributor Root CA"] =
+        "tizen-distributor-root-ca-public.pem";
+    root_certificates["Partner Class Developer Root"] =
+        "tizen-partner-class-developer-root.pem";
+    root_certificates["Partner Class Root Authority"] =
+        "tizen-partner-class-root-authority.pem";
+    root_certificates["Platform Class Developer Root"] =
+        "tizen-platform-class-developer-root.pem";
+    root_certificates["Platform Class Root Authority"] =
+        "tizen-platform-class-root-authority.pem";
+    root_certificates["Public Class Developer Root"] =
+        "tizen-public-class-developer-root.pem";
+    root_certificates["Public Class Root Authority"] =
+        "tizen-public-class-root-authority.pem";
+
+    return root_certificates;
+  }
+
+  static std::map<std::string, std::string> certificate_path_;
+};
+
+std::map<std::string, std::string>
+    CertificateUtil::certificate_path_ = InitCertificatePath();
+
+std::string ConvertBase64ToPemCert(const std::string& cert_in) {
+  return std::string("-----BEGIN CERTIFICATE-----") + cert_in +
+      "-----END CERTIFICATE-----";
+}
+
+std::string ConvertBase64ToDerCert(const std::string& cert_in) {
+  typedef bai::transform_width<
+      bai::binary_from_base64<std::string::const_iterator>, 8, 6>
+          base64_dec;
+
+  std::string cert = cert_in;
+
+  // remove newlines from xml format
+  cert.erase(std::remove(cert.begin(), cert.end(), '\n'), cert.end());
+
+  std::stringstream der;
+
+  // padding
+  unsigned int size = cert.size();
+  int padding = 0;
+  if (size && cert[size - 1] == '=') {
+    ++padding;
+    if (size && cert[size - 2] == '=') ++padding;
+  }
+
+  // replace padding to 'zero'
+  std::replace(cert.begin(), cert.end(), '=', 'A');
+
+  std::copy(base64_dec(cert.begin()), base64_dec(cert.end()),
+      std::ostream_iterator<char>(der));
+
+  // remove padding
+  cert.erase(cert.end() - padding, cert.end());
+
+  return der.str();
+}
+
+class XmlSecContext {
+ public:
+  static void GetExtractedPath(const signature::SignatureData& data);
+  static xmlSecKeysMngrPtr LoadTrustedCerts(
+      const signature::SignatureData& signature_data);
+  static bool VerifyFile(
+      xmlSecKeysMngrPtr mngr, const signature::SignatureData& data);
+
+ private:
+  static int FileMatchCallback(const char* file_name);
+  static void* FileOpenCallback(const char* file_name);
+  static int FileReadCallback(void* context, char* buffer, int len);
+  static int FileCloseCallback(void* context);
+  static boost::filesystem::path GetCertFromStore(const std::string& subject);
+
+  static bf::path prefix_path_;
+  static std::pair<void*, bool> file_wrapper_;
+};
+
+bf::path XmlSecContext::prefix_path_;
+std::pair<void*, bool> XmlSecContext::file_wrapper_;
+
+void XmlSecContext::GetExtractedPath(
+    const signature::SignatureData& data) {
+  prefix_path_ = data.GetExtractedWidgetPath();
+}
+
+int XmlSecContext::FileMatchCallback(const char* file_name) {
+  bf::path path = prefix_path_ / file_name;
+  return xmlFileMatch(path.string().c_str());
+}
+
+void* XmlSecContext::FileOpenCallback(const char* file_name) {
+  bf::path path = prefix_path_ / file_name;
+  XmlSecContext::file_wrapper_ =
+      std::make_pair(xmlFileOpen(path.string().c_str()), false);
+  return &(XmlSecContext::file_wrapper_);
+}
+
+int XmlSecContext::FileReadCallback(void* context, char* buffer, int len) {
+  std::pair<void*, bool>* file_wrapper =
+      static_cast<std::pair<void*, bool>*>(context);
+  assert(file_wrapper);
+  if (file_wrapper->second)
+    return 0;
+
+  int output = xmlFileRead(file_wrapper->first, buffer, len);
+  if (output == 0) {
+    file_wrapper->second = true;
+    xmlFileClose(file_wrapper->first);
+  }
+  return output;
+}
+
+int XmlSecContext::FileCloseCallback(void* context) {
+  std::pair<void*, bool>* file_wrapper =
+      static_cast<std::pair<void*, bool>*>(context);
+  assert(file_wrapper);
+  int output = 0;
+  if (!file_wrapper->second)
+    output = xmlFileClose(file_wrapper->first);
+
+  return output;
+}
+
+xmlSecKeysMngrPtr XmlSecContext::LoadTrustedCerts(
+    const signature::SignatureData& signature_data) {
+  xmlSecKeysMngrPtr mngr = xmlSecKeysMngrCreate();
+  if (!mngr) {
+    LOG(ERROR) << "Error: failed to create keys manager.";
+    return nullptr;
+  }
+  if (xmlSecCryptoAppDefaultKeysMngrInit(mngr) < 0) {
+    LOG(ERROR) << "Error: failed to initialize keys manager.";
+    xmlSecKeysMngrDestroy(mngr);
+    return nullptr;
+  }
+
+  std::list<std::string> certificate_list = signature_data.certificate_list();
+  std::string issuer;
+  for (std::list<std::string>::iterator it = certificate_list.begin();
+      it != certificate_list.end(); ++it) {
+    std::string cert = ConvertBase64ToDerCert(*it);
+
+    X509* x509_cert = nullptr;
+    const unsigned char* data_ptr =
+        reinterpret_cast<const unsigned char*>(cert.data());
+    if (!d2i_X509(&x509_cert, &data_ptr, cert.size())) {
+      LOG(ERROR) << "Cannot parse X509 certificate";
+      return nullptr;
+    }
+
+    X509_NAME* x509_name = X509_get_issuer_name(x509_cert);
+    if (!x509_name) {
+      LOG(ERROR) << "Cannot extract issuer of X509 certificate";
+      X509_free(x509_cert);
+      return nullptr;
+    }
+
+    std::array<char, 200> buffer;
+    if (X509_NAME_get_text_by_NID(x509_name,
+        NID_commonName, buffer.data(), buffer.size()) == -1) {
+      LOG(ERROR) << "Cannot extract DisplayName of X509 certificate";
+      X509_free(x509_cert);
+      return nullptr;
+    }
+    X509_free(x509_cert);
+
+    issuer = buffer.data();
+    LOG(INFO) << "Issuer: " << issuer;
+
+    std::string pem = ConvertBase64ToPemCert(*it);
+    if (xmlSecCryptoAppKeysMngrCertLoadMemory(mngr,
+        reinterpret_cast<const unsigned char*>(pem.c_str()), pem.size(),
+        xmlSecKeyDataFormatCertPem, xmlSecKeyDataTypeTrusted) < 0) {
+      LOG(ERROR) << "Error: failed to load pem certificate.";
+      xmlSecKeysMngrDestroy(mngr);
+      return nullptr;
+    }
+  }
+
+  // TODO(tiwanek): extract to seperate file...
+  const bf::path& root_cert_path =
+      XmlSecContext::GetCertFromStore(issuer);
+  if (!bf::exists(root_cert_path.string().c_str())) {
+    LOG(ERROR) << "Failed to find root certificate.";
+    return nullptr;
+  }
+
+  if (xmlSecCryptoAppKeysMngrCertLoad(mngr,
+      root_cert_path.string().c_str(), xmlSecKeyDataFormatPem,
+      xmlSecKeyDataTypeTrusted) < 0) {
+    LOG(ERROR) << "Error: failed to load root certificate";
+    xmlSecKeysMngrDestroy(mngr);
+    return nullptr;
+  }
+
+  return mngr;
+}
+
+bool XmlSecContext::VerifyFile(xmlSecKeysMngrPtr mngr,
+                              const signature::SignatureData& data) {
+  LOG(INFO) << "Verify " << data.signature_file_name();
+  xmlSecIOCleanupCallbacks();
+  XmlSecContext::GetExtractedPath(data);
+  xmlSecIORegisterCallbacks(
+      XmlSecContext::FileMatchCallback,
+      XmlSecContext::FileOpenCallback,
+      XmlSecContext::FileReadCallback,
+      XmlSecContext::FileCloseCallback);
+
+  xmlDocPtr doc = xmlParseFile(data.signature_file_name().string().c_str());
+  if (!doc) {
+    LOG(ERROR) << "Error: failed to parse "
+               << data.signature_file_name().string();
+    return false;
+  }
+
+  if (!xmlDocGetRootElement(doc)) {
+    LOG(ERROR) << "Error: unable to get root element.";
+    xmlFreeDoc(doc);
+    return false;
+  }
+
+  xmlNodePtr node = xmlSecFindNode(
+      xmlDocGetRootElement(doc), xmlSecNodeSignature, xmlSecDSigNs);
+  if (!node) {
+    LOG(ERROR) << "Error: unable to find SecNodeSignature node.";
+    xmlFreeDoc(doc);
+    return false;
+  }
+
+  xmlSecDSigCtxPtr dsig_ctx = xmlSecDSigCtxCreate(mngr);
+  if (!dsig_ctx) {
+    LOG(ERROR) << "Error: failed to create signature context.";
+    xmlFreeDoc(doc);
+    return false;
+  }
+
+  if (xmlSecDSigCtxVerify(dsig_ctx, node) < 0) {
+    LOG(ERROR) << "Error: signature verify.";
+    xmlFreeDoc(doc);
+    xmlSecDSigCtxDestroy(dsig_ctx);
+    return false;
+  }
+
+  if (dsig_ctx->status != xmlSecDSigStatusSucceeded)
+    LOG(ERROR) << "Signature " << data.signature_file_name() <<" is INVALID";
+
+  LOG(INFO) << "Signature  "<< data.signature_file_name() << " is OK.";
+
+  xmlFreeDoc(doc);
+  xmlSecDSigCtxDestroy(dsig_ctx);
+  return true;
+}
+
+boost::filesystem::path XmlSecContext::GetCertFromStore(
+    const std::string& subject) {
+  std::map<std::string, std::string>::const_iterator iter =
+      CertificateUtil::certificate_path().find(subject);
+
+  if (iter == CertificateUtil::certificate_path().end()) {
+    LOG(ERROR) << "Failing to find root certificate.";
+    return "";
+  }
+  LOG(INFO) << "root cert path is " << cert_prefix_path / iter->second;
+  return cert_prefix_path / iter->second;
+}
+
+}  // namespace
+
+namespace signature {
+
+// static
+bool SignatureXmlSecAdaptor::ValidateFile(
+    const SignatureData& signature_data) {
+  xmlInitParser();
+  xmlSubstituteEntitiesDefault(1);
+#ifndef XMLSEC_NO_XSLT
+  xsltSecurityPrefsPtr xslt_sec_prefs = xsltNewSecurityPrefs();
+  xsltSetSecurityPrefs(
+      xslt_sec_prefs, XSLT_SECPREF_READ_FILE, xsltSecurityForbid);
+  xsltSetSecurityPrefs(
+      xslt_sec_prefs, XSLT_SECPREF_WRITE_FILE, xsltSecurityForbid);
+  xsltSetSecurityPrefs(
+      xslt_sec_prefs, XSLT_SECPREF_CREATE_DIRECTORY, xsltSecurityForbid);
+  xsltSetSecurityPrefs(
+      xslt_sec_prefs, XSLT_SECPREF_READ_NETWORK, xsltSecurityForbid);
+  xsltSetSecurityPrefs(
+      xslt_sec_prefs, XSLT_SECPREF_WRITE_NETWORK, xsltSecurityForbid);
+  xsltSetDefaultSecurityPrefs(xslt_sec_prefs);
+#endif  // XMLSEC_NO_XSLT
+
+  if (xmlSecInit() < 0) {
+    LOG(ERROR) << "Error: xmlsec initialization failed.";
+    return false;
+  }
+
+  if (xmlSecCheckVersion() != 1) {
+    LOG(ERROR) << "Error: loaded xmlsec library version is not compatible.";
+    return false;
+  }
+
+#ifdef XMLSEC_CRYPTO_DYNAMIC_LOADING
+  if (xmlSecCryptoDLLoadLibrary(BAD_CAST XMLSEC_CRYPTO) < 0) {
+    LOG(ERROR) << "Error: unable to load default xmlsec-crypto library.";
+    return false;
+  }
+#endif  // XMLSEC_CRYPTO_DYNAMIC_LOADING
+
+  if (xmlSecCryptoAppInit(nullptr) < 0) {
+    LOG(ERROR) << "Error: crypto initialization failed.";
+    return false;
+  }
+
+  if (xmlSecCryptoInit() < 0) {
+    LOG(ERROR) << "Error: xmlsec-crypto initialization failed.";
+    return false;
+  }
+
+  xmlSecKeysMngrPtr mngr = XmlSecContext::LoadTrustedCerts(signature_data);
+  if (!mngr)
+    return false;
+
+  if (!XmlSecContext::VerifyFile(mngr, signature_data)) {
+    xmlSecKeysMngrDestroy(mngr);
+    return false;
+  }
+
+  xmlSecKeysMngrDestroy(mngr);
+  xmlSecCryptoShutdown();
+  xmlSecCryptoAppShutdown();
+  xmlSecShutdown();
+
+#ifndef XMLSEC_NO_XSLT
+  xsltFreeSecurityPrefs(xslt_sec_prefs);
+  xsltCleanupGlobals();
+#endif  // XMLSEC_NO_XSLT
+  xmlCleanupParser();
+
+  return true;
+}
+
+}  // namespace signature
index 5e57c43..488d899 100644 (file)
@@ -8,8 +8,10 @@
 #include <cstring>
 #include <cerrno>
 #include <cassert>
+#include <memory>
 #include <app_installer.h>
 #include <step_unzip.h>
+#include "step/signature_step.h"
 
 int
 main (int argc, char **argv)
@@ -33,14 +35,20 @@ main (int argc, char **argv)
   switch (pkgmgr_installer_get_request_type (pi))
     {
     case PKGMGR_REQ_INSTALL:
+    {
     Installer = new AppInstaller(PKGMGR_REQ_INSTALL,(char*)pkgmgr_installer_get_request_info(pi),NULL);
     step_unpack = new step_unzip();
     
     Installer->AddStep(step_unpack);
 
+    // FIXME: unique_ptr because steps are not freed in installer.
+    std::unique_ptr<common::SignatureStep> signature_step(
+         new common::SignatureStep);
+    Installer->AddStep(signature_step.get());
+
     Installer->Run();
       break;
-
+    }
     case PKGMGR_REQ_UNINSTALL:
        break;